Ring3: Added SYSCALL draft.

This commit is contained in:
Mikhail Krichanov 2024-01-22 17:29:38 +03:00
parent 233a5cff09
commit 6502e73b0d
10 changed files with 173 additions and 59 deletions

View File

@ -9,6 +9,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include "DxeMain.h" #include "DxeMain.h"
#include "Image.h" #include "Image.h"
#include <Register/Intel/ArchitecturalMsr.h>
// //
// Module Globals // Module Globals
// //
@ -1599,6 +1601,7 @@ CoreStartImage (
VOID *BaseOfStack; VOID *BaseOfStack;
VOID *TopOfStack; VOID *TopOfStack;
UINTN SizeOfStack; UINTN SizeOfStack;
UINT64 Msr;
Handle = ImageHandle; Handle = ImageHandle;
@ -1713,6 +1716,7 @@ CoreStartImage (
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, "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));
// //
// Necessary fix for ProcessLibraryConstructorList() -> DxeCcProbeLibConstructor() // Necessary fix for ProcessLibraryConstructorList() -> DxeCcProbeLibConstructor()
@ -1723,6 +1727,19 @@ CoreStartImage (
EFI_MEMORY_XP | EFI_MEMORY_USER EFI_MEMORY_XP | EFI_MEMORY_USER
); );
//
// Initialize MSR_IA32_STAR and MSR_IA32_LSTAR for SYSCALL and SYSRET.
//
Msr = ((((UINT64)RING3_CODE64_SEL - 16) << 16) | (UINT64)RING0_CODE64_SEL) << 32;
AsmWriteMsr64 (MSR_IA32_STAR, Msr);
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 ( EnterUserImage (
(SWITCH_STACK_ENTRY_POINT)(UINTN)Image->EntryPoint, (SWITCH_STACK_ENTRY_POINT)(UINTN)Image->EntryPoint,
ImageHandle, ImageHandle,

View File

@ -22,7 +22,9 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
**/ **/
#include <Register/Intel/ArchitecturalMsr.h>
#include <Register/Intel/Cpuid.h> #include <Register/Intel/Cpuid.h>
#include "DxeIpl.h" #include "DxeIpl.h"
#include "VirtualMemory.h" #include "VirtualMemory.h"
@ -705,8 +707,11 @@ CreateIdentityMappingPageTables (
IA32_CR4 Cr4; IA32_CR4 Cr4;
IA32_EFLAGS32 Eflags; IA32_EFLAGS32 Eflags;
UINT32 Ebx; UINT32 Ebx;
UINT32 Edx;
MSR_IA32_EFER_REGISTER MsrEfer;
Ebx = 0; Ebx = 0;
Edx = 0;
// //
// Set PageMapLevel5Entry to suppress incorrect compiler/analyzer warnings // Set PageMapLevel5Entry to suppress incorrect compiler/analyzer warnings
@ -984,7 +989,11 @@ CreateIdentityMappingPageTables (
// SMEP and SMAP must be supported. // SMEP and SMAP must be supported.
// //
AsmCpuidEx (0x07, 0x0, NULL, &Ebx, NULL, NULL); AsmCpuidEx (0x07, 0x0, NULL, &Ebx, NULL, NULL);
if (((Ebx & BIT20) != 0) && ((Ebx & BIT7) != 0)) { //
// 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.UintN = AsmReadCr4 ();
Cr4.Bits.SMAP = 1; Cr4.Bits.SMAP = 1;
Cr4.Bits.SMEP = 1; Cr4.Bits.SMEP = 1;
@ -997,6 +1006,12 @@ CreateIdentityMappingPageTables (
// //
Eflags.Bits.IOPL = 3; Eflags.Bits.IOPL = 3;
AsmWriteEflags (Eflags.UintN); AsmWriteEflags (Eflags.UintN);
//
// Enable SYSCALL and SYSRET
//
MsrEfer.Uint64 = AsmReadMsr64 (MSR_IA32_EFER);
MsrEfer.Bits.SCE = 1;
AsmWriteMsr64 (MSR_IA32_EFER, MsrEfer.Uint64);
} }
return (UINTN)PageMap; return (UINTN)PageMap;

View File

@ -5574,16 +5574,17 @@ typedef struct {
DATA_SEGMENT_32 SysData; DATA_SEGMENT_32 SysData;
CODE_SEGMENT_32 SysCode; CODE_SEGMENT_32 SysCode;
CODE_SEGMENT_32 SysCode16; CODE_SEGMENT_32 SysCode16;
DATA_SEGMENT_32 LinearData64;
CODE_SEGMENT_64 LinearCode64; CODE_SEGMENT_64 LinearCode64;
DATA_SEGMENT_32 LinearData64;
SEGMENT_DESCRIPTOR Spare5; SEGMENT_DESCRIPTOR Spare5;
DATA_SEGMENT_32 Ring3Data64; DATA_SEGMENT_32 Ring3Data64;
CODE_SEGMENT_64 Ring3Code64; CODE_SEGMENT_64 Ring3Code64;
// CALL_GATE_64 FromRing3ToRing0;
} GDT; } GDT;
#pragma pack () #pragma pack ()
#define RING0_DATA64_SEL OFFSET_OF (GDT, LinearData64)
#define RING0_CODE64_SEL OFFSET_OF (GDT, LinearCode64)
#define RING3_DATA64_SEL OFFSET_OF (GDT, Ring3Data64) #define RING3_DATA64_SEL OFFSET_OF (GDT, Ring3Data64)
#define RING3_CODE64_SEL OFFSET_OF (GDT, Ring3Code64) #define RING3_CODE64_SEL OFFSET_OF (GDT, Ring3Code64)
@ -6595,6 +6596,13 @@ AsmReadEflags (
VOID VOID
); );
UINTN
EFIAPI
CoreBootServices (
IN UINTN FunctionAddress,
...
);
/** /**
Reads the current value of the Control Register 0 (CR0). Reads the current value of the Control Register 0 (CR0).

View File

@ -91,3 +91,49 @@ o16 mov gs, ax
; Pass control to user image ; Pass control to user image
retfq retfq
;------------------------------------------------------------------------------
; UINTN
; EFIAPI
; CoreBootServices (
; IN UINTN FunctionAddress,
; ...
; );
;
; (rcx) RIP of the next instruction saved by SYSCALL in SysCall().
; (rdx) Argument 1 of the called function.
; (r8) Argument 2 of the called function.
; (r9) Argument 3 of the called function.
; (r10) FunctionAddress.
; (r11) RFLAGS saved by SYSCALL in SysCall().
;On stack Argument 4, 5, ...
;------------------------------------------------------------------------------
global ASM_PFX(CoreBootServices)
ASM_PFX(CoreBootServices):
cmp r10, 0
je readMemory
; Save return address and RFLAGS for SYSRET.
mov [rsp], rcx
mov [rsp + 8], r11
; Replace argument according to UEFI calling convention.
mov rcx, rdx
mov rdx, r8
mov r8, r9
mov r9, [rsp + 8*3]
; Call Boot Service by FunctionAddress.
call r10
; Prepare SYSRET arguments.
mov rcx, [rsp]
mov r11, [rsp + 8]
; SYSCALL saves RFLAGS into R11 and the RIP of the next instruction into RCX.
o64 sysret
; SYSRET copies the value in RCX into RIP and loads RFLAGS from R11.
readMemory:
mov rax, [rdx]
o64 sysret

View File

@ -1,3 +1,18 @@
/** @file
Copyright (c) 2024, Mikhail Krichanov. All rights reserved.
SPDX-License-Identifier: BSD-3-Clause
**/
UINTN
EFIAPI
SysCall (
IN UINTN FunctionAddress,
...
);
/** /**
Raise the task priority level to the new level. Raise the task priority level to the new level.
High level is implemented by disabling processor interrupts. High level is implemented by disabling processor interrupts.

View File

@ -9,6 +9,7 @@
#include <Uefi.h> #include <Uefi.h>
#include <Library/BaseMemoryLib.h> #include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include "Ring3.h" #include "Ring3.h"
@ -66,9 +67,8 @@ EFI_BOOT_SERVICES mBootServices = {
(EFI_CREATE_EVENT_EX)Ring3CreateEventEx // CreateEventEx (EFI_CREATE_EVENT_EX)Ring3CreateEventEx // CreateEventEx
}; };
// EFI_HANDLE gImageHandle = NULL;
// EFI_SYSTEM_TABLE *gST = NULL;
EFI_BOOT_SERVICES *gBS = &mBootServices; EFI_BOOT_SERVICES *gBS = &mBootServices;
EFI_BOOT_SERVICES *mCoreBS = NULL;
/** /**
The function constructs Ring 3 wrappers for the EFI_BOOT_SERVICES. The function constructs Ring 3 wrappers for the EFI_BOOT_SERVICES.
@ -86,23 +86,15 @@ UefiBootServicesTableLibConstructor (
IN EFI_SYSTEM_TABLE *SystemTable IN EFI_SYSTEM_TABLE *SystemTable
) )
{ {
//
// Cache the Image Handle
//
// gImageHandle = ImageHandle;
// ASSERT (gImageHandle != NULL);
//
// Cache pointer to the EFI System Table
//
// gST = SystemTable;
// ASSERT (gST != NULL);
// //
// Cache pointer to the EFI Boot Services Table // Cache pointer to the EFI Boot Services Table
// //
// gBS = SystemTable->BootServices; mCoreBS = (EFI_BOOT_SERVICES *)SysCall (
// ASSERT (gBS != NULL); 0,
(UINTN)SystemTable + OFFSET_OF (EFI_SYSTEM_TABLE, BootServices)
);
ASSERT (mCoreBS != NULL);
// DEBUG ((DEBUG_ERROR, "User: BootServices = %p\n", mCoreBS));
return EFI_SUCCESS; return EFI_SUCCESS;
} }
@ -512,7 +504,16 @@ Ring3LocateProtocol (
OUT VOID **Interface OUT VOID **Interface
) )
{ {
return EFI_SUCCESS; EFI_STATUS Status;
Status = (EFI_STATUS)SysCall (
(UINTN)mCoreBS + OFFSET_OF (EFI_BOOT_SERVICES, LocateProtocol),
Protocol,
Registration,
Interface
);
return Status;
} }
EFI_STATUS EFI_STATUS

View File

@ -26,9 +26,12 @@
Ring3.h Ring3.h
Ring3UefiBootServicesTableLib.c Ring3UefiBootServicesTableLib.c
[Sources.X64]
X64/SysCall.nasm
[Packages] [Packages]
MdePkg/MdePkg.dec MdePkg/MdePkg.dec
[LibraryClasses] [LibraryClasses]
BaseMemoryLib BaseMemoryLib
DebugLib

View File

@ -0,0 +1,26 @@
;------------------------------------------------------------------------------
; Copyright (c) 2024, Mikhail Krichanov. All rights reserved.
; SPDX-License-Identifier: BSD-3-Clause
;------------------------------------------------------------------------------
DEFAULT REL
SECTION .text
;------------------------------------------------------------------------------
; UINTN
; EFIAPI
; SysCall (
; IN UINTN FunctionAddress,
; ...
; );
;------------------------------------------------------------------------------
global ASM_PFX(SysCall)
ASM_PFX(SysCall):
; Save FunctionAddress for CoreBootServices().
mov r10, rcx
; SYSCALL saves RFLAGS into R11 and the RIP of the next instruction into RCX.
syscall
; SYSRET copies the value in RCX into RIP and loads RFLAGS from R11.
ret

View File

@ -129,6 +129,25 @@ STATIC GDT mGdtTemplate = {
.Granularity = 1, .Granularity = 1,
.BaseAddress_31_24 = 0x0 .BaseAddress_31_24 = 0x0
}, },
.LinearCode64 = {
.Reserved1 = 0x0,
.Reserved2 = 0x0,
.Accessed = 0,
.Readable = 1,
.Conforming = 0,
.IsCode = 1,
.IsNotSystemSegment = 1,
.DescriptorPrivilegeLevel = 0,
.SegmentPresent = 1,
.Reserved3 = 0x0,
.Available = 0,
.LongMode = 1,
.Is32Bit = 0,
.Granularity = 1,
.Reserved4 = 0x0
},
.LinearData64 = { .LinearData64 = {
.SegmentLimit_15_0 = 0xFFFF, .SegmentLimit_15_0 = 0xFFFF,
.BaseAddress_15_0 = 0x0, .BaseAddress_15_0 = 0x0,
@ -149,25 +168,6 @@ STATIC GDT mGdtTemplate = {
.Granularity = 1, .Granularity = 1,
.BaseAddress_31_24 = 0x0 .BaseAddress_31_24 = 0x0
}, },
.LinearCode64 = {
.Reserved1 = 0x0,
.Reserved2 = 0x0,
.Accessed = 0,
.Readable = 1,
.Conforming = 0,
.IsCode = 1,
.IsNotSystemSegment = 1,
.DescriptorPrivilegeLevel = 0,
.SegmentPresent = 1,
.Reserved3 = 0x0,
.Available = 0,
.LongMode = 1,
.Is32Bit = 0,
.Granularity = 1,
.Reserved4 = 0x0
},
.Spare5 = { .Spare5 = {
.SegmentLimit_15_0 = 0x0, .SegmentLimit_15_0 = 0x0,
.BaseAddress_15_0 = 0x0, .BaseAddress_15_0 = 0x0,
@ -203,7 +203,7 @@ STATIC GDT mGdtTemplate = {
.Granularity = 1, .Granularity = 1,
.BaseAddress_31_24 = 0x0 .BaseAddress_31_24 = 0x0
}, },
.Ring3Code64 = { // SetCodeSelector () | 5.8.6 Returning from a Called Procedure .Ring3Code64 = {
.Reserved1 = 0x0, .Reserved1 = 0x0,
.Reserved2 = 0x0, .Reserved2 = 0x0,
@ -222,21 +222,6 @@ STATIC GDT mGdtTemplate = {
.Granularity = 1, .Granularity = 1,
.Reserved4 = 0x0 .Reserved4 = 0x0
}, },
// .FromRing3ToRing0 = {
// .Common.OffsetInSegment_15_0 = 0x?,
// .Common.SegmentSelector = (UINT16)LINEAR_CODE64_SEL,
//
// .Common.ParameterCount = 0,
// .Common.Reserved = 0,
//
// .Common.Type = 0xC,
// .Common.IsNotSystemSegment = 0,
// .Common.DescriptorPrivilegeLevel = 3,
// .Common.SegmentPresent = 1,
// .Common.OffsetInSegment_31_16 = 0x?,
// .OffsetInSegment_63_31 = 0x?,
// .Reserved = 0x0
// },
}; };
/** /**

View File

@ -249,8 +249,6 @@ ArchSetupExceptionStack (
IdtTable[Vector].Bits.Reserved_0 = (UINT8)(Index + 1); IdtTable[Vector].Bits.Reserved_0 = (UINT8)(Index + 1);
} }
// Tss->RSP0 = %rsp
// //
// Publish GDT // Publish GDT
// //