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:
parent
f7ad6cf4e6
commit
f9a64b663c
|
@ -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__);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user