From b5d09122016c5173284785276ebbbd8cfc4efcb6 Mon Sep 17 00:00:00 2001 From: Mikhail Krichanov Date: Tue, 23 Jan 2024 19:54:19 +0300 Subject: [PATCH] Ring3: Added CoreSysCallStack. --- MdeModulePkg/Core/Dxe/Image/Image.c | 35 +++++++++++----- .../Core/DxeIplPeim/X64/VirtualMemory.c | 4 +- MdePkg/Library/BaseLib/X64/SwitchStack.nasm | 40 ++++++++++++++++--- .../Ring3UefiBootServicesTableLib.c | 2 +- 4 files changed, 63 insertions(+), 18 deletions(-) diff --git a/MdeModulePkg/Core/Dxe/Image/Image.c b/MdeModulePkg/Core/Dxe/Image/Image.c index 1412f93bac..0893d39fa2 100644 --- a/MdeModulePkg/Core/Dxe/Image/Image.c +++ b/MdeModulePkg/Core/Dxe/Image/Image.c @@ -27,6 +27,7 @@ STATIC EFI_EVENT mPeCoffEmuProtocolRegistrationEvent; STATIC VOID *mPeCoffEmuProtocolNotifyRegistration; extern BOOLEAN gBdsStarted; +extern VOID *gCoreSysCallStackTop; // // 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); 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. // BaseOfStack = AllocatePages (EFI_SIZE_TO_PAGES (USER_STACK_SIZE)); 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. // TopOfStack = (VOID *)((UINTN)BaseOfStack + SizeOfStack - 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() @@ -1736,10 +1755,6 @@ CoreStartImage ( Msr = (UINT64)(UINTN)CoreBootServices; 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 ( (SWITCH_STACK_ENTRY_POINT)(UINTN)Image->EntryPoint, ImageHandle, diff --git a/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c b/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c index 7c76a1b8d4..31db5de3fb 100644 --- a/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c +++ b/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c @@ -995,7 +995,7 @@ CreateIdentityMappingPageTables ( AsmCpuidEx (0x80000001, 0x0, NULL, NULL, NULL, &Edx); if (((Ebx & BIT20) != 0) && ((Ebx & BIT7) != 0) && ((Edx & BIT11) != 0)) { Cr4.UintN = AsmReadCr4 (); - Cr4.Bits.SMAP = 1; + // Cr4.Bits.SMAP = 1; Cr4.Bits.SMEP = 1; AsmWriteCr4 (Cr4.UintN); @@ -1007,7 +1007,7 @@ CreateIdentityMappingPageTables ( Eflags.Bits.IOPL = 3; AsmWriteEflags (Eflags.UintN); // - // Enable SYSCALL and SYSRET + // Enable SYSCALL and SYSRET. // MsrEfer.Uint64 = AsmReadMsr64 (MSR_IA32_EFER); MsrEfer.Bits.SCE = 1; diff --git a/MdePkg/Library/BaseLib/X64/SwitchStack.nasm b/MdePkg/Library/BaseLib/X64/SwitchStack.nasm index 986e5eab41..f7fb758269 100644 --- a/MdePkg/Library/BaseLib/X64/SwitchStack.nasm +++ b/MdePkg/Library/BaseLib/X64/SwitchStack.nasm @@ -113,22 +113,45 @@ ASM_PFX(CoreBootServices): cmp r10, 0 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. - mov [rsp], rcx - mov [rsp + 8], r11 + push rcx + push r11 ; Replace argument according to UEFI calling convention. mov rcx, rdx mov rdx, r8 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 r10 ; Prepare SYSRET arguments. - mov rcx, [rsp] - mov r11, [rsp + 8] + pop r11 + 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. o64 sysret @@ -137,3 +160,10 @@ o64 sysret readMemory: mov rax, [rdx] o64 sysret + + +SECTION .data + +global ASM_PFX(gCoreSysCallStackTop) +ASM_PFX(gCoreSysCallStackTop): + resq 1 diff --git a/MdePkg/Library/Ring3UefiBootServicesTableLib/Ring3UefiBootServicesTableLib.c b/MdePkg/Library/Ring3UefiBootServicesTableLib/Ring3UefiBootServicesTableLib.c index cb5e21107e..1d5ae5064f 100644 --- a/MdePkg/Library/Ring3UefiBootServicesTableLib/Ring3UefiBootServicesTableLib.c +++ b/MdePkg/Library/Ring3UefiBootServicesTableLib/Ring3UefiBootServicesTableLib.c @@ -94,7 +94,7 @@ UefiBootServicesTableLibConstructor ( (UINTN)SystemTable + OFFSET_OF (EFI_SYSTEM_TABLE, BootServices) ); ASSERT (mCoreBS != NULL); - // DEBUG ((DEBUG_ERROR, "User: BootServices = %p\n", mCoreBS)); + DEBUG ((DEBUG_ERROR, "User: BootServices = %p\n", mCoreBS)); return EFI_SUCCESS; }