From dfc04c22615f053f3cd30c6dfecb9bf17e2e39d8 Mon Sep 17 00:00:00 2001 From: Julia Vassiliki Date: Wed, 18 Mar 2026 16:59:53 +1100 Subject: [PATCH] loader: synchronise ARM system register writes System registers (but not special-purpose registers) require explicit synchronisation, as per D24.1.2.2 'Synchronization requirements for AArch64 System registers' (DDI0487 L.b) Signed-off-by: Julia Vassiliki --- loader/src/aarch64/el.c | 2 ++ loader/src/aarch64/exceptions.c | 2 ++ loader/src/aarch64/init.c | 1 + loader/src/aarch64/util64.S | 9 +++++++++ 4 files changed, 14 insertions(+) diff --git a/loader/src/aarch64/el.c b/loader/src/aarch64/el.c index 811ea0d3e..23f5c3e2b 100644 --- a/loader/src/aarch64/el.c +++ b/loader/src/aarch64/el.c @@ -54,12 +54,14 @@ int ensure_correct_el(int logical_cpu) } else { LDR_PRINT("INFO", logical_cpu, "Resetting CNTVOFF\n"); asm volatile("msr cntvoff_el2, xzr"); + asm volatile("isb" ::: "memory"); } } else { if (el == EL2) { /* seL4 relies on the timer to be set to a useful value */ LDR_PRINT("INFO", logical_cpu, "Resetting CNTVOFF\n"); asm volatile("msr cntvoff_el2, xzr"); + asm volatile("isb" ::: "memory"); LDR_PRINT("INFO", logical_cpu, "Dropping from EL2 to EL1\n"); switch_to_el1(); LDR_PRINT("INFO", logical_cpu, "CurrentEL="); diff --git a/loader/src/aarch64/exceptions.c b/loader/src/aarch64/exceptions.c index 160a84de9..7fe83d298 100644 --- a/loader/src/aarch64/exceptions.c +++ b/loader/src/aarch64/exceptions.c @@ -29,6 +29,8 @@ void arch_set_exception_handler(void) if (el != EL0) { asm volatile("msr vbar_el1, %0" :: "r"(arm_vector_table)); } + + asm volatile("isb" ::: "memory"); } uintptr_t exception_register_state[32]; diff --git a/loader/src/aarch64/init.c b/loader/src/aarch64/init.c index 568bfba15..7eafef432 100644 --- a/loader/src/aarch64/init.c +++ b/loader/src/aarch64/init.c @@ -138,6 +138,7 @@ void arch_jump_to_kernel(int logical_cpu) { /* seL4 always expects the current logical CPU number in TPIDR_EL1 */ asm volatile("msr TPIDR_EL1, %0" :: "r"(logical_cpu)); + asm volatile("isb" ::: "memory"); ((sel4_entry)(loader_data->kernel_entry))( loader_data->ui_p_reg_start, diff --git a/loader/src/aarch64/util64.S b/loader/src/aarch64/util64.S index 8aabe46d4..cb098715d 100644 --- a/loader/src/aarch64/util64.S +++ b/loader/src/aarch64/util64.S @@ -249,6 +249,10 @@ BEGIN_FUNC(switch_to_el1) /* set ELR so that it's possible to perform ERET */ msr elr_el2, x30 + + /* ELR_EL2, SP_EL1, and SPSR_EL2 are all special-purpose registers and do + * not require explicit synchronisation (DDI0487 L.b, section C5.2). + */ eret END_FUNC(switch_to_el1) @@ -261,6 +265,7 @@ BEGIN_FUNC(switch_to_el2) * NS => run as non-secure */ mov x9, #(SCR_RW_BIT | SCR_SMD_BIT | SCR_RES_BITS | SCR_NS_BIT) + /* ERET performs the 'Context Synchronisation Event' */ msr scr_el3, x9 /* Set SPSR for EL3 @@ -274,6 +279,10 @@ BEGIN_FUNC(switch_to_el2) /* set ELR so RET returns to caller */ msr elr_el3, x30 + + /* ELR_EL3, SP_EL2, and SPSR_EL3 are all special-purpose registers and do + * not require explicit synchronisation (DDI0487 L.b, section C5.2). + */ eret END_FUNC(switch_to_el2)