diff --git a/repos/os/src/server/vmm/cpu_base.cc b/repos/os/src/server/vmm/cpu_base.cc index c1dd528d51..18d7b37f7e 100644 --- a/repos/os/src/server/vmm/cpu_base.cc +++ b/repos/os/src/server/vmm/cpu_base.cc @@ -1,11 +1,12 @@ /* * \brief VMM cpu object * \author Stefan Kalkowski + * \author Benjamin Lamowski * \date 2019-07-18 */ /* - * Copyright (C) 2019 Genode Labs GmbH + * Copyright (C) 2019-2023 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU Affero General Public License version 3. @@ -37,16 +38,16 @@ Cpu_base::System_register::System_register(unsigned op0, } -bool Cpu_base::_handle_sys_reg() +bool Cpu_base::_handle_sys_reg(State & state) { using Iss = System_register::Iss; - Iss::access_t v = _state.esr_el2; + Iss::access_t v = state.esr_el2; System_register * reg = _reg_tree.first(); if (reg) reg = reg->find_by_encoding(Iss::mask_encoding(v)); if (!reg) { - Genode::error("ignore unknown system register access @ ip=", (void*)_state.ip, ":"); + Genode::error("ignore unknown system register access @ ip=", (void*)state.ip, ":"); Genode::error(Iss::Direction::get(v) ? "read" : "write", ": " "op0=", Iss::Opcode0::get(v), " " @@ -55,125 +56,138 @@ bool Cpu_base::_handle_sys_reg() "crn=", Iss::Crn::get(v), " " "crm=", Iss::Crm::get(v), " ", "op2=", Iss::Opcode2::get(v)); - if (Iss::Direction::get(v)) _state.reg(Iss::Register::get(v), 0); - _state.ip += sizeof(Genode::uint32_t); + if (Iss::Direction::get(v)) state.reg(Iss::Register::get(v), 0); + state.ip += sizeof(Genode::uint32_t); return false; } if (Iss::Direction::get(v)) { /* read access */ - _state.reg(Iss::Register::get(v), reg->read()); + state.reg(Iss::Register::get(v), reg->read()); } else { /* write access */ if (!reg->writeable()) { Genode::error("writing to system register ", reg->name(), " not allowed!"); return false; } - reg->write(_state.reg(Iss::Register::get(v))); + reg->write(state.reg(Iss::Register::get(v))); } - _state.ip += sizeof(Genode::uint32_t); + state.ip += sizeof(Genode::uint32_t); return true; } -void Cpu_base::_handle_wfi() +void Cpu_base::_handle_wfi(State &state) { - _state.ip += sizeof(Genode::uint32_t); + state.ip += sizeof(Genode::uint32_t); - if (_state.esr_el2 & 1) return; /* WFE */ + if (state.esr_el2 & 1) return; /* WFE */ _active = false; - _timer.schedule_timeout(); + _timer.schedule_timeout(state); } -void Cpu_base::_handle_sync() +void Cpu_base::_handle_startup(State &state) +{ + Generic_timer::setup_state(state); + Gic::Gicd_banked::setup_state(state); + + setup_state(state); + + if (cpu_id() == 0) { + initialize_boot(state, _vm.kernel_addr(), _vm.dtb_addr()); + } else { + _cpu_ready.down(); + } + _active = true; +} + + +void Cpu_base::_handle_sync(State &state) { /* check device number*/ - switch (Esr::Ec::get(_state.esr_el2)) { + switch (Esr::Ec::get(state.esr_el2)) { case Esr::Ec::HVC_32: [[fallthrough]]; case Esr::Ec::HVC: - _handle_hyper_call(); + _handle_hyper_call(state); break; case Esr::Ec::MRC_MCR: [[fallthrough]]; case Esr::Ec::MRS_MSR: - _handle_sys_reg(); + _handle_sys_reg(state); break; case Esr::Ec::DA: - _handle_data_abort(); + _handle_data_abort(state); break; case Esr::Ec::WFI: - _handle_wfi(); + _handle_wfi(state); return; case Esr::Ec::BRK: - _handle_brk(); + _handle_brk(state); return; default: throw Exception("Unknown trap: ", - Esr::Ec::get(_state.esr_el2)); + Esr::Ec::get(state.esr_el2)); }; } -void Cpu_base::_handle_irq() +void Cpu_base::_handle_irq(State &state) { - switch (_state.irqs.last_irq) { + switch (state.irqs.last_irq) { case VTIMER_IRQ: - _timer.handle_irq(); + _timer.handle_irq(state); break; default: - _gic.handle_irq(); + _gic.handle_irq(state); }; } -void Cpu_base::_handle_hyper_call() +void Cpu_base::_handle_hyper_call(State &state) { - switch(_state.reg(0)) { + switch(state.reg(0)) { case Psci::PSCI_VERSION: - _state.reg(0, Psci::VERSION); + state.reg(0, Psci::VERSION); return; case Psci::MIGRATE_INFO_TYPE: - _state.reg(0, Psci::NOT_SUPPORTED); + state.reg(0, Psci::NOT_SUPPORTED); return; case Psci::PSCI_FEATURES: - _state.reg(0, Psci::NOT_SUPPORTED); + state.reg(0, Psci::NOT_SUPPORTED); return; case Psci::CPU_ON_32: [[fallthrough]]; case Psci::CPU_ON: - _vm.cpu((unsigned)_state.reg(1), [&] (Cpu & cpu) { - cpu.state().ip = _state.reg(2); - cpu.state().reg(0, _state.reg(3)); - cpu.run(); + _vm.cpu((unsigned)state.reg(1), [&] (Cpu & cpu) { + State & local_state = cpu.state(); + cpu.initialize_boot(local_state, state.reg(2), state.reg(3)); + cpu.set_ready(); }); - _state.reg(0, Psci::SUCCESS); + state.reg(0, Psci::SUCCESS); return; default: Genode::warning("unknown hypercall! ", cpu_id()); - dump(); + dump(state); }; } -void Cpu_base::_handle_data_abort() +void Cpu_base::_handle_data_abort(State &state) { - _vm.bus().handle_memory_access(*static_cast(this)); - _state.ip += sizeof(Genode::uint32_t); + _vm.bus().handle_memory_access(state, *static_cast(this)); + state.ip += sizeof(Genode::uint32_t); } -void Cpu_base::_update_state() +void Cpu_base::_update_state(State &state) { - if (!_gic.pending_irq()) return; + if (!_gic.pending_irq(state)) return; _active = true; _timer.cancel_timeout(); } unsigned Cpu_base::cpu_id() const { return _vcpu_id; } -void Cpu_base::run() { _vm_vcpu.run(); } -void Cpu_base::pause() { _vm_vcpu.pause(); } bool Cpu_base::active() const { return _active; } -Cpu_base::State & Cpu_base::state() const { return _state; } Gic::Gicd_banked & Cpu_base::gic() { return _gic; } @@ -197,6 +211,5 @@ Cpu_base::Cpu_base(Vm & vm, _heap(heap), _vm_handler(*this, ep, *this, &Cpu_base::_handle_nothing), _vm_vcpu(_vm_session, heap, _vm_handler, _exit_config), - _state(*((State*)(&_vm_vcpu.state()))), _gic(*this, gic, bus), _timer(env, ep, _gic.irq(VTIMER_IRQ), *this) { } diff --git a/repos/os/src/server/vmm/cpu_base.h b/repos/os/src/server/vmm/cpu_base.h index 49656f80a9..da31273a02 100644 --- a/repos/os/src/server/vmm/cpu_base.h +++ b/repos/os/src/server/vmm/cpu_base.h @@ -1,11 +1,12 @@ /* * \brief VMM cpu object * \author Stefan Kalkowski + * \author Benjamin Lamowski * \date 2019-07-18 */ /* - * Copyright (C) 2019 Genode Labs GmbH + * Copyright (C) 2019-2023 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU Affero General Public License version 3. @@ -16,6 +17,7 @@ #include #include +#include #include #include @@ -33,12 +35,6 @@ class Vmm::Cpu_base { public: - struct State : Genode::Vm_state - { - addr_t reg(addr_t idx) const; - void reg(addr_t idx, addr_t v); - }; - struct Esr : Genode::Register { struct Ec : Bitfield<26, 6> @@ -65,28 +61,55 @@ class Vmm::Cpu_base unsigned cpu_id); unsigned cpu_id() const; - void run(); - void pause(); bool active() const; - State & state() const; Gic::Gicd_banked & gic(); - void dump(); - void handle_exception(); + void dump(State & state); + void handle_exception(State &state); void recall(); - void initialize_boot(Genode::addr_t ip, + void initialize_boot(State &state, + Genode::addr_t ip, Genode::addr_t dtb); + virtual void setup_state(State &) { }; + + virtual ~Cpu_base() = default; + + State & state() { + return _state->ref; + } + + template + void with_state(FN const & fn) + { + _vm_vcpu.with_state(fn); + } + + void set_ready() { + _cpu_ready.up(); + } template void handle_signal(FUNC handler) { - if (active()) { - pause(); - handle_exception(); - } + _vm_vcpu.with_state([this, handler](Vm_state &vmstate) { + State & state = static_cast(vmstate); + _state.construct(state); - handler(); - _update_state(); - if (active()) run(); + try { + if (active()) { + handle_exception(state); + } + + handler(state); + _update_state(state); + } catch(Exception &e) { + Genode::error(e); + dump(state); + return false; + } + + _state.destruct(); + return active(); + }); } template @@ -100,12 +123,7 @@ class Vmm::Cpu_base void handle() { - try { - cpu.handle_signal([this] () { (obj.*member)(); }); - } catch(Exception &e) { - Genode::error(e); - cpu.dump(); - } + cpu.handle_signal([this] (Vm_state &) { (obj.*member)(); }); } Signal_handler(Cpu_base & cpu, @@ -207,16 +225,20 @@ class Vmm::Cpu_base return (r->_encoding > _encoding); } }; - unsigned _vcpu_id; - bool _active { true }; - Vm & _vm; - Genode::Vm_connection & _vm_session; - Genode::Heap & _heap; - Signal_handler _vm_handler; - Genode::Vm_connection::Exit_config _exit_config { }; - Genode::Vm_connection::Vcpu _vm_vcpu; - State & _state; - Genode::Avl_tree _reg_tree {}; + struct State_container { State &ref; }; + + unsigned _vcpu_id; + bool _active { true }; + Vm & _vm; + Genode::Vm_connection & _vm_session; + Genode::Heap & _heap; + Signal_handler _vm_handler; + Genode::Vm_connection::Exit_config _exit_config { }; + Genode::Vm_connection::Vcpu _vm_vcpu; + Genode::Avl_tree _reg_tree {}; + Genode::Constructible _state {}; + Semaphore _cpu_ready {}; + /*********************** @@ -227,14 +249,15 @@ class Vmm::Cpu_base Generic_timer _timer; void _handle_nothing() {} - bool _handle_sys_reg(); - void _handle_brk(); - void _handle_wfi(); - void _handle_sync(); - void _handle_irq(); - void _handle_data_abort(); - void _handle_hyper_call(); - void _update_state(); + void _handle_startup(State &state); + bool _handle_sys_reg(State &state); + void _handle_brk(State &state); + void _handle_wfi(State &state); + void _handle_sync(State &state); + void _handle_irq(State &state); + void _handle_data_abort(State &state); + void _handle_hyper_call(State &state); + void _update_state(State &state); public: diff --git a/repos/os/src/server/vmm/generic_timer.cc b/repos/os/src/server/vmm/generic_timer.cc index f0e77fbaa5..f98e869d48 100644 --- a/repos/os/src/server/vmm/generic_timer.cc +++ b/repos/os/src/server/vmm/generic_timer.cc @@ -1,11 +1,12 @@ /* * \brief VMM ARM Generic timer device model * \author Stefan Kalkowski + * \author Benjamin Lamowski * \date 2019-08-20 */ /* - * Copyright (C) 2019 Genode Labs GmbH + * Copyright (C) 2019-2023 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU Affero General Public License version 3. @@ -16,22 +17,28 @@ using Vmm::Generic_timer; -bool Generic_timer::_enabled() { - return Ctrl::Enabled::get(_cpu.state().timer.control); } +bool Generic_timer::_enabled(Vm_state &state) +{ + return Ctrl::Enabled::get(state.timer.control); +} + +bool Generic_timer::_masked(Vm_state &state) +{ + return Ctrl::Imask::get(state.timer.control); +} -bool Generic_timer::_masked() { - return Ctrl::Imask::get(_cpu.state().timer.control); } - - -bool Generic_timer::_pending() { - return Ctrl::Istatus::get(_cpu.state().timer.control); } +bool Generic_timer::_pending(Vm_state &state) +{ + return Ctrl::Istatus::get(state.timer.control); +} void Generic_timer::_handle_timeout(Genode::Duration) { - _cpu.handle_signal([this] (void) { - if (_enabled() && !_masked()) handle_irq(); + _cpu.handle_signal([this](Vm_state &state) { + if (_enabled(state) && !_masked(state)) + handle_irq(state); }); } @@ -45,20 +52,19 @@ Generic_timer::Generic_timer(Genode::Env & env, _irq(irq), _cpu(cpu) { - _cpu.state().timer.irq = true; _irq.handler(*this); } -void Generic_timer::schedule_timeout() +void Generic_timer::schedule_timeout(Vm_state &state) { - if (_pending()) { - handle_irq(); + if (_pending(state)) { + handle_irq(state); return; } - if (_enabled()) { - Genode::uint64_t usecs = _usecs_left(); + if (_enabled(state)) { + Genode::uint64_t usecs = _usecs_left(state); if (usecs) { _timeout.schedule(Genode::Microseconds(usecs)); } else _handle_timeout(Genode::Duration(Genode::Microseconds(0))); @@ -72,23 +78,29 @@ void Generic_timer::cancel_timeout() } -void Generic_timer::handle_irq() +void Generic_timer::handle_irq(Vm_state &state) { _irq.assert(); - _cpu.state().timer.irq = false; + state.timer.irq = false; } void Generic_timer::eoi() { - _cpu.state().timer.irq = true; + Genode::Vm_state &state = _cpu.state(); + state.timer.irq = false; }; -void Generic_timer::dump() +void Generic_timer::dump(Vm_state &state) { using namespace Genode; - log(" timer.ctl = ", Hex(_cpu.state().timer.control, Hex::PREFIX, Hex::PAD)); - log(" timer.cmp = ", Hex(_cpu.state().timer.compare, Hex::PREFIX, Hex::PAD)); + log(" timer.ctl = ", Hex(state.timer.control, Hex::PREFIX, Hex::PAD)); + log(" timer.cmp = ", Hex(state.timer.compare, Hex::PREFIX, Hex::PAD)); +} + +void Generic_timer::setup_state(Vm_state &state) +{ + state.timer.irq = true; } diff --git a/repos/os/src/server/vmm/generic_timer.h b/repos/os/src/server/vmm/generic_timer.h index 3f0d7fba2b..da64d94e29 100644 --- a/repos/os/src/server/vmm/generic_timer.h +++ b/repos/os/src/server/vmm/generic_timer.h @@ -1,11 +1,12 @@ /* * \brief VMM ARM Generic timer device model * \author Stefan Kalkowski + * \author Benjamin Lamowski * \date 2019-08-20 */ /* - * Copyright (C) 2019 Genode Labs GmbH + * Copyright (C) 2019-2023 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU Affero General Public License version 3. @@ -26,6 +27,8 @@ namespace Vmm { class Generic_timer; } +using Genode::Vm_state; + class Vmm::Generic_timer : Gic::Irq::Irq_handler { private: @@ -44,12 +47,12 @@ class Vmm::Generic_timer : Gic::Irq::Irq_handler Genode::uint64_t _ticks_per_ms(); - bool _enabled(); - bool _masked(); - bool _pending(); + bool _enabled(Vm_state &state); + bool _masked(Vm_state &state); + bool _pending(Vm_state &state); void _handle_timeout(Genode::Duration); - Genode::uint64_t _usecs_left(); + Genode::uint64_t _usecs_left(Vm_state &state); public: @@ -58,10 +61,11 @@ class Vmm::Generic_timer : Gic::Irq::Irq_handler Gic::Irq & irq, Cpu_base & cpu); - void schedule_timeout(); + void schedule_timeout(Vm_state &state); void cancel_timeout(); - void handle_irq(); - void dump(); + void handle_irq(Vm_state &state); + void dump(Vm_state &state); + static void setup_state(Vm_state &state); /***************** diff --git a/repos/os/src/server/vmm/gic.cc b/repos/os/src/server/vmm/gic.cc index 7517ff1a3f..3461d467d8 100644 --- a/repos/os/src/server/vmm/gic.cc +++ b/repos/os/src/server/vmm/gic.cc @@ -1,11 +1,12 @@ /* * \brief VMM ARM Generic Interrupt Controller v2 device model * \author Stefan Kalkowski + * \author Benjamin Lamowski * \date 2019-08-05 */ /* - * Copyright (C) 2019 Genode Labs GmbH + * Copyright (C) 2019-2023 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU Affero General Public License version 3. @@ -163,29 +164,30 @@ Gic::Irq & Gic::Gicd_banked::irq(unsigned i) } -void Gic::Gicd_banked::handle_irq() +void Gic::Gicd_banked::handle_irq(State &state) { - unsigned i = _cpu.state().irqs.virtual_irq; + unsigned i = state.irqs.virtual_irq; if (i > MAX_IRQ) return; irq(i).deassert(); - _cpu.state().irqs.virtual_irq = SPURIOUS; + state.irqs.virtual_irq = SPURIOUS; } -bool Gic::Gicd_banked::pending_irq() +bool Gic::Gicd_banked::pending_irq(State &state) { Genode::Mutex::Guard guard(big_gic_lock()); - if (_cpu.state().irqs.virtual_irq != SPURIOUS) return true; + if (state.irqs.virtual_irq != SPURIOUS) + return true; Irq * i = _gic._pending_list.highest_enabled(); Irq * j = _pending_list.highest_enabled(); Irq * n = j; if (i && ((j && j->priority() > i->priority()) || !j)) n = i; if (!n) return false; - _cpu.state().irqs.virtual_irq = n->number(); + state.irqs.virtual_irq = n->number(); n->activate(); return true; } @@ -200,8 +202,6 @@ Gic::Gicd_banked::Gicd_banked(Cpu_base & cpu, Gic & gic, Mmio_bus & bus) for (unsigned i = 0; i < MAX_PPI; i++) _ppi[i].construct(i+MAX_SGI, Irq::PPI, _pending_list); - _cpu.state().irqs.last_irq = SPURIOUS; - _cpu.state().irqs.virtual_irq = SPURIOUS; if (gic.version() >= 3) { _rdist.construct(GICR_MMIO_START + @@ -211,6 +211,12 @@ Gic::Gicd_banked::Gicd_banked(Cpu_base & cpu, Gic & gic, Mmio_bus & bus) } } +void Gic::Gicd_banked::setup_state(State &state) +{ + state.irqs.last_irq = SPURIOUS; + state.irqs.virtual_irq = SPURIOUS; +} + Register Gic::Irq_reg::read(Address_range & access, Cpu & cpu) { diff --git a/repos/os/src/server/vmm/gic.h b/repos/os/src/server/vmm/gic.h index a514aea9f5..e3dacbcac2 100644 --- a/repos/os/src/server/vmm/gic.h +++ b/repos/os/src/server/vmm/gic.h @@ -1,11 +1,12 @@ /* * \brief VMM ARM Generic Interrupt Controller device model * \author Stefan Kalkowski + * \author Benjamin Lamowski * \date 2019-08-05 */ /* - * Copyright (C) 2019 Genode Labs GmbH + * Copyright (C) 2019-2023 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU Affero General Public License version 3. @@ -15,6 +16,7 @@ #define _SRC__SERVER__VMM__GIC_H_ #include +#include #include #include @@ -134,9 +136,10 @@ class Vmm::Gic : public Vmm::Mmio_device { public: - Irq & irq(unsigned num); - void handle_irq(); - bool pending_irq(); + Irq & irq(unsigned num); + void handle_irq(State &state); + bool pending_irq(State &state); + static void setup_state(State &state); Gicd_banked(Cpu_base & cpu, Gic & gic, Mmio_bus & bus); diff --git a/repos/os/src/server/vmm/mmio.cc b/repos/os/src/server/vmm/mmio.cc index dd3cf8570c..7c5f22a2a7 100644 --- a/repos/os/src/server/vmm/mmio.cc +++ b/repos/os/src/server/vmm/mmio.cc @@ -1,11 +1,12 @@ /* * \brief VMM mmio abstractions * \author Stefan Kalkowski + * \author Benjamin Lamowski * \date 2019-07-18 */ /* - * Copyright (C) 2019 Genode Labs GmbH + * Copyright (C) 2019-2023 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU Affero General Public License version 3. @@ -79,12 +80,10 @@ void Mmio_device::write(Address_range & access, Cpu & cpu, Register value) void Mmio_device::add(Mmio_register & reg) { _registers.add(reg); } -void Vmm::Mmio_bus::handle_memory_access(Vmm::Cpu & cpu) +void Vmm::Mmio_bus::handle_memory_access(State &state, Vmm::Cpu &cpu) { using namespace Genode; - Cpu::State & state = cpu.state(); - struct Iss : Cpu::Esr { struct Write : Bitfield<6, 1> {}; diff --git a/repos/os/src/server/vmm/mmio.h b/repos/os/src/server/vmm/mmio.h index 4187d392fe..a585a9aec4 100644 --- a/repos/os/src/server/vmm/mmio.h +++ b/repos/os/src/server/vmm/mmio.h @@ -1,11 +1,12 @@ /* * \brief VMM mmio abstractions * \author Stefan Kalkowski + * \author Benjamin Lamowski * \date 2019-07-18 */ /* - * Copyright (C) 2019 Genode Labs GmbH + * Copyright (C) 2019-2023 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU Affero General Public License version 3. @@ -15,6 +16,7 @@ #define _SRC__SERVER__VMM__MMIO_H_ #include +#include namespace Vmm { class Cpu; @@ -98,7 +100,7 @@ class Vmm::Mmio_device : public Vmm::Address_range struct Vmm::Mmio_bus : Vmm::Address_space { - void handle_memory_access(Cpu & cpu); + void handle_memory_access(State &state, Cpu &cpu); }; #endif /* _SRC__SERVER__VMM__MMIO_H_ */ diff --git a/repos/os/src/server/vmm/spec/arm_v7/cpu.cc b/repos/os/src/server/vmm/spec/arm_v7/cpu.cc index b46da70b18..980a5d7688 100644 --- a/repos/os/src/server/vmm/spec/arm_v7/cpu.cc +++ b/repos/os/src/server/vmm/spec/arm_v7/cpu.cc @@ -1,11 +1,12 @@ /* * \brief VMM cpu object * \author Stefan Kalkowski + * \author Benjamin Lamowski * \date 2019-07-18 */ /* - * Copyright (C) 2019 Genode Labs GmbH + * Copyright (C) 2019-2023 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU Affero General Public License version 3. @@ -13,13 +14,14 @@ #include #include #include +#include using Vmm::Cpu_base; using Vmm::Cpu; using Vmm::Gic; using namespace Genode; -addr_t Cpu_base::State::reg(addr_t idx) const +addr_t Vmm::State::reg(addr_t idx) const { if (idx > 15) return 0; @@ -29,7 +31,7 @@ addr_t Cpu_base::State::reg(addr_t idx) const } -void Cpu_base::State::reg(addr_t idx, addr_t v) +void Vmm::State::reg(addr_t idx, addr_t v) { if (idx > 15) return; @@ -62,29 +64,30 @@ Cpu_base::System_register::Iss::mask_encoding(access_t v) } -void Cpu_base::_handle_brk() +void Cpu_base::_handle_brk(State &) { error(__func__, " not implemented yet"); } -void Cpu_base::handle_exception() +void Cpu_base::handle_exception(State & state) { /* check exception reason */ - switch (_state.cpu_exception) { + switch (state.cpu_exception) { case Cpu::NO_EXCEPTION: break; case Cpu::FIQ: [[fallthrough]]; - case Cpu::IRQ: _handle_irq(); break; - case Cpu::TRAP: _handle_sync(); break; + case Cpu::IRQ: _handle_irq(state); break; + case Cpu::TRAP: _handle_sync(state); break; + case VCPU_EXCEPTION_STARTUP: _handle_startup(state); break; default: throw Exception("Curious exception ", - _state.cpu_exception, " occured"); + state.cpu_exception, " occured"); } - _state.cpu_exception = Cpu::NO_EXCEPTION; + state.cpu_exception = Cpu::NO_EXCEPTION; } -void Cpu_base::dump() +void Cpu_base::dump(State &state) { auto lambda = [] (unsigned i) { switch (i) { @@ -100,37 +103,37 @@ void Cpu_base::dump() log("VM state (", _active ? "active" : "inactive", ") :"); for (unsigned i = 0; i < 13; i++) { log(" r", i, " = ", - Hex(_state.reg(i), Hex::PREFIX, Hex::PAD)); + Hex(state.reg(i), Hex::PREFIX, Hex::PAD)); } - log(" sp = ", Hex(_state.sp, Hex::PREFIX, Hex::PAD)); - log(" lr = ", Hex(_state.lr, Hex::PREFIX, Hex::PAD)); - log(" ip = ", Hex(_state.ip, Hex::PREFIX, Hex::PAD)); - log(" cpsr = ", Hex(_state.cpsr, Hex::PREFIX, Hex::PAD)); + log(" sp = ", Hex(state.sp, Hex::PREFIX, Hex::PAD)); + log(" lr = ", Hex(state.lr, Hex::PREFIX, Hex::PAD)); + log(" ip = ", Hex(state.ip, Hex::PREFIX, Hex::PAD)); + log(" cpsr = ", Hex(state.cpsr, Hex::PREFIX, Hex::PAD)); for (unsigned i = 0; i < State::Mode_state::MAX; i++) { log(" sp_", lambda(i), " = ", - Hex(_state.mode[i].sp, Hex::PREFIX, Hex::PAD)); + Hex(state.mode[i].sp, Hex::PREFIX, Hex::PAD)); log(" lr_", lambda(i), " = ", - Hex(_state.mode[i].lr, Hex::PREFIX, Hex::PAD)); + Hex(state.mode[i].lr, Hex::PREFIX, Hex::PAD)); log(" spsr_", lambda(i), " = ", - Hex(_state.mode[i].spsr, Hex::PREFIX, Hex::PAD)); + Hex(state.mode[i].spsr, Hex::PREFIX, Hex::PAD)); } - log(" exception = ", _state.cpu_exception); - log(" esr_el2 = ", Hex(_state.esr_el2, Hex::PREFIX, Hex::PAD)); - log(" hpfar_el2 = ", Hex(_state.hpfar_el2, Hex::PREFIX, Hex::PAD)); - log(" far_el2 = ", Hex(_state.far_el2, Hex::PREFIX, Hex::PAD)); - log(" hifar = ", Hex(_state.hifar, Hex::PREFIX, Hex::PAD)); - log(" dfsr = ", Hex(_state.dfsr, Hex::PREFIX, Hex::PAD)); - log(" ifsr = ", Hex(_state.ifsr, Hex::PREFIX, Hex::PAD)); - log(" sctrl = ", Hex(_state.sctrl, Hex::PREFIX, Hex::PAD)); - _timer.dump(); + log(" exception = ", state.cpu_exception); + log(" esr_el2 = ", Hex(state.esr_el2, Hex::PREFIX, Hex::PAD)); + log(" hpfar_el2 = ", Hex(state.hpfar_el2, Hex::PREFIX, Hex::PAD)); + log(" far_el2 = ", Hex(state.far_el2, Hex::PREFIX, Hex::PAD)); + log(" hifar = ", Hex(state.hifar, Hex::PREFIX, Hex::PAD)); + log(" dfsr = ", Hex(state.dfsr, Hex::PREFIX, Hex::PAD)); + log(" ifsr = ", Hex(state.ifsr, Hex::PREFIX, Hex::PAD)); + log(" sctrl = ", Hex(state.sctrl, Hex::PREFIX, Hex::PAD)); + _timer.dump(state); } -void Cpu_base::initialize_boot(addr_t ip, addr_t dtb) +void Cpu_base::initialize_boot(State &state, addr_t ip, addr_t dtb) { - state().reg(1, 0xffffffff); /* invalid machine type */ - state().reg(2, dtb); - state().ip = ip; + state.reg(1, 0xffffffff); /* invalid machine type */ + state.reg(2, dtb); + state.ip = ip; } @@ -153,6 +156,13 @@ addr_t Cpu::Ccsidr::read() const return 0; } +void Cpu::setup_state(State &state) +{ + state.cpsr = 0x93; /* el1 mode and IRQs disabled */ + state.sctrl = 0xc50078; + state.vmpidr = (1UL << 31) | cpu_id(); +} + Cpu::Cpu(Vm & vm, Vm_connection & vm_session, @@ -184,7 +194,4 @@ Cpu::Cpu(Vm & vm, _sr_ccsidr (_sr_csselr, _reg_tree), _sr_actlr (1, 0, 0, 1, "ACTLR", true, 0x0, _reg_tree) { - _state.cpsr = 0x93; /* el1 mode and IRQs disabled */ - _state.sctrl = 0xc50078; - _state.vmpidr = (1UL << 31) | cpu_id(); } diff --git a/repos/os/src/server/vmm/spec/arm_v7/cpu.h b/repos/os/src/server/vmm/spec/arm_v7/cpu.h index 19f348104c..1e3a9b708d 100644 --- a/repos/os/src/server/vmm/spec/arm_v7/cpu.h +++ b/repos/os/src/server/vmm/spec/arm_v7/cpu.h @@ -1,11 +1,12 @@ /* * \brief VMM cpu object * \author Stefan Kalkowski + * \author Benjamin Lamowski * \date 2019-07-18 */ /* - * Copyright (C) 2019 Genode Labs GmbH + * Copyright (C) 2019-2023 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU Affero General Public License version 3. @@ -40,9 +41,11 @@ class Vmm::Cpu : public Vmm::Cpu_base DATA_ABORT, IRQ, FIQ, - TRAP + TRAP, }; + void setup_state(State & state) override; + private: struct Ccsidr : System_register diff --git a/repos/os/src/server/vmm/spec/arm_v7/generic_timer.cc b/repos/os/src/server/vmm/spec/arm_v7/generic_timer.cc index a5c78d8666..3c55a0d8fa 100644 --- a/repos/os/src/server/vmm/spec/arm_v7/generic_timer.cc +++ b/repos/os/src/server/vmm/spec/arm_v7/generic_timer.cc @@ -1,11 +1,12 @@ /* * \brief VMM ARM Generic timer device model * \author Stefan Kalkowski + * \author Benjamin Lamowski * \date 2019-08-20 */ /* - * Copyright (C) 2019 Genode Labs GmbH + * Copyright (C) 2019-2023 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU Affero General Public License version 3. @@ -28,14 +29,14 @@ Genode::uint64_t Generic_timer::_ticks_per_ms() } -Genode::uint64_t Generic_timer::_usecs_left() +Genode::uint64_t Generic_timer::_usecs_left(Vm_state &state) { Genode::uint64_t count; Genode::uint32_t low, high; asm volatile("mrrc p15, 0, %0, %1, c14" : "=r" (low), "=r" (high)); count = (Genode::uint64_t)high << 32 | (Genode::uint64_t)low; - count -= _cpu.state().timer.offset; - if (count > _cpu.state().timer.compare) return 0; - return Genode::timer_ticks_to_us(_cpu.state().timer.compare - count, + count -= state.timer.offset; + if (count > state.timer.compare) return 0; + return Genode::timer_ticks_to_us(state.timer.compare - count, _ticks_per_ms()); } diff --git a/repos/os/src/server/vmm/spec/arm_v8/cpu.cc b/repos/os/src/server/vmm/spec/arm_v8/cpu.cc index 2c0e7ab7ab..e1c0823734 100644 --- a/repos/os/src/server/vmm/spec/arm_v8/cpu.cc +++ b/repos/os/src/server/vmm/spec/arm_v8/cpu.cc @@ -1,16 +1,18 @@ /* * \brief VMM cpu object * \author Stefan Kalkowski + * \author Benjamin Lamowski * \date 2019-07-18 */ /* - * Copyright (C) 2019 Genode Labs GmbH + * Copyright (C) 2019-2023 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU Affero General Public License version 3. */ #include +#include #include #include @@ -19,14 +21,14 @@ using Vmm::Cpu; using Vmm::Gic; using namespace Genode; -addr_t Cpu_base::State::reg(addr_t idx) const +addr_t Vmm::State::reg(addr_t idx) const { if (idx > 30) return 0; return r[idx]; } -void Cpu_base::State::reg(addr_t idx, addr_t v) +void Vmm::State::reg(addr_t idx, addr_t v) { if (idx > 30) return; r[idx] = v; @@ -58,40 +60,41 @@ Cpu_base::System_register::Iss::mask_encoding(access_t v) } -void Cpu_base::_handle_brk() +void Cpu_base::_handle_brk(State & state) { addr_t offset = 0x0; - if (!(_state.pstate & 0b100)) { + if (!(state.pstate & 0b100)) { offset = 0x400; - } else if (_state.pstate & 0b1) { + } else if (state.pstate & 0b1) { offset = 0x200; } /* 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; + 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; } -void Cpu_base::handle_exception() +void Cpu_base::handle_exception(State &state) { /* check exception reason */ - switch (_state.exception_type) { + switch (state.exception_type) { case Cpu::NO_EXCEPTION: break; - case Cpu::AARCH64_IRQ: _handle_irq(); break; - case Cpu::AARCH64_SYNC: _handle_sync(); break; + case Cpu::AARCH64_IRQ: _handle_irq(state); break; + case Cpu::AARCH64_SYNC: _handle_sync(state); break; + case VCPU_EXCEPTION_STARTUP: _handle_startup(state); break; default: throw Exception("Curious exception ", - _state.exception_type, " occured"); + state.exception_type, " occured"); } - _state.exception_type = Cpu::NO_EXCEPTION; + state.exception_type = Cpu::NO_EXCEPTION; } -void Cpu_base::dump() +void Cpu_base::dump(State &state) { auto lambda = [] (addr_t exc) { switch (exc) { @@ -110,22 +113,24 @@ void Cpu_base::dump() log("VM state (", _active ? "active" : "inactive", ") :"); for (unsigned i = 0; i < 31; i++) { log(" r", i, " = ", - Hex(_state.r[i], Hex::PREFIX, Hex::PAD)); + Hex(state.r[i], Hex::PREFIX, Hex::PAD)); } - log(" sp = ", Hex(_state.sp, Hex::PREFIX, Hex::PAD)); - log(" ip = ", Hex(_state.ip, Hex::PREFIX, Hex::PAD)); - log(" sp_el1 = ", Hex(_state.sp_el1, Hex::PREFIX, Hex::PAD)); - log(" elr_el1 = ", Hex(_state.elr_el1, Hex::PREFIX, Hex::PAD)); - log(" pstate = ", Hex(_state.pstate, Hex::PREFIX, Hex::PAD)); - log(" exception = ", _state.exception_type, " (", - lambda(_state.exception_type), ")"); - log(" esr_el2 = ", Hex(_state.esr_el2, Hex::PREFIX, Hex::PAD)); - _timer.dump(); + log(" sp = ", Hex(state.sp, Hex::PREFIX, Hex::PAD)); + log(" ip = ", Hex(state.ip, Hex::PREFIX, Hex::PAD)); + log(" sp_el1 = ", Hex(state.sp_el1, Hex::PREFIX, Hex::PAD)); + log(" elr_el1 = ", Hex(state.elr_el1, Hex::PREFIX, Hex::PAD)); + log(" pstate = ", Hex(state.pstate, Hex::PREFIX, Hex::PAD)); + log(" exception = ", state.exception_type, " (", + lambda(state.exception_type), ")"); + log(" esr_el2 = ", Hex(state.esr_el2, Hex::PREFIX, Hex::PAD)); + _timer.dump(state); } addr_t Cpu::Ccsidr::read() const { + State & state = cpu.state(); + struct Clidr : Genode::Register<32> { enum Cache_entry { @@ -198,10 +203,25 @@ void Cpu::Icc_sgi1r_el1::write(addr_t v) }; -void Cpu_base::initialize_boot(addr_t ip, addr_t dtb) +void Cpu_base::initialize_boot(State &state, addr_t ip, addr_t dtb) { - state().reg(0, dtb); - state().ip = ip; + state.reg(0, dtb); + state.ip = ip; +} + + +void Cpu::setup_state(State &state) +{ + _sr_id_aa64isar0_el1.write(state.id_aa64isar0_el1); + _sr_id_aa64isar1_el1.write(state.id_aa64isar1_el1); + _sr_id_aa64mmfr0_el1.write(state.id_aa64mmfr0_el1); + _sr_id_aa64mmfr1_el1.write(state.id_aa64mmfr1_el1); + _sr_id_aa64mmfr2_el1.write(state.id_aa64mmfr2_el1); + _sr_id_aa64pfr0_el1.write( _sr_id_aa64pfr0_el1.reset_value( + state.id_aa64pfr0_el1)); + _sr_clidr_el1.write(state.clidr_el1); + state.pstate = 0b1111000101; /* el1 mode and IRQs disabled */ + state.vmpidr_el2 = cpu_id(); } @@ -218,20 +238,20 @@ Cpu::Cpu(Vm & vm, _sr_id_aa64afr1_el1 (3, 0, 0, 5, 5, "ID_AA64AFR1_EL1", false, 0x0, _reg_tree), _sr_id_aa64dfr0_el1 (3, 0, 0, 5, 0, "ID_AA64DFR0_EL1", false, 0x6, _reg_tree), _sr_id_aa64dfr1_el1 (3, 0, 0, 5, 1, "ID_AA64DFR1_EL1", false, 0x0, _reg_tree), - _sr_id_aa64isar0_el1(3, 0, 0, 6, 0, "ID_AA64ISAR0_EL1", false, _state.id_aa64isar0_el1, _reg_tree), - _sr_id_aa64isar1_el1(3, 0, 0, 6, 1, "ID_AA64ISAR1_EL1", false, _state.id_aa64isar1_el1, _reg_tree), - _sr_id_aa64mmfr0_el1(3, 0, 0, 7, 0, "ID_AA64MMFR0_EL1", false, _state.id_aa64mmfr0_el1, _reg_tree), - _sr_id_aa64mmfr1_el1(3, 0, 0, 7, 1, "ID_AA64MMFR1_EL1", false, _state.id_aa64mmfr1_el1, _reg_tree), - _sr_id_aa64mmfr2_el1(3, 0, 0, 7, 2, "ID_AA64MMFR2_EL1", false, _state.id_aa64mmfr2_el1, _reg_tree), - _sr_id_aa64pfr0_el1 (_state.id_aa64pfr0_el1, _reg_tree), + _sr_id_aa64isar0_el1(3, 0, 0, 6, 0, "ID_AA64ISAR0_EL1", false, 0x0, _reg_tree), + _sr_id_aa64isar1_el1(3, 0, 0, 6, 1, "ID_AA64ISAR1_EL1", false, 0x0, _reg_tree), + _sr_id_aa64mmfr0_el1(3, 0, 0, 7, 0, "ID_AA64MMFR0_EL1", false, 0x0, _reg_tree), + _sr_id_aa64mmfr1_el1(3, 0, 0, 7, 1, "ID_AA64MMFR1_EL1", false, 0x0, _reg_tree), + _sr_id_aa64mmfr2_el1(3, 0, 0, 7, 2, "ID_AA64MMFR2_EL1", false, 0x0, _reg_tree), + _sr_id_aa64pfr0_el1 (0x0, _reg_tree), _sr_id_aa64pfr1_el1 (3, 0, 0, 4, 1, "ID_AA64PFR1_EL1", false, 0x0, _reg_tree), _sr_id_aa64zfr0_el1 (3, 0, 0, 4, 4, "ID_AA64ZFR0_EL1", false, 0x0, _reg_tree), _sr_aidr_el1 (3, 0, 1, 0, 7, "AIDR_EL1", false, 0x0, _reg_tree), _sr_revidr_el1 (3, 0, 0, 0, 6, "REVIDR_EL1", false, 0x0, _reg_tree), - _sr_clidr_el1 (3, 0, 1, 0, 1, "CLIDR_EL1", false, _state.clidr_el1, _reg_tree), + _sr_clidr_el1 (3, 0, 1, 0, 1, "CLIDR_EL1", false, 0x0, _reg_tree), _sr_csselr_el1 (3, 0, 2, 0, 0, "CSSELR_EL1", true, 0x0, _reg_tree), _sr_ctr_el0 (_reg_tree), - _sr_ccsidr_el1 (_sr_csselr_el1, _state, _reg_tree), + _sr_ccsidr_el1 (_sr_csselr_el1, *this, _reg_tree), _sr_pmuserenr_el0 (3, 9, 3, 14, 0, "PMUSEREN_EL0", true, 0x0, _reg_tree), _sr_dbgbcr0 (2, 0, 0, 0, 5, "DBGBCR_EL1", true, 0x0, _reg_tree), _sr_dbgbvr0 (2, 0, 0, 0, 4, "DBGBVR_EL1", true, 0x0, _reg_tree), @@ -241,7 +261,4 @@ Cpu::Cpu(Vm & vm, _sr_osdlr (2, 1, 0, 3, 4, "OSDLR_EL1", true, 0x0, _reg_tree), _sr_oslar (2, 1, 0, 0, 4, "OSLAR_EL1", true, 0x0, _reg_tree), _sr_sgi1r_el1 (_reg_tree, vm) -{ - _state.pstate = 0b1111000101; /* el1 mode and IRQs disabled */ - _state.vmpidr_el2 = cpu_id(); -} +{ } diff --git a/repos/os/src/server/vmm/spec/arm_v8/cpu.h b/repos/os/src/server/vmm/spec/arm_v8/cpu.h index 626dac9e21..8392aa8e56 100644 --- a/repos/os/src/server/vmm/spec/arm_v8/cpu.h +++ b/repos/os/src/server/vmm/spec/arm_v8/cpu.h @@ -1,11 +1,12 @@ /* * \brief VMM cpu object * \author Stefan Kalkowski + * \author Benjamin Lamowski * \date 2019-07-18 */ /* - * Copyright (C) 2019 Genode Labs GmbH + * Copyright (C) 2019-2023 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU Affero General Public License version 3. @@ -40,9 +41,11 @@ class Vmm::Cpu : public Vmm::Cpu_base AARCH32_IRQ = 0x680, AARCH32_FIQ = 0x700, AARCH32_SERROR = 0x780, - NO_EXCEPTION = 0xffff + NO_EXCEPTION = 0xffff, }; + void setup_state(State & state) override; + private: class Id_aa64pfr0 : public System_register, @@ -57,7 +60,9 @@ class Vmm::Cpu : public Vmm::Cpu_base struct Ras : Bitfield<28, 4> { enum { NOT_IMPLEMENTED }; }; struct Sve : Bitfield<32, 4> { enum { NOT_IMPLEMENTED }; }; - access_t _reset_value(access_t orig) + public: + + access_t reset_value(access_t orig) { El0::set(orig, El0::AARCH64_ONLY); El1::set(orig, El1::AARCH64_ONLY); @@ -68,24 +73,22 @@ class Vmm::Cpu : public Vmm::Cpu_base return orig; } - public: - Id_aa64pfr0(Genode::uint64_t id_aa64pfr0, Genode::Avl_tree & tree) : System_register(3, 0, 0, 4, 0, "ID_AA64PFR0_EL1", false, - _reset_value(id_aa64pfr0), tree) {} + reset_value(id_aa64pfr0), tree) {} }; struct Ccsidr : System_register { System_register & csselr; - State & state; + Cpu & cpu; Ccsidr(System_register &csselr, - State & state, + Cpu & cpu, Genode::Avl_tree & tree) : System_register(3, 0, 1, 0, 0, "CCSIDR_EL1", false, 0x0, tree), - csselr(csselr), state(state) {} + csselr(csselr), cpu(cpu) {} virtual Genode::addr_t read() const override; }; diff --git a/repos/os/src/server/vmm/spec/arm_v8/generic_timer.cc b/repos/os/src/server/vmm/spec/arm_v8/generic_timer.cc index 16e82651ef..6310dff035 100644 --- a/repos/os/src/server/vmm/spec/arm_v8/generic_timer.cc +++ b/repos/os/src/server/vmm/spec/arm_v8/generic_timer.cc @@ -1,11 +1,12 @@ /* * \brief VMM ARM Generic timer device model * \author Stefan Kalkowski + * \author Benjamin Lamowski * \date 2019-08-20 */ /* - * Copyright (C) 2019 Genode Labs GmbH + * Copyright (C) 2019-2023 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU Affero General Public License version 3. @@ -28,12 +29,12 @@ Genode::uint64_t Generic_timer::_ticks_per_ms() } -Genode::uint64_t Generic_timer::_usecs_left() +Genode::uint64_t Generic_timer::_usecs_left(Vm_state &state) { Genode::uint64_t count; asm volatile("mrs %0, cntpct_el0" : "=r" (count)); - count -= _cpu.state().timer.offset; - if (count > _cpu.state().timer.compare) return 0; - return Genode::timer_ticks_to_us(_cpu.state().timer.compare - count, + count -= state.timer.offset; + if (count > state.timer.compare) return 0; + return Genode::timer_ticks_to_us(state.timer.compare - count, _ticks_per_ms()); } diff --git a/repos/os/src/server/vmm/state.h b/repos/os/src/server/vmm/state.h new file mode 100644 index 0000000000..47143322fa --- /dev/null +++ b/repos/os/src/server/vmm/state.h @@ -0,0 +1,32 @@ +/* + * \brief vCPU state + * \author Benjamin Lamowski + * \date 2023-06-22 + */ + +/* + * Copyright (C) 2023 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _SRC__SERVER__VMM__STATE_H_ +#define _SRC__SERVER__VMM__STATE_H_ + +#include + +using Genode::addr_t; +using Genode::Vm_state; + +namespace Genode { struct Vcpu_state : Vm_state { }; }; + +namespace Vmm { + struct State : Genode::Vcpu_state + { + addr_t reg(addr_t idx) const; + void reg(addr_t idx, addr_t v); + }; +} + +#endif /* _SRC__SERVER__VMM__STATE_H_ */ diff --git a/repos/os/src/server/vmm/vm.cc b/repos/os/src/server/vmm/vm.cc index e9ca4668df..790888b2e4 100644 --- a/repos/os/src/server/vmm/vm.cc +++ b/repos/os/src/server/vmm/vm.cc @@ -1,11 +1,12 @@ /* * \brief VMM example for ARMv8 virtualization * \author Stefan Kalkowski + * \author Benjamin Lamowski * \date 2019-07-18 */ /* - * Copyright (C) 2019 Genode Labs GmbH + * Copyright (C) 2019-2023 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU Affero General Public License version 3. @@ -161,10 +162,7 @@ Vm::Vm(Genode::Env & env, Heap & heap, Config & config) Genode::log("Start virtual machine ..."); - Cpu & cpu = boot_cpu(); - cpu.initialize_boot(_ram.base() + KERNEL_OFFSET, - _ram.base() + _dtb_offset()); - cpu.run(); + boot_cpu(); }; diff --git a/repos/os/src/server/vmm/vm.h b/repos/os/src/server/vmm/vm.h index 19e1f3965c..d5f7bbf6b1 100644 --- a/repos/os/src/server/vmm/vm.h +++ b/repos/os/src/server/vmm/vm.h @@ -1,11 +1,12 @@ /* * \brief VMM example for ARMv8 virtualization * \author Stefan Kalkowski + * \author Benjamin Lamowski * \date 2019-07-18 */ /* - * Copyright (C) 2019 Genode Labs GmbH + * Copyright (C) 2019-2023 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU Affero General Public License version 3. @@ -96,6 +97,14 @@ class Vmm::Vm for (Cpu_entry * ce = _cpu_list.first(); ce; ce = ce->next()) func(ce->cpu); } + + addr_t dtb_addr() { + return _ram.base() + _dtb_offset(); + } + + addr_t kernel_addr() { + return _ram.base() + KERNEL_OFFSET; + } }; #endif /* _SRC__SERVER__VMM__VM_H_ */