genode/repos/os/src/server/tz_vmm/vm_base.cc

135 lines
3.8 KiB
C++

/*
* \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 <base/attached_rom_dataspace.h>
/* local includes */
#include <vm_base.h>
#include <mmu.h>
using namespace Genode;
void Vm_base::_load_kernel()
{
Attached_rom_dataspace kernel(_env, _kernel.string());
memcpy((void*)(_ram.local() + _kernel_off),
kernel.local_addr<void>(), 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;
}