efi/arm64: Preserve FP/SIMD registers on UEFI runtime services calls
According to the UEFI spec section 2.3.6.4, the use of FP/SIMD instructions is allowed, and should adhere to the AAPCS64 calling convention, which states that 'only the bottom 64 bits of each value stored in registers v8-v15 need to be preserved' (section 5.1.2). This applies equally to UEFI Runtime Services called by the kernel, so make sure the FP/SIMD register file is preserved in this case. We do this by enabling the wrappers for UEFI Runtime Services (CONFIG_EFI_RUNTIME_WRAPPERS) and inserting calls to kernel_neon_begin()and kernel_neon_end() into these wrappers. Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Acked-by: Catalin Marinas <catalin.marinas@arm.com> Signed-off-by: Matt Fleming <matt.fleming@intel.com>
This commit is contained in:
Родитель
022ee6c558
Коммит
e15dd4949a
|
@ -298,6 +298,7 @@ config EFI
|
|||
select LIBFDT
|
||||
select UCS2_STRING
|
||||
select EFI_PARAMS_FROM_FDT
|
||||
select EFI_RUNTIME_WRAPPERS
|
||||
default y
|
||||
help
|
||||
This option provides support for runtime services provided
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define _ASM_EFI_H
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/neon.h>
|
||||
|
||||
#ifdef CONFIG_EFI
|
||||
extern void efi_init(void);
|
||||
|
@ -11,4 +12,24 @@ extern void efi_idmap_init(void);
|
|||
#define efi_idmap_init()
|
||||
#endif
|
||||
|
||||
#define efi_call_virt(f, ...) \
|
||||
({ \
|
||||
efi_##f##_t *__f = efi.systab->runtime->f; \
|
||||
efi_status_t __s; \
|
||||
\
|
||||
kernel_neon_begin(); \
|
||||
__s = __f(__VA_ARGS__); \
|
||||
kernel_neon_end(); \
|
||||
__s; \
|
||||
})
|
||||
|
||||
#define __efi_call_virt(f, ...) \
|
||||
({ \
|
||||
efi_##f##_t *__f = efi.systab->runtime->f; \
|
||||
\
|
||||
kernel_neon_begin(); \
|
||||
__f(__VA_ARGS__); \
|
||||
kernel_neon_end(); \
|
||||
})
|
||||
|
||||
#endif /* _ASM_EFI_H */
|
||||
|
|
|
@ -449,19 +449,7 @@ static int __init arm64_enter_virtual_mode(void)
|
|||
|
||||
/* Set up runtime services function pointers */
|
||||
runtime = efi.systab->runtime;
|
||||
efi.get_time = runtime->get_time;
|
||||
efi.set_time = runtime->set_time;
|
||||
efi.get_wakeup_time = runtime->get_wakeup_time;
|
||||
efi.set_wakeup_time = runtime->set_wakeup_time;
|
||||
efi.get_variable = runtime->get_variable;
|
||||
efi.get_next_variable = runtime->get_next_variable;
|
||||
efi.set_variable = runtime->set_variable;
|
||||
efi.query_variable_info = runtime->query_variable_info;
|
||||
efi.update_capsule = runtime->update_capsule;
|
||||
efi.query_capsule_caps = runtime->query_capsule_caps;
|
||||
efi.get_next_high_mono_count = runtime->get_next_high_mono_count;
|
||||
efi.reset_system = runtime->reset_system;
|
||||
|
||||
efi_native_runtime_setup();
|
||||
set_bit(EFI_RUNTIME_SERVICES, &efi.flags);
|
||||
|
||||
return 0;
|
||||
|
|
Загрузка…
Ссылка в новой задаче