From 0d81a104ad2502f46b917c87d7d0c2fdc4d76e18 Mon Sep 17 00:00:00 2001 From: Alexander Boettcher Date: Mon, 16 Dec 2024 08:43:38 +0100 Subject: [PATCH] base: use Map_local_result in io_mem _map_local(...) Issue #5406 --- .../src/core/io_mem_session_support.cc | 15 +++++++---- .../src/core/io_mem_session_support.cc | 24 +++++++++++------- .../src/core/io_mem_session_support.cc | 6 +++-- .../src/core/io_mem_session_support.cc | 5 +++- .../src/core/io_mem_session_support.cc | 5 +++- .../src/core/io_mem_session_support.cc | 17 +++++++------ .../src/core/include/untyped_memory.h | 25 +++++++++++++------ .../src/core/io_mem_session_support.cc | 7 +++--- .../core/include/io_mem_session_component.h | 9 ++++++- .../base/src/core/io_mem_session_component.cc | 8 ++++-- 10 files changed, 82 insertions(+), 39 deletions(-) diff --git a/repos/base-fiasco/src/core/io_mem_session_support.cc b/repos/base-fiasco/src/core/io_mem_session_support.cc index 55bcfab142..e55aa04ae3 100644 --- a/repos/base-fiasco/src/core/io_mem_session_support.cc +++ b/repos/base-fiasco/src/core/io_mem_session_support.cc @@ -38,8 +38,11 @@ static inline bool can_use_super_page(addr_t, size_t) } -addr_t Io_mem_session_component::_map_local(addr_t phys_base, size_t size) +Io_mem_session_component::Map_local_result Io_mem_session_component::_map_local(addr_t const phys_base, + size_t const size_in) { + size_t const size = size_in; + auto map_io_region = [] (addr_t phys_base, addr_t local_base, size_t size) { using namespace Fiasco; @@ -91,14 +94,16 @@ addr_t Io_mem_session_component::_map_local(addr_t phys_base, size_t size) size_t align = (size >= get_super_page_size()) ? get_super_page_size_log2() : get_page_size_log2(); - return platform().region_alloc().alloc_aligned(size, align).convert( + return platform().region_alloc().alloc_aligned(size, align).convert( [&] (void *ptr) { addr_t const core_local_base = (addr_t)ptr; map_io_region(phys_base, core_local_base, size); - return core_local_base; }, + return Map_local_result { .core_local_addr = core_local_base, .success = true }; + }, - [&] (Range_allocator::Alloc_error) -> addr_t { + [&] (Range_allocator::Alloc_error) { error("core-local mapping of memory-mapped I/O range failed"); - return 0; }); + return Map_local_result(); + }); } diff --git a/repos/base-foc/src/core/io_mem_session_support.cc b/repos/base-foc/src/core/io_mem_session_support.cc index b7fdaea88d..778ffb7e69 100644 --- a/repos/base-foc/src/core/io_mem_session_support.cc +++ b/repos/base-foc/src/core/io_mem_session_support.cc @@ -6,7 +6,7 @@ */ /* - * Copyright (C) 2006-2017 Genode Labs GmbH + * Copyright (C) 2006-2024 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU Affero General Public License version 3. @@ -21,31 +21,37 @@ using namespace Core; -void Io_mem_session_component::_unmap_local(addr_t base, size_t, addr_t) +void Io_mem_session_component::_unmap_local(addr_t base, size_t size, addr_t) { + if (!base) + return; + + unmap_local(base, size >> 12); platform().region_alloc().free(reinterpret_cast(base)); } -addr_t Io_mem_session_component::_map_local(addr_t base, size_t size) +Io_mem_session_component::Map_local_result Io_mem_session_component::_map_local(addr_t const base, + size_t const size) { /* align large I/O dataspaces on a super-page boundary within core */ size_t alignment = (size >= get_super_page_size()) ? get_super_page_size_log2() : get_page_size_log2(); - /* find appropriate region for mapping */ - return platform().region_alloc().alloc_aligned(size, (unsigned)alignment).convert( + /* find appropriate region and map it locally */ + return platform().region_alloc().alloc_aligned(size, (unsigned)alignment).convert( [&] (void *local_base) { if (!map_local_io(base, (addr_t)local_base, size >> get_page_size_log2())) { - error("map_local_io failed"); + error("map_local_io failed ", Hex_range(base, size)); platform().region_alloc().free(local_base, base); - return 0UL; + return Map_local_result(); } - return (addr_t)local_base; + return Map_local_result { .core_local_addr = addr_t(local_base), + .success = true }; }, [&] (Range_allocator::Alloc_error) { error("allocation of virtual memory for local I/O mapping failed"); - return 0UL; }); + return Map_local_result(); }); } diff --git a/repos/base-hw/src/core/io_mem_session_support.cc b/repos/base-hw/src/core/io_mem_session_support.cc index a25f199fd8..42092b1e6a 100644 --- a/repos/base-hw/src/core/io_mem_session_support.cc +++ b/repos/base-hw/src/core/io_mem_session_support.cc @@ -21,5 +21,7 @@ using namespace Core; void Io_mem_session_component::_unmap_local(addr_t, size_t, addr_t) { } -addr_t Io_mem_session_component::_map_local(addr_t base, size_t) { return base; } - +Io_mem_session_component::Map_local_result Io_mem_session_component::_map_local(addr_t const base, size_t) +{ + return { .core_local_addr = base, .success = true }; +} diff --git a/repos/base-nova/src/core/io_mem_session_support.cc b/repos/base-nova/src/core/io_mem_session_support.cc index 4bba83ebdc..d249d0368e 100644 --- a/repos/base-nova/src/core/io_mem_session_support.cc +++ b/repos/base-nova/src/core/io_mem_session_support.cc @@ -23,4 +23,7 @@ using namespace Core; void Io_mem_session_component::_unmap_local(addr_t, size_t, addr_t) { } -addr_t Io_mem_session_component::_map_local(addr_t, size_t) { return 0; } +Io_mem_session_component::Map_local_result Io_mem_session_component::_map_local(addr_t, size_t) +{ + return { .core_local_addr = 0, .success = true }; +} diff --git a/repos/base-okl4/src/core/io_mem_session_support.cc b/repos/base-okl4/src/core/io_mem_session_support.cc index 6b0422ea42..b552e88f5b 100644 --- a/repos/base-okl4/src/core/io_mem_session_support.cc +++ b/repos/base-okl4/src/core/io_mem_session_support.cc @@ -22,4 +22,7 @@ using namespace Core; void Io_mem_session_component::_unmap_local(addr_t, size_t, addr_t) { } -addr_t Io_mem_session_component::_map_local(addr_t, size_t) { return 0; } +Io_mem_session_component::Map_local_result Io_mem_session_component::_map_local(addr_t, size_t) +{ + return { .core_local_addr = 0, .success = true }; +} diff --git a/repos/base-pistachio/src/core/io_mem_session_support.cc b/repos/base-pistachio/src/core/io_mem_session_support.cc index f0763ab1e7..29adba2149 100644 --- a/repos/base-pistachio/src/core/io_mem_session_support.cc +++ b/repos/base-pistachio/src/core/io_mem_session_support.cc @@ -56,15 +56,18 @@ static inline bool can_use_super_page(addr_t base, size_t size) } -addr_t Io_mem_session_component::_map_local(addr_t base, size_t size) +Io_mem_session_component::Map_local_result Io_mem_session_component::_map_local(addr_t const phys_base, + size_t const size_in) { using namespace Pistachio; + auto size = size_in; + auto alloc_virt_range = [&] { /* special case for the null page */ - if (is_conventional_memory(base)) - return base; + if (is_conventional_memory(phys_base)) + return phys_base; /* align large I/O dataspaces to super page size, otherwise to size */ size_t const align = (size >= get_super_page_size()) @@ -81,16 +84,16 @@ addr_t Io_mem_session_component::_map_local(addr_t base, size_t size) addr_t const local_base = (addr_t)alloc_virt_range(); if (!local_base) - return 0; + return Map_local_result (); for (unsigned offset = 0; size; ) { size_t page_size = get_page_size(); - if (can_use_super_page(base + offset, size)) + if (can_use_super_page(phys_base + offset, size)) page_size = get_super_page_size(); L4_Sigma0_GetPage_RcvWindow(get_sigma0(), - L4_Fpage(base + offset, page_size), + L4_Fpage(phys_base + offset, page_size), L4_Fpage(local_base + offset, page_size)); if (_cacheable == WRITE_COMBINED) { @@ -104,5 +107,5 @@ addr_t Io_mem_session_component::_map_local(addr_t base, size_t size) size -= page_size; } - return local_base; + return { .core_local_addr = local_base, .success = true }; } diff --git a/repos/base-sel4/src/core/include/untyped_memory.h b/repos/base-sel4/src/core/include/untyped_memory.h index 53c916d1b4..9f89803af8 100644 --- a/repos/base-sel4/src/core/include/untyped_memory.h +++ b/repos/base-sel4/src/core/include/untyped_memory.h @@ -98,9 +98,11 @@ struct Core::Untyped_memory /** * Create page frames from untyped memory */ - static inline void convert_to_page_frames(addr_t phys_addr, + static inline bool convert_to_page_frames(addr_t phys_addr, size_t num_pages) { + auto const phys_addr_base = phys_addr; + for (size_t i = 0; i < num_pages; i++, phys_addr += get_page_size()) { seL4_Untyped const service = untyped_sel(phys_addr).value(); @@ -121,14 +123,21 @@ struct Core::Untyped_memory node_offset, num_objects); - if (ret != seL4_NoError) { - error(__FUNCTION__, ": seL4_Untyped_RetypeAtOffset " - "returned ", ret, " - physical_range=", - Hex_range(node_offset << get_page_size_log2(), - (num_pages - i) * get_page_size())); - return; - } + if (ret == seL4_NoError) + continue; + + error(__FUNCTION__, ": seL4_Untyped_RetypeAtOffset " + "returned ", ret, " - physical_range=", + Hex_range(node_offset << get_page_size_log2(), + (num_pages - i) * get_page_size())); + + /* revert already converted memory */ + convert_to_untyped_frames(phys_addr_base, get_page_size() * i); + + return false; } + + return true; } diff --git a/repos/base-sel4/src/core/io_mem_session_support.cc b/repos/base-sel4/src/core/io_mem_session_support.cc index 008746945c..e93e0ccb3e 100644 --- a/repos/base-sel4/src/core/io_mem_session_support.cc +++ b/repos/base-sel4/src/core/io_mem_session_support.cc @@ -25,10 +25,11 @@ void Io_mem_session_component::_unmap_local(addr_t, size_t size, addr_t phys) } -addr_t Io_mem_session_component::_map_local(addr_t phys, size_t size) +Io_mem_session_component::Map_local_result Io_mem_session_component::_map_local(addr_t const phys, + size_t const size) { size_t const num_pages = size >> get_page_size_log2(); - Untyped_memory::convert_to_page_frames(phys, num_pages); - return 0; + return { .core_local_addr = 0, + .success = Untyped_memory::convert_to_page_frames(phys, num_pages) }; } diff --git a/repos/base/src/core/include/io_mem_session_component.h b/repos/base/src/core/include/io_mem_session_component.h index 93a6ea08bf..08f02095ce 100644 --- a/repos/base/src/core/include/io_mem_session_component.h +++ b/repos/base/src/core/include/io_mem_session_component.h @@ -67,6 +67,12 @@ class Core::Io_mem_session_component : public Rpc_object cacheable(c), req_base(req_base) { } }; + struct Map_local_result + { + addr_t core_local_addr { 0 }; + bool success { }; + }; + struct Io_dataspace_component : Dataspace_component { addr_t req_base; @@ -105,7 +111,8 @@ class Core::Io_mem_session_component : public Rpc_object * * Both parameters - base and size - must be page-aligned. */ - addr_t _map_local(addr_t base, size_t size); + Map_local_result _map_local(addr_t base, size_t size); + /** * Unmap Core-local mapping of region diff --git a/repos/base/src/core/io_mem_session_component.cc b/repos/base/src/core/io_mem_session_component.cc index ab680b4f8c..aa33e2edbc 100644 --- a/repos/base/src/core/io_mem_session_component.cc +++ b/repos/base/src/core/io_mem_session_component.cc @@ -75,9 +75,13 @@ Io_mem_session_component::_prepare_io_mem(const char *args, } /* request local mapping */ - addr_t local_addr = _map_local(base, size); + auto const map_result = _map_local(base, size); - return Dataspace_attr(size, local_addr, base, _cacheable, req_base); + if (!map_result.success) + return Dataspace_attr(); + + return Dataspace_attr(size, map_result.core_local_addr, base, _cacheable, + req_base); }