Ring3: Moved SysCall code to DxeCore.

This commit is contained in:
Mikhail Krichanov 2024-02-02 11:26:53 +03:00
parent b1d42c0979
commit 32e8bcbb62
9 changed files with 339 additions and 354 deletions

View File

@ -2823,4 +2823,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

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -5114,17 +5114,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.
@ -6596,14 +6585,6 @@ AsmReadEflags (
VOID
);
UINTN
EFIAPI
CoreBootServices (
IN UINT8 Type,
IN UINTN FunctionAddress,
...
);
/**
Reads the current value of the Control Register 0 (CR0).

View File

@ -332,71 +332,6 @@ InternalSwitchStack (
IN VA_LIST Marker
);
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
);
VOID
EFIAPI
DisableSMAP (
VOID
);
VOID
EFIAPI
EnableSMAP (
VOID
);
typedef enum {
SysCallReadMemory = 0,
SysCallAllocateRing3Pages = 1,
SysCallAllocateCoreCopy = 2,
SysCallLocateProtocol = 3,
SysCallOpenProtocol = 4,
SysCallMax
} SYS_CALL_TYPE;
typedef
UINTN
(EFIAPI *EFI_ALLOCATE_RING3_PAGES)(
IN UINTN Pages,
IN OUT VOID **Memory
);
typedef
VOID *
(EFIAPI *EFI_ALLOCATE_CORE_COPY)(
IN UINTN AllocationSize,
IN CONST VOID *Buffer
);
typedef
UINTN
(EFIAPI *EFI_LOCATE_PROTOCOL)(
IN VOID *Protocol,
IN VOID *Registration OPTIONAL,
OUT VOID **Interface
);
typedef
UINTN
(EFIAPI *EFI_OPEN_PROTOCOL)(
IN VOID * Handle,
IN VOID *Protocol,
OUT VOID **Interface OPTIONAL,
IN VOID * AgentHandle,
IN VOID * ControllerHandle,
IN UINT32 Attributes
);
/**
Worker function that returns a bit field from Operand.

View File

@ -68,113 +68,3 @@ SwitchStack (
//
ASSERT (FALSE);
}
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);
}
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;
}

View File

@ -1,6 +1,4 @@
;------------------------------------------------------------------------------
; Copyright (c) 2024, Mikhail Krichanov. All rights reserved.
; SPDX-License-Identifier: BSD-3-Clause
;
; Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>
; SPDX-License-Identifier: BSD-2-Clause-Patent
@ -16,8 +14,6 @@
DEFAULT REL
SECTION .text
extern ASM_PFX(CallBootService)
;------------------------------------------------------------------------------
; Routine Description:
;
@ -46,158 +42,3 @@ ASM_PFX(InternalSwitchStack):
;
lea rsp, [r9 - 0x20]
call rax
;------------------------------------------------------------------------------
; 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
%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
SECTION .data
global ASM_PFX(gCoreSysCallStackTop)
ASM_PFX(gCoreSysCallStackTop):
resq 1