mirror of
https://github.com/mmueller41/genode.git
synced 2026-01-21 20:42:56 +01:00
nova: implement Pd_session::map
- factor out Rm_client::pager lambda code into utility Region_map_component::create_map_item - use utility to find/lookup physical addresses to be mapped eagerly Issue #2209
This commit is contained in:
committed by
Christian Helmuth
parent
58e4f6cf9d
commit
fe4bdde687
@@ -32,4 +32,64 @@ bool Pd_session_component::assign_pci(addr_t pci_config_memory, uint16_t bdf)
|
||||
}
|
||||
|
||||
|
||||
void Pd_session_component::map(addr_t, addr_t) { }
|
||||
void Pd_session_component::map(addr_t virt, addr_t size)
|
||||
{
|
||||
Genode::addr_t const pd_core = platform_specific()->core_pd_sel();
|
||||
Platform_pd &target_pd = *_pd;
|
||||
Genode::addr_t const pd_dst = target_pd.pd_sel();
|
||||
Nova::Utcb *utcb = reinterpret_cast<Nova::Utcb *>(Thread::myself()->utcb());
|
||||
|
||||
auto lambda = [&] (Region_map_component *region_map,
|
||||
Rm_region *region,
|
||||
addr_t ds_offset,
|
||||
addr_t region_offset) -> addr_t
|
||||
{
|
||||
Dataspace_component * dsc = region ? region->dataspace() : nullptr;
|
||||
if (!dsc)
|
||||
return ~0UL;
|
||||
|
||||
Mapping mapping = Region_map_component::create_map_item(region_map,
|
||||
region,
|
||||
ds_offset,
|
||||
region_offset,
|
||||
dsc, virt);
|
||||
|
||||
/* asynchronously map memory */
|
||||
uint8_t err = Nova::NOVA_PD_OOM;
|
||||
do {
|
||||
utcb->set_msg_word(0);
|
||||
bool res = utcb->append_item(mapping.mem_crd(), 0, true, false,
|
||||
false, mapping.dma(),
|
||||
mapping.write_combined());
|
||||
/* one item ever fits on the UTCB */
|
||||
(void)res;
|
||||
|
||||
/* receive window in destination pd */
|
||||
Nova::Mem_crd crd_mem(mapping.dst_addr() >> 12,
|
||||
mapping.mem_crd().order(),
|
||||
Nova::Rights(true, dsc->writable(), true));
|
||||
|
||||
err = Nova::delegate(pd_core, pd_dst, crd_mem);
|
||||
} while (err == Nova::NOVA_PD_OOM &&
|
||||
Nova::NOVA_OK == Pager_object::handle_oom(Pager_object::SRC_CORE_PD,
|
||||
_pd->pd_sel(),
|
||||
"core", "ep",
|
||||
Pager_object::Policy::UPGRADE_CORE_TO_DST));
|
||||
|
||||
addr_t const map_crd_size = 1UL << (mapping.mem_crd().order() + 12);
|
||||
addr_t const mapped = mapping.dst_addr() + map_crd_size - virt;
|
||||
|
||||
if (err != Nova::NOVA_OK)
|
||||
error("could not map memory ",
|
||||
Hex_range<addr_t>(mapping.dst_addr(), map_crd_size) , " "
|
||||
"eagerly error=", err);
|
||||
|
||||
return mapped;
|
||||
};
|
||||
|
||||
while (size) {
|
||||
addr_t mapped = _address_space.apply_to_dataspace(virt, lambda);
|
||||
virt += mapped;
|
||||
size = size < mapped ? size - mapped : 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -399,6 +399,15 @@ class Genode::Region_map_component : public Genode::Weak_object<Genode::Region_m
|
||||
void add_client(Rm_client &);
|
||||
void remove_client(Rm_client &);
|
||||
|
||||
/**
|
||||
* Create mapping item to be placed into the page table
|
||||
*/
|
||||
static Mapping create_map_item(Region_map_component *region_map,
|
||||
Rm_region *region,
|
||||
addr_t ds_offset,
|
||||
addr_t region_offset,
|
||||
Dataspace_component *dsc,
|
||||
addr_t);
|
||||
|
||||
/**************************
|
||||
** Region map interface **
|
||||
|
||||
@@ -171,8 +171,6 @@ static void print_page_fault(char const *msg,
|
||||
|
||||
int Rm_client::pager(Ipc_pager &pager)
|
||||
{
|
||||
using Fault_area = Region_map_component::Fault_area;
|
||||
|
||||
Region_map::State::Fault_type pf_type = pager.write_fault() ? Region_map::State::WRITE_FAULT
|
||||
: Region_map::State::READ_FAULT;
|
||||
addr_t pf_addr = pager.fault_addr();
|
||||
@@ -208,25 +206,6 @@ int Rm_client::pager(Ipc_pager &pager)
|
||||
return 1;
|
||||
}
|
||||
|
||||
addr_t ds_base = dsc->map_src_addr();
|
||||
Fault_area src_fault_area(ds_base + ds_offset);
|
||||
Fault_area dst_fault_area(pf_addr);
|
||||
src_fault_area.constrain(ds_base, dsc->size());
|
||||
dst_fault_area.constrain(region_offset + region->base(), region->size());
|
||||
|
||||
/*
|
||||
* Determine mapping size compatible with source and destination,
|
||||
* and apply platform-specific constraint of mapping sizes.
|
||||
*/
|
||||
size_t map_size_log2 = dst_fault_area.common_size_log2(dst_fault_area,
|
||||
src_fault_area);
|
||||
map_size_log2 = constrain_map_size_log2(map_size_log2);
|
||||
|
||||
src_fault_area.constrain(map_size_log2);
|
||||
dst_fault_area.constrain(map_size_log2);
|
||||
if (!src_fault_area.valid() || !dst_fault_area.valid())
|
||||
error("invalid mapping");
|
||||
|
||||
/*
|
||||
* Check if dataspace is compatible with page-fault type
|
||||
*/
|
||||
@@ -237,13 +216,15 @@ int Rm_client::pager(Ipc_pager &pager)
|
||||
pf_addr, pf_ip, pf_type, *this);
|
||||
|
||||
/* register fault at responsible region map */
|
||||
region_map->fault(this, src_fault_area.fault_addr(), pf_type);
|
||||
region_map->fault(this, dsc->map_src_addr() + ds_offset, pf_type);
|
||||
return 2;
|
||||
}
|
||||
|
||||
Mapping mapping(dst_fault_area.base(), src_fault_area.base(),
|
||||
dsc->cacheability(), dsc->io_mem(),
|
||||
map_size_log2, dsc->writable());
|
||||
Mapping mapping = Region_map_component::create_map_item(region_map,
|
||||
region,
|
||||
ds_offset,
|
||||
region_offset,
|
||||
dsc, pf_addr);
|
||||
|
||||
/*
|
||||
* On kernels with a mapping database, the 'dsc' dataspace is a leaf
|
||||
@@ -313,6 +294,38 @@ void Rm_faulter::continue_after_resolved_fault()
|
||||
** Region-map component **
|
||||
**************************/
|
||||
|
||||
Mapping Region_map_component::create_map_item(Region_map_component *region_map,
|
||||
Rm_region *region,
|
||||
addr_t ds_offset,
|
||||
addr_t region_offset,
|
||||
Dataspace_component *dsc,
|
||||
addr_t page_addr)
|
||||
{
|
||||
addr_t ds_base = dsc->map_src_addr();
|
||||
Fault_area src_fault_area(ds_base + ds_offset);
|
||||
Fault_area dst_fault_area(page_addr);
|
||||
src_fault_area.constrain(ds_base, dsc->size());
|
||||
dst_fault_area.constrain(region_offset + region->base(), region->size());
|
||||
|
||||
/*
|
||||
* Determine mapping size compatible with source and destination,
|
||||
* and apply platform-specific constraint of mapping sizes.
|
||||
*/
|
||||
size_t map_size_log2 = dst_fault_area.common_size_log2(dst_fault_area,
|
||||
src_fault_area);
|
||||
map_size_log2 = constrain_map_size_log2(map_size_log2);
|
||||
|
||||
src_fault_area.constrain(map_size_log2);
|
||||
dst_fault_area.constrain(map_size_log2);
|
||||
if (!src_fault_area.valid() || !dst_fault_area.valid())
|
||||
error("invalid mapping");
|
||||
|
||||
return Mapping(dst_fault_area.base(), src_fault_area.base(),
|
||||
dsc->cacheability(), dsc->io_mem(),
|
||||
map_size_log2, dsc->writable());
|
||||
};
|
||||
|
||||
|
||||
Region_map::Local_addr
|
||||
Region_map_component::attach(Dataspace_capability ds_cap, size_t size,
|
||||
off_t offset, bool use_local_addr,
|
||||
|
||||
Reference in New Issue
Block a user