Skip to content

Commit

Permalink
Ring3: Moved SysCall code to DxeCore.
Browse files Browse the repository at this point in the history
  • Loading branch information
Mikhail Krichanov committed Feb 2, 2024
1 parent 4153e95 commit 50016e9
Show file tree
Hide file tree
Showing 9 changed files with 339 additions and 354 deletions.
19 changes: 19 additions & 0 deletions MdeModulePkg/Core/Dxe/DxeMain.h
Original file line number Diff line number Diff line change
Expand Up @@ -2817,4 +2817,23 @@ SetUefiImageMemoryAttributes (
IN UINT64 Attributes
);

UINTN
EFIAPI
CoreBootServices (
IN UINT8 Type,
IN UINTN FunctionAddress,
...
);

VOID
EFIAPI
EnterUserImage (
IN SWITCH_STACK_ENTRY_POINT EntryPoint,
IN VOID *Context1 OPTIONAL,
IN VOID *Context2 OPTIONAL,
IN VOID *NewStack,
IN UINT16 CodeSelector,
IN UINT16 DataSelector
);

#endif
4 changes: 4 additions & 0 deletions MdeModulePkg/Core/Dxe/DxeMain.inf
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@
Dispatcher/Dispatcher.c
DxeMain/DxeProtocolNotify.c
DxeMain/DxeMain.c
SysCall/BootServices.c

[Sources.X64]
SysCall/X64/CoreBootServices.nasm

[Packages]
MdePkg/MdePkg.dec
Expand Down
2 changes: 1 addition & 1 deletion MdeModulePkg/Core/Dxe/Image/Image.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ STATIC EFI_EVENT mPeCoffEmuProtocolRegistrationEvent;
STATIC VOID *mPeCoffEmuProtocolNotifyRegistration;

extern BOOLEAN gBdsStarted;
extern VOID *gCoreSysCallStackTop;
VOID *gCoreSysCallStackTop;

//
// This code is needed to build the Image handle for the DXE Core
Expand Down
154 changes: 154 additions & 0 deletions MdeModulePkg/Core/Dxe/SysCall/BootServices.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
/** @file
Copyright (c) 2024, Mikhail Krichanov. All rights reserved.
SPDX-License-Identifier: BSD-3-Clause
**/

#include <Base.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/PcdLib.h>

VOID
EFIAPI
DisableSMAP (
VOID
);

VOID
EFIAPI
EnableSMAP (
VOID
);

VOID
EFIAPI
InternalEnterUserImage (
IN SWITCH_STACK_ENTRY_POINT EntryPoint,
IN VOID *Context1 OPTIONAL,
IN VOID *Context2 OPTIONAL,
IN VOID *NewStack,
IN UINT16 CodeSelector,
IN UINT16 DataSelector
);

typedef enum {
SysCallReadMemory = 0,
SysCallAllocateRing3Pages = 1,
SysCallAllocateCoreCopy = 2,
SysCallLocateProtocol = 3,
SysCallOpenProtocol = 4,
SysCallMax
} SYS_CALL_TYPE;

UINTN
EFIAPI
CallBootService (
IN UINT8 Type,
IN VOID **FunctionAddress,
IN UINTN CoreRbp,
IN UINTN UserRsp
)
{
UINTN Status;
VOID *Pointer;
VOID * Arg4;
VOID * Arg5;
UINT32 Arg6;
EFI_ALLOCATE_RING3_PAGES Func1;
EFI_ALLOCATE_CORE_COPY Func2;
EFI_LOCATE_PROTOCOL Func3;
EFI_OPEN_PROTOCOL Func4;
// Stack:
// rcx - Rip for SYSCALL
// r8 - Argument 1
// rbp - User Rbp
// r9 - Argument 2
// r11 - User data segment selector <- CoreRbp
// rsp - User Rsp
switch (Type) {
case SysCallReadMemory:
return *(UINTN *)FunctionAddress;

case SysCallAllocateRing3Pages:
Func1 = (EFI_ALLOCATE_RING3_PAGES)*FunctionAddress;
Status = Func1 (
*((UINTN *)CoreRbp + 3),
&Pointer
);
DisableSMAP ();
*(UINTN *)(*((UINTN *)CoreRbp + 1)) = (UINTN)Pointer;
EnableSMAP ();
return (UINTN)Status;

case SysCallAllocateCoreCopy:
DisableSMAP ();
Func2 = (EFI_ALLOCATE_CORE_COPY)*FunctionAddress;
Status = (UINTN)Func2 (
*((UINTN *)CoreRbp + 3),
(VOID *)*((UINTN *)CoreRbp + 1)
);
EnableSMAP ();
return (UINTN)Status;

case SysCallLocateProtocol:
Func3 = (EFI_LOCATE_PROTOCOL)*FunctionAddress;
Status = Func3 (
(VOID *)*((UINTN *)CoreRbp + 3),
(VOID *)*((UINTN *)CoreRbp + 1),
&Pointer
);
DisableSMAP ();
*((UINTN *)UserRsp + 5) = (UINTN)Pointer;
EnableSMAP ();
return (UINTN)Status;

case SysCallOpenProtocol:
DisableSMAP ();
Arg4 = (VOID *)*((UINTN *)UserRsp + 6);
Arg5 = (VOID *)*((UINTN *)UserRsp + 7);
Arg6 = (UINT32)*((UINTN *)UserRsp + 8);
EnableSMAP ();
Func4 = (EFI_OPEN_PROTOCOL)*FunctionAddress;
Status = Func4 (
(VOID *)*((UINTN *)CoreRbp + 3),
(VOID *)*((UINTN *)CoreRbp + 1),
&Pointer,
Arg4,
Arg5,
Arg6
);
DisableSMAP ();
*((UINTN *)UserRsp + 5) = (UINTN)Pointer;
EnableSMAP ();
return (UINTN)Status;
default:
break;
}

return 0;
}

VOID
EFIAPI
EnterUserImage (
IN SWITCH_STACK_ENTRY_POINT EntryPoint,
IN VOID *Context1 OPTIONAL,
IN VOID *Context2 OPTIONAL,
IN VOID *NewStack,
IN UINT16 CodeSelector,
IN UINT16 DataSelector
)
{
ASSERT (EntryPoint != NULL);
ASSERT (NewStack != NULL);

//
// New stack must be aligned with CPU_STACK_ALIGNMENT
//
ASSERT (((UINTN)NewStack & (CPU_STACK_ALIGNMENT - 1)) == 0);

InternalEnterUserImage (EntryPoint, Context1, Context2, NewStack, CodeSelector, DataSelector);
}
161 changes: 161 additions & 0 deletions MdeModulePkg/Core/Dxe/SysCall/X64/CoreBootServices.nasm
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
;------------------------------------------------------------------------------
;
; Copyright (c) 2024, Mikhail Krichanov. All rights reserved.
; SPDX-License-Identifier: BSD-3-Clause
;
;------------------------------------------------------------------------------

DEFAULT REL
SECTION .text

extern ASM_PFX(CallBootService)
extern ASM_PFX(gCoreSysCallStackTop)

%macro CallSysRet 0
; Prepare SYSRET arguments.
mov rcx, [rbp + 8*4]
pop rdx

; Switch from Core to User data segment selectors.
pop r11

o16 mov ds, r11
o16 mov es, r11
o16 mov fs, r11
o16 mov gs, r11

; Restore RFLAGS in R11 for SYSRET.
pushfq
pop r11

; Switch to User Stack.
pop rbp
pop rbp
mov rsp, rdx

; 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.
%endmacro

global ASM_PFX(DisableSMAP)
ASM_PFX(DisableSMAP):
pushfq
pop r10
or r10, 0x40000 ; Set AC (bit 18)
push r10
popfq
ret

global ASM_PFX(EnableSMAP)
ASM_PFX(EnableSMAP):
pushfq
pop r10
and r10, ~0x40000 ; Clear AC (bit 18)
push r10
popfq
ret

;------------------------------------------------------------------------------
; UINTN
; EFIAPI
; CoreBootServices (
; IN UINT8 Type,
; IN UINTN FunctionAddress,
; ...
; );
;
; (rcx) RIP of the next instruction saved by SYSCALL in SysCall().
; (rdx) FunctionAddress.
; (r8) Argument 1 of the called function.
; (r9) Argument 2 of the called function.
; (r10) Type.
; (r11) RFLAGS saved by SYSCALL in SysCall().
;On stack Argument 3, 4, ...
;------------------------------------------------------------------------------
global ASM_PFX(CoreBootServices)
ASM_PFX(CoreBootServices):
; Save User data segment selector temporarily in R11.
mov r11, ds

; Switch from User to Core data segment selectors.
mov ax, ss
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax

; Save User Stack pointers and switch to Core SysCall Stack.
mov rax, [ASM_PFX(gCoreSysCallStackTop)]
; Save return address for SYSRET.
sub rax, 8
mov [rax], rcx
mov rcx, r10
sub rax, 8
mov [rax], r8
sub rax, 8
mov [rax], rbp
sub rax, 8
mov [rax], r9
; Save User data segment selector on Core SysCall Stack.
sub rax, 8
mov [rax], r11

mov r9, rsp

mov rsp, rax

mov rbp, rsp
mov r8, rbp
push r9

call ASM_PFX(CallBootService)

CallSysRet

;------------------------------------------------------------------------------
; Routine Description:
;
; Routine for transfering control to user image with 2 parameters
;
; Arguments:
;
; (rcx) EntryPoint - Entry point with new stack.
; (rdx) Context1 - Parameter1 for entry point.
; (r8) Context2 - Parameter2 for entry point.
; (r9) NewStack - The pointer to new stack.
;On stack CodeSelector - Segment selector for code.
;On stack DataSelector - Segment selector for data.
;
; Returns:
;
; None
;
;------------------------------------------------------------------------------
global ASM_PFX(InternalEnterUserImage)
ASM_PFX(InternalEnterUserImage):
; Set Data selectors
mov rax, [rsp + 8*6]
or rax, 3H ; RPL = 3

mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax

; Save Code selector
mov r10, [rsp + 8*5]
or r10, 3H ; RPL = 3

; Prepare stack before swithcing
push rax ; ss
push r9 ; rsp
push r10 ; cs
push rcx ; rip

; Save 2 parameters
mov rcx, rdx
mov rdx, r8

; Pass control to user image
retfq
19 changes: 0 additions & 19 deletions MdePkg/Include/Library/BaseLib.h
Original file line number Diff line number Diff line change
Expand Up @@ -4830,17 +4830,6 @@ SwitchStack (
...
);

VOID
EFIAPI
EnterUserImage (
IN SWITCH_STACK_ENTRY_POINT EntryPoint,
IN VOID *Context1 OPTIONAL,
IN VOID *Context2 OPTIONAL,
IN VOID *NewStack,
IN UINT16 CodeSelector,
IN UINT16 DataSelector
);

/**
Generates a breakpoint on the CPU.
Expand Down Expand Up @@ -6312,14 +6301,6 @@ AsmReadEflags (
VOID
);

UINTN
EFIAPI
CoreBootServices (
IN UINT8 Type,
IN UINTN FunctionAddress,
...
);

/**
Reads the current value of the Control Register 0 (CR0).
Expand Down
Loading

0 comments on commit 50016e9

Please sign in to comment.