diff --git a/base-nova/include/nova_cpu_session/client.h b/base-nova/include/nova_cpu_session/client.h index 0bc1ecd684..3b1cfc57cd 100644 --- a/base-nova/include/nova_cpu_session/client.h +++ b/base-nova/include/nova_cpu_session/client.h @@ -68,10 +68,11 @@ namespace Genode { return call(cap); } int start_exc_base_vcpu(Thread_capability thread, addr_t ip, - addr_t sp, addr_t exc_base) + addr_t sp, addr_t exc_base, + bool vcpu = false) { return call(thread, ip, sp, - exc_base); + exc_base, vcpu); } diff --git a/base-nova/include/nova_cpu_session/nova_cpu_session.h b/base-nova/include/nova_cpu_session/nova_cpu_session.h index a99c140280..4112c7dc3f 100644 --- a/base-nova/include/nova_cpu_session/nova_cpu_session.h +++ b/base-nova/include/nova_cpu_session/nova_cpu_session.h @@ -25,7 +25,7 @@ namespace Genode { virtual int start_exc_base_vcpu(Thread_capability thread, addr_t ip, - addr_t sp, addr_t exc_base) = 0; + addr_t sp, addr_t exc_base, bool vcpu) = 0; virtual Native_capability native_cap(Thread_capability cap) = 0; @@ -34,7 +34,7 @@ namespace Genode { *********************/ GENODE_RPC(Rpc_start_exc_base_vcpu, int, start_exc_base_vcpu, - Thread_capability, addr_t, addr_t, addr_t); + Thread_capability, addr_t, addr_t, addr_t, bool); GENODE_RPC(Rpc_native_cap, Native_capability, native_cap, Thread_capability); diff --git a/base-nova/src/base/thread/thread_nova.cc b/base-nova/src/base/thread/thread_nova.cc index 162a85b1a9..048d5c2bd7 100644 --- a/base-nova/src/base/thread/thread_nova.cc +++ b/base-nova/src/base/thread/thread_nova.cc @@ -118,7 +118,7 @@ void Thread_base::start() Genode::Nova_cpu_connection cpu; if (cpu.start_exc_base_vcpu(_thread_cap, (addr_t)_thread_start, - thread_sp, _tid.exc_pt_sel)) + thread_sp, _tid.exc_pt_sel, _tid.is_vcpu)) throw Cpu_session::Thread_creation_failed(); /* request native EC thread cap */ @@ -127,10 +127,14 @@ void Thread_base::start() using namespace Nova; - /* request exception portals */ - request_event_portal(pager_cap, _tid.exc_pt_sel, PT_SEL_STARTUP); - request_event_portal(pager_cap, _tid.exc_pt_sel, PT_SEL_PAGE_FAULT); - request_event_portal(pager_cap, _tid.exc_pt_sel, SM_SEL_EC); + /* request exception portals for normal threads */ + if (!_tid.is_vcpu) { + request_event_portal(pager_cap, _tid.exc_pt_sel, + PT_SEL_STARTUP); + request_event_portal(pager_cap, _tid.exc_pt_sel, + PT_SEL_PAGE_FAULT); + request_event_portal(pager_cap, _tid.exc_pt_sel, SM_SEL_EC); + } /* request creation of SC to let thread run*/ env()->cpu_session()->resume(_thread_cap); diff --git a/base-nova/src/core/cpu_session_extension.cc b/base-nova/src/core/cpu_session_extension.cc index 4340cc8262..3d2dd2e6b7 100644 --- a/base-nova/src/core/cpu_session_extension.cc +++ b/base-nova/src/core/cpu_session_extension.cc @@ -32,12 +32,11 @@ Cpu_session_component::native_cap(Thread_capability thread_cap) int Cpu_session_component::start_exc_base_vcpu(Thread_capability thread_cap, addr_t ip, addr_t sp, - addr_t exc_base) + addr_t exc_base, bool vcpu) { Cpu_thread_component *thread = _lookup_thread(thread_cap); if (!thread) return -1; - return thread->platform_thread()->start((void *)ip, (void *)sp, exc_base); + return thread->platform_thread()->start((void *)ip, (void *)sp, + exc_base, vcpu); } - - diff --git a/base-nova/src/core/include/cpu_session_component.h b/base-nova/src/core/include/cpu_session_component.h index e3b9a0d17d..c3c85858e6 100644 --- a/base-nova/src/core/include/cpu_session_component.h +++ b/base-nova/src/core/include/cpu_session_component.h @@ -148,7 +148,7 @@ namespace Genode { ***********************************/ int start_exc_base_vcpu(Thread_capability, addr_t, - addr_t, addr_t); + addr_t, addr_t, bool); Native_capability native_cap(Thread_capability); }; } diff --git a/base-nova/src/core/include/platform_thread.h b/base-nova/src/core/include/platform_thread.h index 4ac3676474..ba860bdad1 100644 --- a/base-nova/src/core/include/platform_thread.h +++ b/base-nova/src/core/include/platform_thread.h @@ -59,13 +59,18 @@ namespace Genode { /** * Start thread * - * \param ip instruction pointer to start at - * \param sp stack pointer to use + * \param ip instruction pointer to start at + * \param sp stack pointer to use + * \param exc_base exception base of thread in caller + * protection domain + * \param vcpu If true it will run as vCPU, + * otherwise it will be a thread. * * \retval 0 successful - * \retval -1 thread could not be started + * \retval -1 thread/vCPU could not be started */ - int start(void *ip, void *sp, addr_t exc_base = ~0UL); + int start(void *ip, void *sp, addr_t exc_base = ~0UL, + bool vcpu = false); /** * Pause this thread diff --git a/base-nova/src/core/platform_thread.cc b/base-nova/src/core/platform_thread.cc index bc40f3e07c..5cb37324df 100644 --- a/base-nova/src/core/platform_thread.cc +++ b/base-nova/src/core/platform_thread.cc @@ -40,7 +40,7 @@ void Platform_thread::set_cpu(unsigned int cpu_no) } -int Platform_thread::start(void *ip, void *sp, addr_t exc_base) +int Platform_thread::start(void *ip, void *sp, addr_t exc_base, bool vcpu) { using namespace Nova; @@ -58,7 +58,7 @@ int Platform_thread::start(void *ip, void *sp, addr_t exc_base) _pager->initial_eip((addr_t)ip); if (!_is_main_thread) { addr_t initial_sp = reinterpret_cast(sp); - addr_t utcb = round_page(initial_sp); + addr_t utcb = vcpu ? 0 : round_page(initial_sp); _pager->initial_esp(initial_sp); if (exc_base == ~0UL) { @@ -83,6 +83,7 @@ int Platform_thread::start(void *ip, void *sp, addr_t exc_base) /* ip == 0 means that caller will use the thread as worker */ bool thread_global = ip; + res = create_ec(_sel_ec(), _pd->pd_sel(), _cpu_no, utcb, initial_sp, exc_base, thread_global); if (res) @@ -195,7 +196,7 @@ int Platform_thread::start(void *ip, void *sp, addr_t exc_base) cap_selector_allocator()->free(_sel_exc_base, NUM_INITIAL_PT_LOG2); _sel_exc_base = ~0UL; - return -1; + return -7; }