From c5d244956ea4c3304105556d0827bbea83264c50 Mon Sep 17 00:00:00 2001 From: Mikhail Krichanov <mikhailkrichanov@gmail.com> Date: Thu, 23 May 2024 20:46:54 +0300 Subject: [PATCH] Ring3: Defined SysCallReturnToCore for AARCH64, forbade ExceptionHanlders to use EL0 stack. --- .../AArch64/ExceptionSupport.S | 27 ++--------------- .../Dxe/SysCall/AARCH64/CoreBootServices.S | 30 +++++++++++++++---- .../Core/Dxe/SysCall/AARCH64/InitializeMsr.c | 8 +++-- MdeModulePkg/Core/Dxe/SysCall/BootServices.c | 13 ++++++++ 4 files changed, 47 insertions(+), 31 deletions(-) diff --git a/ArmPkg/Library/ArmExceptionLib/AArch64/ExceptionSupport.S b/ArmPkg/Library/ArmExceptionLib/AArch64/ExceptionSupport.S index aeb1475075..fbdccb921a 100644 --- a/ArmPkg/Library/ArmExceptionLib/AArch64/ExceptionSupport.S +++ b/ArmPkg/Library/ArmExceptionLib/AArch64/ExceptionSupport.S @@ -116,23 +116,7 @@ ASM_PFX(ExceptionHandlersStart): VECTOR_BASE(ExceptionHandlersStart) #endif - .macro ExceptionEntry, val, sp=SPx - // - // Our backtrace and register dump code is written in C and so it requires - // a stack. This makes it difficult to produce meaningful diagnostics when - // the stack pointer has been corrupted. So in such cases (i.e., when taking - // synchronous exceptions), this macro is expanded with \sp set to SP0, in - // which case we switch to the SP_EL0 stack pointer, which has been - // initialized to point to a buffer that has been set aside for this purpose. - // - // Since 'sp' may no longer refer to the stack frame that was active when - // the exception was taken, we may have to switch back and forth between - // SP_EL0 and SP_ELx to record the correct value for SP in the context struct. - // - .ifnc \sp, SPx - msr SPsel, xzr - .endif - + .macro ExceptionEntry, val // Move the stackpointer so we can reach our structure with the str instruction. sub sp, sp, #(FP_CONTEXT_SIZE + SYS_CONTEXT_SIZE) @@ -154,13 +138,7 @@ VECTOR_BASE(ExceptionHandlersStart) stp x28, x29, [sp, #0xe0] add x28, sp, #(GP_CONTEXT_SIZE + FP_CONTEXT_SIZE + SYS_CONTEXT_SIZE) - .ifnc \sp, SPx - msr SPsel, #1 - mov x7, sp - msr SPsel, xzr - .else mov x7, x28 - .endif stp x30, x7, [sp, #0xf0] @@ -201,7 +179,7 @@ ASM_PFX(SErrorSP0): // VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_CUR_SPX_SYNC) ASM_PFX(SynchronousExceptionSPx): - ExceptionEntry EXCEPT_AARCH64_SYNCHRONOUS_EXCEPTIONS, SP0 + ExceptionEntry EXCEPT_AARCH64_SYNCHRONOUS_EXCEPTIONS VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_CUR_SPX_IRQ) ASM_PFX(IrqSPx): @@ -343,6 +321,7 @@ ASM_PFX(CommonExceptionEntry): b continue is_SVC: ldr x1, [sp, #0x8] + add sp, sp, #0xe0 continue: // Pop FP regs from Stack. diff --git a/MdeModulePkg/Core/Dxe/SysCall/AARCH64/CoreBootServices.S b/MdeModulePkg/Core/Dxe/SysCall/AARCH64/CoreBootServices.S index b6eef51714..c6cc39d265 100644 --- a/MdeModulePkg/Core/Dxe/SysCall/AARCH64/CoreBootServices.S +++ b/MdeModulePkg/Core/Dxe/SysCall/AARCH64/CoreBootServices.S @@ -30,18 +30,22 @@ ASM_FUNC(CallInstallMultipleProtocolInterfaces) // (x0) Data // (x1) gRing3CallStackTop // (x2) gRing3EntryPoint +// (x3) gCoreSysCallStackTop +// (x4) &CoreSp //------------------------------------------------------------------------------ ASM_FUNC(ArmCallRing3) + // Save FP and LR on Core Stack. + stp x29, x30, [sp, #-0x10]! // Disable interrupts msr daifset, #0xf isb - - // Use SP_ELx for Exception level ELx. - msr SPsel, #1 - + // Prepare Ring3 SP and EntryPoint. msr sp_el0, x1 - msr elr_el1, x2 + // Save Core SP and switch to Ring3Call Stack. + mov x5, sp + str x5, [x4] + mov sp, x3 // Copy PSTATE to SPSR. mrs x1, nzcv @@ -61,3 +65,19 @@ ASM_FUNC(ArmCallRing3) dsb sy eret + +//------------------------------------------------------------------------------ +// VOID +// EFIAPI +// ReturnToCore ( +// IN EFI_STATUS Status, +// IN UINTN CoreSp +// ); +//------------------------------------------------------------------------------ +ASM_FUNC(ReturnToCore) + // Switch to Core Stack. + mov sp, x1 + // Restore Stack. + ldp x29, x30, [sp] + add sp, sp, #0x10 + ret diff --git a/MdeModulePkg/Core/Dxe/SysCall/AARCH64/InitializeMsr.c b/MdeModulePkg/Core/Dxe/SysCall/AARCH64/InitializeMsr.c index 0510fc5957..6db895d8de 100644 --- a/MdeModulePkg/Core/Dxe/SysCall/AARCH64/InitializeMsr.c +++ b/MdeModulePkg/Core/Dxe/SysCall/AARCH64/InitializeMsr.c @@ -10,12 +10,16 @@ #include "DxeMain.h" +extern UINTN CoreSp; + EFI_STATUS EFIAPI ArmCallRing3 ( IN RING3_CALL_DATA *Data, IN VOID *StackPointer, - IN VOID *EntryPoint + IN VOID *EntryPoint, + IN VOID *SysCallStack, + IN VOID *CoreStack ); VOID @@ -74,5 +78,5 @@ CallRing3 ( IN RING3_CALL_DATA *Data ) { - return ArmCallRing3 (Data, gRing3CallStackTop, gRing3EntryPoint); + return ArmCallRing3 (Data, gRing3CallStackTop, gRing3EntryPoint, gCoreSysCallStackTop, &CoreSp); } diff --git a/MdeModulePkg/Core/Dxe/SysCall/BootServices.c b/MdeModulePkg/Core/Dxe/SysCall/BootServices.c index 508fe4fba6..061ac97855 100644 --- a/MdeModulePkg/Core/Dxe/SysCall/BootServices.c +++ b/MdeModulePkg/Core/Dxe/SysCall/BootServices.c @@ -8,6 +8,8 @@ #include "DxeMain.h" #include "SupportedProtocols.h" +UINTN CoreSp; + LIST_ENTRY mProtocolsHead = INITIALIZE_LIST_HEAD_VARIABLE (mProtocolsHead); typedef struct { @@ -65,6 +67,13 @@ CallInstallMultipleProtocolInterfaces ( IN VOID *Function ); +VOID +EFIAPI +ReturnToCore ( + IN EFI_STATUS Status, + IN UINTN CoreSp + ); + VOID EFIAPI FreeProtocolsList ( @@ -1403,6 +1412,10 @@ SysCallBootService ( EFI_STATUS Status; EFI_PHYSICAL_ADDRESS Physical; + if (Type == SysCallReturnToCore) { + ReturnToCore (*(EFI_STATUS *)CoreRbp, CoreSp); + } + Status = CoreAllocatePages ( AllocateAnyPages, EfiRing3MemoryType,