diff --git a/MdeModulePkg/Core/Dxe/DxeMain.h b/MdeModulePkg/Core/Dxe/DxeMain.h index f4082f184a..b73721928c 100644 --- a/MdeModulePkg/Core/Dxe/DxeMain.h +++ b/MdeModulePkg/Core/Dxe/DxeMain.h @@ -274,6 +274,7 @@ extern LOADED_IMAGE_PRIVATE_DATA * mCurrentImage; extern RING3_DATA *gRing3Data; extern VOID *gRing3Interfaces; extern VOID *gCoreSysCallStackBase; +extern VOID *gCoreSysCallStackTop; extern VOID *gRing3CallStackBase; // diff --git a/MdeModulePkg/Core/Dxe/DxeMain.inf b/MdeModulePkg/Core/Dxe/DxeMain.inf index 3ca09084b5..8d76d9082a 100644 --- a/MdeModulePkg/Core/Dxe/DxeMain.inf +++ b/MdeModulePkg/Core/Dxe/DxeMain.inf @@ -71,9 +71,11 @@ SysCall/SupportedProtocols.c [Sources.IA32] + SysCall/IA32/InitializeMsr.c SysCall/IA32/CoreBootServices.nasm [Sources.X64] + SysCall/X64/InitializeMsr.c SysCall/X64/CoreBootServices.nasm [Packages] diff --git a/MdeModulePkg/Core/Dxe/SysCall/IA32/InitializeMsr.c b/MdeModulePkg/Core/Dxe/SysCall/IA32/InitializeMsr.c new file mode 100644 index 0000000000..8c1859163e --- /dev/null +++ b/MdeModulePkg/Core/Dxe/SysCall/IA32/InitializeMsr.c @@ -0,0 +1,62 @@ +/** @file + + Copyright (c) 2024, Mikhail Krichanov. All rights reserved. + SPDX-License-Identifier: BSD-3-Clause + +**/ + +#include "DxeMain.h" + +#include + +VOID +EFIAPI +InitializeMsr ( + VOID + ) +{ + UINT64 Msr; + IA32_CR4 Cr4; + IA32_EFLAGS32 Eflags; + UINT32 Ebx; + UINT32 Edx; + + Ebx = 0; + Edx = 0; + + // + // Forbid supervisor-mode accesses to any user-mode pages. + // SMEP and SMAP must be supported. + // + AsmCpuidEx (0x07, 0x0, NULL, &Ebx, NULL, NULL); + // + // SYSENTER and SYSEXIT must be also supported. + // + AsmCpuidEx (0x01, 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); + } else { + DEBUG ((DEBUG_ERROR, "Core: Failed to initialize MSRs for Ring3.\n")); + ASSERT (FALSE); + } + + // + // Initialize MSR_IA32_SYSENTER_CS, MSR_IA32_SYSENTER_EIP and + // MSR_IA32_SYSENTER_ESP for SYSENTER and SYSEXIT. + // + Msr = RING0_CODE32_SEL; + AsmWriteMsr64 (MSR_IA32_SYSENTER_CS, Msr); + + Msr = (UINT64)(UINTN)CoreBootServices; + AsmWriteMsr64 (MSR_IA32_SYSENTER_EIP, Msr); + + Msr = (UINT64)(UINTN)gCoreSysCallStackTop; + AsmWriteMsr64 (MSR_IA32_SYSENTER_ESP, Msr); +} diff --git a/MdeModulePkg/Core/Dxe/SysCall/Initialization.c b/MdeModulePkg/Core/Dxe/SysCall/Initialization.c index be4e9f6a48..2d965b8a80 100644 --- a/MdeModulePkg/Core/Dxe/SysCall/Initialization.c +++ b/MdeModulePkg/Core/Dxe/SysCall/Initialization.c @@ -7,8 +7,6 @@ #include "DxeMain.h" -#include - VOID *gCoreSysCallStackTop; VOID *gCoreSysCallStackBase; VOID *gRing3CallStackTop; @@ -17,6 +15,12 @@ VOID *gRing3EntryPoint; RING3_DATA *gRing3Data; VOID *gRing3Interfaces; +VOID +EFIAPI +InitializeMsr ( + VOID + ); + EFI_STATUS EFIAPI InitializeRing3 ( @@ -27,15 +31,6 @@ InitializeRing3 ( EFI_STATUS Status; 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. @@ -75,32 +70,6 @@ InitializeRing3 ( 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; // @@ -137,19 +106,7 @@ InitializeRing3 ( SetUefiImageMemoryAttributes ((UINTN)gRing3CallStackBase, 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); + InitializeMsr (); return Status; } diff --git a/MdeModulePkg/Core/Dxe/SysCall/X64/InitializeMsr.c b/MdeModulePkg/Core/Dxe/SysCall/X64/InitializeMsr.c new file mode 100644 index 0000000000..171fdc5e7d --- /dev/null +++ b/MdeModulePkg/Core/Dxe/SysCall/X64/InitializeMsr.c @@ -0,0 +1,70 @@ +/** @file + + Copyright (c) 2024, Mikhail Krichanov. All rights reserved. + SPDX-License-Identifier: BSD-3-Clause + +**/ + +#include "DxeMain.h" + +#include + +VOID +EFIAPI +InitializeMsr ( + VOID + ) +{ + UINT64 Msr; + IA32_CR4 Cr4; + IA32_EFLAGS32 Eflags; + UINT32 Ebx; + UINT32 Edx; + MSR_IA32_EFER_REGISTER MsrEfer; + + Ebx = 0; + Edx = 0; + + // + // 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); + } else { + DEBUG ((DEBUG_ERROR, "Core: Failed to initialize MSRs for Ring3.\n")); + ASSERT (FALSE); + } + + // + // 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); +} diff --git a/MdePkg/Include/Library/BaseLib.h b/MdePkg/Include/Library/BaseLib.h index 16c77a57eb..a84a09c467 100644 --- a/MdePkg/Include/Library/BaseLib.h +++ b/MdePkg/Include/Library/BaseLib.h @@ -5560,8 +5560,10 @@ typedef struct { SEGMENT_DESCRIPTOR Null; DATA_SEGMENT_32 Linear; CODE_SEGMENT_32 LinearCode; - DATA_SEGMENT_32 SysData; CODE_SEGMENT_32 SysCode; + DATA_SEGMENT_32 SysData; + CODE_SEGMENT_32 Ring3Code32; + DATA_SEGMENT_32 Ring3Data32; CODE_SEGMENT_32 SysCode16; CODE_SEGMENT_64 LinearCode64; DATA_SEGMENT_32 LinearData64; @@ -5572,6 +5574,11 @@ typedef struct { #pragma pack () +#define RING0_DATA32_SEL OFFSET_OF (GDT, SysData) +#define RING0_CODE32_SEL OFFSET_OF (GDT, SysCode) +#define RING3_DATA32_SEL OFFSET_OF (GDT, Ring3Data32) +#define RING3_CODE32_SEL OFFSET_OF (GDT, Ring3Code32) + #define RING0_DATA64_SEL OFFSET_OF (GDT, LinearData64) #define RING0_CODE64_SEL OFFSET_OF (GDT, LinearCode64) #define RING3_DATA64_SEL OFFSET_OF (GDT, Ring3Data64) diff --git a/UefiCpuPkg/Library/CpuArchLib/CpuGdt.c b/UefiCpuPkg/Library/CpuArchLib/CpuGdt.c index 415d4126aa..9f029c12af 100644 --- a/UefiCpuPkg/Library/CpuArchLib/CpuGdt.c +++ b/UefiCpuPkg/Library/CpuArchLib/CpuGdt.c @@ -69,6 +69,26 @@ STATIC GDT mGdtTemplate = { .Granularity = 1, .BaseAddress_31_24 = 0x0 }, + .SysCode = { + .SegmentLimit_15_0 = 0xFFFF, + .BaseAddress_15_0 = 0x0, + .BaseAddress_23_16 = 0x0, + + .Accessed = 0, + .Readable = 1, + .Conforming = 0, + .IsCode = 1, + .IsNotSystemSegment = 1, + .DescriptorPrivilegeLevel = 0, + .SegmentPresent = 1, + + .SegmentLimit_19_16 = 0xF, + .Available = 0, + .Reserved = 0, + .Is32Bit = 1, + .Granularity = 1, + .BaseAddress_31_24 = 0x0 + }, .SysData = { .SegmentLimit_15_0 = 0xFFFF, .BaseAddress_15_0 = 0x0, @@ -89,7 +109,7 @@ STATIC GDT mGdtTemplate = { .Granularity = 1, .BaseAddress_31_24 = 0x0 }, - .SysCode = { + .Ring3Code32 = { .SegmentLimit_15_0 = 0xFFFF, .BaseAddress_15_0 = 0x0, .BaseAddress_23_16 = 0x0, @@ -99,7 +119,7 @@ STATIC GDT mGdtTemplate = { .Conforming = 0, .IsCode = 1, .IsNotSystemSegment = 1, - .DescriptorPrivilegeLevel = 0, + .DescriptorPrivilegeLevel = 3, .SegmentPresent = 1, .SegmentLimit_19_16 = 0xF, @@ -109,6 +129,26 @@ STATIC GDT mGdtTemplate = { .Granularity = 1, .BaseAddress_31_24 = 0x0 }, + .Ring3Data32 = { + .SegmentLimit_15_0 = 0xFFFF, + .BaseAddress_15_0 = 0x0, + .BaseAddress_23_16 = 0x0, + + .Accessed = 1, + .Writable = 1, + .ExpansionDirection = 0, + .IsCode = 0, + .IsNotSystemSegment = 1, + .DescriptorPrivilegeLevel = 3, + .SegmentPresent = 1, + + .SegmentLimit_19_16 = 0xF, + .Available = 0, + .Reserved = 0, + .UpperBound = 1, + .Granularity = 1, + .BaseAddress_31_24 = 0x0 + }, .SysCode16 = { .SegmentLimit_15_0 = 0xFFFF, .BaseAddress_15_0 = 0x0,