diff options
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/cpu/armv8/sec_firmware_asm.S | 23 | ||||
-rw-r--r-- | arch/arm/cpu/armv8/transition.S | 12 | ||||
-rw-r--r-- | arch/arm/include/asm/system.h | 2 |
3 files changed, 37 insertions, 0 deletions
diff --git a/arch/arm/cpu/armv8/sec_firmware_asm.S b/arch/arm/cpu/armv8/sec_firmware_asm.S index 0c6a462..1b39f1d 100644 --- a/arch/arm/cpu/armv8/sec_firmware_asm.S +++ b/arch/arm/cpu/armv8/sec_firmware_asm.S @@ -50,4 +50,27 @@ ENTRY(_sec_firmware_support_psci_version) smc #0 ret ENDPROC(_sec_firmware_support_psci_version) + +/* + * Switch from AArch64 EL2 to AArch32 EL2 + * @param inputs: + * x0: argument, zero + * x1: machine nr + * x2: fdt address + * x3: kernel entry point + * @param outputs for secure firmware: + * x0: function id + * x1: kernel entry point + * x2: machine nr + * x3: fdt address +*/ +ENTRY(armv8_el2_to_aarch32) + mov x0, x3 + mov x3, x2 + mov x2, x1 + mov x1, x0 + ldr x0, =0xc000ff04 + smc #0 + ret +ENDPROC(armv8_el2_to_aarch32) #endif diff --git a/arch/arm/cpu/armv8/transition.S b/arch/arm/cpu/armv8/transition.S index bbccf2b..adb9f35 100644 --- a/arch/arm/cpu/armv8/transition.S +++ b/arch/arm/cpu/armv8/transition.S @@ -13,6 +13,14 @@ ENTRY(armv8_switch_to_el2) switch_el x5, 1f, 0f, 0f 0: + cmp x4, #ES_TO_AARCH64 + b.eq 2f + /* + * When loading 32-bit kernel, it will jump + * to secure firmware again, and never return. + */ + bl armv8_el2_to_aarch32 +2: /* * x3 is kernel entry point or switch_to_el1 * if CONFIG_ARMV8_SWITCH_TO_EL1 is defined. @@ -32,3 +40,7 @@ ENTRY(armv8_switch_to_el1) br x3 1: armv8_switch_to_el1_m x3, x4, x5 ENDPROC(armv8_switch_to_el1) + +WEAK(armv8_el2_to_aarch32) + ret +ENDPROC(armv8_el2_to_aarch32) diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h index 287ff5c..01efc43 100644 --- a/arch/arm/include/asm/system.h +++ b/arch/arm/include/asm/system.h @@ -215,6 +215,8 @@ void armv8_switch_to_el2(u64 args, u64 mach_nr, u64 fdt_addr, */ void armv8_switch_to_el1(u64 args, u64 mach_nr, u64 fdt_addr, u64 entry_point, u64 es_flag); +void armv8_el2_to_aarch32(u64 args, u64 mach_nr, u64 fdt_addr, + u64 entry_point); void gic_init(void); void gic_send_sgi(unsigned long sgino); void wait_for_wakeup(void); |