Ring3: Added support for ARM User page table.

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

View File

@ -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

View File

@ -11,6 +11,7 @@
#------------------------------------------------------------------------------
#include <Library/PcdLib.h>
#include <AsmMacroIoLib.h>
/*
@ -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

View File

@ -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

View File

@ -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);
}