mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-20 17:52:52 +00:00
nova: support creation of vCPU in own PD
With the patch a VMM is not forced anymore to co-located the VMM and VM in same PD. Fixes #949
This commit is contained in:
parent
1df48b8331
commit
67c1ad4cdd
@ -52,6 +52,7 @@ namespace Genode {
|
||||
addr_t _initial_esp;
|
||||
addr_t _initial_eip;
|
||||
addr_t _client_exc_pt_sel;
|
||||
addr_t _client_exc_vcpu;
|
||||
|
||||
struct
|
||||
{
|
||||
@ -131,6 +132,7 @@ namespace Genode {
|
||||
*/
|
||||
addr_t exc_pt_sel() { return _tid.exc_pt_sel; }
|
||||
addr_t exc_pt_sel_client() { return _client_exc_pt_sel; }
|
||||
addr_t exc_pt_vcpu() { return _client_exc_vcpu; }
|
||||
|
||||
/**
|
||||
* Set initial stack pointer used by the startup handler
|
||||
@ -226,6 +228,18 @@ namespace Genode {
|
||||
* all remotely available portals had been revoked beforehand.
|
||||
*/
|
||||
void cleanup_call();
|
||||
|
||||
/**
|
||||
* Open receive window for initial portals for vCPU.
|
||||
*/
|
||||
void prepare_vCPU_portals()
|
||||
{
|
||||
_client_exc_vcpu = cap_map()->insert(Nova::NUM_INITIAL_VCPU_PT_LOG2);
|
||||
|
||||
Nova::Utcb *utcb = reinterpret_cast<Nova::Utcb *>(Thread_base::utcb());
|
||||
|
||||
utcb->crd_rcv = Nova::Obj_crd(_client_exc_vcpu, Nova::NUM_INITIAL_VCPU_PT_LOG2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
@ -550,6 +550,7 @@ namespace Nova {
|
||||
NUM_INITIAL_PT_LOG2 = 5,
|
||||
NUM_INITIAL_PT = 1UL << NUM_INITIAL_PT_LOG2,
|
||||
NUM_INITIAL_PT_RESERVED = 2 * NUM_INITIAL_PT,
|
||||
NUM_INITIAL_VCPU_PT_LOG2 = 8,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -64,4 +64,27 @@ inline void request_signal_sm_cap(Genode::Native_capability const &cap,
|
||||
Genode::addr_t sel) {
|
||||
request_event_portal(cap, sel, ~0UL - 1, 0); }
|
||||
|
||||
|
||||
inline void delegate_vcpu_portals(Genode::Native_capability const &cap,
|
||||
Genode::addr_t sel)
|
||||
{
|
||||
using namespace Nova;
|
||||
Utcb *utcb = reinterpret_cast<Utcb *>(Genode::Thread_base::myself()->utcb());
|
||||
|
||||
/* save original receive window */
|
||||
Crd orig_crd = utcb->crd_rcv;
|
||||
|
||||
utcb->crd_rcv = Obj_crd();
|
||||
utcb->set_msg_word(0);
|
||||
uint8_t res = utcb->append_item(Obj_crd(sel, NUM_INITIAL_VCPU_PT_LOG2), 0);
|
||||
(void)res;
|
||||
|
||||
res = call(cap.local_name());
|
||||
|
||||
/* restore original receive window */
|
||||
utcb->crd_rcv = orig_crd;
|
||||
|
||||
if (res)
|
||||
PERR("setting exception portals for vCPU failed %u", res);
|
||||
}
|
||||
#endif /* _NOVA__INCLUDE__UTIL_H_ */
|
||||
|
@ -194,6 +194,12 @@ void Pager_object::_invoke_handler()
|
||||
Pager_object *obj;
|
||||
Utcb *utcb = _check_handler(myself, obj);
|
||||
|
||||
/* if protocol is violated ignore request and close receive window */
|
||||
if (utcb->msg_words() != 2) {
|
||||
utcb->crd_rcv = Obj_crd();
|
||||
reply(myself->stack_top());
|
||||
}
|
||||
|
||||
/* send single portal as reply */
|
||||
addr_t const event = utcb->msg[0];
|
||||
addr_t const logcount = utcb->msg[1];
|
||||
@ -325,8 +331,10 @@ static uint8_t create_portal(addr_t pt, addr_t pd, addr_t ec, Mtd mtd,
|
||||
|
||||
|
||||
Pager_object::Pager_object(unsigned long badge, Affinity::Location location)
|
||||
: Thread_base("pager:", PF_HANDLER_STACK_SIZE),
|
||||
_badge(reinterpret_cast<unsigned long>(_context->name + 6))
|
||||
:
|
||||
Thread_base("pager:", PF_HANDLER_STACK_SIZE),
|
||||
_badge(reinterpret_cast<unsigned long>(_context->name + 6)),
|
||||
_client_exc_vcpu(Native_thread::INVALID_INDEX)
|
||||
{
|
||||
class Create_exception_pt_failed { };
|
||||
uint8_t res;
|
||||
@ -441,6 +449,13 @@ Pager_object::~Pager_object()
|
||||
|
||||
cap_map()->remove(_pt_cleanup, 1, false);
|
||||
cap_map()->remove(exc_pt_sel_client(), NUM_INITIAL_PT_LOG2, false);
|
||||
|
||||
if (_client_exc_vcpu == Native_thread::INVALID_INDEX)
|
||||
return;
|
||||
|
||||
/* revoke vCPU exception portals */
|
||||
revoke(Obj_crd(_client_exc_vcpu, NUM_INITIAL_VCPU_PT_LOG2));
|
||||
cap_map()->remove(_client_exc_vcpu, NUM_INITIAL_VCPU_PT_LOG2, false);
|
||||
}
|
||||
|
||||
|
||||
|
@ -100,38 +100,32 @@ int Platform_thread::start(void *ip, void *sp)
|
||||
return -5;
|
||||
}
|
||||
|
||||
/*
|
||||
* For the first thread of a new PD, use the initial stack pointer for
|
||||
* reporting the thread's UTCB address.
|
||||
*/
|
||||
addr_t pd_utcb = Native_config::context_area_virtual_base() +
|
||||
Native_config::context_area_virtual_size() -
|
||||
get_page_size();
|
||||
|
||||
_sel_exc_base = _pager->exc_pt_sel_client();
|
||||
|
||||
addr_t pd_core_sel = Platform_pd::pd_core_sel();
|
||||
addr_t pd_utcb = 0;
|
||||
_sel_exc_base = is_vcpu() ? _pager->exc_pt_vcpu() : _pager->exc_pt_sel_client();
|
||||
|
||||
addr_t remap_src[] = { _pd->parent_pt_sel() };
|
||||
addr_t remap_dst[] = { PT_SEL_PARENT };
|
||||
addr_t pd_sel;
|
||||
if (!is_vcpu()) {
|
||||
pd_utcb = Native_config::context_area_virtual_base() +
|
||||
Native_config::context_area_virtual_size() - get_page_size();
|
||||
|
||||
Obj_crd initial_pts(_sel_exc_base, NUM_INITIAL_PT_LOG2);
|
||||
addr_t remap_src[] = { _pd->parent_pt_sel() };
|
||||
addr_t remap_dst[] = { PT_SEL_PARENT };
|
||||
|
||||
uint8_t res;
|
||||
|
||||
/* remap exception portals for first thread */
|
||||
for (unsigned i = 0; i < sizeof(remap_dst)/sizeof(remap_dst[0]); i++) {
|
||||
if (map_local((Utcb *)Thread_base::myself()->utcb(),
|
||||
Obj_crd(remap_src[i], 0),
|
||||
Obj_crd(_sel_exc_base + remap_dst[i], 0)))
|
||||
return -6;
|
||||
/* remap exception portals for first thread */
|
||||
for (unsigned i = 0; i < sizeof(remap_dst)/sizeof(remap_dst[0]); i++) {
|
||||
if (map_local((Utcb *)Thread_base::myself()->utcb(),
|
||||
Obj_crd(remap_src[i], 0),
|
||||
Obj_crd(_sel_exc_base + remap_dst[i], 0)))
|
||||
return -6;
|
||||
}
|
||||
}
|
||||
|
||||
pd_sel = cap_map()->insert();
|
||||
addr_t pd_sel = cap_map()->insert();
|
||||
|
||||
/* create task */
|
||||
res = create_pd(pd_sel, pd_core_sel, initial_pts);
|
||||
Obj_crd initial_pts(_sel_exc_base, is_vcpu() ?
|
||||
NUM_INITIAL_VCPU_PT_LOG2 : NUM_INITIAL_PT_LOG2);
|
||||
uint8_t res = create_pd(pd_sel, pd_core_sel, initial_pts);
|
||||
if (res != NOVA_OK) {
|
||||
PERR("create_pd returned %d", res);
|
||||
goto cleanup_pd;
|
||||
@ -238,9 +232,6 @@ Thread_state Platform_thread::state()
|
||||
|
||||
void Platform_thread::state(Thread_state s)
|
||||
{
|
||||
/* not permitted for main thread */
|
||||
if (is_main_thread()) throw Cpu_session::State_access_failed();
|
||||
|
||||
/* you can do it only once */
|
||||
if (_sel_exc_base != Native_thread::INVALID_INDEX)
|
||||
throw Cpu_session::State_access_failed();
|
||||
@ -251,8 +242,16 @@ void Platform_thread::state(Thread_state s)
|
||||
* s.is_vcpu If true it will run as vCPU,
|
||||
* otherwise it will be a thread.
|
||||
*/
|
||||
_sel_exc_base = s.sel_exc_base;
|
||||
if (s.is_vcpu) _features |= VCPU;
|
||||
if (!is_main_thread())
|
||||
_sel_exc_base = s.sel_exc_base;
|
||||
|
||||
if (!s.is_vcpu)
|
||||
return;
|
||||
|
||||
_features |= VCPU;
|
||||
|
||||
if (is_main_thread() && _pager)
|
||||
_pager->prepare_vCPU_portals();
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user