Ring3: Saved ReturnSP on SysCallStack.

This commit is contained in:
Mikhail Krichanov 2025-01-20 19:45:00 +03:00
parent aeacf20255
commit 82c76dee94
14 changed files with 69 additions and 88 deletions

View File

@ -12,9 +12,7 @@
typedef
EFI_STATUS
(EFIAPI *EFI_SYS_CALL_BOOT_SERVICE)(
IN UINT8 Type,
IN VOID *CoreRbp,
IN VOID *UserRsp
IN EFI_SYSTEM_CONTEXT Context
);
/**

View File

@ -44,7 +44,7 @@ This is the stack constructed by the exception handler (low address to high addr
LR 0x54 # SVC Link register (we need to restore it)
TTBR0 0x58
Padding 0x5c
SP_EL1 0x5c
LR 0x60 # pushed by srsfd
CPSR 0x64
@ -101,7 +101,7 @@ ASM_PFX(Fiq):
ASM_PFX(ResetEntry):
srsdb #0x13! @ Store return state on SVC stack
@ We are already in SVC mode
sub SP, SP, #0x8 @ Save space for TTBR0
sub SP, SP, #0x8 @ Save space for TTBR0 and SP_EL1
stmfd SP!,{LR} @ Store the link register for the current mode
sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR
stmfd SP!,{R0-R12} @ Store the register state
@ -114,7 +114,7 @@ ASM_PFX(UndefinedInstructionEntry):
sub LR, LR, #4 @ Only -2 for Thumb, adjust in CommonExceptionEntry
srsdb #0x13! @ Store return state on SVC stack
cps #0x13 @ Switch to SVC for common stack
sub SP, SP, #0x8 @ Save space for TTBR0
sub SP, SP, #0x8 @ Save space for TTBR0 and SP_EL1
stmfd SP!,{LR} @ Store the link register for the current mode
sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR
stmfd SP!,{R0-R12} @ Store the register state
@ -128,7 +128,7 @@ ASM_PFX(SoftwareInterruptEntry):
isb
srsdb #0x13! @ Store return state on SVC stack
@ We are already in SVC mode
sub SP, SP, #0x8 @ Save space for TTBR0
sub SP, SP, #0x8 @ Save space for TTBR0 and SP_EL1
stmfd SP!,{LR} @ Store the link register for the current mode
sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR
stmfd SP!,{R0-R12} @ Store the register state
@ -141,7 +141,7 @@ ASM_PFX(PrefetchAbortEntry):
sub LR,LR,#4
srsdb #0x13! @ Store return state on SVC stack
cps #0x13 @ Switch to SVC for common stack
sub SP, SP, #0x8 @ Save space for TTBR0
sub SP, SP, #0x8 @ Save space for TTBR0 and SP_EL1
stmfd SP!,{LR} @ Store the link register for the current mode
sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR
stmfd SP!,{R0-R12} @ Store the register state
@ -154,7 +154,7 @@ ASM_PFX(DataAbortEntry):
sub LR,LR,#8
srsdb #0x13! @ Store return state on SVC stack
cps #0x13 @ Switch to SVC for common stack
sub SP, SP, #0x8 @ Save space for TTBR0
sub SP, SP, #0x8 @ Save space for TTBR0 and SP_EL1
stmfd SP!,{LR} @ Store the link register for the current mode
sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR
stmfd SP!,{R0-R12} @ Store the register state
@ -166,7 +166,7 @@ ASM_PFX(DataAbortEntry):
ASM_PFX(ReservedExceptionEntry):
srsdb #0x13! @ Store return state on SVC stack
cps #0x13 @ Switch to SVC for common stack
sub SP, SP, #0x8 @ Save space for TTBR0
sub SP, SP, #0x8 @ Save space for TTBR0 and SP_EL1
stmfd SP!,{LR} @ Store the link register for the current mode
sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR
stmfd SP!,{R0-R12} @ Store the register state
@ -179,7 +179,7 @@ ASM_PFX(IrqEntry):
sub LR,LR,#4
srsdb #0x13! @ Store return state on SVC stack
cps #0x13 @ Switch to SVC for common stack
sub SP, SP, #0x8 @ Save space for TTBR0
sub SP, SP, #0x8 @ Save space for TTBR0 and SP_EL1
stmfd SP!,{LR} @ Store the link register for the current mode
sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR
stmfd SP!,{R0-R12} @ Store the register state
@ -192,7 +192,7 @@ ASM_PFX(FiqEntry):
sub LR,LR,#4
srsdb #0x13! @ Store return state on SVC stack
cps #0x13 @ Switch to SVC for common stack
sub SP, SP, #0x8 @ Save space for TTBR0
sub SP, SP, #0x8 @ Save space for TTBR0 and SP_EL1
stmfd SP!,{LR} @ Store the link register for the current mode
sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR
stmfd SP!,{R0-R12} @ Store the register state
@ -242,6 +242,8 @@ ASM_PFX(AsmCommonExceptionEntry):
addne R1, SP, #0x68 @ We pushed 0x68 bytes on the stack
strne R1, [SP, #0x34] @ Store it in EFI_SYSTEM_CONTEXT_ARM.SP
add R1, SP, #0x68 @ We pushed 0x68 bytes on the stack
str R1, [SP, #0x5c] @ Store it in EFI_SYSTEM_CONTEXT_ARM.SP_EL1
ldr R5, [SP, #0x60] @ PC is the LR pushed by srsfd
@ Check to see if we have to adjust for Thumb entry
@ -334,7 +336,7 @@ NoTTBR0Switch2:
add SP,SP,#0x20 @ Clear out the remaining stack space
ldmfd SP!,{LR} @ restore the link register for this context
add SP, SP, #0x8 @ Clear out TTBR0 and Padding
add SP, SP, #0x8 @ Clear out TTBR0 and SP_EL1
rfefd SP! @ return from exception via srsfd stack slot
ASM_FUNC_ALIGN(ExceptionHandlerFinal, 4096)

View File

@ -211,11 +211,7 @@ DefaultExceptionHandler (
INT32 Offset;
if (AARCH64_ESR_EC (SystemContext.SystemContextAArch64->ESR) == AARCH64_ESR_EC_SVC64) {
return mSysCallHandler (
SystemContext.SystemContextAArch64->X0,
&(SystemContext.SystemContextAArch64->X1),
&(SystemContext.SystemContextAArch64->X0)
);
return mSysCallHandler (SystemContext);
}
if (mRecursiveException) {

View File

@ -224,11 +224,7 @@ DefaultExceptionHandler (
UINT32 PcAdjust;
if (ExceptionType == EXCEPT_ARM_SOFTWARE_INTERRUPT) {
return mSysCallHandler (
SystemContext.SystemContextArm->R0,
&(SystemContext.SystemContextArm->R1),
(VOID *)SystemContext.SystemContextArm->SP
);
return mSysCallHandler (SystemContext);
}
PcAdjust = 0;

View File

@ -240,7 +240,6 @@ typedef struct {
UINTN UserPageTable;
UINTN UserStackTop;
UINTN SysCallStackTop;
UINTN ReturnSP;
LIST_ENTRY Link;
} USER_SPACE_DRIVER;
@ -2738,7 +2737,8 @@ EFI_STATUS
EFIAPI
CallBootService (
IN UINT8 Type,
IN UINTN *UserArguments
IN UINTN *UserArguments,
IN UINTN ReturnSP
);
VOID

View File

@ -62,16 +62,14 @@ ASM_FUNC_ALIGN(SysCallBase, 4096)
// CallRing3 (
// IN RING3_CALL_DATA *Data,
// IN UINTN UserStackTop,
// IN UINTN SysCallStackTop,
// IN UINTN *ReturnSP
// IN UINTN SysCallStackTop
// );
//
// (x0) Data
// (x1) UserStackTop
// (x2) gRing3EntryPoint
// (x3) SysCallStackTop
// (x4) ReturnSP
// (x5) gUserPageTable
// (x4) gUserPageTable
//------------------------------------------------------------------------------
ASM_FUNC(ArmCallRing3)
// Save registers.
@ -94,10 +92,10 @@ ASM_FUNC(ArmCallRing3)
// Disable interrupts.
msr daifset, #0xf
isb
// Save Core SP and switch to SysCallStackTop.
// Switch to SysCallStackTop and save ReturnSP on it.
mov x6, sp
str x6, [x4]
mov sp, x3
stp x6, xzr, [sp, #-0x10]!
// Copy PSTATE to SPSR.
mrs x6, nzcv
mrs x7, pan
@ -107,12 +105,12 @@ ASM_FUNC(ArmCallRing3)
EL1_OR_EL2(x1)
1:msr elr_el1, x2
msr spsr_el1, x6
msr ttbr0_el1, x5
msr ttbr0_el1, x4
tlbi vmalle1
b 3f
2:msr elr_el2, x2
msr spsr_el2, x6
msr ttbr0_el2, x5
msr ttbr0_el2, x4
tlbi alle2
3:dsb sy
isb

View File

@ -21,7 +21,6 @@ ArmCallRing3 (
IN UINTN UserStackTop,
IN VOID *EntryPoint,
IN UINTN SysCallStackTop,
IN UINTN *ReturnSP,
IN UINTN UserPageTable
);
@ -29,9 +28,7 @@ STATIC
EFI_STATUS
EFIAPI
SysCallBootService (
IN UINT8 Type,
IN VOID *CoreRbp,
IN VOID *UserRsp
IN EFI_SYSTEM_CONTEXT Context
)
{
EFI_STATUS Status;
@ -42,7 +39,7 @@ SysCallBootService (
Status = CoreAllocatePages (
AllocateAnyPages,
EfiRing3MemoryType,
EFI_SIZE_TO_PAGES (9 * sizeof (UINTN)),
EFI_SIZE_TO_PAGES (8 * sizeof (UINTN)),
&Physical
);
if (EFI_ERROR (Status)) {
@ -50,12 +47,13 @@ SysCallBootService (
}
AllowSupervisorAccessToUserMemory ();
CopyMem ((VOID *)((UINTN)Physical + sizeof (UINTN)), (VOID *)UserRsp, 8 * sizeof (UINTN));
CopyMem ((VOID *)Physical, (VOID *)&(Context.SystemContextAArch64->X0), 8 * sizeof (UINTN));
ForbidSupervisorAccessToUserMemory ();
Status = CallBootService (
Type,
(UINTN *)((UINTN)Physical + sizeof (UINTN))
Context.SystemContextAArch64->X0,
(UINTN *)Physical,
*(UINTN *)Context.SystemContextAArch64->SP
);
CoreFreePages (Physical, EFI_SIZE_TO_PAGES (9 * sizeof (UINTN)));
@ -151,8 +149,7 @@ EFIAPI
CallRing3 (
IN RING3_CALL_DATA *Data,
IN UINTN UserStackTop,
IN UINTN SysCallStackTop,
IN UINTN *ReturnSP
IN UINTN SysCallStackTop
)
{
return ArmCallRing3 (
@ -160,7 +157,6 @@ CallRing3 (
UserStackTop,
gRing3EntryPoint,
SysCallStackTop,
ReturnSP,
gUserPageTable
);
}

View File

@ -58,8 +58,7 @@ ASM_FUNC_ALIGN(SysCallBase, 4096)
// CallRing3 (
// IN RING3_CALL_DATA *Data,
// IN UINTN UserStackTop,
// IN UINTN SysCallStackTop,
// IN UINTN *ReturnSP
// IN UINTN SysCallStackTop
// );
//
// (r0) Data
@ -67,15 +66,13 @@ ASM_FUNC_ALIGN(SysCallBase, 4096)
// (r2) gRing3EntryPoint
// (r3) SysCallStackTop
//
// (On Core Stack) ReturnSP, gUserPageTable
// (On Core Stack) gUserPageTable
//------------------------------------------------------------------------------
ASM_FUNC(ArmCallRing3)
// Save registers.
push {R4-R12, LR}
// R6 is ReturnSP
ldr R6, [SP, #0x28]
// R7 is gUserPageTable
ldr R7, [SP, #0x2C]
ldr R7, [SP, #0x28]
// Save old SP_usr and LR_usr on Core Stack.
sub SP, SP, #0x8
stmia SP, {SP, LR}^
@ -98,10 +95,11 @@ ASM_FUNC(ArmCallRing3)
// Set SPSR M[3:0] bits to User mode.
and R4, R4, #0xFFFFFFF0
// Save Core SP and switch to SysCallStackTop.
// Switch to SysCallStackTop and save ReturnSP on it.
mov R5, SP
str R5, [R6]
mov SP, R3
push {R5}
push {R5} // Align stack on 8 bytes
// Switch to UserPageTable.
mrc p15,0,R8,c2,c0,0 // R8 == TTBR0
@ -115,7 +113,7 @@ ASM_FUNC(ArmCallRing3)
push {R4}
push {R2}
rfefd SP
rfefd SP!
ASM_FUNC_ALIGN(SysCallEnd, 4096)
//------------------------------------------------------------------------------

View File

@ -20,7 +20,6 @@ ArmCallRing3 (
IN UINTN UserStackTop,
IN VOID *EntryPoint,
IN UINTN SysCallStackTop,
IN UINTN *ReturnSP,
IN UINTN UserPageTable
);
@ -28,9 +27,7 @@ STATIC
EFI_STATUS
EFIAPI
SysCallBootService (
IN UINT8 Type,
IN VOID *CoreRbp,
IN VOID *UserRsp
IN EFI_SYSTEM_CONTEXT Context
)
{
EFI_STATUS Status;
@ -41,7 +38,7 @@ SysCallBootService (
Status = CoreAllocatePages (
AllocateAnyPages,
EfiRing3MemoryType,
EFI_SIZE_TO_PAGES (9 * sizeof (UINTN)),
EFI_SIZE_TO_PAGES (8 * sizeof (UINTN)),
&Physical
);
if (EFI_ERROR (Status)) {
@ -52,16 +49,17 @@ SysCallBootService (
//
// First 3 arguments are passed through R1-R3 and copied to SysCall Stack.
//
CopyMem ((VOID *)((UINTN)Physical + 2 * sizeof (UINTN)), (VOID *)CoreRbp, 3 * sizeof (UINTN));
CopyMem ((VOID *)(UINTN)Physical, (VOID *)&(Context.SystemContextArm->R0), 4 * sizeof (UINTN));
//
// All remaining arguments are on User Stack.
//
CopyMem ((VOID *)((UINTN)Physical + 5 * sizeof (UINTN)), (VOID *)UserRsp, 4 * sizeof (UINTN));
CopyMem ((VOID *)((UINTN)Physical + 4 * sizeof (UINTN)), (VOID *)Context.SystemContextArm->SP, 4 * sizeof (UINTN));
ForbidSupervisorAccessToUserMemory ();
Status = CallBootService (
Type,
(UINTN *)((UINTN)Physical + sizeof (UINTN))
Context.SystemContextArm->R0,
(UINTN *)(UINTN)Physical,
*(UINTN *)Context.SystemContextArm->SP_EL1
);
//
// TODO: Fix memory leak for ReturnToCore().
@ -146,8 +144,7 @@ EFIAPI
CallRing3 (
IN RING3_CALL_DATA *Data,
IN UINTN UserStackTop,
IN UINTN SysCallStackTop,
IN UINTN *ReturnSP
IN UINTN SysCallStackTop
)
{
return ArmCallRing3 (
@ -155,7 +152,6 @@ CallRing3 (
UserStackTop,
gRing3EntryPoint,
SysCallStackTop,
ReturnSP,
gUserPageTable
);
}

View File

@ -318,7 +318,7 @@ FindUserInfo (
for (Link = gUserSpaceDriversHead.ForwardLink; Link != &gUserSpaceDriversHead; Link = Link->ForwardLink) {
UserDriver = BASE_CR (Link, USER_SPACE_DRIVER, Link);
if ((UserDriver->UserPageTable == gUserPageTable) && (UserDriver->ReturnSP != 0)) {
if (UserDriver->UserPageTable == gUserPageTable) {
return UserDriver;
}
}
@ -330,7 +330,8 @@ EFI_STATUS
EFIAPI
CallBootService (
IN UINT8 Type,
IN UINTN *UserArguments
IN UINTN *UserArguments,
IN UINTN ReturnSP
)
{
EFI_STATUS Status;
@ -372,10 +373,8 @@ CallBootService (
switch (Type) {
case SysCallReturnToCore:
Arguments = CopyUserArguments (1, UserArguments);
UserDriver = FindUserInfo ();
ASSERT (UserDriver != NULL);
ReturnToCore (Arguments[1], UserDriver->ReturnSP);
ReturnToCore (Arguments[1], ReturnSP);
break;
case SysCallLocateProtocol:
//
@ -531,7 +530,6 @@ CallBootService (
NewDriver->UserPageTable = UserDriver->UserPageTable;
NewDriver->UserStackTop = UserDriver->UserStackTop;
NewDriver->SysCallStackTop = UserDriver->SysCallStackTop;
NewDriver->ReturnSP = 0;
InsertTailList (&gUserSpaceDriversHead, &NewDriver->Link);

View File

@ -133,6 +133,8 @@ ASM_PFX(CoreBootServices):
; Prepare CallBootService arguments.
mov ebp, esp
mov eax, [esp + 4*3]
push eax ; ReturnSP
add edx, 4 ; User Arguments[]
push edx
push ecx ; Type
@ -166,11 +168,10 @@ ASM_PFX(CoreBootServices):
; CallRing3 (
; IN RING3_CALL_DATA *Data,
; IN UINTN UserStackTop,
; IN UINTN SysCallStackTop,
; IN UINTN *ReturnSP
; IN UINTN SysCallStackTop
; );
;
; (On User Stack) Data, UserStackTop, SysCallStackTop, ReturnSP
; (On User Stack) Data, UserStackTop, SysCallStackTop
;------------------------------------------------------------------------------
global ASM_PFX(CallRing3)
ASM_PFX(CallRing3):
@ -186,15 +187,16 @@ ASM_PFX(CallRing3):
pop ebx
push eax
; Save Core Stack pointer.
mov ebx, [esp + 4 * 9] ; ReturnSP
mov [ebx], esp
; Set new SysCallStackTop.
mov edx, 0
mov eax, [esp + 4 * 8] ; SysCallStackTop
sub eax, 4
mov ecx, MSR_IA32_SYSENTER_ESP
wrmsr
; Save ReturnSP on SysCallStack.
mov [eax], esp
SetRing3DataSegmentSelectors
; Prepare SYSEXIT arguments.

View File

@ -15,8 +15,7 @@ EFIAPI
CallRing3 (
IN RING3_CALL_DATA *Data,
IN UINTN UserStackTop,
IN UINTN SysCallStackTop,
IN UINTN *ReturnSP
IN UINTN SysCallStackTop
);
EFI_STATUS
@ -66,12 +65,10 @@ GoToRing3 (
Status = CallRing3 (
Input,
UserDriver->UserStackTop,
UserDriver->SysCallStackTop,
&UserDriver->ReturnSP
UserDriver->SysCallStackTop
);
CoreFreePages (Ring3Pages, PagesNumber);
UserDriver->ReturnSP = 0;
return Status;
}

View File

@ -162,6 +162,8 @@ ASM_PFX(CoreBootServices):
mov rcx, r10 ; Type
mov rdx, [rbp + 8*3]
add rdx, 8 ; User Arguments[]
mov rax, [ASM_PFX(SysCallStackTop)]
mov r8, [rax] ; ReturnSP
sti
call ASM_PFX(CallBootService)
@ -195,14 +197,12 @@ o64 sysret
; CallRing3 (
; IN RING3_CALL_DATA *Data,
; IN UINTN UserStackTop,
; IN UINTN SysCallStackTop,
; IN UINTN *ReturnSP
; IN UINTN SysCallStackTop
; );
;
; (rcx) Data
; (rdx) UserStackTop
; (r8) SysCallStackTop
; (r9) ReturnSP
;------------------------------------------------------------------------------
global ASM_PFX(CallRing3)
ASM_PFX(CallRing3):
@ -220,8 +220,9 @@ ASM_PFX(CallRing3):
push r15
push qword [ASM_PFX(SysCallStackTop)]
; Save Core Stack pointer.
mov [r9], rsp
; Save ReturnSP on SysCallStack.
sub r8, 8
mov [r8], rsp
; Save input Arguments.
mov rbx, rdx

View File

@ -507,6 +507,9 @@ typedef struct {
UINT32 DFAR;
UINT32 IFSR;
UINT32 IFAR;
UINT32 SVC_LR;
UINT32 TTBR0;
UINT32 SP_EL1;
} EFI_SYSTEM_CONTEXT_ARM;
///