hw: detach UTCB from core PD in thread destruction

Ref genodelabs/genode#5380
This commit is contained in:
Stefan Kalkowski 2024-11-11 13:01:59 +01:00 committed by Christian Helmuth
parent 9a7fe5e775
commit 7dbc9129db
2 changed files with 116 additions and 58 deletions

View File

@ -30,6 +30,79 @@
using namespace Core;
Ram_dataspace_capability Platform_thread::Utcb::_allocate_utcb(bool core_thread)
{
Ram_dataspace_capability ds;
if (core_thread)
return ds;
try {
ds = core_env().pd_session()->alloc(sizeof(Native_utcb), CACHED);
} catch (...) {
error("failed to allocate UTCB");
throw Out_of_ram();
}
return ds;
}
addr_t Platform_thread::Utcb::_core_local_address(addr_t utcb_addr,
bool core_thread)
{
if (core_thread)
return utcb_addr;
addr_t ret = 0;
Region_map::Attr attr { };
attr.writeable = true;
core_env().rm_session()->attach(_ds, attr).with_result(
[&] (Region_map::Range range) {
ret = range.start; },
[&] (Region_map::Attach_error) {
error("failed to attach UTCB of new thread within core"); });
return ret;
}
Platform_thread::Utcb::Utcb(addr_t pd_addr, bool core_thread)
:
_ds(_allocate_utcb(core_thread)),
_core_addr(_core_local_address(pd_addr, core_thread))
{
/*
* All non-core threads use the typical dataspace/rm_session
* mechanisms to allocate and attach its UTCB.
* But for the very first core threads, we need to use plain
* physical and virtual memory allocators to create/attach its
* UTCBs. Therefore, we've to allocate and map those here.
*/
if (core_thread) {
platform().ram_alloc().try_alloc(sizeof(Native_utcb)).with_result(
[&] (void *utcb_phys) {
map_local((addr_t)utcb_phys, _core_addr,
sizeof(Native_utcb) / get_page_size());
},
[&] (Range_allocator::Alloc_error) {
error("failed to allocate UTCB for core/kernel thread!");
throw Out_of_ram();
}
);
}
}
Platform_thread::Utcb::~Utcb()
{
/* detach UTCB from core/kernel */
core_env().rm_session()->detach((addr_t)_core_addr);
}
void Platform_thread::_init() { }
@ -37,21 +110,6 @@ Weak_ptr<Address_space>& Platform_thread::address_space() {
return _address_space; }
Platform_thread::~Platform_thread()
{
/* detach UTCB of main threads */
if (_main_thread) {
Locked_ptr<Address_space> locked_ptr(_address_space);
if (locked_ptr.valid())
locked_ptr->flush((addr_t)_utcb_pd_addr, sizeof(Native_utcb),
Address_space::Core_local_addr{0});
}
/* free UTCB */
core_env().pd_session()->free(_utcb);
}
void Platform_thread::quota(size_t const quota)
{
_quota = (unsigned)quota;
@ -64,26 +122,10 @@ Platform_thread::Platform_thread(Label const &label, Native_utcb &utcb)
_label(label),
_pd(_kernel_main_get_core_platform_pd()),
_pager(nullptr),
_utcb_core_addr(&utcb),
_utcb_pd_addr(&utcb),
_utcb((addr_t)&utcb, true),
_main_thread(false),
_location(Affinity::Location()),
_kobj(_kobj.CALLED_FROM_CORE, _label.string())
{
/* create UTCB for a core thread */
platform().ram_alloc().try_alloc(sizeof(Native_utcb)).with_result(
[&] (void *utcb_phys) {
map_local((addr_t)utcb_phys, (addr_t)_utcb_core_addr,
sizeof(Native_utcb) / get_page_size());
},
[&] (Range_allocator::Alloc_error) {
error("failed to allocate UTCB");
/* XXX distinguish error conditions */
throw Out_of_ram();
}
);
}
_kobj(_kobj.CALLED_FROM_CORE, _label.string()) { }
Platform_thread::Platform_thread(Platform_pd &pd,
@ -96,33 +138,39 @@ Platform_thread::Platform_thread(Platform_pd &pd,
_label(label),
_pd(pd),
_pager(nullptr),
_utcb_pd_addr((Native_utcb *)utcb),
_utcb(utcb, false),
_priority(_scale_priority(virt_prio)),
_quota((unsigned)quota),
_main_thread(!pd.has_any_thread),
_location(location),
_kobj(_kobj.CALLED_FROM_CORE, _priority, _quota, _label.string())
{
try {
_utcb = core_env().pd_session()->alloc(sizeof(Native_utcb), CACHED);
} catch (...) {
error("failed to allocate UTCB");
throw Out_of_ram();
}
Region_map::Attr attr { };
attr.writeable = true;
core_env().rm_session()->attach(_utcb, attr).with_result(
[&] (Region_map::Range range) {
_utcb_core_addr = (Native_utcb *)range.start; },
[&] (Region_map::Attach_error) {
error("failed to attach UTCB of new thread within core"); });
_address_space = pd.weak_ptr();
pd.has_any_thread = true;
}
Platform_thread::~Platform_thread()
{
/* core/kernel threads have no dataspace, but plain memory as UTCB */
if (!_utcb._ds.valid()) {
error("UTCB of core/kernel thread gets destructed!");
return;
}
/* detach UTCB of main threads */
if (_main_thread) {
Locked_ptr<Address_space> locked_ptr(_address_space);
if (locked_ptr.valid())
locked_ptr->flush(user_utcb_main_thread(), sizeof(Native_utcb),
Address_space::Core_local_addr{0});
}
/* free UTCB */
core_env().pd_session()->free(_utcb._ds);
}
void Platform_thread::affinity(Affinity::Location const &)
{
/* yet no migration support, don't claim wrong location, e.g. for tracing */
@ -147,16 +195,15 @@ void Platform_thread::start(void * const ip, void * const sp)
error("invalid RM client");
return -1;
};
_utcb_pd_addr = (Native_utcb *)user_utcb_main_thread();
Hw::Address_space * as = static_cast<Hw::Address_space*>(&*locked_ptr);
if (!as->insert_translation((addr_t)_utcb_pd_addr, dsc->phys_addr(),
if (!as->insert_translation(user_utcb_main_thread(), dsc->phys_addr(),
sizeof(Native_utcb), Hw::PAGE_FLAGS_UTCB)) {
error("failed to attach UTCB");
return -1;
}
return 0;
};
if (core_env().entrypoint().apply(_utcb, lambda))
if (core_env().entrypoint().apply(_utcb._ds, lambda))
return;
}
@ -174,9 +221,9 @@ void Platform_thread::start(void * const ip, void * const sp)
utcb.cap_add(Capability_space::capid(_kobj.cap()));
if (_main_thread) {
utcb.cap_add(Capability_space::capid(_pd.parent()));
utcb.cap_add(Capability_space::capid(_utcb));
utcb.cap_add(Capability_space::capid(_utcb._ds));
}
Kernel::start_thread(*_kobj, cpu, _pd.kernel_pd(), *_utcb_core_addr);
Kernel::start_thread(*_kobj, cpu, _pd.kernel_pd(), *(Native_utcb*)_utcb._core_addr);
}

View File

@ -55,13 +55,24 @@ class Core::Platform_thread : Noncopyable
using Label = String<32>;
struct Utcb
{
Ram_dataspace_capability _ds { }; /* UTCB ds of non-core threads */
addr_t const _core_addr; /* UTCB address within core/kernel */
Ram_dataspace_capability _allocate_utcb(bool core_thread);
addr_t _core_local_address(addr_t utcb_addr, bool core_thread);
Utcb(addr_t pd_addr, bool core_thread);
~Utcb();
};
Label const _label;
Platform_pd &_pd;
Weak_ptr<Address_space> _address_space { };
Pager_object * _pager;
Native_utcb * _utcb_core_addr { }; /* UTCB addr in core */
Native_utcb * _utcb_pd_addr; /* UTCB addr in pd */
Ram_dataspace_capability _utcb { }; /* UTCB dataspace */
Utcb _utcb;
unsigned _priority {0};
unsigned _quota {0};
@ -241,7 +252,7 @@ class Core::Platform_thread : Noncopyable
Platform_pd &pd() const { return _pd; }
Ram_dataspace_capability utcb() const { return _utcb; }
Ram_dataspace_capability utcb() const { return _utcb._ds; }
};
#endif /* _CORE__PLATFORM_THREAD_H_ */