mirror of
https://github.com/genodelabs/genode.git
synced 2025-06-11 11:51:46 +00:00
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:
parent
6be09a27ca
commit
429cd8d37a
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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_ */
|
||||||
|
@ -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(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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) {}
|
||||||
|
@ -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,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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";
|
||||||
|
@ -46,7 +46,7 @@ namespace Vmm {
|
|||||||
|
|
||||||
VTIMER_IRQ = 27,
|
VTIMER_IRQ = 27,
|
||||||
|
|
||||||
MAX_CPUS = 1,
|
MAX_CPUS = 4,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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>;
|
||||||
|
@ -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,
|
||||||
|
@ -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_ */
|
||||||
|
@ -109,6 +109,8 @@ class Vmm::Virtio_net : public Virtio_device
|
|||||||
|
|
||||||
void _handle()
|
void _handle()
|
||||||
{
|
{
|
||||||
|
Genode::Mutex::Guard guard(_mutex);
|
||||||
|
|
||||||
_rx();
|
_rx();
|
||||||
_tx();
|
_tx();
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user