Ring3: Added support for IA32 User page table.

This commit is contained in:
Mikhail Krichanov 2024-12-03 14:40:52 +03:00
parent 5cd360104a
commit b9976de78c
4 changed files with 155 additions and 6 deletions

View File

@ -224,7 +224,7 @@
gEfiMdePkgTokenSpaceGuid.PcdImageProtectionPolicy ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdSerialUseMmio ## CONSUMES
[Pcd.IA32,Pcd.X64]
[Pcd.IA32, Pcd.X64]
gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable ## SOMETIMES_CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdUse5LevelPageTable ## SOMETIMES_CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask ## CONSUMES

View File

@ -98,6 +98,10 @@ copy:
pop eax
%endmacro
ALIGN 4096
global ASM_PFX(SysCallBase)
ASM_PFX(SysCallBase):
;------------------------------------------------------------------------------
; EFI_STATUS
; EFIAPI
@ -119,6 +123,9 @@ ASM_PFX(CoreBootServices):
push ebp
push eax
mov eax, [ASM_PFX(gCorePageTable)]
mov cr3, eax
; Switch from User to Core data segment selectors.
mov ax, ss
mov ds, ax
@ -147,6 +154,9 @@ ASM_PFX(CoreBootServices):
SetRing3DataSegmentSelectors
mov eax, [ASM_PFX(gUserPageTable)]
mov cr3, eax
pop eax
; Step over User Arguments [1..3] and CallBootService input.
@ -194,10 +204,17 @@ ASM_PFX(CallRing3):
; Switch to User Stack.
mov ebp, ecx
mov ebx, [ASM_PFX(gUserPageTable)]
mov cr3, ebx
; Pass control to user image
sti
sysexit
ALIGN 4096
global ASM_PFX(SysCallEnd)
ASM_PFX(SysCallEnd):
;------------------------------------------------------------------------------
; VOID
; EFIAPI
@ -219,5 +236,16 @@ ASM_PFX(ReturnToCore):
ret
SECTION .data
ALIGN 4096
global ASM_PFX(gCorePageTable)
ASM_PFX(gCorePageTable):
resd 1
global ASM_PFX(gUserPageTable)
ASM_PFX(gUserPageTable):
resd 1
ALIGN 4096
ASM_PFX(CoreEsp):
resd 1

View File

@ -8,6 +8,86 @@
#include "DxeMain.h"
#include <Register/Intel/ArchitecturalMsr.h>
#include <IndustryStandard/PageTable.h>
VOID
EFIAPI
MakeUserPageTableTemplate (
OUT VOID **UserPageTableTemplate,
OUT UINTN *UserPageTableTemplateSize
)
{
UINT8 PhysicalAddressBits;
EFI_PHYSICAL_ADDRESS PhysicalAddress;
UINTN IndexOfPdpEntries;
UINTN IndexOfPageDirectoryEntries;
UINT32 NumberOfPdpEntriesNeeded;
PAGE_MAP_AND_DIRECTORY_POINTER *PageMap;
PAGE_MAP_AND_DIRECTORY_POINTER *PageDirectoryPointerEntry;
PAGE_TABLE_ENTRY *PageDirectoryEntry;
UINTN TotalPagesNum;
UINTN PageAddress;
UINT64 AddressEncMask;
//
// Make sure AddressEncMask is contained to smallest supported address field
//
AddressEncMask = PcdGet64 (PcdPteMemoryEncryptionAddressOrMask) & PAGING_1G_ADDRESS_MASK_64;
PhysicalAddressBits = 32;
//
// Calculate the table entries needed.
//
NumberOfPdpEntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 30));
TotalPagesNum = NumberOfPdpEntriesNeeded + 1;
PageAddress = (UINTN)AllocateAlignedPages (TotalPagesNum, PAGE_TABLE_POOL_ALIGNMENT);
ASSERT (PageAddress != 0);
PageMap = (VOID *)PageAddress;
PageAddress += SIZE_4KB;
PageDirectoryPointerEntry = PageMap;
PhysicalAddress = 0;
for (IndexOfPdpEntries = 0; IndexOfPdpEntries < NumberOfPdpEntriesNeeded; IndexOfPdpEntries++, PageDirectoryPointerEntry++) {
//
// Each Directory Pointer entries points to a page of Page Directory entires.
// So allocate space for them and fill them in in the IndexOfPageDirectoryEntries loop.
//
PageDirectoryEntry = (VOID *)PageAddress;
PageAddress += SIZE_4KB;
//
// Fill in a Page Directory Pointer Entries
//
PageDirectoryPointerEntry->Uint64 = (UINT64)(UINTN)PageDirectoryEntry | AddressEncMask;
PageDirectoryPointerEntry->Bits.Present = 1;
for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PhysicalAddress += SIZE_2MB) {
//
// Fill in the Page Directory entries
//
PageDirectoryEntry->Uint64 = (UINT64)PhysicalAddress | AddressEncMask;
PageDirectoryEntry->Bits.ReadWrite = 1;
PageDirectoryEntry->Bits.Present = 0;
PageDirectoryEntry->Bits.MustBe1 = 1;
}
}
for ( ; IndexOfPdpEntries < 512; IndexOfPdpEntries++, PageDirectoryPointerEntry++) {
ZeroMem (
PageDirectoryPointerEntry,
sizeof (PAGE_MAP_AND_DIRECTORY_POINTER)
);
}
*UserPageTableTemplate = (VOID *)PageMap;
*UserPageTableTemplateSize = ALIGN_VALUE (EFI_PAGES_TO_SIZE (TotalPagesNum), PAGE_TABLE_POOL_ALIGNMENT);
SetUefiImageMemoryAttributes ((UINT64)(UINTN)PageMap, *UserPageTableTemplateSize, EFI_MEMORY_XP);
}
VOID
EFIAPI
@ -25,6 +105,13 @@ InitializeMsr (
Ebx = 0;
Edx = 0;
//
// Forbid global pages.
//
Cr4.UintN = AsmReadCr4 ();
Cr4.Bits.PGE = 0;
AsmWriteCr4 (Cr4.UintN);
//
// Forbid supervisor-mode accesses to any user-mode pages.
//
@ -70,4 +157,6 @@ InitializeMsr (
Msr = (UINT64)(UINTN)gCoreSysCallStackTop;
AsmWriteMsr64 (MSR_IA32_SYSENTER_ESP, Msr);
gCorePageTable = AsmReadCr3 ();
}

View File

@ -23,16 +23,33 @@
;
; CommonExceptionHandler()
;
extern ASM_PFX(mErrorCodeFlag) ; Error code flags for exceptions
extern ASM_PFX(mDoFarReturnFlag) ; Do far return flag
extern ASM_PFX(CommonExceptionHandler)
SECTION .data
ALIGN 4096
extern ASM_PFX(mErrorCodeFlag) ; Error code flags for exceptions
extern ASM_PFX(mDoFarReturnFlag) ; Do far return flag
global ASM_PFX(CorePageTable)
ASM_PFX(CorePageTable):
resq 1
global ASM_PFX(UserPageTable)
ASM_PFX(UserPageTable):
resq 1
global ASM_PFX(mSwitchCr3Flag)
ASM_PFX(mSwitchCr3Flag):
db 0x0
ALIGN 4096
Padding:
db 0x0
SECTION .text
ALIGN 8
ALIGN 4096
global ASM_PFX(ExceptionHandlerBase)
ASM_PFX(ExceptionHandlerBase):
;
; exception handler stub table
@ -88,6 +105,14 @@ HookAfterStubHeaderEnd:
global ASM_PFX(CommonInterruptEntry)
ASM_PFX(CommonInterruptEntry):
cli
cmp byte [ASM_PFX(mSwitchCr3Flag)], 0
jz NoCr3Switch
mov eax, cr3
mov [ASM_PFX(UserPageTable)], eax
mov eax, [ASM_PFX(CorePageTable)]
mov cr3, eax
NoCr3Switch:
pop eax
;
; All interrupt handlers are invoked through interrupt gates, so
@ -413,8 +438,8 @@ continue:
push ecx
mov ecx, ds
and ecx, 3
pop ecx
jnz ReturnToRing3
pop ecx
pop dword [ebp - 8]
pop dword [ebp - 4]
@ -444,11 +469,18 @@ DoReturn:
DoIret:
iretd
ReturnToRing3:
mov ecx, [ASM_PFX(UserPageTable)]
mov cr3, ecx
pop ecx
mov esp, ebp
pop ebp
add esp, 8
iretd
ALIGN 4096
global ASM_PFX(ExceptionHandlerEnd)
ASM_PFX(ExceptionHandlerEnd):
;---------------------------------------;
; _AsmGetTemplateAddressMap ;
;----------------------------------------------------------------------------;