mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-21 10:01:57 +00:00
parent
1bea312ba2
commit
d3d4381128
@ -569,7 +569,7 @@ namespace Nova {
|
||||
struct Item {
|
||||
mword_t crd;
|
||||
mword_t hotspot;
|
||||
bool is_del() { return hotspot & 0x1; }
|
||||
bool is_del() const { return hotspot & 0x1; }
|
||||
};
|
||||
|
||||
#ifdef __x86_64__
|
||||
|
@ -71,8 +71,8 @@ inline void request_signal_sm_cap(Genode::Native_capability const &cap,
|
||||
}
|
||||
|
||||
|
||||
inline void delegate_vcpu_portals(Genode::Native_capability const &cap,
|
||||
Genode::addr_t const sel)
|
||||
inline void translate_remote_pager(Genode::Native_capability const &cap,
|
||||
Genode::addr_t const sel)
|
||||
{
|
||||
Genode::Thread * myself = Genode::Thread::myself();
|
||||
Nova::Utcb *utcb = reinterpret_cast<Nova::Utcb *>(myself->utcb());
|
||||
@ -84,34 +84,22 @@ inline void delegate_vcpu_portals(Genode::Native_capability const &cap,
|
||||
|
||||
Genode::uint8_t res = Nova::NOVA_OK;
|
||||
enum {
|
||||
TRANSLATE = true, THIS_PD = false, NON_GUEST = false, HOTSPOT = 0,
|
||||
TRANSFER_ITEMS = 1U << (Nova::NUM_INITIAL_VCPU_PT_LOG2 - 1)
|
||||
TRANSLATE = true, THIS_PD = false, NON_GUEST = false, HOTSPOT = 0
|
||||
};
|
||||
|
||||
/* prepare translation items for every portal separately */
|
||||
for (unsigned half = 0; !res && half < 2; half++) {
|
||||
/* translate half of portals - due to size constraints on 64bit */
|
||||
utcb->msg[0] = half;
|
||||
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;
|
||||
/* translate one item */
|
||||
utcb->msg[0] = 0xaffe;
|
||||
utcb->set_msg_word(1);
|
||||
|
||||
Nova::Obj_crd obj_crd(sel, 0);
|
||||
if (utcb->append_item(obj_crd, HOTSPOT, THIS_PD, NON_GUEST, TRANSLATE))
|
||||
/* trigger the translation */
|
||||
res = Nova::call(cap.local_name());
|
||||
}
|
||||
|
||||
/* restore original receive window */
|
||||
utcb->crd_rcv = orig_crd;
|
||||
|
||||
if (res)
|
||||
if (res != Nova::NOVA_OK)
|
||||
Genode::error("setting exception portals for vCPU failed res=", res);
|
||||
}
|
||||
#endif /* _INCLUDE__NOVA__UTIL_H_ */
|
||||
|
@ -75,7 +75,6 @@ namespace Genode {
|
||||
addr_t _initial_esp;
|
||||
addr_t _initial_eip;
|
||||
addr_t _client_exc_pt_sel;
|
||||
addr_t _client_exc_vcpu;
|
||||
|
||||
Lock _state_lock;
|
||||
|
||||
@ -121,7 +120,8 @@ namespace Genode {
|
||||
Affinity::Location const _location;
|
||||
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_to_utcb(Nova::Utcb * utcb);
|
||||
@ -179,8 +179,15 @@ namespace Genode {
|
||||
/**
|
||||
* Assign PD selector to PD
|
||||
*/
|
||||
void assign_pd(addr_t pd_sel) { _pd = pd_sel; }
|
||||
addr_t pd_sel() const { return _pd; }
|
||||
void assign_pd(addr_t pd_sel)
|
||||
{
|
||||
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);
|
||||
|
||||
@ -188,7 +195,6 @@ namespace Genode {
|
||||
* Return base of initial portal window
|
||||
*/
|
||||
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
|
||||
@ -324,14 +330,6 @@ namespace Genode {
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
@ -412,6 +410,7 @@ namespace Genode {
|
||||
* constructor.
|
||||
*/
|
||||
void ep(Pager_entrypoint *ep) { _ep = ep; }
|
||||
Pager_entrypoint *ep() { return _ep; }
|
||||
|
||||
/**
|
||||
* Thread interface
|
||||
|
@ -301,32 +301,20 @@ void Pager_object::_invoke_handler(addr_t pager_obj)
|
||||
addr_t const event = utcb->msg[0];
|
||||
addr_t const logcount = utcb->msg[1];
|
||||
|
||||
/* check for translated vCPU portals */
|
||||
unsigned const items_count = 1U << (Nova::NUM_INITIAL_VCPU_PT_LOG2 - 1);
|
||||
/* check for translated pager portals - required for vCPU in remote PDs */
|
||||
if (utcb->msg_items() == 1 && utcb->msg_words() == 1 && event == 0xaffe) {
|
||||
|
||||
if ((obj->_client_exc_vcpu != Native_thread::INVALID_INDEX) &&
|
||||
(utcb->msg_items() == items_count) &&
|
||||
(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);
|
||||
Nova::Utcb::Item const * const item = utcb->get_item(0);
|
||||
Nova::Crd const cap(item->crd);
|
||||
|
||||
if (!item)
|
||||
break;
|
||||
|
||||
Nova::Crd cap(item->crd);
|
||||
|
||||
if (cap.is_null() || item->is_del())
|
||||
continue;
|
||||
|
||||
/**
|
||||
* 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));
|
||||
/* valid item which got translated ? */
|
||||
if (!cap.is_null() && !item->is_del()) {
|
||||
using Pool = Object_pool<Pager_object>;
|
||||
pager_threads[0]->ep()->Pool::apply(cap.base(),
|
||||
[&] (Pager_object *source) {
|
||||
/* set source PD (VMM) where vCPU exception portals are */
|
||||
obj->_pd_source = source->pd_sel();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -591,10 +579,11 @@ Pager_object::Pager_object(Cpu_session_capability cpu_session_cap,
|
||||
_badge(badge),
|
||||
_selectors(cap_map()->insert(2)),
|
||||
_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),
|
||||
_location(location),
|
||||
_exceptions(this)
|
||||
_exceptions(this),
|
||||
_pd_target(Native_thread::INVALID_INDEX),
|
||||
_pd_source(Native_thread::INVALID_INDEX)
|
||||
{
|
||||
uint8_t res;
|
||||
|
||||
@ -681,15 +670,9 @@ Pager_object::~Pager_object()
|
||||
revoke(Obj_crd(_selectors, 2));
|
||||
cap_map()->remove(_selectors, 2, 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,
|
||||
char const * src_pd, char const * src_thread,
|
||||
enum Pager_object::Policy policy)
|
||||
|
@ -62,8 +62,17 @@ int Platform_thread::start(void *ip, void *sp)
|
||||
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();
|
||||
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))) {
|
||||
error("setup of out-of-memory notification portal - failed");
|
||||
return -8;
|
||||
@ -71,7 +80,7 @@ int Platform_thread::start(void *ip, void *sp)
|
||||
|
||||
if (!main_thread()) {
|
||||
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) {
|
||||
error("exception base not specified");
|
||||
@ -80,11 +89,27 @@ int Platform_thread::start(void *ip, void *sp)
|
||||
|
||||
_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;
|
||||
do {
|
||||
unsigned const kernel_cpu_id = platform_specific()->kernel_cpu_id(_location.xpos());
|
||||
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()) {
|
||||
_pager->assign_pd(Native_thread::INVALID_INDEX);
|
||||
error("creation of new thread failed ", res);
|
||||
@ -104,24 +129,31 @@ int Platform_thread::start(void *ip, void *sp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (_sel_exc_base != Native_thread::INVALID_INDEX) {
|
||||
if (!vcpu() && _sel_exc_base != Native_thread::INVALID_INDEX) {
|
||||
error("thread already started");
|
||||
return -5;
|
||||
}
|
||||
|
||||
addr_t pd_utcb = 0;
|
||||
_sel_exc_base = vcpu() ? _pager->exc_pt_vcpu() : _pager->exc_pt_sel_client();
|
||||
Obj_crd initial_pts;
|
||||
|
||||
if (!vcpu()) {
|
||||
_sel_exc_base = _pager->exc_pt_sel_client();
|
||||
|
||||
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(),
|
||||
(unsigned long)_pager->Object_pool<Pager_object>::Entry::cap().local_name() };
|
||||
addr_t remap_dst[] = { PT_SEL_PARENT, PT_SEL_MAIN_PAGER };
|
||||
|
||||
/* remap exception portals for first thread */
|
||||
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(_sel_exc_base + remap_dst[i], 0)))
|
||||
return -6;
|
||||
@ -130,16 +162,12 @@ int Platform_thread::start(void *ip, void *sp)
|
||||
|
||||
/* create task */
|
||||
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 };
|
||||
Obj_crd initial_pts(_sel_exc_base, pts, rights);
|
||||
uint8_t res = create_pd(pd_sel, platform_specific()->core_pd_sel(),
|
||||
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) {
|
||||
error("create_pd returned ", res);
|
||||
goto cleanup_pd;
|
||||
@ -148,7 +176,8 @@ int Platform_thread::start(void *ip, void *sp)
|
||||
/* create first thread in task */
|
||||
enum { THREAD_GLOBAL = true };
|
||||
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);
|
||||
if (res != NOVA_OK) {
|
||||
error("create_ec returned ", res);
|
||||
@ -165,11 +194,25 @@ int Platform_thread::start(void *ip, void *sp)
|
||||
_pager->initial_esp((addr_t)sp);
|
||||
_pager->assign_pd(pd_sel);
|
||||
|
||||
do {
|
||||
/* let the thread run */
|
||||
res = create_sc(_sel_sc(), pd_sel, _sel_ec(),
|
||||
Qpd(Qpd::DEFAULT_QUANTUM, _priority));
|
||||
} while (res == Nova::NOVA_PD_OOM && Nova::NOVA_OK == _pager->handle_oom());
|
||||
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 {
|
||||
/* let the thread run */
|
||||
res = create_sc(_sel_sc(), pd_sel, _sel_ec(),
|
||||
Qpd(Qpd::DEFAULT_QUANTUM, _priority));
|
||||
} while (res == Nova::NOVA_PD_OOM && Nova::NOVA_OK == _pager->handle_oom());
|
||||
}
|
||||
|
||||
if (res != NOVA_OK) {
|
||||
/*
|
||||
@ -184,8 +227,9 @@ int Platform_thread::start(void *ip, void *sp)
|
||||
|
||||
error("create_sc returned ", res);
|
||||
goto cleanup_ec;
|
||||
} else
|
||||
_features |= SC_CREATED;
|
||||
}
|
||||
|
||||
_features |= SC_CREATED;
|
||||
|
||||
return 0;
|
||||
|
||||
@ -262,7 +306,7 @@ void Platform_thread::state(Thread_state s)
|
||||
* s.is_vcpu If true it will run as vCPU,
|
||||
* otherwise it will be a thread.
|
||||
*/
|
||||
if (!main_thread())
|
||||
if (!main_thread() || s.vcpu)
|
||||
_sel_exc_base = s.sel_exc_base;
|
||||
|
||||
if (!s.global_thread)
|
||||
@ -273,9 +317,6 @@ void Platform_thread::state(Thread_state s)
|
||||
|
||||
_features |= VCPU;
|
||||
|
||||
if (main_thread() && _pager)
|
||||
_pager->prepare_vCPU_portals();
|
||||
|
||||
} else {
|
||||
|
||||
if (!_pager) throw Cpu_thread::State_access_failed();
|
||||
|
@ -48,7 +48,7 @@ class Vmm::Vcpu_other_pd : public Vmm::Vcpu_thread
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::Pd_connection _pd_session;
|
||||
Genode::Capability<Genode::Pd_session> _pd_cap;
|
||||
Genode::Affinity::Location _location;
|
||||
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,
|
||||
Genode::Affinity::Location location,
|
||||
Genode::Capability<Genode::Pd_session> pd_cap,
|
||||
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))
|
||||
{ }
|
||||
|
||||
@ -69,12 +70,12 @@ class Vmm::Vcpu_other_pd : public Vmm::Vcpu_thread
|
||||
using namespace Genode;
|
||||
|
||||
Thread_capability vcpu_vm =
|
||||
_cpu_session->create_thread(_pd_session, "vCPU",
|
||||
_cpu_session->create_thread(_pd_cap, "vCPU",
|
||||
_location, Cpu_session::Weight());
|
||||
|
||||
/* tell parent that this will be a vCPU */
|
||||
Thread_state state;
|
||||
state.sel_exc_base = Native_thread::INVALID_INDEX;
|
||||
state.sel_exc_base = _exc_pt_sel;
|
||||
state.vcpu = true;
|
||||
|
||||
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);
|
||||
|
||||
/*
|
||||
* Delegate parent the vCPU exception portals required during PD
|
||||
* creation.
|
||||
* Translate pager cap of current executing thread, which is used
|
||||
* 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 */
|
||||
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
|
||||
*/
|
||||
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; }
|
||||
@ -115,6 +120,7 @@ class Vmm::Vcpu_same_pd : public Vmm::Vcpu_thread, Genode::Thread
|
||||
|
||||
Vcpu_same_pd(Cpu_session * cpu_session,
|
||||
Genode::Affinity::Location location,
|
||||
Genode::Capability<Genode::Pd_session>,
|
||||
Genode::size_t stack_size)
|
||||
:
|
||||
Thread(WEIGHT, "vCPU", stack_size, Type::NORMAL, cpu_session, location)
|
||||
|
@ -34,9 +34,9 @@ append qemu_args " -m 512 "
|
||||
append qemu_args " -cpu phenom "
|
||||
append qemu_args " -nographic "
|
||||
|
||||
run_genode_until {.*VMM: vcpu_s_1 _svm_startup called.*\n} 30
|
||||
run_genode_until {.*VMM: vcpu_s_2 _svm_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_2 _svm_startup called.*\n} 10 [output_spawn_id]
|
||||
run_genode_until {.*VMM: vcpu_s_1 _vcpu_startup called.*\n} 30
|
||||
run_genode_until {.*VMM: vcpu_s_2 _vcpu_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 _vcpu_startup called.*\n} 10 [output_spawn_id]
|
||||
|
||||
puts "Test succeeded"
|
||||
|
@ -862,6 +862,7 @@ class Machine : public StaticReceiver<Machine>
|
||||
Guest_memory &_guest_memory;
|
||||
Boot_module_provider &_boot_modules;
|
||||
Alarm_thread *_alarm_thread;
|
||||
Genode::Pd_connection *_pd_vcpus = nullptr;
|
||||
|
||||
bool _alloc_fb_mem; /* For detecting FB alloc message */
|
||||
bool _colocate_vm_vmm;
|
||||
@ -949,9 +950,13 @@ class Machine : public StaticReceiver<Machine>
|
||||
|
||||
Vmm::Vcpu_thread * vcpu_thread;
|
||||
if (_colocate_vm_vmm)
|
||||
vcpu_thread = new Vmm::Vcpu_same_pd(cpu_session, location, Vcpu_dispatcher::STACK_SIZE);
|
||||
else
|
||||
vcpu_thread = new Vmm::Vcpu_other_pd(cpu_session, location);
|
||||
vcpu_thread = new Vmm::Vcpu_same_pd(cpu_session, location, _env.pd_session_cap(), Vcpu_dispatcher::STACK_SIZE);
|
||||
else {
|
||||
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 =
|
||||
new Vcpu_dispatcher(_motherboard_lock,
|
||||
|
@ -46,21 +46,23 @@ class Vcpu_dispatcher : public Vmm::Vcpu_dispatcher<Genode::Thread>
|
||||
** Virtualization event handlers **
|
||||
***********************************/
|
||||
|
||||
void _svm_startup()
|
||||
void _vcpu_startup()
|
||||
{
|
||||
Vmm::log(name(), " _svm_startup called");
|
||||
Vmm::log(name(), " ", __func__, " called");
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
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(),
|
||||
Genode::Affinity::Location(),
|
||||
name),
|
||||
_vcpu_thread(&env.cpu(), Genode::Affinity::Location(), STACK_SIZE)
|
||||
_vcpu_thread(&env.cpu(), Genode::Affinity::Location(), pd_cap,
|
||||
STACK_SIZE)
|
||||
{
|
||||
using namespace Nova;
|
||||
|
||||
@ -73,7 +75,7 @@ class Vcpu_dispatcher : public Vmm::Vcpu_dispatcher<Genode::Thread>
|
||||
|
||||
/* register virtualization event handlers */
|
||||
if (type == SVM) {
|
||||
_register_handler<0xfe, &This::_svm_startup>
|
||||
_register_handler<0xfe, &This::_vcpu_startup>
|
||||
(exc_base, mtd_all);
|
||||
}
|
||||
|
||||
@ -87,11 +89,12 @@ void Component::construct(Genode::Env &env)
|
||||
{
|
||||
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_2(env, Vcpu_s::SVM, "vcpu_s_2");
|
||||
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", env.pd_session_cap());
|
||||
|
||||
typedef Vcpu_dispatcher<Vmm::Vcpu_other_pd> Vcpu_o;
|
||||
|
||||
static Vcpu_o vcpu_o_1(env, Vcpu_o::SVM, "vcpu_o_1");
|
||||
static Vcpu_o vcpu_o_2(env, Vcpu_o::SVM, "vcpu_o_2");
|
||||
static Genode::Pd_connection remote_pd("VM");
|
||||
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);
|
||||
}
|
||||
|
@ -299,19 +299,21 @@ bool create_emt_vcpu(pthread_t * pthread, size_t stack,
|
||||
if (!hip->has_feature_vmx() && !hip->has_feature_svm())
|
||||
return false;
|
||||
|
||||
static Genode::Pd_connection pd_vcpus("VM");
|
||||
|
||||
Vcpu_handler *vcpu_handler = 0;
|
||||
|
||||
if (hip->has_feature_vmx())
|
||||
vcpu_handler = new (0x10) Vcpu_handler_vmx(genode_env(),
|
||||
stack, attr, start_routine,
|
||||
arg, cpu_session, location,
|
||||
cpu_id, name);
|
||||
cpu_id, name, pd_vcpus);
|
||||
|
||||
if (hip->has_feature_svm())
|
||||
vcpu_handler = new (0x10) Vcpu_handler_svm(genode_env(),
|
||||
stack, attr, start_routine,
|
||||
arg, cpu_session, location,
|
||||
cpu_id, name);
|
||||
cpu_id, name, pd_vcpus);
|
||||
|
||||
Assert(!(reinterpret_cast<unsigned long>(vcpu_handler) & 0xf));
|
||||
|
||||
|
@ -762,12 +762,13 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher<pthread>,
|
||||
void *(*start_routine) (void *), void *arg,
|
||||
Genode::Cpu_session * cpu_session,
|
||||
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,
|
||||
attr ? *attr : 0, start_routine, arg,
|
||||
name),
|
||||
_vcpu(cpu_session, location),
|
||||
_vcpu(cpu_session, location, pd_vcpu),
|
||||
_ec_sel(Genode::cap_map()->insert()),
|
||||
_irq_win(false),
|
||||
_cpu_id(cpu_id)
|
||||
|
@ -88,10 +88,11 @@ class Vcpu_handler_svm : public Vcpu_handler
|
||||
void *(*start_routine) (void *), void *arg,
|
||||
Genode::Cpu_session * cpu_session,
|
||||
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,
|
||||
location, cpu_id, name)
|
||||
location, cpu_id, name, pd_vcpu)
|
||||
{
|
||||
using namespace Nova;
|
||||
|
||||
|
@ -162,10 +162,11 @@ class Vcpu_handler_vmx : public Vcpu_handler
|
||||
void *(*start_routine) (void *), void *arg,
|
||||
Genode::Cpu_session * cpu_session,
|
||||
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,
|
||||
location, cpu_id, name)
|
||||
location, cpu_id, name, pd_vcpu)
|
||||
{
|
||||
using namespace Nova;
|
||||
|
||||
|
@ -560,19 +560,21 @@ bool create_emt_vcpu(pthread_t * pthread, ::size_t stack,
|
||||
if (!hip->has_feature_vmx() && !hip->has_feature_svm())
|
||||
return false;
|
||||
|
||||
static Genode::Pd_connection pd_vcpus("VM");
|
||||
|
||||
Vcpu_handler *vcpu_handler = 0;
|
||||
|
||||
if (hip->has_feature_vmx())
|
||||
vcpu_handler = new (0x10) Vcpu_handler_vmx(genode_env(),
|
||||
stack, attr, start_routine,
|
||||
arg, cpu_session, location,
|
||||
cpu_id, name);
|
||||
cpu_id, name, pd_vcpus);
|
||||
|
||||
if (hip->has_feature_svm())
|
||||
vcpu_handler = new (0x10) Vcpu_handler_svm(genode_env(),
|
||||
stack, attr, start_routine,
|
||||
arg, cpu_session, location,
|
||||
cpu_id, name);
|
||||
cpu_id, name, pd_vcpus);
|
||||
|
||||
Assert(!(reinterpret_cast<unsigned long>(vcpu_handler) & 0xf));
|
||||
|
||||
|
@ -765,12 +765,13 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher<pthread>,
|
||||
void *(*start_routine) (void *), void *arg,
|
||||
Genode::Cpu_session * cpu_session,
|
||||
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,
|
||||
attr ? *attr : 0, start_routine, arg,
|
||||
name),
|
||||
_vcpu(cpu_session, location),
|
||||
_vcpu(cpu_session, location, pd_vcpu),
|
||||
_ec_sel(Genode::cap_map()->insert()),
|
||||
_irq_win(false),
|
||||
_cpu_id(cpu_id)
|
||||
|
@ -88,10 +88,11 @@ class Vcpu_handler_svm : public Vcpu_handler
|
||||
void *(*start_routine) (void *), void *arg,
|
||||
Genode::Cpu_session * cpu_session,
|
||||
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,
|
||||
location, cpu_id, name)
|
||||
location, cpu_id, name, pd_vcpu)
|
||||
{
|
||||
using namespace Nova;
|
||||
|
||||
|
@ -170,10 +170,11 @@ class Vcpu_handler_vmx : public Vcpu_handler
|
||||
void *(*start_routine) (void *), void *arg,
|
||||
Genode::Cpu_session * cpu_session,
|
||||
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,
|
||||
location, cpu_id, name)
|
||||
location, cpu_id, name, pd_vcpu)
|
||||
{
|
||||
using namespace Nova;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user