181 lines
5.8 KiB
C++
181 lines
5.8 KiB
C++
/*
|
|
* \brief Virtual Machine Monitor VM definition
|
|
* \author Stefan Kalkowski
|
|
* \date 2012-06-25
|
|
*/
|
|
|
|
/*
|
|
* Copyright (C) 2012-2013 Genode Labs GmbH
|
|
*
|
|
* This file is part of the Genode OS framework, which is distributed
|
|
* under the terms of the GNU General Public License version 2.
|
|
*/
|
|
|
|
#ifndef _SRC__SERVER__VMM__INCLUDE__VM_H_
|
|
#define _SRC__SERVER__VMM__INCLUDE__VM_H_
|
|
|
|
/* Genode includes */
|
|
#include <base/elf.h>
|
|
#include <dataspace/client.h>
|
|
#include <io_mem_session/connection.h>
|
|
#include <rom_session/connection.h>
|
|
#include <vm_session/connection.h>
|
|
|
|
/* local includes */
|
|
#include <mmu.h>
|
|
|
|
class Vm_base {
|
|
|
|
protected:
|
|
|
|
enum { INITRD_OFFSET = 0x1000000, };
|
|
|
|
Genode::Vm_connection _vm_con;
|
|
Genode::Rom_connection _kernel_rom;
|
|
Genode::Rom_connection _initrd_rom;
|
|
Genode::Dataspace_client _kernel_cap;
|
|
Genode::Dataspace_client _initrd_cap;
|
|
const char* _cmdline;
|
|
Genode::Vm_state *_state;
|
|
Genode::Io_mem_connection _ram_iomem;
|
|
Ram _ram;
|
|
Genode::addr_t _kernel_offset;
|
|
unsigned long _mach_type;
|
|
unsigned long _board_rev;
|
|
|
|
void _load_kernel()
|
|
{
|
|
using namespace Genode;
|
|
|
|
addr_t addr = env()->rm_session()->attach(_kernel_cap);
|
|
memcpy((void*)(_ram.local() + _kernel_offset),
|
|
(void*)addr, _kernel_cap.size());
|
|
_state->ip = _ram.base() + _kernel_offset;
|
|
env()->rm_session()->detach((void*)addr);
|
|
}
|
|
|
|
void _load_initrd()
|
|
{
|
|
using namespace Genode;
|
|
|
|
addr_t addr = env()->rm_session()->attach(_initrd_cap);
|
|
memcpy((void*)(_ram.local() + INITRD_OFFSET),
|
|
(void*)addr, _initrd_cap.size());
|
|
env()->rm_session()->detach((void*)addr);
|
|
}
|
|
|
|
virtual Genode::addr_t _load_board_info() = 0;
|
|
|
|
public:
|
|
|
|
Vm_base(const char *kernel, const char *initrd, const char *cmdline,
|
|
Genode::addr_t ram_base, Genode::size_t ram_size,
|
|
Genode::addr_t kernel_offset, unsigned long mach_type,
|
|
unsigned long board_rev = 0)
|
|
: _kernel_rom(kernel),
|
|
_initrd_rom(initrd),
|
|
_kernel_cap(_kernel_rom.dataspace()),
|
|
_initrd_cap(_initrd_rom.dataspace()),
|
|
_cmdline(cmdline),
|
|
_state((Genode::Vm_state*)Genode::env()->rm_session()->attach(_vm_con.cpu_state())),
|
|
_ram_iomem(ram_base, ram_size),
|
|
_ram(ram_base, ram_size, (Genode::addr_t)Genode::env()->rm_session()->attach(_ram_iomem.dataspace())),
|
|
_kernel_offset(kernel_offset),
|
|
_mach_type(mach_type),
|
|
_board_rev(board_rev) { }
|
|
|
|
void start()
|
|
{
|
|
Genode::memset((void*)_state, 0, sizeof(Genode::Vm_state));
|
|
_load_kernel();
|
|
_load_initrd();
|
|
_state->cpsr = 0x93; /* SVC mode and IRQs disabled */
|
|
_state->r0 = 0;
|
|
_state->r1 = _mach_type;
|
|
_state->r2 = _ram.base() + _load_board_info(); /* board info addr */
|
|
}
|
|
|
|
void sig_handler(Genode::Signal_context_capability sig_cap) {
|
|
_vm_con.exception_handler(sig_cap); }
|
|
|
|
void run() { _vm_con.run(); }
|
|
void pause() { _vm_con.pause(); }
|
|
|
|
void dump()
|
|
{
|
|
using namespace Genode;
|
|
|
|
const char * const modes[] =
|
|
{ "und", "svc", "abt", "irq", "fiq" };
|
|
const char * const exc[] =
|
|
{ "invalid", "reset", "undefined", "smc", "pf_abort",
|
|
"data_abort", "irq", "fiq" };
|
|
|
|
printf("Cpu state:\n");
|
|
printf(" Register Virt Phys\n");
|
|
printf("---------------------------------\n");
|
|
printf(" r0 = %08lx [%08lx]\n",
|
|
_state->r0, va_to_pa(_state->r0));
|
|
printf(" r1 = %08lx [%08lx]\n",
|
|
_state->r1, va_to_pa(_state->r1));
|
|
printf(" r2 = %08lx [%08lx]\n",
|
|
_state->r2, va_to_pa(_state->r2));
|
|
printf(" r3 = %08lx [%08lx]\n",
|
|
_state->r3, va_to_pa(_state->r3));
|
|
printf(" r4 = %08lx [%08lx]\n",
|
|
_state->r4, va_to_pa(_state->r4));
|
|
printf(" r5 = %08lx [%08lx]\n",
|
|
_state->r5, va_to_pa(_state->r5));
|
|
printf(" r6 = %08lx [%08lx]\n",
|
|
_state->r6, va_to_pa(_state->r6));
|
|
printf(" r7 = %08lx [%08lx]\n",
|
|
_state->r7, va_to_pa(_state->r7));
|
|
printf(" r8 = %08lx [%08lx]\n",
|
|
_state->r8, va_to_pa(_state->r8));
|
|
printf(" r9 = %08lx [%08lx]\n",
|
|
_state->r9, va_to_pa(_state->r9));
|
|
printf(" r10 = %08lx [%08lx]\n",
|
|
_state->r10, va_to_pa(_state->r10));
|
|
printf(" r11 = %08lx [%08lx]\n",
|
|
_state->r11, va_to_pa(_state->r11));
|
|
printf(" r12 = %08lx [%08lx]\n",
|
|
_state->r12, va_to_pa(_state->r12));
|
|
printf(" sp = %08lx [%08lx]\n",
|
|
_state->sp, va_to_pa(_state->sp));
|
|
printf(" lr = %08lx [%08lx]\n",
|
|
_state->lr, va_to_pa(_state->lr));
|
|
printf(" ip = %08lx [%08lx]\n",
|
|
_state->ip, va_to_pa(_state->ip));
|
|
printf(" cpsr = %08lx\n", _state->cpsr);
|
|
for (unsigned i = 0;
|
|
i < Genode::Vm_state::Mode_state::MAX; i++) {
|
|
printf(" sp_%s = %08lx [%08lx]\n", modes[i],
|
|
_state->mode[i].sp, va_to_pa(_state->mode[i].sp));
|
|
printf(" lr_%s = %08lx [%08lx]\n", modes[i],
|
|
_state->mode[i].lr, va_to_pa(_state->mode[i].lr));
|
|
printf(" spsr_%s = %08lx [%08lx]\n", modes[i],
|
|
_state->mode[i].spsr, va_to_pa(_state->mode[i].spsr));
|
|
}
|
|
printf(" ttbr0 = %08lx\n", _state->ttbr[0]);
|
|
printf(" ttbr1 = %08lx\n", _state->ttbr[1]);
|
|
printf(" ttbrc = %08lx\n", _state->ttbrc);
|
|
printf(" dfar = %08lx [%08lx]\n",
|
|
_state->dfar, va_to_pa(_state->dfar));
|
|
printf(" exception = %s\n", exc[_state->cpu_exception]);
|
|
}
|
|
|
|
Genode::addr_t va_to_pa(Genode::addr_t va)
|
|
{
|
|
try {
|
|
Mmu mmu(_state, &_ram);
|
|
return mmu.phys_addr(va);
|
|
} catch(Ram::Invalid_addr) {}
|
|
return 0;
|
|
}
|
|
|
|
Genode::Vm_state *state() const { return _state; }
|
|
Ram *ram() { return &_ram; }
|
|
};
|
|
|
|
#endif /* _SRC__SERVER__VMM__INCLUDE__VM_H_ */
|