diff --git a/ArmPkg/Include/AsmMacroIoLib.h b/ArmPkg/Include/AsmMacroIoLib.h index 2493a15b7b..c15000245d 100644 --- a/ArmPkg/Include/AsmMacroIoLib.h +++ b/ArmPkg/Include/AsmMacroIoLib.h @@ -21,6 +21,16 @@ #define ASM_FUNC(Name) _ASM_FUNC(ASM_PFX(Name), .text. ## Name) +#define _ASM_FUNC_ALIGN(Name, Section, Align) \ + .global Name ; \ + .section #Section, "ax" ; \ + .type Name, %function ; \ + .balign Align ; \ + Name: + +#define ASM_FUNC_ALIGN(Name, Align) \ + _ASM_FUNC_ALIGN(ASM_PFX(Name), .text. ## Name, Align) + #define MOV32(Reg, Val) \ movw Reg, #(Val) & 0xffff ; \ movt Reg, #(Val) >> 16 diff --git a/ArmPkg/Library/ArmExceptionLib/Arm/ExceptionSupport.S b/ArmPkg/Library/ArmExceptionLib/Arm/ExceptionSupport.S index 5d2a5617f8..257b0b05a9 100644 --- a/ArmPkg/Library/ArmExceptionLib/Arm/ExceptionSupport.S +++ b/ArmPkg/Library/ArmExceptionLib/Arm/ExceptionSupport.S @@ -11,6 +11,7 @@ #------------------------------------------------------------------------------ #include +#include /* @@ -59,8 +60,10 @@ GCC_ASM_EXPORT(CommonCExceptionHandler) #if !defined(__APPLE__) .fpu neon @ makes vpush/vpop assemble #endif -.align 5 +ASM_FUNC_ALIGN(ExceptionHandlerBase, 4096) + +.align 5 // // This code gets copied to the ARM vector table @@ -117,6 +120,8 @@ ASM_PFX(UndefinedInstructionEntry): bx R1 ASM_PFX(SoftwareInterruptEntry): + cpsid if + isb srsdb #0x13! @ Store return state on SVC stack @ We are already in SVC mode stmfd SP!,{LR} @ Store the link register for the current mode @@ -250,6 +255,24 @@ NoAdjustNeeded: vpush {d0-d15} @ save vstm registers in case they are used in optimizations #endif + ldr R5, [SP, #0x40] @ Saved Processor Status Register + and R5, R5, #0xF + cmp R5, 0 @ Check whether EL0 process was interrupted + bne NoTTBR0Switch + mrc p15,0,R5,c2,c0,0 @ R5 == TTBR0 + ADRL (R6, UserPageTable) + str R5, [R6] + and R5, R5, #0x7F @ Preserve TTBR0 attributes + LDRL (R6, ASM_PFX(CorePageTable)) + orr R6, R6, R5 @ Assign TTBR0 attributes + mcr p15,0,R6,c2,c0,0 @ TTBR0 == R6 + mcr p15,0,r0,c8,c7,0 @ TLBIALL, TLB Invalidate All. + mcr p15,0,r0,c7,c5,6 @ BPIALL, Branch Predictor Invalidate All. + dsb + isb + +NoTTBR0Switch: + mov R4, SP @ Save current SP tst R4, #4 subne SP, SP, #4 @ Adjust SP if not 8-byte aligned @@ -269,6 +292,19 @@ CommonCExceptionHandler ( mov SP, R4 @ Restore SP + ldr R4, [SP, #0x40] @ Saved Processor Status Register + and R4, R4, #0xF + cmp R4, 0 @ Check whether EL0 process was interrupted + bne NoTTBR0Switch2 + LDRL (R4, UserPageTable) + mcr p15,0,R4,c2,c0,0 @ TTBR0 == R4 + mcr p15,0,r0,c8,c7,0 @ TLBIALL, TLB Invalidate All. + mcr p15,0,r0,c7,c5,6 @ BPIALL, Branch Predictor Invalidate All. + dsb + isb + +NoTTBR0Switch2: + #if (FixedPcdGet32(PcdVFPEnabled)) vpop {d0-d15} #endif @@ -290,3 +326,19 @@ CommonCExceptionHandler ( add SP,SP,#0x20 @ Clear out the remaining stack space ldmfd SP!,{LR} @ restore the link register for this context rfefd SP! @ return from exception via srsfd stack slot + +ASM_FUNC_ALIGN(ExceptionHandlerFinal, 4096) + +.data + +.global ASM_PFX(CorePageTable) +.balign 4096 +ASM_PFX(CorePageTable): +.ds.l 1 + +UserPageTable: +.ds.l 1 + +.balign 4096 +Padding: +.ds.b 1 diff --git a/MdeModulePkg/Core/Dxe/SysCall/ARM/CoreBootServices.S b/MdeModulePkg/Core/Dxe/SysCall/ARM/CoreBootServices.S index befe2d5f33..df40693d20 100644 --- a/MdeModulePkg/Core/Dxe/SysCall/ARM/CoreBootServices.S +++ b/MdeModulePkg/Core/Dxe/SysCall/ARM/CoreBootServices.S @@ -51,6 +51,7 @@ call: pop {R4-R8, LR} bx LR +ASM_FUNC_ALIGN(SysCallBase, 4096) //------------------------------------------------------------------------------ // EFI_STATUS // EFIAPI @@ -63,13 +64,15 @@ call: // (r2) gRing3EntryPoint // (r3) gCoreSysCallStackTop // -// (On Core Stack) &CoreSp +// (On Core Stack) &CoreSp, gUserPageTable //------------------------------------------------------------------------------ ASM_FUNC(ArmCallRing3) // Save registers. push {R4-R12, LR} // R6 is &CoreSp ldr R6, [SP, #0x28] + // R7 is gUserPageTable + ldr R7, [SP, #0x2C] #if (FixedPcdGet32(PcdVFPEnabled)) // Save vstm registers in case they are used in optimizations. @@ -94,10 +97,21 @@ ASM_FUNC(ArmCallRing3) str R5, [R6] mov SP, R3 + // Switch to UserPageTable. + mrc p15,0,R8,c2,c0,0 // R8 == TTBR0 + and R8, R8, #0x7F // Preserve Core TTBR0 attributes. + orr R7, R7, R8 // Assign Core attributes to UserPageTable. + mcr p15,0,R7,c2,c0,0 // TTBR0 == UserPageTable + mcr p15,0,r0,c8,c7,0 // TLBIALL, TLB Invalidate All. + mcr p15,0,r0,c7,c5,6 // BPIALL, Branch Predictor Invalidate All. + dsb + isb + push {R4} push {R2} rfefd SP +ASM_FUNC_ALIGN(SysCallEnd, 4096) //------------------------------------------------------------------------------ // VOID // EFIAPI diff --git a/MdeModulePkg/Core/Dxe/SysCall/ARM/InitializeARM.c b/MdeModulePkg/Core/Dxe/SysCall/ARM/InitializeARM.c index b090af890d..26984d4e58 100644 --- a/MdeModulePkg/Core/Dxe/SysCall/ARM/InitializeARM.c +++ b/MdeModulePkg/Core/Dxe/SysCall/ARM/InitializeARM.c @@ -12,7 +12,7 @@ #include "DxeMain.h" STATIC UINTN mCoreSp; -extern UINTN gUartBaseAddress; +UINTN gUserPageTable; EFI_STATUS EFIAPI @@ -21,7 +21,8 @@ ArmCallRing3 ( IN VOID *StackPointer, IN VOID *EntryPoint, IN VOID *SysCallStack, - IN VOID *CoreStack + IN VOID *CoreStack, + IN UINTN UserPageTable ); VOID @@ -52,6 +53,8 @@ SysCallBootService ( EFI_STATUS Status; EFI_PHYSICAL_ADDRESS Physical; + ArmEnableInterrupts (); + Status = CoreAllocatePages ( AllocateAnyPages, EfiRing3MemoryType, @@ -71,12 +74,6 @@ SysCallBootService ( // All remaining arguments are on User Stack. // CopyMem ((VOID *)((UINTN)Physical + 5 * sizeof (UINTN)), (VOID *)UserRsp, 4 * sizeof (UINTN)); - - SetUefiImageMemoryAttributes ( - gUartBaseAddress, - EFI_PAGE_SIZE, - EFI_MEMORY_XP - ); ForbidSupervisorAccessToUserMemory (); Status = CallBootService ( @@ -89,11 +86,7 @@ SysCallBootService ( // CoreFreePages (Physical, EFI_SIZE_TO_PAGES (9 * sizeof (UINTN))); - SetUefiImageMemoryAttributes ( - gUartBaseAddress, - EFI_PAGE_SIZE, - EFI_MEMORY_XP | EFI_MEMORY_USER - ); + ArmDisableInterrupts (); return Status; } @@ -141,6 +134,7 @@ InitializeMsr ( } InitializeSysCallHandler (SysCallBootService); + SetExceptionAddresses (NULL, 0); } VOID @@ -171,5 +165,5 @@ CallRing3 ( IN RING3_CALL_DATA *Data ) { - return ArmCallRing3 (Data, gRing3CallStackTop, gRing3EntryPoint, gCoreSysCallStackTop, &mCoreSp); + return ArmCallRing3 (Data, gRing3CallStackTop, gRing3EntryPoint, gCoreSysCallStackTop, &mCoreSp, gUserPageTable); }