Skip to content

Commit

Permalink
Ring3: Added SYSCALL draft.
Browse files Browse the repository at this point in the history
  • Loading branch information
Mikhail Krichanov committed Jan 19, 2024
1 parent cff574f commit 549c489
Show file tree
Hide file tree
Showing 10 changed files with 134 additions and 45 deletions.
15 changes: 15 additions & 0 deletions MdeModulePkg/Core/Dxe/Image/Image.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include "DxeMain.h"
#include "Image.h"

#include <Register/Intel/ArchitecturalMsr.h>

//
// Module Globals
//
Expand Down Expand Up @@ -1599,6 +1601,7 @@ CoreStartImage (
VOID *BaseOfStack;
VOID *TopOfStack;
UINTN SizeOfStack;
UINT64 Msr;

Handle = ImageHandle;

Expand Down Expand Up @@ -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()
Expand All @@ -1723,6 +1727,17 @@ CoreStartImage (
EFI_MEMORY_XP | EFI_MEMORY_USER
);

// Software can access the old stack, if necessary, by referencing the old
// stack-segment selector and stack pointer saved on the new process stack.

Msr = ((((UINT64)RING3_CODE64_SEL - 16) << 16) | (UINT64)RING0_CODE64_SEL) << 32;
AsmWriteMsr64 (MSR_IA32_STAR, Msr);

Msr = (UINT64)(UINTN)AsmReadMemory;
AsmWriteMsr64 (MSR_IA32_LSTAR, Msr);

// protection keys

EnterUserImage (
(SWITCH_STACK_ENTRY_POINT)(UINTN)Image->EntryPoint,
ImageHandle,
Expand Down
9 changes: 9 additions & 0 deletions MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -705,6 +707,7 @@ CreateIdentityMappingPageTables (
IA32_CR4 Cr4;
IA32_EFLAGS32 Eflags;
UINT32 Ebx;
MSR_IA32_EFER_REGISTER MsrEfer;

Ebx = 0;

Expand Down Expand Up @@ -995,6 +998,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;
Expand Down
11 changes: 9 additions & 2 deletions MdePkg/Include/Library/BaseLib.h
Original file line number Diff line number Diff line change
Expand Up @@ -5290,16 +5290,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)

Expand Down Expand Up @@ -6311,6 +6312,12 @@ AsmReadEflags (
VOID
);

UINTN
EFIAPI
AsmReadMemory (
IN UINTN Address
);

/**
Reads the current value of the Control Register 0 (CR0).
Expand Down
16 changes: 16 additions & 0 deletions MdePkg/Library/BaseLib/X64/SwitchStack.nasm
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,19 @@ o16 mov gs, ax

; Pass control to user image
retfq

;------------------------------------------------------------------------------
; UINTN
; EFIAPI
; AsmReadMemory (
; IN UINTN Address
; );
;------------------------------------------------------------------------------
global ASM_PFX(AsmReadMemory)
ASM_PFX(AsmReadMemory):
; SYSCALL saves RFLAGS into R11 and the RIP of the next instruction into RCX.
; Address is in RDX
mov rax, [rdx]

; SYSRET copies the value in RCX into RIP and loads RFLAGS from R11.
sysret
14 changes: 14 additions & 0 deletions MdePkg/Library/Ring3UefiBootServicesTableLib/Ring3.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
/** @file
Copyright (c) 2024, Mikhail Krichanov. All rights reserved.
SPDX-License-Identifier: BSD-3-Clause
**/

UINTN
EFIAPI
SysCall (
IN UINTN Address
);


/**
Raise the task priority level to the new level.
High level is implemented by disabling processor interrupts.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <Uefi.h>

#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>

#include "Ring3.h"

Expand Down Expand Up @@ -67,8 +68,9 @@ EFI_BOOT_SERVICES mBootServices = {
};

// EFI_HANDLE gImageHandle = NULL;
// EFI_SYSTEM_TABLE *gST = NULL;
EFI_SYSTEM_TABLE *mCoreST = NULL;
EFI_BOOT_SERVICES *gBS = &mBootServices;
EFI_BOOT_SERVICES *mCoreBS = NULL;

/**
The function constructs Ring 3 wrappers for the EFI_BOOT_SERVICES.
Expand All @@ -95,14 +97,15 @@ UefiBootServicesTableLibConstructor (
//
// Cache pointer to the EFI System Table
//
// gST = SystemTable;
// ASSERT (gST != NULL);
mCoreST = SystemTable;
ASSERT (mCoreST != NULL);

//
// Cache pointer to the EFI Boot Services Table
//
// gBS = SystemTable->BootServices;
// ASSERT (gBS != NULL);
mCoreBS = (EFI_BOOT_SERVICES *)SysCall ((UINTN)SystemTable + OFFSET_OF (EFI_SYSTEM_TABLE, BootServices));
ASSERT (mCoreBS != NULL);
DEBUG ((DEBUG_ERROR, "User: BootServices = %p\n", mCoreBS));

return EFI_SUCCESS;
}
Expand Down Expand Up @@ -512,6 +515,19 @@ Ring3LocateProtocol (
OUT VOID **Interface
)
{
// SysCall (
// OFFSET_OF (mBootServices, Ring3LocateProtocol),
// Protocol,
// Registration,
// Interface
// );

// Status = gBS->LocateProtocol (
// &gEfiDevicePathUtilitiesProtocolGuid,
// NULL,
// (VOID **)&mDevicePathLibDevicePathUtilities
// );

return EFI_SUCCESS;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,12 @@
Ring3.h
Ring3UefiBootServicesTableLib.c

[Sources.X64]
X64/SysCall.nasm

[Packages]
MdePkg/MdePkg.dec


[LibraryClasses]
BaseMemoryLib
DebugLib
26 changes: 26 additions & 0 deletions MdePkg/Library/Ring3UefiBootServicesTableLib/X64/SysCall.nasm
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
;------------------------------------------------------------------------------
; Copyright (c) 2024, Mikhail Krichanov. All rights reserved.
; SPDX-License-Identifier: BSD-3-Clause
;------------------------------------------------------------------------------

DEFAULT REL
SECTION .text

; extern ASM_PFX(mCoreBS)

;------------------------------------------------------------------------------
; UINTN
; EFIAPI
; SysCall (
; IN UINTN Address
; );
;------------------------------------------------------------------------------
global ASM_PFX(SysCall)
ASM_PFX(SysCall):
mov rdx, 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
55 changes: 20 additions & 35 deletions UefiCpuPkg/Library/CpuArchLib/CpuGdt.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -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,

Expand All @@ -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
// },
};

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -249,8 +249,6 @@ ArchSetupExceptionStack (
IdtTable[Vector].Bits.Reserved_0 = (UINT8)(Index + 1);
}

// Tss->RSP0 = %rsp

//
// Publish GDT
//
Expand Down

0 comments on commit 549c489

Please sign in to comment.