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:
Stefan Kalkowski 2023-02-23 11:21:33 +01:00 committed by Christian Helmuth
parent adc594a7e6
commit c5b9cabd89
26 changed files with 701 additions and 560 deletions

View File

@ -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);
}

View File

@ -18,44 +18,57 @@
#include <util/avl_tree.h>
namespace Vmm {
using namespace Genode;
struct Address_range;
class Address_space;
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;
bool match(Address_range & other) const {
return other.start >= start && other.end() <= end(); }
public:
Address_range & find(Address_range & bus_addr);
Address_range(uint64_t start,
uint64_t size);
virtual ~Address_range() {}
struct Not_found : Exception
{
Not_found(Address_range & access)
: Exception("Could not find ", access) {}
};
uint64_t start() const { return _start; }
uint64_t size() const { return _size; }
uint64_t end() const { return _start + _size; }
void print(Genode::Output & out) const
{
Genode::print(out, "address=", Genode::Hex(start),
" width=", Genode::Hex(size));
}
bool match(Address_range & other) const {
return other._start >= _start && other.end() <= end(); }
/************************
** Avl_node interface **
************************/
Address_range & find(Address_range & bus_addr);
bool higher(Address_range * range) {
return range->start > start; }
struct Not_found : Exception
{
Not_found(Address_range & access)
: Exception("Could not find ", access) {}
};
void print(Genode::Output & out) const
{
Genode::print(out, "address=", Hex(_start),
" width=", Hex(_size));
}
/************************
** Avl_node interface **
************************/
bool higher(Address_range * range) {
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:

View File

@ -36,22 +36,32 @@ 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
{
enum Type { INVALID, CONSOLE, NET, BLOCK, GPU, INPUT };
private:
enum { MMIO_SIZE = 0x200 };
Config & _config;
Config & _config;
/**
* Noncopyable
*/
Virtio_device(Virtio_device const &);
Virtio_device &operator = (Virtio_device const &);
Virtio_device(Name & name, Type type, Config & config);
~Virtio_device();
public:
Name const name;
Type const type;
void * const mmio_start;
size_t const mmio_size;
unsigned const irq;
enum Type { INVALID, CONSOLE, NET, BLOCK, GPU, INPUT };
enum { MMIO_SIZE = 0x200 };
Virtio_device(Name & name, Type type, Config & config);
~Virtio_device();
Name const name;
Type const type;
void * const mmio_start;
size_t const mmio_size;
unsigned const irq;
};
private:
@ -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

View File

@ -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),

View File

@ -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;
const Esr::access_t _encoding;
const char * _name;
const bool _writeable;
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) {}
const char * name() const { return _name; }
const bool writeable() const { return _writeable; }
virtual ~System_register() {}
const char * name() const { return _name; }
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 {};
/***********************

View File

@ -275,12 +275,12 @@ 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,
GIC_PPI, 0xe, IRQ_TYPE_LEVEL_HIGH,
GIC_PPI, 0xb, IRQ_TYPE_LEVEL_HIGH,
GIC_PPI, 0xa, 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));
});
node(Name("gic"), [&] ()
@ -289,16 +289,16 @@ 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,
0, (gicv2) ? GICC_MMIO_START : GICR_MMIO_START,
0, (gicv2) ? GICC_MMIO_SIZE : GICR_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));
});
node(Name("clocks"), [&] ()
@ -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,
0, PL011_MMIO_SIZE));
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));
});
});
});

View File

@ -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);
}

View File

@ -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 Enable : Bitfield<0, 1> {};
struct Disable : Bitfield<6, 1> {};
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 It_lines_number : Bitfield<0, 5> {};
struct Cpu_number : Bitfield<5, 3> {};
struct Id_bits : Bitfield<19, 5> {};
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 Implementer : Bitfield<0, 12> {};
struct Revision : Bitfield<12, 4> {};
struct Variant : Bitfield<16, 4> {};
struct Product_id : Bitfield<24, 8> {};
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 Int_id : Bitfield<0, 4> {};
struct Target_list : Bitfield<16, 8> {};
struct Target_filter : Bitfield<24, 2> {
enum Target_type { LIST, ALL, MYSELF, INVALID };
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_ */

View File

@ -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);
}
@ -94,27 +97,30 @@ void Vmm::Mmio_bus::handle_memory_access(Vmm::Cpu & cpu)
static bool valid(access_t v) {
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 bool write(access_t v) { return Write::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);

View File

@ -30,23 +30,28 @@ 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);
virtual void set(Register value);
virtual Register value() const;
Mmio_register(Name name,
Type type,
Genode::uint64_t start,
Genode::uint64_t size,
Register reset_value = 0)
Mmio_register(Name name,
Type type,
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,23 +67,32 @@ 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);
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;
Mmio_device(Name name,
uint64_t start,
uint64_t size,
Space & bus)
: Address_range(start, size), _name(name)
{
bus.add(*this);
}
};

View File

@ -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);
}

View File

@ -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,25 +75,31 @@ 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),
terminal(terminal), rx(rx), ris(ris) {}
} _uart_dr { _terminal, _rx_buf, _uart_ris };
:
Mmio_register("UARTDR", Mmio_register::RW, 0x0, 2, device),
terminal(terminal), rx(rx), ris(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>
{
struct Rx_empty : Bitfield<4, 1> {};
struct Rx_full : Bitfield<6, 1> {};
public:
Ring_buffer & rx;
struct Rx_empty : Bitfield<4, 1> {};
struct Rx_full : Bitfield<6, 1> {};
Mmio_register::Register read(Address_range&, Cpu&) override;
Ring_buffer & rx;
Uartfr(Ring_buffer & rx)
: Mmio_register("UARTFR", Mmio_register::RO, 0x18, 4), rx(rx) {}
} _uart_fr { _rx_buf };
Mmio_register::Register read(Address_range&, Cpu&) override;
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),
irq(irq), ris(ris) {}
} _uart_imsc { _irq, _uart_ris };
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 { 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),
ris(ris), imsc(imsc) {}
} _uart_mis { _uart_ris, _uart_imsc };
Uartmis(Space & device, Mmio_register & ris, Uartimsc & imsc)
:
Mmio_register("UARTMIS", Mmio_register::RO, 0x40, 2, device),
ris(ris), imsc(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);
};

View File

@ -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;
}
@ -155,14 +154,14 @@ Genode::addr_t Cpu::Ccsidr::read() const
}
Cpu::Cpu(Vm & vm,
Genode::Vm_connection & vm_session,
Mmio_bus & bus,
Gic & gic,
Genode::Env & env,
Genode::Heap & heap,
Genode::Entrypoint & ep,
short const id)
Cpu::Cpu(Vm & vm,
Vm_connection & vm_session,
Mmio_bus & bus,
Gic & gic,
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),

View File

@ -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,

View File

@ -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,21 +198,21 @@ 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;
}
Cpu::Cpu(Vm & vm,
Genode::Vm_connection & vm_session,
Mmio_bus & bus,
Gic & gic,
Genode::Env & env,
Genode::Heap & heap,
Genode::Entrypoint & ep,
short const id)
Cpu::Cpu(Vm & vm,
Vm_connection & vm_session,
Mmio_bus & bus,
Gic & gic,
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),

View File

@ -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,
@ -45,8 +45,8 @@ class Vmm::Cpu : public Vmm::Cpu_base
private:
class Id_aa64pfr0 : public System_register,
public Genode::Register<64>
class Id_aa64pfr0 : public System_register,
protected Genode::Register<64>
{
private:

View File

@ -15,5 +15,3 @@ SRC_CC += virtio_gpu.cc
INC_DIR += $(PRG_DIR)/../.. $(PRG_DIR)
vpath %.cc $(PRG_DIR)/../..
CC_CXX_WARN_STRICT :=

View File

@ -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,24 +230,27 @@ 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) };
public:
Virtio_block_device(const char * const name,
const uint64_t addr,
const uint64_t size,
unsigned irq,
Cpu & cpu,
Mmio_bus & bus,
Ram & ram,
Env & env,
Heap & heap)
: Virtio_device<Virtio_block_queue,1>(name, addr, size,
irq, cpu, bus, ram, BLOCK),
Virtio_block_device(const char * const name,
const uint64_t addr,
const uint64_t size,
unsigned irq,
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, 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();

View File

@ -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) { }
@ -83,17 +83,18 @@ class Vmm::Virtio_console : public Virtio_device<Virtio_split_queue, 2>
public:
Virtio_console(const char * const name,
const uint64_t addr,
const uint64_t size,
unsigned irq,
Cpu & cpu,
Mmio_bus & bus,
Ram & ram,
Genode::Env & env)
Virtio_console(const char * const name,
const uint64_t addr,
const uint64_t size,
unsigned irq,
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)
{

View File

@ -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();
@ -418,12 +419,13 @@ class Vmm::Virtio_device : public Vmm::Mmio_device, public Virtio_device_base
const Genode::uint64_t addr,
const Genode::uint64_t size,
unsigned irq,
Cpu &cpu,
Mmio_bus &bus,
Ram &ram,
Cpu & cpu,
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; }

View File

@ -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);

View File

@ -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)
{

View File

@ -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)
{

View File

@ -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),
@ -140,17 +140,18 @@ class Vmm::Virtio_net : public Virtio_device<Virtio_split_queue, 2>
public:
Virtio_net(const char * const name,
const uint64_t addr,
const uint64_t size,
unsigned irq,
Cpu &cpu,
Mmio_bus &bus,
Ram &ram,
Genode::Env &env)
Virtio_net(const char * const name,
const uint64_t addr,
const uint64_t size,
unsigned irq,
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)
{

View File

@ -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;
};

View File

@ -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 {};