os: enable smp support for ARM vmm

* Fix GIC model to support priority and cpu target settings correspondingly
* Fix semantic of SGIR register for GICv2
* Minor GIC model IRQ state fix
* Introduce synchronization for VirtIO and GIC models
* Enable multiple CPUs in test run-script for ARMv8

Fix #3926
This commit is contained in:
Stefan Kalkowski 2020-09-11 14:45:47 +02:00 committed by Christian Helmuth
parent 6be09a27ca
commit 429cd8d37a
14 changed files with 185 additions and 44 deletions

View File

@ -150,7 +150,7 @@ if { [have_spec arm_64] } {
if {![file exists bin/dtb]} { if {![file exists bin/dtb]} {
puts "Download device tree blob ..." puts "Download device tree blob ..."
exec >& /dev/null wget -c -O bin/dtb http://genode.org/files/release-20.02/dtb-arm64-virt exec >& /dev/null wget -c -O bin/dtb http://genode.org/files/release-20.11/dtb-arm64-virt-smp
} }
if {![file exists bin/initrd]} { if {![file exists bin/initrd]} {
@ -216,4 +216,4 @@ build_boot_image $boot_modules
# #
append qemu_args " -nographic " append qemu_args " -nographic "
run_genode_until "\[init -> vm\] .*sbin.*" 220 run_genode_until "\[init -> vm\] .*sbin.*" 220
exec rm bin/linux bin/dtb exec rm bin/linux bin/dtb bin/initrd

View File

@ -90,6 +90,7 @@ void Cpu_base::_handle_sync()
{ {
/* check device number*/ /* check device number*/
switch (Esr::Ec::get(_state.esr_el2)) { switch (Esr::Ec::get(_state.esr_el2)) {
case Esr::Ec::HVC_32: [[fallthrough]];
case Esr::Ec::HVC: case Esr::Ec::HVC:
_handle_hyper_call(); _handle_hyper_call();
break; break;
@ -137,6 +138,7 @@ void Cpu_base::_handle_hyper_call()
case Psci::PSCI_FEATURES: case Psci::PSCI_FEATURES:
_state.reg(0, Psci::NOT_SUPPORTED); _state.reg(0, Psci::NOT_SUPPORTED);
return; return;
case Psci::CPU_ON_32: [[fallthrough]];
case Psci::CPU_ON: case Psci::CPU_ON:
_vm.cpu((unsigned)_state.reg(1), [&] (Cpu & cpu) { _vm.cpu((unsigned)_state.reg(1), [&] (Cpu & cpu) {
cpu.state().ip = _state.reg(2); cpu.state().ip = _state.reg(2);

View File

@ -45,6 +45,7 @@ class Vmm::Cpu_base
enum { enum {
WFI = 0x1, WFI = 0x1,
MRC_MCR = 0x3, MRC_MCR = 0x3,
HVC_32 = 0x12,
HVC = 0x16, HVC = 0x16,
MRS_MSR = 0x18, MRS_MSR = 0x18,
DA = 0x24, DA = 0x24,
@ -219,6 +220,10 @@ class Vmm::Cpu_base
void _handle_data_abort(); void _handle_data_abort();
void _handle_hyper_call(); void _handle_hyper_call();
void _update_state(); void _update_state();
public:
Vm & vm() { return _vm; }
}; };
#endif /* _SRC__SERVER__VMM__CPU_BASE_H_ */ #endif /* _SRC__SERVER__VMM__CPU_BASE_H_ */

View File

@ -58,8 +58,9 @@ void Generic_timer::schedule_timeout()
} }
if (_enabled()) { if (_enabled()) {
if (_usecs_left()) { Genode::uint64_t usecs = _usecs_left();
_timeout.schedule(Genode::Microseconds(_usecs_left())); if (usecs) {
_timeout.schedule(Genode::Microseconds(usecs));
} else _handle_timeout(Genode::Duration(Genode::Microseconds(0))); } else _handle_timeout(Genode::Duration(Genode::Microseconds(0)));
} }
} }
@ -67,7 +68,7 @@ void Generic_timer::schedule_timeout()
void Generic_timer::cancel_timeout() void Generic_timer::cancel_timeout()
{ {
if (_timeout.scheduled()) _timeout.discard(); if (_timeout.scheduled()) { _timeout.discard(); }
} }

View File

@ -18,6 +18,13 @@
using Vmm::Gic; using Vmm::Gic;
using Register = Vmm::Mmio_register::Register; using Register = Vmm::Mmio_register::Register;
static Genode::Mutex & big_gic_lock()
{
static Genode::Mutex mutex;
return mutex;
}
bool Gic::Irq::enabled() const { return _enabled; } bool Gic::Irq::enabled() const { return _enabled; }
bool Gic::Irq::active() const { bool Gic::Irq::active() const {
@ -52,10 +59,10 @@ void Gic::Irq::disable()
void Gic::Irq::activate() void Gic::Irq::activate()
{ {
switch (_state) { switch (_state) {
case INACTIVE: return; case INACTIVE: _state = ACTIVE; return;
case PENDING: return; case PENDING: _state = ACTIVE_PENDING; return;
case ACTIVE_PENDING: _state = PENDING; return; case ACTIVE_PENDING: return;
case ACTIVE: _state = INACTIVE; return; case ACTIVE: return;
}; };
} }
@ -75,6 +82,8 @@ void Gic::Irq::assert()
{ {
if (pending()) return; if (pending()) return;
Genode::Mutex::Guard guard(big_gic_lock());
_state = PENDING; _state = PENDING;
_pending_list.insert(*this); _pending_list.insert(*this);
} }
@ -84,6 +93,8 @@ void Gic::Irq::deassert()
{ {
if (_state == INACTIVE) return; if (_state == INACTIVE) return;
Genode::Mutex::Guard guard(big_gic_lock());
_state = INACTIVE; _state = INACTIVE;
_pending_list.remove(this); _pending_list.remove(this);
if (_handler) _handler->eoi(); if (_handler) _handler->eoi();
@ -124,17 +135,17 @@ Gic::Irq::Irq(unsigned num, Type t, Irq::List & l)
void Gic::Irq::List::insert(Irq & irq) void Gic::Irq::List::insert(Irq & irq)
{ {
Irq * i = first(); Irq * i = first();
while (i && i->priority() < irq.priority() && i->next()) i = i->next(); while (i && i->priority() <= irq.priority() && i->next()) i = i->next();
Genode::List<Irq>::insert(&irq, i); Genode::List<Irq>::insert(&irq, i);
} }
Gic::Irq * Gic::Irq::List::highest_enabled() Gic::Irq * Gic::Irq::List::highest_enabled(unsigned cpu_id)
{ {
Irq * i = first(); for (Irq * i = first(); i; i = i->next()) {
while(i) { if (!i->enabled() || i->active()) { continue; }
if (i->enabled()) return i; if (cpu_id < ~0U && (i->target() != cpu_id)) { continue; }
i = i->next(); return i;
} }
return nullptr; return nullptr;
} }
@ -165,6 +176,8 @@ void Gic::Gicd_banked::handle_irq()
bool Gic::Gicd_banked::pending_irq() bool Gic::Gicd_banked::pending_irq()
{ {
Genode::Mutex::Guard guard(big_gic_lock());
if (_cpu.state().irqs.virtual_irq != SPURIOUS) return true; if (_cpu.state().irqs.virtual_irq != SPURIOUS) return true;
Irq * i = _gic._pending_list.highest_enabled(); Irq * i = _gic._pending_list.highest_enabled();
@ -202,6 +215,8 @@ Gic::Gicd_banked::Gicd_banked(Cpu_base & cpu, Gic & gic, Mmio_bus & bus)
Register Gic::Irq_reg::read(Address_range & access, Cpu & cpu) Register Gic::Irq_reg::read(Address_range & access, Cpu & cpu)
{ {
Genode::Mutex::Guard guard(big_gic_lock());
Register ret = 0; Register ret = 0;
Register bits_per_irq = size * 8 / irq_count; Register bits_per_irq = size * 8 / irq_count;
@ -214,6 +229,8 @@ Register Gic::Irq_reg::read(Address_range & access, Cpu & cpu)
void Gic::Irq_reg::write(Address_range & access, Cpu & cpu, Register value) void Gic::Irq_reg::write(Address_range & access, Cpu & cpu, Register value)
{ {
Genode::Mutex::Guard guard(big_gic_lock());
Register bits_per_irq = size * 8 / irq_count; Register bits_per_irq = size * 8 / irq_count;
Register irq_value_mask = (1<<bits_per_irq) - 1; Register irq_value_mask = (1<<bits_per_irq) - 1;
for (unsigned i = (access.start * 8) / bits_per_irq; for (unsigned i = (access.start * 8) / bits_per_irq;
@ -226,6 +243,50 @@ void Gic::Irq_reg::write(Address_range & access, Cpu & cpu, Register value)
unsigned Gic::version() { return _version; } unsigned Gic::version() { return _version; }
void Gic::Gicd_sgir::write(Address_range &, Cpu & cpu,
Mmio_register::Register value)
{
Target_filter::Target_type type =
(Target_filter::Target_type) Target_filter::get(value);
unsigned target_list = Target_list::get(value);
unsigned irq = Int_id::get(value);
for (unsigned i = 0; i <= Vm::last_cpu(); i++) {
switch (type) {
case Target_filter::MYSELF:
if (i != cpu.cpu_id()) { continue; }
break;
case Target_filter::ALL:
if (i == cpu.cpu_id()) { continue; }
break;
case Target_filter::LIST:
if (!(target_list & (1<<i))) { continue; }
break;
default:
continue;
};
cpu.vm().cpu(i, [&] (Cpu & c) {
c.gic().irq(irq).assert();
if (cpu.cpu_id() != c.cpu_id()) { cpu.recall(); }
});
}
}
Register Gic::Gicd_itargetr::read(Address_range & access, Cpu & cpu)
{
if (access.start < 0x20) { return (1 << cpu.cpu_id()) << 8; }
return Irq_reg::read(access, cpu);
}
void Gic::Gicd_itargetr::write(Address_range & access, Cpu & cpu, Register value)
{
if (access.start >= 0x20) { Irq_reg::write(access, cpu, value); }
}
Gic::Gic(const char * const name, Gic::Gic(const char * const name,
const Genode::uint64_t addr, const Genode::uint64_t addr,
const Genode::uint64_t size, const Genode::uint64_t size,

View File

@ -47,7 +47,7 @@ class Vmm::Gic : public Vmm::Mmio_device
struct List : Genode::List<Irq> struct List : Genode::List<Irq>
{ {
void insert(Irq & irq); void insert(Irq & irq);
Irq * highest_enabled(); Irq * highest_enabled(unsigned cpu_id = ~0U);
}; };
struct Irq_handler { struct Irq_handler {
@ -92,7 +92,7 @@ class Vmm::Gic : public Vmm::Mmio_device
Config _config { LEVEL }; Config _config { LEVEL };
unsigned _num { 0 }; unsigned _num { 0 };
Genode::uint8_t _prio { 0 }; Genode::uint8_t _prio { 0 };
Genode::uint8_t _target { 1 }; Genode::uint8_t _target { 0 };
List & _pending_list; List & _pending_list;
Irq_handler * _handler { nullptr }; Irq_handler * _handler { nullptr };
}; };
@ -382,6 +382,9 @@ class Vmm::Gic : public Vmm::Mmio_device
Register read(Irq & irq) { return irq.target(); } Register read(Irq & irq) { return irq.target(); }
void write(Irq & irq, Register v) { irq.target(v); } void write(Irq & irq, Register v) { irq.target(v); }
Register read(Address_range & access, Cpu&) override;
void write(Address_range & access, Cpu&, Register value) override;
Gicd_itargetr() Gicd_itargetr()
: Irq_reg("GICD_ITARGETSR", Mmio_register::RW, 0x800, 8, 1024) {} : Irq_reg("GICD_ITARGETSR", Mmio_register::RW, 0x800, 8, 1024) {}
} _itargetr; } _itargetr;
@ -398,14 +401,14 @@ class Vmm::Gic : public Vmm::Mmio_device
struct Gicd_sgir : Genode::Register<32>, Mmio_register struct Gicd_sgir : Genode::Register<32>, Mmio_register
{ {
struct Enable : Bitfield<0, 1> {}; struct Int_id : Bitfield<0, 4> {};
struct Disable : Bitfield<6, 1> {}; struct Target_list : Bitfield<16, 8> {};
struct Target_filter : Bitfield<24, 2> {
enum Target_type { LIST, ALL, MYSELF, INVALID };
};
void write(Address_range & access, Cpu & cpu, void write(Address_range & access, Cpu & cpu,
Mmio_register::Register value) override Mmio_register::Register value) override;
{
Genode::error("SGIR WRITE ", value);
}
Gicd_sgir() Gicd_sgir()
: Mmio_register("GICD_SGIR", Mmio_register::WO, 0xf00, 4, 0) {} : Mmio_register("GICD_SGIR", Mmio_register::WO, 0xf00, 4, 0) {}
@ -414,8 +417,10 @@ class Vmm::Gic : public Vmm::Mmio_device
struct Gicd_irouter : Irq_reg struct Gicd_irouter : Irq_reg
{ {
Register read(Irq &) { return 0x0; } // FIXME smp Register read(Irq &) { return 0x0; } /* FIXME affinity routing support */
void write(Irq &, Register) { }
void write(Irq & i, Register v) {
if (v) Genode::error("Affinity routing not supported ", i.number()); }
Gicd_irouter() Gicd_irouter()
: Irq_reg("GICD_IROUTER", Mmio_register::RW, 0x6100, 64, 1024) {} : Irq_reg("GICD_IROUTER", Mmio_register::RW, 0x6100, 64, 1024) {}

View File

@ -21,6 +21,7 @@ namespace Vmm {
PSCI_VERSION = 0x84000000, PSCI_VERSION = 0x84000000,
MIGRATE_INFO_TYPE = 0x84000006, MIGRATE_INFO_TYPE = 0x84000006,
PSCI_FEATURES = 0x8400000a, PSCI_FEATURES = 0x8400000a,
CPU_ON_32 = 0x84000003,
CPU_ON = 0xc4000003, CPU_ON = 0xc4000003,
}; };

View File

@ -186,4 +186,5 @@ Cpu::Cpu(Vm & vm,
{ {
_state.cpsr = 0x93; /* el1 mode and IRQs disabled */ _state.cpsr = 0x93; /* el1 mode and IRQs disabled */
_state.sctrl = 0xc50078; _state.sctrl = 0xc50078;
_state.vmpidr = (1UL << 31) | cpu_id();
} }

View File

@ -14,9 +14,18 @@
compatible = "arm,cortex-a15"; compatible = "arm,cortex-a15";
reg = <0x00>; reg = <0x00>;
device_type = "cpu"; device_type = "cpu";
enable-method = "psci";
}; };
}; };
psci {
compatible = "arm,psci-1.0";
method = "hvc";
cpu_suspend = <0xc4000001>;
cpu_off = <0xc4000002>;
cpu_on = <0xc4000003>;
};
timer { timer {
interrupts = <0x01 0x0d 0x04 0x01 0x0e 0x04 0x01 0x0b 0x04 0x01 0x0a 0x04>; interrupts = <0x01 0x0d 0x04 0x01 0x0e 0x04 0x01 0x0b 0x04 0x01 0x0a 0x04>;
compatible = "arm,armv7-timer"; compatible = "arm,armv7-timer";

View File

@ -46,7 +46,7 @@ namespace Vmm {
VTIMER_IRQ = 27, VTIMER_IRQ = 27,
MAX_CPUS = 1, MAX_CPUS = 4,
}; };
} }

View File

@ -4,39 +4,75 @@
compatible = "linux,dummy-virt"; compatible = "linux,dummy-virt";
#address-cells = <0x02>; #address-cells = <0x02>;
#size-cells = <0x02>; #size-cells = <0x02>;
interrupt-parent = <0x8001>; interrupt-parent = <&gic>;
cpus { cpus {
#address-cells = <0x01>; #address-cells = <0x01>;
#size-cells = <0x00>; #size-cells = <0x00>;
cpu@0 { cpu@0 {
compatible = "arm,cortex-a53"; compatible = "arm,cortex-a53";
reg = <0x00>; reg = <0x00>;
device_type = "cpu"; device_type = "cpu";
enable-method = "psci";
}; };
cpu@1 {
compatible = "arm,cortex-a53";
reg = <0x01>;
device_type = "cpu";
enable-method = "psci";
};
cpu@2 {
compatible = "arm,cortex-a53";
reg = <0x02>;
device_type = "cpu";
enable-method = "psci";
};
cpu@3 {
compatible = "arm,cortex-a53";
reg = <0x03>;
device_type = "cpu";
enable-method = "psci";
};
};
psci {
compatible = "arm,psci-1.0";
method = "hvc";
cpu_suspend = <0xc4000001>;
cpu_off = <0xc4000002>;
cpu_on = <0xc4000003>;
}; };
timer { timer {
interrupts = <0x01 0x0d 0x04 0x01 0x0e 0x04 0x01 0x0b 0x04 0x01 0x0a 0x04>; interrupts = <0x01 0x0d 0x04 0x01 0x0e 0x04 0x01 0x0b 0x04 0x01 0x0a 0x04>;
compatible = "arm,armv8-timer\0arm,armv7-timer"; compatible = "arm,armv8-timer", "arm,armv7-timer";
always-on; always-on;
}; };
apb-pclk { clocks {
compatible = "fixed-clock";
phandle = <0x8000>; #address-cells = <1>;
clock-output-names = "clk24mhz"; #size-cells = <0>;
clock-frequency = <0x16e3600>;
#clock-cells = <0x00>; clk_24mhz: clk@0 {
compatible = "fixed-clock";
clock-output-names = "clk24mhz";
clock-frequency = <0x16e3600>;
#clock-cells = <0x00>;
reg = <0>;
};
}; };
pl011@9000000 { pl011@9000000 {
interrupts = <0x00 0x01 0x04>; interrupts = <0x00 0x01 0x04>;
compatible = "arm,pl011\0arm,primecell"; compatible = "arm,pl011", "arm,primecell";
clock-names = "uartclk\0apb_pclk"; clock-names = "uartclk", "apb_pclk";
reg = <0x00 0x9000000 0x00 0x1000>; reg = <0x00 0x9000000 0x00 0x1000>;
clocks = <0x8000 0x8000>; clocks = <&clk_24mhz>, <&clk_24mhz>;
}; };
memory@40000000 { memory@40000000 {
@ -45,17 +81,17 @@
}; };
chosen { chosen {
/* bootargs = "rdinit=/bin/sh console=hvc0 earlycon=pl011,0x9000000"; */ /*bootargs = "rdinit=/bin/sh console=hvc0 earlycon=pl011,0x9000000";*/
bootargs = "init=/sbin/init ip=dhcp console=hvc0"; bootargs = "init=/sbin/init ip=dhcp console=hvc0";
linux,initrd-start = <0x42000000>; linux,initrd-start = <0x42000000>;
linux,initrd-end = <0x420aa539>; linux,initrd-end = <0x420aa539>;
stdout-path = "/pl011@9000000"; stdout-path = "/pl011@9000000";
}; };
intc@8000000 { gic: intc@8000000 {
compatible = "arm,gic-v3"; compatible = "arm,gic-v3";
phandle = <0x8001>; reg = <0x00 0x8000000 0x00 0x10000>,
reg = <0x00 0x8000000 0x00 0x10000 0x00 0x80a0000 0x00 0xf60000>; <0x00 0x80a0000 0x00 0xf60000>;
ranges; ranges;
#address-cells = <0x02>; #address-cells = <0x02>;
#redistributor-regions = <0x01>; #redistributor-regions = <0x01>;

View File

@ -32,6 +32,8 @@ class Vmm::Virtio_console : public Virtio_device
void _read() void _read()
{ {
Genode::Mutex::Guard guard(_mutex);
auto read = [&] (addr_t data, size_t size) auto read = [&] (addr_t data, size_t size)
{ {
if (!_terminal.avail()) return 0ul; if (!_terminal.avail()) return 0ul;
@ -61,6 +63,7 @@ class Vmm::Virtio_console : public Virtio_device
} }
Register _device_specific_features() { return 0; } Register _device_specific_features() { return 0; }
public: public:
Virtio_console(const char * const name, Virtio_console(const char * const name,

View File

@ -225,6 +225,7 @@ class Vmm::Virtio_device : public Vmm::Mmio_device
Genode::Constructible<Virtio_queue> _queue[NUM]; Genode::Constructible<Virtio_queue> _queue[NUM];
Gic::Irq &_irq; Gic::Irq &_irq;
Ram &_ram; Ram &_ram;
Genode::Mutex _mutex;
struct Dummy { struct Dummy {
Mmio_register regs[7]; Mmio_register regs[7];
@ -344,6 +345,7 @@ class Vmm::Virtio_device : public Vmm::Mmio_device
void write(Address_range&, Cpu&, Register reg) override void write(Address_range&, Cpu&, Register reg) override
{ {
Genode::Mutex::Guard guard(device.mutex());
if (reg >= device.NUM) return; if (reg >= device.NUM) return;
device._queue_select(reg); device._queue_select(reg);
} }
@ -359,6 +361,7 @@ class Vmm::Virtio_device : public Vmm::Mmio_device
void write(Address_range&, Cpu&, Register reg) override void write(Address_range&, Cpu&, Register reg) override
{ {
Genode::Mutex::Guard guard(device.mutex());
device._queue_data().num = Genode::min(reg, device._queue_data().num = Genode::min(reg,
device._reg_container.regs[6].value()); device._reg_container.regs[6].value());
} }
@ -374,11 +377,13 @@ class Vmm::Virtio_device : public Vmm::Mmio_device
Register read(Address_range&, Cpu&) override Register read(Address_range&, Cpu&) override
{ {
Genode::Mutex::Guard guard(device.mutex());
return device._queue_data().ready; return device._queue_data().ready;
} }
void write(Address_range&, Cpu&, Register reg) override void write(Address_range&, Cpu&, Register reg) override
{ {
Genode::Mutex::Guard guard(device.mutex());
bool construct = reg == 1 ? true : false; bool construct = reg == 1 ? true : false;
device._queue_data().ready = reg; device._queue_data().ready = reg;
device._queue_state(construct); device._queue_state(construct);
@ -395,6 +400,7 @@ class Vmm::Virtio_device : public Vmm::Mmio_device
void write(Address_range&, Cpu&, Register reg) override void write(Address_range&, Cpu&, Register reg) override
{ {
Genode::Mutex::Guard guard(device.mutex());
if (!device._queue[reg].constructed()) return; if (!device._queue[reg].constructed()) return;
device._notify(reg); device._notify(reg);
@ -411,6 +417,7 @@ class Vmm::Virtio_device : public Vmm::Mmio_device
void write(Address_range&, Cpu&, Register reg) override void write(Address_range&, Cpu&, Register reg) override
{ {
Genode::Mutex::Guard guard(device.mutex());
device._queue_data().descr_low = reg; device._queue_data().descr_low = reg;
} }
@ -425,6 +432,7 @@ class Vmm::Virtio_device : public Vmm::Mmio_device
void write(Address_range&, Cpu&, Register reg) override void write(Address_range&, Cpu&, Register reg) override
{ {
Genode::Mutex::Guard guard(device.mutex());
device._queue_data().descr_high = reg; device._queue_data().descr_high = reg;
} }
@ -439,6 +447,7 @@ class Vmm::Virtio_device : public Vmm::Mmio_device
void write(Address_range&, Cpu&, Register reg) override void write(Address_range&, Cpu&, Register reg) override
{ {
Genode::Mutex::Guard guard(device.mutex());
device._queue_data().driver_low = reg; device._queue_data().driver_low = reg;
} }
@ -453,6 +462,7 @@ class Vmm::Virtio_device : public Vmm::Mmio_device
void write(Address_range&, Cpu&, Register reg) override void write(Address_range&, Cpu&, Register reg) override
{ {
Genode::Mutex::Guard guard(device.mutex());
device._queue_data().driver_high = reg; device._queue_data().driver_high = reg;
} }
@ -467,6 +477,7 @@ class Vmm::Virtio_device : public Vmm::Mmio_device
void write(Address_range&, Cpu&, Register reg) override void write(Address_range&, Cpu&, Register reg) override
{ {
Genode::Mutex::Guard guard(device.mutex());
device._queue_data().device_low = reg; device._queue_data().device_low = reg;
} }
@ -481,6 +492,7 @@ class Vmm::Virtio_device : public Vmm::Mmio_device
void write(Address_range&, Cpu&, Register reg) override void write(Address_range&, Cpu&, Register reg) override
{ {
Genode::Mutex::Guard guard(device.mutex());
device._queue_data().device_high = reg; device._queue_data().device_high = reg;
} }
@ -507,6 +519,7 @@ class Vmm::Virtio_device : public Vmm::Mmio_device
void write(Address_range&, Cpu&, Register reg) override void write(Address_range&, Cpu&, Register reg) override
{ {
Genode::Mutex::Guard guard(device.mutex());
device._deassert_irq(); device._deassert_irq();
} }
@ -525,6 +538,8 @@ class Vmm::Virtio_device : public Vmm::Mmio_device
Mmio_bus &bus, Mmio_bus &bus,
Ram &ram, Ram &ram,
unsigned queue_size = 8); unsigned queue_size = 8);
Genode::Mutex & mutex() { return _mutex; }
}; };
#endif /* _VIRTIO_DEVICE_H_ */ #endif /* _VIRTIO_DEVICE_H_ */

View File

@ -109,6 +109,8 @@ class Vmm::Virtio_net : public Virtio_device
void _handle() void _handle()
{ {
Genode::Mutex::Guard guard(_mutex);
_rx(); _rx();
_tx(); _tx();
} }