Ring3: Added support for ARM User page table.

This commit is contained in:
Mikhail Krichanov 2024-12-19 20:18:28 +03:00
parent 1c10e31d45
commit f4244d8d44
4 changed files with 86 additions and 16 deletions

View File

@ -11,6 +11,7 @@
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
#include <Library/PcdLib.h> #include <Library/PcdLib.h>
#include <AsmMacroIoLib.h>
/* /*
@ -59,8 +60,10 @@ GCC_ASM_EXPORT(CommonCExceptionHandler)
#if !defined(__APPLE__) #if !defined(__APPLE__)
.fpu neon @ makes vpush/vpop assemble .fpu neon @ makes vpush/vpop assemble
#endif #endif
.align 5
ASM_FUNC_ALIGN(ExceptionHandlerBase, 4096)
.align 5
// //
// This code gets copied to the ARM vector table // This code gets copied to the ARM vector table
@ -117,6 +120,8 @@ ASM_PFX(UndefinedInstructionEntry):
bx R1 bx R1
ASM_PFX(SoftwareInterruptEntry): ASM_PFX(SoftwareInterruptEntry):
cpsid if
isb
srsdb #0x13! @ Store return state on SVC stack srsdb #0x13! @ Store return state on SVC stack
@ We are already in SVC mode @ We are already in SVC mode
stmfd SP!,{LR} @ Store the link register for the current 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 vpush {d0-d15} @ save vstm registers in case they are used in optimizations
#endif #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 mov R4, SP @ Save current SP
tst R4, #4 tst R4, #4
subne SP, SP, #4 @ Adjust SP if not 8-byte aligned subne SP, SP, #4 @ Adjust SP if not 8-byte aligned
@ -269,6 +292,19 @@ CommonCExceptionHandler (
mov SP, R4 @ Restore SP 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)) #if (FixedPcdGet32(PcdVFPEnabled))
vpop {d0-d15} vpop {d0-d15}
#endif #endif
@ -290,3 +326,19 @@ CommonCExceptionHandler (
add SP,SP,#0x20 @ Clear out the remaining stack space add SP,SP,#0x20 @ Clear out the remaining stack space
ldmfd SP!,{LR} @ restore the link register for this context ldmfd SP!,{LR} @ restore the link register for this context
rfefd SP! @ return from exception via srsfd stack slot 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

View File

@ -51,6 +51,7 @@ call:
pop {R4-R8, LR} pop {R4-R8, LR}
bx LR bx LR
ASM_FUNC_ALIGN(SysCallBase, 4096)
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// EFI_STATUS // EFI_STATUS
// EFIAPI // EFIAPI
@ -63,13 +64,15 @@ call:
// (r2) gRing3EntryPoint // (r2) gRing3EntryPoint
// (r3) gCoreSysCallStackTop // (r3) gCoreSysCallStackTop
// //
// (On Core Stack) &CoreSp // (On Core Stack) &CoreSp, gUserPageTable
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
ASM_FUNC(ArmCallRing3) ASM_FUNC(ArmCallRing3)
// Save registers. // Save registers.
push {R4-R12, LR} push {R4-R12, LR}
// R6 is &CoreSp // R6 is &CoreSp
ldr R6, [SP, #0x28] ldr R6, [SP, #0x28]
// R7 is gUserPageTable
ldr R7, [SP, #0x2C]
#if (FixedPcdGet32(PcdVFPEnabled)) #if (FixedPcdGet32(PcdVFPEnabled))
// Save vstm registers in case they are used in optimizations. // Save vstm registers in case they are used in optimizations.
@ -94,10 +97,21 @@ ASM_FUNC(ArmCallRing3)
str R5, [R6] str R5, [R6]
mov SP, R3 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 {R4}
push {R2} push {R2}
rfefd SP rfefd SP
ASM_FUNC_ALIGN(SysCallEnd, 4096)
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// VOID // VOID
// EFIAPI // EFIAPI

View File

@ -12,7 +12,7 @@
#include "DxeMain.h" #include "DxeMain.h"
STATIC UINTN mCoreSp; STATIC UINTN mCoreSp;
extern UINTN gUartBaseAddress; UINTN gUserPageTable;
EFI_STATUS EFI_STATUS
EFIAPI EFIAPI
@ -21,7 +21,8 @@ ArmCallRing3 (
IN VOID *StackPointer, IN VOID *StackPointer,
IN VOID *EntryPoint, IN VOID *EntryPoint,
IN VOID *SysCallStack, IN VOID *SysCallStack,
IN VOID *CoreStack IN VOID *CoreStack,
IN UINTN UserPageTable
); );
VOID VOID
@ -52,6 +53,8 @@ SysCallBootService (
EFI_STATUS Status; EFI_STATUS Status;
EFI_PHYSICAL_ADDRESS Physical; EFI_PHYSICAL_ADDRESS Physical;
ArmEnableInterrupts ();
Status = CoreAllocatePages ( Status = CoreAllocatePages (
AllocateAnyPages, AllocateAnyPages,
EfiRing3MemoryType, EfiRing3MemoryType,
@ -71,12 +74,6 @@ SysCallBootService (
// All remaining arguments are on User Stack. // All remaining arguments are on User Stack.
// //
CopyMem ((VOID *)((UINTN)Physical + 5 * sizeof (UINTN)), (VOID *)UserRsp, 4 * sizeof (UINTN)); CopyMem ((VOID *)((UINTN)Physical + 5 * sizeof (UINTN)), (VOID *)UserRsp, 4 * sizeof (UINTN));
SetUefiImageMemoryAttributes (
gUartBaseAddress,
EFI_PAGE_SIZE,
EFI_MEMORY_XP
);
ForbidSupervisorAccessToUserMemory (); ForbidSupervisorAccessToUserMemory ();
Status = CallBootService ( Status = CallBootService (
@ -89,11 +86,7 @@ SysCallBootService (
// //
CoreFreePages (Physical, EFI_SIZE_TO_PAGES (9 * sizeof (UINTN))); CoreFreePages (Physical, EFI_SIZE_TO_PAGES (9 * sizeof (UINTN)));
SetUefiImageMemoryAttributes ( ArmDisableInterrupts ();
gUartBaseAddress,
EFI_PAGE_SIZE,
EFI_MEMORY_XP | EFI_MEMORY_USER
);
return Status; return Status;
} }
@ -141,6 +134,7 @@ InitializeMsr (
} }
InitializeSysCallHandler (SysCallBootService); InitializeSysCallHandler (SysCallBootService);
SetExceptionAddresses (NULL, 0);
} }
VOID VOID
@ -171,5 +165,5 @@ CallRing3 (
IN RING3_CALL_DATA *Data IN RING3_CALL_DATA *Data
) )
{ {
return ArmCallRing3 (Data, gRing3CallStackTop, gRing3EntryPoint, gCoreSysCallStackTop, &mCoreSp); return ArmCallRing3 (Data, gRing3CallStackTop, gRing3EntryPoint, gCoreSysCallStackTop, &mCoreSp, gUserPageTable);
} }

View File

@ -21,6 +21,16 @@
#define ASM_FUNC(Name) _ASM_FUNC(ASM_PFX(Name), .text. ## Name) #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) \ #define MOV32(Reg, Val) \
movw Reg, #(Val) & 0xffff ; \ movw Reg, #(Val) & 0xffff ; \
movt Reg, #(Val) >> 16 movt Reg, #(Val) >> 16