base: use Map_local_result in io_mem _map_local(...)

Issue #5406
This commit is contained in:
Alexander Boettcher 2024-12-16 08:43:38 +01:00 committed by Christian Helmuth
parent 12f87260c0
commit 0d81a104ad
10 changed files with 82 additions and 39 deletions

View File

@ -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<addr_t>(
return platform().region_alloc().alloc_aligned(size, align).convert<Map_local_result>(
[&] (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();
});
}

View File

@ -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<void *>(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<addr_t>(
/* find appropriate region and map it locally */
return platform().region_alloc().alloc_aligned(size, (unsigned)alignment).convert<Map_local_result>(
[&] (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(); });
}

View File

@ -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 };
}

View File

@ -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 };
}

View File

@ -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 };
}

View File

@ -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 };
}

View File

@ -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;
}

View File

@ -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) };
}

View File

@ -67,6 +67,12 @@ class Core::Io_mem_session_component : public Rpc_object<Io_mem_session>
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<Io_mem_session>
*
* 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

View File

@ -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);
}