diff --git a/repos/ports/src/virtualbox/accloff/sup.cc b/repos/ports/src/virtualbox/accloff/sup.cc index 097962cca..26abd29ee 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 9bb54525d..b54e706f9 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 a839e1089..96044a1f6 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 544405759..b2029feee 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();