Ring3: Added CoreSysCallStack.

This commit is contained in:
Mikhail Krichanov 2024-01-23 19:54:19 +03:00
parent e36fd7b639
commit 2fe010f40b
4 changed files with 63 additions and 18 deletions

View File

@ -27,6 +27,7 @@ STATIC EFI_EVENT mPeCoffEmuProtocolRegistrationEvent;
STATIC VOID *mPeCoffEmuProtocolNotifyRegistration; STATIC VOID *mPeCoffEmuProtocolNotifyRegistration;
extern BOOLEAN gBdsStarted; extern BOOLEAN gBdsStarted;
extern VOID *gCoreSysCallStackTop;
// //
// This code is needed to build the Image handle for the DXE Core // This code is needed to build the Image handle for the DXE Core
@ -1700,23 +1701,41 @@ CoreStartImage (
gCpu->GetMemoryAttributes (gCpu, (EFI_PHYSICAL_ADDRESS)Image->EntryPoint, &Attributes); gCpu->GetMemoryAttributes (gCpu, (EFI_PHYSICAL_ADDRESS)Image->EntryPoint, &Attributes);
ASSERT ((Attributes & EFI_MEMORY_USER) != 0); ASSERT ((Attributes & EFI_MEMORY_USER) != 0);
SizeOfStack = EFI_SIZE_TO_PAGES (USER_STACK_SIZE) * EFI_PAGE_SIZE;
//
// Allocate 128KB for the Core SysCall Stack.
//
BaseOfStack = AllocatePages (EFI_SIZE_TO_PAGES (USER_STACK_SIZE));
ASSERT (BaseOfStack != NULL);
//
// Compute the top of the allocated stack. Pre-allocate a UINTN for safety.
//
TopOfStack = (VOID *)((UINTN)BaseOfStack + SizeOfStack - CPU_STACK_ALIGNMENT);
TopOfStack = ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT);
gCoreSysCallStackTop = TopOfStack;
DEBUG ((DEBUG_ERROR, "Core: gCoreSysCallStackTop = %p\n", gCoreSysCallStackTop));
SetUefiImageMemoryAttributes ((UINTN)BaseOfStack, SizeOfStack, EFI_MEMORY_XP);
// //
// Allocate 128KB for the User Stack. // Allocate 128KB for the User Stack.
// //
BaseOfStack = AllocatePages (EFI_SIZE_TO_PAGES (USER_STACK_SIZE)); BaseOfStack = AllocatePages (EFI_SIZE_TO_PAGES (USER_STACK_SIZE));
ASSERT (BaseOfStack != NULL); ASSERT (BaseOfStack != NULL);
SizeOfStack = EFI_SIZE_TO_PAGES (USER_STACK_SIZE) * EFI_PAGE_SIZE;
SetUefiImageMemoryAttributes ((UINTN)BaseOfStack, SizeOfStack, EFI_MEMORY_XP | EFI_MEMORY_USER);
// //
// Compute the top of the allocated stack. Pre-allocate a UINTN for safety. // Compute the top of the allocated stack. Pre-allocate a UINTN for safety.
// //
TopOfStack = (VOID *)((UINTN)BaseOfStack + SizeOfStack - CPU_STACK_ALIGNMENT); TopOfStack = (VOID *)((UINTN)BaseOfStack + SizeOfStack - CPU_STACK_ALIGNMENT);
TopOfStack = ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT); TopOfStack = ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT);
// DEBUG ((DEBUG_ERROR, "RING3_CODE64_SEL = 0x%x RING3_DATA64_SEL = 0x%x\n", (UINT16)RING3_CODE64_SEL, (UINT16)RING3_DATA64_SEL));
// DEBUG ((DEBUG_ERROR, "Core: BootServices = %p\n", Image->Info.SystemTable->BootServices)); SetUefiImageMemoryAttributes ((UINTN)BaseOfStack, SizeOfStack, EFI_MEMORY_XP | EFI_MEMORY_USER);
DEBUG ((DEBUG_ERROR, "Core: UserTopOfStack = %p\n", TopOfStack));
DEBUG ((DEBUG_ERROR, "Core: BootServices = %p\n", Image->Info.SystemTable->BootServices));
// //
// Necessary fix for ProcessLibraryConstructorList() -> DxeCcProbeLibConstructor() // Necessary fix for ProcessLibraryConstructorList() -> DxeCcProbeLibConstructor()
@ -1736,10 +1755,6 @@ CoreStartImage (
Msr = (UINT64)(UINTN)CoreBootServices; Msr = (UINT64)(UINTN)CoreBootServices;
AsmWriteMsr64 (MSR_IA32_LSTAR, Msr); AsmWriteMsr64 (MSR_IA32_LSTAR, Msr);
// protection keys
// Software can access the old stack, if necessary, by referencing the old
// stack-segment selector and stack pointer saved on the new process stack.
EnterUserImage ( EnterUserImage (
(SWITCH_STACK_ENTRY_POINT)(UINTN)Image->EntryPoint, (SWITCH_STACK_ENTRY_POINT)(UINTN)Image->EntryPoint,
ImageHandle, ImageHandle,

View File

@ -998,7 +998,7 @@ CreateIdentityMappingPageTables (
AsmCpuidEx (0x80000001, 0x0, NULL, NULL, NULL, &Edx); AsmCpuidEx (0x80000001, 0x0, NULL, NULL, NULL, &Edx);
if (((Ebx & BIT20) != 0) && ((Ebx & BIT7) != 0) && ((Edx & BIT11) != 0)) { if (((Ebx & BIT20) != 0) && ((Ebx & BIT7) != 0) && ((Edx & BIT11) != 0)) {
Cr4.UintN = AsmReadCr4 (); Cr4.UintN = AsmReadCr4 ();
Cr4.Bits.SMAP = 1; // Cr4.Bits.SMAP = 1;
Cr4.Bits.SMEP = 1; Cr4.Bits.SMEP = 1;
AsmWriteCr4 (Cr4.UintN); AsmWriteCr4 (Cr4.UintN);
@ -1010,7 +1010,7 @@ CreateIdentityMappingPageTables (
Eflags.Bits.IOPL = 3; Eflags.Bits.IOPL = 3;
AsmWriteEflags (Eflags.UintN); AsmWriteEflags (Eflags.UintN);
// //
// Enable SYSCALL and SYSRET // Enable SYSCALL and SYSRET.
// //
MsrEfer.Uint64 = AsmReadMsr64 (MSR_IA32_EFER); MsrEfer.Uint64 = AsmReadMsr64 (MSR_IA32_EFER);
MsrEfer.Bits.SCE = 1; MsrEfer.Bits.SCE = 1;

View File

@ -113,22 +113,45 @@ ASM_PFX(CoreBootServices):
cmp r10, 0 cmp r10, 0
je readMemory je readMemory
mov ax, ss
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
; Save User Stack pointer and switch to Core SysCall Stack.
mov rax, [ASM_PFX(gCoreSysCallStackTop)]
sub rax, 8
mov [rax], rsp
mov rsp, rax
push rbp
mov rbp, rsp
; Save return address and RFLAGS for SYSRET. ; Save return address and RFLAGS for SYSRET.
mov [rsp], rcx push rcx
mov [rsp + 8], r11 push r11
; Replace argument according to UEFI calling convention. ; Replace argument according to UEFI calling convention.
mov rcx, rdx mov rcx, rdx
mov rdx, r8 mov rdx, r8
mov r8, r9 mov r8, r9
mov r9, [rsp + 8*3] ; mov r9, [rax + 8*3]
; mov r11, [rax + 8*4]
; push r11
; ...
; Call Boot Service by FunctionAddress. ; Call Boot Service by FunctionAddress.
call r10 call r10
; Prepare SYSRET arguments. ; Prepare SYSRET arguments.
mov rcx, [rsp] pop r11
mov r11, [rsp + 8] pop rcx
; Switch to User Stack.
pop rbp
pop rdx
mov rsp, rdx
; SYSCALL saves RFLAGS into R11 and the RIP of the next instruction into RCX. ; SYSCALL saves RFLAGS into R11 and the RIP of the next instruction into RCX.
o64 sysret o64 sysret
@ -137,3 +160,10 @@ o64 sysret
readMemory: readMemory:
mov rax, [rdx] mov rax, [rdx]
o64 sysret o64 sysret
SECTION .data
global ASM_PFX(gCoreSysCallStackTop)
ASM_PFX(gCoreSysCallStackTop):
resq 1

View File

@ -94,7 +94,7 @@ UefiBootServicesTableLibConstructor (
(UINTN)SystemTable + OFFSET_OF (EFI_SYSTEM_TABLE, BootServices) (UINTN)SystemTable + OFFSET_OF (EFI_SYSTEM_TABLE, BootServices)
); );
ASSERT (mCoreBS != NULL); ASSERT (mCoreBS != NULL);
// DEBUG ((DEBUG_ERROR, "User: BootServices = %p\n", mCoreBS)); DEBUG ((DEBUG_ERROR, "User: BootServices = %p\n", mCoreBS));
return EFI_SUCCESS; return EFI_SUCCESS;
} }