mirror of
https://github.com/genodelabs/genode.git
synced 2025-03-14 16:26:30 +00:00
parent
12f87260c0
commit
0d81a104ad
@ -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();
|
||||
});
|
||||
}
|
||||
|
@ -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(); });
|
||||
}
|
||||
|
@ -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 };
|
||||
}
|
||||
|
@ -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 };
|
||||
}
|
||||
|
@ -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 };
|
||||
}
|
||||
|
@ -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 };
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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) };
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user