/* * \brief Virtual Machine Monitor VM definition * \author Stefan Kalkowski * \author Martin Stein * \date 2012-06-25 */ /* * Copyright (C) 2012-2017 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. */ /* Genode includes */ #include /* local includes */ #include #include using namespace Genode; void Vm_base::_load_kernel() { Attached_rom_dataspace kernel(_env, _kernel.string()); memcpy((void*)(_ram.local() + _kernel_off), kernel.local_addr(), kernel.size()); _state.ip = _ram.base() + _kernel_off; } Vm_base::Vm_base(Env &env, Kernel_name const &kernel, Command_line const &cmdline, addr_t ram_base, size_t ram_size, off_t kernel_off, Machine_type machine, Board_revision board, Allocator &alloc, Vm_handler_base &handler) : _env(env), _kernel(kernel), _cmdline(cmdline), _kernel_off(kernel_off), _machine(machine), _board(board), _ram(env, ram_base, ram_size), _vcpu_id(_vm.create_vcpu(alloc, env, handler)) { _state.irq_injection = 0; } void Vm_base::start() { memset((void*)&_state, 0, sizeof(Vm_state)); _load_kernel(); _load_kernel_surroundings(); _state.cpsr = 0x93; /* SVC mode and IRQs disabled */ _state.r0 = 0; _state.r1 = _machine.value; _state.r2 = _ram.base() + _board_info_offset(); } void Vm_base::inject_irq(unsigned irq) { if (_state.irq_injection) { throw Inject_irq_failed(); } _state.irq_injection = irq; } void Vm_base::dump() { char const *mod[] = { "und", "svc", "abt", "irq", "fiq" }; char const *exc[] = { "invalid", "reset", "undefined", "smc", "pf_abort", "data_abort", "irq", "fiq" }; auto log_adr_reg = [&] (char const *reg, addr_t val) { log(" ", reg, " = ", Hex(val, Hex::PREFIX, Hex::PAD), " ", Hex(va_to_pa(val), Hex::PREFIX, Hex::PAD)); }; auto log_mod_reg = [&] (char const *reg, addr_t val, char const *mod) { log(" ", reg, "_", mod, " = ", Hex(val, Hex::PREFIX, Hex::PAD), " ", Hex(va_to_pa(val), Hex::PREFIX, Hex::PAD)); }; log("Cpu state:"); log(" Register Virt Phys"); log("------------------------------------"); log_adr_reg("r0 ", _state.r0); log_adr_reg("r1 ", _state.r1); log_adr_reg("r2 ", _state.r2); log_adr_reg("r3 ", _state.r3); log_adr_reg("r4 ", _state.r4); log_adr_reg("r5 ", _state.r5); log_adr_reg("r6 ", _state.r6); log_adr_reg("r7 ", _state.r7); log_adr_reg("r8 ", _state.r8); log_adr_reg("r9 ", _state.r9); log_adr_reg("r10 ", _state.r10); log_adr_reg("r11 ", _state.r11); log_adr_reg("r12 ", _state.r12); log_adr_reg("sp ", _state.sp); log_adr_reg("lr ", _state.lr); log_adr_reg("ip ", _state.ip); log_adr_reg("cpsr ", _state.cpsr); for (unsigned i = 0; i < Vm_state::Mode_state::MAX; i++) { log_mod_reg("sp ", _state.mode[i].sp, mod[i]); log_mod_reg("lr ", _state.mode[i].lr, mod[i]); log_mod_reg("spsr ", _state.mode[i].spsr, mod[i]); } log(" ttbr0 = ", Hex(_state.ttbr[0], Hex::PREFIX, Hex::PAD)); log(" ttbr1 = ", Hex(_state.ttbr[1], Hex::PREFIX, Hex::PAD)); log(" ttbrc = ", Hex(_state.ttbrc , Hex::PREFIX, Hex::PAD)); log_adr_reg("dfar ", _state.dfar); log(" exception = ", exc[_state.cpu_exception]); } void Vm_base::smc_ret(addr_t const ret_0, addr_t const ret_1) { _state.r0 = ret_0; _state.r1 = ret_1; } addr_t Vm_base::va_to_pa(addr_t va) { try { Mmu mmu(_state, _ram); return mmu.phys_addr(va); } catch(Ram::Invalid_addr) { } return 0; }