vbox: replace alarm_timer thread with trigger_once

Instead of using the alarm_timer thread we use our own timer thread
that uses a kernel semaphore on Nova. On all other platforms a timer
connection and trigger_once is used.

Fixes #1727.
This commit is contained in:
Josef Söntgen 2015-09-25 14:54:34 +02:00 committed by Christian Helmuth
parent f7ad6cf4e6
commit f9a64b663c
4 changed files with 58 additions and 9 deletions

View File

@ -16,6 +16,7 @@
/* Genode includes */ /* Genode includes */
#include <base/printf.h> #include <base/printf.h>
#include <base/semaphore.h> #include <base/semaphore.h>
#include <timer_session/connection.h>
/* VirtualBox includes */ /* VirtualBox includes */
#include <VBox/vmm/vm.h> #include <VBox/vmm/vm.h>
@ -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) bool Vmm_memory::revoke_from_vm(Region *r)
{ {
PWRN("%s unimplemented", __func__); PWRN("%s unimplemented", __func__);

View File

@ -19,6 +19,7 @@
#include <rom_session/connection.h> #include <rom_session/connection.h>
#include <timer_session/connection.h> #include <timer_session/connection.h>
#include <os/attached_rom_dataspace.h> #include <os/attached_rom_dataspace.h>
#include <trace/timestamp.h>
#include <vmm/vcpu_thread.h> #include <vmm/vcpu_thread.h>
#include <vmm/vcpu_dispatcher.h> #include <vmm/vcpu_dispatcher.h>
@ -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) bool Vmm_memory::revoke_from_vm(Region *r)
{ {
Assert(r); Assert(r);

View File

@ -39,8 +39,7 @@ struct Attached_gip : Genode::Attached_ram_dataspace
enum { enum {
UPDATE_HZ = 100, /* Hz */ UPDATE_HZ = 1000,
/* Note: UPDATE_MS < 10ms is not supported by alarm timer, take care !*/
UPDATE_MS = 1000 / UPDATE_HZ, UPDATE_MS = 1000 / UPDATE_HZ,
UPDATE_NS = UPDATE_MS * 1000 * 1000, UPDATE_NS = UPDATE_MS * 1000 * 1000,
}; };
@ -49,9 +48,11 @@ enum {
PSUPGLOBALINFOPAGE g_pSUPGlobalInfoPage; 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 * 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. * read struct SUPGIPCPU description for more details.
*/ */
ASMAtomicIncU32(&cpu->u32TransactionId); ASMAtomicIncU32(&cpu->u32TransactionId);
return true;
} }
};
void entry() override { genode_update_tsc(update, UPDATE_MS * 1000); }
};
int SUPR3Init(PSUPDRVSESSION *ppSession) int SUPR3Init(PSUPDRVSESSION *ppSession)
@ -149,8 +149,7 @@ int SUPR3Init(PSUPDRVSESSION *ppSession)
cpu->idApic = 0; cpu->idApic = 0;
/* schedule periodic call of GIP update function */ /* schedule periodic call of GIP update function */
static Periodic_GIP alarm; static Periodic_gip periodic_gip;
Genode::Timeout_thread::alarm_timer()->schedule(&alarm, UPDATE_MS);
initialized = true; initialized = true;

View File

@ -35,6 +35,7 @@ bool create_emt_vcpu(pthread_t * pthread, size_t stack,
uint64_t genode_cpu_hz(); uint64_t genode_cpu_hz();
void genode_update_tsc(void (*update_func)(void), unsigned long update_us);
Genode::Cpu_session * get_vcpu_cpu_session(); Genode::Cpu_session * get_vcpu_cpu_session();