vancouver: Improve locking scheme

This patch replaces the error-prone manual locking with the use of the
'Synced_interface' for the motherboard and the VCPU dispatcher. It also
removes all globally visible locks. Locks are now explicitly passed to
subsystems when needed.
This commit is contained in:
Norman Feske 2013-05-16 23:32:27 +02:00
parent c48a7aa27f
commit 89d0e68983
10 changed files with 167 additions and 141 deletions

View File

@ -33,7 +33,6 @@
extern char _binary_mono_tff_start; extern char _binary_mono_tff_start;
Font default_font(&_binary_mono_tff_start); Font default_font(&_binary_mono_tff_start);
extern Genode::Lock global_lock;
using Genode::env; using Genode::env;
using Genode::Dataspace_client; using Genode::Dataspace_client;
@ -154,12 +153,6 @@ void Vancouver_console::entry()
{ {
Logging::printf("Hello, this is VancouverConsole.\n"); Logging::printf("Hello, this is VancouverConsole.\n");
/* register host operations */
_mb.bus_console.add(this, receive_static<MessageConsole>);
_mb.bus_memregion.add(this, receive_static<MessageMemRegion>);
/* create environment for input/output */
/* /*
* Init sessions to the required external services * Init sessions to the required external services
*/ */
@ -187,7 +180,7 @@ void Vancouver_console::entry()
*/ */
unsigned long count = 0; unsigned long count = 0;
bool revoked = false; bool revoked = false;
Vancouver_keyboard vkeyb(_mb); Vancouver_keyboard vkeyb(_motherboard);
Genode::uint64_t checksum1 = 0; Genode::uint64_t checksum1 = 0;
Genode::uint64_t checksum2 = 0; Genode::uint64_t checksum2 = 0;
@ -234,15 +227,13 @@ void Vancouver_console::entry()
/* if we copy the same data 10 times, unmap the text buffer from guest */ /* if we copy the same data 10 times, unmap the text buffer from guest */
if (unchanged == 10) { if (unchanged == 10) {
/* protect against thread interference */ Genode::Lock::Guard guard(_console_lock);
global_lock.lock();
env()->rm_session()->detach((void *)_guest_fb); env()->rm_session()->detach((void *)_guest_fb);
env()->rm_session()->attach_at(_fb_ds, (Genode::addr_t)_guest_fb); env()->rm_session()->attach_at(_fb_ds, (Genode::addr_t)_guest_fb);
unchanged = 0; unchanged = 0;
fb_active = false; fb_active = false;
global_lock.unlock();
Logging::printf("Deactivated text buffer loop.\n"); Logging::printf("Deactivated text buffer loop.\n");
} }
} else unchanged = 0; } else unchanged = 0;
@ -252,8 +243,7 @@ void Vancouver_console::entry()
if (!revoked) { if (!revoked) {
/* protect against thread interference */ Genode::Lock::Guard guard(_console_lock);
global_lock.lock();
env()->rm_session()->detach((void *)_guest_fb); env()->rm_session()->detach((void *)_guest_fb);
env()->rm_session()->attach_at(framebuffer.dataspace(), env()->rm_session()->attach_at(framebuffer.dataspace(),
@ -269,13 +259,11 @@ void Vancouver_console::entry()
} }
revoked = true; revoked = true;
global_lock.unlock();
} }
} }
framebuffer.refresh(0, 0, _fb_mode.width(), _fb_mode.height()); framebuffer.refresh(0, 0, _fb_mode.width(), _fb_mode.height());
timer.msleep(10); timer.msleep(100);
} }
for (int i = 0, num_ev = input.flush(); i < num_ev; i++) { for (int i = 0, num_ev = input.flush(); i < num_ev; i++) {
@ -284,7 +272,7 @@ void Vancouver_console::entry()
/* update mouse model (PS2) */ /* update mouse model (PS2) */
unsigned mouse = mouse_value(ev); unsigned mouse = mouse_value(ev);
MessageInput msg(0x10001, mouse); MessageInput msg(0x10001, mouse);
_mb.bus_input.send(msg); _motherboard()->bus_input.send(msg);
if (ev->type() == Input::Event::PRESS) { if (ev->type() == Input::Event::PRESS) {
if (ev->code() <= 0xee) { if (ev->code() <= 0xee) {
@ -301,11 +289,21 @@ void Vancouver_console::entry()
} }
Vancouver_console::Vancouver_console(Motherboard &mb, Genode::size_t vm_fb_size, void Vancouver_console::register_host_operations(Motherboard &motherboard)
{
motherboard.bus_console. add(this, receive_static<MessageConsole>);
motherboard.bus_memregion.add(this, receive_static<MessageMemRegion>);
}
Vancouver_console::Vancouver_console(Synced_motherboard &mb,
Genode::Lock &console_lock,
Genode::size_t vm_fb_size,
Genode::Dataspace_capability fb_ds) Genode::Dataspace_capability fb_ds)
: :
_startup_lock(Genode::Lock::LOCKED), _startup_lock(Genode::Lock::LOCKED),
_vm_fb_size(vm_fb_size), _mb(mb), _fb_size(0), _pixels(0), _guest_fb(0), _vm_fb_size(vm_fb_size), _motherboard(mb), _console_lock(console_lock),
_fb_size(0), _pixels(0), _guest_fb(0),
_regs(0), _fb_ds(fb_ds) _regs(0), _fb_ds(fb_ds)
{ {
start(); start();

View File

@ -29,8 +29,8 @@
#include <timer_session/connection.h> #include <timer_session/connection.h>
#include <dataspace/client.h> #include <dataspace/client.h>
/* NOVA userland includes */ /* local includes */
#include <nul/motherboard.h> #include <synced_motherboard.h>
/* includes for I/O */ /* includes for I/O */
#include <base/env.h> #include <base/env.h>
@ -47,13 +47,14 @@ class Vancouver_console : public Thread<8192>, public StaticReceiver<Vancouver_c
private: private:
Genode::Lock _startup_lock; Genode::Lock _startup_lock;
Motherboard &_mb; Synced_motherboard &_motherboard;
short *_pixels; Genode::Lock &_console_lock;
char *_guest_fb; short *_pixels;
char *_guest_fb;
unsigned long _fb_size; unsigned long _fb_size;
Genode::Dataspace_capability _fb_ds; Genode::Dataspace_capability _fb_ds;
Genode::size_t _vm_fb_size; Genode::size_t _vm_fb_size;
VgaRegs *_regs; VgaRegs *_regs;
Framebuffer::Mode _fb_mode; Framebuffer::Mode _fb_mode;
public: public:
@ -62,13 +63,17 @@ class Vancouver_console : public Thread<8192>, public StaticReceiver<Vancouver_c
bool receive(MessageConsole &msg); bool receive(MessageConsole &msg);
bool receive(MessageMemRegion &msg); bool receive(MessageMemRegion &msg);
void register_host_operations(Motherboard &);
/* initialisation */ /* initialisation */
void entry(); void entry();
/** /**
* Constructor * Constructor
*/ */
Vancouver_console(Motherboard &mb, Genode::size_t vm_fb_size, Vancouver_console(Synced_motherboard &,
Genode::Lock &console_lock,
Genode::size_t vm_fb_size,
Genode::Dataspace_capability fb_ds); Genode::Dataspace_capability fb_ds);
}; };

View File

@ -31,15 +31,13 @@
static Genode::Native_utcb utcb_backup; static Genode::Native_utcb utcb_backup;
extern Genode::Lock timeouts_lock;
Vancouver_disk::Vancouver_disk(Synced_motherboard &mb,
Vancouver_disk::Vancouver_disk(Motherboard &mb,
char * backing_store_base, char * backing_store_base,
char * backing_store_fb_base) char * backing_store_fb_base)
: :
_startup_lock(Genode::Lock::LOCKED), _startup_lock(Genode::Lock::LOCKED),
_mb(mb), _backing_store_base(backing_store_base), _motherboard(mb), _backing_store_base(backing_store_base),
_backing_store_fb_base(backing_store_fb_base) _backing_store_fb_base(backing_store_fb_base)
{ {
/* initialize struct with 0 size */ /* initialize struct with 0 size */
@ -53,13 +51,16 @@ Vancouver_disk::Vancouver_disk(Motherboard &mb,
} }
void Vancouver_disk::register_host_operations(Motherboard &motherboard)
{
motherboard.bus_disk.add(this, receive_static<MessageDisk>);
}
void Vancouver_disk::entry() void Vancouver_disk::entry()
{ {
Logging::printf("Hello, this is Vancouver_disk.\n"); Logging::printf("Hello, this is Vancouver_disk.\n");
/* attach to disk bus */
_mb.bus_disk.add(this, receive_static<MessageDisk>);
_startup_lock.unlock(); _startup_lock.unlock();
} }
@ -124,7 +125,7 @@ bool Vancouver_disk::receive(MessageDisk &msg)
if (!read && !_diskcon[msg.disknr].ops.supported(Block::Packet_descriptor::WRITE)) { if (!read && !_diskcon[msg.disknr].ops.supported(Block::Packet_descriptor::WRITE)) {
MessageDiskCommit ro(msg.disknr, msg.usertag, MessageDiskCommit ro(msg.disknr, msg.usertag,
MessageDisk::DISK_STATUS_DEVICE); MessageDisk::DISK_STATUS_DEVICE);
_mb.bus_diskcommit.send(ro); _motherboard()->bus_diskcommit.send(ro);
*Genode::Thread_base::myself()->utcb() = utcb_backup; *Genode::Thread_base::myself()->utcb() = utcb_backup;
return true; return true;
} }
@ -177,29 +178,26 @@ bool Vancouver_disk::receive(MessageDisk &msg)
if (!p.succeeded()) { if (!p.succeeded()) {
Logging::printf("Operation failed.\n"); Logging::printf("Operation failed.\n");
{ {
Genode::Lock::Guard guard(timeouts_lock);
MessageDiskCommit commit(msg.disknr, msg.usertag, MessageDiskCommit commit(msg.disknr, msg.usertag,
MessageDisk::DISK_STATUS_DEVICE); MessageDisk::DISK_STATUS_DEVICE);
_mb.bus_diskcommit.send(commit); _motherboard()->bus_diskcommit.send(commit);
break; break;
} }
} }
} }
{ {
Genode::Lock::Guard guard(timeouts_lock);
MessageDiskCommit commit(msg.disknr, msg.usertag, MessageDiskCommit commit(msg.disknr, msg.usertag,
MessageDisk::DISK_OK); MessageDisk::DISK_OK);
_mb.bus_diskcommit.send(commit); _motherboard()->bus_diskcommit.send(commit);
} }
} else { } else {
Logging::printf("Operation failed.\n"); Logging::printf("Operation failed.\n");
{ {
Genode::Lock::Guard guard(timeouts_lock);
MessageDiskCommit commit(msg.disknr, msg.usertag, MessageDiskCommit commit(msg.disknr, msg.usertag,
MessageDisk::DISK_STATUS_DEVICE); MessageDisk::DISK_STATUS_DEVICE);
_mb.bus_diskcommit.send(commit); _motherboard()->bus_diskcommit.send(commit);
} }
} }

View File

@ -29,8 +29,10 @@
#include <block_session/connection.h> #include <block_session/connection.h>
#include <util/string.h> #include <util/string.h>
/* local includes */
#include <synced_motherboard.h>
/* NOVA userland includes */ /* NOVA userland includes */
#include <nul/motherboard.h>
#include <host/dma.h> #include <host/dma.h>
static const bool read_only = false; static const bool read_only = false;
@ -48,17 +50,17 @@ class Vancouver_disk : public Genode::Thread<8192>, public StaticReceiver<Vancou
Genode::size_t blk_cnt; Genode::size_t blk_cnt;
} _diskcon[MAX_DISKS]; } _diskcon[MAX_DISKS];
Genode::Lock _startup_lock; Genode::Lock _startup_lock;
Motherboard &_mb; Synced_motherboard &_motherboard;
char *_backing_store_base; char *_backing_store_base;
char *_backing_store_fb_base; char *_backing_store_fb_base;
public: public:
/** /**
* Constructor * Constructor
*/ */
Vancouver_disk(Motherboard &mb, Vancouver_disk(Synced_motherboard &,
char * backing_store_base, char * backing_store_base,
char * backing_store_fb_base); char * backing_store_fb_base);
@ -67,6 +69,8 @@ class Vancouver_disk : public Genode::Thread<8192>, public StaticReceiver<Vancou
void entry(); void entry();
bool receive(MessageDisk &msg); bool receive(MessageDisk &msg);
void register_host_operations(Motherboard &);
}; };
#endif /* _DISK_H_ */ #endif /* _DISK_H_ */

View File

@ -25,11 +25,9 @@
#include <host/keyboard.h> #include <host/keyboard.h>
#include <nul/vcpu.h> #include <nul/vcpu.h>
extern Genode::Lock global_lock;
Vancouver_keyboard::Vancouver_keyboard(Synced_motherboard &mb)
Vancouver_keyboard::Vancouver_keyboard(Motherboard &mb) : _motherboard(mb), _flags(0) { }
: _mb(mb), _flags(0) { }
void Vancouver_keyboard::handle_keycode_press(unsigned keycode) void Vancouver_keyboard::handle_keycode_press(unsigned keycode)
@ -93,19 +91,18 @@ void Vancouver_keyboard::handle_keycode_press(unsigned keycode)
/* we send an empty event */ /* we send an empty event */
CpuEvent msg(VCpu::EVENT_DEBUG); CpuEvent msg(VCpu::EVENT_DEBUG);
for (VCpu *vcpu = _mb.last_vcpu; vcpu; vcpu=vcpu->get_last()) for (VCpu *vcpu = _motherboard()->last_vcpu; vcpu; vcpu=vcpu->get_last())
vcpu->bus_event.send(msg); vcpu->bus_event.send(msg);
} }
/* reset */ /* reset */
else if ((_flags & KBFLAG_LWIN) && orig_keycode == Input::KEY_END) { else if ((_flags & KBFLAG_LWIN) && orig_keycode == Input::KEY_END) {
Genode::Lock::Guard guard(global_lock);
Logging::printf("Reset VM\n"); Logging::printf("Reset VM\n");
MessageLegacy msg2(MessageLegacy::RESET, 0); MessageLegacy msg2(MessageLegacy::RESET, 0);
_mb.bus_legacy.send_fifo(msg2); _motherboard()->bus_legacy.send_fifo(msg2);
} }
else _mb.bus_input.send(msg); else _motherboard()->bus_input.send(msg);
_flags &= ~(KBFLAG_EXTEND0 | KBFLAG_RELEASE | KBFLAG_EXTEND1); _flags &= ~(KBFLAG_EXTEND0 | KBFLAG_RELEASE | KBFLAG_EXTEND1);
} }
@ -165,7 +162,7 @@ void Vancouver_keyboard::handle_keycode_release(unsigned keycode)
} }
MessageInput msg(0x10000, _flags | keycode); MessageInput msg(0x10000, _flags | keycode);
_mb.bus_input.send(msg); _motherboard()->bus_input.send(msg);
_flags &= ~(KBFLAG_EXTEND0 | KBFLAG_RELEASE | KBFLAG_EXTEND1); _flags &= ~(KBFLAG_EXTEND0 | KBFLAG_RELEASE | KBFLAG_EXTEND1);
} }

View File

@ -21,8 +21,8 @@
#ifndef _KEYBOARD_H_ #ifndef _KEYBOARD_H_
#define _KEYBOARD_H_ #define _KEYBOARD_H_
/* NOVA userland includes */ /* local includes */
#include <nul/motherboard.h> #include <synced_motherboard.h>
/* includes for I/O */ /* includes for I/O */
#include <base/env.h> #include <base/env.h>
@ -33,15 +33,15 @@ class Vancouver_keyboard
{ {
private: private:
Motherboard &_mb; Synced_motherboard &_motherboard;
unsigned _flags; unsigned _flags;
public: public:
/** /**
* Constructor * Constructor
*/ */
Vancouver_keyboard(Motherboard &mb); Vancouver_keyboard(Synced_motherboard &);
void handle_keycode_press(unsigned keycode); void handle_keycode_press(unsigned keycode);
void handle_keycode_release(unsigned keycode); void handle_keycode_release(unsigned keycode);

View File

@ -47,6 +47,7 @@
#include <nic_session/connection.h> #include <nic_session/connection.h>
#include <os/config.h> #include <os/config.h>
#include <os/alarm.h> #include <os/alarm.h>
#include <os/synced_interface.h>
#include <timer_session/connection.h> #include <timer_session/connection.h>
#include <nova_cpu_session/connection.h> #include <nova_cpu_session/connection.h>
#include <rtc_session/connection.h> #include <rtc_session/connection.h>
@ -60,6 +61,7 @@
#include <sys/hip.h> #include <sys/hip.h>
/* local includes */ /* local includes */
#include <synced_motherboard.h>
#include <device_model_registry.h> #include <device_model_registry.h>
#include <boot_module_provider.h> #include <boot_module_provider.h>
#include <console.h> #include <console.h>
@ -84,29 +86,23 @@ Genode::Lock *utcb_lock()
return &inst; return &inst;
} }
/**
* Semaphore used as global lock
*
* Used for startup synchronization and coarse-grained locking.
*/
Genode::Lock global_lock(Genode::Lock::LOCKED);
Genode::Lock timeouts_lock(Genode::Lock::UNLOCKED);
/* timer service */ /* timer service */
using Genode::Thread; using Genode::Thread;
using Genode::Alarm_scheduler; using Genode::Alarm_scheduler;
using Genode::Alarm; using Genode::Alarm;
typedef Genode::Synced_interface<TimeoutList<32, void> > Synced_timeout_list;
class Alarm_thread : Thread<4096>, public Alarm_scheduler class Alarm_thread : Thread<4096>, public Alarm_scheduler
{ {
private: private:
Timer::Connection _timer; Timer::Connection _timer;
Alarm::Time _curr_time; /* jiffies value */ Alarm::Time _curr_time; /* jiffies value */
Motherboard &_motherboard; Synced_motherboard &_motherboard;
TimeoutList<32, void> &_timeouts; Synced_timeout_list &_timeouts;
/** /**
* Thread entry function * Thread entry function
@ -114,27 +110,19 @@ class Alarm_thread : Thread<4096>, public Alarm_scheduler
void entry() void entry()
{ {
while (true) { while (true) {
unsigned long long now = _motherboard.clock()->time(); unsigned long long now = _motherboard()->clock()->time();
unsigned nr; unsigned nr;
timeouts_lock.lock(); while ((nr = _timeouts()->trigger(now))) {
while ((nr = _timeouts.trigger(now))) { MessageTimeout msg(nr, _timeouts()->timeout());
MessageTimeout msg(nr, _timeouts.timeout()); if (_timeouts()->cancel(nr) < 0)
if (_timeouts.cancel(nr) < 0)
Logging::printf("Timeout not cancelled.\n"); Logging::printf("Timeout not cancelled.\n");
timeouts_lock.unlock(); _motherboard()->bus_timeout.send(msg);
_motherboard.bus_timeout.send(msg);
timeouts_lock.lock();
} }
timeouts_lock.unlock();
_timer.usleep(1000); _timer.usleep(1000);
} }
} }
@ -144,11 +132,11 @@ class Alarm_thread : Thread<4096>, public Alarm_scheduler
/** /**
* Constructor * Constructor
*/ */
Alarm_thread(Motherboard &mb, TimeoutList<32, void> &timeouts) Alarm_thread(Synced_motherboard &mb, Synced_timeout_list &timeouts)
: _curr_time(0), _motherboard(mb), _timeouts(timeouts) { start(); } : _curr_time(0), _motherboard(mb), _timeouts(timeouts) { start(); }
Alarm::Time curr_time() { return _curr_time; } Alarm::Time curr_time() { return _curr_time; }
unsigned long long curr_time_long() { return _motherboard.clock()->time(); } unsigned long long curr_time_long() { return _motherboard()->clock()->time(); }
}; };
@ -354,7 +342,7 @@ class Vcpu_dispatcher : public Genode::Thread<STACK_SIZE>,
/** /**
* Pointer to corresponding VCPU model * Pointer to corresponding VCPU model
*/ */
VCpu * const _vcpu; Genode::Synced_interface<VCpu> _vcpu;
Vcpu_thread _vcpu_thread; Vcpu_thread _vcpu_thread;
@ -366,7 +354,7 @@ class Vcpu_dispatcher : public Genode::Thread<STACK_SIZE>,
/** /**
* Motherboard representing the inter-connections of all device models * Motherboard representing the inter-connections of all device models
*/ */
Motherboard &_motherboard; Synced_motherboard &_motherboard;
/*************** /***************
@ -413,12 +401,10 @@ class Vcpu_dispatcher : public Genode::Thread<STACK_SIZE>,
if (skip == SKIP) if (skip == SKIP)
_skip_instruction(msg); _skip_instruction(msg);
Genode::Lock::Guard guard(global_lock);
/** /**
* Send the message to the VCpu. * Send the message to the VCpu.
*/ */
if (!_vcpu->executor.send(msg, true)) if (!_vcpu()->executor.send(msg, true))
Logging::panic("nobody to execute %s at %x:%x\n", Logging::panic("nobody to execute %s at %x:%x\n",
__func__, msg.cpu->cs.sel, msg.cpu->eip); __func__, msg.cpu->cs.sel, msg.cpu->eip);
@ -427,7 +413,7 @@ class Vcpu_dispatcher : public Genode::Thread<STACK_SIZE>,
*/ */
if (msg.mtr_in & MTD_INJ && msg.type != CpuMessage::TYPE_CHECK_IRQ) { if (msg.mtr_in & MTD_INJ && msg.type != CpuMessage::TYPE_CHECK_IRQ) {
msg.type = CpuMessage::TYPE_CHECK_IRQ; msg.type = CpuMessage::TYPE_CHECK_IRQ;
if (!_vcpu->executor.send(msg, true)) if (!_vcpu()->executor.send(msg, true))
Logging::panic("nobody to execute %s at %x:%x\n", Logging::panic("nobody to execute %s at %x:%x\n",
__func__, msg.cpu->cs.sel, msg.cpu->eip); __func__, msg.cpu->cs.sel, msg.cpu->eip);
} }
@ -437,7 +423,7 @@ class Vcpu_dispatcher : public Genode::Thread<STACK_SIZE>,
*/ */
if (msg.mtr_out & MTD_INJ) { if (msg.mtr_out & MTD_INJ) {
msg.type = CpuMessage::TYPE_CALC_IRQWINDOW; msg.type = CpuMessage::TYPE_CALC_IRQWINDOW;
if (!_vcpu->executor.send(msg, true)) if (!_vcpu()->executor.send(msg, true))
Logging::panic("nobody to execute %s at %x:%x\n", Logging::panic("nobody to execute %s at %x:%x\n",
__func__, msg.cpu->cs.sel, msg.cpu->eip); __func__, msg.cpu->cs.sel, msg.cpu->eip);
} }
@ -510,7 +496,7 @@ class Vcpu_dispatcher : public Genode::Thread<STACK_SIZE>,
MessageMemRegion mem_region(vm_fault_addr >> PAGE_SIZE_LOG2); MessageMemRegion mem_region(vm_fault_addr >> PAGE_SIZE_LOG2);
if (!_motherboard.bus_memregion.send(mem_region, false) || if (!_motherboard()->bus_memregion.send(mem_region, false) ||
!mem_region.ptr) !mem_region.ptr)
return false; return false;
@ -564,7 +550,7 @@ class Vcpu_dispatcher : public Genode::Thread<STACK_SIZE>,
CpuMessage _win(CpuMessage::TYPE_CALC_IRQWINDOW, CpuMessage _win(CpuMessage::TYPE_CALC_IRQWINDOW,
static_cast<CpuState *>(utcb), utcb->mtd); static_cast<CpuState *>(utcb), utcb->mtd);
_win.mtr_out = MTD_INJ; _win.mtr_out = MTD_INJ;
if (!_vcpu->executor.send(_win, true)) if (!_vcpu()->executor.send(_win, true))
Logging::panic("nobody to execute %s at %x:%x\n", Logging::panic("nobody to execute %s at %x:%x\n",
__func__, utcb->cs.sel, utcb->eip); __func__, utcb->cs.sel, utcb->eip);
} }
@ -588,8 +574,7 @@ class Vcpu_dispatcher : public Genode::Thread<STACK_SIZE>,
port, &utcb->eax, utcb->mtd); port, &utcb->eax, utcb->mtd);
_skip_instruction(msg); _skip_instruction(msg);
{ {
Genode::Lock::Guard l(global_lock); if (!_vcpu()->executor.send(msg, true))
if (!_vcpu->executor.send(msg, true))
Logging::panic("nobody to execute %s at %x:%x\n", Logging::panic("nobody to execute %s at %x:%x\n",
__func__, msg.cpu->cs.sel, msg.cpu->eip); __func__, msg.cpu->cs.sel, msg.cpu->eip);
} }
@ -812,13 +797,14 @@ class Vcpu_dispatcher : public Genode::Thread<STACK_SIZE>,
public: public:
Vcpu_dispatcher(VCpu *vcpu, Vcpu_dispatcher(Genode::Lock &vcpu_lock,
VCpu *unsynchronized_vcpu,
Guest_memory &guest_memory, Guest_memory &guest_memory,
Motherboard &motherboard, Synced_motherboard &motherboard,
bool has_svm, bool has_svm,
bool has_vmx) bool has_vmx)
: :
_vcpu(vcpu), _vcpu(vcpu_lock, unsynchronized_vcpu),
_vcpu_thread("vCPU thread"), _vcpu_thread("vCPU thread"),
_guest_memory(guest_memory), _guest_memory(guest_memory),
_motherboard(motherboard) _motherboard(motherboard)
@ -949,7 +935,7 @@ class Vcpu_dispatcher : public Genode::Thread<STACK_SIZE>,
_vcpu_thread.start(sel_sm_ec() + 1); _vcpu_thread.start(sel_sm_ec() + 1);
/* handle cpuid overrides */ /* handle cpuid overrides */
vcpu->executor.add(this, receive_static<CpuMessage>); unsynchronized_vcpu->executor.add(this, receive_static<CpuMessage>);
} }
/** /**
@ -1029,8 +1015,12 @@ class Machine : public StaticReceiver<Machine>
Genode::Rom_connection _hip_rom; Genode::Rom_connection _hip_rom;
Hip * const _hip; Hip * const _hip;
Clock _clock; Clock _clock;
Motherboard _motherboard; Genode::Lock _motherboard_lock;
TimeoutList<32, void> _timeouts; Motherboard _unsynchronized_motherboard;
Synced_motherboard _motherboard;
Genode::Lock _timeouts_lock;
TimeoutList<32, void> _unsynchronized_timeouts;
Synced_timeout_list _timeouts;
Guest_memory &_guest_memory; Guest_memory &_guest_memory;
Boot_module_provider &_boot_modules; Boot_module_provider &_boot_modules;
Alarm_thread *_alarm_thread; Alarm_thread *_alarm_thread;
@ -1111,7 +1101,8 @@ class Machine : public StaticReceiver<Machine>
Logging::printf("OP_VCPU_CREATE_BACKEND\n"); Logging::printf("OP_VCPU_CREATE_BACKEND\n");
Vcpu_dispatcher *vcpu_dispatcher = Vcpu_dispatcher *vcpu_dispatcher =
new Vcpu_dispatcher(msg.vcpu, _guest_memory, new Vcpu_dispatcher(_motherboard_lock, msg.vcpu,
_guest_memory,
_motherboard, _motherboard,
_hip->has_feature_svm(), _hip->has_feature_vmx()); _hip->has_feature_svm(), _hip->has_feature_vmx());
@ -1137,11 +1128,11 @@ class Machine : public StaticReceiver<Machine>
if (verbose_debug) if (verbose_debug)
Logging::printf("OP_VCPU_BLOCK\n"); Logging::printf("OP_VCPU_BLOCK\n");
global_lock.unlock(); _motherboard_lock.unlock();
bool res = (Nova::sm_ctrl(msg.value, Nova::SEMAPHORE_DOWN) == 0); bool res = (Nova::sm_ctrl(msg.value, Nova::SEMAPHORE_DOWN) == 0);
if (verbose_debug) if (verbose_debug)
Logging::printf("woke up from vcpu sem, block on global_lock\n"); Logging::printf("woke up from vcpu sem, block on global_lock\n");
global_lock.lock(); _motherboard_lock.lock();
return res; return res;
} }
@ -1271,20 +1262,15 @@ class Machine : public StaticReceiver<Machine>
_alarm_thread = new Alarm_thread(_motherboard, _timeouts); _alarm_thread = new Alarm_thread(_motherboard, _timeouts);
} }
timeouts_lock.lock(); msg.nr = _timeouts()->alloc();
msg.nr = _timeouts.alloc();
timeouts_lock.unlock();
return true; return true;
case MessageTimer::TIMER_REQUEST_TIMEOUT: case MessageTimer::TIMER_REQUEST_TIMEOUT:
timeouts_lock.lock();
if (_timeouts.request(msg.nr, msg.abstime) < 0) if (_timeouts()->request(msg.nr, msg.abstime) < 0)
Logging::printf("Could not program timeout.\n"); Logging::printf("Could not program timeout.\n");
timeouts_lock.unlock();
return true; return true;
default: default:
@ -1304,14 +1290,14 @@ class Machine : public StaticReceiver<Machine>
Logging::printf("No RTC present, returning dummy time.\n"); Logging::printf("No RTC present, returning dummy time.\n");
msg.wallclocktime = msg.timestamp = 0; msg.wallclocktime = msg.timestamp = 0;
*Genode::Thread_base::myself()->utcb() = utcb_backup; *Genode::Thread_base::myself()->utcb() = utcb_backup;
return true; return true;
} }
} }
msg.wallclocktime = _rtc->get_current_time(); msg.wallclocktime = _rtc->get_current_time();
Logging::printf("Got time %llx\n", msg.wallclocktime); Logging::printf("Got time %llx\n", msg.wallclocktime);
msg.timestamp = _motherboard.clock()->clock(1000000U); msg.timestamp = _unsynchronized_motherboard.clock()->clock(1000000U);
*Genode::Thread_base::myself()->utcb() = utcb_backup; *Genode::Thread_base::myself()->utcb() = utcb_backup;
@ -1394,21 +1380,24 @@ class Machine : public StaticReceiver<Machine>
_hip_rom("hypervisor_info_page"), _hip_rom("hypervisor_info_page"),
_hip(Genode::env()->rm_session()->attach(_hip_rom.dataspace())), _hip(Genode::env()->rm_session()->attach(_hip_rom.dataspace())),
_clock(_hip->tsc_freq*1000), _clock(_hip->tsc_freq*1000),
_motherboard(&_clock, _hip), _motherboard_lock(Genode::Lock::LOCKED),
_unsynchronized_motherboard(&_clock, _hip),
_motherboard(_motherboard_lock, &_unsynchronized_motherboard),
_timeouts(_timeouts_lock, &_unsynchronized_timeouts),
_guest_memory(guest_memory), _guest_memory(guest_memory),
_boot_modules(boot_modules) _boot_modules(boot_modules)
{ {
_timeouts.init(); _timeouts()->init();
/* register host operations, called back by the VMM */ /* register host operations, called back by the VMM */
_motherboard.bus_hostop.add (this, receive_static<MessageHostOp>); _unsynchronized_motherboard.bus_hostop.add (this, receive_static<MessageHostOp>);
_motherboard.bus_disk.add (this, receive_static<MessageDisk>); _unsynchronized_motherboard.bus_disk.add (this, receive_static<MessageDisk>);
_motherboard.bus_timer.add (this, receive_static<MessageTimer>); _unsynchronized_motherboard.bus_timer.add (this, receive_static<MessageTimer>);
_motherboard.bus_time.add (this, receive_static<MessageTime>); _unsynchronized_motherboard.bus_time.add (this, receive_static<MessageTime>);
_motherboard.bus_network.add (this, receive_static<MessageNetwork>); _unsynchronized_motherboard.bus_network.add (this, receive_static<MessageNetwork>);
_motherboard.bus_hwpcicfg.add(this, receive_static<MessageHwPciConfig>); _unsynchronized_motherboard.bus_hwpcicfg.add(this, receive_static<MessageHwPciConfig>);
_motherboard.bus_acpi.add (this, receive_static<MessageAcpi>); _unsynchronized_motherboard.bus_acpi.add (this, receive_static<MessageAcpi>);
_motherboard.bus_legacy.add (this, receive_static<MessageLegacy>); _unsynchronized_motherboard.bus_legacy.add (this, receive_static<MessageLegacy>);
} }
@ -1472,7 +1461,7 @@ class Machine : public StaticReceiver<Machine>
* We never pass any argument string to a device model because * We never pass any argument string to a device model because
* it is not examined by the existing device models. * it is not examined by the existing device models.
*/ */
dmi->create(_motherboard, argv, "", 0); dmi->create(_unsynchronized_motherboard, argv, "", 0);
if (node.is_last()) if (node.is_last())
break; break;
@ -1485,7 +1474,7 @@ class Machine : public StaticReceiver<Machine>
void boot() void boot()
{ {
/* init VCPUs */ /* init VCPUs */
for (VCpu *vcpu = _motherboard.last_vcpu; vcpu; vcpu = vcpu->get_last()) { for (VCpu *vcpu = _unsynchronized_motherboard.last_vcpu; vcpu; vcpu = vcpu->get_last()) {
/* init CPU strings */ /* init CPU strings */
const char *short_name = "NOVA microHV"; const char *short_name = "NOVA microHV";
@ -1512,13 +1501,18 @@ class Machine : public StaticReceiver<Machine>
Logging::printf("RESET device state\n"); Logging::printf("RESET device state\n");
MessageLegacy msg2(MessageLegacy::RESET, 0); MessageLegacy msg2(MessageLegacy::RESET, 0);
_motherboard.bus_legacy.send_fifo(msg2); _unsynchronized_motherboard.bus_legacy.send_fifo(msg2);
global_lock.unlock();
Logging::printf("INIT done\n"); Logging::printf("INIT done\n");
_motherboard_lock.unlock();
} }
Motherboard& get_mb() { return _motherboard; } Synced_motherboard &motherboard() { return _motherboard; }
Motherboard &unsynchronized_motherboard() { return _unsynchronized_motherboard; }
Genode::Lock &motherboard_lock() { return _motherboard_lock; }
~Machine() ~Machine()
{ {
@ -1611,14 +1605,22 @@ int main(int argc, char **argv)
static Machine machine(boot_modules, guest_memory); static Machine machine(boot_modules, guest_memory);
Genode::Lock fb_lock;
/* create console thread */ /* create console thread */
Vancouver_console vcon(machine.get_mb(), fb_size, guest_memory.fb_ds()); Vancouver_console vcon(machine.motherboard(),
fb_lock,
fb_size, guest_memory.fb_ds());
vcon.register_host_operations(machine.unsynchronized_motherboard());
/* create disk thread */ /* create disk thread */
Vancouver_disk vdisk(machine.get_mb(), Vancouver_disk vdisk(machine.motherboard(),
guest_memory.backing_store_local_base(), guest_memory.backing_store_local_base(),
guest_memory.backing_store_fb_local_base()); guest_memory.backing_store_fb_local_base());
vdisk.register_host_operations(machine.unsynchronized_motherboard());
machine.setup_devices(Genode::config()->xml_node().sub_node("machine")); machine.setup_devices(Genode::config()->xml_node().sub_node("machine"));
Genode::printf("\n--- Booting VM ---\n"); Genode::printf("\n--- Booting VM ---\n");

View File

@ -24,8 +24,8 @@
extern const void * _forward_pkt; extern const void * _forward_pkt;
Vancouver_network::Vancouver_network(Motherboard &mb, Nic::Session * nic) Vancouver_network::Vancouver_network(Synced_motherboard &mb, Nic::Session *nic)
: _mb(mb), _nic(nic) : _motherboard(mb), _nic(nic)
{ {
start(); start();
} }
@ -42,7 +42,7 @@ void Vancouver_network::entry()
char * rx_content = _nic->rx()->packet_content(rx_packet); char * rx_content = _nic->rx()->packet_content(rx_packet);
_forward_pkt = rx_content; _forward_pkt = rx_content;
MessageNetwork msg((unsigned char *)rx_content, rx_packet.size(), 0); MessageNetwork msg((unsigned char *)rx_content, rx_packet.size(), 0);
_mb.bus_network.send(msg); _motherboard()->bus_network.send(msg);
_forward_pkt = 0; _forward_pkt = 0;
/* acknowledge received packet */ /* acknowledge received packet */

View File

@ -24,8 +24,8 @@
/* Genode includes */ /* Genode includes */
#include <nic_session/connection.h> #include <nic_session/connection.h>
/* NOVA userland includes */ /* local includes */
#include <nul/motherboard.h> #include <synced_motherboard.h>
using Genode::List; using Genode::List;
using Genode::Thread; using Genode::Thread;
@ -34,8 +34,8 @@ class Vancouver_network : public Thread<4096>
{ {
private: private:
Motherboard &_mb; Synced_motherboard &_motherboard;
Nic::Session *_nic; Nic::Session *_nic;
public: public:
@ -45,7 +45,7 @@ class Vancouver_network : public Thread<4096>
/** /**
* Constructor * Constructor
*/ */
Vancouver_network(Motherboard &mb, Nic::Session *nic); Vancouver_network(Synced_motherboard &, Nic::Session *);
}; };
#endif /* _NETWORK_H_ */ #endif /* _NETWORK_H_ */

View File

@ -0,0 +1,22 @@
/*
* \brief Synchronized access to Vancouver motherboard
* \author Norman Feske
* \date 2013-05-16
*/
/*
* Copyright (C) 2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _SYNCED_MOTHERBOARD_H_
#define _SYNCED_MOTHERBOARD_H_
#include <nul/motherboard.h>
#include <os/synced_interface.h>
typedef Genode::Synced_interface<Motherboard> Synced_motherboard;
#endif /* _SYNCED_MOTHERBOARD_H_ */