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
MdeModulePkg/Core
Dxe/Image
DxeIplPeim/X64
MdePkg
UefiCpuPkg/Library
CpuArchLib
CpuExceptionHandlerLib/X64

View File

@ -9,6 +9,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include "DxeMain.h"
#include "Image.h"
#include <Register/Intel/ArchitecturalMsr.h>
//
// Module Globals
//
@ -1599,6 +1601,7 @@ CoreStartImage (
VOID *BaseOfStack;
VOID *TopOfStack;
UINTN SizeOfStack;
UINT64 Msr;
Handle = ImageHandle;
@ -1713,6 +1716,7 @@ CoreStartImage (
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));
//
// Necessary fix for ProcessLibraryConstructorList() -> DxeCcProbeLibConstructor()
@ -1723,6 +1727,19 @@ CoreStartImage (
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 (
(SWITCH_STACK_ENTRY_POINT)(UINTN)Image->EntryPoint,
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 "DxeIpl.h"
#include "VirtualMemory.h"
@ -705,8 +707,11 @@ CreateIdentityMappingPageTables (
IA32_CR4 Cr4;
IA32_EFLAGS32 Eflags;
UINT32 Ebx;
UINT32 Edx;
MSR_IA32_EFER_REGISTER MsrEfer;
Ebx = 0;
Edx = 0;
//
// Set PageMapLevel5Entry to suppress incorrect compiler/analyzer warnings
@ -984,7 +989,11 @@ CreateIdentityMappingPageTables (
// SMEP and SMAP must be supported.
//
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.Bits.SMAP = 1;
Cr4.Bits.SMEP = 1;
@ -997,6 +1006,12 @@ CreateIdentityMappingPageTables (
//
Eflags.Bits.IOPL = 3;
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;

View File

@ -5574,16 +5574,17 @@ typedef struct {
DATA_SEGMENT_32 SysData;
CODE_SEGMENT_32 SysCode;
CODE_SEGMENT_32 SysCode16;
DATA_SEGMENT_32 LinearData64;
CODE_SEGMENT_64 LinearCode64;
DATA_SEGMENT_32 LinearData64;
SEGMENT_DESCRIPTOR Spare5;
DATA_SEGMENT_32 Ring3Data64;
CODE_SEGMENT_64 Ring3Code64;
// CALL_GATE_64 FromRing3ToRing0;
} GDT;
#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_CODE64_SEL OFFSET_OF (GDT, Ring3Code64)
@ -6595,6 +6596,13 @@ AsmReadEflags (
VOID
);
UINTN
EFIAPI
CoreBootServices (
IN UINTN FunctionAddress,
...
);
/**
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
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.
High level is implemented by disabling processor interrupts.

View File

@ -9,6 +9,7 @@
#include <Uefi.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include "Ring3.h"
@ -66,9 +67,8 @@ EFI_BOOT_SERVICES mBootServices = {
(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.
@ -86,23 +86,15 @@ UefiBootServicesTableLibConstructor (
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
//
// gBS = SystemTable->BootServices;
// ASSERT (gBS != NULL);
mCoreBS = (EFI_BOOT_SERVICES *)SysCall (
0,
(UINTN)SystemTable + OFFSET_OF (EFI_SYSTEM_TABLE, BootServices)
);
ASSERT (mCoreBS != NULL);
// DEBUG ((DEBUG_ERROR, "User: BootServices = %p\n", mCoreBS));
return EFI_SUCCESS;
}
@ -512,7 +504,16 @@ Ring3LocateProtocol (
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

View File

@ -26,9 +26,12 @@
Ring3.h
Ring3UefiBootServicesTableLib.c
[Sources.X64]
X64/SysCall.nasm
[Packages]
MdePkg/MdePkg.dec
[LibraryClasses]
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,
.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 = {
.SegmentLimit_15_0 = 0xFFFF,
.BaseAddress_15_0 = 0x0,
@ -149,25 +168,6 @@ STATIC GDT mGdtTemplate = {
.Granularity = 1,
.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 = {
.SegmentLimit_15_0 = 0x0,
.BaseAddress_15_0 = 0x0,
@ -203,7 +203,7 @@ STATIC GDT mGdtTemplate = {
.Granularity = 1,
.BaseAddress_31_24 = 0x0
},
.Ring3Code64 = { // SetCodeSelector () | 5.8.6 Returning from a Called Procedure
.Ring3Code64 = {
.Reserved1 = 0x0,
.Reserved2 = 0x0,
@ -222,21 +222,6 @@ STATIC GDT mGdtTemplate = {
.Granularity = 1,
.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);
}
// Tss->RSP0 = %rsp
//
// Publish GDT
//