nova: support to run VBox vCPUs within same PD

Issue #2173
This commit is contained in:
Alexander Boettcher
2016-11-24 21:57:33 +01:00
committed by Christian Helmuth
parent 1bea312ba2
commit d3d4381128
17 changed files with 166 additions and 131 deletions

View File

@ -569,7 +569,7 @@ namespace Nova {
struct Item { struct Item {
mword_t crd; mword_t crd;
mword_t hotspot; mword_t hotspot;
bool is_del() { return hotspot & 0x1; } bool is_del() const { return hotspot & 0x1; }
}; };
#ifdef __x86_64__ #ifdef __x86_64__

View File

@ -71,7 +71,7 @@ inline void request_signal_sm_cap(Genode::Native_capability const &cap,
} }
inline void delegate_vcpu_portals(Genode::Native_capability const &cap, inline void translate_remote_pager(Genode::Native_capability const &cap,
Genode::addr_t const sel) Genode::addr_t const sel)
{ {
Genode::Thread * myself = Genode::Thread::myself(); Genode::Thread * myself = Genode::Thread::myself();
@ -84,34 +84,22 @@ inline void delegate_vcpu_portals(Genode::Native_capability const &cap,
Genode::uint8_t res = Nova::NOVA_OK; Genode::uint8_t res = Nova::NOVA_OK;
enum { enum {
TRANSLATE = true, THIS_PD = false, NON_GUEST = false, HOTSPOT = 0, TRANSLATE = true, THIS_PD = false, NON_GUEST = false, HOTSPOT = 0
TRANSFER_ITEMS = 1U << (Nova::NUM_INITIAL_VCPU_PT_LOG2 - 1)
}; };
/* prepare translation items for every portal separately */ /* translate one item */
for (unsigned half = 0; !res && half < 2; half++) { utcb->msg[0] = 0xaffe;
/* translate half of portals - due to size constraints on 64bit */
utcb->msg[0] = half;
utcb->set_msg_word(1); utcb->set_msg_word(1);
/* add one translate item per portal */
for (unsigned i = 0; !res && i < TRANSFER_ITEMS; i++) {
Nova::Obj_crd obj_crd(sel + half * TRANSFER_ITEMS + i, 0);
if (!utcb->append_item(obj_crd, HOTSPOT, THIS_PD, NON_GUEST,
TRANSLATE))
res = 0xff;
}
if (res != Nova::NOVA_OK)
break;
Nova::Obj_crd obj_crd(sel, 0);
if (utcb->append_item(obj_crd, HOTSPOT, THIS_PD, NON_GUEST, TRANSLATE))
/* trigger the translation */ /* trigger the translation */
res = Nova::call(cap.local_name()); res = Nova::call(cap.local_name());
}
/* restore original receive window */ /* restore original receive window */
utcb->crd_rcv = orig_crd; utcb->crd_rcv = orig_crd;
if (res) if (res != Nova::NOVA_OK)
Genode::error("setting exception portals for vCPU failed res=", res); Genode::error("setting exception portals for vCPU failed res=", res);
} }
#endif /* _INCLUDE__NOVA__UTIL_H_ */ #endif /* _INCLUDE__NOVA__UTIL_H_ */

View File

@ -75,7 +75,6 @@ namespace Genode {
addr_t _initial_esp; addr_t _initial_esp;
addr_t _initial_eip; addr_t _initial_eip;
addr_t _client_exc_pt_sel; addr_t _client_exc_pt_sel;
addr_t _client_exc_vcpu;
Lock _state_lock; Lock _state_lock;
@ -121,7 +120,8 @@ namespace Genode {
Affinity::Location const _location; Affinity::Location const _location;
Exception_handlers _exceptions; Exception_handlers _exceptions;
addr_t _pd; addr_t _pd_target;
addr_t _pd_source;
void _copy_state_from_utcb(Nova::Utcb * utcb); void _copy_state_from_utcb(Nova::Utcb * utcb);
void _copy_state_to_utcb(Nova::Utcb * utcb); void _copy_state_to_utcb(Nova::Utcb * utcb);
@ -179,8 +179,15 @@ namespace Genode {
/** /**
* Assign PD selector to PD * Assign PD selector to PD
*/ */
void assign_pd(addr_t pd_sel) { _pd = pd_sel; } void assign_pd(addr_t pd_sel)
addr_t pd_sel() const { return _pd; } {
if (_pd_target == _pd_source)
_pd_source = pd_sel;
_pd_target = pd_sel;
}
addr_t pd_sel() const { return _pd_target; }
addr_t pd_source() const { return _pd_source; }
void exception(uint8_t exit_id); void exception(uint8_t exit_id);
@ -188,7 +195,6 @@ namespace Genode {
* Return base of initial portal window * Return base of initial portal window
*/ */
addr_t exc_pt_sel_client() { return _client_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 * Set initial stack pointer used by the startup handler
@ -324,14 +330,6 @@ namespace Genode {
*/ */
void cleanup_call(); 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);
}
/** /**
* Portal called by thread that causes a out of memory in kernel. * Portal called by thread that causes a out of memory in kernel.
*/ */
@ -412,6 +410,7 @@ namespace Genode {
* constructor. * constructor.
*/ */
void ep(Pager_entrypoint *ep) { _ep = ep; } void ep(Pager_entrypoint *ep) { _ep = ep; }
Pager_entrypoint *ep() { return _ep; }
/** /**
* Thread interface * Thread interface

View File

@ -301,32 +301,20 @@ void Pager_object::_invoke_handler(addr_t pager_obj)
addr_t const event = utcb->msg[0]; addr_t const event = utcb->msg[0];
addr_t const logcount = utcb->msg[1]; addr_t const logcount = utcb->msg[1];
/* check for translated vCPU portals */ /* check for translated pager portals - required for vCPU in remote PDs */
unsigned const items_count = 1U << (Nova::NUM_INITIAL_VCPU_PT_LOG2 - 1); if (utcb->msg_items() == 1 && utcb->msg_words() == 1 && event == 0xaffe) {
if ((obj->_client_exc_vcpu != Native_thread::INVALID_INDEX) && Nova::Utcb::Item const * const item = utcb->get_item(0);
(utcb->msg_items() == items_count) && Nova::Crd const cap(item->crd);
(utcb->msg_words() == 1 && (event == 0UL || event == 1UL))) {
/* check all translated item and remap if valid */
for (unsigned i = 0; i < items_count; i++) {
Nova::Utcb::Item * item = utcb->get_item(i);
if (!item) /* valid item which got translated ? */
break; if (!cap.is_null() && !item->is_del()) {
using Pool = Object_pool<Pager_object>;
Nova::Crd cap(item->crd); pager_threads[0]->ep()->Pool::apply(cap.base(),
[&] (Pager_object *source) {
if (cap.is_null() || item->is_del()) /* set source PD (VMM) where vCPU exception portals are */
continue; obj->_pd_source = source->pd_sel();
});
/**
* Remap portal to dense packed region - required for vCPU running
* in separate PD (non-colocated case)
*/
Obj_crd snd(cap.base(), 0);
Obj_crd rcv(obj->_client_exc_vcpu + event * items_count + i, 0);
if (map_local(utcb, snd, rcv))
warning("could not remap vCPU portal ", Hex(i));
} }
} }
@ -591,10 +579,11 @@ Pager_object::Pager_object(Cpu_session_capability cpu_session_cap,
_badge(badge), _badge(badge),
_selectors(cap_map()->insert(2)), _selectors(cap_map()->insert(2)),
_client_exc_pt_sel(cap_map()->insert(NUM_INITIAL_PT_LOG2)), _client_exc_pt_sel(cap_map()->insert(NUM_INITIAL_PT_LOG2)),
_client_exc_vcpu(Native_thread::INVALID_INDEX),
_cpu_session_cap(cpu_session_cap), _thread_cap(thread_cap), _cpu_session_cap(cpu_session_cap), _thread_cap(thread_cap),
_location(location), _location(location),
_exceptions(this) _exceptions(this),
_pd_target(Native_thread::INVALID_INDEX),
_pd_source(Native_thread::INVALID_INDEX)
{ {
uint8_t res; uint8_t res;
@ -681,15 +670,9 @@ Pager_object::~Pager_object()
revoke(Obj_crd(_selectors, 2)); revoke(Obj_crd(_selectors, 2));
cap_map()->remove(_selectors, 2, false); cap_map()->remove(_selectors, 2, false);
cap_map()->remove(exc_pt_sel_client(), NUM_INITIAL_PT_LOG2, 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);
} }
uint8_t Pager_object::handle_oom(addr_t transfer_from, uint8_t Pager_object::handle_oom(addr_t transfer_from,
char const * src_pd, char const * src_thread, char const * src_pd, char const * src_thread,
enum Pager_object::Policy policy) enum Pager_object::Policy policy)

View File

@ -62,8 +62,17 @@ int Platform_thread::start(void *ip, void *sp)
return -2; return -2;
} }
if (_pager->pd_sel() != Native_thread::INVALID_INDEX) {
error("thread already started");
return -2;
}
Utcb * const utcb = reinterpret_cast<Utcb *>(Thread::myself()->utcb());
addr_t const pts = vcpu() ? NUM_INITIAL_VCPU_PT_LOG2
: NUM_INITIAL_PT_LOG2;
addr_t const pt_oom = _pager->get_oom_portal(); addr_t const pt_oom = _pager->get_oom_portal();
if (!pt_oom || map_local((Utcb *)Thread::myself()->utcb(), if (!pt_oom || map_local(utcb,
Obj_crd(pt_oom, 0), Obj_crd(_sel_pt_oom(), 0))) { Obj_crd(pt_oom, 0), Obj_crd(_sel_pt_oom(), 0))) {
error("setup of out-of-memory notification portal - failed"); error("setup of out-of-memory notification portal - failed");
return -8; return -8;
@ -71,7 +80,7 @@ int Platform_thread::start(void *ip, void *sp)
if (!main_thread()) { if (!main_thread()) {
addr_t const initial_sp = reinterpret_cast<addr_t>(sp); addr_t const initial_sp = reinterpret_cast<addr_t>(sp);
addr_t const utcb = vcpu() ? 0 : round_page(initial_sp); addr_t const utcb_addr = vcpu() ? 0 : round_page(initial_sp);
if (_sel_exc_base == Native_thread::INVALID_INDEX) { if (_sel_exc_base == Native_thread::INVALID_INDEX) {
error("exception base not specified"); error("exception base not specified");
@ -80,11 +89,27 @@ int Platform_thread::start(void *ip, void *sp)
_pager->assign_pd(_pd->pd_sel()); _pager->assign_pd(_pd->pd_sel());
/* second++ vcpu case which runs in other pd than VMM */
if (vcpu() && _pager->pd_sel() != _pager->pd_source()) {
Obj_crd const source_initial_caps(_sel_exc_base, pts);
Obj_crd const target_initial_caps(_sel_exc_base, pts);
/* asynchronously map capabilities */
utcb->set_msg_word(0);
if (!utcb->append_item(source_initial_caps, 0))
return -3;
uint8_t res = Nova::delegate(_pager->pd_source(), _pager->pd_sel(),
target_initial_caps);
if (res != NOVA_OK)
return -3;
}
uint8_t res; uint8_t res;
do { do {
unsigned const kernel_cpu_id = platform_specific()->kernel_cpu_id(_location.xpos()); unsigned const kernel_cpu_id = platform_specific()->kernel_cpu_id(_location.xpos());
res = create_ec(_sel_ec(), _pd->pd_sel(), kernel_cpu_id, res = create_ec(_sel_ec(), _pd->pd_sel(), kernel_cpu_id,
utcb, initial_sp, _sel_exc_base, !worker()); utcb_addr, initial_sp, _sel_exc_base, !worker());
if (res == Nova::NOVA_PD_OOM && Nova::NOVA_OK != _pager->handle_oom()) { if (res == Nova::NOVA_PD_OOM && Nova::NOVA_OK != _pager->handle_oom()) {
_pager->assign_pd(Native_thread::INVALID_INDEX); _pager->assign_pd(Native_thread::INVALID_INDEX);
error("creation of new thread failed ", res); error("creation of new thread failed ", res);
@ -104,24 +129,31 @@ int Platform_thread::start(void *ip, void *sp)
return 0; return 0;
} }
if (_sel_exc_base != Native_thread::INVALID_INDEX) { if (!vcpu() && _sel_exc_base != Native_thread::INVALID_INDEX) {
error("thread already started"); error("thread already started");
return -5; return -5;
} }
addr_t pd_utcb = 0; addr_t pd_utcb = 0;
_sel_exc_base = vcpu() ? _pager->exc_pt_vcpu() : _pager->exc_pt_sel_client(); Obj_crd initial_pts;
if (!vcpu()) { if (!vcpu()) {
_sel_exc_base = _pager->exc_pt_sel_client();
pd_utcb = stack_area_virtual_base() + stack_virtual_size() - get_page_size(); pd_utcb = stack_area_virtual_base() + stack_virtual_size() - get_page_size();
addr_t const rights = Obj_crd::RIGHT_EC_RECALL |
Obj_crd::RIGHT_PT_CTRL | Obj_crd::RIGHT_PT_CALL |
Obj_crd::RIGHT_SM_UP | Obj_crd::RIGHT_SM_DOWN;
initial_pts = Obj_crd(_sel_exc_base, pts, rights);
addr_t remap_src[] = { _pd->parent_pt_sel(), addr_t remap_src[] = { _pd->parent_pt_sel(),
(unsigned long)_pager->Object_pool<Pager_object>::Entry::cap().local_name() }; (unsigned long)_pager->Object_pool<Pager_object>::Entry::cap().local_name() };
addr_t remap_dst[] = { PT_SEL_PARENT, PT_SEL_MAIN_PAGER }; addr_t remap_dst[] = { PT_SEL_PARENT, PT_SEL_MAIN_PAGER };
/* remap exception portals for first thread */ /* remap exception portals for first thread */
for (unsigned i = 0; i < sizeof(remap_dst)/sizeof(remap_dst[0]); i++) { for (unsigned i = 0; i < sizeof(remap_dst)/sizeof(remap_dst[0]); i++) {
if (map_local((Utcb *)Thread::myself()->utcb(), if (map_local(utcb,
Obj_crd(remap_src[i], 0), Obj_crd(remap_src[i], 0),
Obj_crd(_sel_exc_base + remap_dst[i], 0))) Obj_crd(_sel_exc_base + remap_dst[i], 0)))
return -6; return -6;
@ -130,16 +162,12 @@ int Platform_thread::start(void *ip, void *sp)
/* create task */ /* create task */
addr_t const pd_sel = cap_map()->insert(); addr_t const pd_sel = cap_map()->insert();
addr_t const rights = Obj_crd::RIGHT_EC_RECALL |
Obj_crd::RIGHT_PT_CTRL | Obj_crd::RIGHT_PT_CALL |
Obj_crd::RIGHT_SM_UP | Obj_crd::RIGHT_SM_DOWN;
unsigned pts = vcpu() ? NUM_INITIAL_VCPU_PT_LOG2 : NUM_INITIAL_PT_LOG2;
enum { KEEP_FREE_PAGES_NOT_AVAILABLE_FOR_UPGRADE = 2, UPPER_LIMIT_PAGES = 32 }; enum { KEEP_FREE_PAGES_NOT_AVAILABLE_FOR_UPGRADE = 2, UPPER_LIMIT_PAGES = 32 };
Obj_crd initial_pts(_sel_exc_base, pts, rights);
uint8_t res = create_pd(pd_sel, platform_specific()->core_pd_sel(), uint8_t res = create_pd(pd_sel, platform_specific()->core_pd_sel(),
initial_pts, initial_pts,
KEEP_FREE_PAGES_NOT_AVAILABLE_FOR_UPGRADE, UPPER_LIMIT_PAGES); KEEP_FREE_PAGES_NOT_AVAILABLE_FOR_UPGRADE,
UPPER_LIMIT_PAGES);
if (res != NOVA_OK) { if (res != NOVA_OK) {
error("create_pd returned ", res); error("create_pd returned ", res);
goto cleanup_pd; goto cleanup_pd;
@ -148,7 +176,8 @@ int Platform_thread::start(void *ip, void *sp)
/* create first thread in task */ /* create first thread in task */
enum { THREAD_GLOBAL = true }; enum { THREAD_GLOBAL = true };
res = create_ec(_sel_ec(), pd_sel, res = create_ec(_sel_ec(), pd_sel,
platform_specific()->kernel_cpu_id(_location.xpos()), pd_utcb, 0, 0, platform_specific()->kernel_cpu_id(_location.xpos()),
pd_utcb, 0, 0,
THREAD_GLOBAL); THREAD_GLOBAL);
if (res != NOVA_OK) { if (res != NOVA_OK) {
error("create_ec returned ", res); error("create_ec returned ", res);
@ -165,11 +194,25 @@ int Platform_thread::start(void *ip, void *sp)
_pager->initial_esp((addr_t)sp); _pager->initial_esp((addr_t)sp);
_pager->assign_pd(pd_sel); _pager->assign_pd(pd_sel);
if (vcpu() && _pager->pd_sel() != _pager->pd_source()) {
Obj_crd const source_initial_caps(_sel_exc_base, pts);
Obj_crd const target_initial_caps(0, pts);
/* asynchronously map capabilities */
utcb->set_msg_word(0);
res = utcb->append_item(source_initial_caps, 0);
if (res)
res = Nova::delegate(_pager->pd_source(), _pager->pd_sel(),
target_initial_caps);
}
if (res == NOVA_OK) {
do { do {
/* let the thread run */ /* let the thread run */
res = create_sc(_sel_sc(), pd_sel, _sel_ec(), res = create_sc(_sel_sc(), pd_sel, _sel_ec(),
Qpd(Qpd::DEFAULT_QUANTUM, _priority)); Qpd(Qpd::DEFAULT_QUANTUM, _priority));
} while (res == Nova::NOVA_PD_OOM && Nova::NOVA_OK == _pager->handle_oom()); } while (res == Nova::NOVA_PD_OOM && Nova::NOVA_OK == _pager->handle_oom());
}
if (res != NOVA_OK) { if (res != NOVA_OK) {
/* /*
@ -184,7 +227,8 @@ int Platform_thread::start(void *ip, void *sp)
error("create_sc returned ", res); error("create_sc returned ", res);
goto cleanup_ec; goto cleanup_ec;
} else }
_features |= SC_CREATED; _features |= SC_CREATED;
return 0; return 0;
@ -262,7 +306,7 @@ void Platform_thread::state(Thread_state s)
* s.is_vcpu If true it will run as vCPU, * s.is_vcpu If true it will run as vCPU,
* otherwise it will be a thread. * otherwise it will be a thread.
*/ */
if (!main_thread()) if (!main_thread() || s.vcpu)
_sel_exc_base = s.sel_exc_base; _sel_exc_base = s.sel_exc_base;
if (!s.global_thread) if (!s.global_thread)
@ -273,9 +317,6 @@ void Platform_thread::state(Thread_state s)
_features |= VCPU; _features |= VCPU;
if (main_thread() && _pager)
_pager->prepare_vCPU_portals();
} else { } else {
if (!_pager) throw Cpu_thread::State_access_failed(); if (!_pager) throw Cpu_thread::State_access_failed();

View File

@ -48,7 +48,7 @@ class Vmm::Vcpu_other_pd : public Vmm::Vcpu_thread
{ {
private: private:
Genode::Pd_connection _pd_session; Genode::Capability<Genode::Pd_session> _pd_cap;
Genode::Affinity::Location _location; Genode::Affinity::Location _location;
Genode::Cpu_session *_cpu_session; Genode::Cpu_session *_cpu_session;
@ -58,9 +58,10 @@ class Vmm::Vcpu_other_pd : public Vmm::Vcpu_thread
Vcpu_other_pd(Cpu_session * cpu_session, Vcpu_other_pd(Cpu_session * cpu_session,
Genode::Affinity::Location location, Genode::Affinity::Location location,
Genode::Capability<Genode::Pd_session> pd_cap,
Genode::size_t = 0 /* stack_size */) Genode::size_t = 0 /* stack_size */)
: :
_pd_session("VM"), _location(location), _cpu_session(cpu_session), _pd_cap(pd_cap), _location(location), _cpu_session(cpu_session),
_exc_pt_sel(Genode::cap_map()->insert(Nova::NUM_INITIAL_VCPU_PT_LOG2)) _exc_pt_sel(Genode::cap_map()->insert(Nova::NUM_INITIAL_VCPU_PT_LOG2))
{ } { }
@ -69,12 +70,12 @@ class Vmm::Vcpu_other_pd : public Vmm::Vcpu_thread
using namespace Genode; using namespace Genode;
Thread_capability vcpu_vm = Thread_capability vcpu_vm =
_cpu_session->create_thread(_pd_session, "vCPU", _cpu_session->create_thread(_pd_cap, "vCPU",
_location, Cpu_session::Weight()); _location, Cpu_session::Weight());
/* tell parent that this will be a vCPU */ /* tell parent that this will be a vCPU */
Thread_state state; Thread_state state;
state.sel_exc_base = Native_thread::INVALID_INDEX; state.sel_exc_base = _exc_pt_sel;
state.vcpu = true; state.vcpu = true;
Cpu_thread_client cpu_thread(vcpu_vm); Cpu_thread_client cpu_thread(vcpu_vm);
@ -88,10 +89,11 @@ class Vmm::Vcpu_other_pd : public Vmm::Vcpu_thread
Native_capability pager_cap = native_cpu.pager_cap(vcpu_vm); Native_capability pager_cap = native_cpu.pager_cap(vcpu_vm);
/* /*
* Delegate parent the vCPU exception portals required during PD * Translate pager cap of current executing thread, which is used
* creation. * to lookup current PD - required during PD creation.
*/ */
delegate_vcpu_portals(pager_cap, exc_base()); translate_remote_pager(pager_cap,
Thread::myself()->native_thread().ec_sel + 1);
/* start vCPU in separate PD */ /* start vCPU in separate PD */
cpu_thread.start(0, 0); cpu_thread.start(0, 0);
@ -101,6 +103,9 @@ class Vmm::Vcpu_other_pd : public Vmm::Vcpu_thread
* SM cap - see Vcpu_dispatcher->sel_sm_ec description * SM cap - see Vcpu_dispatcher->sel_sm_ec description
*/ */
request_native_ec_cap(pager_cap, sel_ec); request_native_ec_cap(pager_cap, sel_ec);
/* request creation of SC to let vCPU run */
cpu_thread.resume();
} }
Genode::addr_t exc_base() { return _exc_pt_sel; } Genode::addr_t exc_base() { return _exc_pt_sel; }
@ -115,6 +120,7 @@ class Vmm::Vcpu_same_pd : public Vmm::Vcpu_thread, Genode::Thread
Vcpu_same_pd(Cpu_session * cpu_session, Vcpu_same_pd(Cpu_session * cpu_session,
Genode::Affinity::Location location, Genode::Affinity::Location location,
Genode::Capability<Genode::Pd_session>,
Genode::size_t stack_size) Genode::size_t stack_size)
: :
Thread(WEIGHT, "vCPU", stack_size, Type::NORMAL, cpu_session, location) Thread(WEIGHT, "vCPU", stack_size, Type::NORMAL, cpu_session, location)

View File

@ -34,9 +34,9 @@ append qemu_args " -m 512 "
append qemu_args " -cpu phenom " append qemu_args " -cpu phenom "
append qemu_args " -nographic " append qemu_args " -nographic "
run_genode_until {.*VMM: vcpu_s_1 _svm_startup called.*\n} 30 run_genode_until {.*VMM: vcpu_s_1 _vcpu_startup called.*\n} 30
run_genode_until {.*VMM: vcpu_s_2 _svm_startup called.*\n} 10 [output_spawn_id] run_genode_until {.*VMM: vcpu_s_2 _vcpu_startup called.*\n} 10 [output_spawn_id]
run_genode_until {.*VMM: vcpu_o_1 _svm_startup called.*\n} 10 [output_spawn_id] run_genode_until {.*VMM: vcpu_o_1 _vcpu_startup called.*\n} 10 [output_spawn_id]
run_genode_until {.*VMM: vcpu_o_2 _svm_startup called.*\n} 10 [output_spawn_id] run_genode_until {.*VMM: vcpu_o_2 _vcpu_startup called.*\n} 10 [output_spawn_id]
puts "Test succeeded" puts "Test succeeded"

View File

@ -862,6 +862,7 @@ class Machine : public StaticReceiver<Machine>
Guest_memory &_guest_memory; Guest_memory &_guest_memory;
Boot_module_provider &_boot_modules; Boot_module_provider &_boot_modules;
Alarm_thread *_alarm_thread; Alarm_thread *_alarm_thread;
Genode::Pd_connection *_pd_vcpus = nullptr;
bool _alloc_fb_mem; /* For detecting FB alloc message */ bool _alloc_fb_mem; /* For detecting FB alloc message */
bool _colocate_vm_vmm; bool _colocate_vm_vmm;
@ -949,9 +950,13 @@ class Machine : public StaticReceiver<Machine>
Vmm::Vcpu_thread * vcpu_thread; Vmm::Vcpu_thread * vcpu_thread;
if (_colocate_vm_vmm) if (_colocate_vm_vmm)
vcpu_thread = new Vmm::Vcpu_same_pd(cpu_session, location, Vcpu_dispatcher::STACK_SIZE); vcpu_thread = new Vmm::Vcpu_same_pd(cpu_session, location, _env.pd_session_cap(), Vcpu_dispatcher::STACK_SIZE);
else else {
vcpu_thread = new Vmm::Vcpu_other_pd(cpu_session, location); if (!_pd_vcpus)
_pd_vcpus = new Genode::Pd_connection("VM");
vcpu_thread = new Vmm::Vcpu_other_pd(cpu_session, location, *_pd_vcpus);
}
Vcpu_dispatcher *vcpu_dispatcher = Vcpu_dispatcher *vcpu_dispatcher =
new Vcpu_dispatcher(_motherboard_lock, new Vcpu_dispatcher(_motherboard_lock,

View File

@ -46,21 +46,23 @@ class Vcpu_dispatcher : public Vmm::Vcpu_dispatcher<Genode::Thread>
** Virtualization event handlers ** ** Virtualization event handlers **
***********************************/ ***********************************/
void _svm_startup() void _vcpu_startup()
{ {
Vmm::log(name(), " _svm_startup called"); Vmm::log(name(), " ", __func__, " called");
} }
public: public:
enum Type { SVM, VTX }; enum Type { SVM, VTX };
Vcpu_dispatcher(Genode::Env &env, Type type, char const * name) Vcpu_dispatcher(Genode::Env &env, Type type, char const * name,
Genode::Capability<Genode::Pd_session> pd_cap)
: :
Vmm::Vcpu_dispatcher<Genode::Thread>(env, STACK_SIZE, &env.cpu(), Vmm::Vcpu_dispatcher<Genode::Thread>(env, STACK_SIZE, &env.cpu(),
Genode::Affinity::Location(), Genode::Affinity::Location(),
name), name),
_vcpu_thread(&env.cpu(), Genode::Affinity::Location(), STACK_SIZE) _vcpu_thread(&env.cpu(), Genode::Affinity::Location(), pd_cap,
STACK_SIZE)
{ {
using namespace Nova; using namespace Nova;
@ -73,7 +75,7 @@ class Vcpu_dispatcher : public Vmm::Vcpu_dispatcher<Genode::Thread>
/* register virtualization event handlers */ /* register virtualization event handlers */
if (type == SVM) { if (type == SVM) {
_register_handler<0xfe, &This::_svm_startup> _register_handler<0xfe, &This::_vcpu_startup>
(exc_base, mtd_all); (exc_base, mtd_all);
} }
@ -87,11 +89,12 @@ void Component::construct(Genode::Env &env)
{ {
typedef Vcpu_dispatcher<Vmm::Vcpu_same_pd> Vcpu_s; typedef Vcpu_dispatcher<Vmm::Vcpu_same_pd> Vcpu_s;
static Vcpu_s vcpu_s_1(env, Vcpu_s::SVM, "vcpu_s_1"); static Vcpu_s vcpu_s_1(env, Vcpu_s::SVM, "vcpu_s_1", env.pd_session_cap());
static Vcpu_s vcpu_s_2(env, Vcpu_s::SVM, "vcpu_s_2"); static Vcpu_s vcpu_s_2(env, Vcpu_s::SVM, "vcpu_s_2", env.pd_session_cap());
typedef Vcpu_dispatcher<Vmm::Vcpu_other_pd> Vcpu_o; typedef Vcpu_dispatcher<Vmm::Vcpu_other_pd> Vcpu_o;
static Vcpu_o vcpu_o_1(env, Vcpu_o::SVM, "vcpu_o_1"); static Genode::Pd_connection remote_pd("VM");
static Vcpu_o vcpu_o_2(env, Vcpu_o::SVM, "vcpu_o_2"); static Vcpu_o vcpu_o_1(env, Vcpu_o::SVM, "vcpu_o_1", remote_pd);
static Vcpu_o vcpu_o_2(env, Vcpu_o::SVM, "vcpu_o_2", remote_pd);
} }

View File

@ -299,19 +299,21 @@ bool create_emt_vcpu(pthread_t * pthread, size_t stack,
if (!hip->has_feature_vmx() && !hip->has_feature_svm()) if (!hip->has_feature_vmx() && !hip->has_feature_svm())
return false; return false;
static Genode::Pd_connection pd_vcpus("VM");
Vcpu_handler *vcpu_handler = 0; Vcpu_handler *vcpu_handler = 0;
if (hip->has_feature_vmx()) if (hip->has_feature_vmx())
vcpu_handler = new (0x10) Vcpu_handler_vmx(genode_env(), vcpu_handler = new (0x10) Vcpu_handler_vmx(genode_env(),
stack, attr, start_routine, stack, attr, start_routine,
arg, cpu_session, location, arg, cpu_session, location,
cpu_id, name); cpu_id, name, pd_vcpus);
if (hip->has_feature_svm()) if (hip->has_feature_svm())
vcpu_handler = new (0x10) Vcpu_handler_svm(genode_env(), vcpu_handler = new (0x10) Vcpu_handler_svm(genode_env(),
stack, attr, start_routine, stack, attr, start_routine,
arg, cpu_session, location, arg, cpu_session, location,
cpu_id, name); cpu_id, name, pd_vcpus);
Assert(!(reinterpret_cast<unsigned long>(vcpu_handler) & 0xf)); Assert(!(reinterpret_cast<unsigned long>(vcpu_handler) & 0xf));

View File

@ -762,12 +762,13 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher<pthread>,
void *(*start_routine) (void *), void *arg, void *(*start_routine) (void *), void *arg,
Genode::Cpu_session * cpu_session, Genode::Cpu_session * cpu_session,
Genode::Affinity::Location location, Genode::Affinity::Location location,
unsigned int cpu_id, const char * name) unsigned int cpu_id, const char * name,
Genode::Pd_session_capability pd_vcpu)
: :
Vmm::Vcpu_dispatcher<pthread>(env, stack_size, cpu_session, location, Vmm::Vcpu_dispatcher<pthread>(env, stack_size, cpu_session, location,
attr ? *attr : 0, start_routine, arg, attr ? *attr : 0, start_routine, arg,
name), name),
_vcpu(cpu_session, location), _vcpu(cpu_session, location, pd_vcpu),
_ec_sel(Genode::cap_map()->insert()), _ec_sel(Genode::cap_map()->insert()),
_irq_win(false), _irq_win(false),
_cpu_id(cpu_id) _cpu_id(cpu_id)

View File

@ -88,10 +88,11 @@ class Vcpu_handler_svm : public Vcpu_handler
void *(*start_routine) (void *), void *arg, void *(*start_routine) (void *), void *arg,
Genode::Cpu_session * cpu_session, Genode::Cpu_session * cpu_session,
Genode::Affinity::Location location, Genode::Affinity::Location location,
unsigned int cpu_id, const char * name) unsigned int cpu_id, const char * name,
Genode::Pd_session_capability pd_vcpu)
: :
Vcpu_handler(env, stack_size, attr, start_routine, arg, cpu_session, Vcpu_handler(env, stack_size, attr, start_routine, arg, cpu_session,
location, cpu_id, name) location, cpu_id, name, pd_vcpu)
{ {
using namespace Nova; using namespace Nova;

View File

@ -162,10 +162,11 @@ class Vcpu_handler_vmx : public Vcpu_handler
void *(*start_routine) (void *), void *arg, void *(*start_routine) (void *), void *arg,
Genode::Cpu_session * cpu_session, Genode::Cpu_session * cpu_session,
Genode::Affinity::Location location, Genode::Affinity::Location location,
unsigned int cpu_id, const char * name) unsigned int cpu_id, const char * name,
Genode::Pd_session_capability pd_vcpu)
: :
Vcpu_handler(env, stack_size, attr, start_routine, arg, cpu_session, Vcpu_handler(env, stack_size, attr, start_routine, arg, cpu_session,
location, cpu_id, name) location, cpu_id, name, pd_vcpu)
{ {
using namespace Nova; using namespace Nova;

View File

@ -560,19 +560,21 @@ bool create_emt_vcpu(pthread_t * pthread, ::size_t stack,
if (!hip->has_feature_vmx() && !hip->has_feature_svm()) if (!hip->has_feature_vmx() && !hip->has_feature_svm())
return false; return false;
static Genode::Pd_connection pd_vcpus("VM");
Vcpu_handler *vcpu_handler = 0; Vcpu_handler *vcpu_handler = 0;
if (hip->has_feature_vmx()) if (hip->has_feature_vmx())
vcpu_handler = new (0x10) Vcpu_handler_vmx(genode_env(), vcpu_handler = new (0x10) Vcpu_handler_vmx(genode_env(),
stack, attr, start_routine, stack, attr, start_routine,
arg, cpu_session, location, arg, cpu_session, location,
cpu_id, name); cpu_id, name, pd_vcpus);
if (hip->has_feature_svm()) if (hip->has_feature_svm())
vcpu_handler = new (0x10) Vcpu_handler_svm(genode_env(), vcpu_handler = new (0x10) Vcpu_handler_svm(genode_env(),
stack, attr, start_routine, stack, attr, start_routine,
arg, cpu_session, location, arg, cpu_session, location,
cpu_id, name); cpu_id, name, pd_vcpus);
Assert(!(reinterpret_cast<unsigned long>(vcpu_handler) & 0xf)); Assert(!(reinterpret_cast<unsigned long>(vcpu_handler) & 0xf));

View File

@ -765,12 +765,13 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher<pthread>,
void *(*start_routine) (void *), void *arg, void *(*start_routine) (void *), void *arg,
Genode::Cpu_session * cpu_session, Genode::Cpu_session * cpu_session,
Genode::Affinity::Location location, Genode::Affinity::Location location,
unsigned int cpu_id, const char * name) unsigned int cpu_id, const char * name,
Genode::Pd_session_capability pd_vcpu)
: :
Vmm::Vcpu_dispatcher<pthread>(env, stack_size, cpu_session, location, Vmm::Vcpu_dispatcher<pthread>(env, stack_size, cpu_session, location,
attr ? *attr : 0, start_routine, arg, attr ? *attr : 0, start_routine, arg,
name), name),
_vcpu(cpu_session, location), _vcpu(cpu_session, location, pd_vcpu),
_ec_sel(Genode::cap_map()->insert()), _ec_sel(Genode::cap_map()->insert()),
_irq_win(false), _irq_win(false),
_cpu_id(cpu_id) _cpu_id(cpu_id)

View File

@ -88,10 +88,11 @@ class Vcpu_handler_svm : public Vcpu_handler
void *(*start_routine) (void *), void *arg, void *(*start_routine) (void *), void *arg,
Genode::Cpu_session * cpu_session, Genode::Cpu_session * cpu_session,
Genode::Affinity::Location location, Genode::Affinity::Location location,
unsigned int cpu_id, const char * name) unsigned int cpu_id, const char * name,
Genode::Pd_session_capability pd_vcpu)
: :
Vcpu_handler(env, stack_size, attr, start_routine, arg, cpu_session, Vcpu_handler(env, stack_size, attr, start_routine, arg, cpu_session,
location, cpu_id, name) location, cpu_id, name, pd_vcpu)
{ {
using namespace Nova; using namespace Nova;

View File

@ -170,10 +170,11 @@ class Vcpu_handler_vmx : public Vcpu_handler
void *(*start_routine) (void *), void *arg, void *(*start_routine) (void *), void *arg,
Genode::Cpu_session * cpu_session, Genode::Cpu_session * cpu_session,
Genode::Affinity::Location location, Genode::Affinity::Location location,
unsigned int cpu_id, const char * name) unsigned int cpu_id, const char * name,
Genode::Pd_session_capability pd_vcpu)
: :
Vcpu_handler(env, stack_size, attr, start_routine, arg, cpu_session, Vcpu_handler(env, stack_size, attr, start_routine, arg, cpu_session,
location, cpu_id, name) location, cpu_id, name, pd_vcpu)
{ {
using namespace Nova; using namespace Nova;