diff --git a/repos/ports/src/virtualbox5/generic/sup_vmm.cc b/repos/ports/src/virtualbox5/generic/sup_vmm.cc index 36b259da24..f4bb915275 100644 --- a/repos/ports/src/virtualbox5/generic/sup_vmm.cc +++ b/repos/ports/src/virtualbox5/generic/sup_vmm.cc @@ -383,7 +383,7 @@ int SUPR3CallVMMR0Ex(PVMR0 pVMR0, VMCPUID idCpu, unsigned uOperation, Vcpu_handler *vcpu_handler = lookup_vcpu_handler(idCpu); Assert(vcpu_handler); - vcpu_handler->halt(u64NowGip + ns_diff); + vcpu_handler->halt(ns_diff); return VINF_SUCCESS; } @@ -1161,13 +1161,6 @@ class Periodic_gip Libc::with_libc([&] () { rttimer_func(nullptr, rttimer_obj, 0); }); } - - for (Vcpu_handler *vcpu_handler = vcpu_handler_list().first(); - vcpu_handler; - vcpu_handler = vcpu_handler->next()) - { - vcpu_handler->check_time(); - } } public: diff --git a/repos/ports/src/virtualbox5/spec/nova/sup.cc b/repos/ports/src/virtualbox5/spec/nova/sup.cc index 5122d033dd..79ea8be036 100644 --- a/repos/ports/src/virtualbox5/spec/nova/sup.cc +++ b/repos/ports/src/virtualbox5/spec/nova/sup.cc @@ -334,8 +334,8 @@ int SUPR3CallVMMR0Ex(PVMR0 pVMR0, VMCPUID idCpu, unsigned uOperation, case VMMR0_DO_GVMM_SCHED_HALT: { - const uint64_t u64NowGip = RTTimeNanoTS(); - const uint64_t ns_diff = u64Arg > u64NowGip ? u64Arg - u64NowGip : 0; + uint64_t const u64NowGip = RTTimeNanoTS(); + uint64_t const ns_diff = u64Arg > u64NowGip ? u64Arg - u64NowGip : 0; if (!ns_diff) return VINF_SUCCESS; diff --git a/repos/ports/src/virtualbox5/vcpu.h b/repos/ports/src/virtualbox5/vcpu.h index 37fc6bb350..707774c271 100644 --- a/repos/ports/src/virtualbox5/vcpu.h +++ b/repos/ports/src/virtualbox5/vcpu.h @@ -70,10 +70,9 @@ class Vcpu_handler : public Genode::List::Element Genode::Semaphore _sem_handler; Genode::Vm_state *_state { nullptr }; - /* halt / wakeup handling with timeout support */ - Genode::Mutex _r0_mutex; - Genode::Semaphore _r0_block; - Genode::uint64_t _r0_wakeup_abs { 0 }; + pthread_cond_t _cond_wait; + pthread_mutex_t _mutex; + /* information used for NPT/EPT handling */ Genode::addr_t npt_ept_exit_addr { 0 }; @@ -111,6 +110,29 @@ class Vcpu_handler : public Genode::List::Element INTERRUPT_STATE_NONE = 0U, }; + timespec add_timespec_ns(timespec a, uint64_t ns) const + { + enum { NSEC_PER_SEC = 1'000'000'000ull }; + + long sec = a.tv_sec; + + while (a.tv_nsec >= NSEC_PER_SEC) { + a.tv_nsec -= NSEC_PER_SEC; + sec++; + } + while (ns >= NSEC_PER_SEC) { + ns -= NSEC_PER_SEC; + sec++; + } + + long nsec = a.tv_nsec + ns; + while (nsec >= NSEC_PER_SEC) { + nsec -= NSEC_PER_SEC; + sec++; + } + return timespec { sec, nsec }; + } + protected: int map_memory(Genode::Vm_connection &vm_session, @@ -675,7 +697,15 @@ class Vcpu_handler : public Genode::List::Element _ep(env, stack_size, Genode::String<12>("EP-EMT-", cpu_id).string(), location), _cpu_id(cpu_id) - { } + { + pthread_mutexattr_t _attr; + pthread_mutexattr_init(&_attr); + + pthread_cond_init(&_cond_wait, nullptr); + + pthread_mutexattr_settype(&_attr, PTHREAD_MUTEX_ERRORCHECK); + pthread_mutex_init(&_mutex, &_attr); + } unsigned int cpu_id() { return _cpu_id; } @@ -722,37 +752,24 @@ class Vcpu_handler : public Genode::List::Element #endif } - void check_time() + void halt(Genode::uint64_t const wait_ns) { - { - Genode::Mutex::Guard guard(_r0_mutex); + /* calculate timeout */ + timespec ts { 0, 0 }; + clock_gettime(CLOCK_REALTIME, &ts); + ts = add_timespec_ns(ts, wait_ns); - const uint64_t u64NowGip = RTTimeNanoTS(); - if (!_r0_wakeup_abs || _r0_wakeup_abs >= u64NowGip) - return; - } - - wake_up(); - } - - void halt(Genode::uint64_t rttime_abs) - { - { - Genode::Mutex::Guard guard(_r0_mutex); - _r0_wakeup_abs = rttime_abs; - } - - _r0_block.down(); + /* wait for condition or timeout */ + pthread_mutex_lock(&_mutex); + pthread_cond_timedwait(&_cond_wait, &_mutex, &ts); + pthread_mutex_unlock(&_mutex); } void wake_up() { - { - Genode::Mutex::Guard guard(_r0_mutex); - _r0_wakeup_abs = 0; - } - - _r0_block.up(); + pthread_mutex_lock(&_mutex); + pthread_cond_signal(&_cond_wait); + pthread_mutex_unlock(&_mutex); } int run_hw(PVMR0 pVMR0)