diff --git a/MdeModulePkg/Core/Dxe/DxeMain.h b/MdeModulePkg/Core/Dxe/DxeMain.h index 328890495f..3e72054103 100644 --- a/MdeModulePkg/Core/Dxe/DxeMain.h +++ b/MdeModulePkg/Core/Dxe/DxeMain.h @@ -2729,4 +2729,11 @@ GoToRing3 ( ... ); +EFI_STATUS +EFIAPI +InitializeRing3 ( + IN EFI_HANDLE ImageHandle, + IN LOADED_IMAGE_PRIVATE_DATA *Image + ); + #endif diff --git a/MdeModulePkg/Core/Dxe/DxeMain.inf b/MdeModulePkg/Core/Dxe/DxeMain.inf index a7db34c55f..efbda12787 100644 --- a/MdeModulePkg/Core/Dxe/DxeMain.inf +++ b/MdeModulePkg/Core/Dxe/DxeMain.inf @@ -66,6 +66,7 @@ DxeMain/DxeProtocolNotify.c DxeMain/DxeMain.c SysCall/BootServices.c + SysCall/Initialization.c SysCall/SupportedProtocols.h SysCall/SupportedProtocols.c diff --git a/MdeModulePkg/Core/Dxe/Image/Image.c b/MdeModulePkg/Core/Dxe/Image/Image.c index 2f2473be62..e2f00739a8 100644 --- a/MdeModulePkg/Core/Dxe/Image/Image.c +++ b/MdeModulePkg/Core/Dxe/Image/Image.c @@ -9,8 +9,6 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include "DxeMain.h" #include "Image.h" -#include - // // Module Globals // @@ -27,11 +25,6 @@ STATIC EFI_EVENT mPeCoffEmuProtocolRegistrationEvent; STATIC VOID *mPeCoffEmuProtocolNotifyRegistration; extern BOOLEAN gBdsStarted; -VOID *gCoreSysCallStackTop; -VOID *gRing3CallStackTop; -VOID *gRing3EntryPoint; -RING3_DATA *gRing3Data; -VOID *gRing3Interfaces; // // This code is needed to build the Image handle for the DXE Core @@ -1570,144 +1563,6 @@ CoreLoadImage ( return Status; } -EFI_STATUS -EFIAPI -InitializeRing3 ( - IN EFI_HANDLE ImageHandle, - IN LOADED_IMAGE_PRIVATE_DATA *Image - ) -{ - EFI_STATUS Status; - VOID *BaseOfStack; - VOID *TopOfStack; - UINTN SizeOfStack; - UINT64 Msr; - IA32_CR4 Cr4; - IA32_EFLAGS32 Eflags; - UINT32 Ebx; - UINT32 Edx; - MSR_IA32_EFER_REGISTER MsrEfer; - - Ebx = 0; - Edx = 0; - - // - // Set Ring3 EntryPoint and BootServices. - // - Status = CoreAllocatePages ( - AllocateAnyPages, - EfiRing3MemoryType, - EFI_SIZE_TO_PAGES (sizeof (RING3_DATA)), - (EFI_PHYSICAL_ADDRESS *)&gRing3Data - ); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "Core: Failed to allocate memory for Ring3Data.\n")); - return Status; - } - - CopyMem ((VOID *)gRing3Data, (VOID *)Image->Info.SystemTable, sizeof (EFI_SYSTEM_TABLE)); - - Status = Image->EntryPoint (ImageHandle, (EFI_SYSTEM_TABLE *)gRing3Data); - - gRing3EntryPoint = gRing3Data->EntryPoint; - - gRing3Data->SystemTable.BootServices = gRing3Data->BootServices; - gRing3Data->SystemTable.RuntimeServices = gRing3Data->RuntimeServices; - - Status = CoreAllocatePages ( - AllocateAnyPages, - EfiRing3MemoryType, - RING3_INTERFACES_PAGES, - (EFI_PHYSICAL_ADDRESS *)&gRing3Interfaces - ); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "Core: Failed to allocate memory for Ring3Interfaces.\n")); - CoreFreePages ( - (EFI_PHYSICAL_ADDRESS)gRing3Data, - EFI_SIZE_TO_PAGES (sizeof (RING3_DATA)) - ); - return Status; - } - - // - // Forbid supervisor-mode accesses to any user-mode pages. - // SMEP and SMAP must be supported. - // - AsmCpuidEx (0x07, 0x0, NULL, &Ebx, NULL, NULL); - // - // SYSCALL and SYSRET must be also supported. - // - 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.SMEP = 1; - AsmWriteCr4 (Cr4.UintN); - - Eflags.UintN = AsmReadEflags (); - Eflags.Bits.AC = 0; - AsmWriteEflags (Eflags.UintN); - // - // Enable SYSCALL and SYSRET. - // - MsrEfer.Uint64 = AsmReadMsr64 (MSR_IA32_EFER); - MsrEfer.Bits.SCE = 1; - AsmWriteMsr64 (MSR_IA32_EFER, MsrEfer.Uint64); - } - - 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; - - SetUefiImageMemoryAttributes ((UINTN)BaseOfStack, SizeOfStack, EFI_MEMORY_XP); - DEBUG ((DEBUG_ERROR, "Core: gCoreSysCallStackTop = %p\n", gCoreSysCallStackTop)); - - // - // Allocate 128KB for the User 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); - - gRing3CallStackTop = TopOfStack; - - SetUefiImageMemoryAttributes ((UINTN)BaseOfStack, SizeOfStack, EFI_MEMORY_XP | EFI_MEMORY_USER); - DEBUG ((DEBUG_ERROR, "Core: gRing3CallStackTop = %p\n", gRing3CallStackTop)); - - // - // Initialize MSR_IA32_STAR, MSR_IA32_LSTAR and MSR_IA32_FMASK for SYSCALL and SYSRET. - // - Msr = (((((UINT64)RING3_CODE64_SEL - 16) | 3) << 16) | (UINT64)RING0_CODE64_SEL) << 32; - AsmWriteMsr64 (MSR_IA32_STAR, Msr); - - Msr = (UINT64)(UINTN)CoreBootServices; - AsmWriteMsr64 (MSR_IA32_LSTAR, Msr); - // - // Disable maskable interrupts at SYSCALL. - // - Msr = (UINT64)BIT9; - AsmWriteMsr64 (MSR_IA32_FMASK, Msr); - - return Status; -} - /** Transfer control to a loaded image's entry point. diff --git a/MdeModulePkg/Core/Dxe/SysCall/Initialization.c b/MdeModulePkg/Core/Dxe/SysCall/Initialization.c new file mode 100644 index 0000000000..7ad0424a30 --- /dev/null +++ b/MdeModulePkg/Core/Dxe/SysCall/Initialization.c @@ -0,0 +1,154 @@ +/** @file + + Copyright (c) 2024, Mikhail Krichanov. All rights reserved. + SPDX-License-Identifier: BSD-3-Clause + +**/ + +#include "DxeMain.h" + +#include + +VOID *gCoreSysCallStackTop; +VOID *gRing3CallStackTop; +VOID *gRing3EntryPoint; +RING3_DATA *gRing3Data; +VOID *gRing3Interfaces; + +EFI_STATUS +EFIAPI +InitializeRing3 ( + IN EFI_HANDLE ImageHandle, + IN LOADED_IMAGE_PRIVATE_DATA *Image + ) +{ + EFI_STATUS Status; + VOID *BaseOfStack; + VOID *TopOfStack; + UINTN SizeOfStack; + UINT64 Msr; + IA32_CR4 Cr4; + IA32_EFLAGS32 Eflags; + UINT32 Ebx; + UINT32 Edx; + MSR_IA32_EFER_REGISTER MsrEfer; + + Ebx = 0; + Edx = 0; + + // + // Set Ring3 EntryPoint and BootServices. + // + Status = CoreAllocatePages ( + AllocateAnyPages, + EfiRing3MemoryType, + EFI_SIZE_TO_PAGES (sizeof (RING3_DATA)), + (EFI_PHYSICAL_ADDRESS *)&gRing3Data + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Core: Failed to allocate memory for Ring3Data.\n")); + return Status; + } + + CopyMem ((VOID *)gRing3Data, (VOID *)Image->Info.SystemTable, sizeof (EFI_SYSTEM_TABLE)); + + Status = Image->EntryPoint (ImageHandle, (EFI_SYSTEM_TABLE *)gRing3Data); + + gRing3EntryPoint = gRing3Data->EntryPoint; + + gRing3Data->SystemTable.BootServices = gRing3Data->BootServices; + gRing3Data->SystemTable.RuntimeServices = gRing3Data->RuntimeServices; + + Status = CoreAllocatePages ( + AllocateAnyPages, + EfiRing3MemoryType, + RING3_INTERFACES_PAGES, + (EFI_PHYSICAL_ADDRESS *)&gRing3Interfaces + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Core: Failed to allocate memory for Ring3Interfaces.\n")); + CoreFreePages ( + (EFI_PHYSICAL_ADDRESS)gRing3Data, + EFI_SIZE_TO_PAGES (sizeof (RING3_DATA)) + ); + return Status; + } + + // + // Forbid supervisor-mode accesses to any user-mode pages. + // SMEP and SMAP must be supported. + // + AsmCpuidEx (0x07, 0x0, NULL, &Ebx, NULL, NULL); + // + // SYSCALL and SYSRET must be also supported. + // + 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.SMEP = 1; + AsmWriteCr4 (Cr4.UintN); + + Eflags.UintN = AsmReadEflags (); + Eflags.Bits.AC = 0; + AsmWriteEflags (Eflags.UintN); + // + // Enable SYSCALL and SYSRET. + // + MsrEfer.Uint64 = AsmReadMsr64 (MSR_IA32_EFER); + MsrEfer.Bits.SCE = 1; + AsmWriteMsr64 (MSR_IA32_EFER, MsrEfer.Uint64); + } + + 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; + + SetUefiImageMemoryAttributes ((UINTN)BaseOfStack, SizeOfStack, EFI_MEMORY_XP); + DEBUG ((DEBUG_ERROR, "Core: gCoreSysCallStackTop = %p\n", gCoreSysCallStackTop)); + + // + // Allocate 128KB for the User 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); + + gRing3CallStackTop = TopOfStack; + + SetUefiImageMemoryAttributes ((UINTN)BaseOfStack, SizeOfStack, EFI_MEMORY_XP | EFI_MEMORY_USER); + DEBUG ((DEBUG_ERROR, "Core: gRing3CallStackTop = %p\n", gRing3CallStackTop)); + + // + // Initialize MSR_IA32_STAR, MSR_IA32_LSTAR and MSR_IA32_FMASK for SYSCALL and SYSRET. + // + Msr = (((((UINT64)RING3_CODE64_SEL - 16) | 3) << 16) | (UINT64)RING0_CODE64_SEL) << 32; + AsmWriteMsr64 (MSR_IA32_STAR, Msr); + + Msr = (UINT64)(UINTN)CoreBootServices; + AsmWriteMsr64 (MSR_IA32_LSTAR, Msr); + // + // Disable maskable interrupts at SYSCALL. + // + Msr = (UINT64)BIT9; + AsmWriteMsr64 (MSR_IA32_FMASK, Msr); + + return Status; +}