mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-18 10:46:25 +00:00
vmm: enable effective C++ error switch
Several explicit casts could not be avoided yet, due to the missing differentiation in between virtual and physical addresses that leads to casting problems when using 32-bit ARM, and because the MMIO register framework does not allow to return narrowed types of bitfields. Apart from that, this commit fixes a switch-case fallthrough error in Mmio_register::write. Fix genodelabs/genode#4770
This commit is contained in:
parent
adc594a7e6
commit
c5b9cabd89
@ -17,7 +17,7 @@ using Vmm::Address_range;
|
||||
|
||||
Address_range::Address_range(Genode::uint64_t start,
|
||||
Genode::uint64_t size)
|
||||
: start(start), size(size) { }
|
||||
: _start(start), _size(size) { }
|
||||
|
||||
|
||||
Address_range & Address_range::find(Address_range & bus_addr)
|
||||
@ -26,7 +26,7 @@ Address_range & Address_range::find(Address_range & bus_addr)
|
||||
return *this;
|
||||
|
||||
Address_range * ar =
|
||||
Avl_node<Address_range>::child(bus_addr.start > start);
|
||||
Avl_node<Address_range>::child(bus_addr._start > _start);
|
||||
if (!ar) throw Not_found(bus_addr);
|
||||
return ar->find(bus_addr);
|
||||
}
|
||||
|
@ -18,23 +18,36 @@
|
||||
#include <util/avl_tree.h>
|
||||
|
||||
namespace Vmm {
|
||||
using namespace Genode;
|
||||
|
||||
struct Address_range;
|
||||
class Address_space;
|
||||
}
|
||||
|
||||
|
||||
struct Vmm::Address_range : Genode::Avl_node<Address_range>
|
||||
class Vmm::Address_range : private Genode::Avl_node<Address_range>
|
||||
{
|
||||
Genode::uint64_t const start;
|
||||
Genode::uint64_t const size;
|
||||
private:
|
||||
|
||||
Address_range(Genode::uint64_t start,
|
||||
Genode::uint64_t size);
|
||||
uint64_t const _start;
|
||||
uint64_t const _size;
|
||||
|
||||
Genode::uint64_t end() const { return start + size; }
|
||||
friend class Avl_node<Address_range>;
|
||||
friend class Avl_tree<Address_range>;
|
||||
friend class Address_space;
|
||||
|
||||
public:
|
||||
|
||||
Address_range(uint64_t start,
|
||||
uint64_t size);
|
||||
virtual ~Address_range() {}
|
||||
|
||||
uint64_t start() const { return _start; }
|
||||
uint64_t size() const { return _size; }
|
||||
uint64_t end() const { return _start + _size; }
|
||||
|
||||
bool match(Address_range & other) const {
|
||||
return other.start >= start && other.end() <= end(); }
|
||||
return other._start >= _start && other.end() <= end(); }
|
||||
|
||||
Address_range & find(Address_range & bus_addr);
|
||||
|
||||
@ -46,8 +59,8 @@ struct Vmm::Address_range : Genode::Avl_node<Address_range>
|
||||
|
||||
void print(Genode::Output & out) const
|
||||
{
|
||||
Genode::print(out, "address=", Genode::Hex(start),
|
||||
" width=", Genode::Hex(size));
|
||||
Genode::print(out, "address=", Hex(_start),
|
||||
" width=", Hex(_size));
|
||||
}
|
||||
|
||||
/************************
|
||||
@ -55,7 +68,7 @@ struct Vmm::Address_range : Genode::Avl_node<Address_range>
|
||||
************************/
|
||||
|
||||
bool higher(Address_range * range) {
|
||||
return range->start > start; }
|
||||
return range->_start > _start; }
|
||||
};
|
||||
|
||||
|
||||
@ -63,7 +76,7 @@ class Vmm::Address_space
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::Avl_tree<Address_range> _tree;
|
||||
Avl_tree<Address_range> _tree {};
|
||||
|
||||
public:
|
||||
|
||||
|
@ -36,14 +36,24 @@ class Vmm::Config
|
||||
using Name = String<128>;
|
||||
using Arguments = String<512>;
|
||||
|
||||
struct Virtio_device : List_model<Virtio_device>::Element
|
||||
class Virtio_device : public List_model<Virtio_device>::Element
|
||||
{
|
||||
private:
|
||||
|
||||
Config & _config;
|
||||
|
||||
/**
|
||||
* Noncopyable
|
||||
*/
|
||||
Virtio_device(Virtio_device const &);
|
||||
Virtio_device &operator = (Virtio_device const &);
|
||||
|
||||
public:
|
||||
|
||||
enum Type { INVALID, CONSOLE, NET, BLOCK, GPU, INPUT };
|
||||
|
||||
enum { MMIO_SIZE = 0x200 };
|
||||
|
||||
Config & _config;
|
||||
|
||||
Virtio_device(Name & name, Type type, Config & config);
|
||||
~Virtio_device();
|
||||
|
||||
@ -60,8 +70,13 @@ class Vmm::Config
|
||||
{
|
||||
Bit_allocator<VIRTIO_IRQ_COUNT> _alloc {};
|
||||
|
||||
unsigned alloc() {
|
||||
return VIRTIO_IRQ_START + _alloc.alloc(); }
|
||||
unsigned alloc()
|
||||
{
|
||||
/* we assume that the max number of IRQs does fit unsigned */
|
||||
static_assert(VIRTIO_IRQ_COUNT < ~0U);
|
||||
return VIRTIO_IRQ_START + (unsigned)_alloc.alloc();
|
||||
}
|
||||
|
||||
void free(unsigned irq) {
|
||||
_alloc.free(VIRTIO_IRQ_START+irq); }
|
||||
};
|
||||
@ -77,7 +92,7 @@ class Vmm::Config
|
||||
unsigned _gic_version { 0 };
|
||||
Arguments _bootargs { };
|
||||
|
||||
List_model<Virtio_device> _model;
|
||||
List_model<Virtio_device> _model {};
|
||||
|
||||
struct Virtio_device_update_policy
|
||||
: List_model<Config::Virtio_device>::Update_policy
|
||||
|
@ -190,7 +190,7 @@ Cpu_base::Cpu_base(Vm & vm,
|
||||
Genode::Env & env,
|
||||
Genode::Heap & heap,
|
||||
Genode::Entrypoint & ep,
|
||||
short const id)
|
||||
unsigned id)
|
||||
: _vcpu_id(id),
|
||||
_vm(vm),
|
||||
_vm_session(vm_session),
|
||||
|
@ -35,11 +35,11 @@ class Vmm::Cpu_base
|
||||
|
||||
struct State : Genode::Vm_state
|
||||
{
|
||||
Genode::uint64_t reg(unsigned idx) const;
|
||||
void reg(unsigned idx, Genode::uint64_t v);
|
||||
addr_t reg(addr_t idx) const;
|
||||
void reg(addr_t idx, addr_t v);
|
||||
};
|
||||
|
||||
struct Esr : Genode::Register<32>
|
||||
struct Esr : Genode::Register<sizeof(addr_t)*8>
|
||||
{
|
||||
struct Ec : Bitfield<26, 6>
|
||||
{
|
||||
@ -62,7 +62,7 @@ class Vmm::Cpu_base
|
||||
Genode::Env & env,
|
||||
Genode::Heap & heap,
|
||||
Genode::Entrypoint & ep,
|
||||
short const cpu_id);
|
||||
unsigned cpu_id);
|
||||
|
||||
unsigned cpu_id() const;
|
||||
void run();
|
||||
@ -118,14 +118,23 @@ class Vmm::Cpu_base
|
||||
|
||||
protected:
|
||||
|
||||
class System_register : public Genode::Avl_node<System_register>
|
||||
class System_register : protected Genode::Avl_node<System_register>
|
||||
{
|
||||
private:
|
||||
|
||||
const Esr::access_t _encoding;
|
||||
const char * _name;
|
||||
const bool _writeable;
|
||||
Genode::uint64_t _value;
|
||||
uint64_t _value;
|
||||
|
||||
friend class Avl_node<System_register>;
|
||||
friend class Avl_tree<System_register>;
|
||||
|
||||
/*
|
||||
* Noncopyable
|
||||
*/
|
||||
System_register(System_register const &);
|
||||
System_register &operator = (System_register const &);
|
||||
|
||||
public:
|
||||
|
||||
@ -169,8 +178,10 @@ class Vmm::Cpu_base
|
||||
: System_register(0, crn, op1, crm, op2,
|
||||
name, writeable, v, tree) {}
|
||||
|
||||
virtual ~System_register() {}
|
||||
|
||||
const char * name() const { return _name; }
|
||||
const bool writeable() const { return _writeable; }
|
||||
bool writeable() const { return _writeable; }
|
||||
|
||||
System_register * find_by_encoding(Iss::access_t e)
|
||||
{
|
||||
@ -196,7 +207,7 @@ class Vmm::Cpu_base
|
||||
return (r->_encoding > _encoding); }
|
||||
};
|
||||
|
||||
short _vcpu_id;
|
||||
unsigned _vcpu_id;
|
||||
bool _active { true };
|
||||
Vm & _vm;
|
||||
Genode::Vm_connection & _vm_session;
|
||||
@ -205,7 +216,7 @@ class Vmm::Cpu_base
|
||||
Genode::Vm_connection::Exit_config _exit_config { };
|
||||
Genode::Vm_connection::Vcpu _vm_vcpu;
|
||||
State & _state;
|
||||
Genode::Avl_tree<System_register> _reg_tree;
|
||||
Genode::Avl_tree<System_register> _reg_tree {};
|
||||
|
||||
|
||||
/***********************
|
||||
|
@ -275,9 +275,9 @@ void Vmm::Fdt_generator::_generate_tree(uint32_t & off, Config const & config,
|
||||
node(Name("timer"), [&] ()
|
||||
{
|
||||
property(Name("compatible"),
|
||||
::Array<Name, 2>("arm,armv8-timer", "arm,armv7-timer"));
|
||||
::Array<Name, 2U>("arm,armv8-timer", "arm,armv7-timer"));
|
||||
property(Name("interrupts"),
|
||||
::Array<Value, 12>(GIC_PPI, 0xd, IRQ_TYPE_LEVEL_HIGH,
|
||||
::Array<Value, 12U>(GIC_PPI, 0xd, IRQ_TYPE_LEVEL_HIGH,
|
||||
GIC_PPI, 0xe, IRQ_TYPE_LEVEL_HIGH,
|
||||
GIC_PPI, 0xb, IRQ_TYPE_LEVEL_HIGH,
|
||||
GIC_PPI, 0xa, IRQ_TYPE_LEVEL_HIGH));
|
||||
@ -289,14 +289,14 @@ void Vmm::Fdt_generator::_generate_tree(uint32_t & off, Config const & config,
|
||||
property(Name("phandle"), Value(GIC));
|
||||
property(Name("compatible"),
|
||||
(gicv2) ? Name("arm,gic-400") : Name("arm,gic-v3"));
|
||||
property(Name("ranges"), ::Array<Value,0>());
|
||||
property(Name("interrupt-controller"), ::Array<Value,0>());
|
||||
property(Name("ranges"), ::Array<Value,0U>());
|
||||
property(Name("interrupt-controller"), ::Array<Value,0U>());
|
||||
property(Name("#address-cells"), Value(2));
|
||||
property(Name("#redistributor-regions"), Value(1));
|
||||
property(Name("#interrupt-cells"), Value(3));
|
||||
property(Name("#size-cells"), Value(2));
|
||||
property(Name("reg"),
|
||||
::Array<Value, 8>(0, GICD_MMIO_START, 0, GICD_MMIO_SIZE,
|
||||
::Array<Value, 8U>(0, GICD_MMIO_START, 0, GICD_MMIO_SIZE,
|
||||
0, (gicv2) ? GICC_MMIO_START : GICR_MMIO_START,
|
||||
0, (gicv2) ? GICC_MMIO_SIZE : GICR_MMIO_SIZE));
|
||||
});
|
||||
@ -320,19 +320,20 @@ void Vmm::Fdt_generator::_generate_tree(uint32_t & off, Config const & config,
|
||||
node(Name("pl011"), [&] ()
|
||||
{
|
||||
property(Name("compatible"),
|
||||
::Array<Name, 2>("arm,pl011", "arm,primecell"));
|
||||
::Array<Name, 2U>("arm,pl011", "arm,primecell"));
|
||||
property(Name("interrupts"),
|
||||
::Array<Value, 3>(GIC_SPI, PL011_IRQ-32, IRQ_TYPE_LEVEL_HIGH));
|
||||
property(Name("reg"), ::Array<Value, 4>(0, PL011_MMIO_START,
|
||||
property(Name("reg"), ::Array<Value, 4U>(0, PL011_MMIO_START,
|
||||
0, PL011_MMIO_SIZE));
|
||||
property(Name("clock-names"),
|
||||
::Array<Name, 2>("uartclk", "apb_pclk"));
|
||||
property(Name("clocks"), ::Array<Value, 2>(CLK, CLK));
|
||||
::Array<Name, 2U>("uartclk", "apb_pclk"));
|
||||
property(Name("clocks"), ::Array<Value, 2U>(CLK, CLK));
|
||||
});
|
||||
|
||||
node(Name("memory"), [&] ()
|
||||
{
|
||||
property(Name("reg"), ::Array<Value, 4>(0, RAM_START, 0, config.ram_size()));
|
||||
property(Name("reg"), ::Array<Value, 4U>(0, RAM_START, 0,
|
||||
(uint32_t)config.ram_size()));
|
||||
property(Name("device_type"), Name("memory"));
|
||||
});
|
||||
|
||||
@ -347,19 +348,20 @@ void Vmm::Fdt_generator::_generate_tree(uint32_t & off, Config const & config,
|
||||
/* we're sure that the initrd start address is wide below 4GB */
|
||||
uint32_t start = (uint32_t)((addr_t)initrd_start & 0xffffffff);
|
||||
property(Name("linux,initrd-start"), Value(start));
|
||||
property(Name("linux,initrd-end"), Value(start+initrd_size));
|
||||
property(Name("linux,initrd-end"), Value(start+(uint32_t)initrd_size));
|
||||
});
|
||||
|
||||
config.for_each_virtio_device([&] (Config::Virtio_device const & dev) {
|
||||
node(Name("virtio@", dev.mmio_start), [&] ()
|
||||
{
|
||||
property(Name("interrupts"),
|
||||
::Array<Value, 3>(GIC_SPI, dev.irq-32, IRQ_TYPE_EDGE_RISING));
|
||||
::Array<Value, 3U>(GIC_SPI, dev.irq-32U,
|
||||
IRQ_TYPE_EDGE_RISING));
|
||||
property(Name("compatible"), Name("virtio,mmio"));
|
||||
property(Name("dma-coherent"), ::Array<Value,0>());
|
||||
property(Name("dma-coherent"), ::Array<Value,0U>());
|
||||
property(Name("reg"),
|
||||
::Array<Value, 4>(0, (uint32_t)((addr_t)dev.mmio_start & 0xffffffff),
|
||||
0, (uint32_t)dev.mmio_size));
|
||||
::Array<Value, 4U>(0U, (uint32_t)((addr_t)dev.mmio_start & 0xffffffff),
|
||||
0U, (uint32_t)dev.mmio_size));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -205,10 +205,9 @@ Gic::Gicd_banked::Gicd_banked(Cpu_base & cpu, Gic & gic, Mmio_bus & bus)
|
||||
|
||||
if (gic.version() >= 3) {
|
||||
_rdist.construct(GICR_MMIO_START +
|
||||
(cpu.cpu_id()*0x20000), 0x20000,
|
||||
(cpu.cpu_id()*0x20000), 0x20000, bus,
|
||||
cpu.cpu_id(),
|
||||
(_gic._cpu_cnt-1) == cpu.cpu_id());
|
||||
bus.add(*_rdist);
|
||||
}
|
||||
}
|
||||
|
||||
@ -219,10 +218,9 @@ Register Gic::Irq_reg::read(Address_range & access, Cpu & cpu)
|
||||
|
||||
Register ret = 0;
|
||||
|
||||
Register bits_per_irq = size * 8 / irq_count;
|
||||
for (unsigned i = (access.start * 8) / bits_per_irq;
|
||||
i < ((access.start+access.size) * 8) / bits_per_irq; i++)
|
||||
ret |= read(cpu.gic().irq(i)) << ((i % (32/bits_per_irq) * bits_per_irq));
|
||||
for_range(access, [&] (unsigned i, Register bits_per_irq) {
|
||||
ret |= read(cpu.gic().irq((unsigned)i))
|
||||
<< ((i % (32/bits_per_irq) * bits_per_irq)); });
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -231,12 +229,10 @@ 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 irq_value_mask = (1<<bits_per_irq) - 1;
|
||||
for (unsigned i = (access.start * 8) / bits_per_irq;
|
||||
i < ((access.start+access.size) * 8) / bits_per_irq; i++)
|
||||
write(cpu.gic().irq(i), (value >> ((i % (32/bits_per_irq))*bits_per_irq))
|
||||
& irq_value_mask);
|
||||
for_range(access, [&] (unsigned i, Register bits_per_irq) {
|
||||
write(cpu.gic().irq((unsigned)i),
|
||||
(value >> ((i % (32/bits_per_irq))*bits_per_irq))
|
||||
& ((1<<bits_per_irq) - 1)); });
|
||||
}
|
||||
|
||||
|
||||
@ -246,10 +242,12 @@ 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);
|
||||
using Target_filter = Reg::Target_filter;
|
||||
|
||||
Target_filter::Target_type type = (Target_filter::Target_type)
|
||||
Target_filter::get((Reg::access_t)value);
|
||||
unsigned target_list = Reg::Target_list::get((Reg::access_t)value);
|
||||
unsigned irq = Reg::Int_id::get((Reg::access_t)value);
|
||||
|
||||
cpu.vm().for_each_cpu([&] (Cpu & c) {
|
||||
switch (type) {
|
||||
@ -277,14 +275,14 @@ void Gic::Gicd_sgir::write(Address_range &, Cpu & cpu,
|
||||
|
||||
Register Gic::Gicd_itargetr::read(Address_range & access, Cpu & cpu)
|
||||
{
|
||||
if (access.start < 0x20) { return (1 << cpu.cpu_id()) << 8; }
|
||||
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); }
|
||||
if (access.start() >= 0x20) { Irq_reg::write(access, cpu, value); }
|
||||
}
|
||||
|
||||
|
||||
@ -294,33 +292,15 @@ Gic::Gic(const char * const name,
|
||||
unsigned cpus,
|
||||
unsigned version,
|
||||
Genode::Vm_connection & vm,
|
||||
Mmio_bus & bus,
|
||||
Genode::Env & env)
|
||||
: Mmio_device(name, addr, size), _cpu_cnt(cpus), _version(version)
|
||||
Space & bus,
|
||||
Genode::Env &)
|
||||
:
|
||||
Mmio_device(name, addr, size, bus),
|
||||
_cpu_cnt(cpus),
|
||||
_version(version)
|
||||
{
|
||||
add(_ctrl);
|
||||
add(_typer);
|
||||
add(_iidr);
|
||||
add(_igroupr);
|
||||
add(_isenabler);
|
||||
add(_csenabler);
|
||||
add(_ispendr);
|
||||
add(_icpendr);
|
||||
add(_isactiver);
|
||||
add(_icactiver);
|
||||
add(_ipriorityr);
|
||||
add(_itargetr);
|
||||
add(_icfgr);
|
||||
add(_irouter);
|
||||
add(_sgir);
|
||||
|
||||
for (unsigned i = 0; i < (sizeof(Dummy::regs) / sizeof(Mmio_register)); i++)
|
||||
add(_reg_container.regs[i]);
|
||||
|
||||
for (unsigned i = 0; i < MAX_SPI; i++)
|
||||
_spi[i].construct(i+MAX_SGI+MAX_PPI, Irq::SPI, _pending_list);
|
||||
|
||||
bus.add(*this);
|
||||
|
||||
if (version < 3) vm.attach_pic(GICC_MMIO_START);
|
||||
}
|
||||
|
@ -50,10 +50,12 @@ class Vmm::Gic : public Vmm::Mmio_device
|
||||
Irq * highest_enabled(unsigned cpu_id = ~0U);
|
||||
};
|
||||
|
||||
struct Irq_handler {
|
||||
struct Irq_handler
|
||||
{
|
||||
virtual void eoi() {};
|
||||
virtual void enabled() {};
|
||||
virtual void disabled() {};
|
||||
virtual ~Irq_handler() {};
|
||||
};
|
||||
|
||||
enum Type { SGI, PPI, SPI };
|
||||
@ -101,8 +103,8 @@ class Vmm::Gic : public Vmm::Mmio_device
|
||||
{
|
||||
unsigned const irq_count;
|
||||
|
||||
virtual Register read(Irq & irq) { return 0; }
|
||||
virtual void write(Irq & irq, Register reg) { }
|
||||
virtual Register read(Irq &) { return 0; }
|
||||
virtual void write(Irq &, Register) { }
|
||||
|
||||
Register read(Address_range & access, Cpu&) override;
|
||||
void write(Address_range & access, Cpu&, Register value) override;
|
||||
@ -111,9 +113,21 @@ class Vmm::Gic : public Vmm::Mmio_device
|
||||
Mmio_register::Type type,
|
||||
Genode::uint64_t start,
|
||||
unsigned bits_per_irq,
|
||||
unsigned irq_count)
|
||||
: Mmio_register(name, type, start, bits_per_irq*irq_count/8),
|
||||
unsigned irq_count,
|
||||
Space & device)
|
||||
: Mmio_register(name, type, start, bits_per_irq*irq_count/8, device),
|
||||
irq_count(irq_count) {}
|
||||
|
||||
template <typename FN>
|
||||
void for_range(Address_range & access, FN const & fn)
|
||||
{
|
||||
Register bits_per_irq = size() * 8 / irq_count;
|
||||
for (Register i = (access.start() * 8) / bits_per_irq;
|
||||
i < ((access.start()+access.size()) * 8) / bits_per_irq; i++) {
|
||||
static_assert(MAX_IRQ < ~0U);
|
||||
if (i < MAX_IRQ) fn((unsigned)i, bits_per_irq);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class Gicd_banked
|
||||
@ -132,120 +146,140 @@ class Vmm::Gic : public Vmm::Mmio_device
|
||||
Gic & _gic;
|
||||
Genode::Constructible<Irq> _sgi[MAX_SGI];
|
||||
Genode::Constructible<Irq> _ppi[MAX_PPI];
|
||||
Irq::List _pending_list;
|
||||
Irq::List _pending_list {};
|
||||
|
||||
struct Redistributor : Mmio_device, Genode::Interface
|
||||
{
|
||||
unsigned cpu_id;
|
||||
bool last;
|
||||
Mmio_register gicr_ctlr { "GICR_CTLR", Mmio_register::RO,
|
||||
0x0, 4, 0b10010 };
|
||||
0x0, 4, registers(), 0b10010 };
|
||||
Mmio_register gicr_typer { "GICR_TYPER", Mmio_register::RO,
|
||||
0x8, 8,
|
||||
0x8, 8, registers(),
|
||||
(Genode::uint64_t)cpu_id<<32 |
|
||||
cpu_id<<8 | (last ? 1<<4 : 0) };
|
||||
Mmio_register gicr_waker { "GICR_WAKER", Mmio_register::RO,
|
||||
0x14, 4, 0 };
|
||||
0x14, 4, registers(), 0 };
|
||||
Mmio_register gicr_pidr2 { "GICR_PIDR2", Mmio_register::RO,
|
||||
0xffe8, 4, (3<<4) };
|
||||
0xffe8, 4, registers(), (3<<4) };
|
||||
Mmio_register gicr_igroupr0 { "GICR_IGROUPR0", Mmio_register::RO,
|
||||
0x10080, 4, 0 };
|
||||
0x10080, 4, registers(), 0 };
|
||||
|
||||
struct Gicr_isenabler0 : Irq_reg
|
||||
{
|
||||
Register read(Irq & irq) { return irq.enabled(); }
|
||||
void write(Irq & irq, Register v) { if (v) irq.enable(); }
|
||||
Register read(Irq & irq) override {
|
||||
return irq.enabled(); }
|
||||
|
||||
Gicr_isenabler0()
|
||||
: Irq_reg("GICR_ISENABLER0", Mmio_register::RW, 0x10100, 1, 32) {}
|
||||
} gicr_isenabler0;
|
||||
void write(Irq & irq, Register v) override {
|
||||
if (v) irq.enable(); }
|
||||
|
||||
Gicr_isenabler0(Space & device)
|
||||
: Irq_reg("GICR_ISENABLER0", Mmio_register::RW,
|
||||
0x10100, 1, 32, device) {}
|
||||
} gicr_isenabler0 { registers() };
|
||||
|
||||
struct Gicr_icenabler0 : Irq_reg
|
||||
{
|
||||
Register read(Irq & irq) { return irq.enabled(); }
|
||||
void write(Irq & irq, Register v) { if (v) irq.disable(); }
|
||||
Register read(Irq & irq) override {
|
||||
return irq.enabled(); }
|
||||
|
||||
Gicr_icenabler0()
|
||||
: Irq_reg("GICR_ICENABLER0", Mmio_register::RW, 0x10180, 1, 32) {}
|
||||
} gicr_icenabler0;
|
||||
void write(Irq & irq, Register v) override {
|
||||
if (v) irq.disable(); }
|
||||
|
||||
Gicr_icenabler0(Space & device)
|
||||
: Irq_reg("GICR_ICENABLER0", Mmio_register::RW,
|
||||
0x10180, 1, 32, device) {}
|
||||
} gicr_icenabler0 { registers() };
|
||||
|
||||
struct Gicr_ispendr0 : Irq_reg
|
||||
{
|
||||
Register read(Irq & irq) { return irq.pending(); }
|
||||
void write(Irq & irq, Register v) { if (v) irq.assert(); }
|
||||
Register read(Irq & irq) override {
|
||||
return irq.pending(); }
|
||||
|
||||
Gicr_ispendr0()
|
||||
: Irq_reg("GICR_ISPENDR0", Mmio_register::RW, 0x10200, 1, 32) {}
|
||||
} gicr_ispendr0;
|
||||
void write(Irq & irq, Register v) override {
|
||||
if (v) irq.assert(); }
|
||||
|
||||
Gicr_ispendr0(Space & device)
|
||||
: Irq_reg("GICR_ISPENDR0", Mmio_register::RW,
|
||||
0x10200, 1, 32, device) {}
|
||||
} gicr_ispendr0 { registers() };
|
||||
|
||||
struct Gicr_icpendr0 : Irq_reg
|
||||
{
|
||||
Register read(Irq & irq) { return irq.pending(); }
|
||||
void write(Irq & irq, Register v) { if (v) irq.deassert(); }
|
||||
Register read(Irq & irq) override {
|
||||
return irq.pending(); }
|
||||
|
||||
Gicr_icpendr0()
|
||||
: Irq_reg("GICR_ICPENDR0", Mmio_register::RW, 0x10280, 1, 32) {}
|
||||
} gicr_icpendr0;
|
||||
void write(Irq & irq, Register v) override {
|
||||
if (v) irq.deassert(); }
|
||||
|
||||
Gicr_icpendr0(Space & device)
|
||||
: Irq_reg("GICR_ICPENDR0", Mmio_register::RW,
|
||||
0x10280, 1, 32, device) {}
|
||||
} gicr_icpendr0 { registers() };
|
||||
|
||||
struct Gicr_isactiver0 : Irq_reg
|
||||
{
|
||||
Register read(Irq & irq) { return irq.active(); }
|
||||
void write(Irq & irq, Register v) { if (v) irq.activate(); }
|
||||
Register read(Irq & irq) override {
|
||||
return irq.active(); }
|
||||
|
||||
Gicr_isactiver0()
|
||||
: Irq_reg("GICR_ISACTIVER0", Mmio_register::RW, 0x10300, 1, 32) {}
|
||||
} gicr_isactiver0;
|
||||
void write(Irq & irq, Register v) override {
|
||||
if (v) irq.activate(); }
|
||||
|
||||
Gicr_isactiver0(Space & device)
|
||||
: Irq_reg("GICR_ISACTIVER0", Mmio_register::RW,
|
||||
0x10300, 1, 32, device) {}
|
||||
} gicr_isactiver0 { registers() };
|
||||
|
||||
struct Gicr_icactiver0 : Irq_reg
|
||||
{
|
||||
Register read(Irq & irq) { return irq.active(); }
|
||||
void write(Irq & irq, Register v) { if (v) irq.deactivate(); }
|
||||
Register read(Irq & irq) override {
|
||||
return irq.active(); }
|
||||
|
||||
Gicr_icactiver0()
|
||||
: Irq_reg("GICR_ICACTIVER0", Mmio_register::RW, 0x10380, 1, 32) {}
|
||||
} gicr_icactiver0;
|
||||
void write(Irq & irq, Register v) override {
|
||||
if (v) irq.deactivate(); }
|
||||
|
||||
Gicr_icactiver0(Space & device)
|
||||
: Irq_reg("GICR_ICACTIVER0", Mmio_register::RW,
|
||||
0x10380, 1, 32, device) {}
|
||||
} gicr_icactiver0 { registers() };
|
||||
|
||||
struct Gicr_ipriorityr : Irq_reg
|
||||
{
|
||||
Register read(Irq & irq) { return irq.priority(); }
|
||||
void write(Irq & irq, Register v) { irq.priority(v); }
|
||||
Register read(Irq & irq) override {
|
||||
return irq.priority(); }
|
||||
|
||||
Gicr_ipriorityr()
|
||||
: Irq_reg("GICR_IPRIORITYR", Mmio_register::RW, 0x10400, 8, 32) {}
|
||||
} gicr_ipriorityr;
|
||||
void write(Irq & irq, Register v) override {
|
||||
irq.priority((uint8_t)v); }
|
||||
|
||||
Gicr_ipriorityr(Space & device)
|
||||
: Irq_reg("GICR_IPRIORITYR", Mmio_register::RW,
|
||||
0x10400, 8, 32, device) {}
|
||||
} gicr_ipriorityr { registers() };
|
||||
|
||||
struct Gicr_icfgr : Irq_reg
|
||||
{
|
||||
Register read(Irq & irq) { return irq.level() ? 0 : 1; }
|
||||
void write(Irq & irq, Register v) { irq.level(!v); }
|
||||
Register read(Irq & irq) override {
|
||||
return irq.level() ? 0 : 1; }
|
||||
void write(Irq & irq, Register v) override {
|
||||
irq.level(!v); }
|
||||
|
||||
Gicr_icfgr()
|
||||
: Irq_reg("GICR_ICFGR", Mmio_register::RW, 0x10c00, 8, 32) {}
|
||||
} gicr_icfgr;
|
||||
Gicr_icfgr(Space & device)
|
||||
: Irq_reg("GICR_ICFGR", Mmio_register::RW,
|
||||
0x10c00, 8, 32, device) {}
|
||||
} gicr_icfgr { registers() };
|
||||
|
||||
Redistributor(const Genode::uint64_t addr,
|
||||
const Genode::uint64_t size,
|
||||
Space & bus,
|
||||
unsigned cpu_id,
|
||||
bool last)
|
||||
: Mmio_device("GICR", addr, size), cpu_id(cpu_id), last(last)
|
||||
{
|
||||
add(gicr_ctlr);
|
||||
add(gicr_typer);
|
||||
add(gicr_waker);
|
||||
add(gicr_pidr2);
|
||||
add(gicr_igroupr0);
|
||||
add(gicr_isenabler0);
|
||||
add(gicr_icenabler0);
|
||||
add(gicr_ispendr0);
|
||||
add(gicr_icpendr0);
|
||||
add(gicr_isactiver0);
|
||||
add(gicr_icactiver0);
|
||||
add(gicr_ipriorityr);
|
||||
add(gicr_icfgr);
|
||||
}
|
||||
:
|
||||
Mmio_device("GICR", addr, size, bus),
|
||||
cpu_id(cpu_id),
|
||||
last(last) { }
|
||||
};
|
||||
|
||||
Genode::Constructible<Redistributor> _rdist;
|
||||
Genode::Constructible<Redistributor> _rdist {};
|
||||
};
|
||||
|
||||
unsigned version();
|
||||
@ -256,7 +290,7 @@ class Vmm::Gic : public Vmm::Mmio_device
|
||||
unsigned cpus,
|
||||
unsigned version,
|
||||
Genode::Vm_connection & vm,
|
||||
Mmio_bus & bus,
|
||||
Space & bus,
|
||||
Genode::Env & env);
|
||||
|
||||
private:
|
||||
@ -264,167 +298,221 @@ class Vmm::Gic : public Vmm::Mmio_device
|
||||
friend struct Gicd_banked;
|
||||
|
||||
Genode::Constructible<Irq> _spi[MAX_SPI];
|
||||
Irq::List _pending_list;
|
||||
Irq::List _pending_list {};
|
||||
unsigned _cpu_cnt;
|
||||
unsigned _version;
|
||||
|
||||
struct Gicd_ctlr : Genode::Register<32>, Mmio_register
|
||||
struct Gicd_ctlr : Mmio_register
|
||||
{
|
||||
struct Reg : Genode::Register<32>
|
||||
{
|
||||
struct Enable : Bitfield<0, 1> {};
|
||||
struct Disable : Bitfield<6, 1> {};
|
||||
};
|
||||
|
||||
void write(Address_range & access, Cpu & cpu,
|
||||
Mmio_register::Register value) override
|
||||
{
|
||||
access_t v = value;
|
||||
Disable::set(v, 0);
|
||||
Reg::access_t v = (Reg::access_t)value;
|
||||
Reg::Disable::set(v, 0);
|
||||
Mmio_register::write(access, cpu, v);
|
||||
}
|
||||
|
||||
Gicd_ctlr()
|
||||
: Mmio_register("GICD_CTLR", Mmio_register::RW, 0, 4, 0) {}
|
||||
} _ctrl;
|
||||
Gicd_ctlr(Space & device)
|
||||
: Mmio_register("GICD_CTLR", Mmio_register::RW, 0, 4, device, 0) {}
|
||||
} _ctrl { registers() };
|
||||
|
||||
struct Gicd_typer : Genode::Register<32>, Mmio_register
|
||||
struct Gicd_typer : Mmio_register
|
||||
{
|
||||
struct Reg : Genode::Register<32>
|
||||
{
|
||||
struct It_lines_number : Bitfield<0, 5> {};
|
||||
struct Cpu_number : Bitfield<5, 3> {};
|
||||
struct Id_bits : Bitfield<19, 5> {};
|
||||
};
|
||||
|
||||
Gicd_typer(unsigned cpus)
|
||||
: Mmio_register("GICD_TYPER", Mmio_register::RO, 0x4, 4,
|
||||
It_lines_number::bits(31) |
|
||||
Cpu_number::bits(cpus-1) | Id_bits::bits(9)) {}
|
||||
} _typer { _cpu_cnt };
|
||||
Gicd_typer(Space & device, unsigned cpus)
|
||||
: Mmio_register("GICD_TYPER", Mmio_register::RO, 0x4, 4, device,
|
||||
Reg::It_lines_number::bits(31) |
|
||||
Reg::Cpu_number::bits(cpus-1) |
|
||||
Reg::Id_bits::bits(9)) {}
|
||||
} _typer { registers(), _cpu_cnt };
|
||||
|
||||
struct Gicd_iidr : Genode::Register<32>, Mmio_register
|
||||
struct Gicd_iidr : Mmio_register
|
||||
{
|
||||
struct Reg : Genode::Register<32>
|
||||
{
|
||||
struct Implementer : Bitfield<0, 12> {};
|
||||
struct Revision : Bitfield<12, 4> {};
|
||||
struct Variant : Bitfield<16, 4> {};
|
||||
struct Product_id : Bitfield<24, 8> {};
|
||||
};
|
||||
|
||||
Gicd_iidr()
|
||||
: Mmio_register("GICD_IIDR", Mmio_register::RO, 0x8, 4, 0x123) {}
|
||||
} _iidr;
|
||||
Gicd_iidr(Space & device)
|
||||
: Mmio_register("GICD_IIDR", Mmio_register::RO, 0x8, 4,
|
||||
device, 0x123) {}
|
||||
} _iidr { registers() };
|
||||
|
||||
struct Gicd_igroupr : Irq_reg
|
||||
{
|
||||
Gicd_igroupr()
|
||||
: Irq_reg("GICD_IGROUPR", Mmio_register::RW, 0x80, 1, 1024) {}
|
||||
} _igroupr;
|
||||
Gicd_igroupr(Space & device)
|
||||
: Irq_reg("GICD_IGROUPR", Mmio_register::RW, 0x80, 1,
|
||||
1024, device) {}
|
||||
} _igroupr { registers() };
|
||||
|
||||
struct Gicd_isenabler : Irq_reg
|
||||
{
|
||||
Register read(Irq & irq) { return irq.enabled(); }
|
||||
void write(Irq & irq, Register v) { if (v) irq.enable(); }
|
||||
Register read(Irq & irq) override {
|
||||
return irq.enabled(); }
|
||||
|
||||
Gicd_isenabler()
|
||||
: Irq_reg("GICD_ISENABLER", Mmio_register::RW, 0x100, 1, 1024) {}
|
||||
} _isenabler;
|
||||
void write(Irq & irq, Register v) override {
|
||||
if (v) irq.enable(); }
|
||||
|
||||
Gicd_isenabler(Space & device)
|
||||
: Irq_reg("GICD_ISENABLER", Mmio_register::RW, 0x100, 1,
|
||||
1024, device) {}
|
||||
} _isenabler { registers() };
|
||||
|
||||
struct Gicd_icenabler : Irq_reg
|
||||
{
|
||||
Register read(Irq & irq) { return irq.enabled(); }
|
||||
void write(Irq & irq, Register v) { if (v) irq.disable(); }
|
||||
Register read(Irq & irq) override {
|
||||
return irq.enabled(); }
|
||||
|
||||
Gicd_icenabler()
|
||||
: Irq_reg("GICD_ICENABLER", Mmio_register::RW, 0x180, 1, 1024) {}
|
||||
} _csenabler;
|
||||
void write(Irq & irq, Register v) override {
|
||||
if (v) irq.disable(); }
|
||||
|
||||
Gicd_icenabler(Space & device)
|
||||
: Irq_reg("GICD_ICENABLER", Mmio_register::RW, 0x180, 1,
|
||||
1024, device) {}
|
||||
} _csenabler { registers() };
|
||||
|
||||
struct Gicd_ispendr : Irq_reg
|
||||
{
|
||||
Register read(Irq & irq) { return irq.pending(); }
|
||||
void write(Irq & irq, Register v) { if (v) irq.assert(); }
|
||||
Register read(Irq & irq) override {
|
||||
return irq.pending(); }
|
||||
|
||||
Gicd_ispendr()
|
||||
: Irq_reg("GICD_ISPENDR", Mmio_register::RW, 0x200, 1, 1024) {}
|
||||
} _ispendr;
|
||||
void write(Irq & irq, Register v) override {
|
||||
if (v) irq.assert(); }
|
||||
|
||||
Gicd_ispendr(Space & device)
|
||||
: Irq_reg("GICD_ISPENDR", Mmio_register::RW, 0x200, 1,
|
||||
1024, device) {}
|
||||
} _ispendr { registers() };
|
||||
|
||||
struct Gicd_icpendr : Irq_reg
|
||||
{
|
||||
Register read(Irq & irq) { return irq.pending(); }
|
||||
void write(Irq & irq, Register v) { if (v) irq.deassert(); }
|
||||
Register read(Irq & irq) override {
|
||||
return irq.pending(); }
|
||||
|
||||
Gicd_icpendr()
|
||||
: Irq_reg("GICD_ICPENDR", Mmio_register::RW, 0x280, 1, 1024) {}
|
||||
} _icpendr;
|
||||
void write(Irq & irq, Register v) override {
|
||||
if (v) irq.deassert(); }
|
||||
|
||||
Gicd_icpendr(Space & device)
|
||||
: Irq_reg("GICD_ICPENDR", Mmio_register::RW, 0x280, 1,
|
||||
1024, device) {}
|
||||
} _icpendr { registers() };
|
||||
|
||||
struct Gicd_isactiver : Irq_reg
|
||||
{
|
||||
Register read(Irq & irq) { return irq.active(); }
|
||||
void write(Irq & irq, Register v) { if (v) irq.activate(); }
|
||||
Register read(Irq & irq) override {
|
||||
return irq.active(); }
|
||||
|
||||
Gicd_isactiver()
|
||||
: Irq_reg("GICD_ISACTIVER", Mmio_register::RW, 0x300, 1, 1024) {}
|
||||
} _isactiver;
|
||||
void write(Irq & irq, Register v) override {
|
||||
if (v) irq.activate(); }
|
||||
|
||||
Gicd_isactiver(Space & device)
|
||||
: Irq_reg("GICD_ISACTIVER", Mmio_register::RW, 0x300, 1,
|
||||
1024, device) {}
|
||||
} _isactiver { registers() };
|
||||
|
||||
struct Gicd_icactiver : Irq_reg
|
||||
{
|
||||
Register read(Irq & irq) { return irq.active(); }
|
||||
void write(Irq & irq, Register v) { if (v) irq.deactivate(); }
|
||||
Register read(Irq & irq) override {
|
||||
return irq.active(); }
|
||||
|
||||
Gicd_icactiver()
|
||||
: Irq_reg("GICD_ICACTIVER", Mmio_register::RW, 0x380, 1, 1024) {}
|
||||
} _icactiver;
|
||||
void write(Irq & irq, Register v) override {
|
||||
if (v) irq.deactivate(); }
|
||||
|
||||
Gicd_icactiver(Space & device)
|
||||
: Irq_reg("GICD_ICACTIVER", Mmio_register::RW, 0x380, 1,
|
||||
1024, device) {}
|
||||
} _icactiver { registers() };
|
||||
|
||||
struct Gicd_ipriorityr : Irq_reg
|
||||
{
|
||||
Register read(Irq & irq) { return irq.priority(); }
|
||||
void write(Irq & irq, Register v) { irq.priority(v); }
|
||||
Register read(Irq & irq) override {
|
||||
return irq.priority(); }
|
||||
|
||||
Gicd_ipriorityr()
|
||||
: Irq_reg("GICD_IPRIORITYR", Mmio_register::RW, 0x400, 8, 1024) {}
|
||||
} _ipriorityr;
|
||||
void write(Irq & irq, Register v) override {
|
||||
irq.priority((uint8_t)v); }
|
||||
|
||||
Gicd_ipriorityr(Space & device)
|
||||
: Irq_reg("GICD_IPRIORITYR", Mmio_register::RW, 0x400, 8,
|
||||
1024, device) {}
|
||||
} _ipriorityr { registers() };
|
||||
|
||||
struct Gicd_itargetr : Irq_reg
|
||||
{
|
||||
Register read(Irq & irq) { return irq.target(); }
|
||||
void write(Irq & irq, Register v) { irq.target(v); }
|
||||
Register read(Irq & irq) override {
|
||||
return irq.target(); }
|
||||
|
||||
void write(Irq & irq, Register v) override {
|
||||
irq.target((uint8_t)v); }
|
||||
|
||||
Register read(Address_range & access, Cpu&) override;
|
||||
void write(Address_range & access, Cpu&, Register value) override;
|
||||
|
||||
Gicd_itargetr()
|
||||
: Irq_reg("GICD_ITARGETSR", Mmio_register::RW, 0x800, 8, 1024) {}
|
||||
} _itargetr;
|
||||
Gicd_itargetr(Space & device)
|
||||
: Irq_reg("GICD_ITARGETSR", Mmio_register::RW, 0x800, 8,
|
||||
1024, device) {}
|
||||
} _itargetr { registers() };
|
||||
|
||||
|
||||
struct Gicd_icfgr : Irq_reg
|
||||
{
|
||||
Register read(Irq & irq) { return irq.level() ? 0 : 2; }
|
||||
void write(Irq & irq, Register v) { irq.level(!v); }
|
||||
Register read(Irq & irq) override {
|
||||
return irq.level() ? 0 : 2; }
|
||||
|
||||
Gicd_icfgr()
|
||||
: Irq_reg("GICD_ICFGR", Mmio_register::RW, 0xc00, 2, 1024) {}
|
||||
} _icfgr;
|
||||
void write(Irq & irq, Register v) override {
|
||||
irq.level(!v); }
|
||||
|
||||
struct Gicd_sgir : Genode::Register<32>, Mmio_register
|
||||
Gicd_icfgr(Space & device)
|
||||
: Irq_reg("GICD_ICFGR", Mmio_register::RW, 0xc00, 2,
|
||||
1024, device) {}
|
||||
} _icfgr { registers() };
|
||||
|
||||
struct Gicd_sgir : Mmio_register
|
||||
{
|
||||
struct Reg : Genode::Register<32>
|
||||
{
|
||||
struct Int_id : Bitfield<0, 4> {};
|
||||
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,
|
||||
Mmio_register::Register value) override;
|
||||
|
||||
Gicd_sgir()
|
||||
: Mmio_register("GICD_SGIR", Mmio_register::WO, 0xf00, 4, 0) {}
|
||||
} _sgir;
|
||||
Gicd_sgir(Space & device)
|
||||
: Mmio_register("GICD_SGIR", Mmio_register::WO, 0xf00, 4,
|
||||
device, 0) {}
|
||||
} _sgir { registers() };
|
||||
|
||||
|
||||
struct Gicd_irouter : Irq_reg
|
||||
{
|
||||
Register read(Irq &) { return 0x0; } /* FIXME affinity routing support */
|
||||
Register read(Irq &) override {
|
||||
return 0x0; } /* FIXME affinity routing support */
|
||||
|
||||
void write(Irq & i, Register v) {
|
||||
void write(Irq & i, Register v) override {
|
||||
if (v) Genode::error("Affinity routing not supported ", i.number()); }
|
||||
|
||||
Gicd_irouter()
|
||||
: Irq_reg("GICD_IROUTER", Mmio_register::RW, 0x6100, 64, 1024) {}
|
||||
} _irouter;
|
||||
Gicd_irouter(Space & device)
|
||||
: Irq_reg("GICD_IROUTER", Mmio_register::RW, 0x6100, 64,
|
||||
1024, device) {}
|
||||
} _irouter { registers() };
|
||||
|
||||
/**
|
||||
* FIXME: missing registers:
|
||||
@ -436,22 +524,14 @@ class Vmm::Gic : public Vmm::Mmio_device
|
||||
* GICD identification registers 0xfd0...
|
||||
*/
|
||||
|
||||
/**
|
||||
* Dummy container for holding array of noncopyable objects
|
||||
* Workaround for gcc bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70395
|
||||
*/
|
||||
struct Dummy {
|
||||
Mmio_register regs[8];
|
||||
} _reg_container { .regs = {
|
||||
{ "GICD_PIDR4", Mmio_register::RO, 0xffd0, 4, 0x0 },
|
||||
{ "GICD_PIDR5", Mmio_register::RO, 0xffd4, 4, 0x0 },
|
||||
{ "GICD_PIDR6", Mmio_register::RO, 0xffd8, 4, 0x0 },
|
||||
{ "GICD_PIDR7", Mmio_register::RO, 0xffdc, 4, 0x0 },
|
||||
{ "GICD_PIDR0", Mmio_register::RO, 0xffe0, 4, 0x492 },
|
||||
{ "GICD_PIDR1", Mmio_register::RO, 0xffe4, 4, 0xb0 },
|
||||
{ "GICD_PIDR2", Mmio_register::RO, 0xffe8, 4, (_version<<4) | 0xb },
|
||||
{ "GICD_PIDR3", Mmio_register::RO, 0xffec, 4, 0x44 }
|
||||
}};
|
||||
Mmio_register _pidr0 { "GICD_PIDR0", Mmio_register::RO, 0xffe0, 4, registers(), 0x492 };
|
||||
Mmio_register _pidr1 { "GICD_PIDR1", Mmio_register::RO, 0xffe4, 4, registers(), 0xb0 };
|
||||
Mmio_register _pidr2 { "GICD_PIDR2", Mmio_register::RO, 0xffe8, 4, registers(), (_version<<4) | 0xb };
|
||||
Mmio_register _pidr3 { "GICD_PIDR3", Mmio_register::RO, 0xffec, 4, registers(), 0x44 };
|
||||
Mmio_register _pidr4 { "GICD_PIDR4", Mmio_register::RO, 0xffd0, 4, registers(), 0x0 };
|
||||
Mmio_register _pidr5 { "GICD_PIDR5", Mmio_register::RO, 0xffd4, 4, registers(), 0x0 };
|
||||
Mmio_register _pidr6 { "GICD_PIDR6", Mmio_register::RO, 0xffd8, 4, registers(), 0x0 };
|
||||
Mmio_register _pidr7 { "GICD_PIDR7", Mmio_register::RO, 0xffdc, 4, registers(), 0x0 };
|
||||
};
|
||||
|
||||
#endif /* _SRC__SERVER__VMM__GIC_H_ */
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
using namespace Vmm;
|
||||
|
||||
Mmio_register::Register Mmio_register::read(Address_range & access, Cpu & cpu)
|
||||
Mmio_register::Register Mmio_register::read(Address_range & access, Cpu &)
|
||||
{
|
||||
if (_type == WO)
|
||||
throw Exception("Invalid read access to register ",
|
||||
@ -24,17 +24,17 @@ Mmio_register::Register Mmio_register::read(Address_range & access, Cpu & cpu)
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
switch (access.size) {
|
||||
case 1: return *(uint8_t*) ((addr_t)&_value + access.start);
|
||||
case 2: return *(uint16_t*) ((addr_t)&_value + access.start);
|
||||
case 4: return *(uint32_t*) ((addr_t)&_value + access.start);
|
||||
switch (access.size()) {
|
||||
case 1: return *(uint8_t*) ((addr_t)&_value + access.start());
|
||||
case 2: return *(uint16_t*) ((addr_t)&_value + access.start());
|
||||
case 4: return *(uint32_t*) ((addr_t)&_value + access.start());
|
||||
case 8: return _value;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Mmio_register::write(Address_range & access, Cpu & cpu, Register value)
|
||||
void Mmio_register::write(Address_range & access, Cpu &, Register value)
|
||||
{
|
||||
if (_type == RO)
|
||||
throw Exception("Invalid write access to register ",
|
||||
@ -42,10 +42,13 @@ void Mmio_register::write(Address_range & access, Cpu & cpu, Register value)
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
switch (access.size) {
|
||||
case 1: *((uint8_t*) ((addr_t)&_value + access.start)) = value;
|
||||
case 2: *((uint16_t*) ((addr_t)&_value + access.start)) = value;
|
||||
case 4: *((uint32_t*) ((addr_t)&_value + access.start)) = value;
|
||||
switch (access.size()) {
|
||||
case 1: *((uint8_t*) ((addr_t)&_value + access.start())) = (uint8_t) value;
|
||||
break;
|
||||
case 2: *((uint16_t*) ((addr_t)&_value + access.start())) = (uint16_t)value;
|
||||
break;
|
||||
case 4: *((uint32_t*) ((addr_t)&_value + access.start())) = (uint32_t)value;
|
||||
break;
|
||||
case 8: _value = value;
|
||||
}
|
||||
}
|
||||
@ -60,7 +63,7 @@ void Mmio_register::set(Register value) { _value = value; }
|
||||
Mmio_device::Register Mmio_device::read(Address_range & access, Cpu & cpu)
|
||||
{
|
||||
Mmio_register & reg = _registers.get<Mmio_register>(access);
|
||||
Address_range ar(access.start - reg.start, access.size);
|
||||
Address_range ar(access.start() - reg.start(), access.size());
|
||||
return reg.read(ar, cpu);
|
||||
}
|
||||
|
||||
@ -68,7 +71,7 @@ Mmio_device::Register Mmio_device::read(Address_range & access, Cpu & cpu)
|
||||
void Mmio_device::write(Address_range & access, Cpu & cpu, Register value)
|
||||
{
|
||||
Mmio_register & reg = _registers.get<Mmio_register>(access);
|
||||
Address_range ar(access.start - reg.start, access.size);
|
||||
Address_range ar(access.start() - reg.start(), access.size());
|
||||
reg.write(ar, cpu, value);
|
||||
}
|
||||
|
||||
@ -95,26 +98,29 @@ void Vmm::Mmio_bus::handle_memory_access(Vmm::Cpu & cpu)
|
||||
return Valid::get(v) && !Sign_extend::get(v); }
|
||||
|
||||
static bool write(access_t v) { return Write::get(v); }
|
||||
static unsigned r(access_t v) { return Register::get(v); }
|
||||
static addr_t r(access_t v) { return Register::get(v); }
|
||||
};
|
||||
|
||||
if (!Iss::valid(state.esr_el2))
|
||||
Iss::access_t iss = state.esr_el2;
|
||||
|
||||
if (!Iss::valid(iss))
|
||||
throw Exception("Mmio_bus: unknown ESR=", Genode::Hex(state.esr_el2));
|
||||
|
||||
bool wr = Iss::Write::get(state.esr_el2);
|
||||
unsigned idx = Iss::Register::get(state.esr_el2);
|
||||
bool wr = Iss::Write::get(iss);
|
||||
unsigned idx = (unsigned)Iss::Register::get(iss);
|
||||
uint64_t ipa = ((uint64_t)state.hpfar_el2 << 8)
|
||||
+ (state.far_el2 & ((1 << 12) - 1));
|
||||
uint64_t width = 1 << Iss::Access_size::get(state.esr_el2);
|
||||
uint64_t width = 1 << Iss::Access_size::get(iss);
|
||||
|
||||
try {
|
||||
Address_range bus_range(ipa, width);
|
||||
Mmio_device & dev = get<Mmio_device>(bus_range);
|
||||
Address_range dev_range(ipa - dev.start,width);
|
||||
Address_range dev_range(ipa - dev.start(), width);
|
||||
if (wr) {
|
||||
dev.write(dev_range, cpu, state.reg(idx));
|
||||
} else {
|
||||
state.reg(idx, dev.read(dev_range, cpu));
|
||||
/* on 32-bit ARM we do not support 64-bit data access */
|
||||
state.reg(idx, (addr_t)dev.read(dev_range, cpu));
|
||||
}
|
||||
} catch(Exception & e) {
|
||||
Genode::warning(e);
|
||||
|
@ -30,8 +30,9 @@ class Vmm::Mmio_register : public Vmm::Address_range
|
||||
|
||||
enum Type { RO, WO, RW };
|
||||
|
||||
using Name = Genode::String<64>;
|
||||
using Register = Genode::uint64_t;
|
||||
using Name = String<64>;
|
||||
using Register = uint64_t;
|
||||
using Space = Address_space;
|
||||
|
||||
virtual Register read(Address_range & access, Cpu&);
|
||||
virtual void write(Address_range & access, Cpu&, Register value);
|
||||
@ -40,13 +41,17 @@ class Vmm::Mmio_register : public Vmm::Address_range
|
||||
|
||||
Mmio_register(Name name,
|
||||
Type type,
|
||||
Genode::uint64_t start,
|
||||
Genode::uint64_t size,
|
||||
uint64_t start,
|
||||
uint64_t size,
|
||||
Space & device,
|
||||
Register reset_value = 0)
|
||||
: Address_range(start, size),
|
||||
_name(name),
|
||||
_type(type),
|
||||
_value(reset_value) { }
|
||||
_value(reset_value)
|
||||
{
|
||||
device.add(*this);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
@ -62,8 +67,18 @@ class Vmm::Mmio_device : public Vmm::Address_range
|
||||
{
|
||||
public:
|
||||
|
||||
using Name = Genode::String<64>;
|
||||
using Register = Genode::uint64_t;
|
||||
using Name = String<64>;
|
||||
using Register = uint64_t;
|
||||
using Space = Address_space;
|
||||
|
||||
private:
|
||||
|
||||
Name const _name;
|
||||
Address_space _registers {};
|
||||
|
||||
public:
|
||||
|
||||
Space & registers() { return _registers; }
|
||||
|
||||
virtual Register read(Address_range & access, Cpu&);
|
||||
virtual void write(Address_range & access, Cpu&, Register value);
|
||||
@ -71,14 +86,13 @@ class Vmm::Mmio_device : public Vmm::Address_range
|
||||
void add(Mmio_register & reg);
|
||||
|
||||
Mmio_device(Name name,
|
||||
Genode::uint64_t start,
|
||||
Genode::uint64_t size)
|
||||
: Address_range(start, size), _name(name) { }
|
||||
|
||||
private:
|
||||
|
||||
Name const _name;
|
||||
Address_space _registers;
|
||||
uint64_t start,
|
||||
uint64_t size,
|
||||
Space & bus)
|
||||
: Address_range(start, size), _name(name)
|
||||
{
|
||||
bus.add(*this);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
@ -54,7 +54,7 @@ Register Pl011::Uartmis::read(Address_range&, Cpu&)
|
||||
}
|
||||
|
||||
|
||||
void Pl011::Uarticr::write(Address_range & ar, Cpu &, Register value)
|
||||
void Pl011::Uarticr::write(Address_range &, Cpu &, Register value)
|
||||
{
|
||||
ris.set(ris.value() & ~value);
|
||||
}
|
||||
@ -80,23 +80,12 @@ Pl011::Pl011(const char * const name,
|
||||
const Genode::uint64_t size,
|
||||
unsigned irq,
|
||||
Cpu & cpu,
|
||||
Mmio_bus & bus,
|
||||
Space & bus,
|
||||
Genode::Env & env)
|
||||
: Mmio_device(name, addr, size),
|
||||
: Mmio_device(name, addr, size, bus),
|
||||
_terminal(env, "earlycon"),
|
||||
_handler(cpu, env.ep(), *this, &Pl011::_read),
|
||||
_irq(cpu.gic().irq(irq))
|
||||
{
|
||||
for (unsigned i = 0; i < (sizeof(Dummy::regs) / sizeof(Mmio_register)); i++)
|
||||
add(_reg_container.regs[i]);
|
||||
add(_uart_ris);
|
||||
add(_uart_dr);
|
||||
add(_uart_fr);
|
||||
add(_uart_imsc);
|
||||
add(_uart_mis);
|
||||
add(_uart_icr);
|
||||
|
||||
_terminal.read_avail_sigh(_handler);
|
||||
|
||||
bus.add(*this);
|
||||
}
|
||||
|
@ -40,9 +40,9 @@ class Vmm::Pl011 : public Vmm::Mmio_device
|
||||
Terminal::Connection _terminal;
|
||||
Cpu::Signal_handler<Pl011> _handler;
|
||||
Gic::Irq & _irq;
|
||||
Ring_buffer _rx_buf;
|
||||
Ring_buffer _rx_buf {};
|
||||
Mmio_register _uart_ris { "UARTRIS", Mmio_register::RO,
|
||||
0x3c, 2 };
|
||||
0x3c, 2, registers() };
|
||||
|
||||
/**
|
||||
* Dummy container for holding array of noncopyable objects
|
||||
@ -51,19 +51,19 @@ class Vmm::Pl011 : public Vmm::Mmio_device
|
||||
struct Dummy {
|
||||
Mmio_register regs[13];
|
||||
} _reg_container { .regs = {
|
||||
{ "UARTIBRD", Mmio_register::RW, 0x24, 2, 0 },
|
||||
{ "UARTFBRD", Mmio_register::RW, 0x28, 2, 0 },
|
||||
{ "UARTLCR_H", Mmio_register::RW, 0x2c, 2, 0 },
|
||||
{ "UARTCR", Mmio_register::RW, 0x30, 2, 0x300 },
|
||||
{ "UARTIFLS", Mmio_register::RW, 0x34, 2, 0x12 },
|
||||
{ "UARTPERIPHID0", Mmio_register::RO, 0xfe0, 4, 0x11 },
|
||||
{ "UARTPERIPHID1", Mmio_register::RO, 0xfe4, 4, 0x10 },
|
||||
{ "UARTPERIPHID2", Mmio_register::RO, 0xfe8, 4, 0x14 },
|
||||
{ "UARTPERIPHID3", Mmio_register::RO, 0xfec, 4, 0x0 },
|
||||
{ "UARTPCELLID0", Mmio_register::RO, 0xff0, 4, 0xd },
|
||||
{ "UARTPCELLID1", Mmio_register::RO, 0xff4, 4, 0xf0 },
|
||||
{ "UARTPCELLID2", Mmio_register::RO, 0xff8, 4, 0x5 },
|
||||
{ "UARTPCELLID3", Mmio_register::RO, 0xffc, 4, 0xb1 }
|
||||
{ "UARTIBRD", Mmio_register::RW, 0x24, 2, registers(), 0 },
|
||||
{ "UARTFBRD", Mmio_register::RW, 0x28, 2, registers(), 0 },
|
||||
{ "UARTLCR_H", Mmio_register::RW, 0x2c, 2, registers(), 0 },
|
||||
{ "UARTCR", Mmio_register::RW, 0x30, 2, registers(), 0x300 },
|
||||
{ "UARTIFLS", Mmio_register::RW, 0x34, 2, registers(), 0x12 },
|
||||
{ "UARTPERIPHID0", Mmio_register::RO, 0xfe0, 4, registers(), 0x11 },
|
||||
{ "UARTPERIPHID1", Mmio_register::RO, 0xfe4, 4, registers(), 0x10 },
|
||||
{ "UARTPERIPHID2", Mmio_register::RO, 0xfe8, 4, registers(), 0x14 },
|
||||
{ "UARTPERIPHID3", Mmio_register::RO, 0xfec, 4, registers(), 0x0 },
|
||||
{ "UARTPCELLID0", Mmio_register::RO, 0xff0, 4, registers(), 0xd },
|
||||
{ "UARTPCELLID1", Mmio_register::RO, 0xff4, 4, registers(), 0xf0 },
|
||||
{ "UARTPCELLID2", Mmio_register::RO, 0xff8, 4, registers(), 0x5 },
|
||||
{ "UARTPCELLID3", Mmio_register::RO, 0xffc, 4, registers(), 0xb1 }
|
||||
}};
|
||||
|
||||
struct Uartdr : Mmio_register
|
||||
@ -75,15 +75,19 @@ class Vmm::Pl011 : public Vmm::Mmio_device
|
||||
Register read(Address_range&, Cpu&) override;
|
||||
void write(Address_range&, Cpu&, Register) override;
|
||||
|
||||
Uartdr(Terminal::Connection & terminal,
|
||||
Uartdr(Space & device,
|
||||
Terminal::Connection & terminal,
|
||||
Ring_buffer & rx,
|
||||
Mmio_register & ris)
|
||||
: Mmio_register("UARTDR", Mmio_register::RW, 0x0, 2),
|
||||
:
|
||||
Mmio_register("UARTDR", Mmio_register::RW, 0x0, 2, device),
|
||||
terminal(terminal), rx(rx), ris(ris) {}
|
||||
} _uart_dr { _terminal, _rx_buf, _uart_ris };
|
||||
} _uart_dr { registers(), _terminal, _rx_buf, _uart_ris };
|
||||
|
||||
struct Uartfr : Mmio_register, Genode::Register<32>
|
||||
class Uartfr : public Mmio_register, protected Genode::Register<32>
|
||||
{
|
||||
public:
|
||||
|
||||
struct Rx_empty : Bitfield<4, 1> {};
|
||||
struct Rx_full : Bitfield<6, 1> {};
|
||||
|
||||
@ -91,9 +95,11 @@ class Vmm::Pl011 : public Vmm::Mmio_device
|
||||
|
||||
Mmio_register::Register read(Address_range&, Cpu&) override;
|
||||
|
||||
Uartfr(Ring_buffer & rx)
|
||||
: Mmio_register("UARTFR", Mmio_register::RO, 0x18, 4), rx(rx) {}
|
||||
} _uart_fr { _rx_buf };
|
||||
Uartfr(Space & device, Ring_buffer & rx)
|
||||
:
|
||||
Mmio_register("UARTFR", Mmio_register::RO, 0x18, 4, device),
|
||||
rx(rx) {}
|
||||
} _uart_fr { registers(), _rx_buf };
|
||||
|
||||
struct Uartimsc : Mmio_register
|
||||
{
|
||||
@ -102,10 +108,12 @@ class Vmm::Pl011 : public Vmm::Mmio_device
|
||||
|
||||
void write(Address_range&, Cpu&, Register) override;
|
||||
|
||||
Uartimsc(Gic::Irq & irq, Mmio_register & ris)
|
||||
: Mmio_register("UARTIMSC", Mmio_register::RW, 0x38, 2, 0xf),
|
||||
Uartimsc(Space & device, Gic::Irq & irq, Mmio_register & ris)
|
||||
:
|
||||
Mmio_register("UARTIMSC", Mmio_register::RW, 0x38, 2,
|
||||
device, 0xf),
|
||||
irq(irq), ris(ris) {}
|
||||
} _uart_imsc { _irq, _uart_ris };
|
||||
} _uart_imsc { registers(), _irq, _uart_ris };
|
||||
|
||||
struct Uartmis : Mmio_register
|
||||
{
|
||||
@ -114,10 +122,11 @@ class Vmm::Pl011 : public Vmm::Mmio_device
|
||||
|
||||
Register read(Address_range&, Cpu&) override;
|
||||
|
||||
Uartmis(Mmio_register & ris, Uartimsc & imsc)
|
||||
: Mmio_register("UARTMIS", Mmio_register::RO, 0x40, 2),
|
||||
Uartmis(Space & device, Mmio_register & ris, Uartimsc & imsc)
|
||||
:
|
||||
Mmio_register("UARTMIS", Mmio_register::RO, 0x40, 2, device),
|
||||
ris(ris), imsc(imsc) {}
|
||||
} _uart_mis { _uart_ris, _uart_imsc };
|
||||
} _uart_mis { registers(), _uart_ris, _uart_imsc };
|
||||
|
||||
struct Uarticr : Mmio_register
|
||||
{
|
||||
@ -125,9 +134,11 @@ class Vmm::Pl011 : public Vmm::Mmio_device
|
||||
|
||||
void write(Address_range&, Cpu&, Register) override;
|
||||
|
||||
Uarticr(Mmio_register & ris)
|
||||
: Mmio_register("UARTICR", Mmio_register::WO, 0x44, 2), ris(ris) {}
|
||||
} _uart_icr { _uart_ris };
|
||||
Uarticr(Space & device, Mmio_register & ris)
|
||||
:
|
||||
Mmio_register("UARTICR", Mmio_register::WO, 0x44, 2, device),
|
||||
ris(ris) {}
|
||||
} _uart_icr { registers(), _uart_ris };
|
||||
|
||||
void _read();
|
||||
|
||||
@ -138,7 +149,7 @@ class Vmm::Pl011 : public Vmm::Mmio_device
|
||||
const Genode::uint64_t size,
|
||||
unsigned irq,
|
||||
Cpu & cpu,
|
||||
Mmio_bus & bus,
|
||||
Space & bus,
|
||||
Genode::Env & env);
|
||||
};
|
||||
|
||||
|
@ -17,29 +17,30 @@
|
||||
using Vmm::Cpu_base;
|
||||
using Vmm::Cpu;
|
||||
using Vmm::Gic;
|
||||
using namespace Genode;
|
||||
|
||||
Genode::uint64_t Cpu_base::State::reg(unsigned idx) const
|
||||
addr_t Cpu_base::State::reg(addr_t idx) const
|
||||
{
|
||||
if (idx > 15) return 0;
|
||||
|
||||
Genode::uint32_t * r = (Genode::uint32_t*)this;
|
||||
addr_t * r = (addr_t*)this;
|
||||
r += idx;
|
||||
return *r;
|
||||
}
|
||||
|
||||
|
||||
void Cpu_base::State::reg(unsigned idx, Genode::uint64_t v)
|
||||
void Cpu_base::State::reg(addr_t idx, addr_t v)
|
||||
{
|
||||
if (idx > 15) return;
|
||||
|
||||
Genode::uint32_t * r = (Genode::uint32_t*)this;
|
||||
addr_t * r = (addr_t*)this;
|
||||
r += idx;
|
||||
*r = v;
|
||||
}
|
||||
|
||||
|
||||
Cpu_base::System_register::Iss::access_t
|
||||
Cpu_base::System_register::Iss::value(unsigned op0, unsigned crn, unsigned op1,
|
||||
Cpu_base::System_register::Iss::value(unsigned, unsigned crn, unsigned op1,
|
||||
unsigned crm, unsigned op2)
|
||||
{
|
||||
access_t v = 0;
|
||||
@ -63,7 +64,7 @@ Cpu_base::System_register::Iss::mask_encoding(access_t v)
|
||||
|
||||
void Cpu_base::_handle_brk()
|
||||
{
|
||||
Genode::error(__func__, " not implemented yet");
|
||||
error(__func__, " not implemented yet");
|
||||
}
|
||||
|
||||
|
||||
@ -85,8 +86,6 @@ void Cpu_base::handle_exception()
|
||||
|
||||
void Cpu_base::dump()
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
auto lambda = [] (unsigned i) {
|
||||
switch (i) {
|
||||
case 0: return "und";
|
||||
@ -127,7 +126,7 @@ void Cpu_base::dump()
|
||||
}
|
||||
|
||||
|
||||
void Cpu_base::initialize_boot(Genode::addr_t ip, Genode::addr_t dtb)
|
||||
void Cpu_base::initialize_boot(addr_t ip, addr_t dtb)
|
||||
{
|
||||
state().reg(1, 0xffffffff); /* invalid machine type */
|
||||
state().reg(2, dtb);
|
||||
@ -135,9 +134,9 @@ void Cpu_base::initialize_boot(Genode::addr_t ip, Genode::addr_t dtb)
|
||||
}
|
||||
|
||||
|
||||
Genode::addr_t Cpu::Ccsidr::read() const
|
||||
addr_t Cpu::Ccsidr::read() const
|
||||
{
|
||||
struct Csselr : Genode::Register<32>
|
||||
struct Csselr : Register<32>
|
||||
{
|
||||
struct Level : Bitfield<1, 4> {};
|
||||
};
|
||||
@ -147,7 +146,7 @@ Genode::addr_t Cpu::Ccsidr::read() const
|
||||
unsigned level = Csselr::Level::get(csselr.read());
|
||||
|
||||
if (level > 6) {
|
||||
Genode::warning("Invalid Csselr value!");
|
||||
warning("Invalid Csselr value!");
|
||||
return INVALID;
|
||||
}
|
||||
|
||||
@ -156,13 +155,13 @@ Genode::addr_t Cpu::Ccsidr::read() const
|
||||
|
||||
|
||||
Cpu::Cpu(Vm & vm,
|
||||
Genode::Vm_connection & vm_session,
|
||||
Vm_connection & vm_session,
|
||||
Mmio_bus & bus,
|
||||
Gic & gic,
|
||||
Genode::Env & env,
|
||||
Genode::Heap & heap,
|
||||
Genode::Entrypoint & ep,
|
||||
short const id)
|
||||
Env & env,
|
||||
Heap & heap,
|
||||
Entrypoint & ep,
|
||||
unsigned id)
|
||||
: Cpu_base(vm, vm_session, bus, gic, env, heap, ep, id),
|
||||
_sr_midr (0, 0, 0, 0, "MIDR", false, 0x412fc0f1, _reg_tree),
|
||||
_sr_mpidr (0, 0, 0, 5, "MPIDR", false, 1<<31|cpu_id(), _reg_tree),
|
||||
|
@ -29,7 +29,7 @@ class Vmm::Cpu : public Vmm::Cpu_base
|
||||
Genode::Env & env,
|
||||
Genode::Heap & heap,
|
||||
Genode::Entrypoint & ep,
|
||||
short cpu_id);
|
||||
unsigned cpu_id);
|
||||
|
||||
enum Exception_type {
|
||||
NO_EXCEPTION,
|
||||
|
@ -17,15 +17,16 @@
|
||||
using Vmm::Cpu_base;
|
||||
using Vmm::Cpu;
|
||||
using Vmm::Gic;
|
||||
using namespace Genode;
|
||||
|
||||
Genode::uint64_t Cpu_base::State::reg(unsigned idx) const
|
||||
addr_t Cpu_base::State::reg(addr_t idx) const
|
||||
{
|
||||
if (idx > 30) return 0;
|
||||
return r[idx];
|
||||
}
|
||||
|
||||
|
||||
void Cpu_base::State::reg(unsigned idx, Genode::uint64_t v)
|
||||
void Cpu_base::State::reg(addr_t idx, addr_t v)
|
||||
{
|
||||
if (idx > 30) return;
|
||||
r[idx] = v;
|
||||
@ -59,14 +60,16 @@ Cpu_base::System_register::Iss::mask_encoding(access_t v)
|
||||
|
||||
void Cpu_base::_handle_brk()
|
||||
{
|
||||
Genode::uint64_t offset = 0x0;
|
||||
addr_t offset = 0x0;
|
||||
if (!(_state.pstate & 0b100)) {
|
||||
offset = 0x400;
|
||||
} else if (_state.pstate & 0b1) {
|
||||
offset = 0x200;
|
||||
}
|
||||
_state.esr_el1 = _state.esr_el2;
|
||||
_state.spsr_el1 = _state.pstate;
|
||||
|
||||
/* only the below 32-bit of system register ESR_EL2 and PSTATE are used */
|
||||
_state.esr_el1 = (uint32_t)_state.esr_el2;
|
||||
_state.spsr_el1 = (uint32_t)_state.pstate;
|
||||
_state.elr_el1 = _state.ip;
|
||||
_state.ip = _state.vbar_el1 + offset;
|
||||
_state.pstate = 0b1111000101;
|
||||
@ -90,8 +93,6 @@ void Cpu_base::handle_exception()
|
||||
|
||||
void Cpu_base::dump()
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
auto lambda = [] (addr_t exc) {
|
||||
switch (exc) {
|
||||
case Cpu::AARCH64_SYNC: return "aarch64 sync";
|
||||
@ -123,7 +124,7 @@ void Cpu_base::dump()
|
||||
}
|
||||
|
||||
|
||||
Genode::addr_t Cpu::Ccsidr::read() const
|
||||
addr_t Cpu::Ccsidr::read() const
|
||||
{
|
||||
struct Clidr : Genode::Register<32>
|
||||
{
|
||||
@ -147,42 +148,42 @@ Genode::addr_t Cpu::Ccsidr::read() const
|
||||
|
||||
enum { INVALID = 0xffffffff };
|
||||
|
||||
unsigned level = Csselr::Level::get(csselr.read());
|
||||
bool instr = Csselr::Instr::get(csselr.read());
|
||||
unsigned level = Csselr::Level::get((Csselr::access_t)csselr.read());
|
||||
bool instr = Csselr::Instr::get((Csselr::access_t)csselr.read());
|
||||
|
||||
if (level > 6) {
|
||||
Genode::warning("Invalid Csselr value!");
|
||||
warning("Invalid Csselr value!");
|
||||
return INVALID;
|
||||
}
|
||||
|
||||
unsigned ce = Clidr::level(level, state.clidr_el1);
|
||||
unsigned ce = Clidr::level(level, (Clidr::access_t)state.clidr_el1);
|
||||
|
||||
if (ce == Clidr::NO_CACHE ||
|
||||
(ce == Clidr::DATA_CACHE_ONLY && instr)) {
|
||||
Genode::warning("Invalid Csselr value!");
|
||||
warning("Invalid Csselr value!");
|
||||
return INVALID;
|
||||
}
|
||||
|
||||
if (ce == Clidr::INSTRUCTION_CACHE_ONLY ||
|
||||
(ce == Clidr::SEPARATE_CACHE && instr)) {
|
||||
Genode::log("Return Ccsidr instr value ", state.ccsidr_inst_el1[level]);
|
||||
log("Return Ccsidr instr value ", state.ccsidr_inst_el1[level]);
|
||||
return state.ccsidr_inst_el1[level];
|
||||
}
|
||||
|
||||
Genode::log("Return Ccsidr value ", state.ccsidr_data_el1[level]);
|
||||
log("Return Ccsidr value ", state.ccsidr_data_el1[level]);
|
||||
return state.ccsidr_data_el1[level];
|
||||
}
|
||||
|
||||
|
||||
Genode::addr_t Cpu::Ctr_el0::read() const
|
||||
addr_t Cpu::Ctr_el0::read() const
|
||||
{
|
||||
Genode::addr_t ret;
|
||||
addr_t ret;
|
||||
asm volatile("mrs %0, ctr_el0" : "=r" (ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void Cpu::Icc_sgi1r_el1::write(Genode::addr_t v)
|
||||
void Cpu::Icc_sgi1r_el1::write(addr_t v)
|
||||
{
|
||||
|
||||
unsigned target_list = v & 0xffff;
|
||||
@ -197,7 +198,7 @@ void Cpu::Icc_sgi1r_el1::write(Genode::addr_t v)
|
||||
};
|
||||
|
||||
|
||||
void Cpu_base::initialize_boot(Genode::addr_t ip, Genode::addr_t dtb)
|
||||
void Cpu_base::initialize_boot(addr_t ip, addr_t dtb)
|
||||
{
|
||||
state().reg(0, dtb);
|
||||
state().ip = ip;
|
||||
@ -205,13 +206,13 @@ void Cpu_base::initialize_boot(Genode::addr_t ip, Genode::addr_t dtb)
|
||||
|
||||
|
||||
Cpu::Cpu(Vm & vm,
|
||||
Genode::Vm_connection & vm_session,
|
||||
Vm_connection & vm_session,
|
||||
Mmio_bus & bus,
|
||||
Gic & gic,
|
||||
Genode::Env & env,
|
||||
Genode::Heap & heap,
|
||||
Genode::Entrypoint & ep,
|
||||
short const id)
|
||||
Env & env,
|
||||
Heap & heap,
|
||||
Entrypoint & ep,
|
||||
unsigned id)
|
||||
: Cpu_base(vm, vm_session, bus, gic, env, heap, ep, id),
|
||||
_sr_id_aa64afr0_el1 (3, 0, 0, 5, 4, "ID_AA64AFR0_EL1", false, 0x0, _reg_tree),
|
||||
_sr_id_aa64afr1_el1 (3, 0, 0, 5, 5, "ID_AA64AFR1_EL1", false, 0x0, _reg_tree),
|
||||
|
@ -29,7 +29,7 @@ class Vmm::Cpu : public Vmm::Cpu_base
|
||||
Genode::Env & env,
|
||||
Genode::Heap & heap,
|
||||
Genode::Entrypoint & ep,
|
||||
short cpu_id);
|
||||
unsigned cpu_id);
|
||||
|
||||
enum Exception_type {
|
||||
AARCH64_SYNC = 0x400,
|
||||
@ -46,7 +46,7 @@ class Vmm::Cpu : public Vmm::Cpu_base
|
||||
private:
|
||||
|
||||
class Id_aa64pfr0 : public System_register,
|
||||
public Genode::Register<64>
|
||||
protected Genode::Register<64>
|
||||
{
|
||||
private:
|
||||
|
||||
|
@ -15,5 +15,3 @@ SRC_CC += virtio_gpu.cc
|
||||
INC_DIR += $(PRG_DIR)/../.. $(PRG_DIR)
|
||||
|
||||
vpath %.cc $(PRG_DIR)/../..
|
||||
|
||||
CC_CXX_WARN_STRICT :=
|
||||
|
@ -33,7 +33,7 @@ class Vmm::Virtio_block_queue : public Virtio_split_queue
|
||||
{
|
||||
private:
|
||||
|
||||
Ring_index _used_idx;
|
||||
Ring_index _used_idx {};
|
||||
|
||||
friend class Virtio_block_request;
|
||||
friend class Virtio_block_device;
|
||||
@ -103,7 +103,7 @@ class Vmm::Virtio_block_request
|
||||
|
||||
template <typename T>
|
||||
T * _desc_addr(Descriptor const & desc) const {
|
||||
return (T*) _ram.local_address(desc.address(),
|
||||
return (T*) _ram.local_address((addr_t)desc.address(),
|
||||
desc.length()); }
|
||||
|
||||
Index _request_idx;
|
||||
@ -193,7 +193,7 @@ class Vmm::Virtio_block_device
|
||||
_block.update_jobs(*this);
|
||||
}
|
||||
|
||||
void _notify(unsigned idx) override
|
||||
void _notify(unsigned) override
|
||||
{
|
||||
auto lambda = [&] (Index id,
|
||||
Descriptor_array & array,
|
||||
@ -219,10 +219,10 @@ class Vmm::Virtio_block_device
|
||||
|
||||
Register read(Address_range& range, Cpu&) override
|
||||
{
|
||||
if (range.start == 0 && range.size == 4)
|
||||
if (range.start() == 0 && range.size() == 4)
|
||||
return capacity & 0xffffffff;
|
||||
|
||||
if (range.start == 4 && range.size == 4)
|
||||
if (range.start() == 4 && range.size() == 4)
|
||||
return capacity >> 32;
|
||||
|
||||
throw Exception("Invalid read access of configuration area ",
|
||||
@ -230,8 +230,10 @@ class Vmm::Virtio_block_device
|
||||
}
|
||||
|
||||
Configuration_area(Virtio_block_device & device, uint64_t capacity)
|
||||
: Mmio_register("Configuration_area", Mmio_register::RO, 0x100, 8),
|
||||
capacity(capacity) { device.add(*this); }
|
||||
:
|
||||
Mmio_register("Configuration_area", Mmio_register::RO,
|
||||
0x100, 8, device.registers()),
|
||||
capacity(capacity) { }
|
||||
} _config_area{ *this, _block_info.block_count *
|
||||
(_block_info.block_size / 512) };
|
||||
|
||||
@ -244,10 +246,11 @@ class Vmm::Virtio_block_device
|
||||
Cpu & cpu,
|
||||
Mmio_bus & bus,
|
||||
Ram & ram,
|
||||
Virtio_device_list & list,
|
||||
Env & env,
|
||||
Heap & heap)
|
||||
: Virtio_device<Virtio_block_queue,1>(name, addr, size,
|
||||
irq, cpu, bus, ram, BLOCK),
|
||||
: Virtio_device<Virtio_block_queue,1>(name, addr, size, irq,
|
||||
cpu, bus, ram, list, BLOCK),
|
||||
_heap(heap),
|
||||
_block(env, &_block_alloc, BLOCK_BUFFER_SIZE),
|
||||
_handler(cpu, env.ep(), *this, &Virtio_block_device::_block_signal) {
|
||||
@ -273,7 +276,7 @@ class Vmm::Virtio_block_device
|
||||
memcpy((char *)job.address() + offset, src, sz);
|
||||
}
|
||||
|
||||
void completed(Job &job, bool success)
|
||||
void completed(Job &job, bool)
|
||||
{
|
||||
job.done(*_queue[REQUEST]);
|
||||
_assert_irq();
|
||||
|
@ -68,14 +68,14 @@ class Vmm::Virtio_console : public Virtio_device<Virtio_split_queue, 2>
|
||||
{
|
||||
Register read(Address_range & range, Cpu&) override
|
||||
{
|
||||
switch (range.start) {
|
||||
switch (range.start()) {
|
||||
case 4: return 1; /* maximum ports */
|
||||
default: ;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void write(Address_range & range, Cpu&, Register v) override {}
|
||||
void write(Address_range &, Cpu &, Register) override {}
|
||||
|
||||
Config_area(Virtio_console & console)
|
||||
: Reg(console, "ConfigArea", Mmio_register::RW, 0x100, 12) { }
|
||||
@ -90,10 +90,11 @@ class Vmm::Virtio_console : public Virtio_device<Virtio_split_queue, 2>
|
||||
Cpu & cpu,
|
||||
Mmio_bus & bus,
|
||||
Ram & ram,
|
||||
Virtio_device_list & list,
|
||||
Genode::Env & env)
|
||||
:
|
||||
Virtio_device<Virtio_split_queue, 2>(name, addr, size,
|
||||
irq, cpu, bus, ram, CONSOLE),
|
||||
Virtio_device<Virtio_split_queue, 2>(name, addr, size, irq,
|
||||
cpu, bus, ram, list, CONSOLE),
|
||||
_terminal(env, "console"),
|
||||
_handler(cpu, env.ep(), *this, &Virtio_console::_read)
|
||||
{
|
||||
|
@ -26,9 +26,11 @@
|
||||
|
||||
namespace Vmm {
|
||||
class Virtio_split_queue;
|
||||
class Virtio_device_base;
|
||||
struct Virtio_device_base;
|
||||
template <typename QUEUE, unsigned NUM> class Virtio_device;
|
||||
|
||||
using Virtio_device_list = List<Virtio_device_base>;
|
||||
|
||||
using namespace Genode;
|
||||
}
|
||||
|
||||
@ -45,7 +47,7 @@ class Vmm::Virtio_split_queue
|
||||
|
||||
protected:
|
||||
|
||||
template <unsigned LOG2>
|
||||
template <uint16_t LOG2>
|
||||
class Index
|
||||
{
|
||||
private:
|
||||
@ -56,12 +58,12 @@ class Vmm::Virtio_split_queue
|
||||
|
||||
public:
|
||||
|
||||
Index(unsigned idx = 0) : _idx(idx % (1 << LOG2)) {}
|
||||
Index(uint16_t idx = 0) : _idx(idx % (1 << LOG2)) {}
|
||||
|
||||
void inc() {
|
||||
_idx = ((_idx + 1) % (1 << LOG2)); }
|
||||
_idx = ((_idx + 1U) % (1U << LOG2)); }
|
||||
|
||||
unsigned idx() const { return _idx; }
|
||||
uint16_t idx() const { return _idx; }
|
||||
|
||||
bool operator != (Index const & o) const {
|
||||
return _idx != o._idx; }
|
||||
@ -73,9 +75,9 @@ class Vmm::Virtio_split_queue
|
||||
|
||||
struct Queue_base : Mmio
|
||||
{
|
||||
unsigned const max;
|
||||
uint16_t const max;
|
||||
|
||||
Queue_base(addr_t base, unsigned max)
|
||||
Queue_base(addr_t base, uint16_t max)
|
||||
: Mmio(base), max(max) {}
|
||||
|
||||
struct Flags : Register<0x0, 16> { };
|
||||
@ -95,7 +97,7 @@ class Vmm::Virtio_split_queue
|
||||
|
||||
Descriptor_index get(Ring_index id)
|
||||
{
|
||||
unsigned v = read<Ring>(id.idx() % max);
|
||||
uint16_t v = read<Ring>(id.idx() % max);
|
||||
if (v >= max) {
|
||||
throw Exception("Descriptor_index out of bounds"); }
|
||||
return Descriptor_index(v);
|
||||
@ -170,14 +172,14 @@ class Vmm::Virtio_split_queue
|
||||
|
||||
|
||||
Ram & _ram;
|
||||
Ring_index _cur_idx;
|
||||
Ring_index _cur_idx {};
|
||||
|
||||
public:
|
||||
|
||||
Virtio_split_queue(addr_t const descriptor_area,
|
||||
addr_t const device_area,
|
||||
addr_t const driver_area,
|
||||
unsigned const queue_num,
|
||||
uint16_t const queue_num,
|
||||
Ram & ram)
|
||||
:
|
||||
_avail(ram.local_address(driver_area, 6+2*queue_num), queue_num),
|
||||
@ -203,7 +205,7 @@ class Vmm::Virtio_split_queue
|
||||
if (!address || !size) { break; }
|
||||
|
||||
try {
|
||||
addr_t data = _ram.local_address(address, size);
|
||||
addr_t data = _ram.local_address((addr_t)address, size);
|
||||
size_t consumed = func(data, size);
|
||||
if (!consumed) { break; }
|
||||
_used.add(_cur_idx, id, consumed);
|
||||
@ -221,23 +223,18 @@ class Vmm::Virtio_split_queue
|
||||
};
|
||||
|
||||
|
||||
class Vmm::Virtio_device_base : public List<Virtio_device_base>::Element
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~Virtio_device_base() {}
|
||||
};
|
||||
struct Vmm::Virtio_device_base : public List<Virtio_device_base>::Element { };
|
||||
|
||||
|
||||
template <typename QUEUE, unsigned NUM>
|
||||
class Vmm::Virtio_device : public Vmm::Mmio_device, public Virtio_device_base
|
||||
class Vmm::Virtio_device : public Vmm::Mmio_device, private Virtio_device_base
|
||||
{
|
||||
protected:
|
||||
|
||||
Gic::Irq & _irq;
|
||||
Ram & _ram;
|
||||
Genode::Mutex _mutex;
|
||||
Genode::Constructible<QUEUE> _queue[NUM];
|
||||
Genode::Mutex _mutex {};
|
||||
Genode::Constructible<QUEUE> _queue[NUM] {};
|
||||
|
||||
virtual void _notify(unsigned idx) = 0;
|
||||
|
||||
@ -259,8 +256,10 @@ class Vmm::Virtio_device : public Vmm::Mmio_device, public Virtio_device_base
|
||||
Mmio_register::Type type,
|
||||
Genode::uint64_t start,
|
||||
uint32_t value = 0)
|
||||
: Mmio_register(name, type, start, 4, value), _dev(dev) {
|
||||
_dev.add(*this); }
|
||||
:
|
||||
Mmio_register(name, type, start, 4,
|
||||
dev.registers(), value),
|
||||
_dev(dev) { }
|
||||
|
||||
Virtio_device & device() { return _dev; }
|
||||
};
|
||||
@ -285,7 +284,7 @@ class Vmm::Virtio_device : public Vmm::Mmio_device, public Virtio_device_base
|
||||
Register read(Address_range &, Cpu &) override {
|
||||
return _regs[_selector.value()]; }
|
||||
|
||||
void write(Address_range & a, Cpu &, Register reg) override {
|
||||
void write(Address_range &, Cpu &, Register reg) override {
|
||||
_regs[_selector.value()] = reg; }
|
||||
|
||||
void set(Register value) override {
|
||||
@ -358,12 +357,14 @@ class Vmm::Virtio_device : public Vmm::Mmio_device, public Virtio_device_base
|
||||
{
|
||||
Genode::Mutex::Guard guard(mutex());
|
||||
|
||||
unsigned num = _queue_sel.value();
|
||||
unsigned num = (unsigned)_queue_sel.value();
|
||||
|
||||
if (_queue[num].constructed()) { return; }
|
||||
if (num >= NUM || _queue[num].constructed())
|
||||
return;
|
||||
|
||||
_queue[num].construct(_descriptor_area(), _device_area(),
|
||||
_driver_area(), _queue_num.value(), _ram);
|
||||
_queue[num].construct((addr_t)_descriptor_area(), (addr_t)_device_area(),
|
||||
(addr_t)_driver_area(), (uint16_t)_queue_num.value(),
|
||||
_ram);
|
||||
}
|
||||
|
||||
struct Queue_ready : Reg
|
||||
@ -392,7 +393,7 @@ class Vmm::Virtio_device : public Vmm::Mmio_device, public Virtio_device_base
|
||||
return;
|
||||
}
|
||||
|
||||
Reg::device()._notify(reg);
|
||||
Reg::device()._notify((unsigned)reg);
|
||||
}
|
||||
|
||||
Queue_notify(Virtio_device & device)
|
||||
@ -402,7 +403,7 @@ class Vmm::Virtio_device : public Vmm::Mmio_device, public Virtio_device_base
|
||||
|
||||
struct Interrupt_ack : Reg
|
||||
{
|
||||
void write(Address_range&, Cpu&, Register reg) override
|
||||
void write(Address_range&, Cpu&, Register) override
|
||||
{
|
||||
Genode::Mutex::Guard guard(Reg::device().mutex());
|
||||
Reg::device()._deassert_irq();
|
||||
@ -419,11 +420,12 @@ class Vmm::Virtio_device : public Vmm::Mmio_device, public Virtio_device_base
|
||||
const Genode::uint64_t size,
|
||||
unsigned irq,
|
||||
Cpu & cpu,
|
||||
Mmio_bus &bus,
|
||||
Space & bus,
|
||||
Ram & ram,
|
||||
Virtio_device_list & dev_list,
|
||||
uint32_t dev_id)
|
||||
:
|
||||
Mmio_device(name, addr, size),
|
||||
Mmio_device(name, addr, size, bus),
|
||||
_irq(cpu.gic().irq(irq)),
|
||||
_ram(ram)
|
||||
{
|
||||
@ -436,7 +438,7 @@ class Vmm::Virtio_device : public Vmm::Mmio_device, public Virtio_device_base
|
||||
_dev_feature.set(VIRTIO_F_VERSION_1);
|
||||
_dev_sel.set(0); /* set to 0...31 feature bits */
|
||||
|
||||
bus.add(*this);
|
||||
dev_list.insert(this);
|
||||
}
|
||||
|
||||
Genode::Mutex & mutex() { return _mutex; }
|
||||
|
@ -35,7 +35,7 @@ void Vmm::Virtio_gpu_queue::notify(Virtio_gpu_device & dev)
|
||||
if (!inform)
|
||||
return;
|
||||
|
||||
_used.write<Used_queue::Idx>(_cur_idx.idx());
|
||||
_used.write<Used_queue::Idx>((uint16_t)_cur_idx.idx());
|
||||
memory_barrier();
|
||||
if (_avail.inject_irq()) dev.assert_irq();
|
||||
}
|
||||
@ -128,7 +128,7 @@ void Vmm::Virtio_gpu_control_request::_resource_attach_backing()
|
||||
for (unsigned i = 0; i < nr; i++) {
|
||||
Entry entry(entry_base+i*Entry::SIZE);
|
||||
size_t sz = entry.read<Entry::Length>();
|
||||
addr_t off = _device._ram.local_address(entry.read<Entry::Address>(), sz)
|
||||
addr_t off = _device._ram.local_address((addr_t)entry.read<Entry::Address>(), sz)
|
||||
- _device._ram.local();
|
||||
res.attach(off, sz);
|
||||
}
|
||||
@ -211,7 +211,7 @@ void Vmm::Virtio_gpu_control_request::_resource_flush()
|
||||
void * dst =
|
||||
(void*)((addr_t)_device._fb_ds->local_addr<void>() +
|
||||
(_device._fb_mode.area.w() * y + x) * BYTES_PER_PIXEL);
|
||||
size_t line = res.area.w() * BYTES_PER_PIXEL;
|
||||
uint32_t line = res.area.w() * BYTES_PER_PIXEL;
|
||||
|
||||
blit(src, line, dst, line, w*BYTES_PER_PIXEL, h);
|
||||
|
||||
@ -240,7 +240,7 @@ void Vmm::Virtio_gpu_control_request::_transfer_to_host_2d()
|
||||
uint32_t y = tth.read<Transfer_to_host_2d::Y>();
|
||||
uint32_t w = tth.read<Transfer_to_host_2d::Width>();
|
||||
uint32_t h = tth.read<Transfer_to_host_2d::Height>();
|
||||
addr_t off = tth.read<Transfer_to_host_2d::Offset>();
|
||||
addr_t off = (addr_t)tth.read<Transfer_to_host_2d::Offset>();
|
||||
|
||||
if (x + w > res.area.w() || y + h > res.area.h()) {
|
||||
response.write<Control_header::Type>(Control_header::Type::ERR_INVALID_PARAMETER);
|
||||
@ -250,7 +250,7 @@ void Vmm::Virtio_gpu_control_request::_transfer_to_host_2d()
|
||||
void * src = (void*)((addr_t)res.src_ds.local_addr<void>() + off);
|
||||
void * dst = (void*)((addr_t)res.dst_ds.local_addr<void>() +
|
||||
(y * res.area.w() + x) * BYTES_PER_PIXEL);
|
||||
size_t line = res.area.w() * BYTES_PER_PIXEL;
|
||||
uint32_t line = res.area.w() * BYTES_PER_PIXEL;
|
||||
|
||||
blit(src, line, dst, line, w*BYTES_PER_PIXEL, h);
|
||||
|
||||
|
@ -34,7 +34,7 @@ class Vmm::Virtio_gpu_queue : public Virtio_split_queue
|
||||
{
|
||||
private:
|
||||
|
||||
Ring_index _used_idx;
|
||||
Ring_index _used_idx {};
|
||||
|
||||
friend class Virtio_gpu_control_request;
|
||||
|
||||
@ -235,7 +235,8 @@ class Vmm::Virtio_gpu_control_request
|
||||
addr_t _desc_addr(unsigned i)
|
||||
{
|
||||
Descriptor d = _desc(i);
|
||||
return _ram.local_address(d.address(), d.length());
|
||||
/* we only support 32-bit ram addresses by now */
|
||||
return _ram.local_address((addr_t)d.address(), d.length());
|
||||
}
|
||||
|
||||
Control_header _ctrl_hdr { _desc_addr(0) };
|
||||
@ -329,7 +330,8 @@ class Vmm::Virtio_gpu_device : public Virtio_device<Virtio_gpu_queue, 2>
|
||||
uint32_t w, uint32_t h)
|
||||
:
|
||||
Registry<Scanout>::Element(registry, *this),
|
||||
Rect(Point((int)x,(int)y), Area((int)w,(int)h)) { }
|
||||
Rect(Point((int)x,(int)y), Area((int)w,(int)h)),
|
||||
id(id) { }
|
||||
|
||||
using Rect::Rect;
|
||||
};
|
||||
@ -348,7 +350,7 @@ class Vmm::Virtio_gpu_device : public Virtio_device<Virtio_gpu_queue, 2>
|
||||
region_map.dataspace() };
|
||||
Attached_ram_dataspace dst_ds { device._env.ram(),
|
||||
device._env.rm(), _size() };
|
||||
Registry<Scanout> scanouts;
|
||||
Registry<Scanout> scanouts {};
|
||||
|
||||
Resource(Virtio_gpu_device & dev,
|
||||
uint32_t id,
|
||||
@ -392,11 +394,11 @@ class Vmm::Virtio_gpu_device : public Virtio_device<Virtio_gpu_queue, 2>
|
||||
|
||||
Register read(Address_range & range, Cpu&) override
|
||||
{
|
||||
if (range.start == EVENTS_READ && range.size == 4)
|
||||
if (range.start() == EVENTS_READ && range.size() == 4)
|
||||
return dev._mode_changed ? 1 : 0;
|
||||
|
||||
/* we support no multi-head, just return 1 */
|
||||
if (range.start == SCANOUTS && range.size == 4)
|
||||
if (range.start() == SCANOUTS && range.size() == 4)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
@ -404,13 +406,15 @@ class Vmm::Virtio_gpu_device : public Virtio_device<Virtio_gpu_queue, 2>
|
||||
|
||||
void write(Address_range & range, Cpu&, Register v) override
|
||||
{
|
||||
if (range.start == EVENTS_CLEAR && range.size == 4 && v == 1)
|
||||
if (range.start() == EVENTS_CLEAR && range.size() == 4 && v == 1)
|
||||
dev._mode_changed = false;
|
||||
}
|
||||
|
||||
Configuration_area(Virtio_gpu_device & device)
|
||||
: Mmio_register("GPU config area", Mmio_register::RO, 0x100, 16),
|
||||
dev(device) { device.add(*this); }
|
||||
:
|
||||
Mmio_register("GPU config area", Mmio_register::RO,
|
||||
0x100, 16, device.registers()),
|
||||
dev(device) { }
|
||||
} _config_area{ *this };
|
||||
|
||||
void _mode_change()
|
||||
@ -448,15 +452,16 @@ class Vmm::Virtio_gpu_device : public Virtio_device<Virtio_gpu_queue, 2>
|
||||
const uint64_t size,
|
||||
unsigned irq,
|
||||
Cpu & cpu,
|
||||
Mmio_bus & bus,
|
||||
Space & bus,
|
||||
Ram & ram,
|
||||
Virtio_device_list & list,
|
||||
Env & env,
|
||||
Heap & heap,
|
||||
Attached_ram_dataspace & ram_ds,
|
||||
Gui::Connection & gui)
|
||||
:
|
||||
Virtio_device<Virtio_gpu_queue, 2>(name, addr, size,
|
||||
irq, cpu, bus, ram, GPU),
|
||||
irq, cpu, bus, ram, list, GPU),
|
||||
_env(env), _heap(heap), _ram_ds(ram_ds), _gui(gui),
|
||||
_handler(cpu, env.ep(), *this, &Virtio_gpu_device::_mode_change)
|
||||
{
|
||||
|
@ -123,9 +123,9 @@ class Vmm::Virtio_input_device : public Virtio_device<Virtio_split_queue, 2>
|
||||
using namespace Linux_evdev;
|
||||
|
||||
switch (_select) {
|
||||
case ID_NAME: return _name.length() - 1;
|
||||
case ID_SERIAL: return _serial.length() - 1;
|
||||
case ID_DEVIDS: return _dev_id.length() - 1;
|
||||
case ID_NAME: return (uint8_t)(_name.length() - 1);
|
||||
case ID_SERIAL: return (uint8_t)(_serial.length() - 1);
|
||||
case ID_DEVIDS: return (uint8_t)(_dev_id.length() - 1);
|
||||
case PROP_BITS: return 0; /* Unsupported */
|
||||
case EV_BITS:
|
||||
switch (_sub_select) {
|
||||
@ -143,7 +143,7 @@ class Vmm::Virtio_input_device : public Virtio_device<Virtio_split_queue, 2>
|
||||
return 0;
|
||||
}
|
||||
|
||||
Register _data(addr_t off)
|
||||
Register _data(Register off)
|
||||
{
|
||||
using namespace Linux_evdev;
|
||||
|
||||
@ -179,32 +179,33 @@ class Vmm::Virtio_input_device : public Virtio_device<Virtio_split_queue, 2>
|
||||
|
||||
Register read(Address_range & range, Cpu&) override
|
||||
{
|
||||
if (range.start == SIZE)
|
||||
if (range.start() == SIZE)
|
||||
return _size();
|
||||
|
||||
if (range.start >= DATA && range.start < DATA_MAX)
|
||||
return _data(range.start-DATA);
|
||||
if (range.start() >= DATA && range.start() < DATA_MAX)
|
||||
return _data(range.start()-DATA);
|
||||
|
||||
error("Reading from virtio input config space ",
|
||||
"at offset ", range.start, " is not allowed");
|
||||
"at offset ", range.start(), " is not allowed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void write(Address_range & range, Cpu&, Register v) override
|
||||
{
|
||||
switch (range.start) {
|
||||
case SELECT: _select = v; return;
|
||||
case SUB_SELECT: _sub_select = v; return;
|
||||
switch (range.start()) {
|
||||
case SELECT: _select = (uint8_t)v; return;
|
||||
case SUB_SELECT: _sub_select = (uint8_t)v; return;
|
||||
default:
|
||||
error("Writing to virtio input config space ",
|
||||
"at offset ", range.start, " is not allowed");
|
||||
"at offset ", range.start(), " is not allowed");
|
||||
}
|
||||
}
|
||||
|
||||
Configuration_area(Virtio_input_device & device)
|
||||
: Mmio_register("Input config area",
|
||||
Mmio_register::RO, 0x100, 0xa4),
|
||||
dev(device) { device.add(*this); }
|
||||
:
|
||||
Mmio_register("Input config area", Mmio_register::RO,
|
||||
0x100, 0xa4, device.registers()),
|
||||
dev(device) { }
|
||||
} _config_area{ *this };
|
||||
|
||||
void _handle_input()
|
||||
@ -285,6 +286,12 @@ class Vmm::Virtio_input_device : public Virtio_device<Virtio_split_queue, 2>
|
||||
|
||||
enum Device_id { INPUT = 18 };
|
||||
|
||||
/*
|
||||
* Noncopyable
|
||||
*/
|
||||
Virtio_input_device(Virtio_input_device const &);
|
||||
Virtio_input_device &operator = (Virtio_input_device const &);
|
||||
|
||||
public:
|
||||
|
||||
Virtio_input_device(const char * const name,
|
||||
@ -294,12 +301,13 @@ class Vmm::Virtio_input_device : public Virtio_device<Virtio_split_queue, 2>
|
||||
Cpu & cpu,
|
||||
Mmio_bus & bus,
|
||||
Ram & ram,
|
||||
Virtio_device_list & list,
|
||||
Env & env,
|
||||
Heap & heap,
|
||||
Input::Session_client & input)
|
||||
:
|
||||
Virtio_device<Virtio_split_queue, 2>(name, addr, size,
|
||||
irq, cpu, bus, ram, INPUT),
|
||||
Virtio_device<Virtio_split_queue, 2>(name, addr, size, irq,
|
||||
cpu, bus, ram, list, INPUT),
|
||||
_env(env), _heap(heap), _input(input),
|
||||
_handler(cpu, env.ep(), *this, &Virtio_input_device::_handle_input)
|
||||
{
|
||||
|
@ -125,12 +125,12 @@ class Vmm::Virtio_net : public Virtio_device<Virtio_split_queue, 2>
|
||||
|
||||
Register read(Address_range & range, Cpu&) override
|
||||
{
|
||||
if (range.start > 5) return 0;
|
||||
if (range.start() > 5) return 0;
|
||||
|
||||
return mac.addr[range.start];
|
||||
return mac.addr[range.start()];
|
||||
}
|
||||
|
||||
void write(Address_range & range, Cpu&, Register v) override {}
|
||||
void write(Address_range &, Cpu &, Register) override {}
|
||||
|
||||
Config_area(Virtio_net & device, Nic::Mac_address & mac)
|
||||
: Reg(device, "ConfigArea", Mmio_register::RW, 0x100, 24),
|
||||
@ -147,10 +147,11 @@ class Vmm::Virtio_net : public Virtio_device<Virtio_split_queue, 2>
|
||||
Cpu & cpu,
|
||||
Mmio_bus & bus,
|
||||
Ram & ram,
|
||||
Virtio_device_list & list,
|
||||
Genode::Env & env)
|
||||
:
|
||||
Virtio_device<Virtio_split_queue, 2>(name, addr, size,
|
||||
irq, cpu, bus, ram, NIC),
|
||||
Virtio_device<Virtio_split_queue, 2>(name, addr, size, irq,
|
||||
cpu, bus, ram, list, NIC),
|
||||
_env(env),
|
||||
_handler(cpu, _env.ep(), *this, &Virtio_net::_handle)
|
||||
{
|
||||
|
@ -118,36 +118,38 @@ Vm::Vm(Genode::Env & env, Heap & heap, Config & config)
|
||||
_config.for_each_virtio_device([&] (Config::Virtio_device const & dev) {
|
||||
switch (dev.type) {
|
||||
case Config::Virtio_device::CONSOLE:
|
||||
_device_list.insert(new (_heap)
|
||||
new (_heap)
|
||||
Virtio_console(dev.name.string(), (uint64_t)dev.mmio_start,
|
||||
dev.mmio_size, dev.irq, boot_cpu(),
|
||||
_bus, _ram, env));
|
||||
_bus, _ram, _device_list, env);
|
||||
return;
|
||||
case Config::Virtio_device::NET:
|
||||
_device_list.insert(new (_heap)
|
||||
new (_heap)
|
||||
Virtio_net(dev.name.string(), (uint64_t)dev.mmio_start,
|
||||
dev.mmio_size, dev.irq, boot_cpu(), _bus, _ram,
|
||||
env));
|
||||
_device_list, env);
|
||||
return;
|
||||
case Config::Virtio_device::BLOCK:
|
||||
_device_list.insert(new (_heap)
|
||||
new (_heap)
|
||||
Virtio_block_device(dev.name.string(), (uint64_t)dev.mmio_start,
|
||||
dev.mmio_size, dev.irq, boot_cpu(),
|
||||
_bus, _ram, env, heap));
|
||||
_bus, _ram, _device_list, env, heap);
|
||||
return;
|
||||
case Config::Virtio_device::GPU:
|
||||
if (!_gui.constructed()) _gui.construct(env);
|
||||
_device_list.insert(new (_heap)
|
||||
new (_heap)
|
||||
Virtio_gpu_device(dev.name.string(), (uint64_t)dev.mmio_start,
|
||||
dev.mmio_size, dev.irq, boot_cpu(),
|
||||
_bus, _ram, env, heap, _vm_ram, *_gui));
|
||||
_bus, _ram, _device_list, env,
|
||||
heap, _vm_ram, *_gui);
|
||||
return;
|
||||
case Config::Virtio_device::INPUT:
|
||||
if (!_gui.constructed()) _gui.construct(env);
|
||||
_device_list.insert(new (_heap)
|
||||
new (_heap)
|
||||
Virtio_input_device(dev.name.string(), (uint64_t)dev.mmio_start,
|
||||
dev.mmio_size, dev.irq, boot_cpu(),
|
||||
_bus, _ram, env, heap, *_gui->input()));
|
||||
_bus, _ram, _device_list, env,
|
||||
heap, *_gui->input());
|
||||
default:
|
||||
return;
|
||||
};
|
||||
|
@ -58,10 +58,10 @@ class Vmm::Vm
|
||||
_config.ram_size(), CACHED };
|
||||
Ram _ram { RAM_START, _config.ram_size(),
|
||||
(addr_t)_vm_ram.local_addr<void>()};
|
||||
Mmio_bus _bus;
|
||||
Mmio_bus _bus {};
|
||||
Gic _gic;
|
||||
List<Cpu_entry> _cpu_list;
|
||||
List<Virtio_device_base> _device_list;
|
||||
List<Cpu_entry> _cpu_list {};
|
||||
List<Virtio_device_base> _device_list {};
|
||||
Pl011 _uart;
|
||||
|
||||
Constructible<Attached_rom_dataspace> _initrd_rom {};
|
||||
|
Loading…
Reference in New Issue
Block a user