diff --git a/repos/base-hw/lib/mk/spec/arm_v6/core.inc b/repos/base-hw/lib/mk/spec/arm_v6/core.inc index ad61c26fb..0d10e7cfd 100644 --- a/repos/base-hw/lib/mk/spec/arm_v6/core.inc +++ b/repos/base-hw/lib/mk/spec/arm_v6/core.inc @@ -1,6 +1,7 @@ # # \brief Build config for Genodes core process # \author Martin Stein +# \author Stefan Kalkowski # \date 2012-10-04 # @@ -8,11 +9,11 @@ INC_DIR += $(REP_DIR)/src/core/include/spec/arm_v6 # add C++ sources -SRC_CC += spec/arm/cpu.cc -SRC_CC += spec/arm/kernel/cpu_context.cc -SRC_CC += kernel/vm_thread.cc SRC_CC += spec/arm_v6/cpu.cc +SRC_CC += spec/arm/kernel/cpu_context.cc SRC_CC += spec/arm/kernel/cpu.cc +SRC_CC += spec/arm/kernel/thread_update_pd.cc +SRC_CC += kernel/vm_thread.cc SRC_CC += kernel/kernel.cc # add assembly sources diff --git a/repos/base-hw/lib/mk/spec/arndale/core.mk b/repos/base-hw/lib/mk/spec/arndale/core.mk index 24f45dbf7..fbcb40e1f 100644 --- a/repos/base-hw/lib/mk/spec/arndale/core.mk +++ b/repos/base-hw/lib/mk/spec/arndale/core.mk @@ -8,7 +8,7 @@ INC_DIR += $(REP_DIR)/src/core/include/spec/arm_v7/virtualization # add C++ sources -SRC_CC += spec/arndale/board.cc +SRC_CC += spec/arndale/cpu.cc SRC_CC += spec/arndale/pic.cc SRC_CC += spec/arndale/platform_services.cc SRC_CC += spec/arm_v7/kernel/vm_thread.cc diff --git a/repos/base-hw/lib/mk/spec/cortex_a15/core.inc b/repos/base-hw/lib/mk/spec/cortex_a15/core.inc index ab1332890..4d973614b 100644 --- a/repos/base-hw/lib/mk/spec/cortex_a15/core.inc +++ b/repos/base-hw/lib/mk/spec/cortex_a15/core.inc @@ -7,15 +7,16 @@ # add include paths INC_DIR += $(REP_DIR)/src/core/include/spec/cortex_a15 INC_DIR += $(REP_DIR)/src/core/include/spec/arm_gic -INC_DIR += $(REP_DIR)/src/core/include/spec/smp # add C++ sources SRC_CC += spec/cortex_a15/cpu.cc -SRC_CC += spec/arm_v7/smp/kernel/cpu.cc -SRC_CC += spec/smp/kernel/kernel.cc +SRC_CC += spec/cortex_a15/kernel/cpu.cc +SRC_CC += spec/arm/smp/kernel/thread_update_pd.cc +SRC_CC += spec/arm/smp/kernel/cpu.cc # add assembler sources SRC_S += spec/arm/smp/kernel/crt0.s # include less specific configuration +include $(REP_DIR)/lib/mk/spec/smp/core.inc include $(REP_DIR)/lib/mk/spec/arm_v7/core.inc diff --git a/repos/base-hw/lib/mk/spec/cortex_a8/core.inc b/repos/base-hw/lib/mk/spec/cortex_a8/core.inc index 1fed9aab1..a135176ba 100644 --- a/repos/base-hw/lib/mk/spec/cortex_a8/core.inc +++ b/repos/base-hw/lib/mk/spec/cortex_a8/core.inc @@ -8,9 +8,10 @@ INC_DIR += $(REP_DIR)/src/core/include/spec/cortex_a8 # add C++ sources -SRC_CC += spec/arm/cpu.cc +SRC_CC += spec/cortex_a8/cpu.cc SRC_CC += spec/arm/kernel/cpu_context.cc SRC_CC += spec/arm/kernel/cpu.cc +SRC_CC += spec/arm/kernel/thread_update_pd.cc SRC_CC += kernel/kernel.cc # include less specific configuration diff --git a/repos/base-hw/lib/mk/spec/cortex_a9/core.inc b/repos/base-hw/lib/mk/spec/cortex_a9/core.inc index 6223590bb..8ea7a4cbd 100644 --- a/repos/base-hw/lib/mk/spec/cortex_a9/core.inc +++ b/repos/base-hw/lib/mk/spec/cortex_a9/core.inc @@ -9,12 +9,17 @@ INC_DIR += $(REP_DIR)/src/core/include/spec/cortex_a9 INC_DIR += $(REP_DIR)/src/core/include/spec/arm_gic # add C++ sources -SRC_CC += spec/arm/cpu.cc -SRC_CC += spec/arm_gic/pic.cc +SRC_CC += spec/cortex_a9/kernel/cpu.cc +SRC_CC += spec/cortex_a9/cpu.cc +SRC_CC += spec/arm/smp/kernel/thread_update_pd.cc +SRC_CC += spec/arm/smp/kernel/cpu.cc SRC_CC += spec/arm/kernel/cpu_context.cc +SRC_CC += spec/arm_gic/pic.cc SRC_CC += kernel/vm_thread.cc -SRC_CC += spec/arm/kernel/cpu.cc -SRC_CC += kernel/kernel.cc + +# add Assembler sources +SRC_S += spec/arm/smp/kernel/crt0.s # include less specific configuration +include $(REP_DIR)/lib/mk/spec/smp/core.inc include $(REP_DIR)/lib/mk/spec/arm_v7/core.inc diff --git a/repos/base-hw/lib/mk/spec/odroid_xu/core.mk b/repos/base-hw/lib/mk/spec/odroid_xu/core.mk index 4d995650c..b63be2d6f 100644 --- a/repos/base-hw/lib/mk/spec/odroid_xu/core.mk +++ b/repos/base-hw/lib/mk/spec/odroid_xu/core.mk @@ -5,11 +5,11 @@ # # add C++ sources -SRC_CC += spec/exynos5/board.cc -SRC_CC += spec/arm_gic/pic.cc -SRC_CC += platform_services.cc -SRC_CC += kernel/vm_thread.cc +SRC_CC += spec/cortex_a15/cpu_init.cc SRC_CC += spec/arm/kernel/cpu_context.cc +SRC_CC += spec/arm_gic/pic.cc +SRC_CC += kernel/vm_thread.cc +SRC_CC += platform_services.cc # include less specific configuration include $(REP_DIR)/lib/mk/spec/exynos5/core.inc diff --git a/repos/base-hw/lib/mk/spec/pbxa9/core.mk b/repos/base-hw/lib/mk/spec/pbxa9/core.mk index 778a8b819..8327b6523 100644 --- a/repos/base-hw/lib/mk/spec/pbxa9/core.mk +++ b/repos/base-hw/lib/mk/spec/pbxa9/core.mk @@ -12,6 +12,7 @@ INC_DIR += $(REP_DIR)/src/core/include/spec/pl011 # add C++ sources SRC_CC += platform_services.cc SRC_CC += spec/pbxa9/platform_support.cc +SRC_CC += spec/pbxa9/board.cc # include less specific configuration include $(REP_DIR)/lib/mk/spec/cortex_a9/core.inc diff --git a/repos/base-hw/lib/mk/spec/smp/core.inc b/repos/base-hw/lib/mk/spec/smp/core.inc new file mode 100644 index 000000000..aef1d8edc --- /dev/null +++ b/repos/base-hw/lib/mk/spec/smp/core.inc @@ -0,0 +1,12 @@ +# +# \brief Build config for Genodes core process +# \author Stefan Kalkowski +# \date 2016-01-04 +# + +# add include paths +INC_DIR += $(REP_DIR)/src/core/include/spec/smp + +# add C++ sources +SRC_CC += spec/smp/kernel/kernel.cc +SRC_CC += spec/smp/kernel/cpu.cc diff --git a/repos/base-hw/lib/mk/spec/x86/core.inc b/repos/base-hw/lib/mk/spec/x86/core.inc index 8a0d8ce35..e6e929068 100644 --- a/repos/base-hw/lib/mk/spec/x86/core.inc +++ b/repos/base-hw/lib/mk/spec/x86/core.inc @@ -11,8 +11,10 @@ INC_DIR += $(REP_DIR)/src/core/include/spec/x86 # add C++ sources SRC_CC += kernel/kernel.cc SRC_CC += kernel/vm_thread.cc -SRC_CC += spec/x86/platform_support.cc SRC_CC += spec/x86/kernel/pd.cc +SRC_CC += spec/x86/kernel/cpu.cc +SRC_CC += spec/x86/kernel/thread.cc +SRC_CC += spec/x86/platform_support.cc SRC_CC += spec/x86/cpu.cc SRC_CC += spec/x86/bios_data_area.cc SRC_CC += spec/x86/io_port_session_component.cc diff --git a/repos/base-hw/lib/mk/spec/x86_64/core-muen_off.mk b/repos/base-hw/lib/mk/spec/x86_64/core-muen_off.mk index 2085a133d..de7de4990 100644 --- a/repos/base-hw/lib/mk/spec/x86_64/core-muen_off.mk +++ b/repos/base-hw/lib/mk/spec/x86_64/core-muen_off.mk @@ -8,9 +8,9 @@ SRC_S += spec/x86_64/kernel/crt0_translation_table.s # add C++ sources -SRC_CC += spec/x86/kernel/thread.cc -SRC_CC += spec/x86/kernel/cpu.cc SRC_CC += spec/x86/pic.cc +SRC_CC += spec/x86/kernel/cpu_exception.cc +SRC_CC += spec/x86/kernel/thread_exception.cc SRC_CC += spec/x86_64/platform_support.cc # include less specific configuration diff --git a/repos/base-hw/lib/mk/spec/x86_64/core-muen_on.mk b/repos/base-hw/lib/mk/spec/x86_64/core-muen_on.mk index 4100f840d..e6d297af5 100644 --- a/repos/base-hw/lib/mk/spec/x86_64/core-muen_on.mk +++ b/repos/base-hw/lib/mk/spec/x86_64/core-muen_on.mk @@ -11,8 +11,8 @@ INC_DIR += $(REP_DIR)/src/core/include/spec/x86_64/muen SRC_S += spec/x86_64/muen/kernel/crt0_translation_table.s # add C++ sources -SRC_CC += spec/x86_64/muen/kernel/thread.cc -SRC_CC += spec/x86_64/muen/kernel/cpu.cc +SRC_CC += spec/x86_64/muen/kernel/cpu_exception.cc +SRC_CC += spec/x86_64/muen/kernel/thread_exception.cc SRC_CC += spec/x86_64/muen/platform_support.cc SRC_CC += spec/x86_64/muen/sinfo.cc diff --git a/repos/base-hw/mk/spec/hw_panda.mk b/repos/base-hw/mk/spec/hw_panda.mk index 0b1cad1e6..0073363a0 100644 --- a/repos/base-hw/mk/spec/hw_panda.mk +++ b/repos/base-hw/mk/spec/hw_panda.mk @@ -8,7 +8,7 @@ SPECS += hw panda # configure multiprocessor mode -NR_OF_CPUS = 1 +NR_OF_CPUS = 2 # set address where to link the text segment at LD_TEXT_ADDR ?= 0x81000000 diff --git a/repos/base-hw/src/core/include/kernel/cpu.h b/repos/base-hw/src/core/include/kernel/cpu.h index 74acd7b27..9bcb85e02 100644 --- a/repos/base-hw/src/core/include/kernel/cpu.h +++ b/repos/base-hw/src/core/include/kernel/cpu.h @@ -287,8 +287,9 @@ class Kernel::Cpu : public Genode::Cpu, * * \param pic interrupt controller object * \param core_pd core's pd object + * \param board object encapsulating board specifics */ - void init(Pic &pic, Kernel::Pd &core_pd); + void init(Pic &pic, Kernel::Pd &core_pd, Genode::Board & board); /** * Raise the IPI of the CPU diff --git a/repos/base-hw/src/core/include/kernel/kernel.h b/repos/base-hw/src/core/include/kernel/kernel.h index fefb27b07..aa92ff1f7 100644 --- a/repos/base-hw/src/core/include/kernel/kernel.h +++ b/repos/base-hw/src/core/include/kernel/kernel.h @@ -6,7 +6,7 @@ */ /* - * Copyright (C) 2013 Genode Labs GmbH + * Copyright (C) 2013-2016 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. @@ -16,6 +16,7 @@ #define _KERNEL__KERNEL_H_ #include +#include /** * Main routine of every kernel pass @@ -26,11 +27,10 @@ extern "C" void kernel(); namespace Kernel { class Pd; - class Mode_transition_control; - Pd * core_pd(); - Mode_transition_control * mtc(); - Pic * pic(); + Pd * core_pd(); + Pic * pic(); + Genode::Board & board(); } #endif /* _KERNEL__KERNEL_H_ */ 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 e7457e979..8d52bdd00 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 @@ -6,7 +6,7 @@ */ /* - * Copyright (C) 2012-2013 Genode Labs GmbH + * Copyright (C) 2012-2016 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. @@ -20,9 +20,12 @@ #include /* local includes */ +#include #include #include +namespace Kernel { class Pd; } + namespace Genode { /** @@ -30,6 +33,8 @@ namespace Genode */ class Arm; + class Cpu_lazy_state; + typedef Genode::uint64_t sizet_arithm_t; } @@ -75,6 +80,7 @@ class Genode::Arm struct Sctlr : Register<32> { struct M : Bitfield<0,1> { }; /* enable MMU */ + struct A : Bitfield<1,1> { }; /* enable alignment checks */ struct C : Bitfield<2,1> { }; /* enable data cache */ struct I : Bitfield<12,1> { }; /* enable instruction caches */ struct V : Bitfield<13,1> { }; /* select exception entry */ @@ -89,20 +95,26 @@ class Genode::Arm static void write(access_t const v) { asm volatile ("mcr p15, 0, %0, c1, c0, 0" :: "r" (v) : ); } - /** - * Do initialization that is common on value 'v' - */ - static void init_common(access_t & v) + static void init() { - C::set(v, 1); - I::set(v, 1); + access_t v = read(); + + /* disable alignment checks */ + A::set(v, 0); + + /* set exception vector to 0xffff0000 */ V::set(v, 1); + write(v); } - /** - * Do initialization for virtual mode in kernel on value 'v' - */ - static void init_virt_kernel(access_t & v) { M::set(v, 1); } + static void enable_mmu_and_caches() + { + access_t v = read(); + C::set(v, 1); + I::set(v, 1); + M::set(v, 1); + write(v); + } }; /** @@ -162,8 +174,8 @@ class Genode::Arm { access_t v = Ba::masked((addr_t)table); Rgn::set(v, CACHEABLE); - S::set(v, Board::is_smp() ? 1 : 0); - if (Board::is_smp()) Irgn::set(v, CACHEABLE); + S::set(v, Kernel::board().is_smp() ? 1 : 0); + if (Kernel::board().is_smp()) Irgn::set(v, CACHEABLE); else C::set(v, 1); return v; } @@ -473,54 +485,42 @@ class Genode::Arm /** * Invalidate all entries of all instruction caches */ - __attribute__((always_inline)) static void invalidate_instr_caches() { + void invalidate_instr_cache() { asm volatile ("mcr p15, 0, %0, c7, c5, 0" :: "r" (0) : ); } /** * Flush all entries of all data caches */ - static void flush_data_caches(); + void clean_invalidate_data_cache(); /** - * Invalidate all entries of all data caches + * Switch on MMU and caches + * + * \param pd kernel's pd object */ - static void invalidate_data_caches(); - - /** - * Flush all caches - */ - static void flush_caches() - { - flush_data_caches(); - invalidate_instr_caches(); - } + void enable_mmu_and_caches(Kernel::Pd & pd); /** * Invalidate all TLB entries of the address space named 'pid' */ - static void flush_tlb_by_pid(unsigned const pid) - { - flush_caches(); - asm volatile ("mcr p15, 0, %0, c8, c7, 2" :: "r" (pid) : ); - } + void invalidate_tlb_by_pid(unsigned const pid) { + asm volatile ("mcr p15, 0, %0, c8, c7, 2" :: "r" (pid) : ); } /** * Invalidate all TLB entries */ - static void flush_tlb() - { - flush_caches(); - asm volatile ("mcr p15, 0, %0, c8, c7, 0" :: "r" (0) : ); - } + void invalidate_tlb() { + asm volatile ("mcr p15, 0, %0, c8, c7, 0" :: "r" (0) : ); } static constexpr addr_t line_size = 1 << Board::CACHE_LINE_SIZE_LOG2; static constexpr addr_t line_align_mask = ~(line_size - 1); /** - * Flush data-cache entries for virtual region ['base', 'base + size') + * Clean and invalidate data-cache for virtual region + * 'base' - 'base + size' */ - static void - flush_data_caches_by_virt_region(addr_t base, size_t const size) + void clean_invalidate_data_cache_by_virt_region(addr_t base, + size_t const size) { addr_t const top = base + size; base &= line_align_mask; @@ -528,15 +528,34 @@ class Genode::Arm } /** - * Bin instr.-cache entries for virtual region ['base', 'base + size') + * Invalidate instruction-cache for virtual region + * 'base' - 'base + size' */ - static void - invalidate_instr_caches_by_virt_region(addr_t base, size_t const size) + void invalidate_instr_cache_by_virt_region(addr_t base, + size_t const size) { addr_t const top = base + size; base &= line_align_mask; for (; base < top; base += line_size) { Icimvau::write(base); } } + + + /************* + ** Dummies ** + *************/ + + void prepare_proceeding(Cpu_lazy_state *, Cpu_lazy_state *) { } + bool retry_undefined_instr(Cpu_lazy_state *) { return false; } + + /** + * Return kernel name of the executing CPU + */ + static unsigned executing_id() { return 0; } + + /** + * Return kernel name of the primary CPU + */ + static unsigned primary_id() { return 0; } }; #endif /* _SPEC__ARM__CPU_SUPPORT_H_ */ diff --git a/repos/base-hw/src/core/include/spec/arm/pl310.h b/repos/base-hw/src/core/include/spec/arm/pl310.h index 806e6ba0e..fb2898a50 100644 --- a/repos/base-hw/src/core/include/spec/arm/pl310.h +++ b/repos/base-hw/src/core/include/spec/arm/pl310.h @@ -7,7 +7,7 @@ */ /* - * Copyright (C) 2014-2015 Genode Labs GmbH + * Copyright (C) 2014-2016 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. @@ -24,62 +24,69 @@ namespace Arm struct Pl310; } + /** * L2 outer cache controller */ -struct Arm::Pl310 : Genode::Mmio +class Arm::Pl310 : public Genode::Mmio { - struct Control : Register <0x100, 32> - { - struct Enable : Bitfield<0,1> { }; - }; + protected: - struct Aux : Register<0x104, 32> - { - struct Associativity : Bitfield<16,1> { }; - struct Way_size : Bitfield<17,3> { }; - struct Share_override : Bitfield<22,1> { }; - struct Reserved : Bitfield<25,1> { }; - struct Ns_lockdown : Bitfield<26,1> { }; - struct Ns_irq_ctrl : Bitfield<27,1> { }; - struct Data_prefetch : Bitfield<28,1> { }; - struct Inst_prefetch : Bitfield<29,1> { }; - struct Early_bresp : Bitfield<30,1> { }; - }; + struct Control : Register <0x100, 32> + { + struct Enable : Bitfield<0,1> { }; + }; - struct Irq_mask : Register <0x214, 32> { }; - struct Irq_clear : Register <0x220, 32> { }; - struct Cache_sync : Register <0x730, 32> { }; - struct Invalidate_by_way : Register <0x77c, 32> { }; - struct Clean_invalidate_by_way : Register <0x7fc, 32> { }; + struct Aux : Register<0x104, 32> + { + struct Associativity : Bitfield<16,1> { }; + struct Way_size : Bitfield<17,3> { }; + struct Share_override : Bitfield<22,1> { }; + struct Reserved : Bitfield<25,1> { }; + struct Ns_lockdown : Bitfield<26,1> { }; + struct Ns_irq_ctrl : Bitfield<27,1> { }; + struct Data_prefetch : Bitfield<28,1> { }; + struct Inst_prefetch : Bitfield<29,1> { }; + struct Early_bresp : Bitfield<30,1> { }; + }; - struct Debug : Register<0xf40, 32> - { - struct Dcl : Bitfield<0,1> { }; - struct Dwb : Bitfield<1,1> { }; - }; + struct Irq_mask : Register <0x214, 32> { }; + struct Irq_clear : Register <0x220, 32> { }; + struct Cache_sync : Register <0x730, 32> { }; + struct Invalidate_by_way : Register <0x77c, 32> { }; + struct Clean_invalidate_by_way : Register <0x7fc, 32> { }; - Pl310(Genode::addr_t const base) : Mmio(base) { } + struct Debug : Register<0xf40, 32> + { + struct Dcl : Bitfield<0,1> { }; + struct Dwb : Bitfield<1,1> { }; + }; - inline void sync() { while (read()) ; } + void _sync() { while (read()) ; } - void flush() - { - write((1UL << 16) - 1); - sync(); - } + public: - void invalidate() - { - write((1UL << 16) - 1); - sync(); - } + Pl310(Genode::addr_t const base) : Mmio(base) { } - void mask_interrupts() - { - write(0); - write(~0UL); - } + void enable() {} + + void clean_invalidate() + { + write((1UL << 16) - 1); + _sync(); + } + + void invalidate() + { + write((1UL << 16) - 1); + _sync(); + } + + void mask_interrupts() + { + write(0); + write(~0UL); + } }; #endif /* _SPEC__ARM__PL310_H_ */ diff --git a/repos/base-hw/src/core/include/spec/arm/short_translation_table.h b/repos/base-hw/src/core/include/spec/arm/short_translation_table.h index 95003b4d4..8e48b0ae4 100644 --- a/repos/base-hw/src/core/include/spec/arm/short_translation_table.h +++ b/repos/base-hw/src/core/include/spec/arm/short_translation_table.h @@ -62,7 +62,7 @@ class Genode::Translation _create(Page_flags const & f, addr_t const pa) { typename T::access_t v = T::Pa::masked(pa); - T::S::set(v, Board::is_smp()); + T::S::set(v, Kernel::board().is_smp()); T::Ng::set(v, !f.global); T::Xn::set(v, !f.executable); if (f.device) { T::Tex::set(v, _device_tex()); } 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 8fd1696f8..7e594bf90 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 @@ -107,6 +107,10 @@ class Genode::Arm_gic_distributor : public Mmio { struct Sgi_int_id : Bitfield<0, 4> { }; struct Cpu_target_list : Bitfield<16, 8> { }; + struct Target_list_filter : Bitfield<24, 2> + { + enum Target { TARGET_LIST, ALL_OTHER, MYSELF }; + }; }; /** @@ -266,7 +270,7 @@ class Genode::Pic /** * Raise inter-processor IRQ of the CPU with kernel name 'cpu_id' */ - void trigger_ip_interrupt(unsigned const cpu_id) + void send_ipi(unsigned const cpu_id) { typedef Distr::Sgir Sgir; Sgir::access_t sgir = 0; @@ -274,6 +278,19 @@ class Genode::Pic Sgir::Cpu_target_list::set(sgir, 1 << cpu_id); _distr.write(sgir); } + + /** + * Raise inter-processor interrupt on all other cores + */ + void send_ipi() + { + typedef Distr::Sgir Sgir; + Sgir::access_t sgir = 0; + Sgir::Sgi_int_id::set(sgir, IPI); + Sgir::Target_list_filter::set(sgir, + Sgir::Target_list_filter::ALL_OTHER); + _distr.write(sgir); + } }; #endif /* _SPEC__ARM_GIC__PIC_SUPPORT_H_ */ diff --git a/repos/base-hw/src/core/include/spec/arm_v6/cpu.h b/repos/base-hw/src/core/include/spec/arm_v6/cpu.h index 47300393e..38e3def49 100644 --- a/repos/base-hw/src/core/include/spec/arm_v6/cpu.h +++ b/repos/base-hw/src/core/include/spec/arm_v6/cpu.h @@ -35,8 +35,6 @@ namespace Genode namespace Kernel { using Genode::Cpu_lazy_state; - - class Pd; } class Genode::Cpu : public Arm @@ -61,43 +59,18 @@ class Genode::Cpu : public Arm struct It : Bitfield<18,1> { }; /* global instruction TCM enable */ struct U : Bitfield<22,1> { }; /* enable unaligned data access */ struct Xp : Bitfield<23,1> { }; /* disable subpage AP bits */ - struct Unnamed_0 : Bitfield<4,3> { }; /* shall be ones */ - struct Unnamed_1 : Bitfield<26,6> { }; /* shall not be modified */ - /** - * Initialization that is common - */ - static void init_common(access_t & v) + static void init() { - Arm::Sctlr::init_common(v); + access_t v = read(); + A::set(v, 0); + V::set(v, 1); W::set(v, 1); Dt::set(v, 1); It::set(v, 1); U::set(v, 1); Xp::set(v, 1); - Unnamed_0::set(v, ~0); - Unnamed_1::set(v, Unnamed_1::masked(read())); - } - - /** - * Initialization for physical kernel stage - */ - static access_t init_virt_kernel() - { - access_t v = 0; - init_common(v); - Arm::Sctlr::init_virt_kernel(v); - return v; - } - - /** - * Initialization for physical kernel stage - */ - static access_t init_phys_kernel() - { - access_t v = 0; - init_common(v); - return v; + write(v); } }; @@ -107,30 +80,15 @@ class Genode::Cpu : public Arm static bool restricted_page_mappings() { return Ctr::P::get(Ctr::read()); } - /** - * Configure this module appropriately for the first kernel run - */ - static void init_phys_kernel() - { - Board::prepare_kernel(); - Sctlr::write(Sctlr::init_phys_kernel()); - flush_tlb(); - - /* check for mapping restrictions */ - assert(!restricted_page_mappings()); - } - - /** - * Switch to the virtual mode in kernel - * - * \param pd kernel's pd object - */ - static void init_virt_kernel(Kernel::Pd& pd); - /** * Ensure that TLB insertions get applied */ - static void tlb_insertions() { flush_tlb(); } + void translation_table_insertions() + { + clean_invalidate_data_cache(); + invalidate_instr_cache(); + invalidate_tlb(); + } /** * Return wether to retry an undefined user instruction after this call @@ -143,28 +101,8 @@ class Genode::Cpu : public Arm * \param addr virtual address of the translation * \param size size of the translation */ - static void translation_added(addr_t const addr, size_t const size) - { - /* - * The Cortex-A8 CPU can't use the L1 cache on page-table - * walks. Therefore, as the page-tables lie in write-back cacheable - * memory we've to clean the corresponding cache-lines even when a - * page table entry is added. We only do this as core as the kernel - * adds translations solely before MMU and caches are enabled. - */ - if (is_user()) Kernel::update_data_region(addr, size); - else flush_data_caches(); - } + static void translation_added(addr_t const addr, size_t const size); - /** - * Return kernel name of the executing CPU - */ - static unsigned executing_id(); - - /** - * Return kernel name of the primary CPU - */ - static unsigned primary_id(); /************* ** Dummies ** 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 2d1cab8ca..26f35fc0b 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 @@ -17,6 +17,7 @@ /* core includes */ #include #include +#include namespace Genode { @@ -26,8 +27,6 @@ namespace Genode class Arm_v7; } -namespace Kernel { class Pd; } - class Genode::Arm_v7 : public Arm { @@ -88,44 +87,21 @@ class Genode::Arm_v7 : public Arm struct Sctlr : Arm::Sctlr { struct Z : Bitfield<11,1> { }; /* enable program flow prediction */ - struct Unnamed_0 : Bitfield<3,4> { }; /* shall be ones */ - struct Unnamed_1 : Bitfield<16,1> { }; /* shall be ones */ - struct Unnamed_2 : Bitfield<18,1> { }; /* shall be ones */ - struct Unnamed_3 : Bitfield<22,2> { }; /* shall be ones */ - /** - * Initialization that is common - */ - static void init_common(access_t & v) + static access_t init_value() { - Arm::Sctlr::init_common(v); - Unnamed_0::set(v, ~0); - Unnamed_1::set(v, ~0); - Unnamed_2::set(v, ~0); - Unnamed_3::set(v, ~0); - } - - /** - * Initialization for virtual kernel stage - */ - static access_t init_virt_kernel() - { - access_t v = 0; - init_common(v); - Arm::Sctlr::init_virt_kernel(v); + access_t v = read(); + C::set(v, 1); + I::set(v, 1); + V::set(v, 1); + A::set(v, 0); + M::set(v, 1); Z::set(v, 1); return v; } - /** - * Initialization for physical kernel stage - */ - static access_t init_phys_kernel() - { - access_t v = 0; - init_common(v); - return v; - } + static void enable_mmu_and_caches() { + write(init_value()); } }; @@ -143,33 +119,19 @@ class Genode::Arm_v7 : public Arm asm volatile ("mcr p15, 0, %[v], c10, c2, 0" :: [v]"r"(v) : ); } }; - /** * Invalidate all branch predictions */ - static void inval_branch_predicts() { + static void invalidate_branch_predicts() { asm volatile ("mcr p15, 0, r0, c7, c5, 6" ::: "r0"); }; /** - * Switch to the virtual mode in kernel + * Switch on MMU and caches * * \param pd kernel's pd object */ - static void init_virt_kernel(Kernel::Pd& pd); + void enable_mmu_and_caches(Kernel::Pd& pd); - inline static void finish_init_phys_kernel(); - - /** - * Configure this module appropriately for the first kernel run - */ - static void init_phys_kernel() - { - Board::prepare_kernel(); - Sctlr::write(Sctlr::init_phys_kernel()); - Psr::write(Psr::init_kernel()); - flush_tlb(); - finish_init_phys_kernel(); - } /** * Finish all previous data transfers @@ -181,6 +143,22 @@ class Genode::Arm_v7 : public Arm */ static void wait_for_interrupt() { asm volatile ("wfi"); } + /** + * Write back dirty lines of inner data cache and invalidate all + */ + void clean_invalidate_inner_data_cache(); + + /** + * Invalidate all lines of the inner data cache + */ + void invalidate_inner_data_cache(); + + /** + * Invalidate all lines of the instruction cache + */ + void invalidate_instruction_cache() { + asm volatile("mcr p15, 0, r0, c7, c5, 0"); } + /****************************** ** Trustzone specific API ** 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 a472fbf58..3054bd161 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 @@ -1,11 +1,12 @@ /* * \brief CPU driver for core * \author Martin stein + * \author Stefan Kalkowski * \date 2011-11-03 */ /* - * Copyright (C) 2011-2012 Genode Labs GmbH + * Copyright (C) 2011-2016 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. @@ -415,7 +416,7 @@ class Genode::Cpu : public Arm_v7 /** * Return kernel name of the executing CPU */ - static unsigned executing_id(); + static unsigned executing_id() { return Mpidr::Aff_0::get(Mpidr::read()); } /** * Return kernel name of the primary CPU @@ -429,16 +430,32 @@ class Genode::Cpu : public Arm_v7 */ static void init_virt_kernel(Kernel::Pd & pd); + /** + * Write back dirty cache lines and invalidate all cache lines + */ + void clean_invalidate_data_cache() { + clean_invalidate_inner_data_cache(); } + + /** + * Invalidate all cache lines + */ + void invalidate_data_cache() { + invalidate_inner_data_cache(); } + + void translation_table_insertions() { invalidate_branch_predicts(); } + + /** + * Hook function called at the very beginning + * of the local cpu initialization + */ + void init(); + /************* ** Dummies ** *************/ - static void tlb_insertions() { inval_branch_predicts(); } - static void translation_added(addr_t, size_t) { } static void prepare_proceeding(Cpu_lazy_state *, Cpu_lazy_state *) { } }; -void Genode::Arm_v7::finish_init_phys_kernel() { } - #endif /* _CPU_H_ */ diff --git a/repos/base-hw/src/core/include/spec/cortex_a8/cpu.h b/repos/base-hw/src/core/include/spec/cortex_a8/cpu.h index 046158a59..82e041436 100644 --- a/repos/base-hw/src/core/include/spec/cortex_a8/cpu.h +++ b/repos/base-hw/src/core/include/spec/cortex_a8/cpu.h @@ -1,11 +1,12 @@ /* - * \brief CPU driver for core + * \brief ARM Cortex A8 CPU driver for core * \author Martin stein + * \author Stefan Kalkowski * \date 2011-11-03 */ /* - * Copyright (C) 2011-2013 Genode Labs GmbH + * Copyright (C) 2011-2016 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. @@ -37,14 +38,21 @@ class Genode::Cpu : public Arm_v7 public: /** - * Ensure that TLB insertions get applied + * Write back dirty cache lines and invalidate the whole cache */ - static void tlb_insertions() { flush_tlb(); } + void clean_invalidate_data_cache() { + clean_invalidate_inner_data_cache(); } /** - * Return wether to retry an undefined user instruction after this call + * Invalidate all cache lines */ - bool retry_undefined_instr(Cpu_lazy_state *) { return false; } + void invalidate_data_cache() { + invalidate_inner_data_cache(); } + + /** + * Ensure that TLB insertions get applied + */ + void translation_table_insertions(); /** * Post processing after a translation was added to a translation table @@ -52,36 +60,7 @@ class Genode::Cpu : public Arm_v7 * \param addr virtual address of the translation * \param size size of the translation */ - static void translation_added(addr_t const addr, size_t const size) - { - /* - * The Cortex-A8 CPU can't use the L1 cache on page-table - * walks. Therefore, as the page-tables lie in write-back cacheable - * memory we've to clean the corresponding cache-lines even when a - * page table entry is added. We only do this as core as the kernel - * adds translations solely before MMU and caches are enabled. - */ - if (is_user()) Kernel::update_data_region(addr, size); - else flush_data_caches(); - } - - /** - * Return kernel name of the executing CPU - */ - static unsigned executing_id(); - - /** - * Return kernel name of the primary CPU - */ - static unsigned primary_id(); - - /************* - ** Dummies ** - *************/ - - static void prepare_proceeding(Cpu_lazy_state *, Cpu_lazy_state *) { } + static void translation_added(addr_t const addr, size_t const size); }; -void Genode::Arm_v7::finish_init_phys_kernel() { } - #endif /* _CPU_H_ */ diff --git a/repos/base-hw/src/core/include/spec/cortex_a9/board_support.h b/repos/base-hw/src/core/include/spec/cortex_a9/board_support.h index 891c14ad7..358788f8b 100644 --- a/repos/base-hw/src/core/include/spec/cortex_a9/board_support.h +++ b/repos/base-hw/src/core/include/spec/cortex_a9/board_support.h @@ -16,6 +16,7 @@ /* core includes */ #include +#include namespace Cortex_a9 { @@ -27,9 +28,27 @@ namespace Cortex_a9 class Cortex_a9::Board : public Genode::Board_base { + protected: + + using L2_cache = Arm::Pl310; + + L2_cache _l2_cache; + public: + enum Errata { + ARM_754322, + ARM_764369, + ARM_775420, + PL310_588369, + PL310_727915, + PL310_769419, + }; + enum { + /* snoop control unit */ + SCU_MMIO_BASE = CORTEX_A9_PRIVATE_MEM_BASE, + /* interrupt controller */ IRQ_CONTROLLER_DISTR_BASE = CORTEX_A9_PRIVATE_MEM_BASE + 0x1000, IRQ_CONTROLLER_DISTR_SIZE = 0x1000, @@ -41,6 +60,15 @@ class Cortex_a9::Board : public Genode::Board_base PRIVATE_TIMER_MMIO_SIZE = 0x10, PRIVATE_TIMER_IRQ = 29, }; + + Board() : _l2_cache(Genode::Board_base::PL310_MMIO_BASE) {} + + L2_cache & l2_cache() { return _l2_cache; } + + void init() { } + void wake_up_all_cpus(void * const ip); + bool is_smp() { return true; } + bool errata(Errata); }; #endif /* _SPEC__CORTEX_A9__BOARD_SUPPORT_H_ */ diff --git a/repos/base-hw/src/core/include/spec/cortex_a9/cpu.h b/repos/base-hw/src/core/include/spec/cortex_a9/cpu_support.h similarity index 82% rename from repos/base-hw/src/core/include/spec/cortex_a9/cpu.h rename to repos/base-hw/src/core/include/spec/cortex_a9/cpu_support.h index 97881e375..92a2ae462 100644 --- a/repos/base-hw/src/core/include/spec/cortex_a9/cpu.h +++ b/repos/base-hw/src/core/include/spec/cortex_a9/cpu_support.h @@ -1,18 +1,19 @@ /* * \brief CPU driver for core * \author Martin stein + * \author Stefan Kalkowski * \date 2011-11-03 */ /* - * Copyright (C) 2011-2013 Genode Labs GmbH + * Copyright (C) 2011-2016 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 _CPU_H_ -#define _CPU_H_ +#ifndef _SPEC__CORTEX_A9__CPU_SUPPORT_H_ +#define _SPEC__CORTEX_A9__CPU_SUPPORT_H_ /* core includes */ #include @@ -28,14 +29,14 @@ namespace Genode /** * CPU driver for core */ - class Cpu; + class Cortex_a9; } namespace Kernel { using Genode::Cpu_lazy_state; } class Genode::Cpu_lazy_state { - friend class Cpu; + friend class Cortex_a9; private: @@ -55,7 +56,7 @@ class Genode::Cpu_lazy_state inline Cpu_lazy_state(); }; -class Genode::Cpu : public Arm_v7 +class Genode::Cortex_a9 : public Arm_v7 { friend class Cpu_lazy_state; @@ -229,12 +230,19 @@ class Genode::Cpu : public Arm_v7 static void write(access_t const v) { asm volatile ("mcr p15, 0, %0, c1, c0, 1" :: "r" (v) : ); } + + static void enable_smp() + { + access_t v = read(); + Smp::set(v, 1); + write(v); + } }; /** * Constructor */ - Cpu() : _advanced_fp_simd_state(0) { } + Cortex_a9() : _advanced_fp_simd_state(0) { } /** * Initialize advanced FP/SIMD extension @@ -281,26 +289,47 @@ class Genode::Cpu : public Arm_v7 } /** - * Return kernel name of the executing CPU + * Write back dirty cache lines and invalidate whole data cache */ - static unsigned executing_id(); + void clean_invalidate_data_cache() + { + clean_invalidate_inner_data_cache(); + Kernel::board().l2_cache().clean_invalidate(); + } /** - * Return kernel name of the primary CPU + * Invalidate whole data cache */ - static unsigned primary_id(); + void invalidate_data_cache() + { + invalidate_inner_data_cache(); + Kernel::board().l2_cache().invalidate(); + } + + /** + * Clean and invalidate data-cache for virtual region + * 'base' - 'base + size' + */ + void clean_invalidate_data_cache_by_virt_region(addr_t base, + size_t const size) + { + Arm::clean_invalidate_data_cache_by_virt_region(base, size); + Kernel::board().l2_cache().clean_invalidate(); + } + + void translation_table_insertions() { invalidate_branch_predicts(); } + + static unsigned executing_id() { return Mpidr::Aff_0::get(Mpidr::read()); } + /************* ** Dummies ** *************/ static void translation_added(addr_t, size_t) { } - static void tlb_insertions() { inval_branch_predicts(); } }; -void Genode::Arm_v7::finish_init_phys_kernel() { Cpu::init_advanced_fp_simd(); } - -Genode::Cpu_lazy_state::Cpu_lazy_state() { fpexc = Cpu::Fpexc::En::bits(1); } +Genode::Cpu_lazy_state::Cpu_lazy_state() { fpexc = Cortex_a9::Fpexc::En::bits(1); } /* * Annotation 1 @@ -322,4 +351,4 @@ Genode::Cpu_lazy_state::Cpu_lazy_state() { fpexc = Cpu::Fpexc::En::bits(1); } * head branch as from 2014.04.17. */ -#endif /* _CPU_H_ */ +#endif /* _SPEC__CORTEX_A9__CPU_SUPPORT_H_ */ diff --git a/repos/base-hw/src/core/include/spec/cortex_a9/scu.h b/repos/base-hw/src/core/include/spec/cortex_a9/scu.h new file mode 100644 index 000000000..9d699f599 --- /dev/null +++ b/repos/base-hw/src/core/include/spec/cortex_a9/scu.h @@ -0,0 +1,71 @@ +/* + * \brief Snoop control unit + * \author Martin Stein + * \author Stefan Kalkowski + * \date 2015-12-15 + */ + +/* + * Copyright (C) 2015-2016 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 + +/* local includes */ +#include + +namespace Genode { + class Scu; +} + +class Genode::Scu : Genode::Mmio +{ + private: + + struct Cr : Register<0x0, 32> + { + struct Enable : Bitfield<0, 1> { }; + }; + + struct Dcr : Register<0x30, 32> + { + struct Bit_0 : Bitfield<0, 1> { }; + }; + + struct Iassr : Register<0xc, 32> + { + struct Cpu0_way : Bitfield<0, 4> { }; + struct Cpu1_way : Bitfield<4, 4> { }; + struct Cpu2_way : Bitfield<8, 4> { }; + struct Cpu3_way : Bitfield<12, 4> { }; + }; + + Board &_board; + + public: + + Scu(Board & board) : Mmio(Board::SCU_MMIO_BASE), _board(board) { } + + void invalidate() + { + Iassr::access_t iassr = 0; + for (Iassr::access_t way = 0; way <= Iassr::Cpu0_way::mask(); + way++) { + Iassr::Cpu0_way::set(iassr, way); + Iassr::Cpu1_way::set(iassr, way); + Iassr::Cpu2_way::set(iassr, way); + Iassr::Cpu3_way::set(iassr, way); + write(iassr); + } + } + + void enable() + { + if (_board.errata(Board::ARM_764369)) write(1); + write(Cr::Enable::bits(1)); + } +}; 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 266d76070..3f00b32a0 100644 --- a/repos/base-hw/src/core/include/spec/exynos5/board.h +++ b/repos/base-hw/src/core/include/spec/exynos5/board.h @@ -1,11 +1,12 @@ /* * \brief Board driver for core * \author Martin Stein + * \author Stefan Kalkowski * \date 2012-04-23 */ /* - * Copyright (C) 2012-2013 Genode Labs GmbH + * Copyright (C) 2012-2016 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. @@ -23,15 +24,17 @@ namespace Genode { public: - static void outer_cache_invalidate() { } - static void outer_cache_flush() { } - static void prepare_kernel(); + static void init() { } /** * Tell secondary CPUs to start execution from instr. pointer 'ip' */ - static void secondary_cpus_ip(void * const ip) { - *(void * volatile *)IRAM_BASE = ip; } + static void wake_up_all_cpus(void * const ip) + { + *(void * volatile *)IRAM_BASE = ip; + asm volatile("dsb\n" + "sev\n"); + } static bool is_smp() { return true; } }; diff --git a/repos/base-hw/src/core/include/spec/imx/board_support.h b/repos/base-hw/src/core/include/spec/imx/board_support.h index b21b250bc..5c2ddfc75 100644 --- a/repos/base-hw/src/core/include/spec/imx/board_support.h +++ b/repos/base-hw/src/core/include/spec/imx/board_support.h @@ -37,45 +37,44 @@ namespace Imx class Imx::Aipstz : public Genode::Mmio { - /* - * Configuration of the masters - */ + private: - struct Mpr { enum { ALL_UNBUFFERED_AND_FULLY_TRUSTED = 0x77777777 }; }; - struct Mpr1 : Register<0x0, 32>, Mpr { }; - struct Mpr2 : Register<0x4, 32>, Mpr { }; + /* + * Configuration of the masters + */ - /* - * Configuration of the platform peripherals - */ + struct Mpr { enum { ALL_UNBUFFERED_AND_FULLY_TRUSTED = 0x77777777 }; }; + struct Mpr1 : Register<0x0, 32>, Mpr { }; + struct Mpr2 : Register<0x4, 32>, Mpr { }; - struct Pacr { enum { ALL_UNBUFFERED_AND_FULLY_UNPROTECTED = 0 }; }; - struct Pacr1 : Register<0x20, 32>, Pacr { }; - struct Pacr2 : Register<0x24, 32>, Pacr { }; - struct Pacr3 : Register<0x28, 32>, Pacr { }; - struct Pacr4 : Register<0x2c, 32>, Pacr { }; + /* + * Configuration of the platform peripherals + */ - /* - * Configuration of the off-platform peripherals - */ + struct Pacr { enum { ALL_UNBUFFERED_AND_FULLY_UNPROTECTED = 0 }; }; + struct Pacr1 : Register<0x20, 32>, Pacr { }; + struct Pacr2 : Register<0x24, 32>, Pacr { }; + struct Pacr3 : Register<0x28, 32>, Pacr { }; + struct Pacr4 : Register<0x2c, 32>, Pacr { }; - struct Opacr1 : Register<0x40, 32>, Pacr { }; - struct Opacr2 : Register<0x44, 32>, Pacr { }; - struct Opacr3 : Register<0x48, 32>, Pacr { }; - struct Opacr4 : Register<0x4c, 32>, Pacr { }; - struct Opacr5 : Register<0x50, 32>, Pacr { }; + /* + * Configuration of the off-platform peripherals + */ + + struct Opacr1 : Register<0x40, 32>, Pacr { }; + struct Opacr2 : Register<0x44, 32>, Pacr { }; + struct Opacr3 : Register<0x48, 32>, Pacr { }; + struct Opacr4 : Register<0x4c, 32>, Pacr { }; + struct Opacr5 : Register<0x50, 32>, Pacr { }; public: - /** - * Constructor - */ Aipstz(Genode::addr_t const base) : Genode::Mmio(base) { } /** * Configure this module appropriately for the first kernel run */ - void prepare_kernel() + void init() { /* avoid AIPS intervention at any memory access */ write(Mpr::ALL_UNBUFFERED_AND_FULLY_TRUSTED); @@ -94,45 +93,18 @@ class Imx::Aipstz : public Genode::Mmio class Imx::Board : public Genode::Board_base { - /* - * static AIPSTZ instances - */ - - static Aipstz * _aipstz_1() - { - static Aipstz a(AIPS_1_MMIO_BASE); - return &a; - } - - static Aipstz * _aipstz_2() - { - static Aipstz a(AIPS_2_MMIO_BASE); - return &a; - } - public: /** * Configure this module appropriately for the first kernel run */ - static void prepare_kernel() + void init() { - _aipstz_1()->prepare_kernel(); - _aipstz_2()->prepare_kernel(); + Aipstz _aipstz_1(AIPS_1_MMIO_BASE); + Aipstz _aipstz_2(AIPS_2_MMIO_BASE); + _aipstz_1.init(); + _aipstz_2.init(); } - - /** - * Return wether the board has SMP extensions - */ - static bool is_smp(); - - /* - * Dummies - */ - - static void outer_cache_invalidate() { } - static void outer_cache_flush() { } - static void secondary_cpus_ip(void *) { } }; #endif /* _SPEC__IMX__BOARD_SUPPORT_H_ */ diff --git a/repos/base-hw/src/core/include/spec/imx53/board.h b/repos/base-hw/src/core/include/spec/imx53/board.h index ae2760b47..52344e0c7 100644 --- a/repos/base-hw/src/core/include/spec/imx53/board.h +++ b/repos/base-hw/src/core/include/spec/imx53/board.h @@ -23,7 +23,12 @@ namespace Genode /** * Board driver */ - class Board : public Imx::Board { }; + class Board : public Imx::Board + { + public: + + bool is_smp() { return false; } + }; } #endif /* _BOARD_H_ */ diff --git a/repos/base-hw/src/core/include/spec/imx6/board.h b/repos/base-hw/src/core/include/spec/imx6/board.h index 48f22a3fb..81217e6ed 100644 --- a/repos/base-hw/src/core/include/spec/imx6/board.h +++ b/repos/base-hw/src/core/include/spec/imx6/board.h @@ -24,7 +24,16 @@ namespace Genode /** * Board driver */ - class Board : public Imx::Board, public Cortex_a9::Board { }; + class Board : public Imx::Board, public Cortex_a9::Board + { + public: + + void init() + { + Imx::Board::init(); + Cortex_a9::Board::init(); + } + }; } #endif /* _BOARD_H_ */ diff --git a/repos/base-hw/src/core/include/spec/imx6/cpu.h b/repos/base-hw/src/core/include/spec/imx6/cpu.h new file mode 100644 index 000000000..d9f174bfc --- /dev/null +++ b/repos/base-hw/src/core/include/spec/imx6/cpu.h @@ -0,0 +1,26 @@ +/* + * \brief CPU driver for core + * \author Stefan Kalkowski + * \date 2015-12-15 + */ + +/* + * 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. + */ + +#ifndef _CPU_H_ +#define _CPU_H_ + +/* core includes */ +#include + +namespace Genode +{ + using Cpu = Genode::Cortex_a9; +} + +#endif /* _CPU_H_ */ + diff --git a/repos/base-hw/src/core/include/spec/panda/board.h b/repos/base-hw/src/core/include/spec/panda/board.h index fc9778bd8..6443f493d 100644 --- a/repos/base-hw/src/core/include/spec/panda/board.h +++ b/repos/base-hw/src/core/include/spec/panda/board.h @@ -16,77 +16,14 @@ #define _BOARD_H_ /* core includes */ -#include #include +#include namespace Genode { - class L2_cache; class Board; } -/** - * L2 outer cache controller - */ -class Genode::L2_cache -{ - private: - - struct Secure_monitor - { - enum Syscalls - { - L2_CACHE_SET_DEBUG_REG = 0x100, - L2_CACHE_ENABLE_REG = 0x102, - L2_CACHE_AUX_REG = 0x109, - }; - - void call(addr_t func, addr_t val) - { - register addr_t _func asm("r12") = func; - register addr_t _val asm("r0") = val; - asm volatile( - "dsb; smc #0" :: - "r" (_func), "r" (_val) : - "memory", "cc", "r1", "r2", "r3", "r4", "r5", "r6", "r7", - "r8", "r9", "r10", "r11"); - } - } _secure_monitor; - - Arm::Pl310 _pl310; - - public: - - L2_cache() : _pl310(Cortex_a9::Board::PL310_MMIO_BASE) - { - Arm::Pl310::Aux::access_t v = 0; - Arm::Pl310::Aux::Associativity::set(v, 1); - Arm::Pl310::Aux::Way_size::set(v, 3); - Arm::Pl310::Aux::Share_override::set(v, 1); - Arm::Pl310::Aux::Reserved::set(v, 1); - Arm::Pl310::Aux::Ns_lockdown::set(v, 1); - Arm::Pl310::Aux::Ns_irq_ctrl::set(v, 1); - Arm::Pl310::Aux::Data_prefetch::set(v, 1); - Arm::Pl310::Aux::Inst_prefetch::set(v, 1); - Arm::Pl310::Aux::Early_bresp::set(v, 1); - - _secure_monitor.call(Secure_monitor::L2_CACHE_AUX_REG, v); - _secure_monitor.call(Secure_monitor::L2_CACHE_ENABLE_REG, 1); - _pl310.mask_interrupts(); - } - - void flush() - { - Arm::Pl310::Debug::access_t v = 0; - Arm::Pl310::Debug::Dwb::set(v, 1); - Arm::Pl310::Debug::Dcl::set(v, 1); - _secure_monitor.call(Secure_monitor::L2_CACHE_SET_DEBUG_REG, v); - _pl310.flush(); - _secure_monitor.call(Secure_monitor::L2_CACHE_SET_DEBUG_REG, 0); - } - - void invalidate() { _pl310.invalidate(); } -}; /** * Board driver for core @@ -95,11 +32,103 @@ class Genode::Board : public Cortex_a9::Board { public: - static void outer_cache_invalidate(); - static void outer_cache_flush(); - static void prepare_kernel(); - static void secondary_cpus_ip(void * const ip) { } - static bool is_smp() { return true; } + using Base = Cortex_a9::Board; + + /** + * Frontend to monitor firmware running in the secure world + */ + struct Secure_monitor + { + enum Syscalls + { + CPU_ACTLR_SMP_BIT_RAISE = 0x25, + L2_CACHE_SET_DEBUG_REG = 0x100, + L2_CACHE_ENABLE_REG = 0x102, + L2_CACHE_AUX_REG = 0x109, + }; + + void call(addr_t func, addr_t val) + { + register addr_t _func asm("r12") = func; + register addr_t _val asm("r0") = val; + asm volatile("dsb; smc #0" :: + "r" (_func), "r" (_val) : + "memory", "cc", "r1", "r2", "r3", "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "r11"); + } + }; + + + class L2_cache : public Base::L2_cache + { + private: + + Secure_monitor & _monitor; + + unsigned long _init_value() + { + Aux::access_t v = 0; + Aux::Associativity::set(v, 1); + Aux::Way_size::set(v, 3); + Aux::Share_override::set(v, 1); + Aux::Reserved::set(v, 1); + Aux::Ns_lockdown::set(v, 1); + Aux::Ns_irq_ctrl::set(v, 1); + Aux::Data_prefetch::set(v, 1); + Aux::Inst_prefetch::set(v, 1); + Aux::Early_bresp::set(v, 1); + return v; + } + + unsigned long _debug_value() + { + Debug::access_t v = 0; + Debug::Dwb::set(v, 1); + Debug::Dcl::set(v, 1); + return v; + } + + public: + + L2_cache(Secure_monitor & monitor) + : Base::L2_cache(Genode::Board_base::PL310_MMIO_BASE), + _monitor(monitor) + { + _monitor.call(Secure_monitor::L2_CACHE_AUX_REG, + _init_value()); + } + + void clean_invalidate() + { + _monitor.call(Secure_monitor::L2_CACHE_SET_DEBUG_REG, + _debug_value()); + Base::L2_cache::clean_invalidate(); + _monitor.call(Secure_monitor::L2_CACHE_SET_DEBUG_REG, 0); + } + + void invalidate() { Base::L2_cache::invalidate(); } + + void enable() + { + _monitor.call(Secure_monitor::L2_CACHE_ENABLE_REG, 1); + Base::L2_cache::mask_interrupts(); + } + + void disable() { + _monitor.call(Secure_monitor::L2_CACHE_ENABLE_REG, 0); } + }; + + private: + + Secure_monitor _monitor; + L2_cache _l2_cache; + + public: + + Board() : _l2_cache(_monitor) { _l2_cache.disable(); } + + L2_cache & l2_cache() { return _l2_cache; } + Secure_monitor & monitor() { return _monitor; } }; #endif /* _BOARD_H_ */ diff --git a/repos/base-hw/src/core/include/spec/panda/cortex_a9_wugen.h b/repos/base-hw/src/core/include/spec/panda/cortex_a9_wugen.h index b231867fc..f7d020f26 100644 --- a/repos/base-hw/src/core/include/spec/panda/cortex_a9_wugen.h +++ b/repos/base-hw/src/core/include/spec/panda/cortex_a9_wugen.h @@ -14,9 +14,6 @@ #ifndef CORTEX_A9_WUGEN_H #define CORTEX_A9_WUGEN_H -/* base includes */ -#include - /* Genode includes */ #include @@ -27,8 +24,6 @@ namespace Genode { class Cortex_a9_wugen; } */ class Genode::Cortex_a9_wugen : Mmio { - friend Unmanaged_singleton_constructor; - private: struct Aux_core_boot_0 : Register<0x800, 32> { @@ -36,12 +31,9 @@ class Genode::Cortex_a9_wugen : Mmio struct Aux_core_boot_1 : Register<0x804, 32> { }; - Cortex_a9_wugen() : Mmio(Board_base::CORTEX_A9_WUGEN_MMIO_BASE) { } - public: - static Cortex_a9_wugen * singleton() { - return unmanaged_singleton(); } + Cortex_a9_wugen() : Mmio(Board_base::CORTEX_A9_WUGEN_MMIO_BASE) { } /** * Start CPU 1 with instruction pointer 'ip' diff --git a/repos/base-hw/src/core/include/spec/panda/cpu.h b/repos/base-hw/src/core/include/spec/panda/cpu.h new file mode 100644 index 000000000..91003f7d6 --- /dev/null +++ b/repos/base-hw/src/core/include/spec/panda/cpu.h @@ -0,0 +1,41 @@ +/* + * \brief CPU driver for core + * \author Stefan Kalkowski + * \date 2015-12-15 + */ + +/* + * Copyright (C) 2015-2016 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 _CPU_H_ +#define _CPU_H_ + +/* core includes */ +#include + +namespace Genode +{ + class Cpu; +} + + +/** + * Override the Cortex A9 Cpu driver, because some registers can be accessed + * via the firmware running in TrustZone's secure world only + */ +class Genode::Cpu : public Genode::Cortex_a9 +{ + public: + + struct Actlr : Cortex_a9::Actlr + { + static void enable_smp(); + }; +}; + +#endif /* _CPU_H_ */ + diff --git a/repos/base-hw/src/core/include/spec/pbxa9/board.h b/repos/base-hw/src/core/include/spec/pbxa9/board.h index c8a730eed..8dc3c0aa4 100644 --- a/repos/base-hw/src/core/include/spec/pbxa9/board.h +++ b/repos/base-hw/src/core/include/spec/pbxa9/board.h @@ -19,16 +19,7 @@ namespace Genode { - class Board : public Cortex_a9::Board - { - public: - - static void outer_cache_invalidate() { } - static void outer_cache_flush() { } - static void prepare_kernel() { } - static void secondary_cpus_ip(void * const ip) { } - static bool is_smp() { return false; } - }; + using Board = Cortex_a9::Board; } #endif /* _SPEC__PBXA9__BOARD_H_ */ diff --git a/repos/base-hw/src/core/spec/exynos5/board.cc b/repos/base-hw/src/core/include/spec/pbxa9/cpu.h similarity index 55% rename from repos/base-hw/src/core/spec/exynos5/board.cc rename to repos/base-hw/src/core/include/spec/pbxa9/cpu.h index 3f2893804..9628f983b 100644 --- a/repos/base-hw/src/core/spec/exynos5/board.cc +++ b/repos/base-hw/src/core/include/spec/pbxa9/cpu.h @@ -1,7 +1,7 @@ /* - * \brief Board-specific code for Exynos5 boards + * \brief CPU driver for core * \author Stefan Kalkowski - * \date 2015-02-09 + * \date 2015-12-15 */ /* @@ -11,7 +11,15 @@ * under the terms of the GNU General Public License version 2. */ -/* core includes */ -#include +#ifndef _CPU_H_ +#define _CPU_H_ -void Genode::Board::prepare_kernel() { } +/* core includes */ +#include + +namespace Genode +{ + using Cpu = Cortex_a9; +} + +#endif /* _CPU_H_ */ diff --git a/repos/base-hw/src/core/include/board.h b/repos/base-hw/src/core/include/spec/rpi/board.h similarity index 67% rename from repos/base-hw/src/core/include/board.h rename to repos/base-hw/src/core/include/spec/rpi/board.h index 0ab23d9ff..5e4f378ba 100644 --- a/repos/base-hw/src/core/include/board.h +++ b/repos/base-hw/src/core/include/spec/rpi/board.h @@ -1,11 +1,12 @@ /* * \brief Board driver for core * \author Martin Stein + * \author Stefan Kalkowski * \date 2012-04-23 */ /* - * Copyright (C) 2012-2013 Genode Labs GmbH + * Copyright (C) 2012-2016 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. @@ -23,10 +24,8 @@ namespace Genode { public: - static void outer_cache_invalidate() { } - static void outer_cache_flush() { } - static void prepare_kernel() { } - static void secondary_cpus_ip(void * const ip) { } + void init() { } + static bool is_smp() { return false; } }; } diff --git a/repos/base-hw/src/core/include/spec/rpi/pic.h b/repos/base-hw/src/core/include/spec/rpi/pic.h index ea17080de..dfec6b46c 100644 --- a/repos/base-hw/src/core/include/spec/rpi/pic.h +++ b/repos/base-hw/src/core/include/spec/rpi/pic.h @@ -136,12 +136,13 @@ class Genode::Pic : Mmio public: enum { - /* - * FIXME: dummy ipi value on non-SMP platform, should be removed - * when SMP is an aspect of CPUs only compiled where necessary - */ - IPI = 63, NR_OF_IRQ = 64, + + /* + * dummy IPI value on non-SMP platform, + * only used in interrupt reservation within generic code + */ + IPI, }; private: @@ -241,13 +242,6 @@ class Genode::Pic : Mmio else write(1 << (i - 8 - 32)); } - - /* - * Dummies - */ - - bool is_ip_interrupt(unsigned) { return false; } - void trigger_ip_interrupt(unsigned) { } }; namespace Kernel { class Pic : public Genode::Pic { }; } diff --git a/repos/base-hw/src/core/include/spec/x86/board.h b/repos/base-hw/src/core/include/spec/x86/board.h index 9fd54d8cd..bc2926b09 100644 --- a/repos/base-hw/src/core/include/spec/x86/board.h +++ b/repos/base-hw/src/core/include/spec/x86/board.h @@ -29,6 +29,8 @@ namespace Genode TIMER_VECTOR_USER = 50, ISA_IRQ_END = 15, }; + + void init() { } }; } diff --git a/repos/base-hw/src/core/include/spec/x86/cpu_support.h b/repos/base-hw/src/core/include/spec/x86/cpu_support.h index b1a9c118e..92979d5fd 100644 --- a/repos/base-hw/src/core/include/spec/x86/cpu_support.h +++ b/repos/base-hw/src/core/include/spec/x86/cpu_support.h @@ -364,23 +364,6 @@ class Genode::Cpu _disable_fpu(); } - - - /********************************************* - ** Dummy implementations not needed on x86 ** - *********************************************/ - - static void tlb_insertions() { } - static void translation_added(addr_t, size_t) { } - static void flush_data_caches() { } - static void flush_caches() { } - static void flush_tlb_by_pid(unsigned const pid) { } - static void flush_data_caches_by_virt_region(addr_t base, - size_t const size) { } - static void invalidate_instr_caches() { } - static void invalidate_data_caches() { } - static void invalidate_instr_caches_by_virt_region(addr_t base, - size_t const size) {} }; struct Genode::Cpu::Cr0 : Register<64> diff --git a/repos/base-hw/src/core/include/spec/zynq/board.h b/repos/base-hw/src/core/include/spec/zynq/board.h index 2d4aa6fa3..9b615430b 100644 --- a/repos/base-hw/src/core/include/spec/zynq/board.h +++ b/repos/base-hw/src/core/include/spec/zynq/board.h @@ -18,36 +18,10 @@ /* core includes */ #include -#include namespace Genode { - class Pl310; - class Board; + using Board = Cortex_a9::Board; } -/** - * L2 outer cache controller - */ -class Genode::Pl310 : public Arm::Pl310 -{ - public: - - Pl310(addr_t const base) : Arm::Pl310(base) { mask_interrupts(); } -}; - -/** - * Board driver for core - */ -class Genode::Board : public Cortex_a9::Board -{ - public: - - static void outer_cache_invalidate(); - static void outer_cache_flush(); - static void prepare_kernel(); - static void secondary_cpus_ip(void * const ip) { } - static bool is_smp() { return true; } -}; - #endif /* _BOARD_H_ */ diff --git a/repos/base-hw/src/core/include/spec/zynq/cpu.h b/repos/base-hw/src/core/include/spec/zynq/cpu.h new file mode 100644 index 000000000..ac5b4279e --- /dev/null +++ b/repos/base-hw/src/core/include/spec/zynq/cpu.h @@ -0,0 +1,25 @@ +/* + * \brief CPU driver for core + * \author Stefan Kalkowski + * \date 2015-12-15 + */ + +/* + * Copyright (C) 2015-2016 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 _CPU_H_ +#define _CPU_H_ + +/* core includes */ +#include + +namespace Genode +{ + using Cpu = Genode::Cortex_a9; +} + +#endif /* _CPU_H_ */ diff --git a/repos/base-hw/src/core/kernel/cpu.cc b/repos/base-hw/src/core/kernel/cpu.cc index c9da9f98f..f94f67c8f 100644 --- a/repos/base-hw/src/core/kernel/cpu.cc +++ b/repos/base-hw/src/core/kernel/cpu.cc @@ -6,7 +6,7 @@ */ /* - * Copyright (C) 2014 Genode Labs GmbH + * Copyright (C) 2014-2016 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. @@ -29,38 +29,9 @@ using namespace Kernel; namespace Kernel { - /** - * Lists all pending domain updates - */ - class Cpu_domain_update_list; - - Timer * timer(); - Cpu_pool * cpu_pool() { return unmanaged_singleton(); } } -class Kernel::Cpu_domain_update_list -: public Double_list_typed -{ - typedef Cpu_domain_update Update; - - public: - - /** - * Perform all pending domain updates on the executing CPU - */ - void do_each() { for_each([] (Update * const u) { u->_do(); }); } -}; - -namespace Kernel -{ - /** - * Return singleton of the CPU domain-udpate list - */ - Cpu_domain_update_list * cpu_domain_update_list() { - return unmanaged_singleton(); } -} - /************* ** Cpu_job ** @@ -149,25 +120,6 @@ void Cpu::schedule(Job * const job) } -void Cpu::Ipi::occurred() -{ - cpu_domain_update_list()->do_each(); - pending = false; -} - - -void Cpu::Ipi::trigger(unsigned const cpu_id) -{ - if (pending) return; - - pic()->trigger_ip_interrupt(cpu_id); - pending = true; -} - - -Cpu::Ipi::Ipi(Irq::Pool &p) : Irq(Pic::IPI, p) { } - - bool Cpu::interrupt(unsigned const irq_id) { Irq * const irq = object(irq_id); @@ -211,56 +163,6 @@ Cpu::Cpu(unsigned const id, Timer * const timer) _timer_irq(_timer->interrupt_id(_id), *this) { } -/*********************** - ** Cpu_domain_update ** - ***********************/ - -void Cpu_domain_update::_do() -{ - /* perform domain update locally and get pending bit */ - unsigned const id = Cpu::executing_id(); - if (!_pending[id]) { return; } - _domain_update(); - _pending[id] = false; - - /* check wether there are still CPUs pending */ - unsigned i = 0; - for (; i < NR_OF_CPUS && !_pending[i]; i++) { } - if (i < NR_OF_CPUS) { return; } - - /* as no CPU is pending anymore, end the domain update */ - cpu_domain_update_list()->remove(this); - _cpu_domain_update_unblocks(); -} - - -bool Cpu_domain_update::_do_global(unsigned const domain_id) -{ - /* perform locally and leave it at that if in uniprocessor mode */ - _domain_id = domain_id; - _domain_update(); - if (NR_OF_CPUS == 1) { return false; } - - /* inform other CPUs and block until they are done */ - cpu_domain_update_list()->insert_tail(this); - unsigned const cpu_id = Cpu::executing_id(); - for (unsigned i = 0; i < NR_OF_CPUS; i++) { - if (i == cpu_id) { continue; } - _pending[i] = true; - cpu_pool()->cpu(i)->trigger_ip_interrupt(); - } - return true; -} - - -void Cpu_domain_update::_domain_update() { - Genode::Cpu::flush_tlb_by_pid(_domain_id); } - - -Cpu_domain_update::Cpu_domain_update() { - for (unsigned i = 0; i < NR_OF_CPUS; i++) { _pending[i] = false; } } - - /************** ** Cpu_pool ** **************/ @@ -280,6 +182,14 @@ Cpu_pool::Cpu_pool() } +/*********************** + ** Cpu_domain_update ** + ***********************/ + +Cpu_domain_update::Cpu_domain_update() { + for (unsigned i = 0; i < NR_OF_CPUS; i++) { _pending[i] = false; } } + + /***************** ** Cpu_context ** *****************/ diff --git a/repos/base-hw/src/core/kernel/init.cc b/repos/base-hw/src/core/kernel/init.cc index 3871335f1..5c0cd89e0 100644 --- a/repos/base-hw/src/core/kernel/init.cc +++ b/repos/base-hw/src/core/kernel/init.cc @@ -2,11 +2,11 @@ * \brief Common kernel initialization * \author Martin Stein * \author Stefan Kalkowski - * \date 2011-10-20 + * \date 2015-12-20 */ /* - * Copyright (C) 2011-2015 Genode Labs GmbH + * Copyright (C) 2015-2016 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. @@ -18,6 +18,7 @@ #include #include #include +#include #include /* base includes */ @@ -35,6 +36,9 @@ Pd * Kernel::core_pd() { Pic * Kernel::pic() { return unmanaged_singleton(); } +Genode::Board & Kernel::board() { + return *unmanaged_singleton(); } + /** * Setup kernel environment @@ -47,17 +51,13 @@ extern "C" void init_kernel() * local static objects. */ - /* calculate in advance as needed later when data writes aren't allowed */ - core_pd(); + board().init(); /* initialize cpu pool */ cpu_pool(); - /* initialize PIC */ - pic(); - /* initialize current cpu */ - cpu_pool()->cpu(Cpu::executing_id())->init(*pic(), *core_pd()); + cpu_pool()->cpu(Cpu::executing_id())->init(*pic(), *core_pd(), board()); Core_thread::singleton(); diff --git a/repos/base-hw/src/core/kernel/kernel.cc b/repos/base-hw/src/core/kernel/kernel.cc index 67058103f..5fafb9941 100644 --- a/repos/base-hw/src/core/kernel/kernel.cc +++ b/repos/base-hw/src/core/kernel/kernel.cc @@ -1,5 +1,5 @@ /* - * \brief Kernel entrypoint + * \brief Kernel entrypoint for non-SMP systems * \author Martin Stein * \author Stefan Kalkowski * \date 2011-10-20 @@ -20,7 +20,16 @@ extern "C" void kernel() { using namespace Kernel; - Cpu * const cpu = cpu_pool()->cpu(Cpu::executing_id()); + Cpu * const cpu = cpu_pool()->cpu(Cpu::executing_id()); cpu->scheduled_job().exception(cpu->id()); cpu->schedule().proceed(cpu->id()); } + + +void Kernel::Cpu::Ipi::occurred() { } + + +void Kernel::Cpu::Ipi::trigger(unsigned const cpu_id) { } + + +Kernel::Cpu::Ipi::Ipi(Kernel::Irq::Pool &p) : Kernel::Irq(Kernel::Pic::IPI, p) { } diff --git a/repos/base-hw/src/core/kernel/thread.cc b/repos/base-hw/src/core/kernel/thread.cc index 5bb5e303c..4f4063517 100644 --- a/repos/base-hw/src/core/kernel/thread.cc +++ b/repos/base-hw/src/core/kernel/thread.cc @@ -269,13 +269,6 @@ void Thread::_call_resume_local_thread() } -void Thread_event::_signal_acknowledged() -{ - Cpu::tlb_insertions(); - _thread->_resume(); -} - - Thread_event::Thread_event(Thread * const t) : _thread(t), _signal_context(0) { } @@ -362,51 +355,6 @@ Signal_context * const Thread_event::signal_context() const { return _signal_context; } -void Thread::_call_update_data_region() -{ - /* - * FIXME: If the caller is not a core thread, the kernel operates in a - * different address space than the caller. Combined with the fact - * that at least ARMv7 doesn't provide cache operations by physical - * address, this prevents us from selectively maintaining caches. - * The future solution will be a kernel that is mapped to every - * address space so we can use virtual addresses of the caller. Up - * until then we apply operations to caches as a whole instead. - */ - if (!_core()) { - Cpu::flush_data_caches(); - return; - } - auto base = (addr_t)user_arg_1(); - auto const size = (size_t)user_arg_2(); - Cpu::flush_data_caches_by_virt_region(base, size); - Cpu::invalidate_instr_caches(); -} - - -void Thread::_call_update_instr_region() -{ - /* - * FIXME: If the caller is not a core thread, the kernel operates in a - * different address space than the caller. Combined with the fact - * that at least ARMv7 doesn't provide cache operations by physical - * address, this prevents us from selectively maintaining caches. - * The future solution will be a kernel that is mapped to every - * address space so we can use virtual addresses of the caller. Up - * until then we apply operations to caches as a whole instead. - */ - if (!_core()) { - Cpu::flush_data_caches(); - Cpu::invalidate_instr_caches(); - return; - } - auto base = (addr_t)user_arg_1(); - auto const size = (size_t)user_arg_2(); - Cpu::flush_data_caches_by_virt_region(base, size); - Cpu::invalidate_instr_caches_by_virt_region(base, size); -} - - void Thread::_print_activity(bool const printing_thread) { Genode::printf("\033[33m%s -> %s:\033[0m", pd_label(), label()); diff --git a/repos/base-hw/src/core/spec/arm/cpu.cc b/repos/base-hw/src/core/spec/arm/cpu.cc deleted file mode 100644 index 8bfa89a8f..000000000 --- a/repos/base-hw/src/core/spec/arm/cpu.cc +++ /dev/null @@ -1,22 +0,0 @@ -/* - * \brief CPU driver for core - * \author Martin stein - * \date 2014-07-14 - */ - -/* - * Copyright (C) 2011-2014 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; - -unsigned Cpu::primary_id() { return 0; } - - -unsigned Cpu::executing_id() { return primary_id(); } diff --git a/repos/base-hw/src/core/spec/arm/kernel/cpu.cc b/repos/base-hw/src/core/spec/arm/kernel/cpu.cc index c4f678690..ea030ee9e 100644 --- a/repos/base-hw/src/core/spec/arm/kernel/cpu.cc +++ b/repos/base-hw/src/core/spec/arm/kernel/cpu.cc @@ -1,12 +1,12 @@ /* - * \brief Class for kernel data that is needed to manage a specific CPU + * \brief Kernel cpu driver implementations specific to ARM * \author Martin Stein * \author Stefan Kalkowski * \date 2014-01-14 */ /* - * Copyright (C) 2014 Genode Labs GmbH + * Copyright (C) 2014-2016 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. @@ -19,33 +19,31 @@ #include #include -void Kernel::Cpu::init(Kernel::Pic &pic, Kernel::Pd & core_pd) +void Kernel::Cpu::init(Kernel::Pic &pic, Kernel::Pd & core_pd, + Genode::Board & board) { - /* locally initialize interrupt controller */ - pic.init_cpu_local(); - - /* initialize CPU in physical mode */ - Cpu::init_phys_kernel(); + Sctlr::init(); /* switch to core address space */ - Cpu::init_virt_kernel(core_pd); + Cpu::enable_mmu_and_caches(core_pd); /* * TrustZone initialization code - * - * FIXME This is a plattform specific feature */ init_trustzone(pic); /* * Enable performance counter - * - * FIXME This is an optional CPU specific feature */ perf_counter()->enable(); + /* locally initialize interrupt controller */ + pic.init_cpu_local(); + /* enable timer interrupt */ - unsigned const cpu = Cpu::executing_id(); - pic.unmask(Timer::interrupt_id(cpu), cpu); + pic.unmask(Timer::interrupt_id(id()), id()); } + +void Kernel::Cpu_domain_update::_domain_update() { + cpu_pool()->cpu(Cpu::executing_id())->invalidate_tlb_by_pid(_domain_id); } diff --git a/repos/base-hw/src/core/spec/arm/kernel/pd.cc b/repos/base-hw/src/core/spec/arm/kernel/pd.cc index d851ed59e..c392f560f 100644 --- a/repos/base-hw/src/core/spec/arm/kernel/pd.cc +++ b/repos/base-hw/src/core/spec/arm/kernel/pd.cc @@ -40,7 +40,10 @@ Kernel::Pd::~Pd() { oir->~Object_identity_reference(); /* clean up buffers of memory management */ - Cpu::flush_tlb_by_pid(asid); + Cpu * const cpu = cpu_pool()->cpu(Cpu::executing_id()); + cpu->clean_invalidate_data_cache(); + cpu->invalidate_instr_cache(); + cpu->invalidate_tlb_by_pid(asid); alloc().free(asid); } diff --git a/repos/base-hw/src/core/spec/arm/kernel/thread.cc b/repos/base-hw/src/core/spec/arm/kernel/thread.cc index bf1a36c2d..a11c5d787 100644 --- a/repos/base-hw/src/core/spec/arm/kernel/thread.cc +++ b/repos/base-hw/src/core/spec/arm/kernel/thread.cc @@ -6,7 +6,7 @@ */ /* - * Copyright (C) 2013 Genode Labs GmbH + * Copyright (C) 2013-2016 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. @@ -30,14 +30,10 @@ void Thread::exception(unsigned const cpu) _call(); return; case PREFETCH_ABORT: - _mmu_exception(); - return; case DATA_ABORT: _mmu_exception(); return; case INTERRUPT_REQUEST: - _interrupt(cpu); - return; case FAST_INTERRUPT_REQUEST: _interrupt(cpu); return; @@ -76,12 +72,72 @@ void Thread::_mmu_exception() _fault.submit(); return; } - PERR("unknown MMU exception"); + PERR("%s -> %s: raised unhandled %s DFSR=0x%08x ISFR=0x%08x " + "DFAR=0x%08x ip=0x%08lx sp=0x%08lx", pd_label(), label(), + cpu_exception == DATA_ABORT ? "data abort" : "prefetch abort", + Cpu::Dfsr::read(), Cpu::Ifsr::read(), Cpu::Dfar::read(), ip, sp); } -void Thread::_call_update_pd() +void Kernel::Thread::_call_update_data_region() { - Pd * const pd = (Pd *) user_arg_1(); - if (Cpu_domain_update::_do_global(pd->asid)) { _pause(); } + Cpu * const cpu = cpu_pool()->cpu(Cpu::executing_id()); + + /* + * FIXME: If the caller is not a core thread, the kernel operates in a + * different address space than the caller. Combined with the fact + * that at least ARMv7 doesn't provide cache operations by physical + * address, this prevents us from selectively maintaining caches. + * The future solution will be a kernel that is mapped to every + * address space so we can use virtual addresses of the caller. Up + * until then we apply operations to caches as a whole instead. + */ + if (!_core()) { + cpu->clean_invalidate_data_cache(); + return; + } + auto base = (addr_t)user_arg_1(); + auto const size = (size_t)user_arg_2(); + cpu->clean_invalidate_data_cache_by_virt_region(base, size); + cpu->invalidate_instr_cache(); } + + +void Kernel::Thread::_call_update_instr_region() +{ + Cpu * const cpu = cpu_pool()->cpu(Cpu::executing_id()); + + /* + * FIXME: If the caller is not a core thread, the kernel operates in a + * different address space than the caller. Combined with the fact + * that at least ARMv7 doesn't provide cache operations by physical + * address, this prevents us from selectively maintaining caches. + * The future solution will be a kernel that is mapped to every + * address space so we can use virtual addresses of the caller. Up + * until then we apply operations to caches as a whole instead. + */ + if (!_core()) { + cpu->clean_invalidate_data_cache(); + cpu->invalidate_instr_cache(); + return; + } + auto base = (addr_t)user_arg_1(); + auto const size = (size_t)user_arg_2(); + cpu->clean_invalidate_data_cache_by_virt_region(base, size); + cpu->invalidate_instr_cache_by_virt_region(base, size); +} + + +void Thread_event::_signal_acknowledged() +{ + /* + * FIXME: this is currently only called as reply to a page-fault resolution. + * On some ARM platforms, we have to do maintainance operations + * after new page table entries where added. If core runs completely + * in privileged mode, we should move this hook to the mappings + * functions. + */ + cpu_pool()->cpu(Cpu::executing_id())->translation_table_insertions(); + _thread->_resume(); +} + diff --git a/repos/base-hw/src/core/spec/arm/kernel/thread_update_pd.cc b/repos/base-hw/src/core/spec/arm/kernel/thread_update_pd.cc new file mode 100644 index 000000000..c3972bc08 --- /dev/null +++ b/repos/base-hw/src/core/spec/arm/kernel/thread_update_pd.cc @@ -0,0 +1,24 @@ +/* + * \brief ARM non-SMP specific kernel thread implementations + * \author Stefan Kalkowski + * \date 2015-12-20 + */ + +/* + * Copyright (C) 2015-2016 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 + +void Kernel::Thread::_call_update_pd() +{ + Pd * const pd = (Pd *) user_arg_1(); + Cpu * const cpu = cpu_pool()->cpu(Cpu::executing_id()); + cpu->invalidate_instr_cache(); + cpu->clean_invalidate_data_cache(); + cpu->invalidate_tlb_by_pid(pd->asid); +} diff --git a/repos/base-hw/src/core/spec/arm/smp/kernel/cpu.cc b/repos/base-hw/src/core/spec/arm/smp/kernel/cpu.cc new file mode 100644 index 000000000..2f5ce7336 --- /dev/null +++ b/repos/base-hw/src/core/spec/arm/smp/kernel/cpu.cc @@ -0,0 +1,42 @@ +/* + * \brief Cpu class implementation specific to ARM SMP + * \author Stefan Kalkowski + * \date 2015-12-09 + */ + +/* + * Copyright (C) 2015-2016 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 +#include + +/* base includes */ +#include + + +/* spin-lock used to synchronize kernel access of different cpus */ +Kernel::Lock & Kernel::data_lock() { + return *unmanaged_singleton(); } + + +/** + * Setup non-boot CPUs + */ +extern "C" void init_kernel_mp() +{ + using namespace Kernel; + + cpu_pool()->cpu(Genode::Cpu::executing_id())->init(*pic(), *core_pd(), board()); + + kernel(); +} + + +void Kernel::Cpu_domain_update::_domain_update() { + cpu_pool()->cpu(Cpu::executing_id())->invalidate_tlb_by_pid(_domain_id); } diff --git a/repos/base-hw/src/core/spec/arm/smp/kernel/crt0.s b/repos/base-hw/src/core/spec/arm/smp/kernel/crt0.s index a0b751679..eba4f282a 100644 --- a/repos/base-hw/src/core/spec/arm/smp/kernel/crt0.s +++ b/repos/base-hw/src/core/spec/arm/smp/kernel/crt0.s @@ -35,8 +35,5 @@ _init_kernel_sp r0, r1 /* do multiprocessor kernel-initialization */ bl init_kernel_mp -/* call the kernel main-routine */ -bl kernel - /* catch erroneous return of the kernel main-routine */ 1: b 1b diff --git a/repos/base-hw/src/core/spec/arm/smp/kernel/thread_update_pd.cc b/repos/base-hw/src/core/spec/arm/smp/kernel/thread_update_pd.cc new file mode 100644 index 000000000..27762f126 --- /dev/null +++ b/repos/base-hw/src/core/spec/arm/smp/kernel/thread_update_pd.cc @@ -0,0 +1,22 @@ +/* + * \brief ARM SMP specific kernel thread implementations + * \author Stefan Kalkowski + * \date 2015-12-20 + */ + +/* + * Copyright (C) 2015-2016 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 + +void Kernel::Thread::_call_update_pd() +{ + Pd * const pd = (Pd *) user_arg_1(); + if (Cpu_domain_update::_do_global(pd->asid)) { _pause(); } +} diff --git a/repos/base-hw/src/core/spec/arm_v6/cpu.cc b/repos/base-hw/src/core/spec/arm_v6/cpu.cc index fca4949cc..7a76cb5ee 100644 --- a/repos/base-hw/src/core/spec/arm_v6/cpu.cc +++ b/repos/base-hw/src/core/spec/arm_v6/cpu.cc @@ -7,7 +7,7 @@ */ /* - * Copyright (C) 2012-2015 Genode Labs GmbH + * Copyright (C) 2012-2016 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. @@ -15,19 +15,41 @@ #include #include +#include -void Genode::Arm::flush_data_caches() { +void Genode::Arm::clean_invalidate_data_cache() { asm volatile ("mcr p15, 0, %[rd], c7, c14, 0" :: [rd]"r"(0) : ); } -void Genode::Arm::invalidate_data_caches() { - asm volatile ("mcr p15, 0, %[rd], c7, c6, 0" :: [rd]"r"(0) : ); } - -void Genode::Cpu::init_virt_kernel(Kernel::Pd& pd) +void Genode::Arm::enable_mmu_and_caches(Kernel::Pd& pd) { + /* check for mapping restrictions */ + assert(!Cpu::restricted_page_mappings()); + + invalidate_tlb(); Cidr::write(pd.asid); Dacr::write(Dacr::init_virt_kernel()); Ttbr0::write(Ttbr0::init((Genode::addr_t)pd.translation_table())); Ttbcr::write(0); - Sctlr::write(Sctlr::init_virt_kernel()); + Sctlr::enable_mmu_and_caches(); +} + + +void Genode::Cpu::translation_added(Genode::addr_t const addr, + Genode::size_t const size) +{ + using namespace Kernel; + + /* + * The Cortex-A8 CPU can't use the L1 cache on page-table + * walks. Therefore, as the page-tables lie in write-back cacheable + * memory we've to clean the corresponding cache-lines even when a + * page table entry is added. We only do this as core as the kernel + * adds translations solely before MMU and caches are enabled. + */ + if (is_user()) update_data_region(addr, size); + else { + Cpu * const cpu = cpu_pool()->cpu(Cpu::executing_id()); + cpu->clean_invalidate_data_cache(); + } } diff --git a/repos/base-hw/src/core/spec/arm_v7/cpu.cc b/repos/base-hw/src/core/spec/arm_v7/cpu.cc index 432192ed5..84e876f78 100644 --- a/repos/base-hw/src/core/spec/arm_v7/cpu.cc +++ b/repos/base-hw/src/core/spec/arm_v7/cpu.cc @@ -6,7 +6,7 @@ */ /* - * Copyright (C) 2011-2015 Genode Labs GmbH + * Copyright (C) 2011-2016 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. @@ -30,7 +30,7 @@ * Must be inserted directly before the targeted operation. Returns operand * for targeted operation in R6. */ -#define FOR_ALL_SET_WAY_OF_ALL_DATA_CACHES_0 \ +#define FOR_ALL_SET_WAY_IN_R6_0 \ \ /* get the cache level value (Clidr::Loc) */ \ READ_CLIDR(r0) \ @@ -97,7 +97,7 @@ * * Must be inserted directly after the targeted operation. */ -#define FOR_ALL_SET_WAY_OF_ALL_DATA_CACHES_1 \ +#define FOR_ALL_SET_WAY_IN_R6_1 \ \ /* decrement the index */ \ "subs r7, r7, #1\n" \ @@ -129,23 +129,25 @@ ::: "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9" -void Genode::Arm::flush_data_caches() +void Genode::Arm_v7::invalidate_inner_data_cache() { - asm volatile ( - FOR_ALL_SET_WAY_OF_ALL_DATA_CACHES_0 - WRITE_DCCSW(r6) - FOR_ALL_SET_WAY_OF_ALL_DATA_CACHES_1); - Board::outer_cache_flush(); + /** + * Data Cache Invalidate by Set/Way for all Set/Way + */ + asm volatile (FOR_ALL_SET_WAY_IN_R6_0 + WRITE_DCISW(r6) + FOR_ALL_SET_WAY_IN_R6_1); } -void Genode::Arm::invalidate_data_caches() +void Genode::Arm_v7::clean_invalidate_inner_data_cache() { - asm volatile ( - FOR_ALL_SET_WAY_OF_ALL_DATA_CACHES_0 - WRITE_DCISW(r6) - FOR_ALL_SET_WAY_OF_ALL_DATA_CACHES_1); - Board::outer_cache_invalidate(); + /** + * Data Cache Clean by Set/Way for all Set/Way + */ + asm volatile (FOR_ALL_SET_WAY_IN_R6_0 + WRITE_DCCSW(r6) + FOR_ALL_SET_WAY_IN_R6_1); } @@ -157,14 +159,3 @@ Genode::Arm::Psr::access_t Genode::Arm::Psr::init_user_with_trustzone() A::set(v, 1); return v; } - - -void Genode::Arm_v7::init_virt_kernel(Kernel::Pd & pd) -{ - Cidr::write(pd.asid); - Dacr::write(Dacr::init_virt_kernel()); - Ttbr0::write(Ttbr0::init((Genode::addr_t)pd.translation_table())); - Ttbcr::write(0); - Sctlr::write(Sctlr::init_virt_kernel()); - inval_branch_predicts(); -} diff --git a/repos/base-hw/src/core/spec/arm_v7/smp/kernel/cpu.cc b/repos/base-hw/src/core/spec/arm_v7/smp/kernel/cpu.cc deleted file mode 100644 index dec28516b..000000000 --- a/repos/base-hw/src/core/spec/arm_v7/smp/kernel/cpu.cc +++ /dev/null @@ -1,99 +0,0 @@ -/* - * \brief Cpu class implementation specific to Armv7 SMP - * \author Martin Stein - * \author Stefan Kalkowski - * \date 2015-12-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 -#include -#include -#include -#include -#include -#include -#include -#include - -/* base includes */ -#include -#include - -/* base-hw includes */ -#include - -using namespace Kernel; - -extern "C" void * _start_secondary_cpus; - -Lock & Kernel::data_lock() { return *unmanaged_singleton(); } - - -/** - * Setup kernel enviroment after activating secondary CPUs - */ -extern "C" void init_kernel_mp() -{ - /* - * As updates on a cached kernel lock might not be visible to CPUs that - * have not enabled caches, we can't synchronize the activation of MMU and - * caches. Hence we must avoid write access to kernel data by now. - */ - - /* synchronize data view of all CPUs */ - Cpu::invalidate_data_caches(); - 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(); - - /* switch to core address space */ - Cpu::init_virt_kernel(*core_pd()); - - /* - * Now it's safe to use 'cmpxchg' - */ - { - Lock::Guard guard(data_lock()); - - /* - * Now it's save to write to kernel data - */ - - /* TrustZone initialization code */ - init_trustzone(*pic()); - - /* enable performance counter */ - perf_counter()->enable(); - - /* enable timer interrupt */ - unsigned const cpu = Cpu::executing_id(); - pic()->unmask(Timer::interrupt_id(cpu), cpu); - PINF("ok CPU awake"); - } -} - - -void Kernel::Cpu::init(Kernel::Pic &pic, Kernel::Pd & core_pd) -{ - if (NR_OF_CPUS > 1) { - Genode::Board::secondary_cpus_ip(&_start_secondary_cpus); - data_synchronization_barrier(); - asm volatile ("sev\n"); - } - - init_kernel_mp(); -} diff --git a/repos/base-hw/src/core/spec/arm_v7/virtualization/kernel/cpu_context.cc b/repos/base-hw/src/core/spec/arm_v7/virtualization/kernel/cpu_context.cc index 01f53614e..aae9bc11d 100644 --- a/repos/base-hw/src/core/spec/arm_v7/virtualization/kernel/cpu_context.cc +++ b/repos/base-hw/src/core/spec/arm_v7/virtualization/kernel/cpu_context.cc @@ -5,7 +5,7 @@ */ /* - * Copyright (C) 2015 Genode Labs GmbH + * Copyright (C) 2015-2016 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. @@ -18,7 +18,7 @@ void Kernel::Cpu_context::_init(size_t const stack_size, addr_t const table) { r12 = stack_size; cpu_exception = Genode::Cpu::Ttbr0::init(table); - sctlr = Cpu::Sctlr::init_virt_kernel(); + sctlr = Cpu::Sctlr::init_value(); ttbrc = Cpu::Ttbcr::init_virt_kernel(); mair0 = Cpu::Mair0::init_virt_kernel(); } diff --git a/repos/base-hw/src/core/spec/arm_v7/virtualization/kernel/vm.cc b/repos/base-hw/src/core/spec/arm_v7/virtualization/kernel/vm.cc index fd31aa592..55c50f1ed 100644 --- a/repos/base-hw/src/core/spec/arm_v7/virtualization/kernel/vm.cc +++ b/repos/base-hw/src/core/spec/arm_v7/virtualization/kernel/vm.cc @@ -193,7 +193,7 @@ void Kernel::prepare_hypervisor() Cpu::Hcptr::write(Cpu::Hcptr::init()); Cpu::Hmair0::write(Cpu::Mair0::init_virt_kernel()); Cpu::Vtcr::write(Cpu::Vtcr::init()); - Cpu::Hsctlr::write(Cpu::Sctlr::init_virt_kernel()); + Cpu::Hsctlr::write(Cpu::Sctlr::init_value()); /* initialize host context used in virtualization world switch */ *((void**)&_vt_host_context_ptr) = &_mt_master_context_begin; diff --git a/repos/base-hw/src/core/spec/arndale/board.cc b/repos/base-hw/src/core/spec/arndale/cpu.cc similarity index 86% rename from repos/base-hw/src/core/spec/arndale/board.cc rename to repos/base-hw/src/core/spec/arndale/cpu.cc index c023420d9..191f883d1 100644 --- a/repos/base-hw/src/core/spec/arndale/board.cc +++ b/repos/base-hw/src/core/spec/arndale/cpu.cc @@ -1,31 +1,24 @@ /* - * \brief Board-specific code for Arndale + * \brief CPU-specific initialization code for Arndale * \author Stefan Kalkowski - * \date 2015-02-09 + * \date 2016-01-07 */ /* - * Copyright (C) 2015 Genode Labs GmbH + * Copyright (C) 2016 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 -#include -#include -#include -#include -#include -namespace Kernel { - void prepare_hypervisor(void); -} +namespace Kernel { void prepare_hypervisor(void); } static unsigned char hyp_mode_stack[1024]; + static inline void prepare_nonsecure_world() { using Nsacr = Genode::Cpu::Nsacr; @@ -89,7 +82,7 @@ static inline void switch_to_supervisor_mode() } -void Genode::Board::prepare_kernel() +void Genode::Cpu::init() { prepare_nonsecure_world(); Kernel::prepare_hypervisor(); diff --git a/repos/base-hw/src/core/spec/cortex_a15/cpu.cc b/repos/base-hw/src/core/spec/cortex_a15/cpu.cc index 2eec39ec0..dd2c9e395 100644 --- a/repos/base-hw/src/core/spec/cortex_a15/cpu.cc +++ b/repos/base-hw/src/core/spec/cortex_a15/cpu.cc @@ -1,11 +1,11 @@ /* - * \brief Kernel backend for protection domains + * \brief Cpu driver implementations specific to ARM Cortex A15 * \author Stefan Kalkowski - * \date 2015-03-20 + * \date 2016-01-07 */ /* - * Copyright (C) 2015 Genode Labs GmbH + * Copyright (C) 2016 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. @@ -15,13 +15,12 @@ #include #include -void Genode::Cpu::init_virt_kernel(Kernel::Pd & pd) +void Genode::Arm_v7::enable_mmu_and_caches(Kernel::Pd & pd) { - Mair0::write(Mair0::init_virt_kernel()); - Dacr::write(Dacr::init_virt_kernel()); - Ttbr0::write(Ttbr0::init((Genode::addr_t)pd.translation_table(), - pd.asid)); - Ttbcr::write(Ttbcr::init_virt_kernel()); - Sctlr::write(Sctlr::init_virt_kernel()); - inval_branch_predicts(); + Cpu::Mair0::write(Cpu::Mair0::init_virt_kernel()); + Cpu::Dacr::write(Cpu::Dacr::init_virt_kernel()); + Cpu::Ttbr0::write(Cpu::Ttbr0::init((Genode::addr_t)pd.translation_table(), pd.asid)); + Cpu::Ttbcr::write(Cpu::Ttbcr::init_virt_kernel()); + Cpu::Sctlr::enable_mmu_and_caches(); + invalidate_branch_predicts(); } diff --git a/repos/base-hw/src/core/spec/cortex_a15/cpu_init.cc b/repos/base-hw/src/core/spec/cortex_a15/cpu_init.cc new file mode 100644 index 000000000..389af2f79 --- /dev/null +++ b/repos/base-hw/src/core/spec/cortex_a15/cpu_init.cc @@ -0,0 +1,16 @@ +/* + * \brief Cpu-specific code for Cortex A15 + * \author Stefan Kalkowski + * \date 2016-01-07 + */ + +/* + * Copyright (C) 2016 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. + */ + +#include + +void Genode::Cpu::init() {} diff --git a/repos/base-hw/src/core/spec/cortex_a15/kernel/cpu.cc b/repos/base-hw/src/core/spec/cortex_a15/kernel/cpu.cc new file mode 100644 index 000000000..aacc8f62c --- /dev/null +++ b/repos/base-hw/src/core/spec/cortex_a15/kernel/cpu.cc @@ -0,0 +1,65 @@ +/* + * \brief Cpu class implementation specific to Cortex A15 SMP + * \author Stefan Kalkowski + * \date 2015-12-09 + */ + +/* + * Copyright (C) 2015-2016 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 +#include +#include + +/* base-hw includes */ +#include + +using namespace Kernel; + +/* entrypoint for non-boot CPUs */ +extern "C" void * _start_secondary_cpus; + +/* indicates boot cpu status */ +static volatile bool primary_cpu = true; + + +void Kernel::Cpu::init(Kernel::Pic &pic, Kernel::Pd & core_pd, Genode::Board & board) +{ + /* + * local interrupt controller interface needs to be initialized that early, + * because it potentially sets the SGI interrupts to be non-secure before + * entering the normal world in Genode::Cpu::init() + */ + pic.init_cpu_local(); + + Genode::Cpu::init(); + + Sctlr::init(); + Psr::write(Psr::init_kernel()); + + invalidate_inner_data_cache(); + + /* primary cpu wakes up all others */ + if (primary_cpu && NR_OF_CPUS > 1) { + primary_cpu = false; + board.wake_up_all_cpus(&_start_secondary_cpus); + } + + enable_mmu_and_caches(core_pd); + + { + Lock::Guard guard(data_lock()); + + /* enable performance counter */ + perf_counter()->enable(); + + /* enable timer interrupt */ + pic.unmask(Timer::interrupt_id(id()), id()); + } +} diff --git a/repos/base-hw/src/core/spec/cortex_a8/cpu.cc b/repos/base-hw/src/core/spec/cortex_a8/cpu.cc new file mode 100644 index 000000000..b30bec366 --- /dev/null +++ b/repos/base-hw/src/core/spec/cortex_a8/cpu.cc @@ -0,0 +1,56 @@ +/* + * \brief CPU driver for core Arm Cortex A8 specific implementation + * \author Martin stein + * \author Stefan Kalkowski + * \date 2015-12-14 + */ + +/* + * 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. + */ + +#include +#include +#include +#include + +void Genode::Cpu::translation_table_insertions() +{ + clean_invalidate_data_cache(); + invalidate_tlb(); +} + + +void Genode::Cpu::translation_added(Genode::addr_t const addr, + Genode::size_t const size) +{ + using namespace Kernel; + + /* + * The Cortex-A8 CPU can't use the L1 cache on page-table + * walks. Therefore, as the page-tables lie in write-back cacheable + * memory we've to clean the corresponding cache-lines even when a + * page table entry is added. We only do this as core as the kernel + * adds translations solely before MMU and caches are enabled. + */ + if (is_user()) update_data_region(addr, size); + else { + Cpu * const cpu = cpu_pool()->cpu(Cpu::executing_id()); + cpu->clean_invalidate_data_cache(); + } +} + + +void Genode::Arm_v7::enable_mmu_and_caches(Kernel::Pd & pd) +{ + invalidate_tlb(); + Cpu::Cidr::write(pd.asid); + Cpu::Dacr::write(Dacr::init_virt_kernel()); + Cpu::Ttbr0::write(Ttbr0::init((Genode::addr_t)pd.translation_table())); + Cpu::Ttbcr::write(0); + Cpu::Sctlr::enable_mmu_and_caches(); + invalidate_branch_predicts(); +} diff --git a/repos/base-hw/src/core/spec/cortex_a9/cpu.cc b/repos/base-hw/src/core/spec/cortex_a9/cpu.cc new file mode 100644 index 000000000..b2a974fa2 --- /dev/null +++ b/repos/base-hw/src/core/spec/cortex_a9/cpu.cc @@ -0,0 +1,28 @@ +/* + * \brief CPU driver for core + * \author Martin stein + * \author Stefan Kalkowski + * \date 2011-11-03 + */ + +/* + * Copyright (C) 2011-2016 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. + */ + +#include +#include + +void Genode::Arm_v7::enable_mmu_and_caches(Kernel::Pd & pd) +{ + invalidate_tlb(); + Cpu::Cidr::write(pd.asid); + Cpu::Dacr::write(Dacr::init_virt_kernel()); + Cpu::Ttbr0::write(Ttbr0::init((Genode::addr_t)pd.translation_table())); + Cpu::Ttbcr::write(0); + Cpu::Sctlr::enable_mmu_and_caches(); + invalidate_branch_predicts(); +} + diff --git a/repos/base-hw/src/core/spec/cortex_a9/kernel/cpu.cc b/repos/base-hw/src/core/spec/cortex_a9/kernel/cpu.cc new file mode 100644 index 000000000..dd6203459 --- /dev/null +++ b/repos/base-hw/src/core/spec/cortex_a9/kernel/cpu.cc @@ -0,0 +1,128 @@ +/* + * \brief Cpu class implementation specific to Cortex A9 SMP + * \author Stefan Kalkowski + * \date 2015-12-09 + */ + +/* + * Copyright (C) 2015-2016 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 +#include +#include +#include + +/* base-hw includes */ +#include + +using namespace Kernel; + +/* entrypoint for non-boot CPUs */ +extern "C" void * _start_secondary_cpus; + + +/** + * SMP-safe simple counter + */ +class Counter +{ + private: + + Kernel::Lock _lock; + volatile int _value = 0; + + public: + + void inc() + { + Kernel::Lock::Guard guard(_lock); + Genode::memory_barrier(); + _value++; + } + + void wait_for(int const v) { + while (_value < v) ; } +}; + +static volatile bool primary_cpu = true; /* indicates boot cpu status */ +static Counter data_cache_invalidated; /* counts cpus that invalidated + their data cache */ +static Counter data_cache_enabled; /* counts cpus that enabled + their data cache */ +static Counter smp_coherency_enabled; /* counts cpus that enabled + their SCU */ + + +/* + * The initialization of Cortex A9 multicore systems implies a sophisticated + * algorithm in early revisions of this cpu. + * + * See ARM's Cortex-A9 MPCore TRM r2p0 in section 5.3.5 for more details + */ +void Kernel::Cpu::init(Kernel::Pic &pic, Kernel::Pd & core_pd, Genode::Board & board) +{ + bool primary = primary_cpu; + if (primary) primary_cpu = false; + + Sctlr::init(); + Psr::write(Psr::init_kernel()); + + /* locally initialize interrupt controller */ + pic.init_cpu_local(); + + invalidate_inner_data_cache(); + data_cache_invalidated.inc(); + + /* primary cpu wakes up all others */ + if (primary && NR_OF_CPUS > 1) + board.wake_up_all_cpus(&_start_secondary_cpus); + + /* wait for other cores' data cache invalidation */ + data_cache_invalidated.wait_for(NR_OF_CPUS); + + if (primary) { + Genode::Scu scu(board); + scu.invalidate(); + board.l2_cache().invalidate(); + scu.enable(); + } + + /* secondary cpus wait for the primary's cache activation */ + if (!primary) data_cache_enabled.wait_for(1); + + enable_mmu_and_caches(core_pd); + data_cache_enabled.inc(); + clean_invalidate_inner_data_cache(); + + /* wait for other cores' data cache activation */ + data_cache_enabled.wait_for(NR_OF_CPUS); + + if (primary) board.l2_cache().enable(); + + /* secondary cpus wait for the primary's coherency activation */ + if (!primary) smp_coherency_enabled.wait_for(1); + + Actlr::enable_smp(); + smp_coherency_enabled.inc(); + + /* wait for other cores' coherency activation */ + smp_coherency_enabled.wait_for(NR_OF_CPUS); + + init_advanced_fp_simd(); + + { + Lock::Guard guard(data_lock()); + + /* enable performance counter */ + perf_counter()->enable(); + + /* enable timer interrupt */ + pic.unmask(Timer::interrupt_id(id()), id()); + } +} diff --git a/repos/base-hw/src/core/spec/exynos5/cpu.cc b/repos/base-hw/src/core/spec/exynos5/cpu.cc index f78246429..95a63cf44 100644 --- a/repos/base-hw/src/core/spec/exynos5/cpu.cc +++ b/repos/base-hw/src/core/spec/exynos5/cpu.cc @@ -18,7 +18,4 @@ using namespace Genode; -unsigned Cpu::executing_id() { return Mpidr::Aff_0::get(Mpidr::read()); } - - unsigned Cpu::primary_id() { return Board::PRIMARY_MPIDR_AFF_0; } diff --git a/repos/base-hw/src/core/spec/imx53/platform_support.cc b/repos/base-hw/src/core/spec/imx53/platform_support.cc index aebbcffec..fff8738a3 100644 --- a/repos/base-hw/src/core/spec/imx53/platform_support.cc +++ b/repos/base-hw/src/core/spec/imx53/platform_support.cc @@ -59,6 +59,4 @@ Native_region * Platform::_core_only_mmio_regions(unsigned const i) } -bool Imx::Board::is_smp() { return false; } - Cpu::User_context::User_context() { cpsr = Psr::init_user(); } 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 342d0b72c..efecf0ef5 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 @@ -40,15 +40,10 @@ bool secure_irq(unsigned const i) } -void Kernel::init_trustzone(Pic * pic) +void Kernel::init_trustzone(Pic & pic) { using namespace Genode; - /* check for compatibility */ - if (NR_OF_CPUS > 1) { - PERR("trustzone not supported with multiprocessing"); - return; - } /* set exception vector entry */ Cpu::mon_exception_entry_at((Genode::addr_t)&_mon_kernel_entry); @@ -60,7 +55,7 @@ void Kernel::init_trustzone(Pic * pic) /* configure non-secure interrupts */ for (unsigned i = 0; i < Pic::NR_OF_IRQ; i++) { - if (!secure_irq(i)) { pic->unsecure(i); } } + if (!secure_irq(i)) { pic.unsecure(i); } } /* configure central security unit */ Genode::Csu csu(Board::CSU_BASE); @@ -110,6 +105,4 @@ Native_region * Platform::_core_only_mmio_regions(unsigned const i) } -bool Imx::Board::is_smp() { return false; } - Cpu::User_context::User_context() { cpsr = Psr::init_user_with_trustzone(); } diff --git a/repos/base-hw/src/core/spec/imx6/platform_support.cc b/repos/base-hw/src/core/spec/imx6/platform_support.cc index 2a236e5c7..c06079026 100644 --- a/repos/base-hw/src/core/spec/imx6/platform_support.cc +++ b/repos/base-hw/src/core/spec/imx6/platform_support.cc @@ -7,7 +7,7 @@ */ /* - * Copyright (C) 2014-2015 Genode Labs GmbH + * Copyright (C) 2014-2016 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. @@ -49,11 +49,26 @@ Native_region * Platform::_core_only_mmio_regions(unsigned const i) /* CPU-local core MMIO like interrupt controller and timer */ { Board::CORTEX_A9_PRIVATE_MEM_BASE, Board::CORTEX_A9_PRIVATE_MEM_SIZE }, + /* l2 cache controller */ + { Board::PL310_MMIO_BASE, Board::PL310_MMIO_SIZE } }; return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0; } -bool Imx::Board::is_smp() { return true; } - Cpu::User_context::User_context() { cpsr = Psr::init_user(); } + + +bool Cortex_a9::Board::errata(Cortex_a9::Board::Errata err) +{ + switch (err) { + case Cortex_a9::Board::ARM_754322: + case Cortex_a9::Board::ARM_764369: + case Cortex_a9::Board::ARM_775420: + case Cortex_a9::Board::PL310_588369: + case Cortex_a9::Board::PL310_727915: + case Cortex_a9::Board::PL310_769419: + return true; + }; + return false; +} diff --git a/repos/base-hw/src/core/spec/panda/platform_support.cc b/repos/base-hw/src/core/spec/panda/platform_support.cc index 1bd49f981..7e6fb290e 100644 --- a/repos/base-hw/src/core/spec/panda/platform_support.cc +++ b/repos/base-hw/src/core/spec/panda/platform_support.cc @@ -16,6 +16,7 @@ #include #include #include +#include #include using namespace Genode; @@ -62,13 +63,27 @@ Native_region * Platform::_core_only_mmio_regions(unsigned const i) } -static Genode::L2_cache * l2_cache() { - return unmanaged_singleton(); } - - -void Board::outer_cache_invalidate() { l2_cache()->invalidate(); } -void Board::outer_cache_flush() { l2_cache()->flush(); } -void Board::prepare_kernel() { l2_cache()->invalidate(); } - +void Cortex_a9::Board::wake_up_all_cpus(void * const ip) +{ + Cortex_a9_wugen wugen; + wugen.init_cpu_1(ip); + asm volatile("dsb\n" + "sev\n"); +} Cpu::User_context::User_context() { cpsr = Psr::init_user(); } + + +void Cpu::Actlr::enable_smp() { + Kernel::board().monitor().call(Board::Secure_monitor::CPU_ACTLR_SMP_BIT_RAISE, 0); } + + +bool Cortex_a9::Board::errata(Cortex_a9::Board::Errata err) +{ + switch (err) { + case Cortex_a9::Board::PL310_588369: + case Cortex_a9::Board::PL310_727915: return true; + default: ; + }; + return false; +} diff --git a/repos/base-hw/src/core/spec/pbxa9/board.cc b/repos/base-hw/src/core/spec/pbxa9/board.cc new file mode 100644 index 000000000..db940a187 --- /dev/null +++ b/repos/base-hw/src/core/spec/pbxa9/board.cc @@ -0,0 +1,45 @@ +/* + * \brief Board implementation specific to PBXA9 + * \author Stefan Kalkowski + * \date 2016-01-07 + */ + +/* + * Copyright (C) 2016 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. + */ + +#include +#include +#include + +bool Cortex_a9::Board::errata(Cortex_a9::Board::Errata err) { + return false; } + + +void Cortex_a9::Board::wake_up_all_cpus(void * const ip) +{ + /** + * set the entrypoint for the other CPUs via the flags register + * of the system control registers. ARMs boot monitor code will + * read out this register and jump to it after the cpu received + * an interrupt + */ + struct System_control : Genode::Mmio + { + struct Flagsset : Register<0x30, 32> { }; + struct Flagsclr : Register<0x34, 32> { }; + + System_control(void * const ip) + : Mmio(SYSTEM_CONTROL_MMIO_BASE) + { + write(~0UL); + write(reinterpret_cast(ip)); + } + } sc(ip); + + /* send an IPI to all other cpus */ + Kernel::pic()->send_ipi(); +} diff --git a/repos/base-hw/src/core/spec/pbxa9/platform_support.cc b/repos/base-hw/src/core/spec/pbxa9/platform_support.cc index 5ad01366f..96713237e 100644 --- a/repos/base-hw/src/core/spec/pbxa9/platform_support.cc +++ b/repos/base-hw/src/core/spec/pbxa9/platform_support.cc @@ -50,7 +50,10 @@ Native_region * Platform::_core_only_mmio_regions(unsigned const i) { Board::CORTEX_A9_PRIVATE_MEM_BASE, Board::CORTEX_A9_PRIVATE_MEM_SIZE }, /* core UART */ - { Board::PL011_0_MMIO_BASE, Board::PL011_0_MMIO_SIZE } + { Board::PL011_0_MMIO_BASE, Board::PL011_0_MMIO_SIZE }, + + /* L2 Cache Controller */ + { Board::PL310_MMIO_BASE, Board::PL310_MMIO_SIZE } }; return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0; } diff --git a/repos/base-hw/src/core/spec/smp/kernel/cpu.cc b/repos/base-hw/src/core/spec/smp/kernel/cpu.cc new file mode 100644 index 000000000..edd40dbf5 --- /dev/null +++ b/repos/base-hw/src/core/spec/smp/kernel/cpu.cc @@ -0,0 +1,108 @@ +/* + * \brief ARM with SMP support specific aspects of the kernel cpu objects + * \author Stefan Kalkowski + * \author Martin Stein + * \date 2016-01-07 + */ + +/* + * Copyright (C) 2016 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 + +namespace Kernel +{ + /** + * Lists all pending domain updates + */ + class Cpu_domain_update_list; +} + + +class Kernel::Cpu_domain_update_list +: public Double_list_typed +{ + public: + + /** + * Perform all pending domain updates on the executing CPU + */ + void do_each() { + for_each([] (Cpu_domain_update * const u) { u->_do(); }); } +}; + + +using namespace Kernel; + +/** + * Return singleton of the CPU domain-udpate list + */ +Cpu_domain_update_list & cpu_domain_update_list() { + return *unmanaged_singleton(); } + + + +void Cpu::Ipi::occurred() +{ + cpu_domain_update_list().do_each(); + pending = false; +} + + +void Cpu::Ipi::trigger(unsigned const cpu_id) +{ + if (pending) return; + + pic()->send_ipi(cpu_id); + pending = true; +} + + +Cpu::Ipi::Ipi(Irq::Pool &p) : Irq(Pic::IPI, p) { } + + +/*********************** + ** Cpu_domain_update ** + ***********************/ + +void Cpu_domain_update::_do() +{ + /* perform domain update locally and get pending bit */ + unsigned const id = Cpu::executing_id(); + if (!_pending[id]) return; + + _domain_update(); + _pending[id] = false; + + /* check wether there are still CPUs pending */ + for (unsigned i = 0; i < NR_OF_CPUS; i++) + if (_pending[i]) return; + + /* as no CPU is pending anymore, end the domain update */ + cpu_domain_update_list().remove(this); + _cpu_domain_update_unblocks(); +} + + +bool Cpu_domain_update::_do_global(unsigned const domain_id) +{ + /* perform locally and leave it at that if in uniprocessor mode */ + _domain_id = domain_id; + _domain_update(); + if (NR_OF_CPUS == 1) return false; + + /* inform other CPUs and block until they are done */ + cpu_domain_update_list().insert_tail(this); + unsigned const cpu_id = Cpu::executing_id(); + for (unsigned i = 0; i < NR_OF_CPUS; i++) { + if (i == cpu_id) continue; + _pending[i] = true; + cpu_pool()->cpu(i)->trigger_ip_interrupt(); + } + return true; +} diff --git a/repos/base-hw/src/core/spec/smp/kernel/kernel.cc b/repos/base-hw/src/core/spec/smp/kernel/kernel.cc index e57aa09fd..7ee06a76b 100644 --- a/repos/base-hw/src/core/spec/smp/kernel/kernel.cc +++ b/repos/base-hw/src/core/spec/smp/kernel/kernel.cc @@ -1,12 +1,12 @@ /* - * \brief Kernel entrypoint + * \brief Kernel entrypoint for SMP systems * \author Martin Stein * \author Stefan Kalkowski * \date 2011-10-20 */ /* - * Copyright (C) 2011-2015 Genode Labs GmbH + * Copyright (C) 2011-2016 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. diff --git a/repos/base-hw/src/core/spec/x86/kernel/cpu.cc b/repos/base-hw/src/core/spec/x86/kernel/cpu.cc index c3619c4a5..84d363646 100644 --- a/repos/base-hw/src/core/spec/x86/kernel/cpu.cc +++ b/repos/base-hw/src/core/spec/x86/kernel/cpu.cc @@ -1,11 +1,12 @@ /* * \brief Class for kernel data that is needed to manage a specific CPU * \author Reto Buerki + * \author Stefan Kalkowski * \date 2015-02-09 */ /* - * Copyright (C) 2015 Genode Labs GmbH + * Copyright (C) 2015-2016 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. @@ -28,21 +29,7 @@ Cpu_idle::Cpu_idle(Cpu * const cpu) : Cpu_job(Cpu_priority::MIN, 0) } -void Cpu_idle::exception(unsigned const cpu) -{ - if (trapno == RESET) { - return; - } else if (trapno >= INTERRUPTS_START && trapno <= INTERRUPTS_END) { - _interrupt(cpu); - return; - } - PWRN("Unknown exception %lu with error code %lu at ip=%p", trapno, - errcode, (void *)ip); - assert(0); -} - - -void Kernel::Cpu::init(Pic &pic, Kernel::Pd &core_pd) +void Kernel::Cpu::init(Pic &pic, Kernel::Pd &core_pd, Genode::Board&) { Timer::disable_pit(); @@ -62,3 +49,6 @@ void Kernel::Cpu::init(Pic &pic, Kernel::Pd &core_pd) unsigned const cpu = Cpu::executing_id(); pic.unmask(Timer::interrupt_id(cpu), cpu); } + + +void Cpu_domain_update::_domain_update() { } diff --git a/repos/base-hw/src/core/spec/x86/kernel/cpu_exception.cc b/repos/base-hw/src/core/spec/x86/kernel/cpu_exception.cc new file mode 100644 index 000000000..f8475d686 --- /dev/null +++ b/repos/base-hw/src/core/spec/x86/kernel/cpu_exception.cc @@ -0,0 +1,30 @@ +/* + * \brief Kernel backend for protection domains + * \author Reto Buerki + * \author Stefan Kalkowski + * \date 2016-01-11 + */ + +/* + * Copyright (C) 2016 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. + */ + +#include +#include + +void Kernel::Cpu_idle::exception(unsigned const cpu) +{ + if (trapno == RESET) return; + + if (trapno >= INTERRUPTS_START && trapno <= INTERRUPTS_END) { + _interrupt(cpu); + return; + } + + PWRN("Unknown exception %lu with error code %lu at ip=%p", trapno, + errcode, (void *)ip); + assert(0); +} diff --git a/repos/base-hw/src/core/spec/x86/kernel/thread.cc b/repos/base-hw/src/core/spec/x86/kernel/thread.cc index 8747806c8..bcb743d99 100644 --- a/repos/base-hw/src/core/spec/x86/kernel/thread.cc +++ b/repos/base-hw/src/core/spec/x86/kernel/thread.cc @@ -2,11 +2,12 @@ * \brief Kernel backend for execution contexts in userland * \author Adrian-Ken Rueegsegger * \author Reto Buerki + * \author Stefan Kalkowski * \date 2015-02-09 */ /* - * Copyright (C) 2015 Genode Labs GmbH + * Copyright (C) 2015-2016 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. @@ -17,31 +18,11 @@ using namespace Kernel; -void Thread::exception(unsigned const cpu) -{ - switch (trapno) { - case PAGE_FAULT: - _mmu_exception(); - return; - case NO_MATH_COPROC: - if (_cpu->retry_fpu_instr(&_lazy_state)) { return; } - PWRN("%s -> %s: FPU error", pd_label(), label()); - _stop(); - return; - case UNDEFINED_INSTRUCTION: - PWRN("%s -> %s: undefined instruction at ip=%p", - pd_label(), label(), (void*)ip); - _stop(); - return; - case SUPERVISOR_CALL: - _call(); - return; - } - if (trapno >= INTERRUPTS_START && trapno <= INTERRUPTS_END) { - _interrupt(cpu); - return; - } - PWRN("%s -> %s: triggered unknown exception %lu with error code %lu" - " at ip=%p", pd_label(), label(), trapno, errcode, (void*)ip); - _stop(); -} + +void Thread::_call_update_data_region() { } + + +void Thread::_call_update_instr_region() { } + + +void Thread_event::_signal_acknowledged() { _thread->_resume(); } diff --git a/repos/base-hw/src/core/spec/x86/kernel/thread_exception.cc b/repos/base-hw/src/core/spec/x86/kernel/thread_exception.cc new file mode 100644 index 000000000..c479e570e --- /dev/null +++ b/repos/base-hw/src/core/spec/x86/kernel/thread_exception.cc @@ -0,0 +1,48 @@ +/* + * \brief Kernel backend for execution contexts in userland + * \author Adrian-Ken Rueegsegger + * \author Reto Buerki + * \author Stefan Kalkowski + * \date 2015-02-09 + */ + +/* + * Copyright (C) 2015-2016 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 Kernel; + +void Thread::exception(unsigned const cpu) +{ + switch (trapno) { + case PAGE_FAULT: + _mmu_exception(); + return; + case NO_MATH_COPROC: + if (_cpu->retry_fpu_instr(&_lazy_state)) { return; } + PWRN("%s -> %s: FPU error", pd_label(), label()); + _stop(); + return; + case UNDEFINED_INSTRUCTION: + PWRN("%s -> %s: undefined instruction at ip=%p", + pd_label(), label(), (void*)ip); + _stop(); + return; + case SUPERVISOR_CALL: + _call(); + return; + } + if (trapno >= INTERRUPTS_START && trapno <= INTERRUPTS_END) { + _interrupt(cpu); + return; + } + PWRN("%s -> %s: triggered unknown exception %lu with error code %lu" + " at ip=%p", pd_label(), label(), trapno, errcode, (void*)ip); + _stop(); +} diff --git a/repos/base-hw/src/core/spec/x86_64/muen/kernel/cpu.cc b/repos/base-hw/src/core/spec/x86_64/muen/kernel/cpu.cc deleted file mode 100644 index 5e5d44da2..000000000 --- a/repos/base-hw/src/core/spec/x86_64/muen/kernel/cpu.cc +++ /dev/null @@ -1,44 +0,0 @@ -/* - * \brief Class for kernel data that is needed to manage a specific CPU - * \author Reto Buerki - * \date 2015-04-28 - */ - -/* - * 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 -#include - -using namespace Kernel; - - -Cpu_idle::Cpu_idle(Cpu * const cpu) : Cpu_job(Cpu_priority::MIN, 0) -{ - Cpu_job::cpu(cpu); - ip = (addr_t)&_main; - sp = (addr_t)&_stack[stack_size]; - init((addr_t)core_pd()->translation_table(), true); -} - - -void Cpu_idle::exception(unsigned const cpu) -{ - if (trapno == RESET) return; - - if (trapno >= INTERRUPTS_START && trapno <= INTERRUPTS_END) { - pic()->irq_occurred(trapno); - _interrupt(cpu); - return; - } - - PWRN("Unknown exception %lu with error code %lu at ip=%p", trapno, - errcode, (void *)ip); - assert(0); -} diff --git a/repos/base-hw/src/core/spec/x86_64/muen/kernel/cpu_exception.cc b/repos/base-hw/src/core/spec/x86_64/muen/kernel/cpu_exception.cc new file mode 100644 index 000000000..809f760d5 --- /dev/null +++ b/repos/base-hw/src/core/spec/x86_64/muen/kernel/cpu_exception.cc @@ -0,0 +1,31 @@ +/* + * \brief Kernel backend for protection domains + * \author Reto Buerki + * \author Stefan Kalkowski + * \date 2016-01-11 + */ + +/* + * Copyright (C) 2016 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. + */ + +#include +#include + +void Kernel::Cpu_idle::exception(unsigned const cpu) +{ + if (trapno == RESET) return; + + if (trapno >= INTERRUPTS_START && trapno <= INTERRUPTS_END) { + pic()->irq_occurred(trapno); + _interrupt(cpu); + return; + } + + PWRN("Unknown exception %lu with error code %lu at ip=%p", trapno, + errcode, (void *)ip); + assert(0); +} diff --git a/repos/base-hw/src/core/spec/x86_64/muen/kernel/thread.cc b/repos/base-hw/src/core/spec/x86_64/muen/kernel/thread_exception.cc similarity index 99% rename from repos/base-hw/src/core/spec/x86_64/muen/kernel/thread.cc rename to repos/base-hw/src/core/spec/x86_64/muen/kernel/thread_exception.cc index 520d0a9c0..bb19b7491 100644 --- a/repos/base-hw/src/core/spec/x86_64/muen/kernel/thread.cc +++ b/repos/base-hw/src/core/spec/x86_64/muen/kernel/thread_exception.cc @@ -33,6 +33,7 @@ void Thread::exception(unsigned const cpu) PWRN("%s -> %s: undefined instruction at ip=%p", pd_label(), label(), (void*)ip); _stop(); + return; case SUPERVISOR_CALL: _call(); return; diff --git a/repos/base-hw/src/core/spec/zynq/platform_support.cc b/repos/base-hw/src/core/spec/zynq/platform_support.cc index c35efa276..5417cd5ee 100644 --- a/repos/base-hw/src/core/spec/zynq/platform_support.cc +++ b/repos/base-hw/src/core/spec/zynq/platform_support.cc @@ -1,11 +1,12 @@ /* * \brief Platform implementations specific for base-hw and Zynq * \author Johannes Schlatow + * \author Stefan Kalkowski * \date 2014-12-15 */ /* - * Copyright (C) 2012-2014 Genode Labs GmbH + * Copyright (C) 2014-2016 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. @@ -66,10 +67,5 @@ Native_region * Platform::_core_only_mmio_regions(unsigned const i) Cpu::User_context::User_context() { cpsr = Psr::init_user(); } -static Genode::Pl310 * l2_cache() { - return unmanaged_singleton(Board::PL310_MMIO_BASE); } - - -void Genode::Board::outer_cache_invalidate() { l2_cache()->invalidate(); } -void Genode::Board::outer_cache_flush() { l2_cache()->flush(); } -void Genode::Board::prepare_kernel() { l2_cache()->invalidate(); } +bool Cortex_a9::Board::errata(Cortex_a9::Board::Errata err) { + return false; } diff --git a/repos/base/include/spec/imx6/drivers/board_base.h b/repos/base/include/spec/imx6/drivers/board_base.h index 7d04b261b..07dd6ebc6 100644 --- a/repos/base/include/spec/imx6/drivers/board_base.h +++ b/repos/base/include/spec/imx6/drivers/board_base.h @@ -7,8 +7,8 @@ */ /* - * Copyright (C) 2014-2015 Ksys Labs LLC - * Copyright (C) 2014-2015 Genode Labs GmbH + * Copyright (C) 2014-2016 Ksys Labs LLC + * Copyright (C) 2014-2016 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. @@ -56,6 +56,10 @@ struct Genode::Board_base CORTEX_A9_PRIVATE_MEM_SIZE = 0x00002000, CORTEX_A9_PRIVATE_TIMER_CLK = 395037500, + /* L2 cache controller */ + PL310_MMIO_BASE = 0x00a02000, + PL310_MMIO_SIZE = 0x00001000, + /* CPU cache */ CACHE_LINE_SIZE_LOG2 = 5, diff --git a/repos/base/include/spec/pbxa9/drivers/board_base.h b/repos/base/include/spec/pbxa9/drivers/board_base.h index 242c4d432..7c593c6a8 100644 --- a/repos/base/include/spec/pbxa9/drivers/board_base.h +++ b/repos/base/include/spec/pbxa9/drivers/board_base.h @@ -5,7 +5,7 @@ */ /* - * Copyright (C) 2011-2013 Genode Labs GmbH + * Copyright (C) 2011-2016 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. @@ -46,10 +46,17 @@ struct Genode::Board_base /* clocks */ OSC_6_CLOCK = 24*1000*1000, + /* system controller */ + SYSTEM_CONTROL_MMIO_BASE = 0x10000000, + /* CPU */ CORTEX_A9_PRIVATE_TIMER_CLK = 100000000, CORTEX_A9_PRIVATE_MEM_BASE = 0x1f000000, - CORTEX_A9_PRIVATE_MEM_SIZE = 0x01000000, + CORTEX_A9_PRIVATE_MEM_SIZE = 0x2000, + + /* L2 cache controller */ + PL310_MMIO_BASE = 0x1f002000, + PL310_MMIO_SIZE = 0x00001000, /* UART */ PL011_0_MMIO_BASE = 0x10009000, diff --git a/repos/base/run/affinity.run b/repos/base/run/affinity.run index db247c9bb..878961c99 100644 --- a/repos/base/run/affinity.run +++ b/repos/base/run/affinity.run @@ -5,11 +5,13 @@ # if { - ![have_spec hw_arndale] && - ![have_spec foc_x86_32] && - ![have_spec foc_x86_64] && - ![have_spec foc_panda] && - ![have_spec foc_arndale] && + ![have_spec hw_arndale] && + ![have_spec hw_wand_quad] && + ![have_spec hw_panda] && + ![have_spec foc_x86_32] && + ![have_spec foc_x86_64] && + ![have_spec foc_panda] && + ![have_spec foc_arndale] && ![have_spec foc_odroid_x2] && ![have_spec nova] } { diff --git a/repos/base/run/mp_server.run b/repos/base/run/mp_server.run index 1183cd795..ad143eb47 100644 --- a/repos/base/run/mp_server.run +++ b/repos/base/run/mp_server.run @@ -4,10 +4,6 @@ # \author Alexander Boettcher # -if {[have_spec hw_panda]} { - puts "Platform is unsupported." - exit 0 -} build "core init test/mp_server"