vbox: support timeouts for GVMM_SCHED_HALT

Issue #2110
This commit is contained in:
Alexander Boettcher 2016-09-21 11:56:59 +02:00 committed by Christian Helmuth
parent dfce939ac8
commit 14ef7a5312
10 changed files with 60 additions and 98 deletions

View File

@ -1 +1 @@
9739dad12e66d0ac8a900e3c915ea34a1fea1c2b
9d1982f1082108c0dc28855956f61752c6526b1d

View File

@ -1 +1 @@
6f6c20213ce4f96218cd69665d2c1757cebbf269
558507616b26c82ad984d7e4251c7f08131b0da8

View File

@ -6,7 +6,6 @@ vga_fb.patch
vga_vbva.patch
vmmdev.patch
usb.patch
tm_smp.patch
vbox_dd.patch
force_ioapic.patch
vbox-cpuhotplug.dsl.patch

View File

@ -1,36 +0,0 @@
tm_smp.patch
diff --git a/src/app/virtualbox/src/VBox/VMM/VMMR3/TM.cpp b/src/app/virtualbox/src/VBox/VMM/VMMR3/TM.cpp
index c3bc22d..33d705c 100644
--- a/src/app/virtualbox/src/VBox/VMM/VMMR3/TM.cpp
+++ b/src/app/virtualbox/src/VBox/VMM/VMMR3/TM.cpp
@@ -210,7 +210,7 @@ VMM_INT_DECL(int) TMR3Init(PVM pVM)
pVM->tm.s.paTimerQueuesRC = MMHyperR3ToRC(pVM, pv);
pVM->tm.s.offVM = RT_OFFSETOF(VM, tm.s);
- pVM->tm.s.idTimerCpu = pVM->cCpus - 1; /* The last CPU. */
+ pVM->tm.s.idTimerCpu = 0; /* The first CPU. */
pVM->tm.s.paTimerQueuesR3[TMCLOCK_VIRTUAL].enmClock = TMCLOCK_VIRTUAL;
pVM->tm.s.paTimerQueuesR3[TMCLOCK_VIRTUAL].u64Expire = INT64_MAX;
pVM->tm.s.paTimerQueuesR3[TMCLOCK_VIRTUAL_SYNC].enmClock = TMCLOCK_VIRTUAL_SYNC;
@@ -1901,10 +1901,19 @@ static DECLCALLBACK(void) tmR3TimerCallback(PRTTIMER pTimer, void *pvUser, uint6
NOREF(pTimer);
AssertCompile(TMCLOCK_MAX == 4);
+
+ if (VMCPU_FF_IS_SET(pVCpuDst, VMCPU_FF_TIMER)) {
#ifdef DEBUG_Sander /* very annoying, keep it private. */
- if (VMCPU_FF_IS_SET(pVCpuDst, VMCPU_FF_TIMER))
Log(("tmR3TimerCallback: timer event still pending!!\n"));
#endif
+ /*
+ * The VMCPU_FF_TIMER flag could have been set by a non-destination
+ * EMT thread without waking the destination EMT thread.
+ */
+ VMR3NotifyCpuFFU(pVCpuDst->pUVCpu, VMNOTIFYFF_FLAGS_DONE_REM);
+ return;
+ }
+
if ( !VMCPU_FF_IS_SET(pVCpuDst, VMCPU_FF_TIMER)
&& ( pVM->tm.s.paTimerQueuesR3[TMCLOCK_VIRTUAL_SYNC].offSchedule /** @todo FIXME - reconsider offSchedule as a reason for running the timer queues. */
|| pVM->tm.s.paTimerQueuesR3[TMCLOCK_VIRTUAL].offSchedule

View File

@ -117,9 +117,24 @@ int SUPR3CallVMMR0Ex(PVMR0 pVMR0, VMCPUID idCpu, unsigned
case VMMR0_DO_GVMM_SCHED_HALT:
{
const uint64_t u64NowGip = RTTimeNanoTS();
const uint64_t ns_diff = u64Arg > u64NowGip ? u64Arg - u64NowGip : 0;
if (!ns_diff)
return VINF_SUCCESS;
uint64_t const tsc_offset = genode_cpu_hz() * ns_diff / (1000*1000*1000);
uint64_t const tsc_abs = Genode::Trace::timestamp() + tsc_offset;
using namespace Genode;
if (ns_diff > RT_NS_1SEC)
warning(" more than 1 sec vcpu halt ", ns_diff, " ns");
Vcpu_handler *vcpu_handler = lookup_vcpu_handler(idCpu);
Assert(vcpu_handler);
vcpu_handler->halt();
vcpu_handler->halt(tsc_abs);
return VINF_SUCCESS;
}
@ -127,6 +142,11 @@ int SUPR3CallVMMR0Ex(PVMR0 pVMR0, VMCPUID idCpu, unsigned
{
Vcpu_handler *vcpu_handler = lookup_vcpu_handler(idCpu);
Assert(vcpu_handler);
/* don't wake the currently running thread again */
if (vcpu_handler->utcb() == Genode::Thread::myself()->utcb())
return VINF_SUCCESS;
vcpu_handler->wake_up();
return VINF_SUCCESS;
}

View File

@ -17,7 +17,6 @@
/* Genode includes */
#include <base/log.h>
#include <base/semaphore.h>
#include <util/flex_iterator.h>
#include <rom_session/connection.h>
#include <timer_session/connection.h>
@ -88,7 +87,6 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher<pthread>,
bool _irq_win;
unsigned int _cpu_id;
Genode::Semaphore _halt_sem;
unsigned int _last_inj_info;
unsigned int _last_inj_error;
@ -758,14 +756,18 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher<pthread>,
}
}
void halt()
void halt(Genode::uint64_t tsc_abs)
{
_halt_sem.down();
Assert(utcb() == Thread::myself()->utcb());
Genode::addr_t sem = native_thread().exc_pt_sel + Nova::SM_SEL_EC;
Nova::sm_ctrl(sem, Nova::SEMAPHORE_DOWNZERO, tsc_abs);
}
void wake_up()
{
_halt_sem.up();
Genode::addr_t sem = native_thread().exc_pt_sel + Nova::SM_SEL_EC;
Nova::sm_ctrl(sem, Nova::SEMAPHORE_UP);
}
int run_hw(PVMR0 pVMR0)

View File

@ -3,7 +3,6 @@ vbox_main.patch
vga_vbva.patch
vmmdev.patch
usb.patch
tm_smp.patch
vmm.patch
iem_wip.patch
dbg.patch

View File

@ -1,35 +0,0 @@
tm_smp.patch
diff --git a/src/app/virtualbox/src/VBox/VMM/VMMR3/TM.cpp b/src/app/virtualbox/src/VBox/VMM/VMMR3/TM.cpp
index c3bc22d..33d705c 100644
--- a/src/app/virtualbox/src/VBox/VMM/VMMR3/TM.cpp
+++ b/src/app/virtualbox/src/VBox/VMM/VMMR3/TM.cpp
@@ -210,7 +210,7 @@ VMM_INT_DECL(int) TMR3Init(PVM pVM)
pVM->tm.s.paTimerQueuesRC = MMHyperR3ToRC(pVM, pv);
pVM->tm.s.offVM = RT_OFFSETOF(VM, tm.s);
- pVM->tm.s.idTimerCpu = pVM->cCpus - 1; /* The last CPU. */
+ pVM->tm.s.idTimerCpu = 0; /* The first CPU. */
pVM->tm.s.paTimerQueuesR3[TMCLOCK_VIRTUAL].enmClock = TMCLOCK_VIRTUAL;
pVM->tm.s.paTimerQueuesR3[TMCLOCK_VIRTUAL].u64Expire = INT64_MAX;
pVM->tm.s.paTimerQueuesR3[TMCLOCK_VIRTUAL_SYNC].enmClock = TMCLOCK_VIRTUAL_SYNC;
@@ -1901,10 +1901,18 @@ static DECLCALLBACK(void) tmR3TimerCallback(PRTTIMER pTimer, void *pvUser, uint6
AssertCompile(TMCLOCK_MAX == 4);
STAM_COUNTER_INC(&pVM->tm.s.StatTimerCallback);
+ if (VMCPU_FF_IS_SET(pVCpuDst, VMCPU_FF_TIMER)) {
#ifdef DEBUG_Sander /* very annoying, keep it private. */
- if (VMCPU_FF_IS_SET(pVCpuDst, VMCPU_FF_TIMER))
Log(("tmR3TimerCallback: timer event still pending!!\n"));
#endif
+ /*
+ * The VMCPU_FF_TIMER flag could have been set by a non-destination
+ * EMT thread without waking the destination EMT thread.
+ */
+ VMR3NotifyCpuFFU(pVCpuDst->pUVCpu, VMNOTIFYFF_FLAGS_DONE_REM);
+ return;
+ }
+
if ( !VMCPU_FF_IS_SET(pVCpuDst, VMCPU_FF_TIMER)
&& ( pVM->tm.s.paTimerQueuesR3[TMCLOCK_VIRTUAL_SYNC].offSchedule /** @todo FIXME - reconsider offSchedule as a reason for running the timer queues. */
|| pVM->tm.s.paTimerQueuesR3[TMCLOCK_VIRTUAL].offSchedule

View File

@ -148,15 +148,24 @@ int SUPR3CallVMMR0Ex(PVMR0 pVMR0, VMCPUID idCpu, unsigned
case VMMR0_DO_GVMM_SCHED_HALT:
{
const uint64_t u64NowGip = RTTimeNanoTS();
const uint64_t ns_diff = u64Arg > u64NowGip ? u64Arg - u64NowGip : 0;
if (!ns_diff)
return VINF_SUCCESS;
uint64_t const tsc_offset = genode_cpu_hz() * ns_diff / (1000*1000*1000);
uint64_t const tsc_abs = Genode::Trace::timestamp() + tsc_offset;
using namespace Genode;
if (ns_diff > RT_NS_1SEC)
warning(" more than 1 sec vcpu halt ", ns_diff, " ns");
Vcpu_handler *vcpu_handler = lookup_vcpu_handler(idCpu);
Assert(vcpu_handler);
/*
char txt_name[32];
Genode::Thread_base::myself()->name(txt_name, sizeof(txt_name));
PINF("%s - halt - rip=%p", txt_name, __builtin_return_address(0));
*/
vcpu_handler->halt();
// PINF("%s - woken up", txt_name);
vcpu_handler->halt(tsc_abs);
return VINF_SUCCESS;
}
@ -164,11 +173,11 @@ int SUPR3CallVMMR0Ex(PVMR0 pVMR0, VMCPUID idCpu, unsigned
{
Vcpu_handler *vcpu_handler = lookup_vcpu_handler(idCpu);
Assert(vcpu_handler);
/*
char txt_name[32];
Genode::Thread_base::myself()->name(txt_name, sizeof(txt_name));
PINF("%s - wakeup - rip=%p", txt_name, __builtin_return_address(0));
*/
/* don't wake the currently running thread again */
if (vcpu_handler->utcb() == Genode::Thread::myself()->utcb())
return VINF_SUCCESS;
vcpu_handler->wake_up();
return VINF_SUCCESS;
}

View File

@ -17,7 +17,6 @@
/* Genode includes */
#include <base/log.h>
#include <base/semaphore.h>
#include <util/flex_iterator.h>
#include <util/touch.h>
#include <rom_session/connection.h>
@ -42,6 +41,8 @@
#include <VBox/vmm/pdmapi.h>
#include <iprt/time.h>
/* Genode's VirtualBox includes */
#include "sup.h"
@ -86,7 +87,6 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher<pthread>,
bool _irq_win;
unsigned int _cpu_id;
Genode::Semaphore _halt_sem;
unsigned int _last_inj_info;
unsigned int _last_inj_error;
@ -758,14 +758,18 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher<pthread>,
}
}
void halt()
void halt(Genode::uint64_t tsc_abs)
{
_halt_sem.down();
Assert(utcb() == Thread::myself()->utcb());
Genode::addr_t sem = native_thread().exc_pt_sel + Nova::SM_SEL_EC;
Nova::sm_ctrl(sem, Nova::SEMAPHORE_DOWNZERO, tsc_abs);
}
void wake_up()
{
_halt_sem.up();
Genode::addr_t sem = native_thread().exc_pt_sel + Nova::SM_SEL_EC;
Nova::sm_ctrl(sem, Nova::SEMAPHORE_UP);
}
int run_hw(PVMR0 pVMR0)