2013-11-18 14:42:21 +01:00
|
|
|
/*
|
|
|
|
* \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>
|
2015-02-19 14:50:27 +01:00
|
|
|
#include <vm_state.h>
|
2013-11-18 14:42:21 +01:00
|
|
|
|
|
|
|
/* local includes */
|
|
|
|
#include <vm.h>
|
|
|
|
#include <m4if.h>
|
|
|
|
|
|
|
|
using namespace Genode;
|
|
|
|
|
|
|
|
enum {
|
|
|
|
KERNEL_OFFSET = 0x8000,
|
|
|
|
MACH_TYPE_TABLET = 3011,
|
|
|
|
MACH_TYPE_QSB = 3273,
|
|
|
|
BOARD_REV_TABLET = 0x53321,
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2013-11-27 17:12:39 +01:00
|
|
|
static const char* cmdline_tablet = "console=ttymxc0,115200";
|
2013-11-18 14:42:21 +01:00
|
|
|
|
|
|
|
|
|
|
|
namespace Vmm {
|
|
|
|
class Vmm;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
class Vmm::Vmm : public Thread<8192>
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
|
2013-11-27 17:12:39 +01:00
|
|
|
enum Devices {
|
|
|
|
FRAMEBUFFER,
|
|
|
|
INPUT,
|
|
|
|
};
|
|
|
|
|
2013-11-18 14:42:21 +01:00
|
|
|
Signal_receiver _sig_rcv;
|
|
|
|
Signal_context _vm_context;
|
|
|
|
Vm *_vm;
|
|
|
|
Io_mem_connection _m4if_io_mem;
|
|
|
|
M4if _m4if;
|
|
|
|
|
|
|
|
void _handle_hypervisor_call()
|
|
|
|
{
|
|
|
|
/* check device number*/
|
|
|
|
switch (_vm->state()->r0) {
|
2013-11-27 17:12:39 +01:00
|
|
|
case FRAMEBUFFER:
|
|
|
|
case INPUT:
|
|
|
|
break;
|
2013-11-18 14:42:21 +01:00
|
|
|
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();
|
2013-11-27 17:12:39 +01:00
|
|
|
_vm->run();
|
2013-11-18 14:42:21 +01:00
|
|
|
|
|
|
|
while (true) {
|
|
|
|
Signal s = _sig_rcv.wait_for_signal();
|
|
|
|
if (s.context() == &_vm_context) {
|
|
|
|
if (_handle_vm())
|
|
|
|
_vm->run();
|
|
|
|
} else {
|
|
|
|
PWRN("Invalid context");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
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()))
|
|
|
|
{
|
2014-02-12 15:56:52 +01:00
|
|
|
_m4if.set_region0(Trustzone::SECURE_RAM_BASE,
|
|
|
|
Trustzone::SECURE_RAM_SIZE);
|
2013-11-18 14:42:21 +01:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
int main()
|
|
|
|
{
|
|
|
|
static Vm vm("linux", "initrd.gz", cmdline_tablet,
|
|
|
|
Trustzone::NONSECURE_RAM_BASE, Trustzone::NONSECURE_RAM_SIZE,
|
2013-11-27 17:12:39 +01:00
|
|
|
KERNEL_OFFSET, MACH_TYPE_QSB);
|
2013-11-18 14:42:21 +01:00
|
|
|
static Vmm::Vmm vmm(&vm);
|
|
|
|
|
|
|
|
PINF("Start virtual machine ...");
|
|
|
|
vmm.start();
|
|
|
|
|
|
|
|
sleep_forever();
|
|
|
|
return 0;
|
|
|
|
}
|