diff options
author | Heinrich Schuchardt <xypron.glpk@gmx.de> | 2018-10-18 12:29:40 +0200 |
---|---|---|
committer | Alexander Graf <agraf@suse.de> | 2018-12-02 21:59:37 +0100 |
commit | 81ea00838c682da06637bcf208549095181df337 (patch) | |
tree | 34fae16c5c4252c09835e63f605e4be9614a24e7 /arch/arm/cpu | |
parent | eb3bc8bb177e8b19464529826acad5ec0d0edb61 (diff) |
efi_loader: PSCI reset and shutdown
When an operating system started via bootefi tries to reset or power off
this is done by calling the EFI runtime ResetSystem(). On most ARMv8 system
the actual reset relies on PSCI. Depending on whether the PSCI firmware
resides the hypervisor (EL2) or in the secure monitor (EL3) either an HVC
or an SMC command has to be issued.
The current implementation always uses SMC. This results in crashes on
systems where the PSCI firmware is implemented in the hypervisor, e.g.
qemu-arm64_defconfig.
The logic to decide which call is needed based on the device tree is
already implemented in the PSCI firmware driver. During the EFI runtime
the device driver model is not available. But we can minimize code
duplication by merging the EFI runtime reset and poweroff code with
the PSCI firmware driver.
As the same HVC/SMC problem is also evident for the ARMv8 do_poweroff
and reset_misc routines let's move them into the same code module.
Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Reviewed-by: Sumit Garg <sumit.garg@linaro.org>
Tested-by: Sumit Garg <sumit.garg@linaro.org>
Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'arch/arm/cpu')
-rw-r--r-- | arch/arm/cpu/armv7/smccc-call.S | 2 | ||||
-rw-r--r-- | arch/arm/cpu/armv8/Kconfig | 1 | ||||
-rw-r--r-- | arch/arm/cpu/armv8/fwcall.c | 52 | ||||
-rw-r--r-- | arch/arm/cpu/armv8/smccc-call.S | 2 |
4 files changed, 10 insertions, 47 deletions
diff --git a/arch/arm/cpu/armv7/smccc-call.S b/arch/arm/cpu/armv7/smccc-call.S index 0d8b59eb6b..eae69e36c3 100644 --- a/arch/arm/cpu/armv7/smccc-call.S +++ b/arch/arm/cpu/armv7/smccc-call.S @@ -7,6 +7,8 @@ #include <asm/opcodes-sec.h> #include <asm/opcodes-virt.h> + .section .text.efi_runtime + #define UNWIND(x...) /* * Wrap c macros in asm macros to delay expansion until after the diff --git a/arch/arm/cpu/armv8/Kconfig b/arch/arm/cpu/armv8/Kconfig index ff42791fb4..1c12bbde75 100644 --- a/arch/arm/cpu/armv8/Kconfig +++ b/arch/arm/cpu/armv8/Kconfig @@ -96,6 +96,7 @@ endmenu config PSCI_RESET bool "Use PSCI for reset and shutdown" default y + select ARM_SMCCC if OF_CONTROL depends on !ARCH_EXYNOS7 && !ARCH_BCM283X && \ !TARGET_LS2080A_SIMU && !TARGET_LS2080AQDS && \ !TARGET_LS2080ARDB && !TARGET_LS2080A_EMU && \ diff --git a/arch/arm/cpu/armv8/fwcall.c b/arch/arm/cpu/armv8/fwcall.c index 0ba3dad8cc..9957c2974b 100644 --- a/arch/arm/cpu/armv8/fwcall.c +++ b/arch/arm/cpu/armv8/fwcall.c @@ -7,7 +7,6 @@ #include <asm-offsets.h> #include <config.h> -#include <efi_loader.h> #include <version.h> #include <asm/macro.h> #include <asm/psci.h> @@ -19,7 +18,7 @@ * x0~x7: input arguments * x0~x3: output arguments */ -static void __efi_runtime hvc_call(struct pt_regs *args) +static void hvc_call(struct pt_regs *args) { asm volatile( "ldr x0, %0\n" @@ -53,7 +52,7 @@ static void __efi_runtime hvc_call(struct pt_regs *args) * x0~x3: output arguments */ -void __efi_runtime smc_call(struct pt_regs *args) +void smc_call(struct pt_regs *args) { asm volatile( "ldr x0, %0\n" @@ -83,9 +82,9 @@ void __efi_runtime smc_call(struct pt_regs *args) * use PSCI on U-Boot running below a hypervisor, please detect * this and set the flag accordingly. */ -static const __efi_runtime_data bool use_smc_for_psci = true; +static const bool use_smc_for_psci = true; -void __noreturn __efi_runtime psci_system_reset(void) +void __noreturn psci_system_reset(void) { struct pt_regs regs; @@ -100,7 +99,7 @@ void __noreturn __efi_runtime psci_system_reset(void) ; } -void __noreturn __efi_runtime psci_system_off(void) +void __noreturn psci_system_off(void) { struct pt_regs regs; @@ -114,44 +113,3 @@ void __noreturn __efi_runtime psci_system_off(void) while (1) ; } - -#ifdef CONFIG_CMD_POWEROFF -int do_poweroff(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - puts("poweroff ...\n"); - - udelay(50000); /* wait 50 ms */ - - disable_interrupts(); - - psci_system_off(); - - /*NOTREACHED*/ - return 0; -} -#endif - -#ifdef CONFIG_PSCI_RESET -void reset_misc(void) -{ - psci_system_reset(); -} - -#ifdef CONFIG_EFI_LOADER -void __efi_runtime EFIAPI efi_reset_system( - enum efi_reset_type reset_type, - efi_status_t reset_status, - unsigned long data_size, void *reset_data) -{ - if (reset_type == EFI_RESET_COLD || - reset_type == EFI_RESET_WARM || - reset_type == EFI_RESET_PLATFORM_SPECIFIC) { - psci_system_reset(); - } else if (reset_type == EFI_RESET_SHUTDOWN) { - psci_system_off(); - } - - while (1) { } -} -#endif /* CONFIG_EFI_LOADER */ -#endif /* CONFIG_PSCI_RESET */ diff --git a/arch/arm/cpu/armv8/smccc-call.S b/arch/arm/cpu/armv8/smccc-call.S index 16c9e298b4..86de4b4089 100644 --- a/arch/arm/cpu/armv8/smccc-call.S +++ b/arch/arm/cpu/armv8/smccc-call.S @@ -6,6 +6,8 @@ #include <linux/arm-smccc.h> #include <generated/asm-offsets.h> + .section .text.efi_runtime + .macro SMCCC instr .cfi_startproc \instr #0 |