diff --git a/repos/ports/src/virtualbox/accloff/sup.cc b/repos/ports/src/virtualbox/accloff/sup.cc
index 097962cca1..26abd29ee2 100644
--- a/repos/ports/src/virtualbox/accloff/sup.cc
+++ b/repos/ports/src/virtualbox/accloff/sup.cc
@@ -16,6 +16,7 @@
/* Genode includes */
#include
#include
+#include
/* VirtualBox includes */
#include
@@ -101,6 +102,27 @@ uint64_t genode_cpu_hz() {
}
+void genode_update_tsc(void (*update_func)(void), unsigned long update_us)
+{
+ using namespace Genode;
+
+ Timer::Connection timer;
+ Signal_context sig_ctx;
+ Signal_receiver sig_rec;
+ Signal_context_capability sig_cap = sig_rec.manage(&sig_ctx);
+
+ timer.sigh(sig_cap);
+ timer.trigger_once(update_us);
+
+ for (;;) {
+ Signal s = sig_rec.wait_for_signal();
+ update_func();
+
+ timer.trigger_once(update_us);
+ }
+}
+
+
bool Vmm_memory::revoke_from_vm(Region *r)
{
PWRN("%s unimplemented", __func__);
diff --git a/repos/ports/src/virtualbox/spec/nova/sup.cc b/repos/ports/src/virtualbox/spec/nova/sup.cc
index 9bb54525de..b54e706f97 100644
--- a/repos/ports/src/virtualbox/spec/nova/sup.cc
+++ b/repos/ports/src/virtualbox/spec/nova/sup.cc
@@ -19,6 +19,7 @@
#include
#include
#include
+#include
#include
#include
@@ -189,6 +190,32 @@ uint64_t genode_cpu_hz()
}
+void genode_update_tsc(void (*update_func)(void), unsigned long update_us)
+{
+ using namespace Genode;
+ using namespace Nova;
+
+ enum { TSC_FACTOR = 1000ULL };
+
+ Genode::addr_t sem = Thread_base::myself()->tid().exc_pt_sel + Nova::SM_SEL_EC;
+ unsigned long tsc_khz = (genode_cpu_hz() / 1000) / TSC_FACTOR;
+
+ Trace::Timestamp us_64 = update_us;
+
+ for (;;) {
+ update_func();
+
+ Trace::Timestamp now = Trace::timestamp();
+
+ /* block until timeout fires or it gets canceled */
+ unsigned long long tsc_absolute = now + us_64 * tsc_khz;
+ Genode::uint8_t res = sm_ctrl(sem, SEMAPHORE_DOWN, tsc_absolute);
+ if (res != Nova::NOVA_OK && res != Nova::NOVA_TIMEOUT)
+ nova_die();
+ }
+}
+
+
bool Vmm_memory::revoke_from_vm(Region *r)
{
Assert(r);
diff --git a/repos/ports/src/virtualbox/sup.cc b/repos/ports/src/virtualbox/sup.cc
index a839e1089e..96044a1f6a 100644
--- a/repos/ports/src/virtualbox/sup.cc
+++ b/repos/ports/src/virtualbox/sup.cc
@@ -39,8 +39,7 @@ struct Attached_gip : Genode::Attached_ram_dataspace
enum {
- UPDATE_HZ = 100, /* Hz */
- /* Note: UPDATE_MS < 10ms is not supported by alarm timer, take care !*/
+ UPDATE_HZ = 1000,
UPDATE_MS = 1000 / UPDATE_HZ,
UPDATE_NS = UPDATE_MS * 1000 * 1000,
};
@@ -49,9 +48,11 @@ enum {
PSUPGLOBALINFOPAGE g_pSUPGlobalInfoPage;
-class Periodic_GIP : public Genode::Alarm {
+struct Periodic_gip : public Genode::Thread<4096>
+{
+ Periodic_gip() : Thread("periodic_gip") { start(); }
- bool on_alarm(unsigned) override
+ static void update()
{
/**
* We're using rdtsc here since timer_session->elapsed_ms produces
@@ -98,11 +99,10 @@ class Periodic_GIP : public Genode::Alarm {
* read struct SUPGIPCPU description for more details.
*/
ASMAtomicIncU32(&cpu->u32TransactionId);
-
- return true;
}
-};
+ void entry() override { genode_update_tsc(update, UPDATE_MS * 1000); }
+};
int SUPR3Init(PSUPDRVSESSION *ppSession)
@@ -149,8 +149,7 @@ int SUPR3Init(PSUPDRVSESSION *ppSession)
cpu->idApic = 0;
/* schedule periodic call of GIP update function */
- static Periodic_GIP alarm;
- Genode::Timeout_thread::alarm_timer()->schedule(&alarm, UPDATE_MS);
+ static Periodic_gip periodic_gip;
initialized = true;
diff --git a/repos/ports/src/virtualbox/sup.h b/repos/ports/src/virtualbox/sup.h
index 5444057594..b2029feeee 100644
--- a/repos/ports/src/virtualbox/sup.h
+++ b/repos/ports/src/virtualbox/sup.h
@@ -35,6 +35,7 @@ bool create_emt_vcpu(pthread_t * pthread, size_t stack,
uint64_t genode_cpu_hz();
+void genode_update_tsc(void (*update_func)(void), unsigned long update_us);
Genode::Cpu_session * get_vcpu_cpu_session();