vbox6: unify EMT and vCPU entrypoint

Issue #4031
This commit is contained in:
Christian Helmuth 2021-03-09 14:32:44 +01:00 committed by Norman Feske
parent c67e78a7f0
commit 839183d2b6
13 changed files with 415 additions and 121 deletions

View File

@ -29,21 +29,23 @@ src/virtualbox6_sdk:
mkdir -p $(dir $@)
cp -r $(PORT_DIR)/$@ $(dir $@)
MIRROR_FROM_LIBPORTS := lib/mk/libc-mem.mk \
lib/mk/libc-common.inc \
src/lib/libc/internal/init.h \
src/lib/libc/internal/mem_alloc.h \
src/lib/libc/internal/monitor.h \
src/lib/libc/internal/pthread.h \
src/lib/libc/internal/thread_create.h \
src/lib/libc/internal/timer.h \
src/lib/libc/internal/types.h \
src/lib/libc/libc_mem_alloc.cc \
lib/import/import-qemu-usb_include.mk \
lib/mk/qemu-usb_include.mk \
lib/mk/qemu-usb.mk \
include/qemu \
src/lib/qemu-usb
MIRROR_FROM_LIBPORTS := \
include/qemu \
lib/import/import-qemu-usb_include.mk \
lib/mk/libc-common.inc \
lib/mk/libc-mem.mk \
lib/mk/qemu-usb.mk \
lib/mk/qemu-usb_include.mk \
src/lib/libc/internal/init.h \
src/lib/libc/internal/mem_alloc.h \
src/lib/libc/internal/monitor.h \
src/lib/libc/internal/pthread.h \
src/lib/libc/internal/thread_create.h \
src/lib/libc/internal/timer.h \
src/lib/libc/internal/types.h \
src/lib/libc/libc_mem_alloc.cc \
src/lib/libc/spec/x86_64/internal/call_func.h \
src/lib/qemu-usb
content: $(MIRROR_FROM_LIBPORTS)

View File

@ -19,6 +19,8 @@ namespace Genode { struct Env; }
namespace Sup { void init(Genode::Env &); }
namespace Pthread { void init(Genode::Env &); }
namespace Network { void init(Genode::Env &); }
namespace Xhci { void init(Genode::Env &); }

View File

@ -1,5 +1,5 @@
/*
* \brief VirtualBox runtime (RT)
* \brief VirtualBox libc runtime
* \author Norman Feske
* \author Christian Helmuth
* \date 2013-08-20
@ -17,8 +17,6 @@
#include <sys/times.h>
#include <unistd.h>
#include <aio.h>
#include <sched.h>
#include <pthread.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h> /* memset */
@ -29,27 +27,11 @@
/* local includes */
#include <stub_macros.h>
static bool const debug = true;
static bool const debug = true; /* required by stub_macros.h */
extern "C" {
int sched_yield()
{
static unsigned long counter = 0;
if (++counter % 100'000 == 0)
Genode::warning(__func__, " called ", counter, " times");
return 0;
}
int sched_get_priority_max(int policy) TRACE(0)
int sched_get_priority_min(int policy) TRACE(0)
int pthread_setschedparam(pthread_t thread, int policy,
const struct sched_param *param) TRACE(0)
int pthread_getschedparam(pthread_t thread, int *policy,
struct sched_param *param) TRACE(0)
int futimes(int fd, const struct timeval tv[2]) TRACE(0)
int lutimes(const char *filename, const struct timeval tv[2]) TRACE(0)
int lchown(const char *pathname, uid_t owner, gid_t group) TRACE(0)

View File

@ -338,6 +338,7 @@ void Libc::Component::construct(Libc::Env &env)
environ = envp;
Pthread::init(env);
Network::init(env);
/* sidestep 'rtThreadPosixSelectPokeSignal' */

View File

@ -0,0 +1,267 @@
/*
* \brief VirtualBox libc runtime: pthread adaptions
* \author Christian Helmuth
* \date 2021-03-03
*/
/*
* Copyright (C) 2021 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/* libc includes */
#include <errno.h>
#include <sched.h>
#include <pthread.h>
/* libc internal */
#include <internal/thread_create.h> /* Libc::pthread_create() */
#include <internal/call_func.h> /* call_func() */
/* VirtualBox includes */
#include <VBox/vmm/uvm.h>
#include <internal/thread.h> /* RTTHREADINT etc. */
/* Genode includes */
#include <base/env.h>
#include <base/entrypoint.h>
#include <base/registry.h>
#include <util/string.h>
#include <util/reconstructible.h>
/* local includes */
#include <init.h>
#include <pthread_emt.h>
#include <sup.h>
#include <stub_macros.h>
static bool const debug = true; /* required by stub_macros.h */
using namespace Genode;
extern "C" int sched_yield()
{
static unsigned long counter = 0;
if (++counter % 100'000 == 0)
warning(__func__, " called ", counter, " times");
return 0;
}
extern "C" int sched_get_priority_max(int policy) TRACE(0)
extern "C" int sched_get_priority_min(int policy) TRACE(0)
extern "C" int pthread_setschedparam(pthread_t thread, int policy,
const struct sched_param *param) TRACE(0)
extern "C" int pthread_getschedparam(pthread_t thread, int *policy,
struct sched_param *param) TRACE(0)
namespace Pthread {
struct Entrypoint;
struct Factory;
} /* namespace Pthread */
class Pthread::Entrypoint : public Pthread::Emt
{
private:
/* members initialized by constructing thread */
Sup::Cpu_index const _cpu;
size_t const _stack_size; /* stack size for EMT mode */
Genode::Entrypoint _ep;
Blockade _construction_finalized { };
void *(*_emt_start_routine) (void *);
void *_emt_arg;
enum class Mode { VCPU, EMT } _mode { Mode::VCPU };
jmp_buf _vcpu_jmp_buf;
jmp_buf _emt_jmp_buf;
/* members finally initialized by the entrypoint itself */
void *_emt_stack { nullptr };
pthread_t _emt_pthread { };
void _finalize_construction()
{
Genode::Thread &myself = *Genode::Thread::myself();
_emt_stack = myself.alloc_secondary_stack(myself.name().string(),
_stack_size);
Libc::pthread_create_from_thread(&_emt_pthread, myself, _emt_stack);
_construction_finalized.wakeup();
/* switch to EMT mode and call pthread start_routine */
if (setjmp(_vcpu_jmp_buf) == 0) {
_mode = Mode::EMT;
call_func(_emt_stack, (void *)_emt_start_routine, _emt_arg);
}
}
Genode::Signal_handler<Entrypoint> _finalize_construction_sigh {
_ep, *this, &Entrypoint::_finalize_construction };
public:
Entrypoint(Env &env, Sup::Cpu_index cpu, size_t stack_size,
char const *name, Affinity::Location location,
void *(*start_routine) (void *), void *arg)
:
_cpu(cpu), _stack_size(stack_size),
_ep(env, 64*1024, name, location),
_emt_start_routine(start_routine), _emt_arg(arg)
{
Signal_transmitter(_finalize_construction_sigh).submit();
_construction_finalized.block();
}
/* registered object must have virtual destructor */
virtual ~Entrypoint() { }
Sup::Cpu_index cpu() const { return _cpu; }
pthread_t pthread() const { return _emt_pthread; }
/* Pthread::Emt interface */
void switch_to_emt() override
{
Assert(_mode == Mode::VCPU);
if (setjmp(_vcpu_jmp_buf) == 0) {
_mode = Mode::EMT;
longjmp(_emt_jmp_buf, 1);
}
}
void switch_to_vcpu() override
{
Assert(pthread_self() == _emt_pthread);
Assert(_mode == Mode::EMT);
if (setjmp(_emt_jmp_buf) == 0) {
_mode = Mode::VCPU;
longjmp(_vcpu_jmp_buf, 1);
}
}
Genode::Entrypoint & genode_ep() override { return _ep; }
};
class Pthread::Factory
{
private:
Env &_env;
Registry<Registered<Pthread::Entrypoint>> _entrypoints;
Affinity::Space const _affinity_space { _env.cpu().affinity_space() };
public:
Factory(Env &env) : _env(env) { }
Entrypoint & create(Sup::Cpu_index cpu, size_t stack_size, char const *name,
void *(*start_routine) (void *), void *arg)
{
Affinity::Location const location =
_affinity_space.location_of_index(cpu.value);
return *new Registered<Entrypoint>(_entrypoints, _env, cpu,
stack_size, name,
location, start_routine, arg);
}
struct Emt_for_cpu_not_found : Exception { };
Emt & emt_for_cpu(Sup::Cpu_index cpu)
{
Entrypoint *found = nullptr;
_entrypoints.for_each([&] (Entrypoint &ep) {
if (ep.cpu().value == cpu.value)
found = &ep;
});
if (!found)
throw Emt_for_cpu_not_found();
return *found;
}
};
static Pthread::Factory *factory;
Pthread::Emt & Pthread::emt_for_cpu(Sup::Cpu_index cpu)
{
return factory->emt_for_cpu(cpu);
}
void Pthread::init(Env &env)
{
factory = new Pthread::Factory(env);
}
static int create_emt_thread(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *),
PRTTHREADINT rtthread)
{
PUVMCPU pUVCpu = (PUVMCPU)rtthread->pvUser;
Sup::Cpu_index const cpu { pUVCpu->idCpu };
size_t stack_size = 0;
/* try to fetch configured stack size form attribute */
pthread_attr_getstacksize(attr, &stack_size);
Assert(stack_size);
Pthread::Entrypoint &ep =
factory->create(cpu, stack_size, rtthread->szName,
start_routine, rtthread);
*thread = ep.pthread();
return 0;
}
extern "C" int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg)
{
PRTTHREADINT rtthread = reinterpret_cast<PRTTHREADINT>(arg);
/*
* Emulation threads (EMT) represent the guest CPU, so we implement them in
* dedicated entrypoints that also handle vCPU events in combination with
* user-level threading (i.e., setjmp/longjmp).
*/
if (rtthread->enmType == RTTHREADTYPE_EMULATION)
return create_emt_thread(thread, attr, start_routine, rtthread);
else
return Libc::pthread_create(thread, attr, start_routine, arg, rtthread->szName);
}

View File

@ -0,0 +1,38 @@
/*
* \brief Pthread helpers for emulation threads
* \author Christian Helmuth
* \date 2021-03-08
*/
/*
* Copyright (C) 2021 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#ifndef _PTHREAD_EMT_H_
#define _PTHREAD_EMT_H_
/* Genode includes */
#include <util/interface.h>
/* local includes */
#include <sup.h>
namespace Genode { struct Entrypoint; }
namespace Pthread {
struct Emt : Genode::Interface
{
virtual void switch_to_emt() = 0;
virtual void switch_to_vcpu() = 0;
virtual Genode::Entrypoint & genode_ep() = 0;
};
Emt & emt_for_cpu(Sup::Cpu_index cpu);
}
#endif /* _PTHREAD_EMT_H_ */

View File

@ -34,6 +34,7 @@
#include <init.h>
#include <sup_drv.h>
#include <sup_vm.h>
#include <pthread_emt.h>
#include <stub_macros.h>
static bool const debug = true;
@ -171,20 +172,28 @@ static void ioctl(SUPVTCAPS &request)
}
static void setup_vcpu_handler(Sup::Vm &vm, Sup::Cpu_index cpu)
{
Pthread::Emt &emt = Pthread::emt_for_cpu(cpu);
Sup::Vcpu_handler &handler = sup_drv->create_vcpu_handler(cpu, emt);
vm.register_vcpu_handler(cpu, handler);
}
static int vmmr0_gvmm_create_vm(GVMMCREATEVMREQ &request)
{
Sup::Cpu_count cpu_count { request.cCpus };
Sup::Vm &new_vm = Sup::Vm::create(request.pSession, cpu_count);
for (unsigned i = 0; i < cpu_count.value; i++) {
/*
* The first EMT thread creates the VM and must be registered implicitly.
* Additional EMTs register themselves via vmmr0_gvmm_register_vcpu().
*/
Sup::Cpu_index const index { i };
Sup::Vcpu_handler &handler = sup_drv->create_vcpu_handler(index);
new_vm.register_vcpu_handler(index, handler);
}
setup_vcpu_handler(new_vm, Sup::Cpu_index { 0 });
request.pVMR3 = &new_vm;
request.pVMR0 = (PVMR0)request.pVMR3;
@ -195,7 +204,7 @@ static int vmmr0_gvmm_create_vm(GVMMCREATEVMREQ &request)
static int vmmr0_gvmm_register_vcpu(PVMR0 pvmr0, uint32_t cpu)
{
warning(__PRETTY_FUNCTION__, " cpu=", cpu);
Sup::Vm &vm = *(Sup::Vm *)pvmr0;
/*
* EMT threads for additional CPUs are registered on initialization.
@ -206,6 +215,8 @@ static int vmmr0_gvmm_register_vcpu(PVMR0 pvmr0, uint32_t cpu)
* pGVM->aCpus[idCpu].hNativeThreadR0 = pGVM->aCpus[idCpu].hEMT = RTThreadNativeSelf();
*/
setup_vcpu_handler(vm, Sup::Cpu_index { cpu });
return VINF_SUCCESS;
}

View File

@ -17,7 +17,7 @@
/* local includes */
#include <sup_drv.h>
#include <vcpu.h>
#include <pthread_emt.h>
Sup::Cpu_freq_khz Sup::Drv::_cpu_freq_khz_from_rom()
@ -55,30 +55,24 @@ Sup::Drv::Cpu_virt Sup::Drv::_cpu_virt_from_rom()
}
Sup::Vcpu_handler &Sup::Drv::create_vcpu_handler(Cpu_index cpu_index)
Sup::Vcpu_handler &Sup::Drv::create_vcpu_handler(Cpu_index cpu_index,
Pthread::Emt &emt)
{
Libc::Allocator alloc { };
Affinity::Location const location =
_affinity_space.location_of_index(cpu_index.value);
size_t const stack_size = 64*1024;
switch (_cpu_virt) {
case Cpu_virt::VMX:
return *new Vcpu_handler_vmx(_env,
stack_size,
location,
cpu_index.value,
emt,
_vm_connection,
alloc);
case Cpu_virt::SVM:
return *new Vcpu_handler_svm(_env,
stack_size,
location,
cpu_index.value,
emt,
_vm_connection,
alloc);

View File

@ -29,6 +29,8 @@
namespace Sup { struct Drv; }
namespace Pthread { struct Emt; }
class Sup::Drv
{
public:
@ -71,7 +73,7 @@ class Sup::Drv
/*
* \throw Virtualization_support_missing
*/
Vcpu_handler &create_vcpu_handler(Cpu_index);
Vcpu_handler &create_vcpu_handler(Cpu_index, Pthread::Emt &);
};
#endif /* _SUP_DRV_H_ */

View File

@ -63,7 +63,6 @@ void Sup::Vm::init(PSUPDRVSESSION psession, Cpu_count cpu_count)
cpu.hNativeThreadR0 = NIL_RTNATIVETHREAD;
VM::apCpusR3[i] = &cpu;
log(this, ": apCpusR3[", i, "]=", apCpusR3[i]);
}
}

View File

@ -1,3 +1,5 @@
REQUIRES = x86_64
TARGET = virtualbox6
include $(REP_DIR)/lib/mk/virtualbox6-common.inc
@ -6,7 +8,7 @@ CC_WARN += -Wall
SRC_CC := main.cc drivers.cc vcpu_gim.cc
SRC_CC += libc.cc unimpl.cc dummies.cc pdm.cc devices.cc nem.cc dynlib.cc
SRC_CC += network.cc
SRC_CC += pthread.cc network.cc
LIBS += base
LIBS += stdcxx
@ -22,6 +24,7 @@ LIB_MK_FILES := $(notdir $(wildcard $(REP_DIR)/lib/mk/virtualbox6-*.mk) \
LIBS += $(LIB_MK_FILES:.mk=)
INC_DIR += $(call select_from_repositories,src/lib/libc)
INC_DIR += $(call select_from_repositories,src/lib/libc)/spec/x86_64
INC_DIR += $(VBOX_DIR)/Runtime/include

View File

@ -33,6 +33,7 @@
/* local includes */
#include <vcpu.h>
#include <pthread_emt.h>
/*
@ -141,7 +142,6 @@ void Sup::Vcpu_handler_svm::_handle_exit()
break;
case VCPU_STARTUP:
_svm_startup();
_blockade_emt.wakeup();
/* pause - no resume */
break;
default:
@ -158,7 +158,7 @@ void Sup::Vcpu_handler_svm::_handle_exit()
}
/* wait until EMT thread wake's us up */
_sem_handler.down();
/* TODO XXX _sem_handler.down(); */
/* resume vCPU */
_vm_state = RUNNING;
@ -190,23 +190,22 @@ int Sup::Vcpu_handler_svm::_vm_exit_requires_instruction_emulation(PCPUMCTX)
}
Sup::Vcpu_handler_svm::Vcpu_handler_svm(Genode::Env &env, size_t stack_size,
Genode::Affinity::Location location,
Sup::Vcpu_handler_svm::Vcpu_handler_svm(Genode::Env &env,
unsigned int cpu_id,
Pthread::Emt &emt,
Genode::Vm_connection &vm_connection,
Genode::Allocator &alloc)
:
Vcpu_handler(env, stack_size, location, cpu_id),
_handler(_ep, *this, &Vcpu_handler_svm::_handle_exit),
Vcpu_handler(env, cpu_id, emt),
_handler(_emt.genode_ep(), *this, &Vcpu_handler_svm::_handle_exit),
_vm_connection(vm_connection),
_vcpu(_vm_connection, alloc, _handler, _exit_config)
{
_state = &_vcpu.state();
/* run vCPU until initial startup exception */
_vcpu.run();
/* sync with initial startup exception */
_blockade_emt.block();
_emt.switch_to_vcpu();
}
@ -296,6 +295,8 @@ __attribute__((noreturn)) void Sup::Vcpu_handler_vmx::_vmx_invalid()
" actv_state=", Genode::Hex(_state->actv_state.value()));
Genode::error("invalid guest state - dead");
/* FIXME exit() cannot be called in VCPU mode */
exit(-1);
}
@ -333,29 +334,37 @@ void Sup::Vcpu_handler_vmx::_handle_exit()
case VMX_EXIT_XSETBV: _vmx_default(); break;
case VMX_EXIT_TPR_BELOW_THRESHOLD: _vmx_default(); break;
case VMX_EXIT_EPT_VIOLATION: _vmx_ept<VMX_EXIT_EPT_VIOLATION>(); break;
case RECALL:
recall_wait = Vcpu_handler::_recall_handler();
if (!recall_wait) {
_vm_state = RUNNING;
/* XXX early return for resume */
_run_vm();
return;
}
/* paused - no resume of vCPU */
break;
case VCPU_STARTUP:
_vmx_startup();
_blockade_emt.wakeup();
/* pause - no resume */
/* paused - no resume of vCPU */
break;
default:
Genode::error(__func__, " unknown exit - stop - ",
Genode::Hex(exit));
_vm_state = PAUSED;
/* XXX early return without resume */
return;
}
if (exit == RECALL && !recall_wait) {
_vm_state = RUNNING;
_run_vm();
return;
}
/* wait until EMT thread wake's us up */
_sem_handler.down();
/* switch to EMT until next vCPU resume */
Assert(_vm_state != RUNNING);
_emt.switch_to_emt();
/* resume vCPU */
_vm_state = RUNNING;
@ -408,23 +417,22 @@ int Sup::Vcpu_handler_vmx::_vm_exit_requires_instruction_emulation(PCPUMCTX pCtx
}
Sup::Vcpu_handler_vmx::Vcpu_handler_vmx(Genode::Env &env, size_t stack_size,
Genode::Affinity::Location location,
Sup::Vcpu_handler_vmx::Vcpu_handler_vmx(Genode::Env &env,
unsigned int cpu_id,
Pthread::Emt &emt,
Genode::Vm_connection &vm_connection,
Genode::Allocator &alloc)
:
Vcpu_handler(env, stack_size, location, cpu_id),
_handler(_ep, *this, &Vcpu_handler_vmx::_handle_exit),
Vcpu_handler(env, cpu_id, emt),
_handler(_emt.genode_ep(), *this, &Vcpu_handler_vmx::_handle_exit),
_vm_connection(vm_connection),
_vcpu(_vm_connection, alloc, _handler, _exit_config)
{
_state = &_vcpu.state();
/* run vCPU until initial startup exception */
_vcpu.run();
/* sync with initial startup exception */
_blockade_emt.block();
_emt.switch_to_vcpu();
}
@ -435,6 +443,7 @@ Sup::Vcpu_handler_vmx::Vcpu_handler_vmx(Genode::Env &env, size_t stack_size,
Genode::Vm_connection::Exit_config const Sup::Vcpu_handler::_exit_config { /* ... */ };
/* TODO move into Emt */
timespec Sup::Vcpu_handler::_add_timespec_ns(timespec a, ::uint64_t ns) const
{
enum { NSEC_PER_SEC = 1'000'000'000ull };
@ -472,11 +481,8 @@ again:
Assert(_vm_state == IRQ_WIN || _vm_state == PAUSED || _vm_state == NPT_EPT);
Assert(_next_state == PAUSE_EXIT || _next_state == RUN);
/* wake up vcpu ep handler */
_sem_handler.up();
/* wait for next exit */
_blockade_emt.block();
/* run vCPU until next exit */
_emt.switch_to_vcpu();
/* next time run - recall() may change this */
_next_state = RUN;
@ -490,14 +496,6 @@ again:
_state->discharge();
_irq_window_pthread();
goto again;
} else
if (_vm_state == NPT_EPT) {
// if (_npt_ept_unmap) {
// Genode::error("NPT/EPT unmap not supported - stop");
// while (true) {
// _blockade_emt.block();
// }
// }
}
if (!(_vm_state == PAUSED || _vm_state == NPT_EPT))
@ -519,8 +517,6 @@ void Sup::Vcpu_handler::_default_handler()
_vm_exits++;
_vm_state = PAUSED;
_blockade_emt.wakeup();
}
@ -759,7 +755,7 @@ bool Sup::Vcpu_handler::_state_to_vbox(VM *pVM, PVMCPU pVCpu)
pVCpu->cpum.s.fUseFlags |= (CPUM_USED_FPU_GUEST);
// CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_FPU_REM);
// pVCpu->cpum.s.fUseFlags |= (CPUM_USED_FPU_GUEST | CPUM_USED_FPU_SINCE_REM);
if (_state->intr_state.value() != 0) {
Assert(_state->intr_state.value() == INTERRUPT_STATE_BLOCKING_BY_STI ||
_state->intr_state.value() == INTERRUPT_STATE_BLOCKING_BY_MOV_SS);
@ -801,7 +797,6 @@ void Sup::Vcpu_handler::_irq_window()
_vm_exits++;
_vm_state = IRQ_WIN;
_blockade_emt.wakeup();
}
@ -814,7 +809,6 @@ void Sup::Vcpu_handler::_npt_ept()
_vm_exits++;
_vm_state = NPT_EPT;
_blockade_emt.wakeup();
}
@ -983,6 +977,7 @@ void Sup::Vcpu_handler::recall(VM &vm)
}
/* TODO move into Emt */
void Sup::Vcpu_handler::halt(Genode::uint64_t const wait_ns)
{
/* calculate timeout */
@ -997,6 +992,7 @@ void Sup::Vcpu_handler::halt(Genode::uint64_t const wait_ns)
}
/* TODO move into Emt */
void Sup::Vcpu_handler::wake_up()
{
pthread_mutex_lock(&_mutex);
@ -1093,13 +1089,9 @@ int Sup::Vcpu_handler::run_hw(VM &vm)
}
Sup::Vcpu_handler::Vcpu_handler(Env &env, size_t stack_size,
Affinity::Location location,
unsigned int cpu_id)
Sup::Vcpu_handler::Vcpu_handler(Env &env, unsigned int cpu_id, Pthread::Emt &emt)
:
_ep(env, stack_size,
Genode::String<12>("EP-EMT-", cpu_id).string(), location),
_cpu_id(cpu_id)
_emt(emt), _cpu_id(cpu_id)
{
pthread_mutexattr_t _attr;
pthread_mutexattr_init(&_attr);

View File

@ -30,6 +30,8 @@ namespace Sup {
struct Vcpu_handler_svm;
}
namespace Pthread { struct Emt; }
class Sup::Vcpu_handler : Genode::Noncopyable
{
@ -37,16 +39,19 @@ class Sup::Vcpu_handler : Genode::Noncopyable
static Genode::Vm_connection::Exit_config const _exit_config;
Genode::Entrypoint _ep;
Genode::Blockade _blockade_emt { };
Genode::Semaphore _sem_handler;
Pthread::Emt &_emt;
Genode::Vcpu_state *_state { nullptr };
bool _last_exit_triggered_by_wrmsr = false;
/* TODO move into Emt */
/* halt/wake_up */
pthread_cond_t _cond_wait;
pthread_mutex_t _mutex;
/* TODO move into Emt */
timespec _add_timespec_ns(timespec a, ::uint64_t ns) const;
/* information used for NPT/EPT handling */
Genode::addr_t _npt_ept_exit_addr { 0 };
RTGCUINT _npt_ept_errorcode { 0 };
@ -83,8 +88,6 @@ class Sup::Vcpu_handler : Genode::Noncopyable
INTERRUPT_STATE_BLOCKING_BY_MOV_SS = 1U << 1,
};
timespec _add_timespec_ns(timespec a, ::uint64_t ns) const;
void _update_gim_system_time();
protected:
@ -99,8 +102,8 @@ class Sup::Vcpu_handler : Genode::Noncopyable
Genode::addr_t _irq_drop = 0;
struct {
unsigned intr_state;
unsigned ctrl[2];
unsigned intr_state = 0;
unsigned ctrl[2] = { 0, 0 };
} _next_utcb;
unsigned _ept_fault_addr_type;
@ -141,9 +144,7 @@ class Sup::Vcpu_handler : Genode::Noncopyable
RECALL = 0xff,
};
Vcpu_handler(Genode::Env &env, size_t stack_size,
Genode::Affinity::Location location,
unsigned int cpu_id);
Vcpu_handler(Genode::Env &env, unsigned int cpu_id, Pthread::Emt &emt);
unsigned int cpu_id() const { return _cpu_id; }
@ -187,9 +188,9 @@ class Sup::Vcpu_handler_vmx : public Vcpu_handler
public:
Vcpu_handler_vmx(Genode::Env &env, size_t stack_size,
Genode::Affinity::Location location,
Vcpu_handler_vmx(Genode::Env &env,
unsigned int cpu_id,
Pthread::Emt &emt,
Genode::Vm_connection &vm_connection,
Genode::Allocator &alloc);
};
@ -224,9 +225,9 @@ class Sup::Vcpu_handler_svm : public Vcpu_handler
public:
Vcpu_handler_svm(Genode::Env &env, size_t stack_size,
Genode::Affinity::Location location,
Vcpu_handler_svm(Genode::Env &env,
unsigned int cpu_id,
Pthread::Emt &emt,
Genode::Vm_connection &vm_connection,
Genode::Allocator &alloc);
};