Brad Bishop | bec4ebc | 2022-08-03 09:55:16 -0400 | [diff] [blame] | 1 | From 0f15f6b02825b042ddc1d753f62cf87f30b1fe12 Mon Sep 17 00:00:00 2001 |
| 2 | From: Peter Hoyes <Peter.Hoyes@arm.com> |
| 3 | Date: Thu, 19 May 2022 09:02:32 +0100 |
| 4 | Subject: [PATCH 9/9] armv8: Enable icache when switching exception levels in |
| 5 | bootefi |
| 6 | |
| 7 | bootefi calls the function switch_to_non_secure_mode before calling the |
| 8 | UEFI payload to handle the case where U-Boot is running at EL3. |
| 9 | |
| 10 | For AArch64, the UEFI specification states that: |
| 11 | The core will be configured as follows: |
| 12 | * MMU enabled |
| 13 | * Instruction and data caches enabled |
| 14 | |
| 15 | These requirements should be followed when switching exception levels |
| 16 | for EFI applications. |
| 17 | |
| 18 | This function already disables and re-enables the data cache prior to |
| 19 | switching exception levels, but omits the instruction cache, meaning |
| 20 | the function returns with the instruction cache disabled at the new |
| 21 | exception level. Fix this by calling icache_disable prior to switching |
| 22 | exception levels and icache_enable afterwards. |
| 23 | |
| 24 | Issue-Id: SCM-4641 |
| 25 | Signed-off-by: Peter Hoyes <Peter.Hoyes@arm.com> |
| 26 | Upstream-Status: Inappropriate [other] |
| 27 | Implementation pending further discussion |
| 28 | Change-Id: I678cd5ba39b56e124ab7854608289cd14651ce65 |
| 29 | --- |
| 30 | arch/arm/cpu/armv8/exception_level.c | 3 +++ |
| 31 | 1 file changed, 3 insertions(+) |
| 32 | |
| 33 | diff --git a/arch/arm/cpu/armv8/exception_level.c b/arch/arm/cpu/armv8/exception_level.c |
| 34 | index 4aad1550f4..0a3e5428e7 100644 |
| 35 | --- a/arch/arm/cpu/armv8/exception_level.c |
| 36 | +++ b/arch/arm/cpu/armv8/exception_level.c |
| 37 | @@ -27,6 +27,7 @@ |
| 38 | static void entry_non_secure(struct jmp_buf_data *non_secure_jmp) |
| 39 | { |
| 40 | dcache_enable(); |
| 41 | + icache_enable(); |
| 42 | debug("Reached non-secure mode\n"); |
| 43 | |
| 44 | /* Restore stack and registers saved in switch_to_non_secure_mode() */ |
| 45 | @@ -61,6 +62,7 @@ void switch_to_non_secure_mode(void) |
| 46 | if (setjmp(&non_secure_jmp)) |
| 47 | return; |
| 48 | dcache_disable(); /* flush cache before switch to EL2 */ |
| 49 | + icache_disable(); |
| 50 | /* Move into EL2 and keep running there */ |
| 51 | armv8_switch_to_el2((uintptr_t)&non_secure_jmp, 0, 0, 0, |
| 52 | (uintptr_t)entry_non_secure, ES_TO_AARCH64); |
| 53 | @@ -68,6 +70,7 @@ void switch_to_non_secure_mode(void) |
| 54 | if (setjmp(&non_secure_jmp)) |
| 55 | return; |
| 56 | dcache_disable(); /* flush cache before switch to EL1 */ |
| 57 | + icache_disable(); |
| 58 | /* Move into EL1 and keep running there */ |
| 59 | armv8_switch_to_el1((uintptr_t)&non_secure_jmp, 0, 0, 0, |
| 60 | (uintptr_t)entry_non_secure, ES_TO_AARCH64); |
| 61 | -- |
| 62 | 2.25.1 |
| 63 | |