From c7f3cc037bc727fd868262134a543ffddba472cf Mon Sep 17 00:00:00 2001 From: Mikhail Krichanov Date: Sat, 14 Dec 2024 20:26:20 +0300 Subject: [PATCH] Ring3: Added support for AARCH64 User page table. --- .../AArch64/ExceptionSupport.S | 59 +++++++++++++++++++ .../Library/ArmExceptionLib/ArmExceptionLib.c | 42 +++++++++++++ .../Dxe/SysCall/AARCH64/CoreBootServices.S | 17 ++++-- .../Dxe/SysCall/AARCH64/InitializeAARCH64.c | 28 ++------- .../Core/Dxe/SysCall/Initialization.c | 48 +++++++++------ .../Core/Dxe/SysCall/SupportedProtocols.c | 24 -------- 6 files changed, 150 insertions(+), 68 deletions(-) diff --git a/ArmPkg/Library/ArmExceptionLib/AArch64/ExceptionSupport.S b/ArmPkg/Library/ArmExceptionLib/AArch64/ExceptionSupport.S index 06a32d20ca..e76a55d642 100644 --- a/ArmPkg/Library/ArmExceptionLib/AArch64/ExceptionSupport.S +++ b/ArmPkg/Library/ArmExceptionLib/AArch64/ExceptionSupport.S @@ -101,6 +101,8 @@ GCC_ASM_EXPORT(CommonCExceptionHandler) #define FP_CONTEXT_SIZE (32 * 16) #define SYS_CONTEXT_SIZE ( 6 * 8) // 5 SYS regs + Alignment requirement (ie: the stack must be aligned on 0x10) +ASM_FUNC_ALIGN(ExceptionHandlerBase, 4096) + // // There are two methods for installing AArch64 exception vectors: // 1. Install a copy of the vectors to a location specified by a PCD @@ -237,6 +239,26 @@ ASM_PFX(ExceptionHandlersEnd): ASM_PFX(CommonExceptionEntry): + adrp x1, ASM_PFX(CorePageTable) + ldr x2, [x1, #0x10] // mSwitchTTBR0Flag + cmp x2, 0 + b.eq NoTTBR0Switch + EL1_OR_EL2(x3) +1:mrs x4, ttbr0_el1 + str x4, [x1, #0x8] // UserPageTable + ldr x4, [x1] // CorePageTable + msr ttbr0_el1, x4 + tlbi vmalle1 + b 3f +2:mrs x4, ttbr0_el2 + str x4, [x1, #0x8] // UserPageTable + ldr x4, [x1] // CorePageTable + msr ttbr0_el2, x4 + tlbi alle2 +3:dsb sy + isb + +NoTTBR0Switch: EL1_OR_EL2_OR_EL3(x1) 1:mrs x2, elr_el1 // Exception Link Register @@ -296,6 +318,23 @@ ASM_PFX(CommonExceptionEntry): // We do not try to recover. bl ASM_PFX(CommonCExceptionHandler) // Call exception handler + adrp x1, ASM_PFX(CorePageTable) + ldr x2, [x1, #0x10] // mSwitchTTBR0Flag + cmp x2, 0 + b.eq NoTTBR0Switch2 + EL1_OR_EL2(x3) +1:ldr x4, [x1, #0x8] // UserPageTable + msr ttbr0_el1, x4 + tlbi vmalle1 + b 3f +2:ldr x4, [x1, #0x8] // UserPageTable + msr ttbr0_el2, x4 + tlbi alle2 +3:dsb sy + isb + +NoTTBR0Switch2: + // Pop as many GP regs as we can before entering the critical section below ldp x2, x3, [sp, #0x10] ldp x4, x5, [sp, #0x20] @@ -376,6 +415,26 @@ continue: eret +ASM_FUNC_ALIGN(ExceptionHandlerFinal, 4096) + ASM_FUNC(RegisterEl0Stack) msr sp_el0, x0 ret + +.data + +.global ASM_PFX(CorePageTable) +.balign 4096 +ASM_PFX(CorePageTable): +.ds.d 1 + +UserPageTable: +.ds.d 1 + +.global ASM_PFX(mSwitchTTBR0Flag) +ASM_PFX(mSwitchTTBR0Flag): +.ds.b 1 + +.balign 4096 +Padding: +.ds.b 1 diff --git a/ArmPkg/Library/ArmExceptionLib/ArmExceptionLib.c b/ArmPkg/Library/ArmExceptionLib/ArmExceptionLib.c index 345f261679..c8ae64269d 100644 --- a/ArmPkg/Library/ArmExceptionLib/ArmExceptionLib.c +++ b/ArmPkg/Library/ArmExceptionLib/ArmExceptionLib.c @@ -68,6 +68,21 @@ STATIC CONST BOOLEAN gArmRelocateVectorTable = TRUE; STATIC CONST BOOLEAN gArmRelocateVectorTable = FALSE; #endif +EXCEPTION_ADDRESSES mAddresses; + +VOID +ExceptionHandlerBase ( + VOID + ); + +VOID +ExceptionHandlerFinal ( + VOID + ); + +extern UINT8 mSwitchTTBR0Flag; +extern UINTN CorePageTable; + /** Initializes all CPU exceptions entries and provides the default exception handlers. @@ -316,3 +331,30 @@ InitializeSeparateExceptionStacks ( { return EFI_SUCCESS; } + +EXCEPTION_ADDRESSES * +EFIAPI +GetExceptionAddresses ( + VOID + ) +{ + mSwitchTTBR0Flag = 1; + + return &mAddresses; +} + +VOID +EFIAPI +SetExceptionAddresses ( + IN VOID *Buffer, + IN UINTN BufferSize + ) +{ + mAddresses.ExceptionStackBase = (UINTN)Buffer; + mAddresses.ExceptionStackSize = BufferSize; + mAddresses.ExceptionHandlerBase = (UINTN)ExceptionHandlerBase; + mAddresses.ExceptionHandlerSize = (UINTN)ExceptionHandlerFinal - mAddresses.ExceptionHandlerBase; + mAddresses.ExceptionDataBase = (UINTN)&CorePageTable; + + CorePageTable = (UINTN)ArmGetTTBR0BaseAddress (); +} diff --git a/MdeModulePkg/Core/Dxe/SysCall/AARCH64/CoreBootServices.S b/MdeModulePkg/Core/Dxe/SysCall/AARCH64/CoreBootServices.S index 5bc80d9966..f6de8c0a71 100644 --- a/MdeModulePkg/Core/Dxe/SysCall/AARCH64/CoreBootServices.S +++ b/MdeModulePkg/Core/Dxe/SysCall/AARCH64/CoreBootServices.S @@ -55,6 +55,7 @@ call: add sp, sp, #0x10 ret +ASM_FUNC_ALIGN(SysCallBase, 4096) //------------------------------------------------------------------------------ // EFI_STATUS // EFIAPI @@ -67,6 +68,7 @@ call: // (x2) gRing3EntryPoint // (x3) gCoreSysCallStackTop // (x4) &CoreSp +// (x5) gUserPageTable //------------------------------------------------------------------------------ ASM_FUNC(ArmCallRing3) // Save registers. @@ -88,6 +90,10 @@ ASM_FUNC(ArmCallRing3) // Disable interrupts. msr daifset, #0xf isb + // Save Core SP and switch to CoreSysCall Stack. + mov x6, sp + str x6, [x4] + mov sp, x3 // Copy PSTATE to SPSR. mrs x6, nzcv mrs x7, pan @@ -97,17 +103,18 @@ ASM_FUNC(ArmCallRing3) EL1_OR_EL2(x1) 1:msr elr_el1, x2 msr spsr_el1, x6 + msr ttbr0_el1, x5 + tlbi vmalle1 b 3f 2:msr elr_el2, x2 msr spsr_el2, x6 - // Save Core SP and switch to CoreSysCall Stack. -3:mov x5, sp - str x5, [x4] - mov sp, x3 - + msr ttbr0_el2, x5 + tlbi alle2 +3:dsb sy isb eret +ASM_FUNC_ALIGN(SysCallEnd, 4096) //------------------------------------------------------------------------------ // VOID // EFIAPI diff --git a/MdeModulePkg/Core/Dxe/SysCall/AARCH64/InitializeAARCH64.c b/MdeModulePkg/Core/Dxe/SysCall/AARCH64/InitializeAARCH64.c index 54dfd33a6f..7cf67e2643 100644 --- a/MdeModulePkg/Core/Dxe/SysCall/AARCH64/InitializeAARCH64.c +++ b/MdeModulePkg/Core/Dxe/SysCall/AARCH64/InitializeAARCH64.c @@ -8,12 +8,13 @@ #include #include #include +#include #include #include "DxeMain.h" STATIC UINTN mCoreSp; -extern UINTN gUartBaseAddress; +UINTN gUserPageTable; EFI_STATUS EFIAPI @@ -22,7 +23,8 @@ ArmCallRing3 ( IN VOID *StackPointer, IN VOID *EntryPoint, IN VOID *SysCallStack, - IN VOID *CoreStack + IN VOID *CoreStack, + IN UINTN UserPageTable ); VOID @@ -65,12 +67,6 @@ SysCallBootService ( AllowSupervisorAccessToUserMemory (); CopyMem ((VOID *)((UINTN)Physical + sizeof (UINTN)), (VOID *)UserRsp, 8 * sizeof (UINTN)); - - SetUefiImageMemoryAttributes ( - gUartBaseAddress, - EFI_PAGE_SIZE, - EFI_MEMORY_XP - ); ForbidSupervisorAccessToUserMemory (); Status = CallBootService ( @@ -81,12 +77,6 @@ SysCallBootService ( CoreFreePages (Physical, EFI_SIZE_TO_PAGES (9 * sizeof (UINTN))); - SetUefiImageMemoryAttributes ( - gUartBaseAddress, - EFI_PAGE_SIZE, - EFI_MEMORY_XP | EFI_MEMORY_USER - ); - return Status; } @@ -128,13 +118,6 @@ InitializeMsr ( UINTN Tcr; UINTN Sctlr; // - // If HCR_EL2.NV is 1 and the current Exception level is EL1, - // then EL1 read accesses to the CurrentEL register return a value of 0x2 in bits[3:2]. - // CurrentEL == 1 -> HCR_EL2.NV == 0 - // - // If stage 1 is enabled and stage 1 Base permissions use Direct permissions, - // then GCS access is not permitted and UnprivGCS and PrivGCS are not present. - // // Disable Hierarchical permissions just in case. // Tcr = ArmGetTCR (); @@ -153,6 +136,7 @@ InitializeMsr ( } InitializeSysCallHandler ((VOID *)SysCallBootService); + SetExceptionAddresses (NULL, 0); } VOID @@ -183,5 +167,5 @@ CallRing3 ( IN RING3_CALL_DATA *Data ) { - return ArmCallRing3 (Data, gRing3CallStackTop, gRing3EntryPoint, gCoreSysCallStackTop, &mCoreSp); + return ArmCallRing3 (Data, gRing3CallStackTop, gRing3EntryPoint, gCoreSysCallStackTop, &mCoreSp, gUserPageTable); } diff --git a/MdeModulePkg/Core/Dxe/SysCall/Initialization.c b/MdeModulePkg/Core/Dxe/SysCall/Initialization.c index df9fc4a8b5..79cc683ff7 100644 --- a/MdeModulePkg/Core/Dxe/SysCall/Initialization.c +++ b/MdeModulePkg/Core/Dxe/SysCall/Initialization.c @@ -210,7 +210,6 @@ InitializeUserPageTable ( UINTN SectionAddress; UINT32 Index; UEFI_IMAGE_RECORD *UserImageRecord; - IA32_DESCRIPTOR IdtDescriptor; // // TODO: Remove ASSERTs, add proper checks and return status. @@ -270,14 +269,6 @@ InitializeUserPageTable ( EFI_MEMORY_RO ); - gCpu->SetUserMemoryAttributes ( - gCpu, - UserPageTable, - (UINTN)&gCorePageTable, - SIZE_4KB, - EFI_MEMORY_RO | EFI_MEMORY_XP - ); - gCpu->SetUserMemoryAttributes ( gCpu, UserPageTable, @@ -289,14 +280,6 @@ InitializeUserPageTable ( // // Map ExceptionHandlers, ExceptionStacks, Idt // - gCpu->SetUserMemoryAttributes ( - gCpu, - UserPageTable, - mExceptionAddresses->ExceptionStackBase, - mExceptionAddresses->ExceptionStackSize, - EFI_MEMORY_XP - ); - gCpu->SetUserMemoryAttributes ( gCpu, UserPageTable, @@ -313,6 +296,25 @@ InitializeUserPageTable ( EFI_MEMORY_XP ); +#if defined (MDE_CPU_X64) || defined (MDE_CPU_IA32) + IA32_DESCRIPTOR IdtDescriptor; + + gCpu->SetUserMemoryAttributes ( + gCpu, + UserPageTable, + (UINTN)&gCorePageTable, + SIZE_4KB, + EFI_MEMORY_RO | EFI_MEMORY_XP + ); + + gCpu->SetUserMemoryAttributes ( + gCpu, + UserPageTable, + mExceptionAddresses->ExceptionStackBase, + mExceptionAddresses->ExceptionStackSize, + EFI_MEMORY_XP + ); + AsmReadIdtr (&IdtDescriptor); gCpu->SetUserMemoryAttributes ( gCpu, @@ -332,6 +334,18 @@ InitializeUserPageTable ( FixedPcdGet32 (PcdOvmfWorkAreaSize), EFI_MEMORY_XP | EFI_MEMORY_USER ); +#elif defined (MDE_CPU_AARCH64) || defined (MDE_CPU_ARM) + // + // Necessary fix for DEBUG printings. + // + gCpu->SetUserMemoryAttributes ( + gCpu, + UserPageTable, + gUartBaseAddress, + SIZE_4KB, + EFI_MEMORY_XP | EFI_MEMORY_USER + ); +#endif // // Map User Image diff --git a/MdeModulePkg/Core/Dxe/SysCall/SupportedProtocols.c b/MdeModulePkg/Core/Dxe/SysCall/SupportedProtocols.c index 4ef2f87fb8..286ba9f834 100644 --- a/MdeModulePkg/Core/Dxe/SysCall/SupportedProtocols.c +++ b/MdeModulePkg/Core/Dxe/SysCall/SupportedProtocols.c @@ -13,10 +13,6 @@ EFI_FILE_PROTOCOL mRing3FileProtocol; EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *mRing3SimpleFileSystemPointer; -#if defined (MDE_CPU_AARCH64) || defined (MDE_CPU_ARM) -extern UINTN gUartBaseAddress; -#endif - typedef struct { EFI_FILE_PROTOCOL Protocol; EFI_FILE_PROTOCOL *Ring3File; @@ -62,28 +58,8 @@ GoToRing3 ( VA_END (Marker); ForbidSupervisorAccessToUserMemory (); -#if defined (MDE_CPU_AARCH64) || defined (MDE_CPU_ARM) - // - // Necessary fix for DEBUG printings. - // - SetUefiImageMemoryAttributes ( - gUartBaseAddress, - EFI_PAGE_SIZE, - EFI_MEMORY_XP | EFI_MEMORY_USER - ); -#endif Status = CallRing3 (Input); -#if defined (MDE_CPU_AARCH64) || defined (MDE_CPU_ARM) - AllowSupervisorAccessToUserMemory (); - SetUefiImageMemoryAttributes ( - gUartBaseAddress, - EFI_PAGE_SIZE, - EFI_MEMORY_XP - ); - ForbidSupervisorAccessToUserMemory (); -#endif - CoreFreePages (Ring3Pages, PagesNumber); return Status;