diff --git a/repos/base-hw/lib/mk/cortex_a15/core.inc b/repos/base-hw/lib/mk/cortex_a15/core.inc index a1c9b5b907..749ebeeac6 100644 --- a/repos/base-hw/lib/mk/cortex_a15/core.inc +++ b/repos/base-hw/lib/mk/cortex_a15/core.inc @@ -8,8 +8,5 @@ INC_DIR += $(REP_DIR)/src/core/include/spec/cortex_a15 INC_DIR += $(REP_DIR)/src/core/include/spec/arm_gic -# add C++ sources -SRC_CC += spec/arm_gic/pic.cc - # include less specific configuration include $(REP_DIR)/lib/mk/arm_v7/core.inc diff --git a/repos/base-hw/lib/mk/exynos5/core.mk b/repos/base-hw/lib/mk/exynos5/core.inc similarity index 100% rename from repos/base-hw/lib/mk/exynos5/core.mk rename to repos/base-hw/lib/mk/exynos5/core.inc diff --git a/repos/base-hw/lib/mk/platform_arndale/core.mk b/repos/base-hw/lib/mk/platform_arndale/core.mk new file mode 100644 index 0000000000..543f2548c4 --- /dev/null +++ b/repos/base-hw/lib/mk/platform_arndale/core.mk @@ -0,0 +1,12 @@ +# +# \brief Build config for Genodes core process +# \author Stefan Kalkowski +# \date 2015-02-09 +# + +# add C++ sources +SRC_CC += spec/arndale/board.cc +SRC_CC += spec/arndale/pic.cc + +# include less specific configuration +include $(REP_DIR)/lib/mk/exynos5/core.inc diff --git a/repos/base-hw/lib/mk/platform_odroid_xu/core.mk b/repos/base-hw/lib/mk/platform_odroid_xu/core.mk new file mode 100644 index 0000000000..3d83cc3a4c --- /dev/null +++ b/repos/base-hw/lib/mk/platform_odroid_xu/core.mk @@ -0,0 +1,12 @@ +# +# \brief Build config for Genodes core process +# \author Stefan Kalkowski +# \date 2015-02-09 +# + +# add C++ sources +SRC_CC += spec/exynos5/board.cc +SRC_CC += spec/arm_gic/pic.cc + +# include less specific configuration +include $(REP_DIR)/lib/mk/exynos5/core.inc diff --git a/repos/base-hw/src/core/include/spec/arm/cpu_support.h b/repos/base-hw/src/core/include/spec/arm/cpu_support.h index 2e2cef134a..84ce8d4183 100644 --- a/repos/base-hw/src/core/include/spec/arm/cpu_support.h +++ b/repos/base-hw/src/core/include/spec/arm/cpu_support.h @@ -221,10 +221,19 @@ class Genode::Arm */ struct Psr : Register<32> { - static constexpr access_t usr = 16; - static constexpr access_t svc = 19; + /** + * CPU mode + */ + struct M : Bitfield<0,5> + { + enum { + USR = 16, + SVC = 19, + MON = 22, + HYP = 26, + }; + }; - struct M : Bitfield<0,5> { }; /* CPU mode */ struct F : Bitfield<6,1> { }; /* FIQ disable */ struct I : Bitfield<7,1> { }; /* IRQ disable */ struct A : Bitfield<8,1> { }; /* async. abort disable */ @@ -260,7 +269,7 @@ class Genode::Arm { access_t v = 0; init_common(v); - M::set(v, usr); + M::set(v, M::USR); return v; } @@ -271,7 +280,7 @@ class Genode::Arm { access_t v = 0; init_common(v); - M::set(v, svc); + M::set(v, M::SVC); I::set(v, 1); return v; } @@ -418,7 +427,7 @@ class Genode::Arm /** * Returns true if current execution context is running in user mode */ - static bool is_user() { return Psr::M::get(Psr::read()) == Psr::usr; } + static bool is_user() { return Psr::M::get(Psr::read()) == Psr::M::USR; } /** * Invalidate all entries of all instruction caches diff --git a/repos/base-hw/src/core/include/spec/arm_gic/pic.h b/repos/base-hw/src/core/include/spec/arm_gic/pic.h index c2bf521fda..9f8af3b49f 100644 --- a/repos/base-hw/src/core/include/spec/arm_gic/pic.h +++ b/repos/base-hw/src/core/include/spec/arm_gic/pic.h @@ -51,8 +51,12 @@ class Genode::Arm_gic_distributor : public Mmio /** * Control register */ - struct Ctlr : Register<0x000, 32> { - struct Enable : Bitfield<0,1> { }; }; + struct Ctlr : Register<0x000, 32> + { + struct Enable : Bitfield<0,1> { }; + struct Enable_grp0 : Bitfield<0,1> { }; + struct Enable_grp1 : Bitfield<1,1> { }; + }; /** * Controller type register diff --git a/repos/base-hw/src/core/include/spec/arm_v7/cpu_support.h b/repos/base-hw/src/core/include/spec/arm_v7/cpu_support.h index edd790f2c1..bec851aa8b 100644 --- a/repos/base-hw/src/core/include/spec/arm_v7/cpu_support.h +++ b/repos/base-hw/src/core/include/spec/arm_v7/cpu_support.h @@ -141,14 +141,19 @@ namespace Genode class Genode::Arm_v7 : public Arm { - protected: + public: /** * Secure configuration register */ struct Scr : Register<32> { - struct Ns : Bitfield<0, 1> { }; /* not secure */ + struct Ns : Bitfield<0, 1> { }; /* not secure */ + struct Fw : Bitfield<4, 1> { }; /* F bit writeable */ + struct Aw : Bitfield<5, 1> { }; /* A bit writeable */ + struct Scd : Bitfield<7, 1> { }; /* smc call disable */ + struct Hce : Bitfield<8, 1> { }; /* hyp call enable */ + struct Sif : Bitfield<9, 1> { }; /* secure instruction fetch */ /** * Read register value @@ -159,6 +164,15 @@ class Genode::Arm_v7 : public Arm asm volatile ("mrc p15, 0, %[v], c1, c1, 0" : [v]"=r"(v) ::); return v; } + + /** + * Write register value + */ + static void write(access_t const v) + { + asm volatile ("mcr p15, 0, %[v], c1, c1, 0 \n" + "isb" : : [v] "r" (v)); + } }; /** @@ -168,6 +182,14 @@ class Genode::Arm_v7 : public Arm { struct Cpnsae10 : Bitfield<10, 1> { }; struct Cpnsae11 : Bitfield<11, 1> { }; + + /** + * Write register value + */ + static void write(access_t const v) + { + asm volatile ("mcr p15, 0, %[v], c1, c1, 2" : : [v] "r" (v)); + } }; /** @@ -216,8 +238,6 @@ class Genode::Arm_v7 : public Arm } }; - public: - /** * Invalidate all branch predictions */ @@ -255,37 +275,6 @@ class Genode::Arm_v7 : public Arm finish_init_phys_kernel(); } - /** - * Wether we are in secure mode - */ - static bool secure_mode() - { - if (!Board::SECURITY_EXTENSION) return 0; - return !Scr::Ns::get(Scr::read()); - } - - - /****************************** - ** Trustzone specific API ** - ******************************/ - - /** - * Set exception-vector's address for monitor mode to 'a' - */ - static void mon_exception_entry_at(addr_t const a) { - asm volatile ("mcr p15, 0, %[rd], c12, c0, 1" : : [rd] "r" (a)); } - - /** - * Enable access of co-processors cp10 and cp11 from non-secure mode. - */ - static inline void allow_coprocessor_nonsecure() - { - Nsacr::access_t v = 0; - Nsacr::Cpnsae10::set(v, 1); - Nsacr::Cpnsae11::set(v, 1); - asm volatile ("mcr p15, 0, %[v], c1, c1, 2" : : [v] "r" (v)); - } - /** * Finish all previous data transfers */ @@ -306,6 +295,37 @@ class Genode::Arm_v7 : public Arm * Wait for the next interrupt as cheap as possible */ static void wait_for_interrupt() { asm volatile ("wfi"); } + + + /****************************** + ** Trustzone specific API ** + ******************************/ + + /** + * Wether we are in secure mode + */ + static bool secure_mode() + { + if (!Board::SECURITY_EXTENSION) return 0; + return !Scr::Ns::get(Scr::read()); + } + + /** + * Set exception-vector's address for monitor mode to 'a' + */ + static void mon_exception_entry_at(addr_t const a) { + asm volatile ("mcr p15, 0, %[rd], c12, c0, 1" : : [rd] "r" (a)); } + + + /*********************************** + ** Virtualization specific API ** + ***********************************/ + + /** + * Set exception-vector's address for hypervisor mode to 'a' + */ + static void hyp_exception_entry_at(void * a) { + asm volatile ("mcr p15, 4, %[rd], c12, c0, 0" :: [rd] "r" (a)); } }; @@ -332,7 +352,7 @@ void Genode::Arm::invalidate_data_caches() Genode::Arm::Psr::access_t Genode::Arm::Psr::init_user_with_trustzone() { access_t v = 0; - M::set(v, usr); + M::set(v, M::USR); I::set(v, 1); A::set(v, 1); return v; diff --git a/repos/base-hw/src/core/include/spec/cortex_a15/cpu.h b/repos/base-hw/src/core/include/spec/cortex_a15/cpu.h index 47275aeb4e..1de217781a 100644 --- a/repos/base-hw/src/core/include/spec/cortex_a15/cpu.h +++ b/repos/base-hw/src/core/include/spec/cortex_a15/cpu.h @@ -34,7 +34,7 @@ namespace Kernel { using Genode::Cpu_lazy_state; } class Genode::Cpu : public Arm_v7 { - protected: + public: /** * Translation table base control register @@ -66,7 +66,13 @@ class Genode::Cpu : public Arm_v7 } }; - public: + /** + * Non-secure access control register + */ + struct Nsacr : Arm_v7::Nsacr + { + struct Ns_smp : Bitfield<18,1> { }; + }; /** * Translation table base register 0 (64-bit format) diff --git a/repos/base-hw/src/core/include/spec/exynos5/board.h b/repos/base-hw/src/core/include/spec/exynos5/board.h index 3c6aad8b96..266d760708 100644 --- a/repos/base-hw/src/core/include/spec/exynos5/board.h +++ b/repos/base-hw/src/core/include/spec/exynos5/board.h @@ -25,7 +25,7 @@ namespace Genode static void outer_cache_invalidate() { } static void outer_cache_flush() { } - static void prepare_kernel() { } + static void prepare_kernel(); /** * Tell secondary CPUs to start execution from instr. pointer 'ip' diff --git a/repos/base-hw/src/core/kernel/kernel.cc b/repos/base-hw/src/core/kernel/kernel.cc index 70743bbd42..e52cc55edc 100644 --- a/repos/base-hw/src/core/kernel/kernel.cc +++ b/repos/base-hw/src/core/kernel/kernel.cc @@ -229,6 +229,9 @@ extern "C" void init_kernel_up() /* initialize all CPU objects */ cpu_pool(); + /* initialize PIC */ + pic(); + /* go multiprocessor mode */ Cpu::start_secondary_cpus(&_start_secondary_cpus); } @@ -289,6 +292,9 @@ extern "C" void init_kernel_mp() Cpu::invalidate_instr_caches(); Cpu::data_synchronization_barrier(); + /* locally initialize interrupt controller */ + pic()->init_cpu_local(); + /* initialize CPU in physical mode */ Cpu::init_phys_kernel(); @@ -319,9 +325,8 @@ extern "C" void init_kernel_mp() */ perf_counter()->enable(); - /* locally initialize interrupt controller */ + /* enable timer interrupt */ unsigned const cpu = Cpu::executing_id(); - pic()->init_cpu_local(); pic()->unmask(Timer::interrupt_id(cpu), cpu); /* do further initialization only as primary CPU */ diff --git a/repos/base-hw/src/core/spec/arm_v7/mode_transition.s b/repos/base-hw/src/core/spec/arm_v7/mode_transition.s index bd47095273..b8a46d29c5 100644 --- a/repos/base-hw/src/core/spec/arm_v7/mode_transition.s +++ b/repos/base-hw/src/core/spec/arm_v7/mode_transition.s @@ -236,6 +236,16 @@ .endm /* _kernel_to_vm */ +/** + * Enter kernel after hypervisor call + */ +.macro _hyp_to_kernel exception_type + cps #SVC_MODE + mov r0, #\exception_type + 1: b 1b +.endm /* _hyp_to_kernel */ + + /********************************** ** Linked into the text section ** **********************************/ @@ -400,7 +410,7 @@ ldm sp, {r0, r1, pc}^ /* - * On vm exceptions the CPU has to jump to one of the following + * On TrustZone exceptions the CPU has to jump to one of the following * 7 entry vectors to switch to a kernel context. */ .p2align 5 @@ -429,6 +439,30 @@ _mt_vm_entry_pic: _kernel_to_vm + /* + * On virtualization exceptions the CPU has to jump to one of the following + * 7 entry vectors to switch to a kernel context. + */ + .p2align 4 + .global _hyp_kernel_entry + _hyp_kernel_entry: + b _hyp_rst_entry + b _hyp_und_entry /* undefined instruction */ + b _hyp_svc_entry /* hypervisor call */ + b _hyp_pab_entry /* prefetch abort */ + b _hyp_dab_entry /* data abort */ + b _hyp_trp_entry /* hypervisor trap */ + b _hyp_irq_entry /* interrupt request */ + _hyp_to_kernel 7 /* fast interrupt request */ + + _hyp_rst_entry: _hyp_to_kernel 0 + _hyp_und_entry: _hyp_to_kernel 1 + _hyp_svc_entry: _hyp_to_kernel 2 + _hyp_pab_entry: _hyp_to_kernel 3 + _hyp_dab_entry: _hyp_to_kernel 4 + _hyp_trp_entry: _hyp_to_kernel 5 + _hyp_irq_entry: _hyp_to_kernel 6 + /* end of the mode transition code */ .global _mt_end _mt_end: diff --git a/repos/base-hw/src/core/spec/arndale/board.cc b/repos/base-hw/src/core/spec/arndale/board.cc new file mode 100644 index 0000000000..70722df3b0 --- /dev/null +++ b/repos/base-hw/src/core/spec/arndale/board.cc @@ -0,0 +1,83 @@ +/* + * \brief Board-specific code for Arndale + * \author Stefan Kalkowski + * \date 2015-02-09 + */ + +/* + * Copyright (C) 2015 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. + */ + +/* core includes */ +#include +#include + +/* hypervisor exception vector address */ +extern void* _hyp_kernel_entry; + + +static inline void prepare_nonsecure_world() +{ + using Nsacr = Genode::Cpu::Nsacr; + using Cpsr = Genode::Cpu::Psr; + using Scr = Genode::Cpu::Scr; + + /* if we are already in HYP mode we're done (depends on u-boot version) */ + if (Cpsr::M::get(Cpsr::read()) == Cpsr::M::HYP) + return; + + /* + * enable coprocessor 10 + 11 access and SMP bit access in auxiliary control + * register for non-secure world + */ + Nsacr::access_t nsacr = 0; + Nsacr::Cpnsae10::set(nsacr, 1); + Nsacr::Cpnsae11::set(nsacr, 1); + Nsacr::Ns_smp::set(nsacr, 1); + Nsacr::write(nsacr); + + asm volatile ( + "msr sp_mon, sp \n" /* copy current mode's sp */ + "msr lr_mon, lr \n" /* copy current mode's lr */ + "cps #22 \n" /* switch to monitor mode */ + ); + + Scr::access_t scr = 0; + Scr::Ns::set(scr, 1); + Scr::Fw::set(scr, 1); + Scr::Aw::set(scr, 1); + Scr::Scd::set(scr, 1); + Scr::Hce::set(scr, 1); + Scr::Sif::set(scr, 1); + Scr::write(scr); +} + + +static inline void switch_to_supervisor_mode() +{ + using Psr = Genode::Cpu::Psr; + + Psr::access_t psr = 0; + Psr::M::set(psr, Psr::M::SVC); + Psr::F::set(psr, 1); + Psr::I::set(psr, 1); + + asm volatile ( + "msr sp_svc, sp \n" /* copy current mode's sp */ + "msr lr_svc, lr \n" /* copy current mode's lr */ + "msr elr_hyp, lr \n" /* copy current mode's lr to hyp lr */ + "msr spsr_cxfs, %[psr] \n" /* set psr for supervisor mode */ + "eret \n" /* exception return */ + :: [psr] "r" (psr)); +} + + +void Genode::Board::prepare_kernel() +{ + prepare_nonsecure_world(); + Genode::Cpu::hyp_exception_entry_at(&_hyp_kernel_entry); + switch_to_supervisor_mode(); +} diff --git a/repos/base-hw/src/core/spec/arndale/pic.cc b/repos/base-hw/src/core/spec/arndale/pic.cc new file mode 100644 index 0000000000..55c6e69135 --- /dev/null +++ b/repos/base-hw/src/core/spec/arndale/pic.cc @@ -0,0 +1,59 @@ +/* + * \brief Programmable interrupt controller for core + * \author Stefan Kalkowski + * \date 2012-10-24 + */ + +/* + * 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. + */ + +/* core includes */ +#include + +using namespace Genode; + +void Pic::_init() +{ + /* disable device */ + _distr.write(0); + + /* configure every shared peripheral interrupt */ + for (unsigned i = min_spi; i <= _max_irq; i++) { + /* mark as non-secure */ + _distr.write(1, i); + _distr.write(0, i); + _distr.write(0, i); + } + /* enable device */ + Distr::Ctlr::access_t v = 0; + Distr::Ctlr::Enable_grp0::set(v, 1); + Distr::Ctlr::Enable_grp1::set(v, 1); + _distr.write(v); +} + + +void Pic::init_cpu_local() +{ + _cpui.write(0); + + /* mark software-generated IRQs as being non-secure */ + for (unsigned i = 0; i < min_spi; i++) + _distr.write(1, i); + + /* disable the priority filter */ + _cpui.write(_distr.min_priority()); + + /* disable preemption of IRQ handling by other IRQs */ + _cpui.write(~0); + + /* enable device */ + Cpui::Ctlr::access_t v = 0; + Cpui::Ctlr::Enable_grp0::set(v, 1); + Cpui::Ctlr::Enable_grp1::set(v, 1); + Cpui::Ctlr::Fiq_en::set(v, 1); + _cpui.write(v); +} diff --git a/repos/base-hw/src/core/spec/exynos5/board.cc b/repos/base-hw/src/core/spec/exynos5/board.cc new file mode 100644 index 0000000000..3f28938046 --- /dev/null +++ b/repos/base-hw/src/core/spec/exynos5/board.cc @@ -0,0 +1,17 @@ +/* + * \brief Board-specific code for Exynos5 boards + * \author Stefan Kalkowski + * \date 2015-02-09 + */ + +/* + * Copyright (C) 2015 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. + */ + +/* core includes */ +#include + +void Genode::Board::prepare_kernel() { } diff --git a/repos/base-hw/src/core/spec/imx53/trustzone/platform_support.cc b/repos/base-hw/src/core/spec/imx53/trustzone/platform_support.cc index 339f5c881a..297265da99 100644 --- a/repos/base-hw/src/core/spec/imx53/trustzone/platform_support.cc +++ b/repos/base-hw/src/core/spec/imx53/trustzone/platform_support.cc @@ -39,8 +39,11 @@ void Kernel::init_trustzone(Pic * pic) /* set exception vector entry */ Cpu::mon_exception_entry_at((Genode::addr_t)&_mon_kernel_entry); - /* enable coprocessor access for TZ VMs */ - Cpu::allow_coprocessor_nonsecure(); + /* enable coprocessor 10 + 11 access for TZ VMs */ + Cpu::Nsacr::access_t v = 0; + Cpu::Nsacr::Cpnsae10::set(v, 1); + Cpu::Nsacr::Cpnsae11::set(v, 1); + Cpu::Nsacr::write(v); /* configure non-secure interrupts */ for (unsigned i = 0; i < Pic::NR_OF_IRQ; i++) {