genode/repos/os/src/server/tz_vmm/spec/imx53/main.cc

155 lines
3.0 KiB
C++

/*
* \brief Virtual Machine Monitor
* \author Stefan Kalkowski
* \date 2012-06-25
*/
/*
* Copyright (C) 2008-2012 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.
*/
/* Genode includes */
#include <base/env.h>
#include <base/sleep.h>
#include <base/thread.h>
#include <drivers/board_base.h>
#include <drivers/trustzone.h>
#include <vm_state.h>
/* local includes */
#include <vm.h>
#include <m4if.h>
#include <serial.h>
#include <block.h>
using namespace Genode;
enum {
KERNEL_OFFSET = 0x8000,
MACH_TYPE_TABLET = 3011,
MACH_TYPE_QSB = 3273,
BOARD_REV_TABLET = 0x53321,
};
static const char* cmdline_tablet = "console=ttymxc0,115200";
void on_vmm_entry();
void on_vmm_exit();
namespace Vmm {
class Vmm;
}
class Vmm::Vmm : public Thread<8192>
{
private:
Signal_receiver _sig_rcv;
Signal_context _vm_context;
Vm *_vm;
Io_mem_connection _m4if_io_mem;
M4if _m4if;
Serial _serial;
Block _block;
void _handle_hypervisor_call()
{
enum {
FRAMEBUFFER = 0,
INPUT = 1,
SERIAL = 2,
BLOCK = 3,
};
switch (_vm->smc_arg_0()) {
case FRAMEBUFFER: break;
case INPUT: break;
case SERIAL: _serial.handle(_vm); break;
case BLOCK: _block.handle(_vm); break;
default:
PERR("Unknown hypervisor call!");
_vm->dump();
};
}
bool _handle_data_abort()
{
_vm->dump();
return false;
}
bool _handle_vm()
{
/* check exception reason */
switch (_vm->state()->cpu_exception) {
case Cpu_state::DATA_ABORT:
if (!_handle_data_abort()) {
PERR("Could not handle data-abort will exit!");
return false;
}
break;
case Cpu_state::SUPERVISOR_CALL:
_handle_hypervisor_call();
break;
default:
PERR("Curious exception occured");
_vm->dump();
return false;
}
return true;
}
protected:
void entry()
{
_vm->sig_handler(_sig_rcv.manage(&_vm_context));
_vm->start();
_vm->run();
while (true) {
Signal s = _sig_rcv.wait_for_signal();
on_vmm_entry();
if (s.context() == &_vm_context) {
if (_handle_vm())
_vm->run();
} else {
PWRN("Invalid context");
continue;
}
on_vmm_exit();
}
};
public:
Vmm(Vm *vm)
: Thread<8192>("vmm"),
_vm(vm),
_m4if_io_mem(Board_base::M4IF_BASE, Board_base::M4IF_SIZE),
_m4if((addr_t)env()->rm_session()->attach(_m4if_io_mem.dataspace()))
{
_m4if.set_region0(Trustzone::SECURE_RAM_BASE,
Trustzone::SECURE_RAM_SIZE);
}
};
int main()
{
static Vm vm("linux", cmdline_tablet,
Trustzone::NONSECURE_RAM_BASE, Trustzone::NONSECURE_RAM_SIZE,
KERNEL_OFFSET, MACH_TYPE_QSB);
static Vmm::Vmm vmm(&vm);
PINF("Start virtual machine ...");
vmm.start();
sleep_forever();
return 0;
}