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 */
#include <base/printf.h>
#include <base/semaphore.h>
#include <timer_session/connection.h>
/* VirtualBox includes */
#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)
{
PWRN("%s unimplemented", __func__);

View File

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

View File

@ -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;

View File

@ -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();