From 82c76dee94882f903be6c987e20383b758e685e0 Mon Sep 17 00:00:00 2001
From: Mikhail Krichanov <mikhailkrichanov@gmail.com>
Date: Mon, 20 Jan 2025 19:45:00 +0300
Subject: [PATCH] Ring3: Saved ReturnSP on SysCallStack.

---
 .../Library/DefaultExceptionHandlerLib.h      |  4 +---
 .../ArmExceptionLib/Arm/ExceptionSupport.S    | 22 ++++++++++---------
 .../AArch64/DefaultExceptionHandler.c         |  6 +----
 .../Arm/DefaultExceptionHandler.c             |  6 +----
 MdeModulePkg/Core/Dxe/DxeMain.h               |  4 ++--
 .../Dxe/SysCall/AARCH64/CoreBootServices.S    | 14 +++++-------
 .../Dxe/SysCall/AARCH64/InitializeAARCH64.c   | 18 ++++++---------
 .../Core/Dxe/SysCall/ARM/CoreBootServices.S   | 16 ++++++--------
 .../Core/Dxe/SysCall/ARM/InitializeARM.c      | 20 +++++++----------
 MdeModulePkg/Core/Dxe/SysCall/BootServices.c  | 10 ++++-----
 .../Dxe/SysCall/IA32/CoreBootServices.nasm    | 16 ++++++++------
 .../Core/Dxe/SysCall/SupportedProtocols.c     |  7 ++----
 .../Dxe/SysCall/X64/CoreBootServices.nasm     | 11 +++++-----
 MdePkg/Include/Protocol/DebugSupport.h        |  3 +++
 14 files changed, 69 insertions(+), 88 deletions(-)

diff --git a/ArmPkg/Include/Library/DefaultExceptionHandlerLib.h b/ArmPkg/Include/Library/DefaultExceptionHandlerLib.h
index 24893c6fa8..faa91fe589 100644
--- a/ArmPkg/Include/Library/DefaultExceptionHandlerLib.h
+++ b/ArmPkg/Include/Library/DefaultExceptionHandlerLib.h
@@ -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
   );
 
 /**
diff --git a/ArmPkg/Library/ArmExceptionLib/Arm/ExceptionSupport.S b/ArmPkg/Library/ArmExceptionLib/Arm/ExceptionSupport.S
index 9245a00dfe..ed6895a0ff 100644
--- a/ArmPkg/Library/ArmExceptionLib/Arm/ExceptionSupport.S
+++ b/ArmPkg/Library/ArmExceptionLib/Arm/ExceptionSupport.S
@@ -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)
diff --git a/ArmPkg/Library/DefaultExceptionHandlerLib/AArch64/DefaultExceptionHandler.c b/ArmPkg/Library/DefaultExceptionHandlerLib/AArch64/DefaultExceptionHandler.c
index f0ccf7b956..6e2efd724b 100644
--- a/ArmPkg/Library/DefaultExceptionHandlerLib/AArch64/DefaultExceptionHandler.c
+++ b/ArmPkg/Library/DefaultExceptionHandlerLib/AArch64/DefaultExceptionHandler.c
@@ -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) {
diff --git a/ArmPkg/Library/DefaultExceptionHandlerLib/Arm/DefaultExceptionHandler.c b/ArmPkg/Library/DefaultExceptionHandlerLib/Arm/DefaultExceptionHandler.c
index 8519642a8c..39d536c4bb 100644
--- a/ArmPkg/Library/DefaultExceptionHandlerLib/Arm/DefaultExceptionHandler.c
+++ b/ArmPkg/Library/DefaultExceptionHandlerLib/Arm/DefaultExceptionHandler.c
@@ -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;
diff --git a/MdeModulePkg/Core/Dxe/DxeMain.h b/MdeModulePkg/Core/Dxe/DxeMain.h
index 00343e3134..76ca0513cd 100644
--- a/MdeModulePkg/Core/Dxe/DxeMain.h
+++ b/MdeModulePkg/Core/Dxe/DxeMain.h
@@ -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
diff --git a/MdeModulePkg/Core/Dxe/SysCall/AARCH64/CoreBootServices.S b/MdeModulePkg/Core/Dxe/SysCall/AARCH64/CoreBootServices.S
index e6161dff8b..e5ea1c96a0 100644
--- a/MdeModulePkg/Core/Dxe/SysCall/AARCH64/CoreBootServices.S
+++ b/MdeModulePkg/Core/Dxe/SysCall/AARCH64/CoreBootServices.S
@@ -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
diff --git a/MdeModulePkg/Core/Dxe/SysCall/AARCH64/InitializeAARCH64.c b/MdeModulePkg/Core/Dxe/SysCall/AARCH64/InitializeAARCH64.c
index acbe3af845..fbc5581d81 100644
--- a/MdeModulePkg/Core/Dxe/SysCall/AARCH64/InitializeAARCH64.c
+++ b/MdeModulePkg/Core/Dxe/SysCall/AARCH64/InitializeAARCH64.c
@@ -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
             );
 }
diff --git a/MdeModulePkg/Core/Dxe/SysCall/ARM/CoreBootServices.S b/MdeModulePkg/Core/Dxe/SysCall/ARM/CoreBootServices.S
index 73d968b971..d34b6a8a07 100644
--- a/MdeModulePkg/Core/Dxe/SysCall/ARM/CoreBootServices.S
+++ b/MdeModulePkg/Core/Dxe/SysCall/ARM/CoreBootServices.S
@@ -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)
 //------------------------------------------------------------------------------
diff --git a/MdeModulePkg/Core/Dxe/SysCall/ARM/InitializeARM.c b/MdeModulePkg/Core/Dxe/SysCall/ARM/InitializeARM.c
index 34d5c43e2c..498037385b 100644
--- a/MdeModulePkg/Core/Dxe/SysCall/ARM/InitializeARM.c
+++ b/MdeModulePkg/Core/Dxe/SysCall/ARM/InitializeARM.c
@@ -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
             );
 }
diff --git a/MdeModulePkg/Core/Dxe/SysCall/BootServices.c b/MdeModulePkg/Core/Dxe/SysCall/BootServices.c
index 59bef0920e..184c3a7b62 100644
--- a/MdeModulePkg/Core/Dxe/SysCall/BootServices.c
+++ b/MdeModulePkg/Core/Dxe/SysCall/BootServices.c
@@ -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);
 
diff --git a/MdeModulePkg/Core/Dxe/SysCall/IA32/CoreBootServices.nasm b/MdeModulePkg/Core/Dxe/SysCall/IA32/CoreBootServices.nasm
index 72f8e66a22..9478b93345 100644
--- a/MdeModulePkg/Core/Dxe/SysCall/IA32/CoreBootServices.nasm
+++ b/MdeModulePkg/Core/Dxe/SysCall/IA32/CoreBootServices.nasm
@@ -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.
diff --git a/MdeModulePkg/Core/Dxe/SysCall/SupportedProtocols.c b/MdeModulePkg/Core/Dxe/SysCall/SupportedProtocols.c
index ddfa59a657..530f69238f 100644
--- a/MdeModulePkg/Core/Dxe/SysCall/SupportedProtocols.c
+++ b/MdeModulePkg/Core/Dxe/SysCall/SupportedProtocols.c
@@ -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;
 }
diff --git a/MdeModulePkg/Core/Dxe/SysCall/X64/CoreBootServices.nasm b/MdeModulePkg/Core/Dxe/SysCall/X64/CoreBootServices.nasm
index baa3326a7c..2b48d77740 100644
--- a/MdeModulePkg/Core/Dxe/SysCall/X64/CoreBootServices.nasm
+++ b/MdeModulePkg/Core/Dxe/SysCall/X64/CoreBootServices.nasm
@@ -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
diff --git a/MdePkg/Include/Protocol/DebugSupport.h b/MdePkg/Include/Protocol/DebugSupport.h
index 005f89b85c..c65fe48e1b 100644
--- a/MdePkg/Include/Protocol/DebugSupport.h
+++ b/MdePkg/Include/Protocol/DebugSupport.h
@@ -507,6 +507,9 @@ typedef struct {
   UINT32    DFAR;
   UINT32    IFSR;
   UINT32    IFAR;
+  UINT32    SVC_LR;
+  UINT32    TTBR0;
+  UINT32    SP_EL1;
 } EFI_SYSTEM_CONTEXT_ARM;
 
 ///