core: don't rely on Core_env in platform.cc

Replace the use of the global 'core_env()' accessor by the explicit
delegation of interfaces.

- For allocating UTCBs in base-hw, 'Platform_thread' requires
  a way to allocate dataspaces ('Ram_allocator') accounted to the
  corresponding CPU session, a way to locally map the allocated
  dataspaces (core's 'Region_map'), and a way to determine the
  physical address (via 'Rpc_entrypoint') used for the initial
  UTCB mapping of main threads. Hence those interfaces must be
  passed to 'Platform_thread'.

- NOVA's pager code needs to look up 'Cpu_thread_component'
  objects using a map item as key. The lookup requires the
  'Rpc_entrypoint' that hold the 'Cpu_thread_component' objects.
  To make this 'Rpc_entrypoint' available, this patch adds
  the 'init_page_fault_handing' function.

- The 'Region_map_mmap' for Linux requires a way to look up
  'Linux_dataspace' objects for given dataspace capabilities.
  This lookup requires the 'Rpc_entrypoint' holding the dataspaces,
  which is now passed to 'platform.cc' via the new Linux-specific
  'Core_region_map::init' function.

Issue #5408
This commit is contained in:
Norman Feske
2024-12-16 12:17:09 +01:00
committed by Christian Helmuth
parent ac5cfb59ea
commit 43d7c3bd11
43 changed files with 222 additions and 150 deletions

View File

@ -25,7 +25,9 @@ namespace Core { class Core_region_map; }
struct Core::Core_region_map : Region_map_mmap
{
Core_region_map(Rpc_entrypoint &) : Region_map_mmap(false) { }
static void init(Rpc_entrypoint &);
Core_region_map(Rpc_entrypoint &ep) : Region_map_mmap(false) { init(ep); }
};
#endif /* _CORE__INCLUDE__CORE_REGION_MAP_H_ */

View File

@ -29,6 +29,8 @@ namespace Core {
struct Pager_entrypoint;
using Pager_capability = Capability<Pager_object>;
extern void init_page_fault_handling(Rpc_entrypoint &);
}

View File

@ -69,7 +69,8 @@ class Core::Platform_thread : Noncopyable
/**
* Constructor
*/
Platform_thread(Platform_pd &, size_t, auto const &name, auto...)
Platform_thread(Platform_pd &, Rpc_entrypoint &, Ram_allocator &, Region_map &,
size_t, auto const &name, auto...)
: _name(name) { }
/**

View File

@ -160,25 +160,48 @@ void Core::Platform::wait_for_exit()
}
void Core::init_page_fault_handling(Rpc_entrypoint &) { }
/*********************************
** Support for Region_map_mmap **
*********************************/
static Rpc_entrypoint *_core_ep_ptr;
void Core_region_map::init(Rpc_entrypoint &ep) { _core_ep_ptr = &ep; }
static auto with_linux_dataspace(Capability<Dataspace> ds,
auto const &fn, auto const &missing_fn) -> decltype(missing_fn())
{
if (!_core_ep_ptr)
error("missing call of Core_region_map::init");
Capability<Linux_dataspace> lx_ds = static_cap_cast<Linux_dataspace>(ds);
if (_core_ep_ptr)
return _core_ep_ptr->apply(lx_ds, [&] (Linux_dataspace *ds_ptr) {
return ds_ptr ? fn(*ds_ptr) : missing_fn(); });
return missing_fn();
}
size_t Region_map_mmap::_dataspace_size(Capability<Dataspace> ds_cap)
{
if (!ds_cap.valid())
return Local_capability<Dataspace>::deref(ds_cap)->size();
/* use local function call if called from the entrypoint */
return core_env().entrypoint().apply(ds_cap, [] (Dataspace *ds) {
return ds ? ds->size() : 0; });
return with_linux_dataspace(ds_cap,
[&] (Linux_dataspace &ds) -> size_t { return ds.size(); },
[&] () /* missing */ -> size_t { return 0; });
}
int Region_map_mmap::_dataspace_fd(Capability<Dataspace> ds_cap)
{
Capability<Linux_dataspace> lx_ds_cap = static_cap_cast<Linux_dataspace>(ds_cap);
/*
* Return a duplicate of the dataspace file descriptor, which will be freed
* immediately after mmap'ing the file (see 'Region_map_mmap').
@ -188,13 +211,19 @@ int Region_map_mmap::_dataspace_fd(Capability<Dataspace> ds_cap)
* socket descriptor during the RPC handling). When later destroying the
* dataspace, the descriptor would unexpectedly be closed again.
*/
return core_env().entrypoint().apply(lx_ds_cap, [] (Linux_dataspace *ds) {
return ds ? lx_dup(Capability_space::ipc_cap_data(ds->fd()).dst.socket.value) : -1; });
return with_linux_dataspace(ds_cap,
[&] (Linux_dataspace &ds)
{
return lx_dup(Capability_space::ipc_cap_data(ds.fd()).dst.socket.value);
},
[&] /* missing */ { return -1; });
}
bool Region_map_mmap::_dataspace_writeable(Dataspace_capability ds_cap)
{
return core_env().entrypoint().apply(ds_cap, [] (Dataspace *ds) {
return ds ? ds->writeable() : false; });
return with_linux_dataspace(ds_cap,
[&] (Linux_dataspace &ds) { return ds.writeable(); },
[&] /* missing */ { return false; });
}