mirror of
https://github.com/genodelabs/genode.git
synced 2025-05-04 17:53:07 +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)
|
auto map_io_region = [] (addr_t phys_base, addr_t local_base, size_t size)
|
||||||
{
|
{
|
||||||
using namespace Fiasco;
|
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()
|
size_t align = (size >= get_super_page_size()) ? get_super_page_size_log2()
|
||||||
: get_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) {
|
[&] (void *ptr) {
|
||||||
addr_t const core_local_base = (addr_t)ptr;
|
addr_t const core_local_base = (addr_t)ptr;
|
||||||
map_io_region(phys_base, core_local_base, size);
|
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");
|
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
|
* This file is part of the Genode OS framework, which is distributed
|
||||||
* under the terms of the GNU Affero General Public License version 3.
|
* under the terms of the GNU Affero General Public License version 3.
|
||||||
@ -21,31 +21,37 @@
|
|||||||
using namespace Core;
|
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));
|
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 */
|
/* 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()
|
size_t alignment = (size >= get_super_page_size()) ? get_super_page_size_log2()
|
||||||
: get_page_size_log2();
|
: get_page_size_log2();
|
||||||
|
|
||||||
/* find appropriate region for mapping */
|
/* find appropriate region and map it locally */
|
||||||
return platform().region_alloc().alloc_aligned(size, (unsigned)alignment).convert<addr_t>(
|
return platform().region_alloc().alloc_aligned(size, (unsigned)alignment).convert<Map_local_result>(
|
||||||
|
|
||||||
[&] (void *local_base) {
|
[&] (void *local_base) {
|
||||||
if (!map_local_io(base, (addr_t)local_base, size >> get_page_size_log2())) {
|
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);
|
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) {
|
[&] (Range_allocator::Alloc_error) {
|
||||||
error("allocation of virtual memory for local I/O mapping failed");
|
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) { }
|
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) { }
|
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) { }
|
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;
|
using namespace Pistachio;
|
||||||
|
|
||||||
|
auto size = size_in;
|
||||||
|
|
||||||
auto alloc_virt_range = [&]
|
auto alloc_virt_range = [&]
|
||||||
{
|
{
|
||||||
/* special case for the null page */
|
/* special case for the null page */
|
||||||
if (is_conventional_memory(base))
|
if (is_conventional_memory(phys_base))
|
||||||
return base;
|
return phys_base;
|
||||||
|
|
||||||
/* align large I/O dataspaces to super page size, otherwise to size */
|
/* align large I/O dataspaces to super page size, otherwise to size */
|
||||||
size_t const align = (size >= get_super_page_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();
|
addr_t const local_base = (addr_t)alloc_virt_range();
|
||||||
|
|
||||||
if (!local_base)
|
if (!local_base)
|
||||||
return 0;
|
return Map_local_result ();
|
||||||
|
|
||||||
for (unsigned offset = 0; size; ) {
|
for (unsigned offset = 0; size; ) {
|
||||||
|
|
||||||
size_t page_size = get_page_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();
|
page_size = get_super_page_size();
|
||||||
|
|
||||||
L4_Sigma0_GetPage_RcvWindow(get_sigma0(),
|
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));
|
L4_Fpage(local_base + offset, page_size));
|
||||||
|
|
||||||
if (_cacheable == WRITE_COMBINED) {
|
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;
|
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
|
* 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)
|
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()) {
|
for (size_t i = 0; i < num_pages; i++, phys_addr += get_page_size()) {
|
||||||
|
|
||||||
seL4_Untyped const service = untyped_sel(phys_addr).value();
|
seL4_Untyped const service = untyped_sel(phys_addr).value();
|
||||||
@ -121,14 +123,21 @@ struct Core::Untyped_memory
|
|||||||
node_offset,
|
node_offset,
|
||||||
num_objects);
|
num_objects);
|
||||||
|
|
||||||
if (ret != seL4_NoError) {
|
if (ret == seL4_NoError)
|
||||||
error(__FUNCTION__, ": seL4_Untyped_RetypeAtOffset "
|
continue;
|
||||||
"returned ", ret, " - physical_range=",
|
|
||||||
Hex_range(node_offset << get_page_size_log2(),
|
error(__FUNCTION__, ": seL4_Untyped_RetypeAtOffset "
|
||||||
(num_pages - i) * get_page_size()));
|
"returned ", ret, " - physical_range=",
|
||||||
return;
|
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();
|
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) { }
|
cacheable(c), req_base(req_base) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Map_local_result
|
||||||
|
{
|
||||||
|
addr_t core_local_addr { 0 };
|
||||||
|
bool success { };
|
||||||
|
};
|
||||||
|
|
||||||
struct Io_dataspace_component : Dataspace_component
|
struct Io_dataspace_component : Dataspace_component
|
||||||
{
|
{
|
||||||
addr_t req_base;
|
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.
|
* 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
|
* Unmap Core-local mapping of region
|
||||||
|
@ -75,9 +75,13 @@ Io_mem_session_component::_prepare_io_mem(const char *args,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* request local mapping */
|
/* 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