From a7d7337b16f2dc21199dfafac3cbe78baf27aa94 Mon Sep 17 00:00:00 2001 From: Stefan Kalkowski Date: Mon, 18 Nov 2013 14:42:21 +0100 Subject: [PATCH] vmm: add i.MX53 platform as target (ref #954) --- .../platform/imx53/drivers/board_base.h | 3 + os/src/server/vmm/imx53/m4if.h | 61 +++ os/src/server/vmm/imx53/main.cc | 138 +++++++ os/src/server/vmm/imx53/target.mk | 5 + os/src/server/vmm/include/atag.h | 8 + os/src/server/vmm/include/bp_147.h | 130 ------ os/src/server/vmm/include/mmu.h | 91 +++++ os/src/server/vmm/include/ram.h | 48 +++ os/src/server/vmm/include/sp810.h | 45 --- os/src/server/vmm/include/sys_reg.h | 104 ----- os/src/server/vmm/include/tsc_380.h | 212 ---------- os/src/server/vmm/include/vm.h | 193 +++++++++ os/src/server/vmm/include/vm_state.h | 27 ++ os/src/server/vmm/main.cc | 371 ------------------ os/src/server/vmm/vea9x4/bp_147.h | 126 ++++++ os/src/server/vmm/vea9x4/main.cc | 207 ++++++++++ os/src/server/vmm/vea9x4/sp810.h | 41 ++ os/src/server/vmm/vea9x4/sys_reg.h | 100 +++++ os/src/server/vmm/{ => vea9x4}/target.mk | 2 +- os/src/server/vmm/vea9x4/tsc_380.h | 207 ++++++++++ 20 files changed, 1256 insertions(+), 863 deletions(-) create mode 100644 os/src/server/vmm/imx53/m4if.h create mode 100644 os/src/server/vmm/imx53/main.cc create mode 100644 os/src/server/vmm/imx53/target.mk delete mode 100644 os/src/server/vmm/include/bp_147.h create mode 100644 os/src/server/vmm/include/mmu.h create mode 100644 os/src/server/vmm/include/ram.h delete mode 100644 os/src/server/vmm/include/sp810.h delete mode 100644 os/src/server/vmm/include/sys_reg.h delete mode 100644 os/src/server/vmm/include/tsc_380.h create mode 100644 os/src/server/vmm/include/vm.h create mode 100644 os/src/server/vmm/include/vm_state.h delete mode 100644 os/src/server/vmm/main.cc create mode 100644 os/src/server/vmm/vea9x4/bp_147.h create mode 100644 os/src/server/vmm/vea9x4/main.cc create mode 100644 os/src/server/vmm/vea9x4/sp810.h create mode 100644 os/src/server/vmm/vea9x4/sys_reg.h rename os/src/server/vmm/{ => vea9x4}/target.mk (66%) create mode 100644 os/src/server/vmm/vea9x4/tsc_380.h diff --git a/base/include/platform/imx53/drivers/board_base.h b/base/include/platform/imx53/drivers/board_base.h index d4d7ac037..ab3256193 100644 --- a/base/include/platform/imx53/drivers/board_base.h +++ b/base/include/platform/imx53/drivers/board_base.h @@ -103,6 +103,9 @@ namespace Genode IIM_BASE = 0x63f98000, IIM_SIZE = 0x00004000, + M4IF_BASE = 0x63fd8000, + M4IF_SIZE = 0x00001000, + /* wether board provides security extension */ SECURITY_EXTENSION = 1, diff --git a/os/src/server/vmm/imx53/m4if.h b/os/src/server/vmm/imx53/m4if.h new file mode 100644 index 000000000..d7a10cae5 --- /dev/null +++ b/os/src/server/vmm/imx53/m4if.h @@ -0,0 +1,61 @@ +/* + * \brief Driver for the Multi Master Multi Memory Interface + * \author Stefan Kalkowski + * \date 2012-11-06 + */ + +/* + * Copyright (C) 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. + */ + +#ifndef _SRC__SERVER__VMM__INCLUDE__M4IF_H_ +#define _SRC__SERVER__VMM__INCLUDE__M4IF_H_ + +/* Genode includes */ +#include + +class M4if : Genode::Mmio +{ + private: + + struct Wm_reg0_ddr0_start : public Register<0xec, 32> + { + struct Addr : Bitfield<0,20> {}; + struct Enable : Bitfield<31,1> {}; + }; + + struct Wm_reg0_ddr0_end : public Register<0x10c, 32> + { + struct Addr : Bitfield<0,20> {}; + }; + + struct Wm_reg0_irq : public Register<0x114, 32> + { + struct Status_ddr0 : Bitfield<6,1> {}; + struct Enable : Bitfield<31,1> {}; + }; + + struct Wm_reg0_addr : public Register<0x118, 32> {}; + + public: + + M4if(Genode::addr_t const base) : Genode::Mmio(base) {} + + void set_region(Genode::addr_t addr, Genode::size_t size) + { + write((addr+size-1) >> 12); + write( + Wm_reg0_ddr0_start::Addr::bits(addr >> 12) | + Wm_reg0_ddr0_start::Enable::bits(1)); + write(1); + } + + void ack_irq() { write(1); } + + Genode::addr_t violation_addr() { return read(); } +}; + +#endif /* _SRC__SERVER__VMM__INCLUDE__M4IF_H_ */ diff --git a/os/src/server/vmm/imx53/main.cc b/os/src/server/vmm/imx53/main.cc new file mode 100644 index 000000000..6c943a6e9 --- /dev/null +++ b/os/src/server/vmm/imx53/main.cc @@ -0,0 +1,138 @@ +/* + * \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 +#include +#include +#include +#include + +/* local includes */ +#include +#include +#include + +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 androidboot.console=ttymxc0 lpj=4997120 \ +video=mxcdi1fb:RGB666,XGA gpu_memory=64M"; + + +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; + + void _handle_hypervisor_call() + { + /* check device number*/ + switch (_vm->state()->r0) { + 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(); + + 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())) + { + _m4if.set_region(Trustzone::SECURE_RAM_BASE, + Trustzone::SECURE_RAM_SIZE); + } +}; + + +int main() +{ + static Vm vm("linux", "initrd.gz", cmdline_tablet, + Trustzone::NONSECURE_RAM_BASE, Trustzone::NONSECURE_RAM_SIZE, + KERNEL_OFFSET, MACH_TYPE_TABLET, BOARD_REV_TABLET); + static Vmm::Vmm vmm(&vm); + + PINF("Start virtual machine ..."); + vmm.start(); + + sleep_forever(); + return 0; +} diff --git a/os/src/server/vmm/imx53/target.mk b/os/src/server/vmm/imx53/target.mk new file mode 100644 index 000000000..36a5f9f6a --- /dev/null +++ b/os/src/server/vmm/imx53/target.mk @@ -0,0 +1,5 @@ +TARGET = vmm +REQUIRES = trustzone platform_imx53 +LIBS = base +SRC_CC = main.cc +INC_DIR += $(PRG_DIR) $(PRG_DIR)/../include diff --git a/os/src/server/vmm/include/atag.h b/os/src/server/vmm/include/atag.h index 5e8bd8c0a..d6cb6d2eb 100644 --- a/os/src/server/vmm/include/atag.h +++ b/os/src/server/vmm/include/atag.h @@ -162,6 +162,14 @@ class Atag { _next(); } + void setup_rev_tag(Genode::addr_t rev) + { + _params->hdr.tag = ATAG_REVISION; + _params->hdr.size = _size(); + _params->u.revision.rev = rev; + _next(); + } + void setup_mem_tag(Genode::addr_t start, Genode::size_t len) { _params->hdr.tag = ATAG_MEM; diff --git a/os/src/server/vmm/include/bp_147.h b/os/src/server/vmm/include/bp_147.h deleted file mode 100644 index 683491ced..000000000 --- a/os/src/server/vmm/include/bp_147.h +++ /dev/null @@ -1,130 +0,0 @@ -/* - * \brief Driver for the Trustzone Protection Controller BP147 - * \author Stefan Kalkowski - * \date 2012-07-04 - */ - -/* - * 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 _BASE_HW__SRC__SERVER__VMM__BP_147_H_ -#define _BASE_HW__SRC__SERVER__VMM__BP_147_H_ - -/* Genode includes */ -#include - -namespace Genode -{ - - class Bp_147 : Mmio - { - private: - - /** - * Secure RAM Region Size Register - */ - struct Tzpcr0size : public Register<0x00, 32> - { - struct R0size : Bitfield<0,10> { }; - }; - - /** - * Decode Protection 0 Registers - */ - template - struct Tzpcdecprot0 : public Register - { - struct Pl341_apb : Register::template Bitfield<0,1> {}; - struct Pl354_apb : Register::template Bitfield<1,1> {}; - struct Scc : Register::template Bitfield<2,1> {}; - struct Dual_timer : Register::template Bitfield<4,1> {}; - struct Watchdog : Register::template Bitfield<5,1> {}; - struct Tzpc : Register::template Bitfield<6,1> {}; - struct Pl351_apb : Register::template Bitfield<7,1> {}; - struct Fast_pl301_apb : Register::template Bitfield<9,1> {}; - struct Slow_pl301_apb : Register::template Bitfield<10,1> {}; - struct Dmc_tzasc : Register::template Bitfield<12,1> {}; - struct Nmc_tzasc : Register::template Bitfield<12,1> {}; - struct Smc_tzasc : Register::template Bitfield<13,1> {}; - struct Debug_apb_phs : Register::template Bitfield<14,1> {}; - }; - - /** - * Decode Protection 1 Registers - */ - template - struct Tzpcdecprot1 : public Register - { - struct External_axi_slave_port - : Register::template Bitfield<0,1> {}; - /* SMC access */ - struct Pl354_axi - : Register::template Bitfield<1,1> {}; - struct Pl351_axi - : Register::template Bitfield<2,1> {}; - struct Entire_apb - : Register::template Bitfield<3,1> {}; - struct Pl111_configuration_port - : Register::template Bitfield<4,1> {}; - struct Axi_ram - : Register::template Bitfield<5,1> {}; - /* DDR RAM access */ - struct Pl341_axi - : Register::template Bitfield<6,1> {}; - /* ACP access */ - struct Cortexa9_coherency_port - : Register::template Bitfield<8,1> {}; - struct Entire_slow_axi_system - : Register::template Bitfield<9,1> {}; - }; - - /** - * Decode Protection 2 Registers - */ - template - struct Tzpcdecprot2 : public Register - { - struct External_master_tz : Register::template Bitfield<0,1> {}; - struct Dap_tz_override : Register::template Bitfield<1,1> {}; - struct Pl111_master_tz : Register::template Bitfield<2,1> {}; - struct Dmc_tzasc_lockdown : Register::template Bitfield<3,1> {}; - struct Nmc_tzasc_lockdown : Register::template Bitfield<4,1> {}; - struct Smc_tzasc_lockdown : Register::template Bitfield<5,1> {}; - }; - - struct Tzpcdecprot0stat : Tzpcdecprot0<0x800> {}; - struct Tzpcdecprot0set : Tzpcdecprot0<0x804> {}; - struct Tzpcdecprot0clr : Tzpcdecprot0<0x808> {}; - struct Tzpcdecprot1stat : Tzpcdecprot1<0x80c> {}; - struct Tzpcdecprot1set : Tzpcdecprot1<0x810> {}; - struct Tzpcdecprot1clr : Tzpcdecprot1<0x814> {}; - struct Tzpcdecprot2stat : Tzpcdecprot2<0x818> {}; - struct Tzpcdecprot2set : Tzpcdecprot2<0x81c> {}; - struct Tzpcdecprot2clr : Tzpcdecprot2<0x820> {}; - - public: - - Bp_147(addr_t const base) : Mmio(base) - { - /** - * Configure TZPC to allow non-secure AXI signals to - * Static Memory Controller (SMC), - * Dynamic Memory Controller (DMC), - * Accelerator Coherency Port (ACP), and - * PL111 configuration registers - */ - write( - Tzpcdecprot1set::Pl341_axi::bits(1) | - Tzpcdecprot1set::Pl354_axi::bits(1) | - Tzpcdecprot1set::Cortexa9_coherency_port::bits(1) | - Tzpcdecprot1set::Pl111_configuration_port::bits(1)); - } - }; - -} - -#endif /* _BASE_HW__SRC__SERVER__VMM__BP_147_H_ */ diff --git a/os/src/server/vmm/include/mmu.h b/os/src/server/vmm/include/mmu.h new file mode 100644 index 000000000..cd1d4cf0e --- /dev/null +++ b/os/src/server/vmm/include/mmu.h @@ -0,0 +1,91 @@ +/* + * \brief Virtual Machine Monitor MMU 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__MMU_H_ +#define _SRC__SERVER__VMM__INCLUDE__MMU_H_ + +/* local includes */ +#include +#include + +class Mmu +{ + private: + + Vm_state *_state; + Ram *_ram; + + unsigned _n_bits() { return _state->ttbrc & 0x7; } + + bool _ttbr0(Genode::addr_t mva) { + return (!_n_bits() || !(mva >> (32 - _n_bits()))); } + + Genode::addr_t _first_level(Genode::addr_t va) + { + if (!_ttbr0(va)) + return ((_state->ttbr[1] & 0xffffc000) | + ((va >> 18) & 0xffffc)); + unsigned shift = 14 - _n_bits(); + return (((_state->ttbr[0] >> shift) << shift) | + (((va << _n_bits()) >> (18 + _n_bits())) & 0x3ffc)); + } + + Genode::addr_t _page(Genode::addr_t fe, Genode::addr_t va) + { + enum Type { FAULT, LARGE, SMALL }; + + Genode::addr_t se = *((Genode::addr_t*)_ram->va(((fe & (~0UL << 10)) | + ((va >> 10) & 0x3fc)))); + switch (se & 0x3) { + case FAULT: + return 0; + case LARGE: + return ((se & (~0UL << 16)) | (va & (~0UL >> 16))); + default: + return ((se & (~0UL << 12)) | (va & (~0UL >> 20))); + } + return 0; + } + + Genode::addr_t _section(Genode::addr_t fe, Genode::addr_t va) { + return ((fe & 0xfff00000) | (va & 0xfffff)); } + + Genode::addr_t _supersection(Genode::addr_t fe, Genode::addr_t va) + { + PWRN("Not implemented yet!"); + return 0; + } + + public: + + Mmu(Vm_state *state, Ram *ram) + : _state(state), _ram(ram) {} + + + Genode::addr_t phys_addr(Genode::addr_t va) + { + enum Type { FAULT, PAGETABLE, SECTION }; + + Genode::addr_t fe = *((Genode::addr_t*)_ram->va(_first_level(va))); + switch (fe & 0x3) { + case PAGETABLE: + return _page(fe, va); + case SECTION: + return (fe & 0x40000) ? _supersection(fe, va) + : _section(fe, va); + } + return 0; + } +}; + +#endif /* _SRC__SERVER__VMM__INCLUDE__MMU_H_ */ diff --git a/os/src/server/vmm/include/ram.h b/os/src/server/vmm/include/ram.h new file mode 100644 index 000000000..6fce1f8da --- /dev/null +++ b/os/src/server/vmm/include/ram.h @@ -0,0 +1,48 @@ +/* + * \brief Virtual Machine Monitor RAM 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__RAM_H_ +#define _SRC__SERVER__VMM__INCLUDE__RAM_H_ + +/* Genode includes */ +#include +#include + +class Ram { + + private: + + Genode::addr_t _base; + Genode::size_t _size; + Genode::addr_t _local; + + public: + + class Invalid_addr : Genode::Exception {}; + + Ram(Genode::addr_t addr, Genode::size_t sz, Genode::addr_t local) + : _base(addr), _size(sz), _local(local) { } + + Genode::addr_t base() { return _base; } + Genode::size_t size() { return _size; } + Genode::addr_t local() { return _local; } + + Genode::addr_t va(Genode::addr_t phys) + { + if ((phys < _base) || (phys > (_base + _size))) + throw Invalid_addr(); + return _local + (phys - _base); + } +}; + +#endif /* _SRC__SERVER__VMM__INCLUDE__RAM_H_ */ diff --git a/os/src/server/vmm/include/sp810.h b/os/src/server/vmm/include/sp810.h deleted file mode 100644 index 07b5ab3d5..000000000 --- a/os/src/server/vmm/include/sp810.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * \brief Driver for the SP810 system controller - * \author Stefan Kalkowski - * \date 2012-09-21 - */ - -/* - * 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 _BASE_HW__SRC__SERVER__VMM__810_H_ -#define _BASE_HW__SRC__SERVER__VMM__810_H_ - -/* Genode includes */ -#include - -namespace Genode -{ - - class Sp810 : Mmio - { - private: - - struct Ctrl : public Register<0, 32> - { - struct Timer0_enable : Bitfield<15,1> {}; - struct Timer1_enable : Bitfield<17,1> {}; - }; - - public: - - Sp810(addr_t const base) : Mmio(base) {} - - bool timer0() { return read(); } - bool timer1() { return read(); } - - void enable_timer0() { write(1); } - void enable_timer1() { write(1); } - }; -} - -#endif /* _BASE_HW__SRC__SERVER__VMM__SP810_H_ */ diff --git a/os/src/server/vmm/include/sys_reg.h b/os/src/server/vmm/include/sys_reg.h deleted file mode 100644 index cb9ac32a3..000000000 --- a/os/src/server/vmm/include/sys_reg.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * \brief Driver for the Motherboard Express system registers - * \author Stefan Kalkowski - * \date 2012-09-21 - */ - -/* - * 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 _BASE_HW__SRC__SERVER__VMM__SYS_REG_H_ -#define _BASE_HW__SRC__SERVER__VMM__SYS_REG_H_ - -/* Genode includes */ -#include - -namespace Genode -{ - - class Sys_reg : Mmio - { - private: - - struct Sys_mci : public Register<0x48, 32> {}; - - struct Sys_24mhz : public Register<0x5c, 32> {}; - - struct Sys_misc : public Register<0x60, 32> {}; - - struct Sys_cfg_data : public Register<0xa0, 32, true> {}; - - struct Sys_cfg_ctrl : public Register<0xa4, 32, true> - { - struct Device : Bitfield<0,12> { }; - struct Position : Bitfield<12,4> { }; - struct Site : Bitfield<16,2> { }; - struct Function : Bitfield<20,6> { }; - struct Write : Bitfield<30,1> { }; - struct Start : Bitfield<31,1> { }; - }; - - struct Sys_cfg_stat : public Register<0xa8, 32> - { - struct Complete : Bitfield<0,1> { }; - struct Error : Bitfield<1,1> { }; - }; - - public: - - Sys_reg(addr_t const base) : Mmio(base) {} - - uint32_t counter() { return read(); } - - uint32_t misc_flags() { return read(); } - - void osc1(uint32_t mhz) - { - write(0); - write(mhz); - write(Sys_cfg_ctrl::Device::bits(1) | - Sys_cfg_ctrl::Site::bits(1) | - Sys_cfg_ctrl::Function::bits(1) | - Sys_cfg_ctrl::Write::bits(1) | - Sys_cfg_ctrl::Start::bits(1)); - while (!read()) ; - } - - void dvi_source(uint32_t site) - { - if (site > 2) { - PERR("Invalid site value %u ignored", site); - return; - } - write(0); - write(site); - write(Sys_cfg_ctrl::Site::bits(1) | - Sys_cfg_ctrl::Function::bits(0x7) | - Sys_cfg_ctrl::Write::bits(1) | - Sys_cfg_ctrl::Start::bits(1)); - while (!read()) ; - } - - void dvi_mode(uint32_t mode) - { - if (mode > 4) { - PERR("Invalid dvi mode %u ignored", mode); - return; - } - write(0); - write(mode); - write(Sys_cfg_ctrl::Function::bits(0xb) | - Sys_cfg_ctrl::Write::bits(1) | - Sys_cfg_ctrl::Start::bits(1)); - while (!read()) ; - } - - uint32_t mci_status() { return read(); } - }; -} - -#endif /* _BASE_HW__SRC__SERVER__VMM__SYS_REG_H_ */ diff --git a/os/src/server/vmm/include/tsc_380.h b/os/src/server/vmm/include/tsc_380.h deleted file mode 100644 index d91ff485e..000000000 --- a/os/src/server/vmm/include/tsc_380.h +++ /dev/null @@ -1,212 +0,0 @@ -/* - * \brief Driver for the CoreLink Trustzone Address Space Controller TSC-380 - * \author Stefan Kalkowski - * \date 2012-07-04 - */ - -/* - * 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 _BASE_HW__SRC__SERVER__VMM__TSC_380_H_ -#define _BASE_HW__SRC__SERVER__VMM__TSC_380_H_ - -/* Genode includes */ -#include - -namespace Genode -{ - - class Tsc_380 : Mmio - { - private: - - enum { - REGION0_REG_OFF = 0x100, - REGION1_REG_OFF = 0x110, - REGION2_REG_OFF = 0x120, - REGION3_REG_OFF = 0x130, - REGION4_REG_OFF = 0x140, - REGION5_REG_OFF = 0x150, - REGION6_REG_OFF = 0x160, - REGION7_REG_OFF = 0x170, - REGION8_REG_OFF = 0x180, - REGION9_REG_OFF = 0x190, - REGION10_REG_OFF = 0x1a0, - REGION11_REG_OFF = 0x1b0, - REGION12_REG_OFF = 0x1c0, - REGION13_REG_OFF = 0x1d0, - REGION14_REG_OFF = 0x1e0, - REGION15_REG_OFF = 0x1f0, - - REGION_LOW_OFF = 0x0, - REGION_HIGH_OFF = 0x4, - REGION_ATTR_OFF = 0x8, - }; - - /** - * Configuration register - */ - struct Config : public Register<0, 32> - { - struct Region_number : Bitfield<0,4> { }; - struct Address_width : Bitfield<8,6> { }; - }; - - struct Irq_status : public Register<0x10, 32> - { - struct Status : Bitfield<0,1> {}; - struct Overrun : Bitfield<1,1> {}; - }; - - struct Irq_clear : public Register<0x14, 32> - { - struct Status : Bitfield<0,1> {}; - struct Overrun : Bitfield<1,1> {}; - }; - - /** - * Fail address low register - */ - struct Fail_low : public Register<0x20, 32> { }; - - template - struct Region_low : public Register - { - enum { MASK = ~0UL << 15 }; - }; - - template - struct Region_high : public Register { }; - - template - struct Region_attr : public Register - { - struct Enable : - Register::template Bitfield<0, 1> { }; - struct Size : - Register::template Bitfield<1, 6> - { - enum { - SZ_32K = 14, - SZ_64K, - SZ_128K, - SZ_256K, - SZ_512K, - SZ_1M, - SZ_2M, - SZ_4M, - SZ_8M, - SZ_16M, - SZ_32M, - SZ_64M, - SZ_128M, - SZ_256M, - SZ_512M, - SZ_1G, - }; - }; - struct Subreg0 : - Register::template Bitfield<8, 1> { }; - struct Subreg1 : - Register::template Bitfield<9, 1> { }; - struct Subreg2 : - Register::template Bitfield<10, 1> { }; - struct Subreg3 : - Register::template Bitfield<11, 1> { }; - struct Subreg4 : - Register::template Bitfield<12, 1> { }; - struct Subreg5 : - Register::template Bitfield<13, 1> { }; - struct Subreg6 : - Register::template Bitfield<14, 1> { }; - struct Subreg7 : - Register::template Bitfield<15, 1> { }; - struct Normal_write : - Register::template Bitfield<28, 1> { }; - struct Normal_read : - Register::template Bitfield<29, 1> { }; - struct Secure_write : - Register::template Bitfield<30, 1> { }; - struct Secure_read : - Register::template Bitfield<31, 1> { }; - }; - - typedef Region_low<0x100> Region0_low; - - public: - - Tsc_380(addr_t const base) : Mmio(base) - { - /* Access to AACI, MMCI, KMI0/1 */ - write >(0x10000000); - write >(0x10008000); - write::Enable>(1); - write::Size>(Region_attr::Size::SZ_32K); - write::Normal_read>(1); - write::Normal_write>(1); - write::Secure_read>(1); - write::Secure_write>(1); - write::Subreg0>(1); - write::Subreg1>(1); - write::Subreg2>(1); - write::Subreg3>(1); - - /* Access to UART3, and WDT */ - write >(0x10008000); - write >(0x10010000); - write::Enable>(1); - write::Size>(Region_attr::Size::SZ_32K); - write::Normal_read>(1); - write::Normal_write>(1); - write::Secure_read>(1); - write::Secure_write>(1); - write::Subreg0>(1); - write::Subreg1>(1); - write::Subreg2>(1); - write::Subreg3>(1); - write::Subreg5>(1); - write::Subreg6>(1); - - /* Access to SP804, and RTC */ - write >(0x10010000); - write >(0x10018000); - write::Enable>(1); - write::Size>(Region_attr::Size::SZ_32K); - write::Normal_read>(1); - write::Normal_write>(1); - write::Secure_read>(1); - write::Secure_write>(1); - write::Subreg0>(1); - write::Subreg3>(1); - write::Subreg4>(1); - write::Subreg5>(1); - write::Subreg6>(1); - - /* Access to Ethernet and USB */ - write >(0x4e000000); - write >(0x50000000); - write::Enable>(1); - write::Size>(Region_attr::Size::SZ_32M); - write::Normal_read>(1); - write::Normal_write>(1); - write::Secure_read>(1); - write::Secure_write>(1); - - /* clear interrupts */ - write(0x3); - } - - void* last_failed_access() { - void *ret = (void*) read(); - write(0x3); - return ret; - } - }; - -} - -#endif /* _BASE_HW__SRC__SERVER__VMM__TSC_380_H_ */ diff --git a/os/src/server/vmm/include/vm.h b/os/src/server/vmm/include/vm.h new file mode 100644 index 000000000..896978a84 --- /dev/null +++ b/os/src/server/vmm/include/vm.h @@ -0,0 +1,193 @@ +/* + * \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 +#include +#include +#include +#include + +/* local includes */ +#include +#include + +class Vm { + + private: + + enum { + ATAG_OFFSET = 0x100, + 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; + 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); + } + + void _prepare_atag() + { + Atag tag((void*)(_ram.local() + ATAG_OFFSET)); + tag.setup_mem_tag(_ram.base(), _ram.size()); + tag.setup_cmdline_tag(_cmdline); + tag.setup_initrd2_tag(_ram.base() + INITRD_OFFSET, _initrd_cap.size()); + if (_board_rev) + tag.setup_rev_tag(_board_rev); + tag.setup_end_tag(); + } + + public: + + Vm(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((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(Vm_state)); + _load_kernel(); + _load_initrd(); + _prepare_atag(); + _state->cpsr = 0x93; /* SVC mode and IRQs disabled */ + _state->r1 = _mach_type; + _state->r2 = _ram.base() + ATAG_OFFSET; /* ATAG 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 < 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; + } + + Vm_state *state() const { return _state; } + Ram *ram() { return &_ram; } +}; + +#endif /* _SRC__SERVER__VMM__INCLUDE__VM_H_ */ diff --git a/os/src/server/vmm/include/vm_state.h b/os/src/server/vmm/include/vm_state.h new file mode 100644 index 000000000..ec1e4f751 --- /dev/null +++ b/os/src/server/vmm/include/vm_state.h @@ -0,0 +1,27 @@ +/* + * \brief Virtual Machine Monitor VM state 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_STATE_H_ +#define _SRC__SERVER__VMM__INCLUDE__VM_STATE_H_ + +/* Genode includes */ +#include + +struct Vm_state : Genode::Cpu_state_modes +{ + Genode::addr_t dfar; /* data fault address */ + Genode::addr_t ttbr[2]; /* translation table base regs */ + Genode::addr_t ttbrc; /* translation table base control */ +}; + +#endif /* _SRC__SERVER__VMM__INCLUDE__VM_STATE_H_ */ diff --git a/os/src/server/vmm/main.cc b/os/src/server/vmm/main.cc deleted file mode 100644 index a67fae18e..000000000 --- a/os/src/server/vmm/main.cc +++ /dev/null @@ -1,371 +0,0 @@ -/* - * \brief Virtual Machine Monitor - * \author Stefan Kalkowski - * \date 2012-06-25 - */ - -/* - * Copyright (C) 2008-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. - */ - -/* Genode includes */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* local includes */ -#include -#include -#include -#include -#include - -namespace Genode { - - class Ram { - - private: - - addr_t _base; - size_t _size; - addr_t _local; - - public: - - Ram(addr_t addr, size_t sz) - : _base(addr), _size(sz), _local(0) { } - - addr_t base() { return _base; } - size_t size() { return _size; } - addr_t local() { return _local; } - - void attach(Dataspace_capability cap) { - _local = (addr_t) env()->rm_session()->attach(cap); } - }; - - - class Vm { - - private: - - enum { - ATAG_OFFSET = 0x100, - INITRD_OFFSET = 0x800000 - }; - - Vm_connection _vm_con; - Rom_connection _elf_rom; - Rom_connection _initrd_rom; - const char* _cmdline; - size_t _initrd_size; - Cpu_state_modes *_state; - Ram _ram; - Io_mem_connection _ram_iomem; - - void _load_elf() - { - /* attach ELF locally */ - addr_t elf_addr = env()->rm_session()->attach(_elf_rom.dataspace()); - - /* setup ELF object and read program entry pointer */ - Elf_binary elf((addr_t)elf_addr); - _state->ip = elf.entry(); - if (!elf.valid()) { - PWRN("Invalid elf binary!"); - return; - } - - Elf_segment seg; - for (unsigned n = 0; (seg = elf.get_segment(n)).valid(); ++n) { - if (seg.flags().skip) continue; - - addr_t addr = (addr_t)seg.start(); - size_t size = seg.mem_size(); - - if (addr < _ram.base() || - (addr + size) > (_ram.base() + _ram.size())) { - PWRN("Elf binary doesn't fit into RAM"); - return; - } - - void *base = (void*) (_ram.local() + (addr - _ram.base())); - addr_t laddr = elf_addr + seg.file_offset(); - - /* copy contents */ - memcpy(base, (void *)laddr, seg.file_size()); - - /* if writeable region potentially fill with zeros */ - if (size > seg.file_size() && seg.flags().w) - memset((void *)((addr_t)base + seg.file_size()), - 0, size - seg.file_size()); - } - - /* detach ELF */ - env()->rm_session()->detach((void*)elf_addr); - } - - void _load_initrd() - { - addr_t addr = env()->rm_session()->attach(_initrd_rom.dataspace()); - memcpy((void*)(_ram.local() + INITRD_OFFSET), - (void*)addr, _initrd_size); - env()->rm_session()->detach((void*)addr); - } - - void _prepare_atag() - { - Atag tag((void*)(_ram.local() + ATAG_OFFSET)); - tag.setup_mem_tag(_ram.base(), _ram.size()); - tag.setup_cmdline_tag(_cmdline); - tag.setup_initrd2_tag(_ram.base() + INITRD_OFFSET, _initrd_size); - tag.setup_end_tag(); - } - - public: - - Vm(const char *kernel, const char *initrd, const char *cmdline, - addr_t ram_base, size_t ram_size) - : _elf_rom(kernel), - _initrd_rom(initrd), - _cmdline(cmdline), - _initrd_size(Dataspace_client(_initrd_rom.dataspace()).size()), - _state((Cpu_state_modes*)env()->rm_session()->attach(_vm_con.cpu_state())), - _ram(ram_base, ram_size), - _ram_iomem(ram_base, ram_size) - { - memset((void*)_state, 0, sizeof(Cpu_state_modes)); - _ram.attach(_ram_iomem.dataspace()); - } - - void start(Signal_context_capability sig_cap) - { - _load_elf(); - _load_initrd(); - _prepare_atag(); - _state->cpsr = 0x93; /* SVC mode and IRQs disabled */ - _state->r1 = 2272; /* MACH_TYPE vexpress board */ - _state->r2 = _ram.base() + ATAG_OFFSET; /* ATAG addr */ - _vm_con.exception_handler(sig_cap); - } - - void run() { _vm_con.run(); } - - void dump() - { - const char * const modes[] = - { "und", "svc", "abt", "irq", "fiq" }; - const char * const exc[] = - { "reset", "undefined", "smc", "pf_abort", - "data_abort", "irq", "fiq" }; - - printf("Cpu state:\n"); - printf(" r0 = %08lx\n", _state->r0); - printf(" r1 = %08lx\n", _state->r1); - printf(" r2 = %08lx\n", _state->r2); - printf(" r3 = %08lx\n", _state->r3); - printf(" r4 = %08lx\n", _state->r4); - printf(" r5 = %08lx\n", _state->r5); - printf(" r6 = %08lx\n", _state->r6); - printf(" r7 = %08lx\n", _state->r7); - printf(" r8 = %08lx\n", _state->r8); - printf(" r9 = %08lx\n", _state->r9); - printf(" r10 = %08lx\n", _state->r10); - printf(" r11 = %08lx\n", _state->r11); - printf(" r12 = %08lx\n", _state->r12); - printf(" sp = %08lx\n", _state->sp); - printf(" lr = %08lx\n", _state->lr); - printf(" ip = %08lx\n", _state->ip); - printf(" cpsr = %08lx\n", _state->cpsr); - for (unsigned i = 0; - i < Cpu_state_modes::Mode_state::MAX; i++) { - printf(" sp_%s = %08lx\n", modes[i], _state->mode[i].sp); - printf(" lr_%s = %08lx\n", modes[i], _state->mode[i].lr); - printf(" spsr_%s = %08lx\n", modes[i], _state->mode[i].spsr); - } - printf(" exception = %s\n", exc[_state->cpu_exception]); - } - - Cpu_state_modes *state() const { return _state; } - }; - - - class Vmm : public Genode::Thread<8192> - { - private: - - enum Hypervisor_calls { - SP810_ENABLE = 1, - CPU_ID, - SYS_COUNTER, - MISC_FLAGS, - SYS_CTRL, - MCI_STATUS - }; - - Io_mem_connection _tsc_io_mem; - Io_mem_connection _tpc_io_mem; - Io_mem_connection _sys_io_mem; - Io_mem_connection _sp810_io_mem; - - Tsc_380 _tsc; - Bp_147 _tpc; - Sys_reg _sys; - Sp810 _sp810; - - Vm *_vm; - - void _sys_ctrl() - { - enum { - OSC1 = 0xc0110001, - DVI_SRC = 0xc0710000, - DVI_MODE = 0xc0b00000 - }; - - uint32_t ctrl = _vm->state()->r2; - uint32_t data = _vm->state()->r0; - - switch(ctrl) { - case OSC1: - _sys.osc1(data); - break; - case DVI_SRC: - _sys.dvi_source(data); - break; - case DVI_MODE: - _sys.dvi_mode(data); - break; - default: - PWRN("Access violation to sys configuration ctrl=%ux", ctrl); - _vm->dump(); - } - } - - void _handle_hypervisor_call() - { - switch (_vm->state()->r1) { - case SP810_ENABLE: - _sp810.enable_timer0(); - _sp810.enable_timer1(); - break; - case CPU_ID: - _vm->state()->r0 = 0x0c000191; // Coretile A9 ID - break; - case SYS_COUNTER: - _vm->state()->r0 = _sys.counter(); - break; - case MISC_FLAGS: - _vm->state()->r0 = _sys.misc_flags(); - break; - case SYS_CTRL: - _sys_ctrl(); - break; - case MCI_STATUS: - _vm->state()->r0 = _sys.mci_status(); - break; - default: - PERR("Unknown hypervisor call!"); - _vm->dump(); - } - } - - bool _handle_data_abort() - { - PWRN("Vm tried to access %p which isn't allowed", - _tsc.last_failed_access()); - _vm->dump(); - return false; - } - - bool _handle_vm() - { - 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() - { - Signal_receiver sig_rcv; - Signal_context sig_cxt; - Signal_context_capability sig_cap(sig_rcv.manage(&sig_cxt)); - _vm->start(sig_cap); - while (true) { - _vm->run(); - Signal s = sig_rcv.wait_for_signal(); - if (s.context() != &sig_cxt) { - PWRN("Invalid context"); - continue; - } - if (!_handle_vm()) - return; - } - }; - - public: - - Vmm(addr_t tsc_base, addr_t tpc_base, - addr_t sys_base, addr_t sp810_base, - Vm *vm) - : Thread("vmm_signal_handler"), - _tsc_io_mem(tsc_base, 0x1000), - _tpc_io_mem(tpc_base, 0x1000), - _sys_io_mem(sys_base, 0x1000), - _sp810_io_mem(sp810_base, 0x1000), - _tsc((addr_t)env()->rm_session()->attach(_tsc_io_mem.dataspace())), - _tpc((addr_t)env()->rm_session()->attach(_tpc_io_mem.dataspace())), - _sys((addr_t)env()->rm_session()->attach(_sys_io_mem.dataspace())), - _sp810((addr_t)env()->rm_session()->attach(_sp810_io_mem.dataspace())), - _vm(vm) { } - }; -} - - -int main() -{ - enum { - SYS_VEA9X4_BASE = 0x10000000, - SP810_VEA9X4_BASE = 0x10001000, - TPC_VEA9X4_BASE = 0x100e6000, - TSC_VEA9X4_BASE = 0x100ec000, - MAIN_MEM_START = 0x80000000, - MAIN_MEM_SIZE = 0x10000000 - }; - - static const char* cmdline = "console=ttyAMA0,38400n8 root=/dev/ram0 lpj=1554432"; - static Genode::Vm vm("linux", "initrd.gz", cmdline, - MAIN_MEM_START, MAIN_MEM_SIZE); - static Genode::Vmm vmm(TSC_VEA9X4_BASE, TPC_VEA9X4_BASE, - SYS_VEA9X4_BASE, SP810_VEA9X4_BASE, - &vm); - - PINF("Start virtual machine"); - vmm.start(); - - Genode::sleep_forever(); - return 0; -} diff --git a/os/src/server/vmm/vea9x4/bp_147.h b/os/src/server/vmm/vea9x4/bp_147.h new file mode 100644 index 000000000..c10274b42 --- /dev/null +++ b/os/src/server/vmm/vea9x4/bp_147.h @@ -0,0 +1,126 @@ +/* + * \brief Driver for the Trustzone Protection Controller BP147 + * \author Stefan Kalkowski + * \date 2012-07-04 + */ + +/* + * Copyright (C) 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. + */ + +#ifndef _BASE_HW__SRC__SERVER__VMM__BP_147_H_ +#define _BASE_HW__SRC__SERVER__VMM__BP_147_H_ + +/* Genode includes */ +#include + +class Bp_147 : Genode::Mmio +{ + private: + + /** + * Secure RAM Region Size Register + */ + struct Tzpcr0size : public Register<0x00, 32> + { + struct R0size : Bitfield<0,10> { }; + }; + + /** + * Decode Protection 0 Registers + */ + template + struct Tzpcdecprot0 : public Register + { + struct Pl341_apb : Register::template Bitfield<0,1> {}; + struct Pl354_apb : Register::template Bitfield<1,1> {}; + struct Scc : Register::template Bitfield<2,1> {}; + struct Dual_timer : Register::template Bitfield<4,1> {}; + struct Watchdog : Register::template Bitfield<5,1> {}; + struct Tzpc : Register::template Bitfield<6,1> {}; + struct Pl351_apb : Register::template Bitfield<7,1> {}; + struct Fast_pl301_apb : Register::template Bitfield<9,1> {}; + struct Slow_pl301_apb : Register::template Bitfield<10,1> {}; + struct Dmc_tzasc : Register::template Bitfield<12,1> {}; + struct Nmc_tzasc : Register::template Bitfield<12,1> {}; + struct Smc_tzasc : Register::template Bitfield<13,1> {}; + struct Debug_apb_phs : Register::template Bitfield<14,1> {}; + }; + + /** + * Decode Protection 1 Registers + */ + template + struct Tzpcdecprot1 : public Register + { + struct External_axi_slave_port + : Register::template Bitfield<0,1> {}; + /* SMC access */ + struct Pl354_axi + : Register::template Bitfield<1,1> {}; + struct Pl351_axi + : Register::template Bitfield<2,1> {}; + struct Entire_apb + : Register::template Bitfield<3,1> {}; + struct Pl111_configuration_port + : Register::template Bitfield<4,1> {}; + struct Axi_ram + : Register::template Bitfield<5,1> {}; + /* DDR RAM access */ + struct Pl341_axi + : Register::template Bitfield<6,1> {}; + /* ACP access */ + struct Cortexa9_coherency_port + : Register::template Bitfield<8,1> {}; + struct Entire_slow_axi_system + : Register::template Bitfield<9,1> {}; + }; + + /** + * Decode Protection 2 Registers + */ + template + struct Tzpcdecprot2 : public Register + { + struct External_master_tz : Register::template Bitfield<0,1> {}; + struct Dap_tz_override : Register::template Bitfield<1,1> {}; + struct Pl111_master_tz : Register::template Bitfield<2,1> {}; + struct Dmc_tzasc_lockdown : Register::template Bitfield<3,1> {}; + struct Nmc_tzasc_lockdown : Register::template Bitfield<4,1> {}; + struct Smc_tzasc_lockdown : Register::template Bitfield<5,1> {}; + }; + + struct Tzpcdecprot0stat : Tzpcdecprot0<0x800> {}; + struct Tzpcdecprot0set : Tzpcdecprot0<0x804> {}; + struct Tzpcdecprot0clr : Tzpcdecprot0<0x808> {}; + struct Tzpcdecprot1stat : Tzpcdecprot1<0x80c> {}; + struct Tzpcdecprot1set : Tzpcdecprot1<0x810> {}; + struct Tzpcdecprot1clr : Tzpcdecprot1<0x814> {}; + struct Tzpcdecprot2stat : Tzpcdecprot2<0x818> {}; + struct Tzpcdecprot2set : Tzpcdecprot2<0x81c> {}; + struct Tzpcdecprot2clr : Tzpcdecprot2<0x820> {}; + + public: + + Bp_147(Genode::addr_t const base) : Genode::Mmio(base) + { + /** + * Configure TZPC to allow non-secure AXI signals to + * Static Memory Controller (SMC), + * Dynamic Memory Controller (DMC), + * Accelerator Coherency Port (ACP), and + * PL111 configuration registers + */ + write( + Tzpcdecprot1set::Pl341_axi::bits(1) | + Tzpcdecprot1set::Pl354_axi::bits(1) | + Tzpcdecprot1set::Cortexa9_coherency_port::bits(1) | + Tzpcdecprot1set::Pl111_configuration_port::bits(1)); + } + +}; + +#endif /* _BASE_HW__SRC__SERVER__VMM__BP_147_H_ */ diff --git a/os/src/server/vmm/vea9x4/main.cc b/os/src/server/vmm/vea9x4/main.cc new file mode 100644 index 000000000..0578815c4 --- /dev/null +++ b/os/src/server/vmm/vea9x4/main.cc @@ -0,0 +1,207 @@ +/* + * \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 +#include +#include +#include +#include +#include +#include +#include +#include + +/* local includes */ +#include +#include +#include +#include +#include + +using namespace Genode; + +namespace Vmm { + class Vmm; +} + +class Vmm::Vmm : public Thread<8192> +{ + private: + + enum Hypervisor_calls { + SP810_ENABLE = 1, + CPU_ID, + SYS_COUNTER, + MISC_FLAGS, + SYS_CTRL, + MCI_STATUS + }; + + Io_mem_connection _tsc_io_mem; + Io_mem_connection _tpc_io_mem; + Io_mem_connection _sys_io_mem; + Io_mem_connection _sp810_io_mem; + + Tsc_380 _tsc; + Bp_147 _tpc; + Sys_reg _sys; + Sp810 _sp810; + + Vm *_vm; + + void _sys_ctrl() + { + enum { + OSC1 = 0xc0110001, + DVI_SRC = 0xc0710000, + DVI_MODE = 0xc0b00000 + }; + + uint32_t ctrl = _vm->state()->r2; + uint32_t data = _vm->state()->r0; + + switch(ctrl) { + case OSC1: + _sys.osc1(data); + break; + case DVI_SRC: + _sys.dvi_source(data); + break; + case DVI_MODE: + _sys.dvi_mode(data); + break; + default: + PWRN("Access violation to sys configuration ctrl=%ux", ctrl); + _vm->dump(); + } + } + + void _handle_hypervisor_call() + { + switch (_vm->state()->r1) { + case SP810_ENABLE: + _sp810.enable_timer0(); + _sp810.enable_timer1(); + break; + case CPU_ID: + _vm->state()->r0 = 0x0c000191; // Coretile A9 ID + break; + case SYS_COUNTER: + _vm->state()->r0 = _sys.counter(); + break; + case MISC_FLAGS: + _vm->state()->r0 = _sys.misc_flags(); + break; + case SYS_CTRL: + _sys_ctrl(); + break; + case MCI_STATUS: + _vm->state()->r0 = _sys.mci_status(); + break; + default: + PERR("Unknown hypervisor call!"); + _vm->dump(); + } + } + + bool _handle_data_abort() + { + PWRN("Vm tried to access %p which isn't allowed", + _tsc.last_failed_access()); + _vm->dump(); + return false; + } + + bool _handle_vm() + { + 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() + { + Signal_receiver sig_rcv; + Signal_context sig_cxt; + Signal_context_capability sig_cap(sig_rcv.manage(&sig_cxt)); + _vm->start(sig_cap); + while (true) { + _vm->run(); + Signal s = sig_rcv.wait_for_signal(); + if (s.context() != &sig_cxt) { + PWRN("Invalid context"); + continue; + } + if (!_handle_vm()) + return; + } + }; + + public: + + Vmm(addr_t tsc_base, addr_t tpc_base, + addr_t sys_base, addr_t sp810_base, + Vm *vm) + : _tsc_io_mem(tsc_base, 0x1000), + _tpc_io_mem(tpc_base, 0x1000), + _sys_io_mem(sys_base, 0x1000), + _sp810_io_mem(sp810_base, 0x1000), + _tsc((addr_t)env()->rm_session()->attach(_tsc_io_mem.dataspace())), + _tpc((addr_t)env()->rm_session()->attach(_tpc_io_mem.dataspace())), + _sys((addr_t)env()->rm_session()->attach(_sys_io_mem.dataspace())), + _sp810((addr_t)env()->rm_session()->attach(_sp810_io_mem.dataspace())), + _vm(vm) { } +}; + + +int main() +{ + enum { + SYS_VEA9X4_BASE = 0x10000000, + SP810_VEA9X4_BASE = 0x10001000, + TPC_VEA9X4_BASE = 0x100e6000, + TSC_VEA9X4_BASE = 0x100ec000, + MAIN_MEM_START = 0x80000000, + MAIN_MEM_SIZE = 0x10000000, + KERNEL_OFFSET = 0x8000, + MACH_TYPE = 2272, + }; + + static const char* cmdline = "console=ttyAMA0,38400n8 root=/dev/ram0 lpj=1554432"; + static Vm vm("linux", "initrd.gz", cmdline, MAIN_MEM_START, MAIN_MEM_SIZE, + KERNEL_OFFSET, MACH_TYPE); + static Vmm::Vmm vmm(TSC_VEA9X4_BASE, TPC_VEA9X4_BASE, + SYS_VEA9X4_BASE, SP810_VEA9X4_BASE, &vm); + + PINF("Start virtual machine"); + vmm.start(); + + sleep_forever(); + return 0; +} diff --git a/os/src/server/vmm/vea9x4/sp810.h b/os/src/server/vmm/vea9x4/sp810.h new file mode 100644 index 000000000..6469332c1 --- /dev/null +++ b/os/src/server/vmm/vea9x4/sp810.h @@ -0,0 +1,41 @@ +/* + * \brief Driver for the SP810 system controller + * \author Stefan Kalkowski + * \date 2012-09-21 + */ + +/* + * Copyright (C) 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. + */ + +#ifndef _BASE_HW__SRC__SERVER__VMM__810_H_ +#define _BASE_HW__SRC__SERVER__VMM__810_H_ + +/* Genode includes */ +#include + +class Sp810 : Genode::Mmio +{ + private: + + struct Ctrl : public Register<0, 32> + { + struct Timer0_enable : Bitfield<15,1> {}; + struct Timer1_enable : Bitfield<17,1> {}; + }; + + public: + + Sp810(Genode::addr_t const base) : Genode::Mmio(base) {} + + bool timer0() { return read(); } + bool timer1() { return read(); } + + void enable_timer0() { write(1); } + void enable_timer1() { write(1); } +}; + +#endif /* _BASE_HW__SRC__SERVER__VMM__SP810_H_ */ diff --git a/os/src/server/vmm/vea9x4/sys_reg.h b/os/src/server/vmm/vea9x4/sys_reg.h new file mode 100644 index 000000000..c4102fae6 --- /dev/null +++ b/os/src/server/vmm/vea9x4/sys_reg.h @@ -0,0 +1,100 @@ +/* + * \brief Driver for the Motherboard Express system registers + * \author Stefan Kalkowski + * \date 2012-09-21 + */ + +/* + * Copyright (C) 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. + */ + +#ifndef _BASE_HW__SRC__SERVER__VMM__SYS_REG_H_ +#define _BASE_HW__SRC__SERVER__VMM__SYS_REG_H_ + +/* Genode includes */ +#include + +class Sys_reg : Genode::Mmio +{ + private: + + struct Sys_mci : public Register<0x48, 32> {}; + + struct Sys_24mhz : public Register<0x5c, 32> {}; + + struct Sys_misc : public Register<0x60, 32> {}; + + struct Sys_cfg_data : public Register<0xa0, 32, true> {}; + + struct Sys_cfg_ctrl : public Register<0xa4, 32, true> + { + struct Device : Bitfield<0,12> { }; + struct Position : Bitfield<12,4> { }; + struct Site : Bitfield<16,2> { }; + struct Function : Bitfield<20,6> { }; + struct Write : Bitfield<30,1> { }; + struct Start : Bitfield<31,1> { }; + }; + + struct Sys_cfg_stat : public Register<0xa8, 32> + { + struct Complete : Bitfield<0,1> { }; + struct Error : Bitfield<1,1> { }; + }; + + public: + + Sys_reg(Genode::addr_t const base) : Genode::Mmio(base) {} + + Genode::uint32_t counter() { return read(); } + + Genode::uint32_t misc_flags() { return read(); } + + void osc1(Genode::uint32_t mhz) + { + write(0); + write(mhz); + write(Sys_cfg_ctrl::Device::bits(1) | + Sys_cfg_ctrl::Site::bits(1) | + Sys_cfg_ctrl::Function::bits(1) | + Sys_cfg_ctrl::Write::bits(1) | + Sys_cfg_ctrl::Start::bits(1)); + while (!read()) ; + } + + void dvi_source(Genode::uint32_t site) + { + if (site > 2) { + PERR("Invalid site value %u ignored", site); + return; + } + write(0); + write(site); + write(Sys_cfg_ctrl::Site::bits(1) | + Sys_cfg_ctrl::Function::bits(0x7) | + Sys_cfg_ctrl::Write::bits(1) | + Sys_cfg_ctrl::Start::bits(1)); + while (!read()) ; + } + + void dvi_mode(Genode::uint32_t mode) + { + if (mode > 4) { + PERR("Invalid dvi mode %u ignored", mode); + return; + } + write(0); + write(mode); + write(Sys_cfg_ctrl::Function::bits(0xb) | + Sys_cfg_ctrl::Write::bits(1) | + Sys_cfg_ctrl::Start::bits(1)); + while (!read()) ; + } + + Genode::uint32_t mci_status() { return read(); } +}; + +#endif /* _BASE_HW__SRC__SERVER__VMM__SYS_REG_H_ */ diff --git a/os/src/server/vmm/target.mk b/os/src/server/vmm/vea9x4/target.mk similarity index 66% rename from os/src/server/vmm/target.mk rename to os/src/server/vmm/vea9x4/target.mk index 370d77005..f01ce8d14 100644 --- a/os/src/server/vmm/target.mk +++ b/os/src/server/vmm/vea9x4/target.mk @@ -2,4 +2,4 @@ TARGET = vmm REQUIRES = trustzone platform_vea9x4 LIBS = base SRC_CC = main.cc -INC_DIR += $(PRG_DIR)/include +INC_DIR += $(PRG_DIR) $(PRG_DIR)/../include diff --git a/os/src/server/vmm/vea9x4/tsc_380.h b/os/src/server/vmm/vea9x4/tsc_380.h new file mode 100644 index 000000000..ede725a11 --- /dev/null +++ b/os/src/server/vmm/vea9x4/tsc_380.h @@ -0,0 +1,207 @@ +/* + * \brief Driver for the CoreLink Trustzone Address Space Controller TSC-380 + * \author Stefan Kalkowski + * \date 2012-07-04 + */ + +/* + * Copyright (C) 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. + */ + +#ifndef _BASE_HW__SRC__SERVER__VMM__TSC_380_H_ +#define _BASE_HW__SRC__SERVER__VMM__TSC_380_H_ + +/* Genode includes */ +#include + +class Tsc_380 : Genode::Mmio +{ + private: + + enum { + REGION0_REG_OFF = 0x100, + REGION1_REG_OFF = 0x110, + REGION2_REG_OFF = 0x120, + REGION3_REG_OFF = 0x130, + REGION4_REG_OFF = 0x140, + REGION5_REG_OFF = 0x150, + REGION6_REG_OFF = 0x160, + REGION7_REG_OFF = 0x170, + REGION8_REG_OFF = 0x180, + REGION9_REG_OFF = 0x190, + REGION10_REG_OFF = 0x1a0, + REGION11_REG_OFF = 0x1b0, + REGION12_REG_OFF = 0x1c0, + REGION13_REG_OFF = 0x1d0, + REGION14_REG_OFF = 0x1e0, + REGION15_REG_OFF = 0x1f0, + + REGION_LOW_OFF = 0x0, + REGION_HIGH_OFF = 0x4, + REGION_ATTR_OFF = 0x8, + }; + + /** + * Configuration register + */ + struct Config : public Register<0, 32> + { + struct Region_number : Bitfield<0,4> { }; + struct Address_width : Bitfield<8,6> { }; + }; + + struct Irq_status : public Register<0x10, 32> + { + struct Status : Bitfield<0,1> {}; + struct Overrun : Bitfield<1,1> {}; + }; + + struct Irq_clear : public Register<0x14, 32> + { + struct Status : Bitfield<0,1> {}; + struct Overrun : Bitfield<1,1> {}; + }; + + /** + * Fail address low register + */ + struct Fail_low : public Register<0x20, 32> { }; + + template + struct Region_low : public Register + { + enum { MASK = ~0UL << 15 }; + }; + + template + struct Region_high : public Register { }; + + template + struct Region_attr : public Register + { + struct Enable : + Register::template Bitfield<0, 1> { }; + struct Size : + Register::template Bitfield<1, 6> + { + enum { + SZ_32K = 14, + SZ_64K, + SZ_128K, + SZ_256K, + SZ_512K, + SZ_1M, + SZ_2M, + SZ_4M, + SZ_8M, + SZ_16M, + SZ_32M, + SZ_64M, + SZ_128M, + SZ_256M, + SZ_512M, + SZ_1G, + }; + }; + struct Subreg0 : + Register::template Bitfield<8, 1> { }; + struct Subreg1 : + Register::template Bitfield<9, 1> { }; + struct Subreg2 : + Register::template Bitfield<10, 1> { }; + struct Subreg3 : + Register::template Bitfield<11, 1> { }; + struct Subreg4 : + Register::template Bitfield<12, 1> { }; + struct Subreg5 : + Register::template Bitfield<13, 1> { }; + struct Subreg6 : + Register::template Bitfield<14, 1> { }; + struct Subreg7 : + Register::template Bitfield<15, 1> { }; + struct Normal_write : + Register::template Bitfield<28, 1> { }; + struct Normal_read : + Register::template Bitfield<29, 1> { }; + struct Secure_write : + Register::template Bitfield<30, 1> { }; + struct Secure_read : + Register::template Bitfield<31, 1> { }; + }; + + typedef Region_low<0x100> Region0_low; + + public: + + Tsc_380(Genode::addr_t const base) : Genode::Mmio(base) + { + /* Access to AACI, MMCI, KMI0/1 */ + write >(0x10000000); + write >(0x10008000); + write::Enable>(1); + write::Size>(Region_attr::Size::SZ_32K); + write::Normal_read>(1); + write::Normal_write>(1); + write::Secure_read>(1); + write::Secure_write>(1); + write::Subreg0>(1); + write::Subreg1>(1); + write::Subreg2>(1); + write::Subreg3>(1); + + /* Access to UART3, and WDT */ + write >(0x10008000); + write >(0x10010000); + write::Enable>(1); + write::Size>(Region_attr::Size::SZ_32K); + write::Normal_read>(1); + write::Normal_write>(1); + write::Secure_read>(1); + write::Secure_write>(1); + write::Subreg0>(1); + write::Subreg1>(1); + write::Subreg2>(1); + write::Subreg3>(1); + write::Subreg5>(1); + write::Subreg6>(1); + + /* Access to SP804, and RTC */ + write >(0x10010000); + write >(0x10018000); + write::Enable>(1); + write::Size>(Region_attr::Size::SZ_32K); + write::Normal_read>(1); + write::Normal_write>(1); + write::Secure_read>(1); + write::Secure_write>(1); + write::Subreg0>(1); + write::Subreg3>(1); + write::Subreg4>(1); + write::Subreg5>(1); + write::Subreg6>(1); + + /* Access to Ethernet and USB */ + write >(0x4e000000); + write >(0x50000000); + write::Enable>(1); + write::Size>(Region_attr::Size::SZ_32M); + write::Normal_read>(1); + write::Normal_write>(1); + write::Secure_read>(1); + write::Secure_write>(1); + + /* clear interrupts */ + write(0x3); + } + + void* last_failed_access() { + void *ret = (void*) read(); + write(0x3); + return ret; + } +}; + +#endif /* _BASE_HW__SRC__SERVER__VMM__TSC_380_H_ */