mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-19 13:47:56 +00:00
nova: optimize unmap path
Directly unmap memory range instead of looking first it up and then unmap it. Prerequisite for #675
This commit is contained in:
parent
974c5442c6
commit
b2d92f3d94
@ -2,6 +2,7 @@
|
||||
* \brief NOVA-specific convenience functions
|
||||
* \author Norman Feske
|
||||
* \author Sebastian Sumpf
|
||||
* \author Alexander Boettcher
|
||||
* \date 2010-01-19
|
||||
*/
|
||||
|
||||
@ -86,6 +87,20 @@ inline int map_local_one_to_one(Nova::Utcb *utcb, Nova::Crd crd) {
|
||||
return map_local(utcb, crd, crd, true); }
|
||||
|
||||
|
||||
/**
|
||||
* Find least significant set bit in value
|
||||
*/
|
||||
inline unsigned char
|
||||
lsb_bit(unsigned long const &value, unsigned char const shift = 0)
|
||||
{
|
||||
unsigned long const scan = value >> shift;
|
||||
if (scan == 0) return 0;
|
||||
|
||||
unsigned char pos = __builtin_ctzl(scan);
|
||||
unsigned char res = shift ? pos + shift : pos;
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remap pages in the local address space
|
||||
*
|
||||
@ -123,19 +138,10 @@ inline int map_local(Nova::Utcb *utcb,
|
||||
*/
|
||||
addr_t const common_bits = from_curr | to_curr;
|
||||
|
||||
/*
|
||||
* Find highest clear bit in 'diff', starting from the least
|
||||
* significant candidate. We can skip all bits lower then
|
||||
* 'get_page_size_log2()' because they are not relevant as flexpage
|
||||
* size (and are always zero).
|
||||
*/
|
||||
size_t order = get_page_size_log2();
|
||||
for (; order < 32 && !(common_bits & (1UL << order)); order++);
|
||||
|
||||
/*
|
||||
* Look if flexpage fits into both 'from' and 'to' address range
|
||||
*/
|
||||
/* find least set bit in common bits */
|
||||
size_t order = lsb_bit(common_bits, get_page_size_log2());
|
||||
|
||||
/* look if flexpage fits into both 'from' and 'to' address range */
|
||||
if ((from_end - from_curr) < (1UL << order))
|
||||
order = log2(from_end - from_curr);
|
||||
|
||||
@ -165,48 +171,42 @@ inline int map_local(Nova::Utcb *utcb,
|
||||
* \param utcb UTCB of the main thread
|
||||
* \param start local virtual address
|
||||
* \param num_pages number of pages to unmap
|
||||
* \param self unmap from this pd or solely from other pds
|
||||
*/
|
||||
inline void unmap_local(Nova::Utcb *utcb,
|
||||
Genode::addr_t start,
|
||||
Genode::size_t num_pages)
|
||||
inline void unmap_local(Nova::Utcb *utcb, Genode::addr_t start,
|
||||
Genode::size_t num_pages,
|
||||
bool const self = true)
|
||||
{
|
||||
if (verbose_local_map)
|
||||
Genode::printf("::unmap_local: from %lx, %zd pages\n",
|
||||
start, num_pages);
|
||||
|
||||
using namespace Nova;
|
||||
using namespace Genode;
|
||||
Rights const rwx(true, true, true);
|
||||
|
||||
Genode::addr_t end = start + (num_pages << get_page_size_log2()) - 1;
|
||||
Genode::addr_t base = start >> get_page_size_log2();
|
||||
|
||||
while (true) {
|
||||
Nova::Mem_crd crd(start >> 12, 32, rwx);
|
||||
Nova::lookup(crd);
|
||||
if (start & (get_page_size() - 1)) {
|
||||
PERR("unmap failed - unaligned address specified");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!crd.is_null()) {
|
||||
if (verbose_local_map)
|
||||
PINF("Unmapping local: range 0x%lx+0x%zx", base, num_pages);
|
||||
|
||||
if (verbose_local_map)
|
||||
PINF("Unmapping local: %08lx base: %lx order: %lx size: %lx is null: %d",
|
||||
start, crd.base(), crd.order(),
|
||||
(0x1000UL << crd.order()), crd.is_null());
|
||||
Nova::Rights const rwx = Nova::Rights(true, true, true);
|
||||
|
||||
unmap_local(crd, true);
|
||||
while (num_pages) {
|
||||
unsigned char const base_bit = lsb_bit(base);
|
||||
unsigned char const order_bit = min(log2(num_pages), 31U);
|
||||
unsigned char const order = min(order_bit, base_bit);
|
||||
|
||||
start = (crd.base() << 12) /* base address of mapping */
|
||||
+ (0x1000 << crd.order()); /* size of mapping */
|
||||
} else {
|
||||
Mem_crd const crd(base, order, rwx);
|
||||
|
||||
/* This can happen if the region has never been touched */
|
||||
if (verbose_local_map)
|
||||
PINF("Unmapping local: 0x%lx+0x%lx", crd.base(),
|
||||
1UL << crd.order());
|
||||
|
||||
if (verbose_local_map)
|
||||
PINF("Nothing mapped at local: %08lx", start);
|
||||
unmap_local(crd, self);
|
||||
|
||||
start += 0x1000;
|
||||
}
|
||||
|
||||
if (start > end)
|
||||
return;
|
||||
num_pages -= 1UL << order;
|
||||
base += 1UL << order;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,53 +12,19 @@
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/printf.h>
|
||||
#include <base/ipc_pager.h>
|
||||
|
||||
/* core includes */
|
||||
#include <rm_session_component.h>
|
||||
#include <nova_util.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
static const bool verbose = false;
|
||||
|
||||
|
||||
void Rm_client::unmap(addr_t core_local_base, addr_t virt_base, size_t size)
|
||||
void Rm_client::unmap(addr_t core_local_base, addr_t, size_t size)
|
||||
{
|
||||
addr_t const core_local_end = core_local_base + (size - 1);
|
||||
off_t const core_to_virt = virt_base - core_local_base;
|
||||
using namespace Nova;
|
||||
|
||||
Nova::Rights rwx(true, true, true);
|
||||
Utcb * utcb = reinterpret_cast<Utcb *>(Genode::Thread_base::myself()->utcb());
|
||||
|
||||
while (true) {
|
||||
Nova::Mem_crd crd(core_local_base >> 12, 32, rwx);
|
||||
Nova::lookup(crd);
|
||||
|
||||
if (!crd.is_null()) {
|
||||
|
||||
if (verbose)
|
||||
PINF("Unmapping local: %08lx virt: %08lx base: %lx order: %lx size: %lx is null: %d",
|
||||
core_local_base, core_local_base + core_to_virt, crd.base(), crd.order(),
|
||||
(0x1000UL << crd.order()), crd.is_null());
|
||||
|
||||
unmap_local(crd, false);
|
||||
|
||||
core_local_base = (crd.base() << 12) /* base address of mapping */
|
||||
+ (0x1000 << crd.order()); /* size of mapping */
|
||||
} else {
|
||||
|
||||
/* this can happen if the region has never been touched */
|
||||
|
||||
if (verbose)
|
||||
PINF("Nothing mapped at local: %08lx virt: %08lx",
|
||||
core_local_base, core_local_base + core_to_virt);
|
||||
|
||||
core_local_base += 0x1000;
|
||||
}
|
||||
|
||||
if (core_local_base > core_local_end)
|
||||
return;
|
||||
}
|
||||
unmap_local(utcb, trunc_page(core_local_base),
|
||||
(round_page(core_local_base + size) -
|
||||
trunc_page(core_local_base)) / get_page_size(), false);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user