Skip to content

Commit

Permalink
mpu: Return largest possible order from failed v_lookup
Browse files Browse the repository at this point in the history
v_lookup() is used during unmap() and as such needs to return the
largest possible order for addresses that are not mapped in any region.
Otherwise unmap() iterates the address space in 2M steps, which takes
essentially forever.

Co-authored-by: Jan Klötzke <[email protected]>
Change-Id: I8891b68b1791685a9c3598edbeec4fb615741591
  • Loading branch information
jermar and jkloetzke committed Aug 14, 2024
1 parent 4836983 commit a179530
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 6 deletions.
25 changes: 19 additions & 6 deletions src/kern/arm/mem_space-arm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,7 @@ IMPLEMENTATION [arm && mpu]:
#include <cassert>
#include <cstring>

#include "arithmetic.h"
#include "atomic.h"
#include "config.h"
#include "kmem.h"
Expand Down Expand Up @@ -556,15 +557,27 @@ bool
Mem_space::v_lookup(Vaddr virt, Phys_addr *phys,
Page_order *order, Attr *page_attribs)
{
// MUST be reported in any case! The mapdb relies on this information.
if (order)
*order = Page_order(Config::SUPERPAGE_SHIFT);

auto guard = lock_guard(_lock);

auto r = _dir->find(Vaddr::val(virt));
Mword v(Vaddr::val(virt));
auto r = _dir->find(v);
if (!r)
return false;
{
if (order)
{
// Calculate the largest possible order that covers the gap to make
// iterating over the vast address space during unmap() viable.
Mword gap_end(0);
auto n = _dir->find_next(v);
if (n)
gap_end = n->start();
Mword gap_size = gap_end - v;
unsigned gap_order = gap_size ? cxx::log2u(gap_size) : MWORD_BITS - 1;
unsigned max_order = v ? __builtin_ctzl(v) : MWORD_BITS - 1;
*order = Page_order(min(gap_order, max_order));
}
return false;
}

// We always need to report the smallest order. The disabled code below that
// tries to report the order more truthfully breaks mapdb.
Expand Down
13 changes: 13 additions & 0 deletions src/kern/mpu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,19 @@ Mpu_regions::find(Mword addr) const
return nullptr;
}

PUBLIC inline
Mpu_region const *
Mpu_regions::find_next(Mword addr) const
{
for (auto const &i : _used_list)
{
if (addr < i->start())
return i;
}

return nullptr;
}

/**
* Dump regions list.
*/
Expand Down

0 comments on commit a179530

Please sign in to comment.