diff --git a/repos/base-hw/lib/mk/spec/arm/core-hw.inc b/repos/base-hw/lib/mk/spec/arm/core-hw.inc index c4e071a24..6fb10c535 100644 --- a/repos/base-hw/lib/mk/spec/arm/core-hw.inc +++ b/repos/base-hw/lib/mk/spec/arm/core-hw.inc @@ -17,7 +17,7 @@ SRC_CC += spec/arm/platform_support.cc # add assembly sources SRC_S += spec/arm/crt0.s -SRC_S += spec/arm/exception_vector.s +SRC_S += spec/arm/exception_vector.S vpath spec/32bit/memory_map.cc $(BASE_DIR)/../base-hw/src/lib/hw diff --git a/repos/base-hw/src/bootstrap/spec/arm/cortex_a9_mmu.cc b/repos/base-hw/src/bootstrap/spec/arm/cortex_a9_mmu.cc index ce339dc99..3dece9e7e 100644 --- a/repos/base-hw/src/bootstrap/spec/arm/cortex_a9_mmu.cc +++ b/repos/base-hw/src/bootstrap/spec/arm/cortex_a9_mmu.cc @@ -175,6 +175,7 @@ unsigned Bootstrap::Platform::enable_mmu() /* wait for other cores' coherency activation */ smp_coherency_enabled.wait_for(NR_OF_CPUS); - Cpu::synchronization_barrier(); + asm volatile("dsb sy\n" + "isb sy\n" ::: "memory"); return Cpu::Mpidr::Aff_0::get(Cpu::Mpidr::read()); } diff --git a/repos/base-hw/src/core/spec/arm/cpu.cc b/repos/base-hw/src/core/spec/arm/cpu.cc index 58968ea5d..4d2201961 100644 --- a/repos/base-hw/src/core/spec/arm/cpu.cc +++ b/repos/base-hw/src/core/spec/arm/cpu.cc @@ -83,3 +83,24 @@ void Arm_cpu::mmu_fault_status(Fsr::access_t fsr, Thread_fault & fault) default: fault.type = Thread_fault::UNKNOWN; }; } + + +void Arm_cpu::switch_to(Arm_cpu::Context&, Arm_cpu::Mmu_context & o) +{ + if (o.cidr == 0) return; + + Cidr::access_t cidr = Cidr::read(); + if (cidr != o.cidr) { + /** + * First switch to global mappings only to prevent + * that wrong branch predicts result due to ASID + * and Page-Table not being in sync (see ARM RM B 3.10.4) + */ + Cidr::write(0); + Cpu::synchronization_barrier(); + Ttbr0::write(o.ttbr0); + Cpu::synchronization_barrier(); + Cidr::write(o.cidr); + Cpu::synchronization_barrier(); + } +} diff --git a/repos/base-hw/src/core/spec/arm/cpu_support.h b/repos/base-hw/src/core/spec/arm/cpu_support.h index 18a55e7da..6aad17e86 100644 --- a/repos/base-hw/src/core/spec/arm/cpu_support.h +++ b/repos/base-hw/src/core/spec/arm/cpu_support.h @@ -110,16 +110,7 @@ struct Genode::Arm_cpu : public Hw::Arm_cpu else Tlbiall::write(0); } - void switch_to(Context&, Mmu_context & o) - { - if (o.cidr == 0) return; - - Cidr::access_t cidr = Cidr::read(); - if (cidr != o.cidr) { - Cidr::write(o.cidr); - Ttbr0::write(o.ttbr0); - } - } + void switch_to(Context&, Mmu_context & o); static void mmu_fault(Context & c, Kernel::Thread_fault & fault); static void mmu_fault_status(Fsr::access_t fsr, diff --git a/repos/base-hw/src/core/spec/arm/exception_vector.s b/repos/base-hw/src/core/spec/arm/exception_vector.S similarity index 95% rename from repos/base-hw/src/core/spec/arm/exception_vector.s rename to repos/base-hw/src/core/spec/arm/exception_vector.S index 440db4ae6..3a7d9b6e4 100644 --- a/repos/base-hw/src/core/spec/arm/exception_vector.s +++ b/repos/base-hw/src/core/spec/arm/exception_vector.S @@ -12,6 +12,7 @@ * under the terms of the GNU Affero General Public License version 3. */ +#include /********************* ** Constant values ** @@ -123,6 +124,8 @@ ldr r1, [r1] blx r1 + SYSTEM_REGISTER_SYNC_BARRIER /* synchronize after the context switch */ + /* * Go to kernel entry code */ @@ -164,4 +167,5 @@ ldr r1, [sp, #16*4] msr spsr_cxsf, r1 ldm sp, {r0-r14}^ + SYSTEM_REGISTER_SYNC_BARRIER /* synchronize after the context switch */ subs pc, lr, #0 diff --git a/repos/base-hw/src/core/spec/arm_v6/cpu.h b/repos/base-hw/src/core/spec/arm_v6/cpu.h index 4a8cad82e..dfa3377c0 100644 --- a/repos/base-hw/src/core/spec/arm_v6/cpu.h +++ b/repos/base-hw/src/core/spec/arm_v6/cpu.h @@ -18,6 +18,11 @@ /* core includes */ #include -namespace Genode { using Cpu = Arm_cpu; } +namespace Genode { struct Cpu; } + +struct Genode::Cpu : Arm_cpu +{ + static inline void synchronization_barrier() {} +}; #endif /* _CORE__SPEC__ARM_V6__CPU_H_ */ diff --git a/repos/base-hw/src/core/spec/arm_v6/synchronize.s b/repos/base-hw/src/core/spec/arm_v6/synchronize.s new file mode 100644 index 000000000..cee4792d4 --- /dev/null +++ b/repos/base-hw/src/core/spec/arm_v6/synchronize.s @@ -0,0 +1,15 @@ +/* + * \brief Assembler macros for ARMv6 + * \author Stefan Kalkowski + * \date 2020-02-16 + */ + +/* + * Copyright (C) 2020 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +.macro SYSTEM_REGISTER_SYNC_BARRIER +.endm diff --git a/repos/base-hw/src/core/spec/arm_v7/cpu_support.h b/repos/base-hw/src/core/spec/arm_v7/cpu_support.h index aaf6cddde..a08a515c1 100644 --- a/repos/base-hw/src/core/spec/arm_v7/cpu_support.h +++ b/repos/base-hw/src/core/spec/arm_v7/cpu_support.h @@ -41,6 +41,12 @@ struct Genode::Arm_v7_cpu : Arm_cpu else Tlbiallis::write(0); } else Arm_cpu::invalidate_tlb(asid); } + + static inline void synchronization_barrier() + { + asm volatile("dsb sy\n" + "isb sy\n" ::: "memory"); + } }; #endif /* _CORE__SPEC__ARM_V7__CPU_SUPPORT_H_ */ diff --git a/repos/base-hw/src/core/spec/arm_v7/synchronize.s b/repos/base-hw/src/core/spec/arm_v7/synchronize.s new file mode 100644 index 000000000..04cff0fcf --- /dev/null +++ b/repos/base-hw/src/core/spec/arm_v7/synchronize.s @@ -0,0 +1,17 @@ +/* + * \brief Assembler macros for ARMv7 + * \author Stefan Kalkowski + * \date 2020-02-16 + */ + +/* + * Copyright (C) 2020 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +.macro SYSTEM_REGISTER_SYNC_BARRIER + dsb sy + isb sy +.endm diff --git a/repos/base-hw/src/include/hw/spec/arm/cpu.h b/repos/base-hw/src/include/hw/spec/arm/cpu.h index 3773cf309..55d897a7b 100644 --- a/repos/base-hw/src/include/hw/spec/arm/cpu.h +++ b/repos/base-hw/src/include/hw/spec/arm/cpu.h @@ -286,12 +286,6 @@ struct Hw::Arm_cpu ** Cache maintainance functions ** **********************************/ - static inline void synchronization_barrier() - { - asm volatile("dsb\n" - "isb\n"); - } - static inline void wait_for_xchg(volatile void * addr, unsigned long new_value, unsigned long expected_value)