Skip to content

Commit

Permalink
Ring3: Added support for AARCH64 User page table.
Browse files Browse the repository at this point in the history
  • Loading branch information
Mikhail Krichanov committed Dec 14, 2024
1 parent 4589835 commit c7f3cc0
Show file tree
Hide file tree
Showing 6 changed files with 150 additions and 68 deletions.
59 changes: 59 additions & 0 deletions ArmPkg/Library/ArmExceptionLib/AArch64/ExceptionSupport.S
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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]
Expand Down Expand Up @@ -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
42 changes: 42 additions & 0 deletions ArmPkg/Library/ArmExceptionLib/ArmExceptionLib.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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 ();
}
17 changes: 12 additions & 5 deletions MdeModulePkg/Core/Dxe/SysCall/AARCH64/CoreBootServices.S
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ call:
add sp, sp, #0x10
ret

ASM_FUNC_ALIGN(SysCallBase, 4096)
//------------------------------------------------------------------------------
// EFI_STATUS
// EFIAPI
Expand All @@ -67,6 +68,7 @@ call:
// (x2) gRing3EntryPoint
// (x3) gCoreSysCallStackTop
// (x4) &CoreSp
// (x5) gUserPageTable
//------------------------------------------------------------------------------
ASM_FUNC(ArmCallRing3)
// Save registers.
Expand All @@ -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
Expand All @@ -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
Expand Down
28 changes: 6 additions & 22 deletions MdeModulePkg/Core/Dxe/SysCall/AARCH64/InitializeAARCH64.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@
#include <Chipset/AArch64.h>
#include <Library/ArmLib.h>
#include <Library/ArmMmuLib.h>
#include <Library/CpuExceptionHandlerLib.h>
#include <Library/DefaultExceptionHandlerLib.h>

#include "DxeMain.h"

STATIC UINTN mCoreSp;
extern UINTN gUartBaseAddress;
UINTN gUserPageTable;

EFI_STATUS
EFIAPI
Expand All @@ -22,7 +23,8 @@ ArmCallRing3 (
IN VOID *StackPointer,
IN VOID *EntryPoint,
IN VOID *SysCallStack,
IN VOID *CoreStack
IN VOID *CoreStack,
IN UINTN UserPageTable
);

VOID
Expand Down Expand Up @@ -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 (
Expand All @@ -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;
}

Expand Down Expand Up @@ -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 ();
Expand All @@ -153,6 +136,7 @@ InitializeMsr (
}

InitializeSysCallHandler ((VOID *)SysCallBootService);
SetExceptionAddresses (NULL, 0);
}

VOID
Expand Down Expand Up @@ -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);
}
48 changes: 31 additions & 17 deletions MdeModulePkg/Core/Dxe/SysCall/Initialization.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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,
Expand All @@ -289,14 +280,6 @@ InitializeUserPageTable (
//
// Map ExceptionHandlers, ExceptionStacks, Idt
//
gCpu->SetUserMemoryAttributes (
gCpu,
UserPageTable,
mExceptionAddresses->ExceptionStackBase,
mExceptionAddresses->ExceptionStackSize,
EFI_MEMORY_XP
);

gCpu->SetUserMemoryAttributes (
gCpu,
UserPageTable,
Expand All @@ -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,
Expand All @@ -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
Expand Down
24 changes: 0 additions & 24 deletions MdeModulePkg/Core/Dxe/SysCall/SupportedProtocols.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit c7f3cc0

Please sign in to comment.