From 738ca741665adc2367fd88c2d37cecd6f11dc8ff Mon Sep 17 00:00:00 2001 From: Alexander Boettcher Date: Wed, 13 Jul 2016 11:50:26 +0200 Subject: [PATCH] sel4: clear dataspace page wise Creating mappings inside core may exhaust the internal allocators if very large dataspaces must be cleared. Issue #2044 --- .../base-sel4/src/core/ram_session_support.cc | 64 ++++++++++--------- 1 file changed, 35 insertions(+), 29 deletions(-) diff --git a/repos/base-sel4/src/core/ram_session_support.cc b/repos/base-sel4/src/core/ram_session_support.cc index e21e53b91..923815e2b 100644 --- a/repos/base-sel4/src/core/ram_session_support.cc +++ b/repos/base-sel4/src/core/ram_session_support.cc @@ -11,9 +11,6 @@ * under the terms of the GNU General Public License version 2. */ -/* Genode includes */ -#include - /* core includes */ #include #include @@ -25,45 +22,54 @@ using namespace Genode; void Ram_session_component::_export_ram_ds(Dataspace_component *ds) { - size_t const num_pages = ds->size() >> get_page_size_log2(); + size_t const page_rounded_size = (ds->size() + get_page_size() - 1) & get_page_mask(); + size_t const num_pages = page_rounded_size >> get_page_size_log2(); + Untyped_memory::convert_to_page_frames(ds->phys_addr(), num_pages); } void Ram_session_component::_revoke_ram_ds(Dataspace_component *ds) { - Untyped_memory::convert_to_untyped_frames(ds->phys_addr(), ds->size()); + size_t const page_rounded_size = (ds->size() + get_page_size() - 1) & get_page_mask(); + + Untyped_memory::convert_to_untyped_frames(ds->phys_addr(), page_rounded_size); } void Ram_session_component::_clear_ds (Dataspace_component *ds) { - size_t page_rounded_size = (ds->size() + get_page_size() - 1) & get_page_mask(); + size_t const page_rounded_size = (ds->size() + get_page_size() - 1) & get_page_mask(); - /* allocate range in core's virtual address space */ - void *virt_addr; - if (!platform()->region_alloc()->alloc(page_rounded_size, &virt_addr)) { - error("could not allocate virtual address range in core of size ", - page_rounded_size); - return; + enum { ONE_PAGE = 1 }; + + /* allocate one page in core's virtual address space */ + void *virt_addr_ptr = nullptr; + if (!platform()->region_alloc()->alloc(get_page_size(), &virt_addr_ptr) || + !virt_addr_ptr) + ASSERT(!"could not map 4k inside core"); + + addr_t const virt_addr = reinterpret_cast(virt_addr_ptr); + + /* map each page of dataspace one at a time and clear it */ + for (addr_t offset = 0; offset < page_rounded_size; offset += get_page_size()) + { + addr_t const phys_addr = ds->phys_addr() + offset; + + /* map one physical page to the core-local address */ + if (!map_local(phys_addr, virt_addr, ONE_PAGE)) { + ASSERT(!"could not map 4k inside core"); + } + + /* clear one page */ + size_t num_longwords = get_page_size()/sizeof(long); + for (long *dst = reinterpret_cast(virt_addr); num_longwords--;) + *dst++ = 0; + + /* unmap cleared page from core */ + unmap_local(virt_addr, ONE_PAGE); } - /* map the dataspace's physical pages to core-local virtual addresses */ - size_t num_pages = page_rounded_size >> get_page_size_log2(); - if (!map_local(ds->phys_addr(), (addr_t)virt_addr, num_pages)) { - error("could not map virtual address range in core of size ", - page_rounded_size); - return; - } - - /* clear dataspace */ - size_t num_longwords = page_rounded_size/sizeof(long); - for (long *dst = (long *)virt_addr; num_longwords--;) - *dst++ = 0; - - /* unmap dataspace from core */ - unmap_local((addr_t)virt_addr, num_pages); - /* free core's virtual address space */ - platform()->region_alloc()->free(virt_addr, page_rounded_size); + platform()->region_alloc()->free(virt_addr_ptr, get_page_size()); }