From 3fc05b04735d40429ff3953810b1df76918e97f4 Mon Sep 17 00:00:00 2001
From: Mikhail Krichanov <mikhailkrichanov@gmail.com>
Date: Mon, 20 May 2024 17:27:09 +0300
Subject: [PATCH] Ring3: Defined CallRing3() for AARCH64.

---
 .../AArch64/DefaultExceptionHandler.c         |  4 +++
 MdeModulePkg/Core/Dxe/DxeMain.h               |  2 ++
 .../Core/Dxe/DxeRing3/AARCH64/SysCall.S       |  8 ++---
 .../Dxe/SysCall/AARCH64/CoreBootServices.S    | 36 +++++++++++++++++--
 .../Core/Dxe/SysCall/AARCH64/InitializeMsr.c  | 17 +++++++++
 5 files changed, 60 insertions(+), 7 deletions(-)

diff --git a/ArmPkg/Library/DefaultExceptionHandlerLib/AArch64/DefaultExceptionHandler.c b/ArmPkg/Library/DefaultExceptionHandlerLib/AArch64/DefaultExceptionHandler.c
index 65e9a81e2d..7e5460aa58 100644
--- a/ArmPkg/Library/DefaultExceptionHandlerLib/AArch64/DefaultExceptionHandler.c
+++ b/ArmPkg/Library/DefaultExceptionHandlerLib/AArch64/DefaultExceptionHandler.c
@@ -8,6 +8,8 @@
 
 **/
 
+#include <Chipset/AArch64.h>
+
 #include <Uefi.h>
 #include <Library/UefiLib.h>
 #include <Library/BaseLib.h>
@@ -233,6 +235,8 @@ DefaultExceptionHandler (
     DEBUG ((DEBUG_ERROR, "PC 0x%012lx\n", SystemContext.SystemContextAArch64->ELR));
   }
 
+  ArmClearPan ();
+
   if ((UINT64 *)SystemContext.SystemContextAArch64->FP != 0) {
     Idx = 0;
 
diff --git a/MdeModulePkg/Core/Dxe/DxeMain.h b/MdeModulePkg/Core/Dxe/DxeMain.h
index 2a78eb063d..f50bf3de02 100644
--- a/MdeModulePkg/Core/Dxe/DxeMain.h
+++ b/MdeModulePkg/Core/Dxe/DxeMain.h
@@ -276,6 +276,8 @@ extern VOID                              *gRing3Interfaces;
 extern VOID                              *gCoreSysCallStackBase;
 extern VOID                              *gCoreSysCallStackTop;
 extern VOID                              *gRing3CallStackBase;
+extern VOID                              *gRing3CallStackTop;
+extern VOID                              *gRing3EntryPoint;
 
 //
 // Service Initialization Functions
diff --git a/MdeModulePkg/Core/Dxe/DxeRing3/AARCH64/SysCall.S b/MdeModulePkg/Core/Dxe/DxeRing3/AARCH64/SysCall.S
index 2a22be0c0a..8678dacbfe 100644
--- a/MdeModulePkg/Core/Dxe/DxeRing3/AARCH64/SysCall.S
+++ b/MdeModulePkg/Core/Dxe/DxeRing3/AARCH64/SysCall.S
@@ -5,6 +5,8 @@
 
 #include <AsmMacroIoLibV8.h>
 
+.extern ASM_PFX(Ring3Call)
+
 //------------------------------------------------------------------------------
 // EFI_STATUS
 // EFIAPI
@@ -24,9 +26,7 @@ ASM_FUNC(SysCall)
 //   IN RING3_CALL_DATA *Data
 //   );
 //
-//   (rcx) RIP of Ring3EntryPoint saved for SYSRET in CallRing3().
-//   (rdx) Data
+//   (x0) Data
 //------------------------------------------------------------------------------
 ASM_FUNC(Ring3EntryPoint)
-
-  ret
+  b ASM_PFX(Ring3Call)
diff --git a/MdeModulePkg/Core/Dxe/SysCall/AARCH64/CoreBootServices.S b/MdeModulePkg/Core/Dxe/SysCall/AARCH64/CoreBootServices.S
index 35e0c3f6c9..06d28f0c3e 100644
--- a/MdeModulePkg/Core/Dxe/SysCall/AARCH64/CoreBootServices.S
+++ b/MdeModulePkg/Core/Dxe/SysCall/AARCH64/CoreBootServices.S
@@ -47,7 +47,37 @@ ASM_FUNC(CoreBootServices)
 //   IN RING3_CALL_DATA *Data
 //   );
 //
-//   (rcx) Data
+//   (x0) Data
+//   (x1) gRing3CallStackTop
+//   (x2) gRing3EntryPoint
 //------------------------------------------------------------------------------
-ASM_FUNC(CallRing3)
-    ret
+ASM_FUNC(ArmCallRing3)
+  // Disable interrupts
+  msr  daifset, #0xf
+  isb
+
+  // Use SP_ELx for Exception level ELx.
+  msr  SPsel, #1
+
+  msr  sp_el0, x1
+
+  msr  elr_el1, x2
+
+  // Copy PSTATE to SPSR.
+  mrs  x1, nzcv
+  mrs  x2, pan
+  orr  x1, x1, x2
+  mrs  x2, daif
+  orr  x1, x1, x2
+  //
+  // M[3:0], bits [3:0] AArch64 Exception level and selected Stack Pointer.
+  // 0b0000 - EL0.
+  // 0b0100 - EL1 with SP_EL0 (ELt).
+  // 0b0101 - EL1 with SP_EL1 (EL1h).
+  //
+  msr  spsr_el1, x1
+
+  isb
+  dsb sy
+
+  eret
diff --git a/MdeModulePkg/Core/Dxe/SysCall/AARCH64/InitializeMsr.c b/MdeModulePkg/Core/Dxe/SysCall/AARCH64/InitializeMsr.c
index 470773a19a..0510fc5957 100644
--- a/MdeModulePkg/Core/Dxe/SysCall/AARCH64/InitializeMsr.c
+++ b/MdeModulePkg/Core/Dxe/SysCall/AARCH64/InitializeMsr.c
@@ -10,6 +10,14 @@
 
 #include "DxeMain.h"
 
+EFI_STATUS
+EFIAPI
+ArmCallRing3 (
+  IN RING3_CALL_DATA *Data,
+  IN VOID            *StackPointer,
+  IN VOID            *EntryPoint
+  );
+
 VOID
 EFIAPI
 InitializeMsr (
@@ -59,3 +67,12 @@ EnableSMAP (
 {
   ArmSetPan ();
 }
+
+EFI_STATUS
+EFIAPI
+CallRing3 (
+  IN RING3_CALL_DATA *Data
+  )
+{
+  return ArmCallRing3 (Data, gRing3CallStackTop, gRing3EntryPoint);
+}