public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH v4 0/1] New RISC-V Patches
@ 2020-06-02 16:51 Daniel Schaefer
  2020-06-02 16:51 ` [PATCH v4 1/1] ProcessorPkg/Library: Add RiscVEdk2SbiLib Daniel Schaefer
  0 siblings, 1 reply; 7+ messages in thread
From: Daniel Schaefer @ 2020-06-02 16:51 UTC (permalink / raw)
  To: devel; +Cc: Leif Lindholm, Gilbert Chen, Abner Chang, Michael D . Kinney

Hi,

here's the latest version of the RiscVEdk2SbiLib patch. The other commits from
the last series haven't changed, so I'm not resending them to reduce the noise.

Below in this email, I included a patch showing the differences betwen the last patchset and this one.

The branch is at https://github.com/changab/edk2-platforms/tree/devel-riscvplatforms
and I made another repo, to easily try out booting to EFI Shell on RISC-V:
https://github.com/JohnAZoidberg/riscv-edk2-docker

Other TODOs for upstreaming RISC-V:
- Deduplicating SMBIOS code -> I am doing that currently
- Figuring out in which repo to put the code -> Discussion is still going on

Cheers,
Daniel

Cc: Leif Lindholm <leif@nuviainc.com>
Cc: Gilbert Chen <gilbert.chen@hpe.com>
Cc: Abner Chang <abner.chang@hpe.com>
Cc: Michael D. Kinney <michael.d.kinney@intel.com>

Daniel Schaefer (1):
  ProcessorPkg/Library: Add RiscVEdk2SbiLib

 Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.inf |  28 +
 Silicon/RISC-V/ProcessorPkg/Include/Library/RiscVEdk2SbiLib.h           | 563 ++++++++++++
 Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.c   | 897 ++++++++++++++++++++
 3 files changed, 1488 insertions(+)
 create mode 100644 Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.inf
 create mode 100644 Silicon/RISC-V/ProcessorPkg/Include/Library/RiscVEdk2SbiLib.h
 create mode 100644 Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.c
--
diff --git i/Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.c w/Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.c
index d26adaa37ce7..0df505d2675b 100644
--- i/Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.c
+++ w/Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.c
@@ -16,8 +16,10 @@
   - SbiLegacyShutdown            -> Wait for new System Reset extension
 
   Copyright (c) 2020, Hewlett Packard Development LP. All rights reserved.<BR>
-
   SPDX-License-Identifier: BSD-2-Clause-Patent
+
+  @par Revision Reference:
+    - OpenSBI Version 0.6
 **/
 
 #include <IndustryStandard/RiscVOpensbi.h>
@@ -30,12 +32,22 @@
 #include <sbi/sbi_init.h>
 
 
+//
+// Maximum arguments for SBI ecall
+// It's possible to pass more but no SBI call uses more as of SBI 0.2.
+// The additional arguments would have to be passed on the stack instead of as
+// registers, like it's done now.
+//
+#define SBI_CALL_MAX_ARGS 6
+
 /**
   Call SBI call using ecall instruction.
 
+  Asserts when NumArgs exceeds SBI_CALL_MAX_ARGS.
+
   @param[in] ExtId    SBI extension ID.
   @param[in] FuncId   SBI function ID.
-  @param[in] NumAargs Number of arguments to pass to the ecall.
+  @param[in] NumArgs  Number of arguments to pass to the ecall.
   @param[in] ...      Argument list for the ecall.
 
   @retval  Returns SbiRet structure with value and error code.
@@ -49,16 +61,19 @@ SbiCall(
   IN  UINTN FuncId,
   IN  UINTN NumArgs,
   ...
-) {
+  )
+{
     UINTN I;
     SbiRet Ret;
-    UINTN Args[6];
+    UINTN Args[SBI_CALL_MAX_ARGS];
     VA_LIST ArgList;
-    VA_START(ArgList, NumArgs);
+    VA_START (ArgList, NumArgs);
 
-    for (I = 0; I < 6; I++) {
+    ASSERT (NumArgs <= SBI_CALL_MAX_ARGS);
+
+    for (I = 0; I < SBI_CALL_MAX_ARGS; I++) {
       if (I < NumArgs) {
-        Args[I] = VA_ARG(ArgList, UINTN);
+        Args[I] = VA_ARG (ArgList, UINTN);
       } else {
         // Default to 0 for all arguments that are not given
         Args[I] = 0;
@@ -95,8 +110,9 @@ STATIC
 EFI_STATUS
 EFIAPI
 TranslateError(
-  IN UINTN SbiError
-  ) {
+  IN  UINTN SbiError
+  )
+{
   switch (SbiError) {
     case SBI_SUCCESS:
       return EFI_SUCCESS;
@@ -129,7 +145,7 @@ TranslateError(
 }
 
 //
-// OpenSBI libraary interface function for the base extension
+// OpenSBI library interface function for the base extension
 //
 
 /**
@@ -150,7 +166,7 @@ SbiGetSpecVersion (
   SbiRet Ret = SbiCall (SBI_EXT_BASE, SBI_EXT_BASE_GET_SPEC_VERSION, 0);
 
   if (!Ret.Error) {
-    *SpecVersion = (UINTN) Ret.Value;
+    *SpecVersion = (UINTN)Ret.Value;
   }
 }
 
@@ -169,7 +185,7 @@ SbiGetImplId (
   )
 {
   SbiRet Ret = SbiCall (SBI_EXT_BASE, SBI_EXT_BASE_GET_IMP_ID, 0);
-  *ImplId = (UINTN) Ret.Value;
+  *ImplId = (UINTN)Ret.Value;
 }
 
 /**
@@ -187,7 +203,7 @@ SbiGetImplVersion (
   )
 {
   SbiRet Ret = SbiCall (SBI_EXT_BASE, SBI_EXT_BASE_GET_IMP_VERSION, 0);
-  *ImplVersion = (UINTN) Ret.Value;
+  *ImplVersion = (UINTN)Ret.Value;
 }
 
 /**
@@ -207,7 +223,7 @@ SbiProbeExtension (
   )
 {
   SbiRet Ret = SbiCall (SBI_EXT_BASE, SBI_EXT_BASE_PROBE_EXT, 0);
-  *ProbeResult = (UINTN) Ret.Value;
+  *ProbeResult = (UINTN)Ret.Value;
 }
 
 /**
@@ -224,7 +240,7 @@ SbiGetMachineVendorId (
   )
 {
   SbiRet Ret = SbiCall (SBI_EXT_BASE, SBI_EXT_BASE_GET_MVENDORID, 0);
-  *MachineVendorId = (UINTN) Ret.Value;
+  *MachineVendorId = (UINTN)Ret.Value;
 }
 
 /**
@@ -241,7 +257,7 @@ SbiGetMachineArchId (
   )
 {
   SbiRet Ret = SbiCall (SBI_EXT_BASE, SBI_EXT_BASE_GET_MARCHID, 0);
-  *MachineArchId = (UINTN) Ret.Value;
+  *MachineArchId = (UINTN)Ret.Value;
 }
 
 /**
@@ -258,7 +274,7 @@ SbiGetMachineImplId (
   )
 {
   SbiRet Ret = SbiCall (SBI_EXT_BASE, SBI_EXT_BASE_GET_MIMPID, 0);
-  *MachineImplId = (UINTN) Ret.Value;
+  *MachineImplId = (UINTN)Ret.Value;
 }
 
 //
@@ -296,13 +312,15 @@ SbiHartStart (
   IN  UINTN                          Priv
   )
 {
-  SbiRet Ret = SbiCall (SBI_EXT_HSM,
-                        SBI_EXT_HSM_HART_START,
-                        3,
-                        HartId,
-                        StartAddr,
-                        Priv);
-  return TranslateError(Ret.Error);
+  SbiRet Ret = SbiCall (
+                 SBI_EXT_HSM,
+                 SBI_EXT_HSM_HART_START,
+                 3,
+                 HartId,
+                 StartAddr,
+                 Priv
+                 );
+  return TranslateError (Ret.Error);
 }
 
 /**
@@ -320,7 +338,7 @@ SbiHartStop (
   )
 {
   SbiRet Ret = SbiCall (SBI_EXT_HSM, SBI_EXT_HSM_HART_STOP, 0);
-  return TranslateError(Ret.Error);
+  return TranslateError (Ret.Error);
 }
 
 /**
@@ -350,10 +368,10 @@ SbiHartGetStatus (
   SbiRet Ret = SbiCall (SBI_EXT_HSM, SBI_EXT_HSM_HART_GET_STATUS, 1, HartId);
 
   if (!Ret.Error) {
-    *HartStatus = (UINTN) Ret.Value;
+    *HartStatus = (UINTN)Ret.Value;
   }
 
-  return TranslateError(Ret.Error);
+  return TranslateError (Ret.Error);
 }
 
 /**
@@ -380,12 +398,14 @@ SbiSendIpi (
   IN  UINTN                          HartMaskBase
   )
 {
-  SbiRet Ret = SbiCall (SBI_EXT_IPI,
-                        SBI_EXT_IPI_SEND_IPI,
-                        2,
-                        (UINTN) HartMask,
-                        HartMaskBase);
-  return TranslateError(Ret.Error);
+  SbiRet Ret = SbiCall (
+                 SBI_EXT_IPI,
+                 SBI_EXT_IPI_SEND_IPI,
+                 2,
+                 (UINTN)HartMask,
+                 HartMaskBase
+                 );
+  return TranslateError (Ret.Error);
 }
 
 /**
@@ -408,12 +428,14 @@ SbiRemoteFenceI (
   IN  UINTN                          HartMaskBase
   )
 {
-  SbiRet Ret = SbiCall (SBI_EXT_RFENCE,
-                        SBI_EXT_RFENCE_REMOTE_FENCE_I,
-                        2,
-                        (UINTN) HartMask,
-                        HartMaskBase);
-  return TranslateError(Ret.Error);
+  SbiRet Ret = SbiCall (
+                 SBI_EXT_RFENCE,
+                 SBI_EXT_RFENCE_REMOTE_FENCE_I,
+                 2,
+                 (UINTN)HartMask,
+                 HartMaskBase
+                 );
+  return TranslateError (Ret.Error);
 }
 
 /**
@@ -446,14 +468,16 @@ SbiRemoteSfenceVma (
   IN  UINTN                          Size
   )
 {
-  SbiRet Ret = SbiCall (SBI_EXT_RFENCE,
-                        SBI_EXT_RFENCE_REMOTE_SFENCE_VMA,
-                        4,
-                        (UINTN) HartMask,
-                        HartMaskBase,
-                        StartAddr,
-                        Size);
-  return TranslateError(Ret.Error);
+  SbiRet Ret = SbiCall (
+                 SBI_EXT_RFENCE,
+                 SBI_EXT_RFENCE_REMOTE_SFENCE_VMA,
+                 4,
+                 (UINTN)HartMask,
+                 HartMaskBase,
+                 StartAddr,
+                 Size
+                 );
+  return TranslateError (Ret.Error);
 }
 
 /**
@@ -488,15 +512,17 @@ SbiRemoteSfenceVmaAsid (
   IN  UINTN                          Asid
   )
 {
-  SbiRet Ret = SbiCall (SBI_EXT_RFENCE,
-                        SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID,
-                        5,
-                        (UINTN) HartMask,
-                        HartMaskBase,
-                        StartAddr,
-                        Size,
-                        Asid);
-  return TranslateError(Ret.Error);
+  SbiRet Ret = SbiCall (
+                 SBI_EXT_RFENCE,
+                 SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID,
+                 5,
+                 (UINTN)HartMask,
+                 HartMaskBase,
+                 StartAddr,
+                 Size,
+                 Asid
+                 );
+  return TranslateError (Ret.Error);
 }
 
 /**
@@ -535,15 +561,17 @@ SbiRemoteHFenceGvmaVmid (
   IN  UINTN                          Vmid
   )
 {
-  SbiRet Ret = SbiCall (SBI_EXT_RFENCE,
-                        SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA,
-                        5,
-                        (UINTN) HartMask,
-                        HartMaskBase,
-                        StartAddr,
-                        Size,
-                        Vmid);
-  return TranslateError(Ret.Error);
+  SbiRet Ret = SbiCall (
+                 SBI_EXT_RFENCE,
+                 SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA,
+                 5,
+                 (UINTN)HartMask,
+                 HartMaskBase,
+                 StartAddr,
+                 Size,
+                 Vmid
+                 );
+  return TranslateError (Ret.Error);
 }
 
 /**
@@ -580,14 +608,16 @@ SbiRemoteHFenceGvma (
   IN  UINTN                          Size
   )
 {
-  SbiRet Ret = SbiCall (SBI_EXT_RFENCE,
-                        SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA_VMID,
-                        4,
-                        (UINTN) HartMask,
-                        HartMaskBase,
-                        StartAddr,
-                        Size);
-  return TranslateError(Ret.Error);
+  SbiRet Ret = SbiCall (
+                 SBI_EXT_RFENCE,
+                 SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA_VMID,
+                 4,
+                 (UINTN)HartMask,
+                 HartMaskBase,
+                 StartAddr,
+                 Size
+                 );
+  return TranslateError (Ret.Error);
 }
 
 /**
@@ -626,15 +656,17 @@ SbiRemoteHFenceVvmaAsid (
   IN  UINTN                          Asid
   )
 {
-  SbiRet Ret = SbiCall (SBI_EXT_RFENCE,
-                        SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA,
-                        5,
-                        (UINTN) HartMask,
-                        HartMaskBase,
-                        StartAddr,
-                        Size,
-                        Asid);
-  return TranslateError(Ret.Error);
+  SbiRet Ret = SbiCall (
+                 SBI_EXT_RFENCE,
+                 SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA,
+                 5,
+                 (UINTN)HartMask,
+                 HartMaskBase,
+                 StartAddr,
+                 Size,
+                 Asid
+                 );
+  return TranslateError (Ret.Error);
 }
 
 /**
@@ -671,14 +703,16 @@ SbiRemoteHFenceVvma (
   IN  UINTN                          Size
   )
 {
-  SbiRet Ret = SbiCall (SBI_EXT_RFENCE,
-                        SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA_ASID,
-                        4,
-                        (UINTN) HartMask,
-                        HartMaskBase,
-                        StartAddr,
-                        Size);
-  return TranslateError(Ret.Error);
+  SbiRet Ret = SbiCall (
+                 SBI_EXT_RFENCE,
+                 SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA_ASID,
+                 4,
+                 (UINTN)HartMask,
+                 HartMaskBase,
+                 StartAddr,
+                 Size
+                 );
+  return TranslateError (Ret.Error);
 }
 
 //
@@ -689,14 +723,13 @@ SbiRemoteHFenceVvma (
   Call a function in a vendor defined SBI extension
 
   ASSERT() if the ExtensionId is not in the designated SBI Vendor Extension
-  Space.
+  Space or NumArgs exceeds SBI_CALL_MAX_ARGS.
 
   @param[in]  ExtensionId          The SBI vendor extension ID.
   @param[in]  FunctionId           The function ID to call in this extension.
   @param[in]  NumArgs              How many arguments are passed.
   @param[in]  ...                  Actual Arguments to the function.
   @retval EFI_SUCCESS if the SBI function was called and it was successful
-  @retval EFI_INVALID_PARAMETER if NumArgs exceeds 6
   @retval others if the called SBI function returns an error
 **/
 EFI_STATUS
@@ -710,39 +743,41 @@ SbiVendorCall (
 {
     SbiRet Ret;
     VA_LIST Args;
-    VA_START(Args, NumArgs);
+    VA_START (Args, NumArgs);
 
-    ASSERT (ExtensionId >= 0x09000000 && ExtensionId <= 0x09FFFFFF);
+    ASSERT (ExtensionId >= SBI_EXT_VENDOR_START && ExtensionId <= SBI_EXT_VENDOR_END);
+    ASSERT (NumArgs <= SBI_CALL_MAX_ARGS);
 
     switch (NumArgs) {
       case 0:
         Ret = SbiCall (ExtensionId, FunctionId, NumArgs);
         break;
       case 1:
-        Ret = SbiCall (ExtensionId, FunctionId, NumArgs, VA_ARG(Args, UINTN));
+        Ret = SbiCall (ExtensionId, FunctionId, NumArgs, VA_ARG (Args, UINTN));
         break;
       case 2:
-        Ret = SbiCall (ExtensionId, FunctionId, NumArgs, VA_ARG(Args, UINTN),
-                       VA_ARG(Args, UINTN));
+        Ret = SbiCall (ExtensionId, FunctionId, NumArgs, VA_ARG (Args, UINTN),
+                       VA_ARG (Args, UINTN));
         break;
       case 3:
-        Ret = SbiCall (ExtensionId, FunctionId, NumArgs, VA_ARG(Args, UINTN),
-                       VA_ARG(Args, UINTN), VA_ARG(Args, UINTN));
+        Ret = SbiCall (ExtensionId, FunctionId, NumArgs, VA_ARG (Args, UINTN),
+                       VA_ARG (Args, UINTN), VA_ARG (Args, UINTN));
         break;
       case 4:
-        Ret = SbiCall (ExtensionId, FunctionId, NumArgs, VA_ARG(Args, UINTN),
-                       VA_ARG(Args, UINTN), VA_ARG(Args, UINTN), VA_ARG(Args, UINTN));
+        Ret = SbiCall (ExtensionId, FunctionId, NumArgs, VA_ARG (Args, UINTN),
+                       VA_ARG (Args, UINTN), VA_ARG (Args, UINTN),
+                       VA_ARG (Args, UINTN));
         break;
       case 5:
-        Ret = SbiCall (ExtensionId, FunctionId, NumArgs, VA_ARG(Args, UINTN),
-                       VA_ARG(Args, UINTN), VA_ARG(Args, UINTN),
-                       VA_ARG(Args, UINTN), VA_ARG(Args, UINTN));
+        Ret = SbiCall (ExtensionId, FunctionId, NumArgs, VA_ARG (Args, UINTN),
+                       VA_ARG (Args, UINTN), VA_ARG (Args, UINTN),
+                       VA_ARG (Args, UINTN), VA_ARG (Args, UINTN));
         break;
       case 6:
-        Ret = SbiCall (ExtensionId, FunctionId, NumArgs, VA_ARG(Args, UINTN),
-                       VA_ARG(Args, UINTN), VA_ARG(Args, UINTN),
-                       VA_ARG(Args, UINTN), VA_ARG(Args, UINTN),
-                       VA_ARG(Args, UINTN));
+        Ret = SbiCall (ExtensionId, FunctionId, NumArgs, VA_ARG (Args, UINTN),
+                       VA_ARG (Args, UINTN), VA_ARG (Args, UINTN),
+                       VA_ARG (Args, UINTN), VA_ARG (Args, UINTN),
+                       VA_ARG (Args, UINTN));
         break;
       default:
         // Too many args. In theory SBI can handle more arguments when they are
@@ -752,7 +787,7 @@ SbiVendorCall (
      }
 
     VA_END(Args);
-    return TranslateError(Ret.Error);
+    return TranslateError (Ret.Error);
 }
 
 //
@@ -777,7 +812,7 @@ SbiGetMscratch (
   SbiRet Ret = SbiCall (SBI_EDK2_FW_EXT, SBI_EXT_FW_MSCRATCH_FUNC, 0);
 
   if (!Ret.Error) {
-    *ScratchSpace = (SBI_SCRATCH *) Ret.Value;
+    *ScratchSpace = (SBI_SCRATCH *)Ret.Value;
   }
 
   return EFI_SUCCESS;
@@ -797,13 +832,15 @@ SbiGetMscratchHartid (
   OUT SBI_SCRATCH                    **ScratchSpace
   )
 {
-  SbiRet Ret = SbiCall (SBI_EDK2_FW_EXT,
-                        SBI_EXT_FW_MSCRATCH_HARTID_FUNC,
-                        1,
-                        HartId);
+  SbiRet Ret = SbiCall (
+                 SBI_EDK2_FW_EXT,
+                 SBI_EXT_FW_MSCRATCH_HARTID_FUNC,
+                 1,
+                 HartId
+                 );
 
   if (!Ret.Error) {
-    *ScratchSpace = (SBI_SCRATCH *) Ret.Value;
+    *ScratchSpace = (SBI_SCRATCH *)Ret.Value;
   }
 
   return EFI_SUCCESS;
@@ -826,9 +863,9 @@ SbiGetFirmwareContext (
   SbiRet Ret = SbiCall (SBI_EDK2_FW_EXT, SBI_EXT_FW_MSCRATCH_FUNC, 0);
 
   if (!Ret.Error) {
-    ScratchSpace = (SBI_SCRATCH *) Ret.Value;
-    SbiPlatform = (SBI_PLATFORM *) sbi_platform_ptr(ScratchSpace);
-    *FirmwareContext = (EFI_RISCV_OPENSBI_FIRMWARE_CONTEXT *) SbiPlatform->firmware_context;
+    ScratchSpace = (SBI_SCRATCH *)Ret.Value;
+    SbiPlatform = (SBI_PLATFORM *)sbi_platform_ptr(ScratchSpace);
+    *FirmwareContext = (EFI_RISCV_OPENSBI_FIRMWARE_CONTEXT *)SbiPlatform->firmware_context;
   }
 
   return EFI_SUCCESS;
@@ -851,9 +888,9 @@ SbiSetFirmwareContext (
   SbiRet Ret = SbiCall (SBI_EDK2_FW_EXT, SBI_EXT_FW_MSCRATCH_FUNC, 0);
 
   if (!Ret.Error) {
-    ScratchSpace = (SBI_SCRATCH *) Ret.Value;
-    SbiPlatform = (SBI_PLATFORM *) sbi_platform_ptr(ScratchSpace);
-    SbiPlatform->firmware_context = (UINTN) FirmwareContext;
+    ScratchSpace = (SBI_SCRATCH *)Ret.Value;
+    SbiPlatform = (SBI_PLATFORM *)sbi_platform_ptr (ScratchSpace);
+    SbiPlatform->firmware_context = (UINTN)FirmwareContext;
   }
 
   return EFI_SUCCESS;
-- 
2.26.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v4 1/1] ProcessorPkg/Library: Add RiscVEdk2SbiLib
  2020-06-02 16:51 [PATCH v4 0/1] New RISC-V Patches Daniel Schaefer
@ 2020-06-02 16:51 ` Daniel Schaefer
  2020-06-02 22:00   ` [edk2-devel] " Michael D Kinney
  2020-06-18 16:49   ` Leif Lindholm
  0 siblings, 2 replies; 7+ messages in thread
From: Daniel Schaefer @ 2020-06-02 16:51 UTC (permalink / raw)
  To: devel; +Cc: Leif Lindholm, Gilbert Chen, Abner Chang, Michael D . Kinney

Library provides interfaces to invoke SBI ecalls.

Signed-off-by: Daniel Schaefer <daniel.schaefer@hpe.com>

Cc: Leif Lindholm <leif@nuviainc.com>
Cc: Gilbert Chen <gilbert.chen@hpe.com>
Cc: Abner Chang <abner.chang@hpe.com>
Cc: Michael D. Kinney <michael.d.kinney@intel.com>
---
 Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.inf |  28 +
 Silicon/RISC-V/ProcessorPkg/Include/Library/RiscVEdk2SbiLib.h           | 563 ++++++++++++
 Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.c   | 897 ++++++++++++++++++++
 3 files changed, 1488 insertions(+)

diff --git a/Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.inf b/Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.inf
new file mode 100644
index 000000000000..665dcbf40e01
--- /dev/null
+++ b/Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.inf
@@ -0,0 +1,28 @@
+## @file
+# RISC-V Library to call SBI ecalls
+#
+#  Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION    = 0x0001001b
+  BASE_NAME      = RiscVEdk2SbiLib
+  FILE_GUID      = 0DF1BBBD-F7E5-4E8A-BCF1-9D63D2DD9FDD
+  MODULE_TYPE    = BASE
+  VERSION_STRING = 1.0
+  LIBRARY_CLASS  = RiscVEdk2SbiLib
+
+[Sources]
+  RiscVEdk2SbiLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  Silicon/RISC-V/ProcessorPkg/RiscVProcessorPkg.dec
+  Platform/RISC-V/PlatformPkg/RiscVPlatformPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  RiscVOpensbiLib
diff --git a/Silicon/RISC-V/ProcessorPkg/Include/Library/RiscVEdk2SbiLib.h b/Silicon/RISC-V/ProcessorPkg/Include/Library/RiscVEdk2SbiLib.h
new file mode 100644
index 000000000000..c1ae3176147f
--- /dev/null
+++ b/Silicon/RISC-V/ProcessorPkg/Include/Library/RiscVEdk2SbiLib.h
@@ -0,0 +1,563 @@
+/** @file
+  Library to call the RISC-V SBI ecalls
+
+  Copyright (c) 2020, Hewlett Packard Development LP. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+  @par Glossary:
+    - Hart - Hardware Thread, similar to a CPU core
+**/
+
+#ifndef RISCV_SBI_LIB_H_
+#define RISCV_SBI_LIB_H_
+
+#include <Uefi.h>
+#include <IndustryStandard/RiscVOpensbi.h>
+#include <sbi/sbi_scratch.h>
+#include <sbi/sbi_platform.h>
+
+//
+// EDK2 OpenSBI Firmware extension.
+//
+#define SBI_EDK2_FW_EXT (SBI_EXT_FIRMWARE_CODE_BASE_START | SBI_OPENSBI_IMPID)
+//
+// EDK2 OpenSBI Firmware extension functions.
+//
+#define SBI_EXT_FW_MSCRATCH_FUNC        0
+#define SBI_EXT_FW_MSCRATCH_HARTID_FUNC 1
+
+//
+// EDK2 OpenSBI firmware extension return status.
+//
+typedef struct {
+  UINTN Error;   ///< SBI status code
+  UINTN Value;   ///< Value returned
+} SbiRet;
+
+/**
+  Get the implemented SBI specification version
+
+  The minor number of the SBI specification is encoded in the low 24 bits,
+  with the major number encoded in the next 7 bits.  Bit 32 must be 0 and is
+  reserved for future expansion.
+
+  @param[out] SpecVersion          The Version of the SBI specification.
+**/
+VOID
+EFIAPI
+SbiGetSpecVersion (
+  OUT UINTN                       *SpecVersion
+  );
+
+/**
+  Get the SBI implementation ID
+
+  This ID is used to idenetify a specific SBI implementation in order to work
+  around any quirks it might have.
+
+  @param[out] ImplId               The ID of the SBI implementation.
+**/
+VOID
+EFIAPI
+SbiGetImplId (
+  OUT UINTN                      *ImplId
+  );
+
+/**
+  Get the SBI implementation version
+
+  The version of this SBI implementation.
+  The encoding of this number is determined by the specific SBI implementation.
+
+  @param[out] ImplVersion          The version of the SBI implementation.
+**/
+VOID
+EFIAPI
+SbiGetImplVersion (
+  OUT UINTN                       *ImplVersion
+  );
+
+/**
+  Probe whether an SBI extension is available
+
+  ProbeResult is set to 0 if the extension is not available or to an extension
+  specified value if it is available.
+
+  @param[in]  ExtensionId          The extension ID.
+  @param[out] ProbeResult          The return value of the probe.
+**/
+VOID
+EFIAPI
+SbiProbeExtension (
+  IN  INTN                         ExtensionId,
+  OUT INTN                        *ProbeResult
+  );
+
+/**
+  Get the CPU's vendor ID
+
+  Reads the mvendorid CSR.
+
+  @param[out] MachineVendorId      The CPU's vendor ID.
+**/
+VOID
+EFIAPI
+SbiGetMachineVendorId (
+  OUT UINTN                       *MachineVendorId
+  );
+
+/**
+  Get the CPU's architecture ID
+
+  Reads the marchid CSR.
+
+  @param[out] MachineArchId        The CPU's architecture ID.
+**/
+VOID
+EFIAPI
+SbiGetMachineArchId (
+  OUT UINTN                       *MachineArchId
+  );
+
+/**
+  Get the CPU's implementation ID
+
+  Reads the mimpid CSR.
+
+  @param[out] MachineImplId        The CPU's implementation ID.
+**/
+VOID
+EFIAPI
+SbiGetMachineImplId (
+  OUT UINTN                       *MachineImplId
+  );
+
+/**
+  Politely ask the SBI to start a given hart.
+
+  This call may return before the hart has actually started executing, if the
+  SBI implementation can guarantee that the hart is actually going to start.
+
+  Before the hart jumps to StartAddr, the hart MUST configure PMP if present
+  and switch to S-mode.
+
+  @param[in]  HartId               The id of the hart to start.
+  @param[in]  StartAddr            The physical address, where the hart starts
+                                   executing from.
+  @param[in]  Priv                 An XLEN-bit value, which will be in register
+                                   a1 when the hart starts.
+  @retval EFI_SUCCESS              Hart was stopped and will start executing from StartAddr.
+  @retval EFI_LOAD_ERROR           StartAddr is not valid, possibly due to following reasons:
+                                    - It is not a valid physical address.
+                                    - The address is prohibited by PMP to run in
+                                      supervisor mode.
+  @retval EFI_INVALID_PARAMETER    HartId is not a valid hart id
+  @retval EFI_ALREADY_STARTED      The hart is already running.
+  @retval other                    The start request failed for unknown reasons.
+**/
+EFI_STATUS
+EFIAPI
+SbiHartStart (
+  IN  UINTN                          HartId,
+  IN  UINTN                          StartAddr,
+  IN  UINTN                          Priv
+  );
+
+/**
+  Return execution of the calling hart to SBI.
+
+  MUST be called in S-Mode with user interrupts disabled.
+  This call is not expected to return, unless a failure occurs.
+
+  @retval     EFI_SUCCESS          Never occurs. When successful, the call does not return.
+  @retval     other                Failed to stop hard for an unknown reason.
+**/
+EFI_STATUS
+EFIAPI
+SbiHartStop (
+  );
+
+/**
+  Get the current status of a hart.
+
+  Since harts can transition between states at any time, the status retrieved
+  by this function may already be out of date, once it returns.
+
+  Possible values for HartStatus are:
+  0: STARTED
+  1: STOPPED
+  2: START_REQUEST_PENDING
+  3: STOP_REQUEST_PENDING
+
+  @param[out] HartStatus           The pointer in which the hart's status is
+                                   stored.
+  @retval EFI_SUCCESS              The operation succeeds.
+  @retval EFI_INVALID_PARAMETER    A parameter is invalid.
+**/
+EFI_STATUS
+EFIAPI
+SbiHartGetStatus (
+  IN  UINTN                          HartId,
+  OUT UINTN                         *HartStatus
+  );
+
+///
+/// Timer extension
+///
+
+/**
+  Clear pending timer interrupt bit and set timer for next event after Time.
+
+  To clear the timer without scheduling a timer event, set Time to a
+  practically infinite value or mask the timer interrupt by clearing sie.STIE.
+
+  @param[in]  Time                 The time offset to the next scheduled timer interrupt.
+**/
+VOID
+EFIAPI
+SbiSetTimer (
+  IN  UINT64                         Time
+  );
+
+///
+/// IPI extension
+///
+
+/**
+  Send IPI to all harts specified in the mask.
+
+  The interrupts are registered as supervisor software interrupts at the
+  receiving hart.
+
+  @param[in]  HartMask             Scalar bit-vector containing hart ids
+  @param[in]  HartMaskBase         The starting hartid from which the bit-vector
+                                   must be computed. If set to -1, HartMask is
+                                   ignored and all harts are considered.
+  @retval EFI_SUCCESS              IPI was sent to all the targeted harts.
+  @retval EFI_INVALID_PARAMETER    Either hart_mask_base or any of the hartid
+                                   from hart_mask is not valid i.e. either the
+                                   hartid is not enabled by the platform or is
+                                   not available to the supervisor.
+**/
+EFI_STATUS
+EFIAPI
+SbiSendIpi (
+  IN  UINTN                         *HartMask,
+  IN  UINTN                          HartMaskBase
+  );
+
+///
+/// Remote fence extension
+///
+
+/**
+  Instructs remote harts to execute a FENCE.I instruction.
+
+  @param[in]  HartMask             Scalar bit-vector containing hart ids
+  @param[in]  HartMaskBase         The starting hartid from which the bit-vector
+                                   must be computed. If set to -1, HartMask is
+                                   ignored and all harts are considered.
+  @retval EFI_SUCCESS              IPI was sent to all the targeted harts.
+  @retval EFI_INVALID_PARAMETER    Either hart_mask_base or any of the hartid
+                                   from hart_mask is not valid i.e. either the
+                                   hartid is not enabled by the platform or is
+                                   not available to the supervisor.
+**/
+EFI_STATUS
+EFIAPI
+SbiRemoteFenceI (
+  IN  UINTN                         *HartMask,
+  IN  UINTN                          HartMaskBase
+  );
+
+/**
+  Instructs the remote harts to execute one or more SFENCE.VMA instructions.
+
+  The SFENCE.VMA covers the range of virtual addresses between StartAaddr and Size.
+
+  The remote fence function acts as a full tlb flush if * StartAddr and size
+  are both 0 * size is equal to 2^XLEN-1
+
+  @param[in]  HartMask             Scalar bit-vector containing hart ids
+  @param[in]  HartMaskBase         The starting hartid from which the bit-vector
+                                   must be computed. If set to -1, HartMask is
+                                   ignored and all harts are considered.
+  @param[in]  StartAddr            The first address of the affected range.
+  @param[in]  Size                 How many addresses are affected.
+  @retval EFI_SUCCESS              IPI was sent to all the targeted harts.
+  @retval EFI_LOAD_ERROR           StartAddr or Size is not valid.
+  @retval EFI_INVALID_PARAMETER    Either hart_mask_base or any of the hartid
+                                   from hart_mask is not valid i.e. either the
+                                   hartid is not enabled by the platform or is
+                                   not available to the supervisor.
+**/
+EFI_STATUS
+EFIAPI
+SbiRemoteSfenceVma (
+  IN  UINTN                         *HartMask,
+  IN  UINTN                          HartMaskBase,
+  IN  UINTN                          StartAddr,
+  IN  UINTN                          Size
+  );
+
+/**
+  Instructs the remote harts to execute one or more SFENCE.VMA instructions.
+
+  The SFENCE.VMA covers the range of virtual addresses between StartAaddr and Size.
+  Covers only the given ASID.
+
+  The remote fence function acts as a full tlb flush if * StartAddr and size
+  are both 0 * size is equal to 2^XLEN-1
+
+  @param[in]  HartMask             Scalar bit-vector containing hart ids
+  @param[in]  HartMaskBase         The starting hartid from which the bit-vector
+                                   must be computed. If set to -1, HartMask is
+                                   ignored and all harts are considered.
+  @param[in]  StartAddr            The first address of the affected range.
+  @param[in]  Size                 How many addresses are affected.
+  @retval EFI_SUCCESS              IPI was sent to all the targeted harts.
+  @retval EFI_LOAD_ERROR           StartAddr or Size is not valid.
+  @retval EFI_INVALID_PARAMETER    Either hart_mask_base or any of the hartid
+                                   from hart_mask is not valid i.e. either the
+                                   hartid is not enabled by the platform or is
+                                   not available to the supervisor.
+**/
+EFI_STATUS
+EFIAPI
+SbiRemoteSfenceVmaAsid (
+  IN  UINTN                         *HartMask,
+  IN  UINTN                          HartMaskBase,
+  IN  UINTN                          StartAddr,
+  IN  UINTN                          Size,
+  IN  UINTN                          Asid
+  );
+
+/**
+  Instructs the remote harts to execute one or more SFENCE.GVMA instructions.
+
+  The SFENCE.GVMA covers the range of virtual addresses between StartAaddr and Size.
+  Covers only the given VMID.
+  This function call is only valid for harts implementing the hypervisor extension.
+
+  The remote fence function acts as a full tlb flush if * StartAddr and size
+  are both 0 * size is equal to 2^XLEN-1
+
+  @param[in]  HartMask             Scalar bit-vector containing hart ids
+  @param[in]  HartMaskBase         The starting hartid from which the bit-vector
+                                   must be computed. If set to -1, HartMask is
+                                   ignored and all harts are considered.
+  @param[in]  StartAddr            The first address of the affected range.
+  @param[in]  Size                 How many addresses are affected.
+  @retval EFI_SUCCESS              IPI was sent to all the targeted harts.
+  @retval EFI_LOAD_ERROR           StartAddr or Size is not valid.
+  @retval EFI_UNSUPPORTED          SBI does not implement this function or one
+                                   of the target harts does not support the
+                                   hypervisor extension.
+  @retval EFI_INVALID_PARAMETER    Either hart_mask_base or any of the hartid
+                                   from hart_mask is not valid i.e. either the
+                                   hartid is not enabled by the platform or is
+                                   not available to the supervisor.
+**/
+EFI_STATUS
+EFIAPI
+SbiRemoteHfenceGvmaVmid (
+  IN  UINTN                         *HartMask,
+  IN  UINTN                          HartMaskBase,
+  IN  UINTN                          StartAddr,
+  IN  UINTN                          Size,
+  IN  UINTN                          Vmid
+  );
+
+/**
+  Instructs the remote harts to execute one or more SFENCE.GVMA instructions.
+
+  The SFENCE.GVMA covers the range of virtual addresses between StartAaddr and Size.
+  This function call is only valid for harts implementing the hypervisor extension.
+
+  The remote fence function acts as a full tlb flush if * StartAddr and size
+  are both 0 * size is equal to 2^XLEN-1
+
+  @param[in]  HartMask             Scalar bit-vector containing hart ids
+  @param[in]  HartMaskBase         The starting hartid from which the bit-vector
+                                   must be computed. If set to -1, HartMask is
+                                   ignored and all harts are considered.
+  @param[in]  StartAddr            The first address of the affected range.
+  @param[in]  Size                 How many addresses are affected.
+  @retval EFI_SUCCESS              IPI was sent to all the targeted harts.
+  @retval EFI_LOAD_ERROR           StartAddr or Size is not valid.
+  @retval EFI_UNSUPPORTED          SBI does not implement this function or one
+                                   of the target harts does not support the
+                                   hypervisor extension.
+  @retval EFI_INVALID_PARAMETER    Either hart_mask_base or any of the hartid
+                                   from hart_mask is not valid i.e. either the
+                                   hartid is not enabled by the platform or is
+                                   not available to the supervisor.
+**/
+EFI_STATUS
+EFIAPI
+SbiRemoteHfenceGvma (
+  IN  UINTN                         *HartMask,
+  IN  UINTN                          HartMaskBase,
+  IN  UINTN                          StartAddr,
+  IN  UINTN                          Size
+  );
+
+/**
+  Instructs the remote harts to execute one or more SFENCE.VVMA instructions.
+
+  The SFENCE.GVMA covers the range of virtual addresses between StartAaddr and Size.
+  Covers only the given ASID.
+  This function call is only valid for harts implementing the hypervisor extension.
+
+  The remote fence function acts as a full tlb flush if * StartAddr and size
+  are both 0 * size is equal to 2^XLEN-1
+
+  @param[in]  HartMask             Scalar bit-vector containing hart ids
+  @param[in]  HartMaskBase         The starting hartid from which the bit-vector
+                                   must be computed. If set to -1, HartMask is
+                                   ignored and all harts are considered.
+  @param[in]  StartAddr            The first address of the affected range.
+  @param[in]  Size                 How many addresses are affected.
+  @retval EFI_SUCCESS              IPI was sent to all the targeted harts.
+  @retval EFI_LOAD_ERROR           StartAddr or Size is not valid.
+  @retval EFI_UNSUPPORTED          SBI does not implement this function or one
+                                   of the target harts does not support the
+                                   hypervisor extension.
+  @retval EFI_INVALID_PARAMETER    Either hart_mask_base or any of the hartid
+                                   from hart_mask is not valid i.e. either the
+                                   hartid is not enabled by the platform or is
+                                   not available to the supervisor.
+**/
+EFI_STATUS
+EFIAPI
+SbiRemoteHfenceVvmaAsid (
+  IN  UINTN                         *HartMask,
+  IN  UINTN                          HartMaskBase,
+  IN  UINTN                          StartAddr,
+  IN  UINTN                          Size,
+  IN  UINTN                          Asid
+  );
+
+/**
+  Instructs the remote harts to execute one or more SFENCE.VVMA instructions.
+
+  The SFENCE.GVMA covers the range of virtual addresses between StartAaddr and Size.
+  This function call is only valid for harts implementing the hypervisor extension.
+
+  The remote fence function acts as a full tlb flush if * StartAddr and size
+  are both 0 * size is equal to 2^XLEN-1
+
+  @param[in]  HartMask             Scalar bit-vector containing hart ids
+  @param[in]  HartMaskBase         The starting hartid from which the bit-vector
+                                   must be computed. If set to -1, HartMask is
+                                   ignored and all harts are considered.
+  @param[in]  StartAddr            The first address of the affected range.
+  @param[in]  Size                 How many addresses are affected.
+  @retval EFI_SUCCESS              IPI was sent to all the targeted harts.
+  @retval EFI_LOAD_ERROR           StartAddr or Size is not valid.
+  @retval EFI_UNSUPPORTED          SBI does not implement this function or one
+                                   of the target harts does not support the
+                                   hypervisor extension.
+  @retval EFI_INVALID_PARAMETER    Either hart_mask_base or any of the hartid
+                                   from hart_mask is not valid i.e. either the
+                                   hartid is not enabled by the platform or is
+                                   not available to the supervisor.
+**/
+EFI_STATUS
+EFIAPI
+SbiRemoteHfenceVvma (
+  IN  UINTN                         *HartMask,
+  IN  UINTN                          HartMaskBase,
+  IN  UINTN                          StartAddr,
+  IN  UINTN                          Size
+  );
+
+///
+/// Vendor Specific extension space: Extension Ids 0x09000000 through 0x09FFFFFF
+///
+
+/**
+  Call a function in a vendor defined SBI extension
+
+  ASSERT() if the ExtensionId is not in the designated SBI Vendor Extension
+  Space.
+
+  @param[in]  ExtensionId          The SBI vendor extension ID.
+  @param[in]  FunctionId           The function ID to call in this extension.
+  @param[in]  NumArgs              How many arguments are passed.
+  @param[in]  ...                  Actual Arguments to the function.
+  @retval EFI_SUCCESS if the SBI function was called and it was successful
+  @retval EFI_INVALID_PARAMETER if NumArgs exceeds 6
+  @retval others if the called SBI function returns an error
+**/
+EFI_STATUS
+EFIAPI
+SbiVendorCall (
+  IN  UINTN                          ExtensionId,
+  IN  UINTN                          FunctionId,
+  IN  UINTN                          NumArgs,
+  ...
+  );
+
+///
+/// Firmware SBI Extension
+///
+/// This SBI Extension is defined and used by EDK2 only in order to be able to
+/// run PI and DXE phase in S-Mode.
+///
+
+/**
+  Get scratch space of the current hart.
+
+  Please consider using the wrapper SbiGetFirmwareContext if you only need to
+  access the firmware context.
+
+  @param[out] ScratchSpace         The scratch space pointer.
+  @retval EFI_SUCCESS              The operation succeeds.
+**/
+EFI_STATUS
+EFIAPI
+SbiGetMscratch (
+  OUT SBI_SCRATCH                    **ScratchSpace
+  );
+
+/**
+  Get scratch space of the given hart id.
+
+  @param[in]  HartId               The hart id.
+  @param[out] ScratchSpace         The scratch space pointer.
+  @retval EFI_SUCCESS              The operation succeeds.
+**/
+EFI_STATUS
+EFIAPI
+SbiGetMscratchHartid (
+  IN  UINTN                            HartId,
+  OUT SBI_SCRATCH                    **ScratchSpace
+  );
+
+/**
+  Get firmware context of the calling hart.
+
+  @param[out] FirmwareContext      The firmware context pointer.
+  @retval EFI_SUCCESS              The operation succeeds.
+**/
+EFI_STATUS
+EFIAPI
+SbiGetFirmwareContext (
+  OUT EFI_RISCV_OPENSBI_FIRMWARE_CONTEXT **FirmwareContext
+  );
+
+/**
+  Set firmware context of the calling hart.
+
+  @param[in] FirmwareContext       The firmware context pointer.
+  @retval EFI_SUCCESS              The operation succeeds.
+**/
+EFI_STATUS
+EFIAPI
+SbiSetFirmwareContext (
+  IN EFI_RISCV_OPENSBI_FIRMWARE_CONTEXT *FirmwareContext
+  );
+
+#endif
diff --git a/Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.c b/Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.c
new file mode 100644
index 000000000000..0df505d2675b
--- /dev/null
+++ b/Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.c
@@ -0,0 +1,897 @@
+/** @file
+  Instance of the SBI ecall library.
+
+  It allows calling an SBI function via an ecall from S-Mode.
+
+  The legacy extensions are not included because they are not necessary.
+  They would be:
+  - SbiLegacySetTimer            -> Use SbiSetTimer
+  - SbiLegacyConsolePutChar      -> No replacement - Use regular UEFI functions
+  - SbiLegacyConsoleGetChar      -> No replacement - Use regular UEFI functions
+  - SbiLegacyClearIpi            -> Write 0 to SSIP
+  - SbiLegacySendIpi             -> Use SbiSendIpi
+  - SbiLegacyRemoteFenceI        -> Use SbiRemoteFenceI
+  - SbiLegacyRemoteSfenceVma     -> Use SbiRemoteSfenceVma
+  - SbiLegacyRemoteSfenceVmaAsid -> Use SbiRemoteSfenceVmaAsid
+  - SbiLegacyShutdown            -> Wait for new System Reset extension
+
+  Copyright (c) 2020, Hewlett Packard Development LP. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+  @par Revision Reference:
+    - OpenSBI Version 0.6
+**/
+
+#include <IndustryStandard/RiscVOpensbi.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/RiscVEdk2SbiLib.h>
+#include <sbi/riscv_asm.h>
+#include <sbi/sbi_hart.h>
+#include <sbi/sbi_types.h>
+#include <sbi/sbi_init.h>
+
+
+//
+// Maximum arguments for SBI ecall
+// It's possible to pass more but no SBI call uses more as of SBI 0.2.
+// The additional arguments would have to be passed on the stack instead of as
+// registers, like it's done now.
+//
+#define SBI_CALL_MAX_ARGS 6
+
+/**
+  Call SBI call using ecall instruction.
+
+  Asserts when NumArgs exceeds SBI_CALL_MAX_ARGS.
+
+  @param[in] ExtId    SBI extension ID.
+  @param[in] FuncId   SBI function ID.
+  @param[in] NumArgs  Number of arguments to pass to the ecall.
+  @param[in] ...      Argument list for the ecall.
+
+  @retval  Returns SbiRet structure with value and error code.
+
+**/
+STATIC
+SbiRet
+EFIAPI
+SbiCall(
+  IN  UINTN ExtId,
+  IN  UINTN FuncId,
+  IN  UINTN NumArgs,
+  ...
+  )
+{
+    UINTN I;
+    SbiRet Ret;
+    UINTN Args[SBI_CALL_MAX_ARGS];
+    VA_LIST ArgList;
+    VA_START (ArgList, NumArgs);
+
+    ASSERT (NumArgs <= SBI_CALL_MAX_ARGS);
+
+    for (I = 0; I < SBI_CALL_MAX_ARGS; I++) {
+      if (I < NumArgs) {
+        Args[I] = VA_ARG (ArgList, UINTN);
+      } else {
+        // Default to 0 for all arguments that are not given
+        Args[I] = 0;
+      }
+    }
+
+    VA_END(ArgList);
+
+    register UINTN a0 asm ("a0") = Args[0];
+    register UINTN a1 asm ("a1") = Args[1];
+    register UINTN a2 asm ("a2") = Args[2];
+    register UINTN a3 asm ("a3") = Args[3];
+    register UINTN a4 asm ("a4") = Args[4];
+    register UINTN a5 asm ("a5") = Args[5];
+    register UINTN a6 asm ("a6") = (UINTN)(FuncId);
+    register UINTN a7 asm ("a7") = (UINTN)(ExtId);
+    asm volatile ("ecall" \
+         : "+r" (a0), "+r" (a1) \
+         : "r" (a2), "r" (a3), "r" (a4), "r" (a5), "r" (a6), "r" (a7) \
+         : "memory"); \
+    Ret.Error = a0;
+    Ret.Value = a1;
+    return Ret;
+}
+
+/**
+  Translate SBI error code to EFI status.
+
+  @param[in] SbiError   SBI error code
+  @retval EFI_STATUS
+**/
+
+STATIC
+EFI_STATUS
+EFIAPI
+TranslateError(
+  IN  UINTN SbiError
+  )
+{
+  switch (SbiError) {
+    case SBI_SUCCESS:
+      return EFI_SUCCESS;
+    case SBI_ERR_FAILED:
+      return EFI_DEVICE_ERROR;
+      break;
+    case SBI_ERR_NOT_SUPPORTED:
+      return EFI_UNSUPPORTED;
+      break;
+    case SBI_ERR_INVALID_PARAM:
+      return EFI_INVALID_PARAMETER;
+      break;
+    case SBI_ERR_DENIED:
+      return EFI_ACCESS_DENIED;
+      break;
+    case SBI_ERR_INVALID_ADDRESS:
+      return EFI_LOAD_ERROR;
+      break;
+    case SBI_ERR_ALREADY_AVAILABLE:
+      return EFI_ALREADY_STARTED;
+      break;
+    default:
+      //
+      // Reaches here only if SBI has defined a new error type
+      //
+      ASSERT (FALSE);
+      return EFI_UNSUPPORTED;
+      break;
+  }
+}
+
+//
+// OpenSBI library interface function for the base extension
+//
+
+/**
+  Get the implemented SBI specification version
+
+  The minor number of the SBI specification is encoded in the low 24 bits,
+  with the major number encoded in the next 7 bits.  Bit 32 must be 0 and is
+  reserved for future expansion.
+
+  @param[out] SpecVersion          The Version of the SBI specification.
+**/
+VOID
+EFIAPI
+SbiGetSpecVersion (
+  OUT UINTN                       *SpecVersion
+  )
+{
+  SbiRet Ret = SbiCall (SBI_EXT_BASE, SBI_EXT_BASE_GET_SPEC_VERSION, 0);
+
+  if (!Ret.Error) {
+    *SpecVersion = (UINTN)Ret.Value;
+  }
+}
+
+/**
+  Get the SBI implementation ID
+
+  This ID is used to idenetify a specific SBI implementation in order to work
+  around any quirks it might have.
+
+  @param[out] ImplId               The ID of the SBI implementation.
+**/
+VOID
+EFIAPI
+SbiGetImplId (
+  OUT UINTN                       *ImplId
+  )
+{
+  SbiRet Ret = SbiCall (SBI_EXT_BASE, SBI_EXT_BASE_GET_IMP_ID, 0);
+  *ImplId = (UINTN)Ret.Value;
+}
+
+/**
+  Get the SBI implementation version
+
+  The version of this SBI implementation.
+  The encoding of this number is determined by the specific SBI implementation.
+
+  @param[out] ImplVersion          The version of the SBI implementation.
+**/
+VOID
+EFIAPI
+SbiGetImplVersion (
+  OUT UINTN                       *ImplVersion
+  )
+{
+  SbiRet Ret = SbiCall (SBI_EXT_BASE, SBI_EXT_BASE_GET_IMP_VERSION, 0);
+  *ImplVersion = (UINTN)Ret.Value;
+}
+
+/**
+  Probe whether an SBI extension is available
+
+  ProbeResult is set to 0 if the extension is not available or to an extension
+  specified value if it is available.
+
+  @param[in]  ExtensionId          The extension ID.
+  @param[out] ProbeResult          The return value of the probe.
+**/
+VOID
+EFIAPI
+SbiProbeExtension (
+  IN  INTN                         ExtensionId,
+  OUT INTN                        *ProbeResult
+  )
+{
+  SbiRet Ret = SbiCall (SBI_EXT_BASE, SBI_EXT_BASE_PROBE_EXT, 0);
+  *ProbeResult = (UINTN)Ret.Value;
+}
+
+/**
+  Get the CPU's vendor ID
+
+  Reads the mvendorid CSR.
+
+  @param[out] MachineVendorId      The CPU's vendor ID.
+**/
+VOID
+EFIAPI
+SbiGetMachineVendorId (
+  OUT UINTN                       *MachineVendorId
+  )
+{
+  SbiRet Ret = SbiCall (SBI_EXT_BASE, SBI_EXT_BASE_GET_MVENDORID, 0);
+  *MachineVendorId = (UINTN)Ret.Value;
+}
+
+/**
+  Get the CPU's architecture ID
+
+  Reads the marchid CSR.
+
+  @param[out] MachineArchId        The CPU's architecture ID.
+**/
+VOID
+EFIAPI
+SbiGetMachineArchId (
+  OUT UINTN                       *MachineArchId
+  )
+{
+  SbiRet Ret = SbiCall (SBI_EXT_BASE, SBI_EXT_BASE_GET_MARCHID, 0);
+  *MachineArchId = (UINTN)Ret.Value;
+}
+
+/**
+  Get the CPU's architecture ID
+
+  Reads the marchid CSR.
+
+  @param[out] MachineImplId        The CPU's implementation ID.
+**/
+VOID
+EFIAPI
+SbiGetMachineImplId (
+  OUT UINTN                       *MachineImplId
+  )
+{
+  SbiRet Ret = SbiCall (SBI_EXT_BASE, SBI_EXT_BASE_GET_MIMPID, 0);
+  *MachineImplId = (UINTN)Ret.Value;
+}
+
+//
+// SBI interface function for the hart state management extension
+//
+
+/**
+  Politely ask the SBI to start a given hart.
+
+  This call may return before the hart has actually started executing, if the
+  SBI implementation can guarantee that the hart is actually going to start.
+
+  Before the hart jumps to StartAddr, the hart MUST configure PMP if present
+  and switch to S-mode.
+
+  @param[in]  HartId               The id of the hart to start.
+  @param[in]  StartAddr            The physical address, where the hart starts
+                                   executing from.
+  @param[in]  Priv                 An XLEN-bit value, which will be in register
+                                   a1 when the hart starts.
+  @retval EFI_SUCCESS              Hart was stopped and will start executing from StartAddr.
+  @retval EFI_LOAD_ERROR           StartAddr is not valid, possibly due to following reasons:
+                                     - It is not a valid physical address.
+                                     - The address is prohibited by PMP to run in
+                                       supervisor mode.
+  @retval EFI_INVALID_PARAMETER    HartId is not a valid hart id
+  @retval EFI_ALREADY_STARTED      The hart is already running.
+  @retval other                    The start request failed for unknown reasons.
+**/
+EFI_STATUS
+EFIAPI
+SbiHartStart (
+  IN  UINTN                          HartId,
+  IN  UINTN                          StartAddr,
+  IN  UINTN                          Priv
+  )
+{
+  SbiRet Ret = SbiCall (
+                 SBI_EXT_HSM,
+                 SBI_EXT_HSM_HART_START,
+                 3,
+                 HartId,
+                 StartAddr,
+                 Priv
+                 );
+  return TranslateError (Ret.Error);
+}
+
+/**
+  Return execution of the calling hart to SBI.
+
+  MUST be called in S-Mode with user interrupts disabled.
+  This call is not expected to return, unless a failure occurs.
+
+  @retval     EFI_SUCCESS          Never occurs. When successful, the call does not return.
+  @retval     other                Failed to stop hard for an unknown reason.
+**/
+EFI_STATUS
+EFIAPI
+SbiHartStop (
+  )
+{
+  SbiRet Ret = SbiCall (SBI_EXT_HSM, SBI_EXT_HSM_HART_STOP, 0);
+  return TranslateError (Ret.Error);
+}
+
+/**
+  Get the current status of a hart.
+
+  Since harts can transition between states at any time, the status retrieved
+  by this function may already be out of date, once it returns.
+
+  Possible values for HartStatus are:
+  0: STARTED
+  1: STOPPED
+  2: START_REQUEST_PENDING
+  3: STOP_REQUEST_PENDING
+
+  @param[out] HartStatus           The pointer in which the hart's status is
+                                   stored.
+  @retval EFI_SUCCESS              The operation succeeds.
+  @retval EFI_INVALID_PARAMETER    A parameter is invalid.
+**/
+EFI_STATUS
+EFIAPI
+SbiHartGetStatus (
+  IN  UINTN                          HartId,
+  OUT UINTN                         *HartStatus
+  )
+{
+  SbiRet Ret = SbiCall (SBI_EXT_HSM, SBI_EXT_HSM_HART_GET_STATUS, 1, HartId);
+
+  if (!Ret.Error) {
+    *HartStatus = (UINTN)Ret.Value;
+  }
+
+  return TranslateError (Ret.Error);
+}
+
+/**
+  Clear pending timer interrupt bit and set timer for next event after Time.
+
+  To clear the timer without scheduling a timer event, set Time to a
+  practically infinite value or mask the timer interrupt by clearing sie.STIE.
+
+  @param[in]  Time                 The time offset to the next scheduled timer interrupt.
+**/
+VOID
+EFIAPI
+SbiSetTimer (
+  IN  UINT64                         Time
+  )
+{
+  SbiCall (SBI_EXT_TIME, SBI_EXT_TIME_SET_TIMER, 1, Time);
+}
+
+EFI_STATUS
+EFIAPI
+SbiSendIpi (
+  IN  UINTN                         *HartMask,
+  IN  UINTN                          HartMaskBase
+  )
+{
+  SbiRet Ret = SbiCall (
+                 SBI_EXT_IPI,
+                 SBI_EXT_IPI_SEND_IPI,
+                 2,
+                 (UINTN)HartMask,
+                 HartMaskBase
+                 );
+  return TranslateError (Ret.Error);
+}
+
+/**
+  Instructs remote harts to execute a FENCE.I instruction.
+
+  @param[in]  HartMask             Scalar bit-vector containing hart ids
+  @param[in]  HartMaskBase         The starting hartid from which the bit-vector
+                                   must be computed. If set to -1, HartMask is
+                                   ignored and all harts are considered.
+  @retval EFI_SUCCESS              IPI was sent to all the targeted harts.
+  @retval EFI_INVALID_PARAMETER    Either hart_mask_base or any of the hartid
+                                   from hart_mask is not valid i.e. either the
+                                   hartid is not enabled by the platform or is
+                                   not available to the supervisor.
+**/
+EFI_STATUS
+EFIAPI
+SbiRemoteFenceI (
+  IN  UINTN                         *HartMask,
+  IN  UINTN                          HartMaskBase
+  )
+{
+  SbiRet Ret = SbiCall (
+                 SBI_EXT_RFENCE,
+                 SBI_EXT_RFENCE_REMOTE_FENCE_I,
+                 2,
+                 (UINTN)HartMask,
+                 HartMaskBase
+                 );
+  return TranslateError (Ret.Error);
+}
+
+/**
+  Instructs the remote harts to execute one or more SFENCE.VMA instructions.
+
+  The SFENCE.VMA covers the range of virtual addresses between StartAaddr and Size.
+
+  The remote fence function acts as a full tlb flush if * StartAddr and size
+  are both 0 * size is equal to 2^XLEN-1
+
+  @param[in]  HartMask             Scalar bit-vector containing hart ids
+  @param[in]  HartMaskBase         The starting hartid from which the bit-vector
+                                   must be computed. If set to -1, HartMask is
+                                   ignored and all harts are considered.
+  @param[in]  StartAddr            The first address of the affected range.
+  @param[in]  Size                 How many addresses are affected.
+  @retval EFI_SUCCESS              IPI was sent to all the targeted harts.
+  @retval EFI_LOAD_ERROR           StartAddr or Size is not valid.
+  @retval EFI_INVALID_PARAMETER    Either hart_mask_base or any of the hartid
+                                   from hart_mask is not valid i.e. either the
+                                   hartid is not enabled by the platform or is
+                                   not available to the supervisor.
+**/
+EFI_STATUS
+EFIAPI
+SbiRemoteSfenceVma (
+  IN  UINTN                         *HartMask,
+  IN  UINTN                          HartMaskBase,
+  IN  UINTN                          StartAddr,
+  IN  UINTN                          Size
+  )
+{
+  SbiRet Ret = SbiCall (
+                 SBI_EXT_RFENCE,
+                 SBI_EXT_RFENCE_REMOTE_SFENCE_VMA,
+                 4,
+                 (UINTN)HartMask,
+                 HartMaskBase,
+                 StartAddr,
+                 Size
+                 );
+  return TranslateError (Ret.Error);
+}
+
+/**
+  Instructs the remote harts to execute one or more SFENCE.VMA instructions.
+
+  The SFENCE.VMA covers the range of virtual addresses between StartAaddr and Size.
+  Covers only the given ASID.
+
+  The remote fence function acts as a full tlb flush if * StartAddr and size
+  are both 0 * size is equal to 2^XLEN-1
+
+  @param[in]  HartMask             Scalar bit-vector containing hart ids
+  @param[in]  HartMaskBase         The starting hartid from which the bit-vector
+                                   must be computed. If set to -1, HartMask is
+                                   ignored and all harts are considered.
+  @param[in]  StartAddr            The first address of the affected range.
+  @param[in]  Size                 How many addresses are affected.
+  @retval EFI_SUCCESS              IPI was sent to all the targeted harts.
+  @retval EFI_LOAD_ERROR           StartAddr or Size is not valid.
+  @retval EFI_INVALID_PARAMETER    Either hart_mask_base or any of the hartid
+                                   from hart_mask is not valid i.e. either the
+                                   hartid is not enabled by the platform or is
+                                   not available to the supervisor.
+**/
+EFI_STATUS
+EFIAPI
+SbiRemoteSfenceVmaAsid (
+  IN  UINTN                         *HartMask,
+  IN  UINTN                          HartMaskBase,
+  IN  UINTN                          StartAddr,
+  IN  UINTN                          Size,
+  IN  UINTN                          Asid
+  )
+{
+  SbiRet Ret = SbiCall (
+                 SBI_EXT_RFENCE,
+                 SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID,
+                 5,
+                 (UINTN)HartMask,
+                 HartMaskBase,
+                 StartAddr,
+                 Size,
+                 Asid
+                 );
+  return TranslateError (Ret.Error);
+}
+
+/**
+  Instructs the remote harts to execute one or more SFENCE.GVMA instructions.
+
+  The SFENCE.GVMA covers the range of virtual addresses between StartAaddr and Size.
+  Covers only the given VMID.
+  This function call is only valid for harts implementing the hypervisor extension.
+
+  The remote fence function acts as a full tlb flush if * StartAddr and size
+  are both 0 * size is equal to 2^XLEN-1
+
+  @param[in]  HartMask             Scalar bit-vector containing hart ids
+  @param[in]  HartMaskBase         The starting hartid from which the bit-vector
+                                   must be computed. If set to -1, HartMask is
+                                   ignored and all harts are considered.
+  @param[in]  StartAddr            The first address of the affected range.
+  @param[in]  Size                 How many addresses are affected.
+  @retval EFI_SUCCESS              IPI was sent to all the targeted harts.
+  @retval EFI_LOAD_ERROR           StartAddr or Size is not valid.
+  @retval EFI_UNSUPPORTED          SBI does not implement this function or one
+                                   of the target harts does not support the
+                                   hypervisor extension.
+  @retval EFI_INVALID_PARAMETER    Either hart_mask_base or any of the hartid
+                                   from hart_mask is not valid i.e. either the
+                                   hartid is not enabled by the platform or is
+                                   not available to the supervisor.
+**/
+EFI_STATUS
+EFIAPI
+SbiRemoteHFenceGvmaVmid (
+  IN  UINTN                         *HartMask,
+  IN  UINTN                          HartMaskBase,
+  IN  UINTN                          StartAddr,
+  IN  UINTN                          Size,
+  IN  UINTN                          Vmid
+  )
+{
+  SbiRet Ret = SbiCall (
+                 SBI_EXT_RFENCE,
+                 SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA,
+                 5,
+                 (UINTN)HartMask,
+                 HartMaskBase,
+                 StartAddr,
+                 Size,
+                 Vmid
+                 );
+  return TranslateError (Ret.Error);
+}
+
+/**
+  Instructs the remote harts to execute one or more SFENCE.GVMA instructions.
+
+  The SFENCE.GVMA covers the range of virtual addresses between StartAaddr and Size.
+  This function call is only valid for harts implementing the hypervisor extension.
+
+  The remote fence function acts as a full tlb flush if * StartAddr and size
+  are both 0 * size is equal to 2^XLEN-1
+
+  @param[in]  HartMask             Scalar bit-vector containing hart ids
+  @param[in]  HartMaskBase         The starting hartid from which the bit-vector
+                                   must be computed. If set to -1, HartMask is
+                                   ignored and all harts are considered.
+  @param[in]  StartAddr            The first address of the affected range.
+  @param[in]  Size                 How many addresses are affected.
+  @retval EFI_SUCCESS              IPI was sent to all the targeted harts.
+  @retval EFI_LOAD_ERROR           StartAddr or Size is not valid.
+  @retval EFI_UNSUPPORTED          SBI does not implement this function or one
+                                   of the target harts does not support the
+                                   hypervisor extension.
+  @retval EFI_INVALID_PARAMETER    Either hart_mask_base or any of the hartid
+                                   from hart_mask is not valid i.e. either the
+                                   hartid is not enabled by the platform or is
+                                   not available to the supervisor.
+**/
+EFI_STATUS
+EFIAPI
+SbiRemoteHFenceGvma (
+  IN  UINTN                         *HartMask,
+  IN  UINTN                          HartMaskBase,
+  IN  UINTN                          StartAddr,
+  IN  UINTN                          Size
+  )
+{
+  SbiRet Ret = SbiCall (
+                 SBI_EXT_RFENCE,
+                 SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA_VMID,
+                 4,
+                 (UINTN)HartMask,
+                 HartMaskBase,
+                 StartAddr,
+                 Size
+                 );
+  return TranslateError (Ret.Error);
+}
+
+/**
+  Instructs the remote harts to execute one or more SFENCE.VVMA instructions.
+
+  The SFENCE.GVMA covers the range of virtual addresses between StartAaddr and Size.
+  Covers only the given ASID.
+  This function call is only valid for harts implementing the hypervisor extension.
+
+  The remote fence function acts as a full tlb flush if * StartAddr and size
+  are both 0 * size is equal to 2^XLEN-1
+
+  @param[in]  HartMask             Scalar bit-vector containing hart ids
+  @param[in]  HartMaskBase         The starting hartid from which the bit-vector
+                                   must be computed. If set to -1, HartMask is
+                                   ignored and all harts are considered.
+  @param[in]  StartAddr            The first address of the affected range.
+  @param[in]  Size                 How many addresses are affected.
+  @retval EFI_SUCCESS              IPI was sent to all the targeted harts.
+  @retval EFI_LOAD_ERROR           StartAddr or Size is not valid.
+  @retval EFI_UNSUPPORTED          SBI does not implement this function or one
+                                   of the target harts does not support the
+                                   hypervisor extension.
+  @retval EFI_INVALID_PARAMETER    Either hart_mask_base or any of the hartid
+                                   from hart_mask is not valid i.e. either the
+                                   hartid is not enabled by the platform or is
+                                   not available to the supervisor.
+**/
+EFI_STATUS
+EFIAPI
+SbiRemoteHFenceVvmaAsid (
+  IN  UINTN                         *HartMask,
+  IN  UINTN                          HartMaskBase,
+  IN  UINTN                          StartAddr,
+  IN  UINTN                          Size,
+  IN  UINTN                          Asid
+  )
+{
+  SbiRet Ret = SbiCall (
+                 SBI_EXT_RFENCE,
+                 SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA,
+                 5,
+                 (UINTN)HartMask,
+                 HartMaskBase,
+                 StartAddr,
+                 Size,
+                 Asid
+                 );
+  return TranslateError (Ret.Error);
+}
+
+/**
+  Instructs the remote harts to execute one or more SFENCE.VVMA instructions.
+
+  The SFENCE.GVMA covers the range of virtual addresses between StartAaddr and Size.
+  This function call is only valid for harts implementing the hypervisor extension.
+
+  The remote fence function acts as a full tlb flush if * StartAddr and size
+  are both 0 * size is equal to 2^XLEN-1
+
+  @param[in]  HartMask             Scalar bit-vector containing hart ids
+  @param[in]  HartMaskBase         The starting hartid from which the bit-vector
+                                   must be computed. If set to -1, HartMask is
+                                   ignored and all harts are considered.
+  @param[in]  StartAddr            The first address of the affected range.
+  @param[in]  Size                 How many addresses are affected.
+  @retval EFI_SUCCESS              IPI was sent to all the targeted harts.
+  @retval EFI_LOAD_ERROR           StartAddr or Size is not valid.
+  @retval EFI_UNSUPPORTED          SBI does not implement this function or one
+                                   of the target harts does not support the
+                                   hypervisor extension.
+  @retval EFI_INVALID_PARAMETER    Either hart_mask_base or any of the hartid
+                                   from hart_mask is not valid i.e. either the
+                                   hartid is not enabled by the platform or is
+                                   not available to the supervisor.
+**/
+EFI_STATUS
+EFIAPI
+SbiRemoteHFenceVvma (
+  IN  UINTN                         *HartMask,
+  IN  UINTN                          HartMaskBase,
+  IN  UINTN                          StartAddr,
+  IN  UINTN                          Size
+  )
+{
+  SbiRet Ret = SbiCall (
+                 SBI_EXT_RFENCE,
+                 SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA_ASID,
+                 4,
+                 (UINTN)HartMask,
+                 HartMaskBase,
+                 StartAddr,
+                 Size
+                 );
+  return TranslateError (Ret.Error);
+}
+
+//
+// SBI interface function for the vendor extension
+//
+
+/**
+  Call a function in a vendor defined SBI extension
+
+  ASSERT() if the ExtensionId is not in the designated SBI Vendor Extension
+  Space or NumArgs exceeds SBI_CALL_MAX_ARGS.
+
+  @param[in]  ExtensionId          The SBI vendor extension ID.
+  @param[in]  FunctionId           The function ID to call in this extension.
+  @param[in]  NumArgs              How many arguments are passed.
+  @param[in]  ...                  Actual Arguments to the function.
+  @retval EFI_SUCCESS if the SBI function was called and it was successful
+  @retval others if the called SBI function returns an error
+**/
+EFI_STATUS
+EFIAPI
+SbiVendorCall (
+  IN  UINTN                          ExtensionId,
+  IN  UINTN                          FunctionId,
+  IN  UINTN                          NumArgs,
+  ...
+  )
+{
+    SbiRet Ret;
+    VA_LIST Args;
+    VA_START (Args, NumArgs);
+
+    ASSERT (ExtensionId >= SBI_EXT_VENDOR_START && ExtensionId <= SBI_EXT_VENDOR_END);
+    ASSERT (NumArgs <= SBI_CALL_MAX_ARGS);
+
+    switch (NumArgs) {
+      case 0:
+        Ret = SbiCall (ExtensionId, FunctionId, NumArgs);
+        break;
+      case 1:
+        Ret = SbiCall (ExtensionId, FunctionId, NumArgs, VA_ARG (Args, UINTN));
+        break;
+      case 2:
+        Ret = SbiCall (ExtensionId, FunctionId, NumArgs, VA_ARG (Args, UINTN),
+                       VA_ARG (Args, UINTN));
+        break;
+      case 3:
+        Ret = SbiCall (ExtensionId, FunctionId, NumArgs, VA_ARG (Args, UINTN),
+                       VA_ARG (Args, UINTN), VA_ARG (Args, UINTN));
+        break;
+      case 4:
+        Ret = SbiCall (ExtensionId, FunctionId, NumArgs, VA_ARG (Args, UINTN),
+                       VA_ARG (Args, UINTN), VA_ARG (Args, UINTN),
+                       VA_ARG (Args, UINTN));
+        break;
+      case 5:
+        Ret = SbiCall (ExtensionId, FunctionId, NumArgs, VA_ARG (Args, UINTN),
+                       VA_ARG (Args, UINTN), VA_ARG (Args, UINTN),
+                       VA_ARG (Args, UINTN), VA_ARG (Args, UINTN));
+        break;
+      case 6:
+        Ret = SbiCall (ExtensionId, FunctionId, NumArgs, VA_ARG (Args, UINTN),
+                       VA_ARG (Args, UINTN), VA_ARG (Args, UINTN),
+                       VA_ARG (Args, UINTN), VA_ARG (Args, UINTN),
+                       VA_ARG (Args, UINTN));
+        break;
+      default:
+        // Too many args. In theory SBI can handle more arguments when they are
+        // passed on the stack but no SBI extension uses this, therefore it's
+        // not yet implemented here.
+        return EFI_INVALID_PARAMETER;
+     }
+
+    VA_END(Args);
+    return TranslateError (Ret.Error);
+}
+
+//
+// SBI Firmware extension
+//
+
+/**
+  Get scratch space of the current hart.
+
+  Please consider using the wrapper SbiGetFirmwareContext if you only need to
+  access the firmware context.
+
+  @param[out] ScratchSpace         The scratch space pointer.
+  @retval EFI_SUCCESS              The operation succeeds.
+**/
+EFI_STATUS
+EFIAPI
+SbiGetMscratch (
+  OUT SBI_SCRATCH                    **ScratchSpace
+  )
+{
+  SbiRet Ret = SbiCall (SBI_EDK2_FW_EXT, SBI_EXT_FW_MSCRATCH_FUNC, 0);
+
+  if (!Ret.Error) {
+    *ScratchSpace = (SBI_SCRATCH *)Ret.Value;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Get scratch space of the given hart id.
+
+  @param[in]  HartId               The hart id.
+  @param[out] ScratchSpace         The scratch space pointer.
+  @retval EFI_SUCCESS              The operation succeeds.
+**/
+EFI_STATUS
+EFIAPI
+SbiGetMscratchHartid (
+  IN  UINTN                            HartId,
+  OUT SBI_SCRATCH                    **ScratchSpace
+  )
+{
+  SbiRet Ret = SbiCall (
+                 SBI_EDK2_FW_EXT,
+                 SBI_EXT_FW_MSCRATCH_HARTID_FUNC,
+                 1,
+                 HartId
+                 );
+
+  if (!Ret.Error) {
+    *ScratchSpace = (SBI_SCRATCH *)Ret.Value;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Get firmware context of the calling hart.
+
+  @param[out] FirmwareContext      The firmware context pointer.
+  @retval EFI_SUCCESS              The operation succeeds.
+**/
+EFI_STATUS
+EFIAPI
+SbiGetFirmwareContext (
+  OUT EFI_RISCV_OPENSBI_FIRMWARE_CONTEXT **FirmwareContext
+  )
+{
+  SBI_SCRATCH  *ScratchSpace;
+  SBI_PLATFORM *SbiPlatform;
+  SbiRet Ret = SbiCall (SBI_EDK2_FW_EXT, SBI_EXT_FW_MSCRATCH_FUNC, 0);
+
+  if (!Ret.Error) {
+    ScratchSpace = (SBI_SCRATCH *)Ret.Value;
+    SbiPlatform = (SBI_PLATFORM *)sbi_platform_ptr(ScratchSpace);
+    *FirmwareContext = (EFI_RISCV_OPENSBI_FIRMWARE_CONTEXT *)SbiPlatform->firmware_context;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Set firmware context of the calling hart.
+
+  @param[in] FirmwareContext       The firmware context pointer.
+  @retval EFI_SUCCESS              The operation succeeds.
+**/
+EFI_STATUS
+EFIAPI
+SbiSetFirmwareContext (
+  IN EFI_RISCV_OPENSBI_FIRMWARE_CONTEXT *FirmwareContext
+  )
+{
+  SBI_SCRATCH  *ScratchSpace;
+  SBI_PLATFORM *SbiPlatform;
+  SbiRet Ret = SbiCall (SBI_EDK2_FW_EXT, SBI_EXT_FW_MSCRATCH_FUNC, 0);
+
+  if (!Ret.Error) {
+    ScratchSpace = (SBI_SCRATCH *)Ret.Value;
+    SbiPlatform = (SBI_PLATFORM *)sbi_platform_ptr (ScratchSpace);
+    SbiPlatform->firmware_context = (UINTN)FirmwareContext;
+  }
+
+  return EFI_SUCCESS;
+}
-- 
2.26.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [edk2-devel] [PATCH v4 1/1] ProcessorPkg/Library: Add RiscVEdk2SbiLib
  2020-06-02 16:51 ` [PATCH v4 1/1] ProcessorPkg/Library: Add RiscVEdk2SbiLib Daniel Schaefer
@ 2020-06-02 22:00   ` Michael D Kinney
  2020-06-03  1:24     ` Abner Chang
       [not found]     ` <1614E4344379EB27.21938@groups.io>
  2020-06-18 16:49   ` Leif Lindholm
  1 sibling, 2 replies; 7+ messages in thread
From: Michael D Kinney @ 2020-06-02 22:00 UTC (permalink / raw)
  To: devel@edk2.groups.io, daniel.schaefer@hpe.com, Kinney, Michael D
  Cc: Leif Lindholm, Gilbert Chen, Abner Chang

Hi Daniel,

I see some inconsistence in the names used in these patches.

For example, there should not be a need to use "Edk2" in the
name of a library.  This library is in an edk2 repo.

I see "RiscV" and "Risk-V" used in file paths.  I recommend
you pick one and use it consistently.  In the MdePkg, I see
RiscV64, and macros using RISCV, RISCV32, RISCV64, and RISCV128.
which seems consistent and does not use a '-'.  Perhaps use 
"RiscV" for content that works for 32, 64, and 128 bit and
RiscV32, RiscV64, and RiskV128 for content is specific to the
bit width?

Thanks,

Mike

> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On
> Behalf Of Daniel Schaefer
> Sent: Tuesday, June 2, 2020 9:52 AM
> To: devel@edk2.groups.io
> Cc: Leif Lindholm <leif@nuviainc.com>; Gilbert Chen
> <gilbert.chen@hpe.com>; Abner Chang
> <abner.chang@hpe.com>; Kinney, Michael D
> <michael.d.kinney@intel.com>
> Subject: [edk2-devel] [PATCH v4 1/1]
> ProcessorPkg/Library: Add RiscVEdk2SbiLib
> 
> Library provides interfaces to invoke SBI ecalls.
> 
> Signed-off-by: Daniel Schaefer <daniel.schaefer@hpe.com>
> 
> Cc: Leif Lindholm <leif@nuviainc.com>
> Cc: Gilbert Chen <gilbert.chen@hpe.com>
> Cc: Abner Chang <abner.chang@hpe.com>
> Cc: Michael D. Kinney <michael.d.kinney@intel.com>
> ---
>  Silicon/RISC-
> V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.i
> nf |  28 +
>  Silicon/RISC-
> V/ProcessorPkg/Include/Library/RiscVEdk2SbiLib.h
> | 563 ++++++++++++
>  Silicon/RISC-
> V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.c
> | 897 ++++++++++++++++++++
>  3 files changed, 1488 insertions(+)
> 
> diff --git a/Silicon/RISC-
> V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.i
> nf b/Silicon/RISC-
> V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.i
> nf
> new file mode 100644
> index 000000000000..665dcbf40e01
> --- /dev/null
> +++ b/Silicon/RISC-
> V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.i
> nf
> @@ -0,0 +1,28 @@
> +## @file
> 
> 
> +# RISC-V Library to call SBI ecalls
> 
> 
> +#
> 
> 
> +#  Copyright (c) 2020, Hewlett Packard Enterprise
> Development LP. All rights reserved.<BR>
> 
> 
> +#
> 
> 
> +#  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> 
> +#
> 
> 
> +##
> 
> 
> +
> 
> 
> +[Defines]
> 
> 
> +  INF_VERSION    = 0x0001001b
> 
> 
> +  BASE_NAME      = RiscVEdk2SbiLib
> 
> 
> +  FILE_GUID      = 0DF1BBBD-F7E5-4E8A-BCF1-9D63D2DD9FDD
> 
> 
> +  MODULE_TYPE    = BASE
> 
> 
> +  VERSION_STRING = 1.0
> 
> 
> +  LIBRARY_CLASS  = RiscVEdk2SbiLib
> 
> 
> +
> 
> 
> +[Sources]
> 
> 
> +  RiscVEdk2SbiLib.c
> 
> 
> +
> 
> 
> +[Packages]
> 
> 
> +  MdePkg/MdePkg.dec
> 
> 
> +  Silicon/RISC-V/ProcessorPkg/RiscVProcessorPkg.dec
> 
> 
> +  Platform/RISC-V/PlatformPkg/RiscVPlatformPkg.dec
> 
> 
> +
> 
> 
> +[LibraryClasses]
> 
> 
> +  BaseLib
> 
> 
> +  RiscVOpensbiLib
> 
> 
> diff --git a/Silicon/RISC-
> V/ProcessorPkg/Include/Library/RiscVEdk2SbiLib.h
> b/Silicon/RISC-
> V/ProcessorPkg/Include/Library/RiscVEdk2SbiLib.h
> new file mode 100644
> index 000000000000..c1ae3176147f
> --- /dev/null
> +++ b/Silicon/RISC-
> V/ProcessorPkg/Include/Library/RiscVEdk2SbiLib.h
> @@ -0,0 +1,563 @@
> +/** @file
> 
> 
> +  Library to call the RISC-V SBI ecalls
> 
> 
> +
> 
> 
> +  Copyright (c) 2020, Hewlett Packard Development LP.
> All rights reserved.<BR>
> 
> 
> +
> 
> 
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> 
> +
> 
> 
> +  @par Glossary:
> 
> 
> +    - Hart - Hardware Thread, similar to a CPU core
> 
> 
> +**/
> 
> 
> +
> 
> 
> +#ifndef RISCV_SBI_LIB_H_
> 
> 
> +#define RISCV_SBI_LIB_H_
> 
> 
> +
> 
> 
> +#include <Uefi.h>
> 
> 
> +#include <IndustryStandard/RiscVOpensbi.h>
> 
> 
> +#include <sbi/sbi_scratch.h>
> 
> 
> +#include <sbi/sbi_platform.h>
> 
> 
> +
> 
> 
> +//
> 
> 
> +// EDK2 OpenSBI Firmware extension.
> 
> 
> +//
> 
> 
> +#define SBI_EDK2_FW_EXT
> (SBI_EXT_FIRMWARE_CODE_BASE_START | SBI_OPENSBI_IMPID)
> 
> 
> +//
> 
> 
> +// EDK2 OpenSBI Firmware extension functions.
> 
> 
> +//
> 
> 
> +#define SBI_EXT_FW_MSCRATCH_FUNC        0
> 
> 
> +#define SBI_EXT_FW_MSCRATCH_HARTID_FUNC 1
> 
> 
> +
> 
> 
> +//
> 
> 
> +// EDK2 OpenSBI firmware extension return status.
> 
> 
> +//
> 
> 
> +typedef struct {
> 
> 
> +  UINTN Error;   ///< SBI status code
> 
> 
> +  UINTN Value;   ///< Value returned
> 
> 
> +} SbiRet;
> 
> 
> +
> 
> 
> +/**
> 
> 
> +  Get the implemented SBI specification version
> 
> 
> +
> 
> 
> +  The minor number of the SBI specification is encoded
> in the low 24 bits,
> 
> 
> +  with the major number encoded in the next 7 bits.
> Bit 32 must be 0 and is
> 
> 
> +  reserved for future expansion.
> 
> 
> +
> 
> 
> +  @param[out] SpecVersion          The Version of the
> SBI specification.
> 
> 
> +**/
> 
> 
> +VOID
> 
> 
> +EFIAPI
> 
> 
> +SbiGetSpecVersion (
> 
> 
> +  OUT UINTN                       *SpecVersion
> 
> 
> +  );
> 
> 
> +
> 
> 
> +/**
> 
> 
> +  Get the SBI implementation ID
> 
> 
> +
> 
> 
> +  This ID is used to idenetify a specific SBI
> implementation in order to work
> 
> 
> +  around any quirks it might have.
> 
> 
> +
> 
> 
> +  @param[out] ImplId               The ID of the SBI
> implementation.
> 
> 
> +**/
> 
> 
> +VOID
> 
> 
> +EFIAPI
> 
> 
> +SbiGetImplId (
> 
> 
> +  OUT UINTN                      *ImplId
> 
> 
> +  );
> 
> 
> +
> 
> 
> +/**
> 
> 
> +  Get the SBI implementation version
> 
> 
> +
> 
> 
> +  The version of this SBI implementation.
> 
> 
> +  The encoding of this number is determined by the
> specific SBI implementation.
> 
> 
> +
> 
> 
> +  @param[out] ImplVersion          The version of the
> SBI implementation.
> 
> 
> +**/
> 
> 
> +VOID
> 
> 
> +EFIAPI
> 
> 
> +SbiGetImplVersion (
> 
> 
> +  OUT UINTN                       *ImplVersion
> 
> 
> +  );
> 
> 
> +
> 
> 
> +/**
> 
> 
> +  Probe whether an SBI extension is available
> 
> 
> +
> 
> 
> +  ProbeResult is set to 0 if the extension is not
> available or to an extension
> 
> 
> +  specified value if it is available.
> 
> 
> +
> 
> 
> +  @param[in]  ExtensionId          The extension ID.
> 
> 
> +  @param[out] ProbeResult          The return value of
> the probe.
> 
> 
> +**/
> 
> 
> +VOID
> 
> 
> +EFIAPI
> 
> 
> +SbiProbeExtension (
> 
> 
> +  IN  INTN                         ExtensionId,
> 
> 
> +  OUT INTN                        *ProbeResult
> 
> 
> +  );
> 
> 
> +
> 
> 
> +/**
> 
> 
> +  Get the CPU's vendor ID
> 
> 
> +
> 
> 
> +  Reads the mvendorid CSR.
> 
> 
> +
> 
> 
> +  @param[out] MachineVendorId      The CPU's vendor ID.
> 
> 
> +**/
> 
> 
> +VOID
> 
> 
> +EFIAPI
> 
> 
> +SbiGetMachineVendorId (
> 
> 
> +  OUT UINTN                       *MachineVendorId
> 
> 
> +  );
> 
> 
> +
> 
> 
> +/**
> 
> 
> +  Get the CPU's architecture ID
> 
> 
> +
> 
> 
> +  Reads the marchid CSR.
> 
> 
> +
> 
> 
> +  @param[out] MachineArchId        The CPU's
> architecture ID.
> 
> 
> +**/
> 
> 
> +VOID
> 
> 
> +EFIAPI
> 
> 
> +SbiGetMachineArchId (
> 
> 
> +  OUT UINTN                       *MachineArchId
> 
> 
> +  );
> 
> 
> +
> 
> 
> +/**
> 
> 
> +  Get the CPU's implementation ID
> 
> 
> +
> 
> 
> +  Reads the mimpid CSR.
> 
> 
> +
> 
> 
> +  @param[out] MachineImplId        The CPU's
> implementation ID.
> 
> 
> +**/
> 
> 
> +VOID
> 
> 
> +EFIAPI
> 
> 
> +SbiGetMachineImplId (
> 
> 
> +  OUT UINTN                       *MachineImplId
> 
> 
> +  );
> 
> 
> +
> 
> 
> +/**
> 
> 
> +  Politely ask the SBI to start a given hart.
> 
> 
> +
> 
> 
> +  This call may return before the hart has actually
> started executing, if the
> 
> 
> +  SBI implementation can guarantee that the hart is
> actually going to start.
> 
> 
> +
> 
> 
> +  Before the hart jumps to StartAddr, the hart MUST
> configure PMP if present
> 
> 
> +  and switch to S-mode.
> 
> 
> +
> 
> 
> +  @param[in]  HartId               The id of the hart
> to start.
> 
> 
> +  @param[in]  StartAddr            The physical
> address, where the hart starts
> 
> 
> +                                   executing from.
> 
> 
> +  @param[in]  Priv                 An XLEN-bit value,
> which will be in register
> 
> 
> +                                   a1 when the hart
> starts.
> 
> 
> +  @retval EFI_SUCCESS              Hart was stopped and
> will start executing from StartAddr.
> 
> 
> +  @retval EFI_LOAD_ERROR           StartAddr is not
> valid, possibly due to following reasons:
> 
> 
> +                                    - It is not a valid
> physical address.
> 
> 
> +                                    - The address is
> prohibited by PMP to run in
> 
> 
> +                                      supervisor mode.
> 
> 
> +  @retval EFI_INVALID_PARAMETER    HartId is not a
> valid hart id
> 
> 
> +  @retval EFI_ALREADY_STARTED      The hart is already
> running.
> 
> 
> +  @retval other                    The start request
> failed for unknown reasons.
> 
> 
> +**/
> 
> 
> +EFI_STATUS
> 
> 
> +EFIAPI
> 
> 
> +SbiHartStart (
> 
> 
> +  IN  UINTN                          HartId,
> 
> 
> +  IN  UINTN                          StartAddr,
> 
> 
> +  IN  UINTN                          Priv
> 
> 
> +  );
> 
> 
> +
> 
> 
> +/**
> 
> 
> +  Return execution of the calling hart to SBI.
> 
> 
> +
> 
> 
> +  MUST be called in S-Mode with user interrupts
> disabled.
> 
> 
> +  This call is not expected to return, unless a failure
> occurs.
> 
> 
> +
> 
> 
> +  @retval     EFI_SUCCESS          Never occurs. When
> successful, the call does not return.
> 
> 
> +  @retval     other                Failed to stop hard
> for an unknown reason.
> 
> 
> +**/
> 
> 
> +EFI_STATUS
> 
> 
> +EFIAPI
> 
> 
> +SbiHartStop (
> 
> 
> +  );
> 
> 
> +
> 
> 
> +/**
> 
> 
> +  Get the current status of a hart.
> 
> 
> +
> 
> 
> +  Since harts can transition between states at any
> time, the status retrieved
> 
> 
> +  by this function may already be out of date, once it
> returns.
> 
> 
> +
> 
> 
> +  Possible values for HartStatus are:
> 
> 
> +  0: STARTED
> 
> 
> +  1: STOPPED
> 
> 
> +  2: START_REQUEST_PENDING
> 
> 
> +  3: STOP_REQUEST_PENDING
> 
> 
> +
> 
> 
> +  @param[out] HartStatus           The pointer in which
> the hart's status is
> 
> 
> +                                   stored.
> 
> 
> +  @retval EFI_SUCCESS              The operation
> succeeds.
> 
> 
> +  @retval EFI_INVALID_PARAMETER    A parameter is
> invalid.
> 
> 
> +**/
> 
> 
> +EFI_STATUS
> 
> 
> +EFIAPI
> 
> 
> +SbiHartGetStatus (
> 
> 
> +  IN  UINTN                          HartId,
> 
> 
> +  OUT UINTN                         *HartStatus
> 
> 
> +  );
> 
> 
> +
> 
> 
> +///
> 
> 
> +/// Timer extension
> 
> 
> +///
> 
> 
> +
> 
> 
> +/**
> 
> 
> +  Clear pending timer interrupt bit and set timer for
> next event after Time.
> 
> 
> +
> 
> 
> +  To clear the timer without scheduling a timer event,
> set Time to a
> 
> 
> +  practically infinite value or mask the timer
> interrupt by clearing sie.STIE.
> 
> 
> +
> 
> 
> +  @param[in]  Time                 The time offset to
> the next scheduled timer interrupt.
> 
> 
> +**/
> 
> 
> +VOID
> 
> 
> +EFIAPI
> 
> 
> +SbiSetTimer (
> 
> 
> +  IN  UINT64                         Time
> 
> 
> +  );
> 
> 
> +
> 
> 
> +///
> 
> 
> +/// IPI extension
> 
> 
> +///
> 
> 
> +
> 
> 
> +/**
> 
> 
> +  Send IPI to all harts specified in the mask.
> 
> 
> +
> 
> 
> +  The interrupts are registered as supervisor software
> interrupts at the
> 
> 
> +  receiving hart.
> 
> 
> +
> 
> 
> +  @param[in]  HartMask             Scalar bit-vector
> containing hart ids
> 
> 
> +  @param[in]  HartMaskBase         The starting hartid
> from which the bit-vector
> 
> 
> +                                   must be computed. If
> set to -1, HartMask is
> 
> 
> +                                   ignored and all
> harts are considered.
> 
> 
> +  @retval EFI_SUCCESS              IPI was sent to all
> the targeted harts.
> 
> 
> +  @retval EFI_INVALID_PARAMETER    Either
> hart_mask_base or any of the hartid
> 
> 
> +                                   from hart_mask is
> not valid i.e. either the
> 
> 
> +                                   hartid is not
> enabled by the platform or is
> 
> 
> +                                   not available to the
> supervisor.
> 
> 
> +**/
> 
> 
> +EFI_STATUS
> 
> 
> +EFIAPI
> 
> 
> +SbiSendIpi (
> 
> 
> +  IN  UINTN                         *HartMask,
> 
> 
> +  IN  UINTN                          HartMaskBase
> 
> 
> +  );
> 
> 
> +
> 
> 
> +///
> 
> 
> +/// Remote fence extension
> 
> 
> +///
> 
> 
> +
> 
> 
> +/**
> 
> 
> +  Instructs remote harts to execute a FENCE.I
> instruction.
> 
> 
> +
> 
> 
> +  @param[in]  HartMask             Scalar bit-vector
> containing hart ids
> 
> 
> +  @param[in]  HartMaskBase         The starting hartid
> from which the bit-vector
> 
> 
> +                                   must be computed. If
> set to -1, HartMask is
> 
> 
> +                                   ignored and all
> harts are considered.
> 
> 
> +  @retval EFI_SUCCESS              IPI was sent to all
> the targeted harts.
> 
> 
> +  @retval EFI_INVALID_PARAMETER    Either
> hart_mask_base or any of the hartid
> 
> 
> +                                   from hart_mask is
> not valid i.e. either the
> 
> 
> +                                   hartid is not
> enabled by the platform or is
> 
> 
> +                                   not available to the
> supervisor.
> 
> 
> +**/
> 
> 
> +EFI_STATUS
> 
> 
> +EFIAPI
> 
> 
> +SbiRemoteFenceI (
> 
> 
> +  IN  UINTN                         *HartMask,
> 
> 
> +  IN  UINTN                          HartMaskBase
> 
> 
> +  );
> 
> 
> +
> 
> 
> +/**
> 
> 
> +  Instructs the remote harts to execute one or more
> SFENCE.VMA instructions.
> 
> 
> +
> 
> 
> +  The SFENCE.VMA covers the range of virtual addresses
> between StartAaddr and Size.
> 
> 
> +
> 
> 
> +  The remote fence function acts as a full tlb flush if
> * StartAddr and size
> 
> 
> +  are both 0 * size is equal to 2^XLEN-1
> 
> 
> +
> 
> 
> +  @param[in]  HartMask             Scalar bit-vector
> containing hart ids
> 
> 
> +  @param[in]  HartMaskBase         The starting hartid
> from which the bit-vector
> 
> 
> +                                   must be computed. If
> set to -1, HartMask is
> 
> 
> +                                   ignored and all
> harts are considered.
> 
> 
> +  @param[in]  StartAddr            The first address of
> the affected range.
> 
> 
> +  @param[in]  Size                 How many addresses
> are affected.
> 
> 
> +  @retval EFI_SUCCESS              IPI was sent to all
> the targeted harts.
> 
> 
> +  @retval EFI_LOAD_ERROR           StartAddr or Size is
> not valid.
> 
> 
> +  @retval EFI_INVALID_PARAMETER    Either
> hart_mask_base or any of the hartid
> 
> 
> +                                   from hart_mask is
> not valid i.e. either the
> 
> 
> +                                   hartid is not
> enabled by the platform or is
> 
> 
> +                                   not available to the
> supervisor.
> 
> 
> +**/
> 
> 
> +EFI_STATUS
> 
> 
> +EFIAPI
> 
> 
> +SbiRemoteSfenceVma (
> 
> 
> +  IN  UINTN                         *HartMask,
> 
> 
> +  IN  UINTN                          HartMaskBase,
> 
> 
> +  IN  UINTN                          StartAddr,
> 
> 
> +  IN  UINTN                          Size
> 
> 
> +  );
> 
> 
> +
> 
> 
> +/**
> 
> 
> +  Instructs the remote harts to execute one or more
> SFENCE.VMA instructions.
> 
> 
> +
> 
> 
> +  The SFENCE.VMA covers the range of virtual addresses
> between StartAaddr and Size.
> 
> 
> +  Covers only the given ASID.
> 
> 
> +
> 
> 
> +  The remote fence function acts as a full tlb flush if
> * StartAddr and size
> 
> 
> +  are both 0 * size is equal to 2^XLEN-1
> 
> 
> +
> 
> 
> +  @param[in]  HartMask             Scalar bit-vector
> containing hart ids
> 
> 
> +  @param[in]  HartMaskBase         The starting hartid
> from which the bit-vector
> 
> 
> +                                   must be computed. If
> set to -1, HartMask is
> 
> 
> +                                   ignored and all
> harts are considered.
> 
> 
> +  @param[in]  StartAddr            The first address of
> the affected range.
> 
> 
> +  @param[in]  Size                 How many addresses
> are affected.
> 
> 
> +  @retval EFI_SUCCESS              IPI was sent to all
> the targeted harts.
> 
> 
> +  @retval EFI_LOAD_ERROR           StartAddr or Size is
> not valid.
> 
> 
> +  @retval EFI_INVALID_PARAMETER    Either
> hart_mask_base or any of the hartid
> 
> 
> +                                   from hart_mask is
> not valid i.e. either the
> 
> 
> +                                   hartid is not
> enabled by the platform or is
> 
> 
> +                                   not available to the
> supervisor.
> 
> 
> +**/
> 
> 
> +EFI_STATUS
> 
> 
> +EFIAPI
> 
> 
> +SbiRemoteSfenceVmaAsid (
> 
> 
> +  IN  UINTN                         *HartMask,
> 
> 
> +  IN  UINTN                          HartMaskBase,
> 
> 
> +  IN  UINTN                          StartAddr,
> 
> 
> +  IN  UINTN                          Size,
> 
> 
> +  IN  UINTN                          Asid
> 
> 
> +  );
> 
> 
> +
> 
> 
> +/**
> 
> 
> +  Instructs the remote harts to execute one or more
> SFENCE.GVMA instructions.
> 
> 
> +
> 
> 
> +  The SFENCE.GVMA covers the range of virtual addresses
> between StartAaddr and Size.
> 
> 
> +  Covers only the given VMID.
> 
> 
> +  This function call is only valid for harts
> implementing the hypervisor extension.
> 
> 
> +
> 
> 
> +  The remote fence function acts as a full tlb flush if
> * StartAddr and size
> 
> 
> +  are both 0 * size is equal to 2^XLEN-1
> 
> 
> +
> 
> 
> +  @param[in]  HartMask             Scalar bit-vector
> containing hart ids
> 
> 
> +  @param[in]  HartMaskBase         The starting hartid
> from which the bit-vector
> 
> 
> +                                   must be computed. If
> set to -1, HartMask is
> 
> 
> +                                   ignored and all
> harts are considered.
> 
> 
> +  @param[in]  StartAddr            The first address of
> the affected range.
> 
> 
> +  @param[in]  Size                 How many addresses
> are affected.
> 
> 
> +  @retval EFI_SUCCESS              IPI was sent to all
> the targeted harts.
> 
> 
> +  @retval EFI_LOAD_ERROR           StartAddr or Size is
> not valid.
> 
> 
> +  @retval EFI_UNSUPPORTED          SBI does not
> implement this function or one
> 
> 
> +                                   of the target harts
> does not support the
> 
> 
> +                                   hypervisor
> extension.
> 
> 
> +  @retval EFI_INVALID_PARAMETER    Either
> hart_mask_base or any of the hartid
> 
> 
> +                                   from hart_mask is
> not valid i.e. either the
> 
> 
> +                                   hartid is not
> enabled by the platform or is
> 
> 
> +                                   not available to the
> supervisor.
> 
> 
> +**/
> 
> 
> +EFI_STATUS
> 
> 
> +EFIAPI
> 
> 
> +SbiRemoteHfenceGvmaVmid (
> 
> 
> +  IN  UINTN                         *HartMask,
> 
> 
> +  IN  UINTN                          HartMaskBase,
> 
> 
> +  IN  UINTN                          StartAddr,
> 
> 
> +  IN  UINTN                          Size,
> 
> 
> +  IN  UINTN                          Vmid
> 
> 
> +  );
> 
> 
> +
> 
> 
> +/**
> 
> 
> +  Instructs the remote harts to execute one or more
> SFENCE.GVMA instructions.
> 
> 
> +
> 
> 
> +  The SFENCE.GVMA covers the range of virtual addresses
> between StartAaddr and Size.
> 
> 
> +  This function call is only valid for harts
> implementing the hypervisor extension.
> 
> 
> +
> 
> 
> +  The remote fence function acts as a full tlb flush if
> * StartAddr and size
> 
> 
> +  are both 0 * size is equal to 2^XLEN-1
> 
> 
> +
> 
> 
> +  @param[in]  HartMask             Scalar bit-vector
> containing hart ids
> 
> 
> +  @param[in]  HartMaskBase         The starting hartid
> from which the bit-vector
> 
> 
> +                                   must be computed. If
> set to -1, HartMask is
> 
> 
> +                                   ignored and all
> harts are considered.
> 
> 
> +  @param[in]  StartAddr            The first address of
> the affected range.
> 
> 
> +  @param[in]  Size                 How many addresses
> are affected.
> 
> 
> +  @retval EFI_SUCCESS              IPI was sent to all
> the targeted harts.
> 
> 
> +  @retval EFI_LOAD_ERROR           StartAddr or Size is
> not valid.
> 
> 
> +  @retval EFI_UNSUPPORTED          SBI does not
> implement this function or one
> 
> 
> +                                   of the target harts
> does not support the
> 
> 
> +                                   hypervisor
> extension.
> 
> 
> +  @retval EFI_INVALID_PARAMETER    Either
> hart_mask_base or any of the hartid
> 
> 
> +                                   from hart_mask is
> not valid i.e. either the
> 
> 
> +                                   hartid is not
> enabled by the platform or is
> 
> 
> +                                   not available to the
> supervisor.
> 
> 
> +**/
> 
> 
> +EFI_STATUS
> 
> 
> +EFIAPI
> 
> 
> +SbiRemoteHfenceGvma (
> 
> 
> +  IN  UINTN                         *HartMask,
> 
> 
> +  IN  UINTN                          HartMaskBase,
> 
> 
> +  IN  UINTN                          StartAddr,
> 
> 
> +  IN  UINTN                          Size
> 
> 
> +  );
> 
> 
> +
> 
> 
> +/**
> 
> 
> +  Instructs the remote harts to execute one or more
> SFENCE.VVMA instructions.
> 
> 
> +
> 
> 
> +  The SFENCE.GVMA covers the range of virtual addresses
> between StartAaddr and Size.
> 
> 
> +  Covers only the given ASID.
> 
> 
> +  This function call is only valid for harts
> implementing the hypervisor extension.
> 
> 
> +
> 
> 
> +  The remote fence function acts as a full tlb flush if
> * StartAddr and size
> 
> 
> +  are both 0 * size is equal to 2^XLEN-1
> 
> 
> +
> 
> 
> +  @param[in]  HartMask             Scalar bit-vector
> containing hart ids
> 
> 
> +  @param[in]  HartMaskBase         The starting hartid
> from which the bit-vector
> 
> 
> +                                   must be computed. If
> set to -1, HartMask is
> 
> 
> +                                   ignored and all
> harts are considered.
> 
> 
> +  @param[in]  StartAddr            The first address of
> the affected range.
> 
> 
> +  @param[in]  Size                 How many addresses
> are affected.
> 
> 
> +  @retval EFI_SUCCESS              IPI was sent to all
> the targeted harts.
> 
> 
> +  @retval EFI_LOAD_ERROR           StartAddr or Size is
> not valid.
> 
> 
> +  @retval EFI_UNSUPPORTED          SBI does not
> implement this function or one
> 
> 
> +                                   of the target harts
> does not support the
> 
> 
> +                                   hypervisor
> extension.
> 
> 
> +  @retval EFI_INVALID_PARAMETER    Either
> hart_mask_base or any of the hartid
> 
> 
> +                                   from hart_mask is
> not valid i.e. either the
> 
> 
> +                                   hartid is not
> enabled by the platform or is
> 
> 
> +                                   not available to the
> supervisor.
> 
> 
> +**/
> 
> 
> +EFI_STATUS
> 
> 
> +EFIAPI
> 
> 
> +SbiRemoteHfenceVvmaAsid (
> 
> 
> +  IN  UINTN                         *HartMask,
> 
> 
> +  IN  UINTN                          HartMaskBase,
> 
> 
> +  IN  UINTN                          StartAddr,
> 
> 
> +  IN  UINTN                          Size,
> 
> 
> +  IN  UINTN                          Asid
> 
> 
> +  );
> 
> 
> +
> 
> 
> +/**
> 
> 
> +  Instructs the remote harts to execute one or more
> SFENCE.VVMA instructions.
> 
> 
> +
> 
> 
> +  The SFENCE.GVMA covers the range of virtual addresses
> between StartAaddr and Size.
> 
> 
> +  This function call is only valid for harts
> implementing the hypervisor extension.
> 
> 
> +
> 
> 
> +  The remote fence function acts as a full tlb flush if
> * StartAddr and size
> 
> 
> +  are both 0 * size is equal to 2^XLEN-1
> 
> 
> +
> 
> 
> +  @param[in]  HartMask             Scalar bit-vector
> containing hart ids
> 
> 
> +  @param[in]  HartMaskBase         The starting hartid
> from which the bit-vector
> 
> 
> +                                   must be computed. If
> set to -1, HartMask is
> 
> 
> +                                   ignored and all
> harts are considered.
> 
> 
> +  @param[in]  StartAddr            The first address of
> the affected range.
> 
> 
> +  @param[in]  Size                 How many addresses
> are affected.
> 
> 
> +  @retval EFI_SUCCESS              IPI was sent to all
> the targeted harts.
> 
> 
> +  @retval EFI_LOAD_ERROR           StartAddr or Size is
> not valid.
> 
> 
> +  @retval EFI_UNSUPPORTED          SBI does not
> implement this function or one
> 
> 
> +                                   of the target harts
> does not support the
> 
> 
> +                                   hypervisor
> extension.
> 
> 
> +  @retval EFI_INVALID_PARAMETER    Either
> hart_mask_base or any of the hartid
> 
> 
> +                                   from hart_mask is
> not valid i.e. either the
> 
> 
> +                                   hartid is not
> enabled by the platform or is
> 
> 
> +                                   not available to the
> supervisor.
> 
> 
> +**/
> 
> 
> +EFI_STATUS
> 
> 
> +EFIAPI
> 
> 
> +SbiRemoteHfenceVvma (
> 
> 
> +  IN  UINTN                         *HartMask,
> 
> 
> +  IN  UINTN                          HartMaskBase,
> 
> 
> +  IN  UINTN                          StartAddr,
> 
> 
> +  IN  UINTN                          Size
> 
> 
> +  );
> 
> 
> +
> 
> 
> +///
> 
> 
> +/// Vendor Specific extension space: Extension Ids
> 0x09000000 through 0x09FFFFFF
> 
> 
> +///
> 
> 
> +
> 
> 
> +/**
> 
> 
> +  Call a function in a vendor defined SBI extension
> 
> 
> +
> 
> 
> +  ASSERT() if the ExtensionId is not in the designated
> SBI Vendor Extension
> 
> 
> +  Space.
> 
> 
> +
> 
> 
> +  @param[in]  ExtensionId          The SBI vendor
> extension ID.
> 
> 
> +  @param[in]  FunctionId           The function ID to
> call in this extension.
> 
> 
> +  @param[in]  NumArgs              How many arguments
> are passed.
> 
> 
> +  @param[in]  ...                  Actual Arguments to
> the function.
> 
> 
> +  @retval EFI_SUCCESS if the SBI function was called
> and it was successful
> 
> 
> +  @retval EFI_INVALID_PARAMETER if NumArgs exceeds 6
> 
> 
> +  @retval others if the called SBI function returns an
> error
> 
> 
> +**/
> 
> 
> +EFI_STATUS
> 
> 
> +EFIAPI
> 
> 
> +SbiVendorCall (
> 
> 
> +  IN  UINTN                          ExtensionId,
> 
> 
> +  IN  UINTN                          FunctionId,
> 
> 
> +  IN  UINTN                          NumArgs,
> 
> 
> +  ...
> 
> 
> +  );
> 
> 
> +
> 
> 
> +///
> 
> 
> +/// Firmware SBI Extension
> 
> 
> +///
> 
> 
> +/// This SBI Extension is defined and used by EDK2 only
> in order to be able to
> 
> 
> +/// run PI and DXE phase in S-Mode.
> 
> 
> +///
> 
> 
> +
> 
> 
> +/**
> 
> 
> +  Get scratch space of the current hart.
> 
> 
> +
> 
> 
> +  Please consider using the wrapper
> SbiGetFirmwareContext if you only need to
> 
> 
> +  access the firmware context.
> 
> 
> +
> 
> 
> +  @param[out] ScratchSpace         The scratch space
> pointer.
> 
> 
> +  @retval EFI_SUCCESS              The operation
> succeeds.
> 
> 
> +**/
> 
> 
> +EFI_STATUS
> 
> 
> +EFIAPI
> 
> 
> +SbiGetMscratch (
> 
> 
> +  OUT SBI_SCRATCH                    **ScratchSpace
> 
> 
> +  );
> 
> 
> +
> 
> 
> +/**
> 
> 
> +  Get scratch space of the given hart id.
> 
> 
> +
> 
> 
> +  @param[in]  HartId               The hart id.
> 
> 
> +  @param[out] ScratchSpace         The scratch space
> pointer.
> 
> 
> +  @retval EFI_SUCCESS              The operation
> succeeds.
> 
> 
> +**/
> 
> 
> +EFI_STATUS
> 
> 
> +EFIAPI
> 
> 
> +SbiGetMscratchHartid (
> 
> 
> +  IN  UINTN                            HartId,
> 
> 
> +  OUT SBI_SCRATCH                    **ScratchSpace
> 
> 
> +  );
> 
> 
> +
> 
> 
> +/**
> 
> 
> +  Get firmware context of the calling hart.
> 
> 
> +
> 
> 
> +  @param[out] FirmwareContext      The firmware context
> pointer.
> 
> 
> +  @retval EFI_SUCCESS              The operation
> succeeds.
> 
> 
> +**/
> 
> 
> +EFI_STATUS
> 
> 
> +EFIAPI
> 
> 
> +SbiGetFirmwareContext (
> 
> 
> +  OUT EFI_RISCV_OPENSBI_FIRMWARE_CONTEXT
> **FirmwareContext
> 
> 
> +  );
> 
> 
> +
> 
> 
> +/**
> 
> 
> +  Set firmware context of the calling hart.
> 
> 
> +
> 
> 
> +  @param[in] FirmwareContext       The firmware context
> pointer.
> 
> 
> +  @retval EFI_SUCCESS              The operation
> succeeds.
> 
> 
> +**/
> 
> 
> +EFI_STATUS
> 
> 
> +EFIAPI
> 
> 
> +SbiSetFirmwareContext (
> 
> 
> +  IN EFI_RISCV_OPENSBI_FIRMWARE_CONTEXT
> *FirmwareContext
> 
> 
> +  );
> 
> 
> +
> 
> 
> +#endif
> 
> 
> diff --git a/Silicon/RISC-
> V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.c
> b/Silicon/RISC-
> V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.c
> new file mode 100644
> index 000000000000..0df505d2675b
> --- /dev/null
> +++ b/Silicon/RISC-
> V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.c
> @@ -0,0 +1,897 @@
> +/** @file
> 
> 
> +  Instance of the SBI ecall library.
> 
> 
> +
> 
> 
> +  It allows calling an SBI function via an ecall from
> S-Mode.
> 
> 
> +
> 
> 
> +  The legacy extensions are not included because they
> are not necessary.
> 
> 
> +  They would be:
> 
> 
> +  - SbiLegacySetTimer            -> Use SbiSetTimer
> 
> 
> +  - SbiLegacyConsolePutChar      -> No replacement -
> Use regular UEFI functions
> 
> 
> +  - SbiLegacyConsoleGetChar      -> No replacement -
> Use regular UEFI functions
> 
> 
> +  - SbiLegacyClearIpi            -> Write 0 to SSIP
> 
> 
> +  - SbiLegacySendIpi             -> Use SbiSendIpi
> 
> 
> +  - SbiLegacyRemoteFenceI        -> Use SbiRemoteFenceI
> 
> 
> +  - SbiLegacyRemoteSfenceVma     -> Use
> SbiRemoteSfenceVma
> 
> 
> +  - SbiLegacyRemoteSfenceVmaAsid -> Use
> SbiRemoteSfenceVmaAsid
> 
> 
> +  - SbiLegacyShutdown            -> Wait for new System
> Reset extension
> 
> 
> +
> 
> 
> +  Copyright (c) 2020, Hewlett Packard Development LP.
> All rights reserved.<BR>
> 
> 
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> 
> +
> 
> 
> +  @par Revision Reference:
> 
> 
> +    - OpenSBI Version 0.6
> 
> 
> +**/
> 
> 
> +
> 
> 
> +#include <IndustryStandard/RiscVOpensbi.h>
> 
> 
> +#include <Library/BaseMemoryLib.h>
> 
> 
> +#include <Library/DebugLib.h>
> 
> 
> +#include <Library/RiscVEdk2SbiLib.h>
> 
> 
> +#include <sbi/riscv_asm.h>
> 
> 
> +#include <sbi/sbi_hart.h>
> 
> 
> +#include <sbi/sbi_types.h>
> 
> 
> +#include <sbi/sbi_init.h>
> 
> 
> +
> 
> 
> +
> 
> 
> +//
> 
> 
> +// Maximum arguments for SBI ecall
> 
> 
> +// It's possible to pass more but no SBI call uses more
> as of SBI 0.2.
> 
> 
> +// The additional arguments would have to be passed on
> the stack instead of as
> 
> 
> +// registers, like it's done now.
> 
> 
> +//
> 
> 
> +#define SBI_CALL_MAX_ARGS 6
> 
> 
> +
> 
> 
> +/**
> 
> 
> +  Call SBI call using ecall instruction.
> 
> 
> +
> 
> 
> +  Asserts when NumArgs exceeds SBI_CALL_MAX_ARGS.
> 
> 
> +
> 
> 
> +  @param[in] ExtId    SBI extension ID.
> 
> 
> +  @param[in] FuncId   SBI function ID.
> 
> 
> +  @param[in] NumArgs  Number of arguments to pass to
> the ecall.
> 
> 
> +  @param[in] ...      Argument list for the ecall.
> 
> 
> +
> 
> 
> +  @retval  Returns SbiRet structure with value and
> error code.
> 
> 
> +
> 
> 
> +**/
> 
> 
> +STATIC
> 
> 
> +SbiRet
> 
> 
> +EFIAPI
> 
> 
> +SbiCall(
> 
> 
> +  IN  UINTN ExtId,
> 
> 
> +  IN  UINTN FuncId,
> 
> 
> +  IN  UINTN NumArgs,
> 
> 
> +  ...
> 
> 
> +  )
> 
> 
> +{
> 
> 
> +    UINTN I;
> 
> 
> +    SbiRet Ret;
> 
> 
> +    UINTN Args[SBI_CALL_MAX_ARGS];
> 
> 
> +    VA_LIST ArgList;
> 
> 
> +    VA_START (ArgList, NumArgs);
> 
> 
> +
> 
> 
> +    ASSERT (NumArgs <= SBI_CALL_MAX_ARGS);
> 
> 
> +
> 
> 
> +    for (I = 0; I < SBI_CALL_MAX_ARGS; I++) {
> 
> 
> +      if (I < NumArgs) {
> 
> 
> +        Args[I] = VA_ARG (ArgList, UINTN);
> 
> 
> +      } else {
> 
> 
> +        // Default to 0 for all arguments that are not
> given
> 
> 
> +        Args[I] = 0;
> 
> 
> +      }
> 
> 
> +    }
> 
> 
> +
> 
> 
> +    VA_END(ArgList);
> 
> 
> +
> 
> 
> +    register UINTN a0 asm ("a0") = Args[0];
> 
> 
> +    register UINTN a1 asm ("a1") = Args[1];
> 
> 
> +    register UINTN a2 asm ("a2") = Args[2];
> 
> 
> +    register UINTN a3 asm ("a3") = Args[3];
> 
> 
> +    register UINTN a4 asm ("a4") = Args[4];
> 
> 
> +    register UINTN a5 asm ("a5") = Args[5];
> 
> 
> +    register UINTN a6 asm ("a6") = (UINTN)(FuncId);
> 
> 
> +    register UINTN a7 asm ("a7") = (UINTN)(ExtId);
> 
> 
> +    asm volatile ("ecall" \
> 
> 
> +         : "+r" (a0), "+r" (a1) \
> 
> 
> +         : "r" (a2), "r" (a3), "r" (a4), "r" (a5), "r"
> (a6), "r" (a7) \
> 
> 
> +         : "memory"); \
> 
> 
> +    Ret.Error = a0;
> 
> 
> +    Ret.Value = a1;
> 
> 
> +    return Ret;
> 
> 
> +}
> 
> 
> +
> 
> 
> +/**
> 
> 
> +  Translate SBI error code to EFI status.
> 
> 
> +
> 
> 
> +  @param[in] SbiError   SBI error code
> 
> 
> +  @retval EFI_STATUS
> 
> 
> +**/
> 
> 
> +
> 
> 
> +STATIC
> 
> 
> +EFI_STATUS
> 
> 
> +EFIAPI
> 
> 
> +TranslateError(
> 
> 
> +  IN  UINTN SbiError
> 
> 
> +  )
> 
> 
> +{
> 
> 
> +  switch (SbiError) {
> 
> 
> +    case SBI_SUCCESS:
> 
> 
> +      return EFI_SUCCESS;
> 
> 
> +    case SBI_ERR_FAILED:
> 
> 
> +      return EFI_DEVICE_ERROR;
> 
> 
> +      break;
> 
> 
> +    case SBI_ERR_NOT_SUPPORTED:
> 
> 
> +      return EFI_UNSUPPORTED;
> 
> 
> +      break;
> 
> 
> +    case SBI_ERR_INVALID_PARAM:
> 
> 
> +      return EFI_INVALID_PARAMETER;
> 
> 
> +      break;
> 
> 
> +    case SBI_ERR_DENIED:
> 
> 
> +      return EFI_ACCESS_DENIED;
> 
> 
> +      break;
> 
> 
> +    case SBI_ERR_INVALID_ADDRESS:
> 
> 
> +      return EFI_LOAD_ERROR;
> 
> 
> +      break;
> 
> 
> +    case SBI_ERR_ALREADY_AVAILABLE:
> 
> 
> +      return EFI_ALREADY_STARTED;
> 
> 
> +      break;
> 
> 
> +    default:
> 
> 
> +      //
> 
> 
> +      // Reaches here only if SBI has defined a new
> error type
> 
> 
> +      //
> 
> 
> +      ASSERT (FALSE);
> 
> 
> +      return EFI_UNSUPPORTED;
> 
> 
> +      break;
> 
> 
> +  }
> 
> 
> +}
> 
> 
> +
> 
> 
> +//
> 
> 
> +// OpenSBI library interface function for the base
> extension
> 
> 
> +//
> 
> 
> +
> 
> 
> +/**
> 
> 
> +  Get the implemented SBI specification version
> 
> 
> +
> 
> 
> +  The minor number of the SBI specification is encoded
> in the low 24 bits,
> 
> 
> +  with the major number encoded in the next 7 bits.
> Bit 32 must be 0 and is
> 
> 
> +  reserved for future expansion.
> 
> 
> +
> 
> 
> +  @param[out] SpecVersion          The Version of the
> SBI specification.
> 
> 
> +**/
> 
> 
> +VOID
> 
> 
> +EFIAPI
> 
> 
> +SbiGetSpecVersion (
> 
> 
> +  OUT UINTN                       *SpecVersion
> 
> 
> +  )
> 
> 
> +{
> 
> 
> +  SbiRet Ret = SbiCall (SBI_EXT_BASE,
> SBI_EXT_BASE_GET_SPEC_VERSION, 0);
> 
> 
> +
> 
> 
> +  if (!Ret.Error) {
> 
> 
> +    *SpecVersion = (UINTN)Ret.Value;
> 
> 
> +  }
> 
> 
> +}
> 
> 
> +
> 
> 
> +/**
> 
> 
> +  Get the SBI implementation ID
> 
> 
> +
> 
> 
> +  This ID is used to idenetify a specific SBI
> implementation in order to work
> 
> 
> +  around any quirks it might have.
> 
> 
> +
> 
> 
> +  @param[out] ImplId               The ID of the SBI
> implementation.
> 
> 
> +**/
> 
> 
> +VOID
> 
> 
> +EFIAPI
> 
> 
> +SbiGetImplId (
> 
> 
> +  OUT UINTN                       *ImplId
> 
> 
> +  )
> 
> 
> +{
> 
> 
> +  SbiRet Ret = SbiCall (SBI_EXT_BASE,
> SBI_EXT_BASE_GET_IMP_ID, 0);
> 
> 
> +  *ImplId = (UINTN)Ret.Value;
> 
> 
> +}
> 
> 
> +
> 
> 
> +/**
> 
> 
> +  Get the SBI implementation version
> 
> 
> +
> 
> 
> +  The version of this SBI implementation.
> 
> 
> +  The encoding of this number is determined by the
> specific SBI implementation.
> 
> 
> +
> 
> 
> +  @param[out] ImplVersion          The version of the
> SBI implementation.
> 
> 
> +**/
> 
> 
> +VOID
> 
> 
> +EFIAPI
> 
> 
> +SbiGetImplVersion (
> 
> 
> +  OUT UINTN                       *ImplVersion
> 
> 
> +  )
> 
> 
> +{
> 
> 
> +  SbiRet Ret = SbiCall (SBI_EXT_BASE,
> SBI_EXT_BASE_GET_IMP_VERSION, 0);
> 
> 
> +  *ImplVersion = (UINTN)Ret.Value;
> 
> 
> +}
> 
> 
> +
> 
> 
> +/**
> 
> 
> +  Probe whether an SBI extension is available
> 
> 
> +
> 
> 
> +  ProbeResult is set to 0 if the extension is not
> available or to an extension
> 
> 
> +  specified value if it is available.
> 
> 
> +
> 
> 
> +  @param[in]  ExtensionId          The extension ID.
> 
> 
> +  @param[out] ProbeResult          The return value of
> the probe.
> 
> 
> +**/
> 
> 
> +VOID
> 
> 
> +EFIAPI
> 
> 
> +SbiProbeExtension (
> 
> 
> +  IN  INTN                         ExtensionId,
> 
> 
> +  OUT INTN                        *ProbeResult
> 
> 
> +  )
> 
> 
> +{
> 
> 
> +  SbiRet Ret = SbiCall (SBI_EXT_BASE,
> SBI_EXT_BASE_PROBE_EXT, 0);
> 
> 
> +  *ProbeResult = (UINTN)Ret.Value;
> 
> 
> +}
> 
> 
> +
> 
> 
> +/**
> 
> 
> +  Get the CPU's vendor ID
> 
> 
> +
> 
> 
> +  Reads the mvendorid CSR.
> 
> 
> +
> 
> 
> +  @param[out] MachineVendorId      The CPU's vendor ID.
> 
> 
> +**/
> 
> 
> +VOID
> 
> 
> +EFIAPI
> 
> 
> +SbiGetMachineVendorId (
> 
> 
> +  OUT UINTN                       *MachineVendorId
> 
> 
> +  )
> 
> 
> +{
> 
> 
> +  SbiRet Ret = SbiCall (SBI_EXT_BASE,
> SBI_EXT_BASE_GET_MVENDORID, 0);
> 
> 
> +  *MachineVendorId = (UINTN)Ret.Value;
> 
> 
> +}
> 
> 
> +
> 
> 
> +/**
> 
> 
> +  Get the CPU's architecture ID
> 
> 
> +
> 
> 
> +  Reads the marchid CSR.
> 
> 
> +
> 
> 
> +  @param[out] MachineArchId        The CPU's
> architecture ID.
> 
> 
> +**/
> 
> 
> +VOID
> 
> 
> +EFIAPI
> 
> 
> +SbiGetMachineArchId (
> 
> 
> +  OUT UINTN                       *MachineArchId
> 
> 
> +  )
> 
> 
> +{
> 
> 
> +  SbiRet Ret = SbiCall (SBI_EXT_BASE,
> SBI_EXT_BASE_GET_MARCHID, 0);
> 
> 
> +  *MachineArchId = (UINTN)Ret.Value;
> 
> 
> +}
> 
> 
> +
> 
> 
> +/**
> 
> 
> +  Get the CPU's architecture ID
> 
> 
> +
> 
> 
> +  Reads the marchid CSR.
> 
> 
> +
> 
> 
> +  @param[out] MachineImplId        The CPU's
> implementation ID.
> 
> 
> +**/
> 
> 
> +VOID
> 
> 
> +EFIAPI
> 
> 
> +SbiGetMachineImplId (
> 
> 
> +  OUT UINTN                       *MachineImplId
> 
> 
> +  )
> 
> 
> +{
> 
> 
> +  SbiRet Ret = SbiCall (SBI_EXT_BASE,
> SBI_EXT_BASE_GET_MIMPID, 0);
> 
> 
> +  *MachineImplId = (UINTN)Ret.Value;
> 
> 
> +}
> 
> 
> +
> 
> 
> +//
> 
> 
> +// SBI interface function for the hart state management
> extension
> 
> 
> +//
> 
> 
> +
> 
> 
> +/**
> 
> 
> +  Politely ask the SBI to start a given hart.
> 
> 
> +
> 
> 
> +  This call may return before the hart has actually
> started executing, if the
> 
> 
> +  SBI implementation can guarantee that the hart is
> actually going to start.
> 
> 
> +
> 
> 
> +  Before the hart jumps to StartAddr, the hart MUST
> configure PMP if present
> 
> 
> +  and switch to S-mode.
> 
> 
> +
> 
> 
> +  @param[in]  HartId               The id of the hart
> to start.
> 
> 
> +  @param[in]  StartAddr            The physical
> address, where the hart starts
> 
> 
> +                                   executing from.
> 
> 
> +  @param[in]  Priv                 An XLEN-bit value,
> which will be in register
> 
> 
> +                                   a1 when the hart
> starts.
> 
> 
> +  @retval EFI_SUCCESS              Hart was stopped and
> will start executing from StartAddr.
> 
> 
> +  @retval EFI_LOAD_ERROR           StartAddr is not
> valid, possibly due to following reasons:
> 
> 
> +                                     - It is not a
> valid physical address.
> 
> 
> +                                     - The address is
> prohibited by PMP to run in
> 
> 
> +                                       supervisor mode.
> 
> 
> +  @retval EFI_INVALID_PARAMETER    HartId is not a
> valid hart id
> 
> 
> +  @retval EFI_ALREADY_STARTED      The hart is already
> running.
> 
> 
> +  @retval other                    The start request
> failed for unknown reasons.
> 
> 
> +**/
> 
> 
> +EFI_STATUS
> 
> 
> +EFIAPI
> 
> 
> +SbiHartStart (
> 
> 
> +  IN  UINTN                          HartId,
> 
> 
> +  IN  UINTN                          StartAddr,
> 
> 
> +  IN  UINTN                          Priv
> 
> 
> +  )
> 
> 
> +{
> 
> 
> +  SbiRet Ret = SbiCall (
> 
> 
> +                 SBI_EXT_HSM,
> 
> 
> +                 SBI_EXT_HSM_HART_START,
> 
> 
> +                 3,
> 
> 
> +                 HartId,
> 
> 
> +                 StartAddr,
> 
> 
> +                 Priv
> 
> 
> +                 );
> 
> 
> +  return TranslateError (Ret.Error);
> 
> 
> +}
> 
> 
> +
> 
> 
> +/**
> 
> 
> +  Return execution of the calling hart to SBI.
> 
> 
> +
> 
> 
> +  MUST be called in S-Mode with user interrupts
> disabled.
> 
> 
> +  This call is not expected to return, unless a failure
> occurs.
> 
> 
> +
> 
> 
> +  @retval     EFI_SUCCESS          Never occurs. When
> successful, the call does not return.
> 
> 
> +  @retval     other                Failed to stop hard
> for an unknown reason.
> 
> 
> +**/
> 
> 
> +EFI_STATUS
> 
> 
> +EFIAPI
> 
> 
> +SbiHartStop (
> 
> 
> +  )
> 
> 
> +{
> 
> 
> +  SbiRet Ret = SbiCall (SBI_EXT_HSM,
> SBI_EXT_HSM_HART_STOP, 0);
> 
> 
> +  return TranslateError (Ret.Error);
> 
> 
> +}
> 
> 
> +
> 
> 
> +/**
> 
> 
> +  Get the current status of a hart.
> 
> 
> +
> 
> 
> +  Since harts can transition between states at any
> time, the status retrieved
> 
> 
> +  by this function may already be out of date, once it
> returns.
> 
> 
> +
> 
> 
> +  Possible values for HartStatus are:
> 
> 
> +  0: STARTED
> 
> 
> +  1: STOPPED
> 
> 
> +  2: START_REQUEST_PENDING
> 
> 
> +  3: STOP_REQUEST_PENDING
> 
> 
> +
> 
> 
> +  @param[out] HartStatus           The pointer in which
> the hart's status is
> 
> 
> +                                   stored.
> 
> 
> +  @retval EFI_SUCCESS              The operation
> succeeds.
> 
> 
> +  @retval EFI_INVALID_PARAMETER    A parameter is
> invalid.
> 
> 
> +**/
> 
> 
> +EFI_STATUS
> 
> 
> +EFIAPI
> 
> 
> +SbiHartGetStatus (
> 
> 
> +  IN  UINTN                          HartId,
> 
> 
> +  OUT UINTN                         *HartStatus
> 
> 
> +  )
> 
> 
> +{
> 
> 
> +  SbiRet Ret = SbiCall (SBI_EXT_HSM,
> SBI_EXT_HSM_HART_GET_STATUS, 1, HartId);
> 
> 
> +
> 
> 
> +  if (!Ret.Error) {
> 
> 
> +    *HartStatus = (UINTN)Ret.Value;
> 
> 
> +  }
> 
> 
> +
> 
> 
> +  return TranslateError (Ret.Error);
> 
> 
> +}
> 
> 
> +
> 
> 
> +/**
> 
> 
> +  Clear pending timer interrupt bit and set timer for
> next event after Time.
> 
> 
> +
> 
> 
> +  To clear the timer without scheduling a timer event,
> set Time to a
> 
> 
> +  practically infinite value or mask the timer
> interrupt by clearing sie.STIE.
> 
> 
> +
> 
> 
> +  @param[in]  Time                 The time offset to
> the next scheduled timer interrupt.
> 
> 
> +**/
> 
> 
> +VOID
> 
> 
> +EFIAPI
> 
> 
> +SbiSetTimer (
> 
> 
> +  IN  UINT64                         Time
> 
> 
> +  )
> 
> 
> +{
> 
> 
> +  SbiCall (SBI_EXT_TIME, SBI_EXT_TIME_SET_TIMER, 1,
> Time);
> 
> 
> +}
> 
> 
> +
> 
> 
> +EFI_STATUS
> 
> 
> +EFIAPI
> 
> 
> +SbiSendIpi (
> 
> 
> +  IN  UINTN                         *HartMask,
> 
> 
> +  IN  UINTN                          HartMaskBase
> 
> 
> +  )
> 
> 
> +{
> 
> 
> +  SbiRet Ret = SbiCall (
> 
> 
> +                 SBI_EXT_IPI,
> 
> 
> +                 SBI_EXT_IPI_SEND_IPI,
> 
> 
> +                 2,
> 
> 
> +                 (UINTN)HartMask,
> 
> 
> +                 HartMaskBase
> 
> 
> +                 );
> 
> 
> +  return TranslateError (Ret.Error);
> 
> 
> +}
> 
> 
> +
> 
> 
> +/**
> 
> 
> +  Instructs remote harts to execute a FENCE.I
> instruction.
> 
> 
> +
> 
> 
> +  @param[in]  HartMask             Scalar bit-vector
> containing hart ids
> 
> 
> +  @param[in]  HartMaskBase         The starting hartid
> from which the bit-vector
> 
> 
> +                                   must be computed. If
> set to -1, HartMask is
> 
> 
> +                                   ignored and all
> harts are considered.
> 
> 
> +  @retval EFI_SUCCESS              IPI was sent to all
> the targeted harts.
> 
> 
> +  @retval EFI_INVALID_PARAMETER    Either
> hart_mask_base or any of the hartid
> 
> 
> +                                   from hart_mask is
> not valid i.e. either the
> 
> 
> +                                   hartid is not
> enabled by the platform or is
> 
> 
> +                                   not available to the
> supervisor.
> 
> 
> +**/
> 
> 
> +EFI_STATUS
> 
> 
> +EFIAPI
> 
> 
> +SbiRemoteFenceI (
> 
> 
> +  IN  UINTN                         *HartMask,
> 
> 
> +  IN  UINTN                          HartMaskBase
> 
> 
> +  )
> 
> 
> +{
> 
> 
> +  SbiRet Ret = SbiCall (
> 
> 
> +                 SBI_EXT_RFENCE,
> 
> 
> +                 SBI_EXT_RFENCE_REMOTE_FENCE_I,
> 
> 
> +                 2,
> 
> 
> +                 (UINTN)HartMask,
> 
> 
> +                 HartMaskBase
> 
> 
> +                 );
> 
> 
> +  return TranslateError (Ret.Error);
> 
> 
> +}
> 
> 
> +
> 
> 
> +/**
> 
> 
> +  Instructs the remote harts to execute one or more
> SFENCE.VMA instructions.
> 
> 
> +
> 
> 
> +  The SFENCE.VMA covers the range of virtual addresses
> between StartAaddr and Size.
> 
> 
> +
> 
> 
> +  The remote fence function acts as a full tlb flush if
> * StartAddr and size
> 
> 
> +  are both 0 * size is equal to 2^XLEN-1
> 
> 
> +
> 
> 
> +  @param[in]  HartMask             Scalar bit-vector
> containing hart ids
> 
> 
> +  @param[in]  HartMaskBase         The starting hartid
> from which the bit-vector
> 
> 
> +                                   must be computed. If
> set to -1, HartMask is
> 
> 
> +                                   ignored and all
> harts are considered.
> 
> 
> +  @param[in]  StartAddr            The first address of
> the affected range.
> 
> 
> +  @param[in]  Size                 How many addresses
> are affected.
> 
> 
> +  @retval EFI_SUCCESS              IPI was sent to all
> the targeted harts.
> 
> 
> +  @retval EFI_LOAD_ERROR           StartAddr or Size is
> not valid.
> 
> 
> +  @retval EFI_INVALID_PARAMETER    Either
> hart_mask_base or any of the hartid
> 
> 
> +                                   from hart_mask is
> not valid i.e. either the
> 
> 
> +                                   hartid is not
> enabled by the platform or is
> 
> 
> +                                   not available to the
> supervisor.
> 
> 
> +**/
> 
> 
> +EFI_STATUS
> 
> 
> +EFIAPI
> 
> 
> +SbiRemoteSfenceVma (
> 
> 
> +  IN  UINTN                         *HartMask,
> 
> 
> +  IN  UINTN                          HartMaskBase,
> 
> 
> +  IN  UINTN                          StartAddr,
> 
> 
> +  IN  UINTN                          Size
> 
> 
> +  )
> 
> 
> +{
> 
> 
> +  SbiRet Ret = SbiCall (
> 
> 
> +                 SBI_EXT_RFENCE,
> 
> 
> +                 SBI_EXT_RFENCE_REMOTE_SFENCE_VMA,
> 
> 
> +                 4,
> 
> 
> +                 (UINTN)HartMask,
> 
> 
> +                 HartMaskBase,
> 
> 
> +                 StartAddr,
> 
> 
> +                 Size
> 
> 
> +                 );
> 
> 
> +  return TranslateError (Ret.Error);
> 
> 
> +}
> 
> 
> +
> 
> 
> +/**
> 
> 
> +  Instructs the remote harts to execute one or more
> SFENCE.VMA instructions.
> 
> 
> +
> 
> 
> +  The SFENCE.VMA covers the range of virtual addresses
> between StartAaddr and Size.
> 
> 
> +  Covers only the given ASID.
> 
> 
> +
> 
> 
> +  The remote fence function acts as a full tlb flush if
> * StartAddr and size
> 
> 
> +  are both 0 * size is equal to 2^XLEN-1
> 
> 
> +
> 
> 
> +  @param[in]  HartMask             Scalar bit-vector
> containing hart ids
> 
> 
> +  @param[in]  HartMaskBase         The starting hartid
> from which the bit-vector
> 
> 
> +                                   must be computed. If
> set to -1, HartMask is
> 
> 
> +                                   ignored and all
> harts are considered.
> 
> 
> +  @param[in]  StartAddr            The first address of
> the affected range.
> 
> 
> +  @param[in]  Size                 How many addresses
> are affected.
> 
> 
> +  @retval EFI_SUCCESS              IPI was sent to all
> the targeted harts.
> 
> 
> +  @retval EFI_LOAD_ERROR           StartAddr or Size is
> not valid.
> 
> 
> +  @retval EFI_INVALID_PARAMETER    Either
> hart_mask_base or any of the hartid
> 
> 
> +                                   from hart_mask is
> not valid i.e. either the
> 
> 
> +                                   hartid is not
> enabled by the platform or is
> 
> 
> +                                   not available to the
> supervisor.
> 
> 
> +**/
> 
> 
> +EFI_STATUS
> 
> 
> +EFIAPI
> 
> 
> +SbiRemoteSfenceVmaAsid (
> 
> 
> +  IN  UINTN                         *HartMask,
> 
> 
> +  IN  UINTN                          HartMaskBase,
> 
> 
> +  IN  UINTN                          StartAddr,
> 
> 
> +  IN  UINTN                          Size,
> 
> 
> +  IN  UINTN                          Asid
> 
> 
> +  )
> 
> 
> +{
> 
> 
> +  SbiRet Ret = SbiCall (
> 
> 
> +                 SBI_EXT_RFENCE,
> 
> 
> +                 SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID,
> 
> 
> +                 5,
> 
> 
> +                 (UINTN)HartMask,
> 
> 
> +                 HartMaskBase,
> 
> 
> +                 StartAddr,
> 
> 
> +                 Size,
> 
> 
> +                 Asid
> 
> 
> +                 );
> 
> 
> +  return TranslateError (Ret.Error);
> 
> 
> +}
> 
> 
> +
> 
> 
> +/**
> 
> 
> +  Instructs the remote harts to execute one or more
> SFENCE.GVMA instructions.
> 
> 
> +
> 
> 
> +  The SFENCE.GVMA covers the range of virtual addresses
> between StartAaddr and Size.
> 
> 
> +  Covers only the given VMID.
> 
> 
> +  This function call is only valid for harts
> implementing the hypervisor extension.
> 
> 
> +
> 
> 
> +  The remote fence function acts as a full tlb flush if
> * StartAddr and size
> 
> 
> +  are both 0 * size is equal to 2^XLEN-1
> 
> 
> +
> 
> 
> +  @param[in]  HartMask             Scalar bit-vector
> containing hart ids
> 
> 
> +  @param[in]  HartMaskBase         The starting hartid
> from which the bit-vector
> 
> 
> +                                   must be computed. If
> set to -1, HartMask is
> 
> 
> +                                   ignored and all
> harts are considered.
> 
> 
> +  @param[in]  StartAddr            The first address of
> the affected range.
> 
> 
> +  @param[in]  Size                 How many addresses
> are affected.
> 
> 
> +  @retval EFI_SUCCESS              IPI was sent to all
> the targeted harts.
> 
> 
> +  @retval EFI_LOAD_ERROR           StartAddr or Size is
> not valid.
> 
> 
> +  @retval EFI_UNSUPPORTED          SBI does not
> implement this function or one
> 
> 
> +                                   of the target harts
> does not support the
> 
> 
> +                                   hypervisor
> extension.
> 
> 
> +  @retval EFI_INVALID_PARAMETER    Either
> hart_mask_base or any of the hartid
> 
> 
> +                                   from hart_mask is
> not valid i.e. either the
> 
> 
> +                                   hartid is not
> enabled by the platform or is
> 
> 
> +                                   not available to the
> supervisor.
> 
> 
> +**/
> 
> 
> +EFI_STATUS
> 
> 
> +EFIAPI
> 
> 
> +SbiRemoteHFenceGvmaVmid (
> 
> 
> +  IN  UINTN                         *HartMask,
> 
> 
> +  IN  UINTN                          HartMaskBase,
> 
> 
> +  IN  UINTN                          StartAddr,
> 
> 
> +  IN  UINTN                          Size,
> 
> 
> +  IN  UINTN                          Vmid
> 
> 
> +  )
> 
> 
> +{
> 
> 
> +  SbiRet Ret = SbiCall (
> 
> 
> +                 SBI_EXT_RFENCE,
> 
> 
> +                 SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA,
> 
> 
> +                 5,
> 
> 
> +                 (UINTN)HartMask,
> 
> 
> +                 HartMaskBase,
> 
> 
> +                 StartAddr,
> 
> 
> +                 Size,
> 
> 
> +                 Vmid
> 
> 
> +                 );
> 
> 
> +  return TranslateError (Ret.Error);
> 
> 
> +}
> 
> 
> +
> 
> 
> +/**
> 
> 
> +  Instructs the remote harts to execute one or more
> SFENCE.GVMA instructions.
> 
> 
> +
> 
> 
> +  The SFENCE.GVMA covers the range of virtual addresses
> between StartAaddr and Size.
> 
> 
> +  This function call is only valid for harts
> implementing the hypervisor extension.
> 
> 
> +
> 
> 
> +  The remote fence function acts as a full tlb flush if
> * StartAddr and size
> 
> 
> +  are both 0 * size is equal to 2^XLEN-1
> 
> 
> +
> 
> 
> +  @param[in]  HartMask             Scalar bit-vector
> containing hart ids
> 
> 
> +  @param[in]  HartMaskBase         The starting hartid
> from which the bit-vector
> 
> 
> +                                   must be computed. If
> set to -1, HartMask is
> 
> 
> +                                   ignored and all
> harts are considered.
> 
> 
> +  @param[in]  StartAddr            The first address of
> the affected range.
> 
> 
> +  @param[in]  Size                 How many addresses
> are affected.
> 
> 
> +  @retval EFI_SUCCESS              IPI was sent to all
> the targeted harts.
> 
> 
> +  @retval EFI_LOAD_ERROR           StartAddr or Size is
> not valid.
> 
> 
> +  @retval EFI_UNSUPPORTED          SBI does not
> implement this function or one
> 
> 
> +                                   of the target harts
> does not support the
> 
> 
> +                                   hypervisor
> extension.
> 
> 
> +  @retval EFI_INVALID_PARAMETER    Either
> hart_mask_base or any of the hartid
> 
> 
> +                                   from hart_mask is
> not valid i.e. either the
> 
> 
> +                                   hartid is not
> enabled by the platform or is
> 
> 
> +                                   not available to the
> supervisor.
> 
> 
> +**/
> 
> 
> +EFI_STATUS
> 
> 
> +EFIAPI
> 
> 
> +SbiRemoteHFenceGvma (
> 
> 
> +  IN  UINTN                         *HartMask,
> 
> 
> +  IN  UINTN                          HartMaskBase,
> 
> 
> +  IN  UINTN                          StartAddr,
> 
> 
> +  IN  UINTN                          Size
> 
> 
> +  )
> 
> 
> +{
> 
> 
> +  SbiRet Ret = SbiCall (
> 
> 
> +                 SBI_EXT_RFENCE,
> 
> 
> +
> SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA_VMID,
> 
> 
> +                 4,
> 
> 
> +                 (UINTN)HartMask,
> 
> 
> +                 HartMaskBase,
> 
> 
> +                 StartAddr,
> 
> 
> +                 Size
> 
> 
> +                 );
> 
> 
> +  return TranslateError (Ret.Error);
> 
> 
> +}
> 
> 
> +
> 
> 
> +/**
> 
> 
> +  Instructs the remote harts to execute one or more
> SFENCE.VVMA instructions.
> 
> 
> +
> 
> 
> +  The SFENCE.GVMA covers the range of virtual addresses
> between StartAaddr and Size.
> 
> 
> +  Covers only the given ASID.
> 
> 
> +  This function call is only valid for harts
> implementing the hypervisor extension.
> 
> 
> +
> 
> 
> +  The remote fence function acts as a full tlb flush if
> * StartAddr and size
> 
> 
> +  are both 0 * size is equal to 2^XLEN-1
> 
> 
> +
> 
> 
> +  @param[in]  HartMask             Scalar bit-vector
> containing hart ids
> 
> 
> +  @param[in]  HartMaskBase         The starting hartid
> from which the bit-vector
> 
> 
> +                                   must be computed. If
> set to -1, HartMask is
> 
> 
> +                                   ignored and all
> harts are considered.
> 
> 
> +  @param[in]  StartAddr            The first address of
> the affected range.
> 
> 
> +  @param[in]  Size                 How many addresses
> are affected.
> 
> 
> +  @retval EFI_SUCCESS              IPI was sent to all
> the targeted harts.
> 
> 
> +  @retval EFI_LOAD_ERROR           StartAddr or Size is
> not valid.
> 
> 
> +  @retval EFI_UNSUPPORTED          SBI does not
> implement this function or one
> 
> 
> +                                   of the target harts
> does not support the
> 
> 
> +                                   hypervisor
> extension.
> 
> 
> +  @retval EFI_INVALID_PARAMETER    Either
> hart_mask_base or any of the hartid
> 
> 
> +                                   from hart_mask is
> not valid i.e. either the
> 
> 
> +                                   hartid is not
> enabled by the platform or is
> 
> 
> +                                   not available to the
> supervisor.
> 
> 
> +**/
> 
> 
> +EFI_STATUS
> 
> 
> +EFIAPI
> 
> 
> +SbiRemoteHFenceVvmaAsid (
> 
> 
> +  IN  UINTN                         *HartMask,
> 
> 
> +  IN  UINTN                          HartMaskBase,
> 
> 
> +  IN  UINTN                          StartAddr,
> 
> 
> +  IN  UINTN                          Size,
> 
> 
> +  IN  UINTN                          Asid
> 
> 
> +  )
> 
> 
> +{
> 
> 
> +  SbiRet Ret = SbiCall (
> 
> 
> +                 SBI_EXT_RFENCE,
> 
> 
> +                 SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA,
> 
> 
> +                 5,
> 
> 
> +                 (UINTN)HartMask,
> 
> 
> +                 HartMaskBase,
> 
> 
> +                 StartAddr,
> 
> 
> +                 Size,
> 
> 
> +                 Asid
> 
> 
> +                 );
> 
> 
> +  return TranslateError (Ret.Error);
> 
> 
> +}
> 
> 
> +
> 
> 
> +/**
> 
> 
> +  Instructs the remote harts to execute one or more
> SFENCE.VVMA instructions.
> 
> 
> +
> 
> 
> +  The SFENCE.GVMA covers the range of virtual addresses
> between StartAaddr and Size.
> 
> 
> +  This function call is only valid for harts
> implementing the hypervisor extension.
> 
> 
> +
> 
> 
> +  The remote fence function acts as a full tlb flush if
> * StartAddr and size
> 
> 
> +  are both 0 * size is equal to 2^XLEN-1
> 
> 
> +
> 
> 
> +  @param[in]  HartMask             Scalar bit-vector
> containing hart ids
> 
> 
> +  @param[in]  HartMaskBase         The starting hartid
> from which the bit-vector
> 
> 
> +                                   must be computed. If
> set to -1, HartMask is
> 
> 
> +                                   ignored and all
> harts are considered.
> 
> 
> +  @param[in]  StartAddr            The first address of
> the affected range.
> 
> 
> +  @param[in]  Size                 How many addresses
> are affected.
> 
> 
> +  @retval EFI_SUCCESS              IPI was sent to all
> the targeted harts.
> 
> 
> +  @retval EFI_LOAD_ERROR           StartAddr or Size is
> not valid.
> 
> 
> +  @retval EFI_UNSUPPORTED          SBI does not
> implement this function or one
> 
> 
> +                                   of the target harts
> does not support the
> 
> 
> +                                   hypervisor
> extension.
> 
> 
> +  @retval EFI_INVALID_PARAMETER    Either
> hart_mask_base or any of the hartid
> 
> 
> +                                   from hart_mask is
> not valid i.e. either the
> 
> 
> +                                   hartid is not
> enabled by the platform or is
> 
> 
> +                                   not available to the
> supervisor.
> 
> 
> +**/
> 
> 
> +EFI_STATUS
> 
> 
> +EFIAPI
> 
> 
> +SbiRemoteHFenceVvma (
> 
> 
> +  IN  UINTN                         *HartMask,
> 
> 
> +  IN  UINTN                          HartMaskBase,
> 
> 
> +  IN  UINTN                          StartAddr,
> 
> 
> +  IN  UINTN                          Size
> 
> 
> +  )
> 
> 
> +{
> 
> 
> +  SbiRet Ret = SbiCall (
> 
> 
> +                 SBI_EXT_RFENCE,
> 
> 
> +
> SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA_ASID,
> 
> 
> +                 4,
> 
> 
> +                 (UINTN)HartMask,
> 
> 
> +                 HartMaskBase,
> 
> 
> +                 StartAddr,
> 
> 
> +                 Size
> 
> 
> +                 );
> 
> 
> +  return TranslateError (Ret.Error);
> 
> 
> +}
> 
> 
> +
> 
> 
> +//
> 
> 
> +// SBI interface function for the vendor extension
> 
> 
> +//
> 
> 
> +
> 
> 
> +/**
> 
> 
> +  Call a function in a vendor defined SBI extension
> 
> 
> +
> 
> 
> +  ASSERT() if the ExtensionId is not in the designated
> SBI Vendor Extension
> 
> 
> +  Space or NumArgs exceeds SBI_CALL_MAX_ARGS.
> 
> 
> +
> 
> 
> +  @param[in]  ExtensionId          The SBI vendor
> extension ID.
> 
> 
> +  @param[in]  FunctionId           The function ID to
> call in this extension.
> 
> 
> +  @param[in]  NumArgs              How many arguments
> are passed.
> 
> 
> +  @param[in]  ...                  Actual Arguments to
> the function.
> 
> 
> +  @retval EFI_SUCCESS if the SBI function was called
> and it was successful
> 
> 
> +  @retval others if the called SBI function returns an
> error
> 
> 
> +**/
> 
> 
> +EFI_STATUS
> 
> 
> +EFIAPI
> 
> 
> +SbiVendorCall (
> 
> 
> +  IN  UINTN                          ExtensionId,
> 
> 
> +  IN  UINTN                          FunctionId,
> 
> 
> +  IN  UINTN                          NumArgs,
> 
> 
> +  ...
> 
> 
> +  )
> 
> 
> +{
> 
> 
> +    SbiRet Ret;
> 
> 
> +    VA_LIST Args;
> 
> 
> +    VA_START (Args, NumArgs);
> 
> 
> +
> 
> 
> +    ASSERT (ExtensionId >= SBI_EXT_VENDOR_START &&
> ExtensionId <= SBI_EXT_VENDOR_END);
> 
> 
> +    ASSERT (NumArgs <= SBI_CALL_MAX_ARGS);
> 
> 
> +
> 
> 
> +    switch (NumArgs) {
> 
> 
> +      case 0:
> 
> 
> +        Ret = SbiCall (ExtensionId, FunctionId,
> NumArgs);
> 
> 
> +        break;
> 
> 
> +      case 1:
> 
> 
> +        Ret = SbiCall (ExtensionId, FunctionId,
> NumArgs, VA_ARG (Args, UINTN));
> 
> 
> +        break;
> 
> 
> +      case 2:
> 
> 
> +        Ret = SbiCall (ExtensionId, FunctionId,
> NumArgs, VA_ARG (Args, UINTN),
> 
> 
> +                       VA_ARG (Args, UINTN));
> 
> 
> +        break;
> 
> 
> +      case 3:
> 
> 
> +        Ret = SbiCall (ExtensionId, FunctionId,
> NumArgs, VA_ARG (Args, UINTN),
> 
> 
> +                       VA_ARG (Args, UINTN), VA_ARG
> (Args, UINTN));
> 
> 
> +        break;
> 
> 
> +      case 4:
> 
> 
> +        Ret = SbiCall (ExtensionId, FunctionId,
> NumArgs, VA_ARG (Args, UINTN),
> 
> 
> +                       VA_ARG (Args, UINTN), VA_ARG
> (Args, UINTN),
> 
> 
> +                       VA_ARG (Args, UINTN));
> 
> 
> +        break;
> 
> 
> +      case 5:
> 
> 
> +        Ret = SbiCall (ExtensionId, FunctionId,
> NumArgs, VA_ARG (Args, UINTN),
> 
> 
> +                       VA_ARG (Args, UINTN), VA_ARG
> (Args, UINTN),
> 
> 
> +                       VA_ARG (Args, UINTN), VA_ARG
> (Args, UINTN));
> 
> 
> +        break;
> 
> 
> +      case 6:
> 
> 
> +        Ret = SbiCall (ExtensionId, FunctionId,
> NumArgs, VA_ARG (Args, UINTN),
> 
> 
> +                       VA_ARG (Args, UINTN), VA_ARG
> (Args, UINTN),
> 
> 
> +                       VA_ARG (Args, UINTN), VA_ARG
> (Args, UINTN),
> 
> 
> +                       VA_ARG (Args, UINTN));
> 
> 
> +        break;
> 
> 
> +      default:
> 
> 
> +        // Too many args. In theory SBI can handle more
> arguments when they are
> 
> 
> +        // passed on the stack but no SBI extension
> uses this, therefore it's
> 
> 
> +        // not yet implemented here.
> 
> 
> +        return EFI_INVALID_PARAMETER;
> 
> 
> +     }
> 
> 
> +
> 
> 
> +    VA_END(Args);
> 
> 
> +    return TranslateError (Ret.Error);
> 
> 
> +}
> 
> 
> +
> 
> 
> +//
> 
> 
> +// SBI Firmware extension
> 
> 
> +//
> 
> 
> +
> 
> 
> +/**
> 
> 
> +  Get scratch space of the current hart.
> 
> 
> +
> 
> 
> +  Please consider using the wrapper
> SbiGetFirmwareContext if you only need to
> 
> 
> +  access the firmware context.
> 
> 
> +
> 
> 
> +  @param[out] ScratchSpace         The scratch space
> pointer.
> 
> 
> +  @retval EFI_SUCCESS              The operation
> succeeds.
> 
> 
> +**/
> 
> 
> +EFI_STATUS
> 
> 
> +EFIAPI
> 
> 
> +SbiGetMscratch (
> 
> 
> +  OUT SBI_SCRATCH                    **ScratchSpace
> 
> 
> +  )
> 
> 
> +{
> 
> 
> +  SbiRet Ret = SbiCall (SBI_EDK2_FW_EXT,
> SBI_EXT_FW_MSCRATCH_FUNC, 0);
> 
> 
> +
> 
> 
> +  if (!Ret.Error) {
> 
> 
> +    *ScratchSpace = (SBI_SCRATCH *)Ret.Value;
> 
> 
> +  }
> 
> 
> +
> 
> 
> +  return EFI_SUCCESS;
> 
> 
> +}
> 
> 
> +
> 
> 
> +/**
> 
> 
> +  Get scratch space of the given hart id.
> 
> 
> +
> 
> 
> +  @param[in]  HartId               The hart id.
> 
> 
> +  @param[out] ScratchSpace         The scratch space
> pointer.
> 
> 
> +  @retval EFI_SUCCESS              The operation
> succeeds.
> 
> 
> +**/
> 
> 
> +EFI_STATUS
> 
> 
> +EFIAPI
> 
> 
> +SbiGetMscratchHartid (
> 
> 
> +  IN  UINTN                            HartId,
> 
> 
> +  OUT SBI_SCRATCH                    **ScratchSpace
> 
> 
> +  )
> 
> 
> +{
> 
> 
> +  SbiRet Ret = SbiCall (
> 
> 
> +                 SBI_EDK2_FW_EXT,
> 
> 
> +                 SBI_EXT_FW_MSCRATCH_HARTID_FUNC,
> 
> 
> +                 1,
> 
> 
> +                 HartId
> 
> 
> +                 );
> 
> 
> +
> 
> 
> +  if (!Ret.Error) {
> 
> 
> +    *ScratchSpace = (SBI_SCRATCH *)Ret.Value;
> 
> 
> +  }
> 
> 
> +
> 
> 
> +  return EFI_SUCCESS;
> 
> 
> +}
> 
> 
> +
> 
> 
> +/**
> 
> 
> +  Get firmware context of the calling hart.
> 
> 
> +
> 
> 
> +  @param[out] FirmwareContext      The firmware context
> pointer.
> 
> 
> +  @retval EFI_SUCCESS              The operation
> succeeds.
> 
> 
> +**/
> 
> 
> +EFI_STATUS
> 
> 
> +EFIAPI
> 
> 
> +SbiGetFirmwareContext (
> 
> 
> +  OUT EFI_RISCV_OPENSBI_FIRMWARE_CONTEXT
> **FirmwareContext
> 
> 
> +  )
> 
> 
> +{
> 
> 
> +  SBI_SCRATCH  *ScratchSpace;
> 
> 
> +  SBI_PLATFORM *SbiPlatform;
> 
> 
> +  SbiRet Ret = SbiCall (SBI_EDK2_FW_EXT,
> SBI_EXT_FW_MSCRATCH_FUNC, 0);
> 
> 
> +
> 
> 
> +  if (!Ret.Error) {
> 
> 
> +    ScratchSpace = (SBI_SCRATCH *)Ret.Value;
> 
> 
> +    SbiPlatform = (SBI_PLATFORM
> *)sbi_platform_ptr(ScratchSpace);
> 
> 
> +    *FirmwareContext =
> (EFI_RISCV_OPENSBI_FIRMWARE_CONTEXT *)SbiPlatform-
> >firmware_context;
> 
> 
> +  }
> 
> 
> +
> 
> 
> +  return EFI_SUCCESS;
> 
> 
> +}
> 
> 
> +
> 
> 
> +/**
> 
> 
> +  Set firmware context of the calling hart.
> 
> 
> +
> 
> 
> +  @param[in] FirmwareContext       The firmware context
> pointer.
> 
> 
> +  @retval EFI_SUCCESS              The operation
> succeeds.
> 
> 
> +**/
> 
> 
> +EFI_STATUS
> 
> 
> +EFIAPI
> 
> 
> +SbiSetFirmwareContext (
> 
> 
> +  IN EFI_RISCV_OPENSBI_FIRMWARE_CONTEXT
> *FirmwareContext
> 
> 
> +  )
> 
> 
> +{
> 
> 
> +  SBI_SCRATCH  *ScratchSpace;
> 
> 
> +  SBI_PLATFORM *SbiPlatform;
> 
> 
> +  SbiRet Ret = SbiCall (SBI_EDK2_FW_EXT,
> SBI_EXT_FW_MSCRATCH_FUNC, 0);
> 
> 
> +
> 
> 
> +  if (!Ret.Error) {
> 
> 
> +    ScratchSpace = (SBI_SCRATCH *)Ret.Value;
> 
> 
> +    SbiPlatform = (SBI_PLATFORM *)sbi_platform_ptr
> (ScratchSpace);
> 
> 
> +    SbiPlatform->firmware_context =
> (UINTN)FirmwareContext;
> 
> 
> +  }
> 
> 
> +
> 
> 
> +  return EFI_SUCCESS;
> 
> 
> +}
> 
> 
> --
> 2.26.1
> 
> 
> 


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [edk2-devel] [PATCH v4 1/1] ProcessorPkg/Library: Add RiscVEdk2SbiLib
  2020-06-02 22:00   ` [edk2-devel] " Michael D Kinney
@ 2020-06-03  1:24     ` Abner Chang
       [not found]     ` <1614E4344379EB27.21938@groups.io>
  1 sibling, 0 replies; 7+ messages in thread
From: Abner Chang @ 2020-06-03  1:24 UTC (permalink / raw)
  To: Kinney, Michael D, devel@edk2.groups.io,
	Schaefer, Daniel (DualStudy)
  Cc: Leif Lindholm, Chen, Gilbert



> -----Original Message-----
> From: Kinney, Michael D [mailto:michael.d.kinney@intel.com]
> Sent: Wednesday, June 3, 2020 6:00 AM
> To: devel@edk2.groups.io; Schaefer, Daniel (DualStudy)
> <daniel.schaefer@hpe.com>; Kinney, Michael D
> <michael.d.kinney@intel.com>
> Cc: Leif Lindholm <leif@nuviainc.com>; Chen, Gilbert
> <gilbert.chen@hpe.com>; Chang, Abner (HPS SW/FW Technologist)
> <abner.chang@hpe.com>
> Subject: RE: [edk2-devel] [PATCH v4 1/1] ProcessorPkg/Library: Add
> RiscVEdk2SbiLib
> 
> Hi Daniel,
> 
> I see some inconsistence in the names used in these patches.
> 
> For example, there should not be a need to use "Edk2" in the
> name of a library.  This library is in an edk2 repo.
We currently have two libraries regards to RISC-V SBI spec. One is the wrapper to build OpenSBI lib, which is RiscVOpenSbiLib.
Another one is SBI firmware code base extension in which the ABIs are provided by system firmware other than the standard ABIs defined in SBI spec. To name it with EDK2 makes sense because that is RISC-V EDK2 firmware code base SBI extension.
> 
> I see "RiscV" and "Risk-V" used in file paths.  I recommend
> you pick one and use it consistently.  In the MdePkg, I see
> RiscV64, and macros using RISCV, RISCV32, RISCV64, and RISCV128.
> which seems consistent and does not use a '-'.  Perhaps use
> "RiscV" for content that works for 32, 64, and 128 bit and
> RiscV32, RiscV64, and RiskV128 for content is specific to the
> bit width?
For the folders under Silicon and platform, I prefer to use "RISC-V" which is the official name of this processor. All other files can use RiscV which conform the naming rule. RISCV32, RISCV64, and RISCV128 are used for the architectures.

>  
> Thanks,
> 
> Mike
> 
> > -----Original Message-----
> > From: devel@edk2.groups.io <devel@edk2.groups.io> On
> > Behalf Of Daniel Schaefer
> > Sent: Tuesday, June 2, 2020 9:52 AM
> > To: devel@edk2.groups.io
> > Cc: Leif Lindholm <leif@nuviainc.com>; Gilbert Chen
> > <gilbert.chen@hpe.com>; Abner Chang
> > <abner.chang@hpe.com>; Kinney, Michael D
> > <michael.d.kinney@intel.com>
> > Subject: [edk2-devel] [PATCH v4 1/1]
> > ProcessorPkg/Library: Add RiscVEdk2SbiLib
> >
> > Library provides interfaces to invoke SBI ecalls.
> >
> > Signed-off-by: Daniel Schaefer <daniel.schaefer@hpe.com>
> >
> > Cc: Leif Lindholm <leif@nuviainc.com>
> > Cc: Gilbert Chen <gilbert.chen@hpe.com>
> > Cc: Abner Chang <abner.chang@hpe.com>
> > Cc: Michael D. Kinney <michael.d.kinney@intel.com>
> > ---
> >  Silicon/RISC-
> > V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.i
> > nf |  28 +
> >  Silicon/RISC-
> > V/ProcessorPkg/Include/Library/RiscVEdk2SbiLib.h
> > | 563 ++++++++++++
> >  Silicon/RISC-
> > V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.c
> > | 897 ++++++++++++++++++++
> >  3 files changed, 1488 insertions(+)
> >
> > diff --git a/Silicon/RISC-
> > V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.i
> > nf b/Silicon/RISC-
> > V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.i
> > nf
> > new file mode 100644
> > index 000000000000..665dcbf40e01
> > --- /dev/null
> > +++ b/Silicon/RISC-
> > V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.i
> > nf
> > @@ -0,0 +1,28 @@
> > +## @file
> >
> >
> > +# RISC-V Library to call SBI ecalls
> >
> >
> > +#
> >
> >
> > +#  Copyright (c) 2020, Hewlett Packard Enterprise
> > Development LP. All rights reserved.<BR>
> >
> >
> > +#
> >
> >
> > +#  SPDX-License-Identifier: BSD-2-Clause-Patent
> >
> >
> > +#
> >
> >
> > +##
> >
> >
> > +
> >
> >
> > +[Defines]
> >
> >
> > +  INF_VERSION    = 0x0001001b
> >
> >
> > +  BASE_NAME      = RiscVEdk2SbiLib
> >
> >
> > +  FILE_GUID      = 0DF1BBBD-F7E5-4E8A-BCF1-9D63D2DD9FDD
> >
> >
> > +  MODULE_TYPE    = BASE
> >
> >
> > +  VERSION_STRING = 1.0
> >
> >
> > +  LIBRARY_CLASS  = RiscVEdk2SbiLib
> >
> >
> > +
> >
> >
> > +[Sources]
> >
> >
> > +  RiscVEdk2SbiLib.c
> >
> >
> > +
> >
> >
> > +[Packages]
> >
> >
> > +  MdePkg/MdePkg.dec
> >
> >
> > +  Silicon/RISC-V/ProcessorPkg/RiscVProcessorPkg.dec
> >
> >
> > +  Platform/RISC-V/PlatformPkg/RiscVPlatformPkg.dec
> >
> >
> > +
> >
> >
> > +[LibraryClasses]
> >
> >
> > +  BaseLib
> >
> >
> > +  RiscVOpensbiLib
> >
> >
> > diff --git a/Silicon/RISC-
> > V/ProcessorPkg/Include/Library/RiscVEdk2SbiLib.h
> > b/Silicon/RISC-
> > V/ProcessorPkg/Include/Library/RiscVEdk2SbiLib.h
> > new file mode 100644
> > index 000000000000..c1ae3176147f
> > --- /dev/null
> > +++ b/Silicon/RISC-
> > V/ProcessorPkg/Include/Library/RiscVEdk2SbiLib.h
> > @@ -0,0 +1,563 @@
> > +/** @file
> >
> >
> > +  Library to call the RISC-V SBI ecalls
> >
> >
> > +
> >
> >
> > +  Copyright (c) 2020, Hewlett Packard Development LP.
> > All rights reserved.<BR>
> >
> >
> > +
> >
> >
> > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> >
> >
> > +
> >
> >
> > +  @par Glossary:
> >
> >
> > +    - Hart - Hardware Thread, similar to a CPU core
> >
> >
> > +**/
> >
> >
> > +
> >
> >
> > +#ifndef RISCV_SBI_LIB_H_
> >
> >
> > +#define RISCV_SBI_LIB_H_
> >
> >
> > +
> >
> >
> > +#include <Uefi.h>
> >
> >
> > +#include <IndustryStandard/RiscVOpensbi.h>
> >
> >
> > +#include <sbi/sbi_scratch.h>
> >
> >
> > +#include <sbi/sbi_platform.h>
> >
> >
> > +
> >
> >
> > +//
> >
> >
> > +// EDK2 OpenSBI Firmware extension.
> >
> >
> > +//
> >
> >
> > +#define SBI_EDK2_FW_EXT
> > (SBI_EXT_FIRMWARE_CODE_BASE_START | SBI_OPENSBI_IMPID)
> >
> >
> > +//
> >
> >
> > +// EDK2 OpenSBI Firmware extension functions.
> >
> >
> > +//
> >
> >
> > +#define SBI_EXT_FW_MSCRATCH_FUNC        0
> >
> >
> > +#define SBI_EXT_FW_MSCRATCH_HARTID_FUNC 1
> >
> >
> > +
> >
> >
> > +//
> >
> >
> > +// EDK2 OpenSBI firmware extension return status.
> >
> >
> > +//
> >
> >
> > +typedef struct {
> >
> >
> > +  UINTN Error;   ///< SBI status code
> >
> >
> > +  UINTN Value;   ///< Value returned
> >
> >
> > +} SbiRet;
> >
> >
> > +
> >
> >
> > +/**
> >
> >
> > +  Get the implemented SBI specification version
> >
> >
> > +
> >
> >
> > +  The minor number of the SBI specification is encoded
> > in the low 24 bits,
> >
> >
> > +  with the major number encoded in the next 7 bits.
> > Bit 32 must be 0 and is
> >
> >
> > +  reserved for future expansion.
> >
> >
> > +
> >
> >
> > +  @param[out] SpecVersion          The Version of the
> > SBI specification.
> >
> >
> > +**/
> >
> >
> > +VOID
> >
> >
> > +EFIAPI
> >
> >
> > +SbiGetSpecVersion (
> >
> >
> > +  OUT UINTN                       *SpecVersion
> >
> >
> > +  );
> >
> >
> > +
> >
> >
> > +/**
> >
> >
> > +  Get the SBI implementation ID
> >
> >
> > +
> >
> >
> > +  This ID is used to idenetify a specific SBI
> > implementation in order to work
> >
> >
> > +  around any quirks it might have.
> >
> >
> > +
> >
> >
> > +  @param[out] ImplId               The ID of the SBI
> > implementation.
> >
> >
> > +**/
> >
> >
> > +VOID
> >
> >
> > +EFIAPI
> >
> >
> > +SbiGetImplId (
> >
> >
> > +  OUT UINTN                      *ImplId
> >
> >
> > +  );
> >
> >
> > +
> >
> >
> > +/**
> >
> >
> > +  Get the SBI implementation version
> >
> >
> > +
> >
> >
> > +  The version of this SBI implementation.
> >
> >
> > +  The encoding of this number is determined by the
> > specific SBI implementation.
> >
> >
> > +
> >
> >
> > +  @param[out] ImplVersion          The version of the
> > SBI implementation.
> >
> >
> > +**/
> >
> >
> > +VOID
> >
> >
> > +EFIAPI
> >
> >
> > +SbiGetImplVersion (
> >
> >
> > +  OUT UINTN                       *ImplVersion
> >
> >
> > +  );
> >
> >
> > +
> >
> >
> > +/**
> >
> >
> > +  Probe whether an SBI extension is available
> >
> >
> > +
> >
> >
> > +  ProbeResult is set to 0 if the extension is not
> > available or to an extension
> >
> >
> > +  specified value if it is available.
> >
> >
> > +
> >
> >
> > +  @param[in]  ExtensionId          The extension ID.
> >
> >
> > +  @param[out] ProbeResult          The return value of
> > the probe.
> >
> >
> > +**/
> >
> >
> > +VOID
> >
> >
> > +EFIAPI
> >
> >
> > +SbiProbeExtension (
> >
> >
> > +  IN  INTN                         ExtensionId,
> >
> >
> > +  OUT INTN                        *ProbeResult
> >
> >
> > +  );
> >
> >
> > +
> >
> >
> > +/**
> >
> >
> > +  Get the CPU's vendor ID
> >
> >
> > +
> >
> >
> > +  Reads the mvendorid CSR.
> >
> >
> > +
> >
> >
> > +  @param[out] MachineVendorId      The CPU's vendor ID.
> >
> >
> > +**/
> >
> >
> > +VOID
> >
> >
> > +EFIAPI
> >
> >
> > +SbiGetMachineVendorId (
> >
> >
> > +  OUT UINTN                       *MachineVendorId
> >
> >
> > +  );
> >
> >
> > +
> >
> >
> > +/**
> >
> >
> > +  Get the CPU's architecture ID
> >
> >
> > +
> >
> >
> > +  Reads the marchid CSR.
> >
> >
> > +
> >
> >
> > +  @param[out] MachineArchId        The CPU's
> > architecture ID.
> >
> >
> > +**/
> >
> >
> > +VOID
> >
> >
> > +EFIAPI
> >
> >
> > +SbiGetMachineArchId (
> >
> >
> > +  OUT UINTN                       *MachineArchId
> >
> >
> > +  );
> >
> >
> > +
> >
> >
> > +/**
> >
> >
> > +  Get the CPU's implementation ID
> >
> >
> > +
> >
> >
> > +  Reads the mimpid CSR.
> >
> >
> > +
> >
> >
> > +  @param[out] MachineImplId        The CPU's
> > implementation ID.
> >
> >
> > +**/
> >
> >
> > +VOID
> >
> >
> > +EFIAPI
> >
> >
> > +SbiGetMachineImplId (
> >
> >
> > +  OUT UINTN                       *MachineImplId
> >
> >
> > +  );
> >
> >
> > +
> >
> >
> > +/**
> >
> >
> > +  Politely ask the SBI to start a given hart.
> >
> >
> > +
> >
> >
> > +  This call may return before the hart has actually
> > started executing, if the
> >
> >
> > +  SBI implementation can guarantee that the hart is
> > actually going to start.
> >
> >
> > +
> >
> >
> > +  Before the hart jumps to StartAddr, the hart MUST
> > configure PMP if present
> >
> >
> > +  and switch to S-mode.
> >
> >
> > +
> >
> >
> > +  @param[in]  HartId               The id of the hart
> > to start.
> >
> >
> > +  @param[in]  StartAddr            The physical
> > address, where the hart starts
> >
> >
> > +                                   executing from.
> >
> >
> > +  @param[in]  Priv                 An XLEN-bit value,
> > which will be in register
> >
> >
> > +                                   a1 when the hart
> > starts.
> >
> >
> > +  @retval EFI_SUCCESS              Hart was stopped and
> > will start executing from StartAddr.
> >
> >
> > +  @retval EFI_LOAD_ERROR           StartAddr is not
> > valid, possibly due to following reasons:
> >
> >
> > +                                    - It is not a valid
> > physical address.
> >
> >
> > +                                    - The address is
> > prohibited by PMP to run in
> >
> >
> > +                                      supervisor mode.
> >
> >
> > +  @retval EFI_INVALID_PARAMETER    HartId is not a
> > valid hart id
> >
> >
> > +  @retval EFI_ALREADY_STARTED      The hart is already
> > running.
> >
> >
> > +  @retval other                    The start request
> > failed for unknown reasons.
> >
> >
> > +**/
> >
> >
> > +EFI_STATUS
> >
> >
> > +EFIAPI
> >
> >
> > +SbiHartStart (
> >
> >
> > +  IN  UINTN                          HartId,
> >
> >
> > +  IN  UINTN                          StartAddr,
> >
> >
> > +  IN  UINTN                          Priv
> >
> >
> > +  );
> >
> >
> > +
> >
> >
> > +/**
> >
> >
> > +  Return execution of the calling hart to SBI.
> >
> >
> > +
> >
> >
> > +  MUST be called in S-Mode with user interrupts
> > disabled.
> >
> >
> > +  This call is not expected to return, unless a failure
> > occurs.
> >
> >
> > +
> >
> >
> > +  @retval     EFI_SUCCESS          Never occurs. When
> > successful, the call does not return.
> >
> >
> > +  @retval     other                Failed to stop hard
> > for an unknown reason.
> >
> >
> > +**/
> >
> >
> > +EFI_STATUS
> >
> >
> > +EFIAPI
> >
> >
> > +SbiHartStop (
> >
> >
> > +  );
> >
> >
> > +
> >
> >
> > +/**
> >
> >
> > +  Get the current status of a hart.
> >
> >
> > +
> >
> >
> > +  Since harts can transition between states at any
> > time, the status retrieved
> >
> >
> > +  by this function may already be out of date, once it
> > returns.
> >
> >
> > +
> >
> >
> > +  Possible values for HartStatus are:
> >
> >
> > +  0: STARTED
> >
> >
> > +  1: STOPPED
> >
> >
> > +  2: START_REQUEST_PENDING
> >
> >
> > +  3: STOP_REQUEST_PENDING
> >
> >
> > +
> >
> >
> > +  @param[out] HartStatus           The pointer in which
> > the hart's status is
> >
> >
> > +                                   stored.
> >
> >
> > +  @retval EFI_SUCCESS              The operation
> > succeeds.
> >
> >
> > +  @retval EFI_INVALID_PARAMETER    A parameter is
> > invalid.
> >
> >
> > +**/
> >
> >
> > +EFI_STATUS
> >
> >
> > +EFIAPI
> >
> >
> > +SbiHartGetStatus (
> >
> >
> > +  IN  UINTN                          HartId,
> >
> >
> > +  OUT UINTN                         *HartStatus
> >
> >
> > +  );
> >
> >
> > +
> >
> >
> > +///
> >
> >
> > +/// Timer extension
> >
> >
> > +///
> >
> >
> > +
> >
> >
> > +/**
> >
> >
> > +  Clear pending timer interrupt bit and set timer for
> > next event after Time.
> >
> >
> > +
> >
> >
> > +  To clear the timer without scheduling a timer event,
> > set Time to a
> >
> >
> > +  practically infinite value or mask the timer
> > interrupt by clearing sie.STIE.
> >
> >
> > +
> >
> >
> > +  @param[in]  Time                 The time offset to
> > the next scheduled timer interrupt.
> >
> >
> > +**/
> >
> >
> > +VOID
> >
> >
> > +EFIAPI
> >
> >
> > +SbiSetTimer (
> >
> >
> > +  IN  UINT64                         Time
> >
> >
> > +  );
> >
> >
> > +
> >
> >
> > +///
> >
> >
> > +/// IPI extension
> >
> >
> > +///
> >
> >
> > +
> >
> >
> > +/**
> >
> >
> > +  Send IPI to all harts specified in the mask.
> >
> >
> > +
> >
> >
> > +  The interrupts are registered as supervisor software
> > interrupts at the
> >
> >
> > +  receiving hart.
> >
> >
> > +
> >
> >
> > +  @param[in]  HartMask             Scalar bit-vector
> > containing hart ids
> >
> >
> > +  @param[in]  HartMaskBase         The starting hartid
> > from which the bit-vector
> >
> >
> > +                                   must be computed. If
> > set to -1, HartMask is
> >
> >
> > +                                   ignored and all
> > harts are considered.
> >
> >
> > +  @retval EFI_SUCCESS              IPI was sent to all
> > the targeted harts.
> >
> >
> > +  @retval EFI_INVALID_PARAMETER    Either
> > hart_mask_base or any of the hartid
> >
> >
> > +                                   from hart_mask is
> > not valid i.e. either the
> >
> >
> > +                                   hartid is not
> > enabled by the platform or is
> >
> >
> > +                                   not available to the
> > supervisor.
> >
> >
> > +**/
> >
> >
> > +EFI_STATUS
> >
> >
> > +EFIAPI
> >
> >
> > +SbiSendIpi (
> >
> >
> > +  IN  UINTN                         *HartMask,
> >
> >
> > +  IN  UINTN                          HartMaskBase
> >
> >
> > +  );
> >
> >
> > +
> >
> >
> > +///
> >
> >
> > +/// Remote fence extension
> >
> >
> > +///
> >
> >
> > +
> >
> >
> > +/**
> >
> >
> > +  Instructs remote harts to execute a FENCE.I
> > instruction.
> >
> >
> > +
> >
> >
> > +  @param[in]  HartMask             Scalar bit-vector
> > containing hart ids
> >
> >
> > +  @param[in]  HartMaskBase         The starting hartid
> > from which the bit-vector
> >
> >
> > +                                   must be computed. If
> > set to -1, HartMask is
> >
> >
> > +                                   ignored and all
> > harts are considered.
> >
> >
> > +  @retval EFI_SUCCESS              IPI was sent to all
> > the targeted harts.
> >
> >
> > +  @retval EFI_INVALID_PARAMETER    Either
> > hart_mask_base or any of the hartid
> >
> >
> > +                                   from hart_mask is
> > not valid i.e. either the
> >
> >
> > +                                   hartid is not
> > enabled by the platform or is
> >
> >
> > +                                   not available to the
> > supervisor.
> >
> >
> > +**/
> >
> >
> > +EFI_STATUS
> >
> >
> > +EFIAPI
> >
> >
> > +SbiRemoteFenceI (
> >
> >
> > +  IN  UINTN                         *HartMask,
> >
> >
> > +  IN  UINTN                          HartMaskBase
> >
> >
> > +  );
> >
> >
> > +
> >
> >
> > +/**
> >
> >
> > +  Instructs the remote harts to execute one or more
> > SFENCE.VMA instructions.
> >
> >
> > +
> >
> >
> > +  The SFENCE.VMA covers the range of virtual addresses
> > between StartAaddr and Size.
> >
> >
> > +
> >
> >
> > +  The remote fence function acts as a full tlb flush if
> > * StartAddr and size
> >
> >
> > +  are both 0 * size is equal to 2^XLEN-1
> >
> >
> > +
> >
> >
> > +  @param[in]  HartMask             Scalar bit-vector
> > containing hart ids
> >
> >
> > +  @param[in]  HartMaskBase         The starting hartid
> > from which the bit-vector
> >
> >
> > +                                   must be computed. If
> > set to -1, HartMask is
> >
> >
> > +                                   ignored and all
> > harts are considered.
> >
> >
> > +  @param[in]  StartAddr            The first address of
> > the affected range.
> >
> >
> > +  @param[in]  Size                 How many addresses
> > are affected.
> >
> >
> > +  @retval EFI_SUCCESS              IPI was sent to all
> > the targeted harts.
> >
> >
> > +  @retval EFI_LOAD_ERROR           StartAddr or Size is
> > not valid.
> >
> >
> > +  @retval EFI_INVALID_PARAMETER    Either
> > hart_mask_base or any of the hartid
> >
> >
> > +                                   from hart_mask is
> > not valid i.e. either the
> >
> >
> > +                                   hartid is not
> > enabled by the platform or is
> >
> >
> > +                                   not available to the
> > supervisor.
> >
> >
> > +**/
> >
> >
> > +EFI_STATUS
> >
> >
> > +EFIAPI
> >
> >
> > +SbiRemoteSfenceVma (
> >
> >
> > +  IN  UINTN                         *HartMask,
> >
> >
> > +  IN  UINTN                          HartMaskBase,
> >
> >
> > +  IN  UINTN                          StartAddr,
> >
> >
> > +  IN  UINTN                          Size
> >
> >
> > +  );
> >
> >
> > +
> >
> >
> > +/**
> >
> >
> > +  Instructs the remote harts to execute one or more
> > SFENCE.VMA instructions.
> >
> >
> > +
> >
> >
> > +  The SFENCE.VMA covers the range of virtual addresses
> > between StartAaddr and Size.
> >
> >
> > +  Covers only the given ASID.
> >
> >
> > +
> >
> >
> > +  The remote fence function acts as a full tlb flush if
> > * StartAddr and size
> >
> >
> > +  are both 0 * size is equal to 2^XLEN-1
> >
> >
> > +
> >
> >
> > +  @param[in]  HartMask             Scalar bit-vector
> > containing hart ids
> >
> >
> > +  @param[in]  HartMaskBase         The starting hartid
> > from which the bit-vector
> >
> >
> > +                                   must be computed. If
> > set to -1, HartMask is
> >
> >
> > +                                   ignored and all
> > harts are considered.
> >
> >
> > +  @param[in]  StartAddr            The first address of
> > the affected range.
> >
> >
> > +  @param[in]  Size                 How many addresses
> > are affected.
> >
> >
> > +  @retval EFI_SUCCESS              IPI was sent to all
> > the targeted harts.
> >
> >
> > +  @retval EFI_LOAD_ERROR           StartAddr or Size is
> > not valid.
> >
> >
> > +  @retval EFI_INVALID_PARAMETER    Either
> > hart_mask_base or any of the hartid
> >
> >
> > +                                   from hart_mask is
> > not valid i.e. either the
> >
> >
> > +                                   hartid is not
> > enabled by the platform or is
> >
> >
> > +                                   not available to the
> > supervisor.
> >
> >
> > +**/
> >
> >
> > +EFI_STATUS
> >
> >
> > +EFIAPI
> >
> >
> > +SbiRemoteSfenceVmaAsid (
> >
> >
> > +  IN  UINTN                         *HartMask,
> >
> >
> > +  IN  UINTN                          HartMaskBase,
> >
> >
> > +  IN  UINTN                          StartAddr,
> >
> >
> > +  IN  UINTN                          Size,
> >
> >
> > +  IN  UINTN                          Asid
> >
> >
> > +  );
> >
> >
> > +
> >
> >
> > +/**
> >
> >
> > +  Instructs the remote harts to execute one or more
> > SFENCE.GVMA instructions.
> >
> >
> > +
> >
> >
> > +  The SFENCE.GVMA covers the range of virtual addresses
> > between StartAaddr and Size.
> >
> >
> > +  Covers only the given VMID.
> >
> >
> > +  This function call is only valid for harts
> > implementing the hypervisor extension.
> >
> >
> > +
> >
> >
> > +  The remote fence function acts as a full tlb flush if
> > * StartAddr and size
> >
> >
> > +  are both 0 * size is equal to 2^XLEN-1
> >
> >
> > +
> >
> >
> > +  @param[in]  HartMask             Scalar bit-vector
> > containing hart ids
> >
> >
> > +  @param[in]  HartMaskBase         The starting hartid
> > from which the bit-vector
> >
> >
> > +                                   must be computed. If
> > set to -1, HartMask is
> >
> >
> > +                                   ignored and all
> > harts are considered.
> >
> >
> > +  @param[in]  StartAddr            The first address of
> > the affected range.
> >
> >
> > +  @param[in]  Size                 How many addresses
> > are affected.
> >
> >
> > +  @retval EFI_SUCCESS              IPI was sent to all
> > the targeted harts.
> >
> >
> > +  @retval EFI_LOAD_ERROR           StartAddr or Size is
> > not valid.
> >
> >
> > +  @retval EFI_UNSUPPORTED          SBI does not
> > implement this function or one
> >
> >
> > +                                   of the target harts
> > does not support the
> >
> >
> > +                                   hypervisor
> > extension.
> >
> >
> > +  @retval EFI_INVALID_PARAMETER    Either
> > hart_mask_base or any of the hartid
> >
> >
> > +                                   from hart_mask is
> > not valid i.e. either the
> >
> >
> > +                                   hartid is not
> > enabled by the platform or is
> >
> >
> > +                                   not available to the
> > supervisor.
> >
> >
> > +**/
> >
> >
> > +EFI_STATUS
> >
> >
> > +EFIAPI
> >
> >
> > +SbiRemoteHfenceGvmaVmid (
> >
> >
> > +  IN  UINTN                         *HartMask,
> >
> >
> > +  IN  UINTN                          HartMaskBase,
> >
> >
> > +  IN  UINTN                          StartAddr,
> >
> >
> > +  IN  UINTN                          Size,
> >
> >
> > +  IN  UINTN                          Vmid
> >
> >
> > +  );
> >
> >
> > +
> >
> >
> > +/**
> >
> >
> > +  Instructs the remote harts to execute one or more
> > SFENCE.GVMA instructions.
> >
> >
> > +
> >
> >
> > +  The SFENCE.GVMA covers the range of virtual addresses
> > between StartAaddr and Size.
> >
> >
> > +  This function call is only valid for harts
> > implementing the hypervisor extension.
> >
> >
> > +
> >
> >
> > +  The remote fence function acts as a full tlb flush if
> > * StartAddr and size
> >
> >
> > +  are both 0 * size is equal to 2^XLEN-1
> >
> >
> > +
> >
> >
> > +  @param[in]  HartMask             Scalar bit-vector
> > containing hart ids
> >
> >
> > +  @param[in]  HartMaskBase         The starting hartid
> > from which the bit-vector
> >
> >
> > +                                   must be computed. If
> > set to -1, HartMask is
> >
> >
> > +                                   ignored and all
> > harts are considered.
> >
> >
> > +  @param[in]  StartAddr            The first address of
> > the affected range.
> >
> >
> > +  @param[in]  Size                 How many addresses
> > are affected.
> >
> >
> > +  @retval EFI_SUCCESS              IPI was sent to all
> > the targeted harts.
> >
> >
> > +  @retval EFI_LOAD_ERROR           StartAddr or Size is
> > not valid.
> >
> >
> > +  @retval EFI_UNSUPPORTED          SBI does not
> > implement this function or one
> >
> >
> > +                                   of the target harts
> > does not support the
> >
> >
> > +                                   hypervisor
> > extension.
> >
> >
> > +  @retval EFI_INVALID_PARAMETER    Either
> > hart_mask_base or any of the hartid
> >
> >
> > +                                   from hart_mask is
> > not valid i.e. either the
> >
> >
> > +                                   hartid is not
> > enabled by the platform or is
> >
> >
> > +                                   not available to the
> > supervisor.
> >
> >
> > +**/
> >
> >
> > +EFI_STATUS
> >
> >
> > +EFIAPI
> >
> >
> > +SbiRemoteHfenceGvma (
> >
> >
> > +  IN  UINTN                         *HartMask,
> >
> >
> > +  IN  UINTN                          HartMaskBase,
> >
> >
> > +  IN  UINTN                          StartAddr,
> >
> >
> > +  IN  UINTN                          Size
> >
> >
> > +  );
> >
> >
> > +
> >
> >
> > +/**
> >
> >
> > +  Instructs the remote harts to execute one or more
> > SFENCE.VVMA instructions.
> >
> >
> > +
> >
> >
> > +  The SFENCE.GVMA covers the range of virtual addresses
> > between StartAaddr and Size.
> >
> >
> > +  Covers only the given ASID.
> >
> >
> > +  This function call is only valid for harts
> > implementing the hypervisor extension.
> >
> >
> > +
> >
> >
> > +  The remote fence function acts as a full tlb flush if
> > * StartAddr and size
> >
> >
> > +  are both 0 * size is equal to 2^XLEN-1
> >
> >
> > +
> >
> >
> > +  @param[in]  HartMask             Scalar bit-vector
> > containing hart ids
> >
> >
> > +  @param[in]  HartMaskBase         The starting hartid
> > from which the bit-vector
> >
> >
> > +                                   must be computed. If
> > set to -1, HartMask is
> >
> >
> > +                                   ignored and all
> > harts are considered.
> >
> >
> > +  @param[in]  StartAddr            The first address of
> > the affected range.
> >
> >
> > +  @param[in]  Size                 How many addresses
> > are affected.
> >
> >
> > +  @retval EFI_SUCCESS              IPI was sent to all
> > the targeted harts.
> >
> >
> > +  @retval EFI_LOAD_ERROR           StartAddr or Size is
> > not valid.
> >
> >
> > +  @retval EFI_UNSUPPORTED          SBI does not
> > implement this function or one
> >
> >
> > +                                   of the target harts
> > does not support the
> >
> >
> > +                                   hypervisor
> > extension.
> >
> >
> > +  @retval EFI_INVALID_PARAMETER    Either
> > hart_mask_base or any of the hartid
> >
> >
> > +                                   from hart_mask is
> > not valid i.e. either the
> >
> >
> > +                                   hartid is not
> > enabled by the platform or is
> >
> >
> > +                                   not available to the
> > supervisor.
> >
> >
> > +**/
> >
> >
> > +EFI_STATUS
> >
> >
> > +EFIAPI
> >
> >
> > +SbiRemoteHfenceVvmaAsid (
> >
> >
> > +  IN  UINTN                         *HartMask,
> >
> >
> > +  IN  UINTN                          HartMaskBase,
> >
> >
> > +  IN  UINTN                          StartAddr,
> >
> >
> > +  IN  UINTN                          Size,
> >
> >
> > +  IN  UINTN                          Asid
> >
> >
> > +  );
> >
> >
> > +
> >
> >
> > +/**
> >
> >
> > +  Instructs the remote harts to execute one or more
> > SFENCE.VVMA instructions.
> >
> >
> > +
> >
> >
> > +  The SFENCE.GVMA covers the range of virtual addresses
> > between StartAaddr and Size.
> >
> >
> > +  This function call is only valid for harts
> > implementing the hypervisor extension.
> >
> >
> > +
> >
> >
> > +  The remote fence function acts as a full tlb flush if
> > * StartAddr and size
> >
> >
> > +  are both 0 * size is equal to 2^XLEN-1
> >
> >
> > +
> >
> >
> > +  @param[in]  HartMask             Scalar bit-vector
> > containing hart ids
> >
> >
> > +  @param[in]  HartMaskBase         The starting hartid
> > from which the bit-vector
> >
> >
> > +                                   must be computed. If
> > set to -1, HartMask is
> >
> >
> > +                                   ignored and all
> > harts are considered.
> >
> >
> > +  @param[in]  StartAddr            The first address of
> > the affected range.
> >
> >
> > +  @param[in]  Size                 How many addresses
> > are affected.
> >
> >
> > +  @retval EFI_SUCCESS              IPI was sent to all
> > the targeted harts.
> >
> >
> > +  @retval EFI_LOAD_ERROR           StartAddr or Size is
> > not valid.
> >
> >
> > +  @retval EFI_UNSUPPORTED          SBI does not
> > implement this function or one
> >
> >
> > +                                   of the target harts
> > does not support the
> >
> >
> > +                                   hypervisor
> > extension.
> >
> >
> > +  @retval EFI_INVALID_PARAMETER    Either
> > hart_mask_base or any of the hartid
> >
> >
> > +                                   from hart_mask is
> > not valid i.e. either the
> >
> >
> > +                                   hartid is not
> > enabled by the platform or is
> >
> >
> > +                                   not available to the
> > supervisor.
> >
> >
> > +**/
> >
> >
> > +EFI_STATUS
> >
> >
> > +EFIAPI
> >
> >
> > +SbiRemoteHfenceVvma (
> >
> >
> > +  IN  UINTN                         *HartMask,
> >
> >
> > +  IN  UINTN                          HartMaskBase,
> >
> >
> > +  IN  UINTN                          StartAddr,
> >
> >
> > +  IN  UINTN                          Size
> >
> >
> > +  );
> >
> >
> > +
> >
> >
> > +///
> >
> >
> > +/// Vendor Specific extension space: Extension Ids
> > 0x09000000 through 0x09FFFFFF
> >
> >
> > +///
> >
> >
> > +
> >
> >
> > +/**
> >
> >
> > +  Call a function in a vendor defined SBI extension
> >
> >
> > +
> >
> >
> > +  ASSERT() if the ExtensionId is not in the designated
> > SBI Vendor Extension
> >
> >
> > +  Space.
> >
> >
> > +
> >
> >
> > +  @param[in]  ExtensionId          The SBI vendor
> > extension ID.
> >
> >
> > +  @param[in]  FunctionId           The function ID to
> > call in this extension.
> >
> >
> > +  @param[in]  NumArgs              How many arguments
> > are passed.
> >
> >
> > +  @param[in]  ...                  Actual Arguments to
> > the function.
> >
> >
> > +  @retval EFI_SUCCESS if the SBI function was called
> > and it was successful
> >
> >
> > +  @retval EFI_INVALID_PARAMETER if NumArgs exceeds 6
> >
> >
> > +  @retval others if the called SBI function returns an
> > error
> >
> >
> > +**/
> >
> >
> > +EFI_STATUS
> >
> >
> > +EFIAPI
> >
> >
> > +SbiVendorCall (
> >
> >
> > +  IN  UINTN                          ExtensionId,
> >
> >
> > +  IN  UINTN                          FunctionId,
> >
> >
> > +  IN  UINTN                          NumArgs,
> >
> >
> > +  ...
> >
> >
> > +  );
> >
> >
> > +
> >
> >
> > +///
> >
> >
> > +/// Firmware SBI Extension
> >
> >
> > +///
> >
> >
> > +/// This SBI Extension is defined and used by EDK2 only
> > in order to be able to
> >
> >
> > +/// run PI and DXE phase in S-Mode.
> >
> >
> > +///
> >
> >
> > +
> >
> >
> > +/**
> >
> >
> > +  Get scratch space of the current hart.
> >
> >
> > +
> >
> >
> > +  Please consider using the wrapper
> > SbiGetFirmwareContext if you only need to
> >
> >
> > +  access the firmware context.
> >
> >
> > +
> >
> >
> > +  @param[out] ScratchSpace         The scratch space
> > pointer.
> >
> >
> > +  @retval EFI_SUCCESS              The operation
> > succeeds.
> >
> >
> > +**/
> >
> >
> > +EFI_STATUS
> >
> >
> > +EFIAPI
> >
> >
> > +SbiGetMscratch (
> >
> >
> > +  OUT SBI_SCRATCH                    **ScratchSpace
> >
> >
> > +  );
> >
> >
> > +
> >
> >
> > +/**
> >
> >
> > +  Get scratch space of the given hart id.
> >
> >
> > +
> >
> >
> > +  @param[in]  HartId               The hart id.
> >
> >
> > +  @param[out] ScratchSpace         The scratch space
> > pointer.
> >
> >
> > +  @retval EFI_SUCCESS              The operation
> > succeeds.
> >
> >
> > +**/
> >
> >
> > +EFI_STATUS
> >
> >
> > +EFIAPI
> >
> >
> > +SbiGetMscratchHartid (
> >
> >
> > +  IN  UINTN                            HartId,
> >
> >
> > +  OUT SBI_SCRATCH                    **ScratchSpace
> >
> >
> > +  );
> >
> >
> > +
> >
> >
> > +/**
> >
> >
> > +  Get firmware context of the calling hart.
> >
> >
> > +
> >
> >
> > +  @param[out] FirmwareContext      The firmware context
> > pointer.
> >
> >
> > +  @retval EFI_SUCCESS              The operation
> > succeeds.
> >
> >
> > +**/
> >
> >
> > +EFI_STATUS
> >
> >
> > +EFIAPI
> >
> >
> > +SbiGetFirmwareContext (
> >
> >
> > +  OUT EFI_RISCV_OPENSBI_FIRMWARE_CONTEXT
> > **FirmwareContext
> >
> >
> > +  );
> >
> >
> > +
> >
> >
> > +/**
> >
> >
> > +  Set firmware context of the calling hart.
> >
> >
> > +
> >
> >
> > +  @param[in] FirmwareContext       The firmware context
> > pointer.
> >
> >
> > +  @retval EFI_SUCCESS              The operation
> > succeeds.
> >
> >
> > +**/
> >
> >
> > +EFI_STATUS
> >
> >
> > +EFIAPI
> >
> >
> > +SbiSetFirmwareContext (
> >
> >
> > +  IN EFI_RISCV_OPENSBI_FIRMWARE_CONTEXT
> > *FirmwareContext
> >
> >
> > +  );
> >
> >
> > +
> >
> >
> > +#endif
> >
> >
> > diff --git a/Silicon/RISC-
> > V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.c
> > b/Silicon/RISC-
> > V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.c
> > new file mode 100644
> > index 000000000000..0df505d2675b
> > --- /dev/null
> > +++ b/Silicon/RISC-
> > V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.c
> > @@ -0,0 +1,897 @@
> > +/** @file
> >
> >
> > +  Instance of the SBI ecall library.
> >
> >
> > +
> >
> >
> > +  It allows calling an SBI function via an ecall from
> > S-Mode.
> >
> >
> > +
> >
> >
> > +  The legacy extensions are not included because they
> > are not necessary.
> >
> >
> > +  They would be:
> >
> >
> > +  - SbiLegacySetTimer            -> Use SbiSetTimer
> >
> >
> > +  - SbiLegacyConsolePutChar      -> No replacement -
> > Use regular UEFI functions
> >
> >
> > +  - SbiLegacyConsoleGetChar      -> No replacement -
> > Use regular UEFI functions
> >
> >
> > +  - SbiLegacyClearIpi            -> Write 0 to SSIP
> >
> >
> > +  - SbiLegacySendIpi             -> Use SbiSendIpi
> >
> >
> > +  - SbiLegacyRemoteFenceI        -> Use SbiRemoteFenceI
> >
> >
> > +  - SbiLegacyRemoteSfenceVma     -> Use
> > SbiRemoteSfenceVma
> >
> >
> > +  - SbiLegacyRemoteSfenceVmaAsid -> Use
> > SbiRemoteSfenceVmaAsid
> >
> >
> > +  - SbiLegacyShutdown            -> Wait for new System
> > Reset extension
> >
> >
> > +
> >
> >
> > +  Copyright (c) 2020, Hewlett Packard Development LP.
> > All rights reserved.<BR>
> >
> >
> > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> >
> >
> > +
> >
> >
> > +  @par Revision Reference:
> >
> >
> > +    - OpenSBI Version 0.6
> >
> >
> > +**/
> >
> >
> > +
> >
> >
> > +#include <IndustryStandard/RiscVOpensbi.h>
> >
> >
> > +#include <Library/BaseMemoryLib.h>
> >
> >
> > +#include <Library/DebugLib.h>
> >
> >
> > +#include <Library/RiscVEdk2SbiLib.h>
> >
> >
> > +#include <sbi/riscv_asm.h>
> >
> >
> > +#include <sbi/sbi_hart.h>
> >
> >
> > +#include <sbi/sbi_types.h>
> >
> >
> > +#include <sbi/sbi_init.h>
> >
> >
> > +
> >
> >
> > +
> >
> >
> > +//
> >
> >
> > +// Maximum arguments for SBI ecall
> >
> >
> > +// It's possible to pass more but no SBI call uses more
> > as of SBI 0.2.
> >
> >
> > +// The additional arguments would have to be passed on
> > the stack instead of as
> >
> >
> > +// registers, like it's done now.
> >
> >
> > +//
> >
> >
> > +#define SBI_CALL_MAX_ARGS 6
> >
> >
> > +
> >
> >
> > +/**
> >
> >
> > +  Call SBI call using ecall instruction.
> >
> >
> > +
> >
> >
> > +  Asserts when NumArgs exceeds SBI_CALL_MAX_ARGS.
> >
> >
> > +
> >
> >
> > +  @param[in] ExtId    SBI extension ID.
> >
> >
> > +  @param[in] FuncId   SBI function ID.
> >
> >
> > +  @param[in] NumArgs  Number of arguments to pass to
> > the ecall.
> >
> >
> > +  @param[in] ...      Argument list for the ecall.
> >
> >
> > +
> >
> >
> > +  @retval  Returns SbiRet structure with value and
> > error code.
> >
> >
> > +
> >
> >
> > +**/
> >
> >
> > +STATIC
> >
> >
> > +SbiRet
> >
> >
> > +EFIAPI
> >
> >
> > +SbiCall(
> >
> >
> > +  IN  UINTN ExtId,
> >
> >
> > +  IN  UINTN FuncId,
> >
> >
> > +  IN  UINTN NumArgs,
> >
> >
> > +  ...
> >
> >
> > +  )
> >
> >
> > +{
> >
> >
> > +    UINTN I;
> >
> >
> > +    SbiRet Ret;
> >
> >
> > +    UINTN Args[SBI_CALL_MAX_ARGS];
> >
> >
> > +    VA_LIST ArgList;
> >
> >
> > +    VA_START (ArgList, NumArgs);
> >
> >
> > +
> >
> >
> > +    ASSERT (NumArgs <= SBI_CALL_MAX_ARGS);
> >
> >
> > +
> >
> >
> > +    for (I = 0; I < SBI_CALL_MAX_ARGS; I++) {
> >
> >
> > +      if (I < NumArgs) {
> >
> >
> > +        Args[I] = VA_ARG (ArgList, UINTN);
> >
> >
> > +      } else {
> >
> >
> > +        // Default to 0 for all arguments that are not
> > given
> >
> >
> > +        Args[I] = 0;
> >
> >
> > +      }
> >
> >
> > +    }
> >
> >
> > +
> >
> >
> > +    VA_END(ArgList);
> >
> >
> > +
> >
> >
> > +    register UINTN a0 asm ("a0") = Args[0];
> >
> >
> > +    register UINTN a1 asm ("a1") = Args[1];
> >
> >
> > +    register UINTN a2 asm ("a2") = Args[2];
> >
> >
> > +    register UINTN a3 asm ("a3") = Args[3];
> >
> >
> > +    register UINTN a4 asm ("a4") = Args[4];
> >
> >
> > +    register UINTN a5 asm ("a5") = Args[5];
> >
> >
> > +    register UINTN a6 asm ("a6") = (UINTN)(FuncId);
> >
> >
> > +    register UINTN a7 asm ("a7") = (UINTN)(ExtId);
> >
> >
> > +    asm volatile ("ecall" \
> >
> >
> > +         : "+r" (a0), "+r" (a1) \
> >
> >
> > +         : "r" (a2), "r" (a3), "r" (a4), "r" (a5), "r"
> > (a6), "r" (a7) \
> >
> >
> > +         : "memory"); \
> >
> >
> > +    Ret.Error = a0;
> >
> >
> > +    Ret.Value = a1;
> >
> >
> > +    return Ret;
> >
> >
> > +}
> >
> >
> > +
> >
> >
> > +/**
> >
> >
> > +  Translate SBI error code to EFI status.
> >
> >
> > +
> >
> >
> > +  @param[in] SbiError   SBI error code
> >
> >
> > +  @retval EFI_STATUS
> >
> >
> > +**/
> >
> >
> > +
> >
> >
> > +STATIC
> >
> >
> > +EFI_STATUS
> >
> >
> > +EFIAPI
> >
> >
> > +TranslateError(
> >
> >
> > +  IN  UINTN SbiError
> >
> >
> > +  )
> >
> >
> > +{
> >
> >
> > +  switch (SbiError) {
> >
> >
> > +    case SBI_SUCCESS:
> >
> >
> > +      return EFI_SUCCESS;
> >
> >
> > +    case SBI_ERR_FAILED:
> >
> >
> > +      return EFI_DEVICE_ERROR;
> >
> >
> > +      break;
> >
> >
> > +    case SBI_ERR_NOT_SUPPORTED:
> >
> >
> > +      return EFI_UNSUPPORTED;
> >
> >
> > +      break;
> >
> >
> > +    case SBI_ERR_INVALID_PARAM:
> >
> >
> > +      return EFI_INVALID_PARAMETER;
> >
> >
> > +      break;
> >
> >
> > +    case SBI_ERR_DENIED:
> >
> >
> > +      return EFI_ACCESS_DENIED;
> >
> >
> > +      break;
> >
> >
> > +    case SBI_ERR_INVALID_ADDRESS:
> >
> >
> > +      return EFI_LOAD_ERROR;
> >
> >
> > +      break;
> >
> >
> > +    case SBI_ERR_ALREADY_AVAILABLE:
> >
> >
> > +      return EFI_ALREADY_STARTED;
> >
> >
> > +      break;
> >
> >
> > +    default:
> >
> >
> > +      //
> >
> >
> > +      // Reaches here only if SBI has defined a new
> > error type
> >
> >
> > +      //
> >
> >
> > +      ASSERT (FALSE);
> >
> >
> > +      return EFI_UNSUPPORTED;
> >
> >
> > +      break;
> >
> >
> > +  }
> >
> >
> > +}
> >
> >
> > +
> >
> >
> > +//
> >
> >
> > +// OpenSBI library interface function for the base
> > extension
> >
> >
> > +//
> >
> >
> > +
> >
> >
> > +/**
> >
> >
> > +  Get the implemented SBI specification version
> >
> >
> > +
> >
> >
> > +  The minor number of the SBI specification is encoded
> > in the low 24 bits,
> >
> >
> > +  with the major number encoded in the next 7 bits.
> > Bit 32 must be 0 and is
> >
> >
> > +  reserved for future expansion.
> >
> >
> > +
> >
> >
> > +  @param[out] SpecVersion          The Version of the
> > SBI specification.
> >
> >
> > +**/
> >
> >
> > +VOID
> >
> >
> > +EFIAPI
> >
> >
> > +SbiGetSpecVersion (
> >
> >
> > +  OUT UINTN                       *SpecVersion
> >
> >
> > +  )
> >
> >
> > +{
> >
> >
> > +  SbiRet Ret = SbiCall (SBI_EXT_BASE,
> > SBI_EXT_BASE_GET_SPEC_VERSION, 0);
> >
> >
> > +
> >
> >
> > +  if (!Ret.Error) {
> >
> >
> > +    *SpecVersion = (UINTN)Ret.Value;
> >
> >
> > +  }
> >
> >
> > +}
> >
> >
> > +
> >
> >
> > +/**
> >
> >
> > +  Get the SBI implementation ID
> >
> >
> > +
> >
> >
> > +  This ID is used to idenetify a specific SBI
> > implementation in order to work
> >
> >
> > +  around any quirks it might have.
> >
> >
> > +
> >
> >
> > +  @param[out] ImplId               The ID of the SBI
> > implementation.
> >
> >
> > +**/
> >
> >
> > +VOID
> >
> >
> > +EFIAPI
> >
> >
> > +SbiGetImplId (
> >
> >
> > +  OUT UINTN                       *ImplId
> >
> >
> > +  )
> >
> >
> > +{
> >
> >
> > +  SbiRet Ret = SbiCall (SBI_EXT_BASE,
> > SBI_EXT_BASE_GET_IMP_ID, 0);
> >
> >
> > +  *ImplId = (UINTN)Ret.Value;
> >
> >
> > +}
> >
> >
> > +
> >
> >
> > +/**
> >
> >
> > +  Get the SBI implementation version
> >
> >
> > +
> >
> >
> > +  The version of this SBI implementation.
> >
> >
> > +  The encoding of this number is determined by the
> > specific SBI implementation.
> >
> >
> > +
> >
> >
> > +  @param[out] ImplVersion          The version of the
> > SBI implementation.
> >
> >
> > +**/
> >
> >
> > +VOID
> >
> >
> > +EFIAPI
> >
> >
> > +SbiGetImplVersion (
> >
> >
> > +  OUT UINTN                       *ImplVersion
> >
> >
> > +  )
> >
> >
> > +{
> >
> >
> > +  SbiRet Ret = SbiCall (SBI_EXT_BASE,
> > SBI_EXT_BASE_GET_IMP_VERSION, 0);
> >
> >
> > +  *ImplVersion = (UINTN)Ret.Value;
> >
> >
> > +}
> >
> >
> > +
> >
> >
> > +/**
> >
> >
> > +  Probe whether an SBI extension is available
> >
> >
> > +
> >
> >
> > +  ProbeResult is set to 0 if the extension is not
> > available or to an extension
> >
> >
> > +  specified value if it is available.
> >
> >
> > +
> >
> >
> > +  @param[in]  ExtensionId          The extension ID.
> >
> >
> > +  @param[out] ProbeResult          The return value of
> > the probe.
> >
> >
> > +**/
> >
> >
> > +VOID
> >
> >
> > +EFIAPI
> >
> >
> > +SbiProbeExtension (
> >
> >
> > +  IN  INTN                         ExtensionId,
> >
> >
> > +  OUT INTN                        *ProbeResult
> >
> >
> > +  )
> >
> >
> > +{
> >
> >
> > +  SbiRet Ret = SbiCall (SBI_EXT_BASE,
> > SBI_EXT_BASE_PROBE_EXT, 0);
> >
> >
> > +  *ProbeResult = (UINTN)Ret.Value;
> >
> >
> > +}
> >
> >
> > +
> >
> >
> > +/**
> >
> >
> > +  Get the CPU's vendor ID
> >
> >
> > +
> >
> >
> > +  Reads the mvendorid CSR.
> >
> >
> > +
> >
> >
> > +  @param[out] MachineVendorId      The CPU's vendor ID.
> >
> >
> > +**/
> >
> >
> > +VOID
> >
> >
> > +EFIAPI
> >
> >
> > +SbiGetMachineVendorId (
> >
> >
> > +  OUT UINTN                       *MachineVendorId
> >
> >
> > +  )
> >
> >
> > +{
> >
> >
> > +  SbiRet Ret = SbiCall (SBI_EXT_BASE,
> > SBI_EXT_BASE_GET_MVENDORID, 0);
> >
> >
> > +  *MachineVendorId = (UINTN)Ret.Value;
> >
> >
> > +}
> >
> >
> > +
> >
> >
> > +/**
> >
> >
> > +  Get the CPU's architecture ID
> >
> >
> > +
> >
> >
> > +  Reads the marchid CSR.
> >
> >
> > +
> >
> >
> > +  @param[out] MachineArchId        The CPU's
> > architecture ID.
> >
> >
> > +**/
> >
> >
> > +VOID
> >
> >
> > +EFIAPI
> >
> >
> > +SbiGetMachineArchId (
> >
> >
> > +  OUT UINTN                       *MachineArchId
> >
> >
> > +  )
> >
> >
> > +{
> >
> >
> > +  SbiRet Ret = SbiCall (SBI_EXT_BASE,
> > SBI_EXT_BASE_GET_MARCHID, 0);
> >
> >
> > +  *MachineArchId = (UINTN)Ret.Value;
> >
> >
> > +}
> >
> >
> > +
> >
> >
> > +/**
> >
> >
> > +  Get the CPU's architecture ID
> >
> >
> > +
> >
> >
> > +  Reads the marchid CSR.
> >
> >
> > +
> >
> >
> > +  @param[out] MachineImplId        The CPU's
> > implementation ID.
> >
> >
> > +**/
> >
> >
> > +VOID
> >
> >
> > +EFIAPI
> >
> >
> > +SbiGetMachineImplId (
> >
> >
> > +  OUT UINTN                       *MachineImplId
> >
> >
> > +  )
> >
> >
> > +{
> >
> >
> > +  SbiRet Ret = SbiCall (SBI_EXT_BASE,
> > SBI_EXT_BASE_GET_MIMPID, 0);
> >
> >
> > +  *MachineImplId = (UINTN)Ret.Value;
> >
> >
> > +}
> >
> >
> > +
> >
> >
> > +//
> >
> >
> > +// SBI interface function for the hart state management
> > extension
> >
> >
> > +//
> >
> >
> > +
> >
> >
> > +/**
> >
> >
> > +  Politely ask the SBI to start a given hart.
> >
> >
> > +
> >
> >
> > +  This call may return before the hart has actually
> > started executing, if the
> >
> >
> > +  SBI implementation can guarantee that the hart is
> > actually going to start.
> >
> >
> > +
> >
> >
> > +  Before the hart jumps to StartAddr, the hart MUST
> > configure PMP if present
> >
> >
> > +  and switch to S-mode.
> >
> >
> > +
> >
> >
> > +  @param[in]  HartId               The id of the hart
> > to start.
> >
> >
> > +  @param[in]  StartAddr            The physical
> > address, where the hart starts
> >
> >
> > +                                   executing from.
> >
> >
> > +  @param[in]  Priv                 An XLEN-bit value,
> > which will be in register
> >
> >
> > +                                   a1 when the hart
> > starts.
> >
> >
> > +  @retval EFI_SUCCESS              Hart was stopped and
> > will start executing from StartAddr.
> >
> >
> > +  @retval EFI_LOAD_ERROR           StartAddr is not
> > valid, possibly due to following reasons:
> >
> >
> > +                                     - It is not a
> > valid physical address.
> >
> >
> > +                                     - The address is
> > prohibited by PMP to run in
> >
> >
> > +                                       supervisor mode.
> >
> >
> > +  @retval EFI_INVALID_PARAMETER    HartId is not a
> > valid hart id
> >
> >
> > +  @retval EFI_ALREADY_STARTED      The hart is already
> > running.
> >
> >
> > +  @retval other                    The start request
> > failed for unknown reasons.
> >
> >
> > +**/
> >
> >
> > +EFI_STATUS
> >
> >
> > +EFIAPI
> >
> >
> > +SbiHartStart (
> >
> >
> > +  IN  UINTN                          HartId,
> >
> >
> > +  IN  UINTN                          StartAddr,
> >
> >
> > +  IN  UINTN                          Priv
> >
> >
> > +  )
> >
> >
> > +{
> >
> >
> > +  SbiRet Ret = SbiCall (
> >
> >
> > +                 SBI_EXT_HSM,
> >
> >
> > +                 SBI_EXT_HSM_HART_START,
> >
> >
> > +                 3,
> >
> >
> > +                 HartId,
> >
> >
> > +                 StartAddr,
> >
> >
> > +                 Priv
> >
> >
> > +                 );
> >
> >
> > +  return TranslateError (Ret.Error);
> >
> >
> > +}
> >
> >
> > +
> >
> >
> > +/**
> >
> >
> > +  Return execution of the calling hart to SBI.
> >
> >
> > +
> >
> >
> > +  MUST be called in S-Mode with user interrupts
> > disabled.
> >
> >
> > +  This call is not expected to return, unless a failure
> > occurs.
> >
> >
> > +
> >
> >
> > +  @retval     EFI_SUCCESS          Never occurs. When
> > successful, the call does not return.
> >
> >
> > +  @retval     other                Failed to stop hard
> > for an unknown reason.
> >
> >
> > +**/
> >
> >
> > +EFI_STATUS
> >
> >
> > +EFIAPI
> >
> >
> > +SbiHartStop (
> >
> >
> > +  )
> >
> >
> > +{
> >
> >
> > +  SbiRet Ret = SbiCall (SBI_EXT_HSM,
> > SBI_EXT_HSM_HART_STOP, 0);
> >
> >
> > +  return TranslateError (Ret.Error);
> >
> >
> > +}
> >
> >
> > +
> >
> >
> > +/**
> >
> >
> > +  Get the current status of a hart.
> >
> >
> > +
> >
> >
> > +  Since harts can transition between states at any
> > time, the status retrieved
> >
> >
> > +  by this function may already be out of date, once it
> > returns.
> >
> >
> > +
> >
> >
> > +  Possible values for HartStatus are:
> >
> >
> > +  0: STARTED
> >
> >
> > +  1: STOPPED
> >
> >
> > +  2: START_REQUEST_PENDING
> >
> >
> > +  3: STOP_REQUEST_PENDING
> >
> >
> > +
> >
> >
> > +  @param[out] HartStatus           The pointer in which
> > the hart's status is
> >
> >
> > +                                   stored.
> >
> >
> > +  @retval EFI_SUCCESS              The operation
> > succeeds.
> >
> >
> > +  @retval EFI_INVALID_PARAMETER    A parameter is
> > invalid.
> >
> >
> > +**/
> >
> >
> > +EFI_STATUS
> >
> >
> > +EFIAPI
> >
> >
> > +SbiHartGetStatus (
> >
> >
> > +  IN  UINTN                          HartId,
> >
> >
> > +  OUT UINTN                         *HartStatus
> >
> >
> > +  )
> >
> >
> > +{
> >
> >
> > +  SbiRet Ret = SbiCall (SBI_EXT_HSM,
> > SBI_EXT_HSM_HART_GET_STATUS, 1, HartId);
> >
> >
> > +
> >
> >
> > +  if (!Ret.Error) {
> >
> >
> > +    *HartStatus = (UINTN)Ret.Value;
> >
> >
> > +  }
> >
> >
> > +
> >
> >
> > +  return TranslateError (Ret.Error);
> >
> >
> > +}
> >
> >
> > +
> >
> >
> > +/**
> >
> >
> > +  Clear pending timer interrupt bit and set timer for
> > next event after Time.
> >
> >
> > +
> >
> >
> > +  To clear the timer without scheduling a timer event,
> > set Time to a
> >
> >
> > +  practically infinite value or mask the timer
> > interrupt by clearing sie.STIE.
> >
> >
> > +
> >
> >
> > +  @param[in]  Time                 The time offset to
> > the next scheduled timer interrupt.
> >
> >
> > +**/
> >
> >
> > +VOID
> >
> >
> > +EFIAPI
> >
> >
> > +SbiSetTimer (
> >
> >
> > +  IN  UINT64                         Time
> >
> >
> > +  )
> >
> >
> > +{
> >
> >
> > +  SbiCall (SBI_EXT_TIME, SBI_EXT_TIME_SET_TIMER, 1,
> > Time);
> >
> >
> > +}
> >
> >
> > +
> >
> >
> > +EFI_STATUS
> >
> >
> > +EFIAPI
> >
> >
> > +SbiSendIpi (
> >
> >
> > +  IN  UINTN                         *HartMask,
> >
> >
> > +  IN  UINTN                          HartMaskBase
> >
> >
> > +  )
> >
> >
> > +{
> >
> >
> > +  SbiRet Ret = SbiCall (
> >
> >
> > +                 SBI_EXT_IPI,
> >
> >
> > +                 SBI_EXT_IPI_SEND_IPI,
> >
> >
> > +                 2,
> >
> >
> > +                 (UINTN)HartMask,
> >
> >
> > +                 HartMaskBase
> >
> >
> > +                 );
> >
> >
> > +  return TranslateError (Ret.Error);
> >
> >
> > +}
> >
> >
> > +
> >
> >
> > +/**
> >
> >
> > +  Instructs remote harts to execute a FENCE.I
> > instruction.
> >
> >
> > +
> >
> >
> > +  @param[in]  HartMask             Scalar bit-vector
> > containing hart ids
> >
> >
> > +  @param[in]  HartMaskBase         The starting hartid
> > from which the bit-vector
> >
> >
> > +                                   must be computed. If
> > set to -1, HartMask is
> >
> >
> > +                                   ignored and all
> > harts are considered.
> >
> >
> > +  @retval EFI_SUCCESS              IPI was sent to all
> > the targeted harts.
> >
> >
> > +  @retval EFI_INVALID_PARAMETER    Either
> > hart_mask_base or any of the hartid
> >
> >
> > +                                   from hart_mask is
> > not valid i.e. either the
> >
> >
> > +                                   hartid is not
> > enabled by the platform or is
> >
> >
> > +                                   not available to the
> > supervisor.
> >
> >
> > +**/
> >
> >
> > +EFI_STATUS
> >
> >
> > +EFIAPI
> >
> >
> > +SbiRemoteFenceI (
> >
> >
> > +  IN  UINTN                         *HartMask,
> >
> >
> > +  IN  UINTN                          HartMaskBase
> >
> >
> > +  )
> >
> >
> > +{
> >
> >
> > +  SbiRet Ret = SbiCall (
> >
> >
> > +                 SBI_EXT_RFENCE,
> >
> >
> > +                 SBI_EXT_RFENCE_REMOTE_FENCE_I,
> >
> >
> > +                 2,
> >
> >
> > +                 (UINTN)HartMask,
> >
> >
> > +                 HartMaskBase
> >
> >
> > +                 );
> >
> >
> > +  return TranslateError (Ret.Error);
> >
> >
> > +}
> >
> >
> > +
> >
> >
> > +/**
> >
> >
> > +  Instructs the remote harts to execute one or more
> > SFENCE.VMA instructions.
> >
> >
> > +
> >
> >
> > +  The SFENCE.VMA covers the range of virtual addresses
> > between StartAaddr and Size.
> >
> >
> > +
> >
> >
> > +  The remote fence function acts as a full tlb flush if
> > * StartAddr and size
> >
> >
> > +  are both 0 * size is equal to 2^XLEN-1
> >
> >
> > +
> >
> >
> > +  @param[in]  HartMask             Scalar bit-vector
> > containing hart ids
> >
> >
> > +  @param[in]  HartMaskBase         The starting hartid
> > from which the bit-vector
> >
> >
> > +                                   must be computed. If
> > set to -1, HartMask is
> >
> >
> > +                                   ignored and all
> > harts are considered.
> >
> >
> > +  @param[in]  StartAddr            The first address of
> > the affected range.
> >
> >
> > +  @param[in]  Size                 How many addresses
> > are affected.
> >
> >
> > +  @retval EFI_SUCCESS              IPI was sent to all
> > the targeted harts.
> >
> >
> > +  @retval EFI_LOAD_ERROR           StartAddr or Size is
> > not valid.
> >
> >
> > +  @retval EFI_INVALID_PARAMETER    Either
> > hart_mask_base or any of the hartid
> >
> >
> > +                                   from hart_mask is
> > not valid i.e. either the
> >
> >
> > +                                   hartid is not
> > enabled by the platform or is
> >
> >
> > +                                   not available to the
> > supervisor.
> >
> >
> > +**/
> >
> >
> > +EFI_STATUS
> >
> >
> > +EFIAPI
> >
> >
> > +SbiRemoteSfenceVma (
> >
> >
> > +  IN  UINTN                         *HartMask,
> >
> >
> > +  IN  UINTN                          HartMaskBase,
> >
> >
> > +  IN  UINTN                          StartAddr,
> >
> >
> > +  IN  UINTN                          Size
> >
> >
> > +  )
> >
> >
> > +{
> >
> >
> > +  SbiRet Ret = SbiCall (
> >
> >
> > +                 SBI_EXT_RFENCE,
> >
> >
> > +                 SBI_EXT_RFENCE_REMOTE_SFENCE_VMA,
> >
> >
> > +                 4,
> >
> >
> > +                 (UINTN)HartMask,
> >
> >
> > +                 HartMaskBase,
> >
> >
> > +                 StartAddr,
> >
> >
> > +                 Size
> >
> >
> > +                 );
> >
> >
> > +  return TranslateError (Ret.Error);
> >
> >
> > +}
> >
> >
> > +
> >
> >
> > +/**
> >
> >
> > +  Instructs the remote harts to execute one or more
> > SFENCE.VMA instructions.
> >
> >
> > +
> >
> >
> > +  The SFENCE.VMA covers the range of virtual addresses
> > between StartAaddr and Size.
> >
> >
> > +  Covers only the given ASID.
> >
> >
> > +
> >
> >
> > +  The remote fence function acts as a full tlb flush if
> > * StartAddr and size
> >
> >
> > +  are both 0 * size is equal to 2^XLEN-1
> >
> >
> > +
> >
> >
> > +  @param[in]  HartMask             Scalar bit-vector
> > containing hart ids
> >
> >
> > +  @param[in]  HartMaskBase         The starting hartid
> > from which the bit-vector
> >
> >
> > +                                   must be computed. If
> > set to -1, HartMask is
> >
> >
> > +                                   ignored and all
> > harts are considered.
> >
> >
> > +  @param[in]  StartAddr            The first address of
> > the affected range.
> >
> >
> > +  @param[in]  Size                 How many addresses
> > are affected.
> >
> >
> > +  @retval EFI_SUCCESS              IPI was sent to all
> > the targeted harts.
> >
> >
> > +  @retval EFI_LOAD_ERROR           StartAddr or Size is
> > not valid.
> >
> >
> > +  @retval EFI_INVALID_PARAMETER    Either
> > hart_mask_base or any of the hartid
> >
> >
> > +                                   from hart_mask is
> > not valid i.e. either the
> >
> >
> > +                                   hartid is not
> > enabled by the platform or is
> >
> >
> > +                                   not available to the
> > supervisor.
> >
> >
> > +**/
> >
> >
> > +EFI_STATUS
> >
> >
> > +EFIAPI
> >
> >
> > +SbiRemoteSfenceVmaAsid (
> >
> >
> > +  IN  UINTN                         *HartMask,
> >
> >
> > +  IN  UINTN                          HartMaskBase,
> >
> >
> > +  IN  UINTN                          StartAddr,
> >
> >
> > +  IN  UINTN                          Size,
> >
> >
> > +  IN  UINTN                          Asid
> >
> >
> > +  )
> >
> >
> > +{
> >
> >
> > +  SbiRet Ret = SbiCall (
> >
> >
> > +                 SBI_EXT_RFENCE,
> >
> >
> > +                 SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID,
> >
> >
> > +                 5,
> >
> >
> > +                 (UINTN)HartMask,
> >
> >
> > +                 HartMaskBase,
> >
> >
> > +                 StartAddr,
> >
> >
> > +                 Size,
> >
> >
> > +                 Asid
> >
> >
> > +                 );
> >
> >
> > +  return TranslateError (Ret.Error);
> >
> >
> > +}
> >
> >
> > +
> >
> >
> > +/**
> >
> >
> > +  Instructs the remote harts to execute one or more
> > SFENCE.GVMA instructions.
> >
> >
> > +
> >
> >
> > +  The SFENCE.GVMA covers the range of virtual addresses
> > between StartAaddr and Size.
> >
> >
> > +  Covers only the given VMID.
> >
> >
> > +  This function call is only valid for harts
> > implementing the hypervisor extension.
> >
> >
> > +
> >
> >
> > +  The remote fence function acts as a full tlb flush if
> > * StartAddr and size
> >
> >
> > +  are both 0 * size is equal to 2^XLEN-1
> >
> >
> > +
> >
> >
> > +  @param[in]  HartMask             Scalar bit-vector
> > containing hart ids
> >
> >
> > +  @param[in]  HartMaskBase         The starting hartid
> > from which the bit-vector
> >
> >
> > +                                   must be computed. If
> > set to -1, HartMask is
> >
> >
> > +                                   ignored and all
> > harts are considered.
> >
> >
> > +  @param[in]  StartAddr            The first address of
> > the affected range.
> >
> >
> > +  @param[in]  Size                 How many addresses
> > are affected.
> >
> >
> > +  @retval EFI_SUCCESS              IPI was sent to all
> > the targeted harts.
> >
> >
> > +  @retval EFI_LOAD_ERROR           StartAddr or Size is
> > not valid.
> >
> >
> > +  @retval EFI_UNSUPPORTED          SBI does not
> > implement this function or one
> >
> >
> > +                                   of the target harts
> > does not support the
> >
> >
> > +                                   hypervisor
> > extension.
> >
> >
> > +  @retval EFI_INVALID_PARAMETER    Either
> > hart_mask_base or any of the hartid
> >
> >
> > +                                   from hart_mask is
> > not valid i.e. either the
> >
> >
> > +                                   hartid is not
> > enabled by the platform or is
> >
> >
> > +                                   not available to the
> > supervisor.
> >
> >
> > +**/
> >
> >
> > +EFI_STATUS
> >
> >
> > +EFIAPI
> >
> >
> > +SbiRemoteHFenceGvmaVmid (
> >
> >
> > +  IN  UINTN                         *HartMask,
> >
> >
> > +  IN  UINTN                          HartMaskBase,
> >
> >
> > +  IN  UINTN                          StartAddr,
> >
> >
> > +  IN  UINTN                          Size,
> >
> >
> > +  IN  UINTN                          Vmid
> >
> >
> > +  )
> >
> >
> > +{
> >
> >
> > +  SbiRet Ret = SbiCall (
> >
> >
> > +                 SBI_EXT_RFENCE,
> >
> >
> > +                 SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA,
> >
> >
> > +                 5,
> >
> >
> > +                 (UINTN)HartMask,
> >
> >
> > +                 HartMaskBase,
> >
> >
> > +                 StartAddr,
> >
> >
> > +                 Size,
> >
> >
> > +                 Vmid
> >
> >
> > +                 );
> >
> >
> > +  return TranslateError (Ret.Error);
> >
> >
> > +}
> >
> >
> > +
> >
> >
> > +/**
> >
> >
> > +  Instructs the remote harts to execute one or more
> > SFENCE.GVMA instructions.
> >
> >
> > +
> >
> >
> > +  The SFENCE.GVMA covers the range of virtual addresses
> > between StartAaddr and Size.
> >
> >
> > +  This function call is only valid for harts
> > implementing the hypervisor extension.
> >
> >
> > +
> >
> >
> > +  The remote fence function acts as a full tlb flush if
> > * StartAddr and size
> >
> >
> > +  are both 0 * size is equal to 2^XLEN-1
> >
> >
> > +
> >
> >
> > +  @param[in]  HartMask             Scalar bit-vector
> > containing hart ids
> >
> >
> > +  @param[in]  HartMaskBase         The starting hartid
> > from which the bit-vector
> >
> >
> > +                                   must be computed. If
> > set to -1, HartMask is
> >
> >
> > +                                   ignored and all
> > harts are considered.
> >
> >
> > +  @param[in]  StartAddr            The first address of
> > the affected range.
> >
> >
> > +  @param[in]  Size                 How many addresses
> > are affected.
> >
> >
> > +  @retval EFI_SUCCESS              IPI was sent to all
> > the targeted harts.
> >
> >
> > +  @retval EFI_LOAD_ERROR           StartAddr or Size is
> > not valid.
> >
> >
> > +  @retval EFI_UNSUPPORTED          SBI does not
> > implement this function or one
> >
> >
> > +                                   of the target harts
> > does not support the
> >
> >
> > +                                   hypervisor
> > extension.
> >
> >
> > +  @retval EFI_INVALID_PARAMETER    Either
> > hart_mask_base or any of the hartid
> >
> >
> > +                                   from hart_mask is
> > not valid i.e. either the
> >
> >
> > +                                   hartid is not
> > enabled by the platform or is
> >
> >
> > +                                   not available to the
> > supervisor.
> >
> >
> > +**/
> >
> >
> > +EFI_STATUS
> >
> >
> > +EFIAPI
> >
> >
> > +SbiRemoteHFenceGvma (
> >
> >
> > +  IN  UINTN                         *HartMask,
> >
> >
> > +  IN  UINTN                          HartMaskBase,
> >
> >
> > +  IN  UINTN                          StartAddr,
> >
> >
> > +  IN  UINTN                          Size
> >
> >
> > +  )
> >
> >
> > +{
> >
> >
> > +  SbiRet Ret = SbiCall (
> >
> >
> > +                 SBI_EXT_RFENCE,
> >
> >
> > +
> > SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA_VMID,
> >
> >
> > +                 4,
> >
> >
> > +                 (UINTN)HartMask,
> >
> >
> > +                 HartMaskBase,
> >
> >
> > +                 StartAddr,
> >
> >
> > +                 Size
> >
> >
> > +                 );
> >
> >
> > +  return TranslateError (Ret.Error);
> >
> >
> > +}
> >
> >
> > +
> >
> >
> > +/**
> >
> >
> > +  Instructs the remote harts to execute one or more
> > SFENCE.VVMA instructions.
> >
> >
> > +
> >
> >
> > +  The SFENCE.GVMA covers the range of virtual addresses
> > between StartAaddr and Size.
> >
> >
> > +  Covers only the given ASID.
> >
> >
> > +  This function call is only valid for harts
> > implementing the hypervisor extension.
> >
> >
> > +
> >
> >
> > +  The remote fence function acts as a full tlb flush if
> > * StartAddr and size
> >
> >
> > +  are both 0 * size is equal to 2^XLEN-1
> >
> >
> > +
> >
> >
> > +  @param[in]  HartMask             Scalar bit-vector
> > containing hart ids
> >
> >
> > +  @param[in]  HartMaskBase         The starting hartid
> > from which the bit-vector
> >
> >
> > +                                   must be computed. If
> > set to -1, HartMask is
> >
> >
> > +                                   ignored and all
> > harts are considered.
> >
> >
> > +  @param[in]  StartAddr            The first address of
> > the affected range.
> >
> >
> > +  @param[in]  Size                 How many addresses
> > are affected.
> >
> >
> > +  @retval EFI_SUCCESS              IPI was sent to all
> > the targeted harts.
> >
> >
> > +  @retval EFI_LOAD_ERROR           StartAddr or Size is
> > not valid.
> >
> >
> > +  @retval EFI_UNSUPPORTED          SBI does not
> > implement this function or one
> >
> >
> > +                                   of the target harts
> > does not support the
> >
> >
> > +                                   hypervisor
> > extension.
> >
> >
> > +  @retval EFI_INVALID_PARAMETER    Either
> > hart_mask_base or any of the hartid
> >
> >
> > +                                   from hart_mask is
> > not valid i.e. either the
> >
> >
> > +                                   hartid is not
> > enabled by the platform or is
> >
> >
> > +                                   not available to the
> > supervisor.
> >
> >
> > +**/
> >
> >
> > +EFI_STATUS
> >
> >
> > +EFIAPI
> >
> >
> > +SbiRemoteHFenceVvmaAsid (
> >
> >
> > +  IN  UINTN                         *HartMask,
> >
> >
> > +  IN  UINTN                          HartMaskBase,
> >
> >
> > +  IN  UINTN                          StartAddr,
> >
> >
> > +  IN  UINTN                          Size,
> >
> >
> > +  IN  UINTN                          Asid
> >
> >
> > +  )
> >
> >
> > +{
> >
> >
> > +  SbiRet Ret = SbiCall (
> >
> >
> > +                 SBI_EXT_RFENCE,
> >
> >
> > +                 SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA,
> >
> >
> > +                 5,
> >
> >
> > +                 (UINTN)HartMask,
> >
> >
> > +                 HartMaskBase,
> >
> >
> > +                 StartAddr,
> >
> >
> > +                 Size,
> >
> >
> > +                 Asid
> >
> >
> > +                 );
> >
> >
> > +  return TranslateError (Ret.Error);
> >
> >
> > +}
> >
> >
> > +
> >
> >
> > +/**
> >
> >
> > +  Instructs the remote harts to execute one or more
> > SFENCE.VVMA instructions.
> >
> >
> > +
> >
> >
> > +  The SFENCE.GVMA covers the range of virtual addresses
> > between StartAaddr and Size.
> >
> >
> > +  This function call is only valid for harts
> > implementing the hypervisor extension.
> >
> >
> > +
> >
> >
> > +  The remote fence function acts as a full tlb flush if
> > * StartAddr and size
> >
> >
> > +  are both 0 * size is equal to 2^XLEN-1
> >
> >
> > +
> >
> >
> > +  @param[in]  HartMask             Scalar bit-vector
> > containing hart ids
> >
> >
> > +  @param[in]  HartMaskBase         The starting hartid
> > from which the bit-vector
> >
> >
> > +                                   must be computed. If
> > set to -1, HartMask is
> >
> >
> > +                                   ignored and all
> > harts are considered.
> >
> >
> > +  @param[in]  StartAddr            The first address of
> > the affected range.
> >
> >
> > +  @param[in]  Size                 How many addresses
> > are affected.
> >
> >
> > +  @retval EFI_SUCCESS              IPI was sent to all
> > the targeted harts.
> >
> >
> > +  @retval EFI_LOAD_ERROR           StartAddr or Size is
> > not valid.
> >
> >
> > +  @retval EFI_UNSUPPORTED          SBI does not
> > implement this function or one
> >
> >
> > +                                   of the target harts
> > does not support the
> >
> >
> > +                                   hypervisor
> > extension.
> >
> >
> > +  @retval EFI_INVALID_PARAMETER    Either
> > hart_mask_base or any of the hartid
> >
> >
> > +                                   from hart_mask is
> > not valid i.e. either the
> >
> >
> > +                                   hartid is not
> > enabled by the platform or is
> >
> >
> > +                                   not available to the
> > supervisor.
> >
> >
> > +**/
> >
> >
> > +EFI_STATUS
> >
> >
> > +EFIAPI
> >
> >
> > +SbiRemoteHFenceVvma (
> >
> >
> > +  IN  UINTN                         *HartMask,
> >
> >
> > +  IN  UINTN                          HartMaskBase,
> >
> >
> > +  IN  UINTN                          StartAddr,
> >
> >
> > +  IN  UINTN                          Size
> >
> >
> > +  )
> >
> >
> > +{
> >
> >
> > +  SbiRet Ret = SbiCall (
> >
> >
> > +                 SBI_EXT_RFENCE,
> >
> >
> > +
> > SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA_ASID,
> >
> >
> > +                 4,
> >
> >
> > +                 (UINTN)HartMask,
> >
> >
> > +                 HartMaskBase,
> >
> >
> > +                 StartAddr,
> >
> >
> > +                 Size
> >
> >
> > +                 );
> >
> >
> > +  return TranslateError (Ret.Error);
> >
> >
> > +}
> >
> >
> > +
> >
> >
> > +//
> >
> >
> > +// SBI interface function for the vendor extension
> >
> >
> > +//
> >
> >
> > +
> >
> >
> > +/**
> >
> >
> > +  Call a function in a vendor defined SBI extension
> >
> >
> > +
> >
> >
> > +  ASSERT() if the ExtensionId is not in the designated
> > SBI Vendor Extension
> >
> >
> > +  Space or NumArgs exceeds SBI_CALL_MAX_ARGS.
> >
> >
> > +
> >
> >
> > +  @param[in]  ExtensionId          The SBI vendor
> > extension ID.
> >
> >
> > +  @param[in]  FunctionId           The function ID to
> > call in this extension.
> >
> >
> > +  @param[in]  NumArgs              How many arguments
> > are passed.
> >
> >
> > +  @param[in]  ...                  Actual Arguments to
> > the function.
> >
> >
> > +  @retval EFI_SUCCESS if the SBI function was called
> > and it was successful
> >
> >
> > +  @retval others if the called SBI function returns an
> > error
> >
> >
> > +**/
> >
> >
> > +EFI_STATUS
> >
> >
> > +EFIAPI
> >
> >
> > +SbiVendorCall (
> >
> >
> > +  IN  UINTN                          ExtensionId,
> >
> >
> > +  IN  UINTN                          FunctionId,
> >
> >
> > +  IN  UINTN                          NumArgs,
> >
> >
> > +  ...
> >
> >
> > +  )
> >
> >
> > +{
> >
> >
> > +    SbiRet Ret;
> >
> >
> > +    VA_LIST Args;
> >
> >
> > +    VA_START (Args, NumArgs);
> >
> >
> > +
> >
> >
> > +    ASSERT (ExtensionId >= SBI_EXT_VENDOR_START &&
> > ExtensionId <= SBI_EXT_VENDOR_END);
> >
> >
> > +    ASSERT (NumArgs <= SBI_CALL_MAX_ARGS);
> >
> >
> > +
> >
> >
> > +    switch (NumArgs) {
> >
> >
> > +      case 0:
> >
> >
> > +        Ret = SbiCall (ExtensionId, FunctionId,
> > NumArgs);
> >
> >
> > +        break;
> >
> >
> > +      case 1:
> >
> >
> > +        Ret = SbiCall (ExtensionId, FunctionId,
> > NumArgs, VA_ARG (Args, UINTN));
> >
> >
> > +        break;
> >
> >
> > +      case 2:
> >
> >
> > +        Ret = SbiCall (ExtensionId, FunctionId,
> > NumArgs, VA_ARG (Args, UINTN),
> >
> >
> > +                       VA_ARG (Args, UINTN));
> >
> >
> > +        break;
> >
> >
> > +      case 3:
> >
> >
> > +        Ret = SbiCall (ExtensionId, FunctionId,
> > NumArgs, VA_ARG (Args, UINTN),
> >
> >
> > +                       VA_ARG (Args, UINTN), VA_ARG
> > (Args, UINTN));
> >
> >
> > +        break;
> >
> >
> > +      case 4:
> >
> >
> > +        Ret = SbiCall (ExtensionId, FunctionId,
> > NumArgs, VA_ARG (Args, UINTN),
> >
> >
> > +                       VA_ARG (Args, UINTN), VA_ARG
> > (Args, UINTN),
> >
> >
> > +                       VA_ARG (Args, UINTN));
> >
> >
> > +        break;
> >
> >
> > +      case 5:
> >
> >
> > +        Ret = SbiCall (ExtensionId, FunctionId,
> > NumArgs, VA_ARG (Args, UINTN),
> >
> >
> > +                       VA_ARG (Args, UINTN), VA_ARG
> > (Args, UINTN),
> >
> >
> > +                       VA_ARG (Args, UINTN), VA_ARG
> > (Args, UINTN));
> >
> >
> > +        break;
> >
> >
> > +      case 6:
> >
> >
> > +        Ret = SbiCall (ExtensionId, FunctionId,
> > NumArgs, VA_ARG (Args, UINTN),
> >
> >
> > +                       VA_ARG (Args, UINTN), VA_ARG
> > (Args, UINTN),
> >
> >
> > +                       VA_ARG (Args, UINTN), VA_ARG
> > (Args, UINTN),
> >
> >
> > +                       VA_ARG (Args, UINTN));
> >
> >
> > +        break;
> >
> >
> > +      default:
> >
> >
> > +        // Too many args. In theory SBI can handle more
> > arguments when they are
> >
> >
> > +        // passed on the stack but no SBI extension
> > uses this, therefore it's
> >
> >
> > +        // not yet implemented here.
> >
> >
> > +        return EFI_INVALID_PARAMETER;
> >
> >
> > +     }
> >
> >
> > +
> >
> >
> > +    VA_END(Args);
> >
> >
> > +    return TranslateError (Ret.Error);
> >
> >
> > +}
> >
> >
> > +
> >
> >
> > +//
> >
> >
> > +// SBI Firmware extension
> >
> >
> > +//
> >
> >
> > +
> >
> >
> > +/**
> >
> >
> > +  Get scratch space of the current hart.
> >
> >
> > +
> >
> >
> > +  Please consider using the wrapper
> > SbiGetFirmwareContext if you only need to
> >
> >
> > +  access the firmware context.
> >
> >
> > +
> >
> >
> > +  @param[out] ScratchSpace         The scratch space
> > pointer.
> >
> >
> > +  @retval EFI_SUCCESS              The operation
> > succeeds.
> >
> >
> > +**/
> >
> >
> > +EFI_STATUS
> >
> >
> > +EFIAPI
> >
> >
> > +SbiGetMscratch (
> >
> >
> > +  OUT SBI_SCRATCH                    **ScratchSpace
> >
> >
> > +  )
> >
> >
> > +{
> >
> >
> > +  SbiRet Ret = SbiCall (SBI_EDK2_FW_EXT,
> > SBI_EXT_FW_MSCRATCH_FUNC, 0);
> >
> >
> > +
> >
> >
> > +  if (!Ret.Error) {
> >
> >
> > +    *ScratchSpace = (SBI_SCRATCH *)Ret.Value;
> >
> >
> > +  }
> >
> >
> > +
> >
> >
> > +  return EFI_SUCCESS;
> >
> >
> > +}
> >
> >
> > +
> >
> >
> > +/**
> >
> >
> > +  Get scratch space of the given hart id.
> >
> >
> > +
> >
> >
> > +  @param[in]  HartId               The hart id.
> >
> >
> > +  @param[out] ScratchSpace         The scratch space
> > pointer.
> >
> >
> > +  @retval EFI_SUCCESS              The operation
> > succeeds.
> >
> >
> > +**/
> >
> >
> > +EFI_STATUS
> >
> >
> > +EFIAPI
> >
> >
> > +SbiGetMscratchHartid (
> >
> >
> > +  IN  UINTN                            HartId,
> >
> >
> > +  OUT SBI_SCRATCH                    **ScratchSpace
> >
> >
> > +  )
> >
> >
> > +{
> >
> >
> > +  SbiRet Ret = SbiCall (
> >
> >
> > +                 SBI_EDK2_FW_EXT,
> >
> >
> > +                 SBI_EXT_FW_MSCRATCH_HARTID_FUNC,
> >
> >
> > +                 1,
> >
> >
> > +                 HartId
> >
> >
> > +                 );
> >
> >
> > +
> >
> >
> > +  if (!Ret.Error) {
> >
> >
> > +    *ScratchSpace = (SBI_SCRATCH *)Ret.Value;
> >
> >
> > +  }
> >
> >
> > +
> >
> >
> > +  return EFI_SUCCESS;
> >
> >
> > +}
> >
> >
> > +
> >
> >
> > +/**
> >
> >
> > +  Get firmware context of the calling hart.
> >
> >
> > +
> >
> >
> > +  @param[out] FirmwareContext      The firmware context
> > pointer.
> >
> >
> > +  @retval EFI_SUCCESS              The operation
> > succeeds.
> >
> >
> > +**/
> >
> >
> > +EFI_STATUS
> >
> >
> > +EFIAPI
> >
> >
> > +SbiGetFirmwareContext (
> >
> >
> > +  OUT EFI_RISCV_OPENSBI_FIRMWARE_CONTEXT
> > **FirmwareContext
> >
> >
> > +  )
> >
> >
> > +{
> >
> >
> > +  SBI_SCRATCH  *ScratchSpace;
> >
> >
> > +  SBI_PLATFORM *SbiPlatform;
> >
> >
> > +  SbiRet Ret = SbiCall (SBI_EDK2_FW_EXT,
> > SBI_EXT_FW_MSCRATCH_FUNC, 0);
> >
> >
> > +
> >
> >
> > +  if (!Ret.Error) {
> >
> >
> > +    ScratchSpace = (SBI_SCRATCH *)Ret.Value;
> >
> >
> > +    SbiPlatform = (SBI_PLATFORM
> > *)sbi_platform_ptr(ScratchSpace);
> >
> >
> > +    *FirmwareContext =
> > (EFI_RISCV_OPENSBI_FIRMWARE_CONTEXT *)SbiPlatform-
> > >firmware_context;
> >
> >
> > +  }
> >
> >
> > +
> >
> >
> > +  return EFI_SUCCESS;
> >
> >
> > +}
> >
> >
> > +
> >
> >
> > +/**
> >
> >
> > +  Set firmware context of the calling hart.
> >
> >
> > +
> >
> >
> > +  @param[in] FirmwareContext       The firmware context
> > pointer.
> >
> >
> > +  @retval EFI_SUCCESS              The operation
> > succeeds.
> >
> >
> > +**/
> >
> >
> > +EFI_STATUS
> >
> >
> > +EFIAPI
> >
> >
> > +SbiSetFirmwareContext (
> >
> >
> > +  IN EFI_RISCV_OPENSBI_FIRMWARE_CONTEXT
> > *FirmwareContext
> >
> >
> > +  )
> >
> >
> > +{
> >
> >
> > +  SBI_SCRATCH  *ScratchSpace;
> >
> >
> > +  SBI_PLATFORM *SbiPlatform;
> >
> >
> > +  SbiRet Ret = SbiCall (SBI_EDK2_FW_EXT,
> > SBI_EXT_FW_MSCRATCH_FUNC, 0);
> >
> >
> > +
> >
> >
> > +  if (!Ret.Error) {
> >
> >
> > +    ScratchSpace = (SBI_SCRATCH *)Ret.Value;
> >
> >
> > +    SbiPlatform = (SBI_PLATFORM *)sbi_platform_ptr
> > (ScratchSpace);
> >
> >
> > +    SbiPlatform->firmware_context =
> > (UINTN)FirmwareContext;
> >
> >
> > +  }
> >
> >
> > +
> >
> >
> > +  return EFI_SUCCESS;
> >
> >
> > +}
> >
> >
> > --
> > 2.26.1
> >
> >
> > 


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [edk2-devel] [PATCH v4 1/1] ProcessorPkg/Library: Add RiscVEdk2SbiLib
       [not found]     ` <1614E4344379EB27.21938@groups.io>
@ 2020-06-03  1:33       ` Abner Chang
  0 siblings, 0 replies; 7+ messages in thread
From: Abner Chang @ 2020-06-03  1:33 UTC (permalink / raw)
  To: devel@edk2.groups.io, Kinney, Michael D,
	Schaefer, Daniel (DualStudy)
  Cc: Leif Lindholm, Chen, Gilbert



> -----Original Message-----
> From: devel@edk2.groups.io [mailto:devel@edk2.groups.io] On Behalf Of
> Abner Chang
> Sent: Wednesday, June 3, 2020 9:25 AM
> To: Kinney, Michael D <michael.d.kinney@intel.com>; devel@edk2.groups.io;
> Schaefer, Daniel (DualStudy) <daniel.schaefer@hpe.com>
> Cc: Leif Lindholm <leif@nuviainc.com>; Chen, Gilbert
> <gilbert.chen@hpe.com>
> Subject: Re: [edk2-devel] [PATCH v4 1/1] ProcessorPkg/Library: Add
> RiscVEdk2SbiLib
> 
> 
> 
> > -----Original Message-----
> > From: Kinney, Michael D [mailto:michael.d.kinney@intel.com]
> > Sent: Wednesday, June 3, 2020 6:00 AM
> > To: devel@edk2.groups.io; Schaefer, Daniel (DualStudy)
> > <daniel.schaefer@hpe.com>; Kinney, Michael D
> > <michael.d.kinney@intel.com>
> > Cc: Leif Lindholm <leif@nuviainc.com>; Chen, Gilbert
> > <gilbert.chen@hpe.com>; Chang, Abner (HPS SW/FW Technologist)
> > <abner.chang@hpe.com>
> > Subject: RE: [edk2-devel] [PATCH v4 1/1] ProcessorPkg/Library: Add
> > RiscVEdk2SbiLib
> >
> > Hi Daniel,
> >
> > I see some inconsistence in the names used in these patches.
> >
> > For example, there should not be a need to use "Edk2" in the
> > name of a library.  This library is in an edk2 repo.
> We currently have two libraries regards to RISC-V SBI spec. One is the
> wrapper to build OpenSBI lib, which is RiscVOpenSbiLib.
> Another one is SBI firmware code base extension in which the ABIs are
> provided by system firmware other than the standard ABIs defined in SBI
> spec. To name it with EDK2 makes sense because that is RISC-V EDK2
> firmware code base SBI extension.
More information is in below,
https://github.com/riscv/riscv-sbi-doc/blob/master/riscv-sbi.adoc
- Firmware Code Base Specific SBI Extension Space, Extension Ids 0x0A000000 through 0x0AFFFFFF
> >
> > I see "RiscV" and "Risk-V" used in file paths.  I recommend
> > you pick one and use it consistently.  In the MdePkg, I see
> > RiscV64, and macros using RISCV, RISCV32, RISCV64, and RISCV128.
> > which seems consistent and does not use a '-'.  Perhaps use
> > "RiscV" for content that works for 32, 64, and 128 bit and
> > RiscV32, RiscV64, and RiskV128 for content is specific to the
> > bit width?
> For the folders under Silicon and platform, I prefer to use "RISC-V" which is
> the official name of this processor. All other files can use RiscV which
> conform the naming rule. RISCV32, RISCV64, and RISCV128 are used for the
> architectures.
> 
> >
> > Thanks,
> >
> > Mike
> >
> > > -----Original Message-----
> > > From: devel@edk2.groups.io <devel@edk2.groups.io> On
> > > Behalf Of Daniel Schaefer
> > > Sent: Tuesday, June 2, 2020 9:52 AM
> > > To: devel@edk2.groups.io
> > > Cc: Leif Lindholm <leif@nuviainc.com>; Gilbert Chen
> > > <gilbert.chen@hpe.com>; Abner Chang
> > > <abner.chang@hpe.com>; Kinney, Michael D
> > > <michael.d.kinney@intel.com>
> > > Subject: [edk2-devel] [PATCH v4 1/1]
> > > ProcessorPkg/Library: Add RiscVEdk2SbiLib
> > >
> > > Library provides interfaces to invoke SBI ecalls.
> > >
> > > Signed-off-by: Daniel Schaefer <daniel.schaefer@hpe.com>
> > >
> > > Cc: Leif Lindholm <leif@nuviainc.com>
> > > Cc: Gilbert Chen <gilbert.chen@hpe.com>
> > > Cc: Abner Chang <abner.chang@hpe.com>
> > > Cc: Michael D. Kinney <michael.d.kinney@intel.com>
> > > ---
> > >  Silicon/RISC-
> > > V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.i
> > > nf |  28 +
> > >  Silicon/RISC-
> > > V/ProcessorPkg/Include/Library/RiscVEdk2SbiLib.h
> > > | 563 ++++++++++++
> > >  Silicon/RISC-
> > > V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.c
> > > | 897 ++++++++++++++++++++
> > >  3 files changed, 1488 insertions(+)
> > >
> > > diff --git a/Silicon/RISC-
> > > V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.i
> > > nf b/Silicon/RISC-
> > > V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.i
> > > nf
> > > new file mode 100644
> > > index 000000000000..665dcbf40e01
> > > --- /dev/null
> > > +++ b/Silicon/RISC-
> > > V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.i
> > > nf
> > > @@ -0,0 +1,28 @@
> > > +## @file
> > >
> > >
> > > +# RISC-V Library to call SBI ecalls
> > >
> > >
> > > +#
> > >
> > >
> > > +#  Copyright (c) 2020, Hewlett Packard Enterprise
> > > Development LP. All rights reserved.<BR>
> > >
> > >
> > > +#
> > >
> > >
> > > +#  SPDX-License-Identifier: BSD-2-Clause-Patent
> > >
> > >
> > > +#
> > >
> > >
> > > +##
> > >
> > >
> > > +
> > >
> > >
> > > +[Defines]
> > >
> > >
> > > +  INF_VERSION    = 0x0001001b
> > >
> > >
> > > +  BASE_NAME      = RiscVEdk2SbiLib
> > >
> > >
> > > +  FILE_GUID      = 0DF1BBBD-F7E5-4E8A-BCF1-9D63D2DD9FDD
> > >
> > >
> > > +  MODULE_TYPE    = BASE
> > >
> > >
> > > +  VERSION_STRING = 1.0
> > >
> > >
> > > +  LIBRARY_CLASS  = RiscVEdk2SbiLib
> > >
> > >
> > > +
> > >
> > >
> > > +[Sources]
> > >
> > >
> > > +  RiscVEdk2SbiLib.c
> > >
> > >
> > > +
> > >
> > >
> > > +[Packages]
> > >
> > >
> > > +  MdePkg/MdePkg.dec
> > >
> > >
> > > +  Silicon/RISC-V/ProcessorPkg/RiscVProcessorPkg.dec
> > >
> > >
> > > +  Platform/RISC-V/PlatformPkg/RiscVPlatformPkg.dec
> > >
> > >
> > > +
> > >
> > >
> > > +[LibraryClasses]
> > >
> > >
> > > +  BaseLib
> > >
> > >
> > > +  RiscVOpensbiLib
> > >
> > >
> > > diff --git a/Silicon/RISC-
> > > V/ProcessorPkg/Include/Library/RiscVEdk2SbiLib.h
> > > b/Silicon/RISC-
> > > V/ProcessorPkg/Include/Library/RiscVEdk2SbiLib.h
> > > new file mode 100644
> > > index 000000000000..c1ae3176147f
> > > --- /dev/null
> > > +++ b/Silicon/RISC-
> > > V/ProcessorPkg/Include/Library/RiscVEdk2SbiLib.h
> > > @@ -0,0 +1,563 @@
> > > +/** @file
> > >
> > >
> > > +  Library to call the RISC-V SBI ecalls
> > >
> > >
> > > +
> > >
> > >
> > > +  Copyright (c) 2020, Hewlett Packard Development LP.
> > > All rights reserved.<BR>
> > >
> > >
> > > +
> > >
> > >
> > > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > >
> > >
> > > +
> > >
> > >
> > > +  @par Glossary:
> > >
> > >
> > > +    - Hart - Hardware Thread, similar to a CPU core
> > >
> > >
> > > +**/
> > >
> > >
> > > +
> > >
> > >
> > > +#ifndef RISCV_SBI_LIB_H_
> > >
> > >
> > > +#define RISCV_SBI_LIB_H_
> > >
> > >
> > > +
> > >
> > >
> > > +#include <Uefi.h>
> > >
> > >
> > > +#include <IndustryStandard/RiscVOpensbi.h>
> > >
> > >
> > > +#include <sbi/sbi_scratch.h>
> > >
> > >
> > > +#include <sbi/sbi_platform.h>
> > >
> > >
> > > +
> > >
> > >
> > > +//
> > >
> > >
> > > +// EDK2 OpenSBI Firmware extension.
> > >
> > >
> > > +//
> > >
> > >
> > > +#define SBI_EDK2_FW_EXT
> > > (SBI_EXT_FIRMWARE_CODE_BASE_START | SBI_OPENSBI_IMPID)
> > >
> > >
> > > +//
> > >
> > >
> > > +// EDK2 OpenSBI Firmware extension functions.
> > >
> > >
> > > +//
> > >
> > >
> > > +#define SBI_EXT_FW_MSCRATCH_FUNC        0
> > >
> > >
> > > +#define SBI_EXT_FW_MSCRATCH_HARTID_FUNC 1
> > >
> > >
> > > +
> > >
> > >
> > > +//
> > >
> > >
> > > +// EDK2 OpenSBI firmware extension return status.
> > >
> > >
> > > +//
> > >
> > >
> > > +typedef struct {
> > >
> > >
> > > +  UINTN Error;   ///< SBI status code
> > >
> > >
> > > +  UINTN Value;   ///< Value returned
> > >
> > >
> > > +} SbiRet;
> > >
> > >
> > > +
> > >
> > >
> > > +/**
> > >
> > >
> > > +  Get the implemented SBI specification version
> > >
> > >
> > > +
> > >
> > >
> > > +  The minor number of the SBI specification is encoded
> > > in the low 24 bits,
> > >
> > >
> > > +  with the major number encoded in the next 7 bits.
> > > Bit 32 must be 0 and is
> > >
> > >
> > > +  reserved for future expansion.
> > >
> > >
> > > +
> > >
> > >
> > > +  @param[out] SpecVersion          The Version of the
> > > SBI specification.
> > >
> > >
> > > +**/
> > >
> > >
> > > +VOID
> > >
> > >
> > > +EFIAPI
> > >
> > >
> > > +SbiGetSpecVersion (
> > >
> > >
> > > +  OUT UINTN                       *SpecVersion
> > >
> > >
> > > +  );
> > >
> > >
> > > +
> > >
> > >
> > > +/**
> > >
> > >
> > > +  Get the SBI implementation ID
> > >
> > >
> > > +
> > >
> > >
> > > +  This ID is used to idenetify a specific SBI
> > > implementation in order to work
> > >
> > >
> > > +  around any quirks it might have.
> > >
> > >
> > > +
> > >
> > >
> > > +  @param[out] ImplId               The ID of the SBI
> > > implementation.
> > >
> > >
> > > +**/
> > >
> > >
> > > +VOID
> > >
> > >
> > > +EFIAPI
> > >
> > >
> > > +SbiGetImplId (
> > >
> > >
> > > +  OUT UINTN                      *ImplId
> > >
> > >
> > > +  );
> > >
> > >
> > > +
> > >
> > >
> > > +/**
> > >
> > >
> > > +  Get the SBI implementation version
> > >
> > >
> > > +
> > >
> > >
> > > +  The version of this SBI implementation.
> > >
> > >
> > > +  The encoding of this number is determined by the
> > > specific SBI implementation.
> > >
> > >
> > > +
> > >
> > >
> > > +  @param[out] ImplVersion          The version of the
> > > SBI implementation.
> > >
> > >
> > > +**/
> > >
> > >
> > > +VOID
> > >
> > >
> > > +EFIAPI
> > >
> > >
> > > +SbiGetImplVersion (
> > >
> > >
> > > +  OUT UINTN                       *ImplVersion
> > >
> > >
> > > +  );
> > >
> > >
> > > +
> > >
> > >
> > > +/**
> > >
> > >
> > > +  Probe whether an SBI extension is available
> > >
> > >
> > > +
> > >
> > >
> > > +  ProbeResult is set to 0 if the extension is not
> > > available or to an extension
> > >
> > >
> > > +  specified value if it is available.
> > >
> > >
> > > +
> > >
> > >
> > > +  @param[in]  ExtensionId          The extension ID.
> > >
> > >
> > > +  @param[out] ProbeResult          The return value of
> > > the probe.
> > >
> > >
> > > +**/
> > >
> > >
> > > +VOID
> > >
> > >
> > > +EFIAPI
> > >
> > >
> > > +SbiProbeExtension (
> > >
> > >
> > > +  IN  INTN                         ExtensionId,
> > >
> > >
> > > +  OUT INTN                        *ProbeResult
> > >
> > >
> > > +  );
> > >
> > >
> > > +
> > >
> > >
> > > +/**
> > >
> > >
> > > +  Get the CPU's vendor ID
> > >
> > >
> > > +
> > >
> > >
> > > +  Reads the mvendorid CSR.
> > >
> > >
> > > +
> > >
> > >
> > > +  @param[out] MachineVendorId      The CPU's vendor ID.
> > >
> > >
> > > +**/
> > >
> > >
> > > +VOID
> > >
> > >
> > > +EFIAPI
> > >
> > >
> > > +SbiGetMachineVendorId (
> > >
> > >
> > > +  OUT UINTN                       *MachineVendorId
> > >
> > >
> > > +  );
> > >
> > >
> > > +
> > >
> > >
> > > +/**
> > >
> > >
> > > +  Get the CPU's architecture ID
> > >
> > >
> > > +
> > >
> > >
> > > +  Reads the marchid CSR.
> > >
> > >
> > > +
> > >
> > >
> > > +  @param[out] MachineArchId        The CPU's
> > > architecture ID.
> > >
> > >
> > > +**/
> > >
> > >
> > > +VOID
> > >
> > >
> > > +EFIAPI
> > >
> > >
> > > +SbiGetMachineArchId (
> > >
> > >
> > > +  OUT UINTN                       *MachineArchId
> > >
> > >
> > > +  );
> > >
> > >
> > > +
> > >
> > >
> > > +/**
> > >
> > >
> > > +  Get the CPU's implementation ID
> > >
> > >
> > > +
> > >
> > >
> > > +  Reads the mimpid CSR.
> > >
> > >
> > > +
> > >
> > >
> > > +  @param[out] MachineImplId        The CPU's
> > > implementation ID.
> > >
> > >
> > > +**/
> > >
> > >
> > > +VOID
> > >
> > >
> > > +EFIAPI
> > >
> > >
> > > +SbiGetMachineImplId (
> > >
> > >
> > > +  OUT UINTN                       *MachineImplId
> > >
> > >
> > > +  );
> > >
> > >
> > > +
> > >
> > >
> > > +/**
> > >
> > >
> > > +  Politely ask the SBI to start a given hart.
> > >
> > >
> > > +
> > >
> > >
> > > +  This call may return before the hart has actually
> > > started executing, if the
> > >
> > >
> > > +  SBI implementation can guarantee that the hart is
> > > actually going to start.
> > >
> > >
> > > +
> > >
> > >
> > > +  Before the hart jumps to StartAddr, the hart MUST
> > > configure PMP if present
> > >
> > >
> > > +  and switch to S-mode.
> > >
> > >
> > > +
> > >
> > >
> > > +  @param[in]  HartId               The id of the hart
> > > to start.
> > >
> > >
> > > +  @param[in]  StartAddr            The physical
> > > address, where the hart starts
> > >
> > >
> > > +                                   executing from.
> > >
> > >
> > > +  @param[in]  Priv                 An XLEN-bit value,
> > > which will be in register
> > >
> > >
> > > +                                   a1 when the hart
> > > starts.
> > >
> > >
> > > +  @retval EFI_SUCCESS              Hart was stopped and
> > > will start executing from StartAddr.
> > >
> > >
> > > +  @retval EFI_LOAD_ERROR           StartAddr is not
> > > valid, possibly due to following reasons:
> > >
> > >
> > > +                                    - It is not a valid
> > > physical address.
> > >
> > >
> > > +                                    - The address is
> > > prohibited by PMP to run in
> > >
> > >
> > > +                                      supervisor mode.
> > >
> > >
> > > +  @retval EFI_INVALID_PARAMETER    HartId is not a
> > > valid hart id
> > >
> > >
> > > +  @retval EFI_ALREADY_STARTED      The hart is already
> > > running.
> > >
> > >
> > > +  @retval other                    The start request
> > > failed for unknown reasons.
> > >
> > >
> > > +**/
> > >
> > >
> > > +EFI_STATUS
> > >
> > >
> > > +EFIAPI
> > >
> > >
> > > +SbiHartStart (
> > >
> > >
> > > +  IN  UINTN                          HartId,
> > >
> > >
> > > +  IN  UINTN                          StartAddr,
> > >
> > >
> > > +  IN  UINTN                          Priv
> > >
> > >
> > > +  );
> > >
> > >
> > > +
> > >
> > >
> > > +/**
> > >
> > >
> > > +  Return execution of the calling hart to SBI.
> > >
> > >
> > > +
> > >
> > >
> > > +  MUST be called in S-Mode with user interrupts
> > > disabled.
> > >
> > >
> > > +  This call is not expected to return, unless a failure
> > > occurs.
> > >
> > >
> > > +
> > >
> > >
> > > +  @retval     EFI_SUCCESS          Never occurs. When
> > > successful, the call does not return.
> > >
> > >
> > > +  @retval     other                Failed to stop hard
> > > for an unknown reason.
> > >
> > >
> > > +**/
> > >
> > >
> > > +EFI_STATUS
> > >
> > >
> > > +EFIAPI
> > >
> > >
> > > +SbiHartStop (
> > >
> > >
> > > +  );
> > >
> > >
> > > +
> > >
> > >
> > > +/**
> > >
> > >
> > > +  Get the current status of a hart.
> > >
> > >
> > > +
> > >
> > >
> > > +  Since harts can transition between states at any
> > > time, the status retrieved
> > >
> > >
> > > +  by this function may already be out of date, once it
> > > returns.
> > >
> > >
> > > +
> > >
> > >
> > > +  Possible values for HartStatus are:
> > >
> > >
> > > +  0: STARTED
> > >
> > >
> > > +  1: STOPPED
> > >
> > >
> > > +  2: START_REQUEST_PENDING
> > >
> > >
> > > +  3: STOP_REQUEST_PENDING
> > >
> > >
> > > +
> > >
> > >
> > > +  @param[out] HartStatus           The pointer in which
> > > the hart's status is
> > >
> > >
> > > +                                   stored.
> > >
> > >
> > > +  @retval EFI_SUCCESS              The operation
> > > succeeds.
> > >
> > >
> > > +  @retval EFI_INVALID_PARAMETER    A parameter is
> > > invalid.
> > >
> > >
> > > +**/
> > >
> > >
> > > +EFI_STATUS
> > >
> > >
> > > +EFIAPI
> > >
> > >
> > > +SbiHartGetStatus (
> > >
> > >
> > > +  IN  UINTN                          HartId,
> > >
> > >
> > > +  OUT UINTN                         *HartStatus
> > >
> > >
> > > +  );
> > >
> > >
> > > +
> > >
> > >
> > > +///
> > >
> > >
> > > +/// Timer extension
> > >
> > >
> > > +///
> > >
> > >
> > > +
> > >
> > >
> > > +/**
> > >
> > >
> > > +  Clear pending timer interrupt bit and set timer for
> > > next event after Time.
> > >
> > >
> > > +
> > >
> > >
> > > +  To clear the timer without scheduling a timer event,
> > > set Time to a
> > >
> > >
> > > +  practically infinite value or mask the timer
> > > interrupt by clearing sie.STIE.
> > >
> > >
> > > +
> > >
> > >
> > > +  @param[in]  Time                 The time offset to
> > > the next scheduled timer interrupt.
> > >
> > >
> > > +**/
> > >
> > >
> > > +VOID
> > >
> > >
> > > +EFIAPI
> > >
> > >
> > > +SbiSetTimer (
> > >
> > >
> > > +  IN  UINT64                         Time
> > >
> > >
> > > +  );
> > >
> > >
> > > +
> > >
> > >
> > > +///
> > >
> > >
> > > +/// IPI extension
> > >
> > >
> > > +///
> > >
> > >
> > > +
> > >
> > >
> > > +/**
> > >
> > >
> > > +  Send IPI to all harts specified in the mask.
> > >
> > >
> > > +
> > >
> > >
> > > +  The interrupts are registered as supervisor software
> > > interrupts at the
> > >
> > >
> > > +  receiving hart.
> > >
> > >
> > > +
> > >
> > >
> > > +  @param[in]  HartMask             Scalar bit-vector
> > > containing hart ids
> > >
> > >
> > > +  @param[in]  HartMaskBase         The starting hartid
> > > from which the bit-vector
> > >
> > >
> > > +                                   must be computed. If
> > > set to -1, HartMask is
> > >
> > >
> > > +                                   ignored and all
> > > harts are considered.
> > >
> > >
> > > +  @retval EFI_SUCCESS              IPI was sent to all
> > > the targeted harts.
> > >
> > >
> > > +  @retval EFI_INVALID_PARAMETER    Either
> > > hart_mask_base or any of the hartid
> > >
> > >
> > > +                                   from hart_mask is
> > > not valid i.e. either the
> > >
> > >
> > > +                                   hartid is not
> > > enabled by the platform or is
> > >
> > >
> > > +                                   not available to the
> > > supervisor.
> > >
> > >
> > > +**/
> > >
> > >
> > > +EFI_STATUS
> > >
> > >
> > > +EFIAPI
> > >
> > >
> > > +SbiSendIpi (
> > >
> > >
> > > +  IN  UINTN                         *HartMask,
> > >
> > >
> > > +  IN  UINTN                          HartMaskBase
> > >
> > >
> > > +  );
> > >
> > >
> > > +
> > >
> > >
> > > +///
> > >
> > >
> > > +/// Remote fence extension
> > >
> > >
> > > +///
> > >
> > >
> > > +
> > >
> > >
> > > +/**
> > >
> > >
> > > +  Instructs remote harts to execute a FENCE.I
> > > instruction.
> > >
> > >
> > > +
> > >
> > >
> > > +  @param[in]  HartMask             Scalar bit-vector
> > > containing hart ids
> > >
> > >
> > > +  @param[in]  HartMaskBase         The starting hartid
> > > from which the bit-vector
> > >
> > >
> > > +                                   must be computed. If
> > > set to -1, HartMask is
> > >
> > >
> > > +                                   ignored and all
> > > harts are considered.
> > >
> > >
> > > +  @retval EFI_SUCCESS              IPI was sent to all
> > > the targeted harts.
> > >
> > >
> > > +  @retval EFI_INVALID_PARAMETER    Either
> > > hart_mask_base or any of the hartid
> > >
> > >
> > > +                                   from hart_mask is
> > > not valid i.e. either the
> > >
> > >
> > > +                                   hartid is not
> > > enabled by the platform or is
> > >
> > >
> > > +                                   not available to the
> > > supervisor.
> > >
> > >
> > > +**/
> > >
> > >
> > > +EFI_STATUS
> > >
> > >
> > > +EFIAPI
> > >
> > >
> > > +SbiRemoteFenceI (
> > >
> > >
> > > +  IN  UINTN                         *HartMask,
> > >
> > >
> > > +  IN  UINTN                          HartMaskBase
> > >
> > >
> > > +  );
> > >
> > >
> > > +
> > >
> > >
> > > +/**
> > >
> > >
> > > +  Instructs the remote harts to execute one or more
> > > SFENCE.VMA instructions.
> > >
> > >
> > > +
> > >
> > >
> > > +  The SFENCE.VMA covers the range of virtual addresses
> > > between StartAaddr and Size.
> > >
> > >
> > > +
> > >
> > >
> > > +  The remote fence function acts as a full tlb flush if
> > > * StartAddr and size
> > >
> > >
> > > +  are both 0 * size is equal to 2^XLEN-1
> > >
> > >
> > > +
> > >
> > >
> > > +  @param[in]  HartMask             Scalar bit-vector
> > > containing hart ids
> > >
> > >
> > > +  @param[in]  HartMaskBase         The starting hartid
> > > from which the bit-vector
> > >
> > >
> > > +                                   must be computed. If
> > > set to -1, HartMask is
> > >
> > >
> > > +                                   ignored and all
> > > harts are considered.
> > >
> > >
> > > +  @param[in]  StartAddr            The first address of
> > > the affected range.
> > >
> > >
> > > +  @param[in]  Size                 How many addresses
> > > are affected.
> > >
> > >
> > > +  @retval EFI_SUCCESS              IPI was sent to all
> > > the targeted harts.
> > >
> > >
> > > +  @retval EFI_LOAD_ERROR           StartAddr or Size is
> > > not valid.
> > >
> > >
> > > +  @retval EFI_INVALID_PARAMETER    Either
> > > hart_mask_base or any of the hartid
> > >
> > >
> > > +                                   from hart_mask is
> > > not valid i.e. either the
> > >
> > >
> > > +                                   hartid is not
> > > enabled by the platform or is
> > >
> > >
> > > +                                   not available to the
> > > supervisor.
> > >
> > >
> > > +**/
> > >
> > >
> > > +EFI_STATUS
> > >
> > >
> > > +EFIAPI
> > >
> > >
> > > +SbiRemoteSfenceVma (
> > >
> > >
> > > +  IN  UINTN                         *HartMask,
> > >
> > >
> > > +  IN  UINTN                          HartMaskBase,
> > >
> > >
> > > +  IN  UINTN                          StartAddr,
> > >
> > >
> > > +  IN  UINTN                          Size
> > >
> > >
> > > +  );
> > >
> > >
> > > +
> > >
> > >
> > > +/**
> > >
> > >
> > > +  Instructs the remote harts to execute one or more
> > > SFENCE.VMA instructions.
> > >
> > >
> > > +
> > >
> > >
> > > +  The SFENCE.VMA covers the range of virtual addresses
> > > between StartAaddr and Size.
> > >
> > >
> > > +  Covers only the given ASID.
> > >
> > >
> > > +
> > >
> > >
> > > +  The remote fence function acts as a full tlb flush if
> > > * StartAddr and size
> > >
> > >
> > > +  are both 0 * size is equal to 2^XLEN-1
> > >
> > >
> > > +
> > >
> > >
> > > +  @param[in]  HartMask             Scalar bit-vector
> > > containing hart ids
> > >
> > >
> > > +  @param[in]  HartMaskBase         The starting hartid
> > > from which the bit-vector
> > >
> > >
> > > +                                   must be computed. If
> > > set to -1, HartMask is
> > >
> > >
> > > +                                   ignored and all
> > > harts are considered.
> > >
> > >
> > > +  @param[in]  StartAddr            The first address of
> > > the affected range.
> > >
> > >
> > > +  @param[in]  Size                 How many addresses
> > > are affected.
> > >
> > >
> > > +  @retval EFI_SUCCESS              IPI was sent to all
> > > the targeted harts.
> > >
> > >
> > > +  @retval EFI_LOAD_ERROR           StartAddr or Size is
> > > not valid.
> > >
> > >
> > > +  @retval EFI_INVALID_PARAMETER    Either
> > > hart_mask_base or any of the hartid
> > >
> > >
> > > +                                   from hart_mask is
> > > not valid i.e. either the
> > >
> > >
> > > +                                   hartid is not
> > > enabled by the platform or is
> > >
> > >
> > > +                                   not available to the
> > > supervisor.
> > >
> > >
> > > +**/
> > >
> > >
> > > +EFI_STATUS
> > >
> > >
> > > +EFIAPI
> > >
> > >
> > > +SbiRemoteSfenceVmaAsid (
> > >
> > >
> > > +  IN  UINTN                         *HartMask,
> > >
> > >
> > > +  IN  UINTN                          HartMaskBase,
> > >
> > >
> > > +  IN  UINTN                          StartAddr,
> > >
> > >
> > > +  IN  UINTN                          Size,
> > >
> > >
> > > +  IN  UINTN                          Asid
> > >
> > >
> > > +  );
> > >
> > >
> > > +
> > >
> > >
> > > +/**
> > >
> > >
> > > +  Instructs the remote harts to execute one or more
> > > SFENCE.GVMA instructions.
> > >
> > >
> > > +
> > >
> > >
> > > +  The SFENCE.GVMA covers the range of virtual addresses
> > > between StartAaddr and Size.
> > >
> > >
> > > +  Covers only the given VMID.
> > >
> > >
> > > +  This function call is only valid for harts
> > > implementing the hypervisor extension.
> > >
> > >
> > > +
> > >
> > >
> > > +  The remote fence function acts as a full tlb flush if
> > > * StartAddr and size
> > >
> > >
> > > +  are both 0 * size is equal to 2^XLEN-1
> > >
> > >
> > > +
> > >
> > >
> > > +  @param[in]  HartMask             Scalar bit-vector
> > > containing hart ids
> > >
> > >
> > > +  @param[in]  HartMaskBase         The starting hartid
> > > from which the bit-vector
> > >
> > >
> > > +                                   must be computed. If
> > > set to -1, HartMask is
> > >
> > >
> > > +                                   ignored and all
> > > harts are considered.
> > >
> > >
> > > +  @param[in]  StartAddr            The first address of
> > > the affected range.
> > >
> > >
> > > +  @param[in]  Size                 How many addresses
> > > are affected.
> > >
> > >
> > > +  @retval EFI_SUCCESS              IPI was sent to all
> > > the targeted harts.
> > >
> > >
> > > +  @retval EFI_LOAD_ERROR           StartAddr or Size is
> > > not valid.
> > >
> > >
> > > +  @retval EFI_UNSUPPORTED          SBI does not
> > > implement this function or one
> > >
> > >
> > > +                                   of the target harts
> > > does not support the
> > >
> > >
> > > +                                   hypervisor
> > > extension.
> > >
> > >
> > > +  @retval EFI_INVALID_PARAMETER    Either
> > > hart_mask_base or any of the hartid
> > >
> > >
> > > +                                   from hart_mask is
> > > not valid i.e. either the
> > >
> > >
> > > +                                   hartid is not
> > > enabled by the platform or is
> > >
> > >
> > > +                                   not available to the
> > > supervisor.
> > >
> > >
> > > +**/
> > >
> > >
> > > +EFI_STATUS
> > >
> > >
> > > +EFIAPI
> > >
> > >
> > > +SbiRemoteHfenceGvmaVmid (
> > >
> > >
> > > +  IN  UINTN                         *HartMask,
> > >
> > >
> > > +  IN  UINTN                          HartMaskBase,
> > >
> > >
> > > +  IN  UINTN                          StartAddr,
> > >
> > >
> > > +  IN  UINTN                          Size,
> > >
> > >
> > > +  IN  UINTN                          Vmid
> > >
> > >
> > > +  );
> > >
> > >
> > > +
> > >
> > >
> > > +/**
> > >
> > >
> > > +  Instructs the remote harts to execute one or more
> > > SFENCE.GVMA instructions.
> > >
> > >
> > > +
> > >
> > >
> > > +  The SFENCE.GVMA covers the range of virtual addresses
> > > between StartAaddr and Size.
> > >
> > >
> > > +  This function call is only valid for harts
> > > implementing the hypervisor extension.
> > >
> > >
> > > +
> > >
> > >
> > > +  The remote fence function acts as a full tlb flush if
> > > * StartAddr and size
> > >
> > >
> > > +  are both 0 * size is equal to 2^XLEN-1
> > >
> > >
> > > +
> > >
> > >
> > > +  @param[in]  HartMask             Scalar bit-vector
> > > containing hart ids
> > >
> > >
> > > +  @param[in]  HartMaskBase         The starting hartid
> > > from which the bit-vector
> > >
> > >
> > > +                                   must be computed. If
> > > set to -1, HartMask is
> > >
> > >
> > > +                                   ignored and all
> > > harts are considered.
> > >
> > >
> > > +  @param[in]  StartAddr            The first address of
> > > the affected range.
> > >
> > >
> > > +  @param[in]  Size                 How many addresses
> > > are affected.
> > >
> > >
> > > +  @retval EFI_SUCCESS              IPI was sent to all
> > > the targeted harts.
> > >
> > >
> > > +  @retval EFI_LOAD_ERROR           StartAddr or Size is
> > > not valid.
> > >
> > >
> > > +  @retval EFI_UNSUPPORTED          SBI does not
> > > implement this function or one
> > >
> > >
> > > +                                   of the target harts
> > > does not support the
> > >
> > >
> > > +                                   hypervisor
> > > extension.
> > >
> > >
> > > +  @retval EFI_INVALID_PARAMETER    Either
> > > hart_mask_base or any of the hartid
> > >
> > >
> > > +                                   from hart_mask is
> > > not valid i.e. either the
> > >
> > >
> > > +                                   hartid is not
> > > enabled by the platform or is
> > >
> > >
> > > +                                   not available to the
> > > supervisor.
> > >
> > >
> > > +**/
> > >
> > >
> > > +EFI_STATUS
> > >
> > >
> > > +EFIAPI
> > >
> > >
> > > +SbiRemoteHfenceGvma (
> > >
> > >
> > > +  IN  UINTN                         *HartMask,
> > >
> > >
> > > +  IN  UINTN                          HartMaskBase,
> > >
> > >
> > > +  IN  UINTN                          StartAddr,
> > >
> > >
> > > +  IN  UINTN                          Size
> > >
> > >
> > > +  );
> > >
> > >
> > > +
> > >
> > >
> > > +/**
> > >
> > >
> > > +  Instructs the remote harts to execute one or more
> > > SFENCE.VVMA instructions.
> > >
> > >
> > > +
> > >
> > >
> > > +  The SFENCE.GVMA covers the range of virtual addresses
> > > between StartAaddr and Size.
> > >
> > >
> > > +  Covers only the given ASID.
> > >
> > >
> > > +  This function call is only valid for harts
> > > implementing the hypervisor extension.
> > >
> > >
> > > +
> > >
> > >
> > > +  The remote fence function acts as a full tlb flush if
> > > * StartAddr and size
> > >
> > >
> > > +  are both 0 * size is equal to 2^XLEN-1
> > >
> > >
> > > +
> > >
> > >
> > > +  @param[in]  HartMask             Scalar bit-vector
> > > containing hart ids
> > >
> > >
> > > +  @param[in]  HartMaskBase         The starting hartid
> > > from which the bit-vector
> > >
> > >
> > > +                                   must be computed. If
> > > set to -1, HartMask is
> > >
> > >
> > > +                                   ignored and all
> > > harts are considered.
> > >
> > >
> > > +  @param[in]  StartAddr            The first address of
> > > the affected range.
> > >
> > >
> > > +  @param[in]  Size                 How many addresses
> > > are affected.
> > >
> > >
> > > +  @retval EFI_SUCCESS              IPI was sent to all
> > > the targeted harts.
> > >
> > >
> > > +  @retval EFI_LOAD_ERROR           StartAddr or Size is
> > > not valid.
> > >
> > >
> > > +  @retval EFI_UNSUPPORTED          SBI does not
> > > implement this function or one
> > >
> > >
> > > +                                   of the target harts
> > > does not support the
> > >
> > >
> > > +                                   hypervisor
> > > extension.
> > >
> > >
> > > +  @retval EFI_INVALID_PARAMETER    Either
> > > hart_mask_base or any of the hartid
> > >
> > >
> > > +                                   from hart_mask is
> > > not valid i.e. either the
> > >
> > >
> > > +                                   hartid is not
> > > enabled by the platform or is
> > >
> > >
> > > +                                   not available to the
> > > supervisor.
> > >
> > >
> > > +**/
> > >
> > >
> > > +EFI_STATUS
> > >
> > >
> > > +EFIAPI
> > >
> > >
> > > +SbiRemoteHfenceVvmaAsid (
> > >
> > >
> > > +  IN  UINTN                         *HartMask,
> > >
> > >
> > > +  IN  UINTN                          HartMaskBase,
> > >
> > >
> > > +  IN  UINTN                          StartAddr,
> > >
> > >
> > > +  IN  UINTN                          Size,
> > >
> > >
> > > +  IN  UINTN                          Asid
> > >
> > >
> > > +  );
> > >
> > >
> > > +
> > >
> > >
> > > +/**
> > >
> > >
> > > +  Instructs the remote harts to execute one or more
> > > SFENCE.VVMA instructions.
> > >
> > >
> > > +
> > >
> > >
> > > +  The SFENCE.GVMA covers the range of virtual addresses
> > > between StartAaddr and Size.
> > >
> > >
> > > +  This function call is only valid for harts
> > > implementing the hypervisor extension.
> > >
> > >
> > > +
> > >
> > >
> > > +  The remote fence function acts as a full tlb flush if
> > > * StartAddr and size
> > >
> > >
> > > +  are both 0 * size is equal to 2^XLEN-1
> > >
> > >
> > > +
> > >
> > >
> > > +  @param[in]  HartMask             Scalar bit-vector
> > > containing hart ids
> > >
> > >
> > > +  @param[in]  HartMaskBase         The starting hartid
> > > from which the bit-vector
> > >
> > >
> > > +                                   must be computed. If
> > > set to -1, HartMask is
> > >
> > >
> > > +                                   ignored and all
> > > harts are considered.
> > >
> > >
> > > +  @param[in]  StartAddr            The first address of
> > > the affected range.
> > >
> > >
> > > +  @param[in]  Size                 How many addresses
> > > are affected.
> > >
> > >
> > > +  @retval EFI_SUCCESS              IPI was sent to all
> > > the targeted harts.
> > >
> > >
> > > +  @retval EFI_LOAD_ERROR           StartAddr or Size is
> > > not valid.
> > >
> > >
> > > +  @retval EFI_UNSUPPORTED          SBI does not
> > > implement this function or one
> > >
> > >
> > > +                                   of the target harts
> > > does not support the
> > >
> > >
> > > +                                   hypervisor
> > > extension.
> > >
> > >
> > > +  @retval EFI_INVALID_PARAMETER    Either
> > > hart_mask_base or any of the hartid
> > >
> > >
> > > +                                   from hart_mask is
> > > not valid i.e. either the
> > >
> > >
> > > +                                   hartid is not
> > > enabled by the platform or is
> > >
> > >
> > > +                                   not available to the
> > > supervisor.
> > >
> > >
> > > +**/
> > >
> > >
> > > +EFI_STATUS
> > >
> > >
> > > +EFIAPI
> > >
> > >
> > > +SbiRemoteHfenceVvma (
> > >
> > >
> > > +  IN  UINTN                         *HartMask,
> > >
> > >
> > > +  IN  UINTN                          HartMaskBase,
> > >
> > >
> > > +  IN  UINTN                          StartAddr,
> > >
> > >
> > > +  IN  UINTN                          Size
> > >
> > >
> > > +  );
> > >
> > >
> > > +
> > >
> > >
> > > +///
> > >
> > >
> > > +/// Vendor Specific extension space: Extension Ids
> > > 0x09000000 through 0x09FFFFFF
> > >
> > >
> > > +///
> > >
> > >
> > > +
> > >
> > >
> > > +/**
> > >
> > >
> > > +  Call a function in a vendor defined SBI extension
> > >
> > >
> > > +
> > >
> > >
> > > +  ASSERT() if the ExtensionId is not in the designated
> > > SBI Vendor Extension
> > >
> > >
> > > +  Space.
> > >
> > >
> > > +
> > >
> > >
> > > +  @param[in]  ExtensionId          The SBI vendor
> > > extension ID.
> > >
> > >
> > > +  @param[in]  FunctionId           The function ID to
> > > call in this extension.
> > >
> > >
> > > +  @param[in]  NumArgs              How many arguments
> > > are passed.
> > >
> > >
> > > +  @param[in]  ...                  Actual Arguments to
> > > the function.
> > >
> > >
> > > +  @retval EFI_SUCCESS if the SBI function was called
> > > and it was successful
> > >
> > >
> > > +  @retval EFI_INVALID_PARAMETER if NumArgs exceeds 6
> > >
> > >
> > > +  @retval others if the called SBI function returns an
> > > error
> > >
> > >
> > > +**/
> > >
> > >
> > > +EFI_STATUS
> > >
> > >
> > > +EFIAPI
> > >
> > >
> > > +SbiVendorCall (
> > >
> > >
> > > +  IN  UINTN                          ExtensionId,
> > >
> > >
> > > +  IN  UINTN                          FunctionId,
> > >
> > >
> > > +  IN  UINTN                          NumArgs,
> > >
> > >
> > > +  ...
> > >
> > >
> > > +  );
> > >
> > >
> > > +
> > >
> > >
> > > +///
> > >
> > >
> > > +/// Firmware SBI Extension
> > >
> > >
> > > +///
> > >
> > >
> > > +/// This SBI Extension is defined and used by EDK2 only
> > > in order to be able to
> > >
> > >
> > > +/// run PI and DXE phase in S-Mode.
> > >
> > >
> > > +///
> > >
> > >
> > > +
> > >
> > >
> > > +/**
> > >
> > >
> > > +  Get scratch space of the current hart.
> > >
> > >
> > > +
> > >
> > >
> > > +  Please consider using the wrapper
> > > SbiGetFirmwareContext if you only need to
> > >
> > >
> > > +  access the firmware context.
> > >
> > >
> > > +
> > >
> > >
> > > +  @param[out] ScratchSpace         The scratch space
> > > pointer.
> > >
> > >
> > > +  @retval EFI_SUCCESS              The operation
> > > succeeds.
> > >
> > >
> > > +**/
> > >
> > >
> > > +EFI_STATUS
> > >
> > >
> > > +EFIAPI
> > >
> > >
> > > +SbiGetMscratch (
> > >
> > >
> > > +  OUT SBI_SCRATCH                    **ScratchSpace
> > >
> > >
> > > +  );
> > >
> > >
> > > +
> > >
> > >
> > > +/**
> > >
> > >
> > > +  Get scratch space of the given hart id.
> > >
> > >
> > > +
> > >
> > >
> > > +  @param[in]  HartId               The hart id.
> > >
> > >
> > > +  @param[out] ScratchSpace         The scratch space
> > > pointer.
> > >
> > >
> > > +  @retval EFI_SUCCESS              The operation
> > > succeeds.
> > >
> > >
> > > +**/
> > >
> > >
> > > +EFI_STATUS
> > >
> > >
> > > +EFIAPI
> > >
> > >
> > > +SbiGetMscratchHartid (
> > >
> > >
> > > +  IN  UINTN                            HartId,
> > >
> > >
> > > +  OUT SBI_SCRATCH                    **ScratchSpace
> > >
> > >
> > > +  );
> > >
> > >
> > > +
> > >
> > >
> > > +/**
> > >
> > >
> > > +  Get firmware context of the calling hart.
> > >
> > >
> > > +
> > >
> > >
> > > +  @param[out] FirmwareContext      The firmware context
> > > pointer.
> > >
> > >
> > > +  @retval EFI_SUCCESS              The operation
> > > succeeds.
> > >
> > >
> > > +**/
> > >
> > >
> > > +EFI_STATUS
> > >
> > >
> > > +EFIAPI
> > >
> > >
> > > +SbiGetFirmwareContext (
> > >
> > >
> > > +  OUT EFI_RISCV_OPENSBI_FIRMWARE_CONTEXT
> > > **FirmwareContext
> > >
> > >
> > > +  );
> > >
> > >
> > > +
> > >
> > >
> > > +/**
> > >
> > >
> > > +  Set firmware context of the calling hart.
> > >
> > >
> > > +
> > >
> > >
> > > +  @param[in] FirmwareContext       The firmware context
> > > pointer.
> > >
> > >
> > > +  @retval EFI_SUCCESS              The operation
> > > succeeds.
> > >
> > >
> > > +**/
> > >
> > >
> > > +EFI_STATUS
> > >
> > >
> > > +EFIAPI
> > >
> > >
> > > +SbiSetFirmwareContext (
> > >
> > >
> > > +  IN EFI_RISCV_OPENSBI_FIRMWARE_CONTEXT
> > > *FirmwareContext
> > >
> > >
> > > +  );
> > >
> > >
> > > +
> > >
> > >
> > > +#endif
> > >
> > >
> > > diff --git a/Silicon/RISC-
> > > V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.c
> > > b/Silicon/RISC-
> > > V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.c
> > > new file mode 100644
> > > index 000000000000..0df505d2675b
> > > --- /dev/null
> > > +++ b/Silicon/RISC-
> > > V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.c
> > > @@ -0,0 +1,897 @@
> > > +/** @file
> > >
> > >
> > > +  Instance of the SBI ecall library.
> > >
> > >
> > > +
> > >
> > >
> > > +  It allows calling an SBI function via an ecall from
> > > S-Mode.
> > >
> > >
> > > +
> > >
> > >
> > > +  The legacy extensions are not included because they
> > > are not necessary.
> > >
> > >
> > > +  They would be:
> > >
> > >
> > > +  - SbiLegacySetTimer            -> Use SbiSetTimer
> > >
> > >
> > > +  - SbiLegacyConsolePutChar      -> No replacement -
> > > Use regular UEFI functions
> > >
> > >
> > > +  - SbiLegacyConsoleGetChar      -> No replacement -
> > > Use regular UEFI functions
> > >
> > >
> > > +  - SbiLegacyClearIpi            -> Write 0 to SSIP
> > >
> > >
> > > +  - SbiLegacySendIpi             -> Use SbiSendIpi
> > >
> > >
> > > +  - SbiLegacyRemoteFenceI        -> Use SbiRemoteFenceI
> > >
> > >
> > > +  - SbiLegacyRemoteSfenceVma     -> Use
> > > SbiRemoteSfenceVma
> > >
> > >
> > > +  - SbiLegacyRemoteSfenceVmaAsid -> Use
> > > SbiRemoteSfenceVmaAsid
> > >
> > >
> > > +  - SbiLegacyShutdown            -> Wait for new System
> > > Reset extension
> > >
> > >
> > > +
> > >
> > >
> > > +  Copyright (c) 2020, Hewlett Packard Development LP.
> > > All rights reserved.<BR>
> > >
> > >
> > > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > >
> > >
> > > +
> > >
> > >
> > > +  @par Revision Reference:
> > >
> > >
> > > +    - OpenSBI Version 0.6
> > >
> > >
> > > +**/
> > >
> > >
> > > +
> > >
> > >
> > > +#include <IndustryStandard/RiscVOpensbi.h>
> > >
> > >
> > > +#include <Library/BaseMemoryLib.h>
> > >
> > >
> > > +#include <Library/DebugLib.h>
> > >
> > >
> > > +#include <Library/RiscVEdk2SbiLib.h>
> > >
> > >
> > > +#include <sbi/riscv_asm.h>
> > >
> > >
> > > +#include <sbi/sbi_hart.h>
> > >
> > >
> > > +#include <sbi/sbi_types.h>
> > >
> > >
> > > +#include <sbi/sbi_init.h>
> > >
> > >
> > > +
> > >
> > >
> > > +
> > >
> > >
> > > +//
> > >
> > >
> > > +// Maximum arguments for SBI ecall
> > >
> > >
> > > +// It's possible to pass more but no SBI call uses more
> > > as of SBI 0.2.
> > >
> > >
> > > +// The additional arguments would have to be passed on
> > > the stack instead of as
> > >
> > >
> > > +// registers, like it's done now.
> > >
> > >
> > > +//
> > >
> > >
> > > +#define SBI_CALL_MAX_ARGS 6
> > >
> > >
> > > +
> > >
> > >
> > > +/**
> > >
> > >
> > > +  Call SBI call using ecall instruction.
> > >
> > >
> > > +
> > >
> > >
> > > +  Asserts when NumArgs exceeds SBI_CALL_MAX_ARGS.
> > >
> > >
> > > +
> > >
> > >
> > > +  @param[in] ExtId    SBI extension ID.
> > >
> > >
> > > +  @param[in] FuncId   SBI function ID.
> > >
> > >
> > > +  @param[in] NumArgs  Number of arguments to pass to
> > > the ecall.
> > >
> > >
> > > +  @param[in] ...      Argument list for the ecall.
> > >
> > >
> > > +
> > >
> > >
> > > +  @retval  Returns SbiRet structure with value and
> > > error code.
> > >
> > >
> > > +
> > >
> > >
> > > +**/
> > >
> > >
> > > +STATIC
> > >
> > >
> > > +SbiRet
> > >
> > >
> > > +EFIAPI
> > >
> > >
> > > +SbiCall(
> > >
> > >
> > > +  IN  UINTN ExtId,
> > >
> > >
> > > +  IN  UINTN FuncId,
> > >
> > >
> > > +  IN  UINTN NumArgs,
> > >
> > >
> > > +  ...
> > >
> > >
> > > +  )
> > >
> > >
> > > +{
> > >
> > >
> > > +    UINTN I;
> > >
> > >
> > > +    SbiRet Ret;
> > >
> > >
> > > +    UINTN Args[SBI_CALL_MAX_ARGS];
> > >
> > >
> > > +    VA_LIST ArgList;
> > >
> > >
> > > +    VA_START (ArgList, NumArgs);
> > >
> > >
> > > +
> > >
> > >
> > > +    ASSERT (NumArgs <= SBI_CALL_MAX_ARGS);
> > >
> > >
> > > +
> > >
> > >
> > > +    for (I = 0; I < SBI_CALL_MAX_ARGS; I++) {
> > >
> > >
> > > +      if (I < NumArgs) {
> > >
> > >
> > > +        Args[I] = VA_ARG (ArgList, UINTN);
> > >
> > >
> > > +      } else {
> > >
> > >
> > > +        // Default to 0 for all arguments that are not
> > > given
> > >
> > >
> > > +        Args[I] = 0;
> > >
> > >
> > > +      }
> > >
> > >
> > > +    }
> > >
> > >
> > > +
> > >
> > >
> > > +    VA_END(ArgList);
> > >
> > >
> > > +
> > >
> > >
> > > +    register UINTN a0 asm ("a0") = Args[0];
> > >
> > >
> > > +    register UINTN a1 asm ("a1") = Args[1];
> > >
> > >
> > > +    register UINTN a2 asm ("a2") = Args[2];
> > >
> > >
> > > +    register UINTN a3 asm ("a3") = Args[3];
> > >
> > >
> > > +    register UINTN a4 asm ("a4") = Args[4];
> > >
> > >
> > > +    register UINTN a5 asm ("a5") = Args[5];
> > >
> > >
> > > +    register UINTN a6 asm ("a6") = (UINTN)(FuncId);
> > >
> > >
> > > +    register UINTN a7 asm ("a7") = (UINTN)(ExtId);
> > >
> > >
> > > +    asm volatile ("ecall" \
> > >
> > >
> > > +         : "+r" (a0), "+r" (a1) \
> > >
> > >
> > > +         : "r" (a2), "r" (a3), "r" (a4), "r" (a5), "r"
> > > (a6), "r" (a7) \
> > >
> > >
> > > +         : "memory"); \
> > >
> > >
> > > +    Ret.Error = a0;
> > >
> > >
> > > +    Ret.Value = a1;
> > >
> > >
> > > +    return Ret;
> > >
> > >
> > > +}
> > >
> > >
> > > +
> > >
> > >
> > > +/**
> > >
> > >
> > > +  Translate SBI error code to EFI status.
> > >
> > >
> > > +
> > >
> > >
> > > +  @param[in] SbiError   SBI error code
> > >
> > >
> > > +  @retval EFI_STATUS
> > >
> > >
> > > +**/
> > >
> > >
> > > +
> > >
> > >
> > > +STATIC
> > >
> > >
> > > +EFI_STATUS
> > >
> > >
> > > +EFIAPI
> > >
> > >
> > > +TranslateError(
> > >
> > >
> > > +  IN  UINTN SbiError
> > >
> > >
> > > +  )
> > >
> > >
> > > +{
> > >
> > >
> > > +  switch (SbiError) {
> > >
> > >
> > > +    case SBI_SUCCESS:
> > >
> > >
> > > +      return EFI_SUCCESS;
> > >
> > >
> > > +    case SBI_ERR_FAILED:
> > >
> > >
> > > +      return EFI_DEVICE_ERROR;
> > >
> > >
> > > +      break;
> > >
> > >
> > > +    case SBI_ERR_NOT_SUPPORTED:
> > >
> > >
> > > +      return EFI_UNSUPPORTED;
> > >
> > >
> > > +      break;
> > >
> > >
> > > +    case SBI_ERR_INVALID_PARAM:
> > >
> > >
> > > +      return EFI_INVALID_PARAMETER;
> > >
> > >
> > > +      break;
> > >
> > >
> > > +    case SBI_ERR_DENIED:
> > >
> > >
> > > +      return EFI_ACCESS_DENIED;
> > >
> > >
> > > +      break;
> > >
> > >
> > > +    case SBI_ERR_INVALID_ADDRESS:
> > >
> > >
> > > +      return EFI_LOAD_ERROR;
> > >
> > >
> > > +      break;
> > >
> > >
> > > +    case SBI_ERR_ALREADY_AVAILABLE:
> > >
> > >
> > > +      return EFI_ALREADY_STARTED;
> > >
> > >
> > > +      break;
> > >
> > >
> > > +    default:
> > >
> > >
> > > +      //
> > >
> > >
> > > +      // Reaches here only if SBI has defined a new
> > > error type
> > >
> > >
> > > +      //
> > >
> > >
> > > +      ASSERT (FALSE);
> > >
> > >
> > > +      return EFI_UNSUPPORTED;
> > >
> > >
> > > +      break;
> > >
> > >
> > > +  }
> > >
> > >
> > > +}
> > >
> > >
> > > +
> > >
> > >
> > > +//
> > >
> > >
> > > +// OpenSBI library interface function for the base
> > > extension
> > >
> > >
> > > +//
> > >
> > >
> > > +
> > >
> > >
> > > +/**
> > >
> > >
> > > +  Get the implemented SBI specification version
> > >
> > >
> > > +
> > >
> > >
> > > +  The minor number of the SBI specification is encoded
> > > in the low 24 bits,
> > >
> > >
> > > +  with the major number encoded in the next 7 bits.
> > > Bit 32 must be 0 and is
> > >
> > >
> > > +  reserved for future expansion.
> > >
> > >
> > > +
> > >
> > >
> > > +  @param[out] SpecVersion          The Version of the
> > > SBI specification.
> > >
> > >
> > > +**/
> > >
> > >
> > > +VOID
> > >
> > >
> > > +EFIAPI
> > >
> > >
> > > +SbiGetSpecVersion (
> > >
> > >
> > > +  OUT UINTN                       *SpecVersion
> > >
> > >
> > > +  )
> > >
> > >
> > > +{
> > >
> > >
> > > +  SbiRet Ret = SbiCall (SBI_EXT_BASE,
> > > SBI_EXT_BASE_GET_SPEC_VERSION, 0);
> > >
> > >
> > > +
> > >
> > >
> > > +  if (!Ret.Error) {
> > >
> > >
> > > +    *SpecVersion = (UINTN)Ret.Value;
> > >
> > >
> > > +  }
> > >
> > >
> > > +}
> > >
> > >
> > > +
> > >
> > >
> > > +/**
> > >
> > >
> > > +  Get the SBI implementation ID
> > >
> > >
> > > +
> > >
> > >
> > > +  This ID is used to idenetify a specific SBI
> > > implementation in order to work
> > >
> > >
> > > +  around any quirks it might have.
> > >
> > >
> > > +
> > >
> > >
> > > +  @param[out] ImplId               The ID of the SBI
> > > implementation.
> > >
> > >
> > > +**/
> > >
> > >
> > > +VOID
> > >
> > >
> > > +EFIAPI
> > >
> > >
> > > +SbiGetImplId (
> > >
> > >
> > > +  OUT UINTN                       *ImplId
> > >
> > >
> > > +  )
> > >
> > >
> > > +{
> > >
> > >
> > > +  SbiRet Ret = SbiCall (SBI_EXT_BASE,
> > > SBI_EXT_BASE_GET_IMP_ID, 0);
> > >
> > >
> > > +  *ImplId = (UINTN)Ret.Value;
> > >
> > >
> > > +}
> > >
> > >
> > > +
> > >
> > >
> > > +/**
> > >
> > >
> > > +  Get the SBI implementation version
> > >
> > >
> > > +
> > >
> > >
> > > +  The version of this SBI implementation.
> > >
> > >
> > > +  The encoding of this number is determined by the
> > > specific SBI implementation.
> > >
> > >
> > > +
> > >
> > >
> > > +  @param[out] ImplVersion          The version of the
> > > SBI implementation.
> > >
> > >
> > > +**/
> > >
> > >
> > > +VOID
> > >
> > >
> > > +EFIAPI
> > >
> > >
> > > +SbiGetImplVersion (
> > >
> > >
> > > +  OUT UINTN                       *ImplVersion
> > >
> > >
> > > +  )
> > >
> > >
> > > +{
> > >
> > >
> > > +  SbiRet Ret = SbiCall (SBI_EXT_BASE,
> > > SBI_EXT_BASE_GET_IMP_VERSION, 0);
> > >
> > >
> > > +  *ImplVersion = (UINTN)Ret.Value;
> > >
> > >
> > > +}
> > >
> > >
> > > +
> > >
> > >
> > > +/**
> > >
> > >
> > > +  Probe whether an SBI extension is available
> > >
> > >
> > > +
> > >
> > >
> > > +  ProbeResult is set to 0 if the extension is not
> > > available or to an extension
> > >
> > >
> > > +  specified value if it is available.
> > >
> > >
> > > +
> > >
> > >
> > > +  @param[in]  ExtensionId          The extension ID.
> > >
> > >
> > > +  @param[out] ProbeResult          The return value of
> > > the probe.
> > >
> > >
> > > +**/
> > >
> > >
> > > +VOID
> > >
> > >
> > > +EFIAPI
> > >
> > >
> > > +SbiProbeExtension (
> > >
> > >
> > > +  IN  INTN                         ExtensionId,
> > >
> > >
> > > +  OUT INTN                        *ProbeResult
> > >
> > >
> > > +  )
> > >
> > >
> > > +{
> > >
> > >
> > > +  SbiRet Ret = SbiCall (SBI_EXT_BASE,
> > > SBI_EXT_BASE_PROBE_EXT, 0);
> > >
> > >
> > > +  *ProbeResult = (UINTN)Ret.Value;
> > >
> > >
> > > +}
> > >
> > >
> > > +
> > >
> > >
> > > +/**
> > >
> > >
> > > +  Get the CPU's vendor ID
> > >
> > >
> > > +
> > >
> > >
> > > +  Reads the mvendorid CSR.
> > >
> > >
> > > +
> > >
> > >
> > > +  @param[out] MachineVendorId      The CPU's vendor ID.
> > >
> > >
> > > +**/
> > >
> > >
> > > +VOID
> > >
> > >
> > > +EFIAPI
> > >
> > >
> > > +SbiGetMachineVendorId (
> > >
> > >
> > > +  OUT UINTN                       *MachineVendorId
> > >
> > >
> > > +  )
> > >
> > >
> > > +{
> > >
> > >
> > > +  SbiRet Ret = SbiCall (SBI_EXT_BASE,
> > > SBI_EXT_BASE_GET_MVENDORID, 0);
> > >
> > >
> > > +  *MachineVendorId = (UINTN)Ret.Value;
> > >
> > >
> > > +}
> > >
> > >
> > > +
> > >
> > >
> > > +/**
> > >
> > >
> > > +  Get the CPU's architecture ID
> > >
> > >
> > > +
> > >
> > >
> > > +  Reads the marchid CSR.
> > >
> > >
> > > +
> > >
> > >
> > > +  @param[out] MachineArchId        The CPU's
> > > architecture ID.
> > >
> > >
> > > +**/
> > >
> > >
> > > +VOID
> > >
> > >
> > > +EFIAPI
> > >
> > >
> > > +SbiGetMachineArchId (
> > >
> > >
> > > +  OUT UINTN                       *MachineArchId
> > >
> > >
> > > +  )
> > >
> > >
> > > +{
> > >
> > >
> > > +  SbiRet Ret = SbiCall (SBI_EXT_BASE,
> > > SBI_EXT_BASE_GET_MARCHID, 0);
> > >
> > >
> > > +  *MachineArchId = (UINTN)Ret.Value;
> > >
> > >
> > > +}
> > >
> > >
> > > +
> > >
> > >
> > > +/**
> > >
> > >
> > > +  Get the CPU's architecture ID
> > >
> > >
> > > +
> > >
> > >
> > > +  Reads the marchid CSR.
> > >
> > >
> > > +
> > >
> > >
> > > +  @param[out] MachineImplId        The CPU's
> > > implementation ID.
> > >
> > >
> > > +**/
> > >
> > >
> > > +VOID
> > >
> > >
> > > +EFIAPI
> > >
> > >
> > > +SbiGetMachineImplId (
> > >
> > >
> > > +  OUT UINTN                       *MachineImplId
> > >
> > >
> > > +  )
> > >
> > >
> > > +{
> > >
> > >
> > > +  SbiRet Ret = SbiCall (SBI_EXT_BASE,
> > > SBI_EXT_BASE_GET_MIMPID, 0);
> > >
> > >
> > > +  *MachineImplId = (UINTN)Ret.Value;
> > >
> > >
> > > +}
> > >
> > >
> > > +
> > >
> > >
> > > +//
> > >
> > >
> > > +// SBI interface function for the hart state management
> > > extension
> > >
> > >
> > > +//
> > >
> > >
> > > +
> > >
> > >
> > > +/**
> > >
> > >
> > > +  Politely ask the SBI to start a given hart.
> > >
> > >
> > > +
> > >
> > >
> > > +  This call may return before the hart has actually
> > > started executing, if the
> > >
> > >
> > > +  SBI implementation can guarantee that the hart is
> > > actually going to start.
> > >
> > >
> > > +
> > >
> > >
> > > +  Before the hart jumps to StartAddr, the hart MUST
> > > configure PMP if present
> > >
> > >
> > > +  and switch to S-mode.
> > >
> > >
> > > +
> > >
> > >
> > > +  @param[in]  HartId               The id of the hart
> > > to start.
> > >
> > >
> > > +  @param[in]  StartAddr            The physical
> > > address, where the hart starts
> > >
> > >
> > > +                                   executing from.
> > >
> > >
> > > +  @param[in]  Priv                 An XLEN-bit value,
> > > which will be in register
> > >
> > >
> > > +                                   a1 when the hart
> > > starts.
> > >
> > >
> > > +  @retval EFI_SUCCESS              Hart was stopped and
> > > will start executing from StartAddr.
> > >
> > >
> > > +  @retval EFI_LOAD_ERROR           StartAddr is not
> > > valid, possibly due to following reasons:
> > >
> > >
> > > +                                     - It is not a
> > > valid physical address.
> > >
> > >
> > > +                                     - The address is
> > > prohibited by PMP to run in
> > >
> > >
> > > +                                       supervisor mode.
> > >
> > >
> > > +  @retval EFI_INVALID_PARAMETER    HartId is not a
> > > valid hart id
> > >
> > >
> > > +  @retval EFI_ALREADY_STARTED      The hart is already
> > > running.
> > >
> > >
> > > +  @retval other                    The start request
> > > failed for unknown reasons.
> > >
> > >
> > > +**/
> > >
> > >
> > > +EFI_STATUS
> > >
> > >
> > > +EFIAPI
> > >
> > >
> > > +SbiHartStart (
> > >
> > >
> > > +  IN  UINTN                          HartId,
> > >
> > >
> > > +  IN  UINTN                          StartAddr,
> > >
> > >
> > > +  IN  UINTN                          Priv
> > >
> > >
> > > +  )
> > >
> > >
> > > +{
> > >
> > >
> > > +  SbiRet Ret = SbiCall (
> > >
> > >
> > > +                 SBI_EXT_HSM,
> > >
> > >
> > > +                 SBI_EXT_HSM_HART_START,
> > >
> > >
> > > +                 3,
> > >
> > >
> > > +                 HartId,
> > >
> > >
> > > +                 StartAddr,
> > >
> > >
> > > +                 Priv
> > >
> > >
> > > +                 );
> > >
> > >
> > > +  return TranslateError (Ret.Error);
> > >
> > >
> > > +}
> > >
> > >
> > > +
> > >
> > >
> > > +/**
> > >
> > >
> > > +  Return execution of the calling hart to SBI.
> > >
> > >
> > > +
> > >
> > >
> > > +  MUST be called in S-Mode with user interrupts
> > > disabled.
> > >
> > >
> > > +  This call is not expected to return, unless a failure
> > > occurs.
> > >
> > >
> > > +
> > >
> > >
> > > +  @retval     EFI_SUCCESS          Never occurs. When
> > > successful, the call does not return.
> > >
> > >
> > > +  @retval     other                Failed to stop hard
> > > for an unknown reason.
> > >
> > >
> > > +**/
> > >
> > >
> > > +EFI_STATUS
> > >
> > >
> > > +EFIAPI
> > >
> > >
> > > +SbiHartStop (
> > >
> > >
> > > +  )
> > >
> > >
> > > +{
> > >
> > >
> > > +  SbiRet Ret = SbiCall (SBI_EXT_HSM,
> > > SBI_EXT_HSM_HART_STOP, 0);
> > >
> > >
> > > +  return TranslateError (Ret.Error);
> > >
> > >
> > > +}
> > >
> > >
> > > +
> > >
> > >
> > > +/**
> > >
> > >
> > > +  Get the current status of a hart.
> > >
> > >
> > > +
> > >
> > >
> > > +  Since harts can transition between states at any
> > > time, the status retrieved
> > >
> > >
> > > +  by this function may already be out of date, once it
> > > returns.
> > >
> > >
> > > +
> > >
> > >
> > > +  Possible values for HartStatus are:
> > >
> > >
> > > +  0: STARTED
> > >
> > >
> > > +  1: STOPPED
> > >
> > >
> > > +  2: START_REQUEST_PENDING
> > >
> > >
> > > +  3: STOP_REQUEST_PENDING
> > >
> > >
> > > +
> > >
> > >
> > > +  @param[out] HartStatus           The pointer in which
> > > the hart's status is
> > >
> > >
> > > +                                   stored.
> > >
> > >
> > > +  @retval EFI_SUCCESS              The operation
> > > succeeds.
> > >
> > >
> > > +  @retval EFI_INVALID_PARAMETER    A parameter is
> > > invalid.
> > >
> > >
> > > +**/
> > >
> > >
> > > +EFI_STATUS
> > >
> > >
> > > +EFIAPI
> > >
> > >
> > > +SbiHartGetStatus (
> > >
> > >
> > > +  IN  UINTN                          HartId,
> > >
> > >
> > > +  OUT UINTN                         *HartStatus
> > >
> > >
> > > +  )
> > >
> > >
> > > +{
> > >
> > >
> > > +  SbiRet Ret = SbiCall (SBI_EXT_HSM,
> > > SBI_EXT_HSM_HART_GET_STATUS, 1, HartId);
> > >
> > >
> > > +
> > >
> > >
> > > +  if (!Ret.Error) {
> > >
> > >
> > > +    *HartStatus = (UINTN)Ret.Value;
> > >
> > >
> > > +  }
> > >
> > >
> > > +
> > >
> > >
> > > +  return TranslateError (Ret.Error);
> > >
> > >
> > > +}
> > >
> > >
> > > +
> > >
> > >
> > > +/**
> > >
> > >
> > > +  Clear pending timer interrupt bit and set timer for
> > > next event after Time.
> > >
> > >
> > > +
> > >
> > >
> > > +  To clear the timer without scheduling a timer event,
> > > set Time to a
> > >
> > >
> > > +  practically infinite value or mask the timer
> > > interrupt by clearing sie.STIE.
> > >
> > >
> > > +
> > >
> > >
> > > +  @param[in]  Time                 The time offset to
> > > the next scheduled timer interrupt.
> > >
> > >
> > > +**/
> > >
> > >
> > > +VOID
> > >
> > >
> > > +EFIAPI
> > >
> > >
> > > +SbiSetTimer (
> > >
> > >
> > > +  IN  UINT64                         Time
> > >
> > >
> > > +  )
> > >
> > >
> > > +{
> > >
> > >
> > > +  SbiCall (SBI_EXT_TIME, SBI_EXT_TIME_SET_TIMER, 1,
> > > Time);
> > >
> > >
> > > +}
> > >
> > >
> > > +
> > >
> > >
> > > +EFI_STATUS
> > >
> > >
> > > +EFIAPI
> > >
> > >
> > > +SbiSendIpi (
> > >
> > >
> > > +  IN  UINTN                         *HartMask,
> > >
> > >
> > > +  IN  UINTN                          HartMaskBase
> > >
> > >
> > > +  )
> > >
> > >
> > > +{
> > >
> > >
> > > +  SbiRet Ret = SbiCall (
> > >
> > >
> > > +                 SBI_EXT_IPI,
> > >
> > >
> > > +                 SBI_EXT_IPI_SEND_IPI,
> > >
> > >
> > > +                 2,
> > >
> > >
> > > +                 (UINTN)HartMask,
> > >
> > >
> > > +                 HartMaskBase
> > >
> > >
> > > +                 );
> > >
> > >
> > > +  return TranslateError (Ret.Error);
> > >
> > >
> > > +}
> > >
> > >
> > > +
> > >
> > >
> > > +/**
> > >
> > >
> > > +  Instructs remote harts to execute a FENCE.I
> > > instruction.
> > >
> > >
> > > +
> > >
> > >
> > > +  @param[in]  HartMask             Scalar bit-vector
> > > containing hart ids
> > >
> > >
> > > +  @param[in]  HartMaskBase         The starting hartid
> > > from which the bit-vector
> > >
> > >
> > > +                                   must be computed. If
> > > set to -1, HartMask is
> > >
> > >
> > > +                                   ignored and all
> > > harts are considered.
> > >
> > >
> > > +  @retval EFI_SUCCESS              IPI was sent to all
> > > the targeted harts.
> > >
> > >
> > > +  @retval EFI_INVALID_PARAMETER    Either
> > > hart_mask_base or any of the hartid
> > >
> > >
> > > +                                   from hart_mask is
> > > not valid i.e. either the
> > >
> > >
> > > +                                   hartid is not
> > > enabled by the platform or is
> > >
> > >
> > > +                                   not available to the
> > > supervisor.
> > >
> > >
> > > +**/
> > >
> > >
> > > +EFI_STATUS
> > >
> > >
> > > +EFIAPI
> > >
> > >
> > > +SbiRemoteFenceI (
> > >
> > >
> > > +  IN  UINTN                         *HartMask,
> > >
> > >
> > > +  IN  UINTN                          HartMaskBase
> > >
> > >
> > > +  )
> > >
> > >
> > > +{
> > >
> > >
> > > +  SbiRet Ret = SbiCall (
> > >
> > >
> > > +                 SBI_EXT_RFENCE,
> > >
> > >
> > > +                 SBI_EXT_RFENCE_REMOTE_FENCE_I,
> > >
> > >
> > > +                 2,
> > >
> > >
> > > +                 (UINTN)HartMask,
> > >
> > >
> > > +                 HartMaskBase
> > >
> > >
> > > +                 );
> > >
> > >
> > > +  return TranslateError (Ret.Error);
> > >
> > >
> > > +}
> > >
> > >
> > > +
> > >
> > >
> > > +/**
> > >
> > >
> > > +  Instructs the remote harts to execute one or more
> > > SFENCE.VMA instructions.
> > >
> > >
> > > +
> > >
> > >
> > > +  The SFENCE.VMA covers the range of virtual addresses
> > > between StartAaddr and Size.
> > >
> > >
> > > +
> > >
> > >
> > > +  The remote fence function acts as a full tlb flush if
> > > * StartAddr and size
> > >
> > >
> > > +  are both 0 * size is equal to 2^XLEN-1
> > >
> > >
> > > +
> > >
> > >
> > > +  @param[in]  HartMask             Scalar bit-vector
> > > containing hart ids
> > >
> > >
> > > +  @param[in]  HartMaskBase         The starting hartid
> > > from which the bit-vector
> > >
> > >
> > > +                                   must be computed. If
> > > set to -1, HartMask is
> > >
> > >
> > > +                                   ignored and all
> > > harts are considered.
> > >
> > >
> > > +  @param[in]  StartAddr            The first address of
> > > the affected range.
> > >
> > >
> > > +  @param[in]  Size                 How many addresses
> > > are affected.
> > >
> > >
> > > +  @retval EFI_SUCCESS              IPI was sent to all
> > > the targeted harts.
> > >
> > >
> > > +  @retval EFI_LOAD_ERROR           StartAddr or Size is
> > > not valid.
> > >
> > >
> > > +  @retval EFI_INVALID_PARAMETER    Either
> > > hart_mask_base or any of the hartid
> > >
> > >
> > > +                                   from hart_mask is
> > > not valid i.e. either the
> > >
> > >
> > > +                                   hartid is not
> > > enabled by the platform or is
> > >
> > >
> > > +                                   not available to the
> > > supervisor.
> > >
> > >
> > > +**/
> > >
> > >
> > > +EFI_STATUS
> > >
> > >
> > > +EFIAPI
> > >
> > >
> > > +SbiRemoteSfenceVma (
> > >
> > >
> > > +  IN  UINTN                         *HartMask,
> > >
> > >
> > > +  IN  UINTN                          HartMaskBase,
> > >
> > >
> > > +  IN  UINTN                          StartAddr,
> > >
> > >
> > > +  IN  UINTN                          Size
> > >
> > >
> > > +  )
> > >
> > >
> > > +{
> > >
> > >
> > > +  SbiRet Ret = SbiCall (
> > >
> > >
> > > +                 SBI_EXT_RFENCE,
> > >
> > >
> > > +                 SBI_EXT_RFENCE_REMOTE_SFENCE_VMA,
> > >
> > >
> > > +                 4,
> > >
> > >
> > > +                 (UINTN)HartMask,
> > >
> > >
> > > +                 HartMaskBase,
> > >
> > >
> > > +                 StartAddr,
> > >
> > >
> > > +                 Size
> > >
> > >
> > > +                 );
> > >
> > >
> > > +  return TranslateError (Ret.Error);
> > >
> > >
> > > +}
> > >
> > >
> > > +
> > >
> > >
> > > +/**
> > >
> > >
> > > +  Instructs the remote harts to execute one or more
> > > SFENCE.VMA instructions.
> > >
> > >
> > > +
> > >
> > >
> > > +  The SFENCE.VMA covers the range of virtual addresses
> > > between StartAaddr and Size.
> > >
> > >
> > > +  Covers only the given ASID.
> > >
> > >
> > > +
> > >
> > >
> > > +  The remote fence function acts as a full tlb flush if
> > > * StartAddr and size
> > >
> > >
> > > +  are both 0 * size is equal to 2^XLEN-1
> > >
> > >
> > > +
> > >
> > >
> > > +  @param[in]  HartMask             Scalar bit-vector
> > > containing hart ids
> > >
> > >
> > > +  @param[in]  HartMaskBase         The starting hartid
> > > from which the bit-vector
> > >
> > >
> > > +                                   must be computed. If
> > > set to -1, HartMask is
> > >
> > >
> > > +                                   ignored and all
> > > harts are considered.
> > >
> > >
> > > +  @param[in]  StartAddr            The first address of
> > > the affected range.
> > >
> > >
> > > +  @param[in]  Size                 How many addresses
> > > are affected.
> > >
> > >
> > > +  @retval EFI_SUCCESS              IPI was sent to all
> > > the targeted harts.
> > >
> > >
> > > +  @retval EFI_LOAD_ERROR           StartAddr or Size is
> > > not valid.
> > >
> > >
> > > +  @retval EFI_INVALID_PARAMETER    Either
> > > hart_mask_base or any of the hartid
> > >
> > >
> > > +                                   from hart_mask is
> > > not valid i.e. either the
> > >
> > >
> > > +                                   hartid is not
> > > enabled by the platform or is
> > >
> > >
> > > +                                   not available to the
> > > supervisor.
> > >
> > >
> > > +**/
> > >
> > >
> > > +EFI_STATUS
> > >
> > >
> > > +EFIAPI
> > >
> > >
> > > +SbiRemoteSfenceVmaAsid (
> > >
> > >
> > > +  IN  UINTN                         *HartMask,
> > >
> > >
> > > +  IN  UINTN                          HartMaskBase,
> > >
> > >
> > > +  IN  UINTN                          StartAddr,
> > >
> > >
> > > +  IN  UINTN                          Size,
> > >
> > >
> > > +  IN  UINTN                          Asid
> > >
> > >
> > > +  )
> > >
> > >
> > > +{
> > >
> > >
> > > +  SbiRet Ret = SbiCall (
> > >
> > >
> > > +                 SBI_EXT_RFENCE,
> > >
> > >
> > > +                 SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID,
> > >
> > >
> > > +                 5,
> > >
> > >
> > > +                 (UINTN)HartMask,
> > >
> > >
> > > +                 HartMaskBase,
> > >
> > >
> > > +                 StartAddr,
> > >
> > >
> > > +                 Size,
> > >
> > >
> > > +                 Asid
> > >
> > >
> > > +                 );
> > >
> > >
> > > +  return TranslateError (Ret.Error);
> > >
> > >
> > > +}
> > >
> > >
> > > +
> > >
> > >
> > > +/**
> > >
> > >
> > > +  Instructs the remote harts to execute one or more
> > > SFENCE.GVMA instructions.
> > >
> > >
> > > +
> > >
> > >
> > > +  The SFENCE.GVMA covers the range of virtual addresses
> > > between StartAaddr and Size.
> > >
> > >
> > > +  Covers only the given VMID.
> > >
> > >
> > > +  This function call is only valid for harts
> > > implementing the hypervisor extension.
> > >
> > >
> > > +
> > >
> > >
> > > +  The remote fence function acts as a full tlb flush if
> > > * StartAddr and size
> > >
> > >
> > > +  are both 0 * size is equal to 2^XLEN-1
> > >
> > >
> > > +
> > >
> > >
> > > +  @param[in]  HartMask             Scalar bit-vector
> > > containing hart ids
> > >
> > >
> > > +  @param[in]  HartMaskBase         The starting hartid
> > > from which the bit-vector
> > >
> > >
> > > +                                   must be computed. If
> > > set to -1, HartMask is
> > >
> > >
> > > +                                   ignored and all
> > > harts are considered.
> > >
> > >
> > > +  @param[in]  StartAddr            The first address of
> > > the affected range.
> > >
> > >
> > > +  @param[in]  Size                 How many addresses
> > > are affected.
> > >
> > >
> > > +  @retval EFI_SUCCESS              IPI was sent to all
> > > the targeted harts.
> > >
> > >
> > > +  @retval EFI_LOAD_ERROR           StartAddr or Size is
> > > not valid.
> > >
> > >
> > > +  @retval EFI_UNSUPPORTED          SBI does not
> > > implement this function or one
> > >
> > >
> > > +                                   of the target harts
> > > does not support the
> > >
> > >
> > > +                                   hypervisor
> > > extension.
> > >
> > >
> > > +  @retval EFI_INVALID_PARAMETER    Either
> > > hart_mask_base or any of the hartid
> > >
> > >
> > > +                                   from hart_mask is
> > > not valid i.e. either the
> > >
> > >
> > > +                                   hartid is not
> > > enabled by the platform or is
> > >
> > >
> > > +                                   not available to the
> > > supervisor.
> > >
> > >
> > > +**/
> > >
> > >
> > > +EFI_STATUS
> > >
> > >
> > > +EFIAPI
> > >
> > >
> > > +SbiRemoteHFenceGvmaVmid (
> > >
> > >
> > > +  IN  UINTN                         *HartMask,
> > >
> > >
> > > +  IN  UINTN                          HartMaskBase,
> > >
> > >
> > > +  IN  UINTN                          StartAddr,
> > >
> > >
> > > +  IN  UINTN                          Size,
> > >
> > >
> > > +  IN  UINTN                          Vmid
> > >
> > >
> > > +  )
> > >
> > >
> > > +{
> > >
> > >
> > > +  SbiRet Ret = SbiCall (
> > >
> > >
> > > +                 SBI_EXT_RFENCE,
> > >
> > >
> > > +                 SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA,
> > >
> > >
> > > +                 5,
> > >
> > >
> > > +                 (UINTN)HartMask,
> > >
> > >
> > > +                 HartMaskBase,
> > >
> > >
> > > +                 StartAddr,
> > >
> > >
> > > +                 Size,
> > >
> > >
> > > +                 Vmid
> > >
> > >
> > > +                 );
> > >
> > >
> > > +  return TranslateError (Ret.Error);
> > >
> > >
> > > +}
> > >
> > >
> > > +
> > >
> > >
> > > +/**
> > >
> > >
> > > +  Instructs the remote harts to execute one or more
> > > SFENCE.GVMA instructions.
> > >
> > >
> > > +
> > >
> > >
> > > +  The SFENCE.GVMA covers the range of virtual addresses
> > > between StartAaddr and Size.
> > >
> > >
> > > +  This function call is only valid for harts
> > > implementing the hypervisor extension.
> > >
> > >
> > > +
> > >
> > >
> > > +  The remote fence function acts as a full tlb flush if
> > > * StartAddr and size
> > >
> > >
> > > +  are both 0 * size is equal to 2^XLEN-1
> > >
> > >
> > > +
> > >
> > >
> > > +  @param[in]  HartMask             Scalar bit-vector
> > > containing hart ids
> > >
> > >
> > > +  @param[in]  HartMaskBase         The starting hartid
> > > from which the bit-vector
> > >
> > >
> > > +                                   must be computed. If
> > > set to -1, HartMask is
> > >
> > >
> > > +                                   ignored and all
> > > harts are considered.
> > >
> > >
> > > +  @param[in]  StartAddr            The first address of
> > > the affected range.
> > >
> > >
> > > +  @param[in]  Size                 How many addresses
> > > are affected.
> > >
> > >
> > > +  @retval EFI_SUCCESS              IPI was sent to all
> > > the targeted harts.
> > >
> > >
> > > +  @retval EFI_LOAD_ERROR           StartAddr or Size is
> > > not valid.
> > >
> > >
> > > +  @retval EFI_UNSUPPORTED          SBI does not
> > > implement this function or one
> > >
> > >
> > > +                                   of the target harts
> > > does not support the
> > >
> > >
> > > +                                   hypervisor
> > > extension.
> > >
> > >
> > > +  @retval EFI_INVALID_PARAMETER    Either
> > > hart_mask_base or any of the hartid
> > >
> > >
> > > +                                   from hart_mask is
> > > not valid i.e. either the
> > >
> > >
> > > +                                   hartid is not
> > > enabled by the platform or is
> > >
> > >
> > > +                                   not available to the
> > > supervisor.
> > >
> > >
> > > +**/
> > >
> > >
> > > +EFI_STATUS
> > >
> > >
> > > +EFIAPI
> > >
> > >
> > > +SbiRemoteHFenceGvma (
> > >
> > >
> > > +  IN  UINTN                         *HartMask,
> > >
> > >
> > > +  IN  UINTN                          HartMaskBase,
> > >
> > >
> > > +  IN  UINTN                          StartAddr,
> > >
> > >
> > > +  IN  UINTN                          Size
> > >
> > >
> > > +  )
> > >
> > >
> > > +{
> > >
> > >
> > > +  SbiRet Ret = SbiCall (
> > >
> > >
> > > +                 SBI_EXT_RFENCE,
> > >
> > >
> > > +
> > > SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA_VMID,
> > >
> > >
> > > +                 4,
> > >
> > >
> > > +                 (UINTN)HartMask,
> > >
> > >
> > > +                 HartMaskBase,
> > >
> > >
> > > +                 StartAddr,
> > >
> > >
> > > +                 Size
> > >
> > >
> > > +                 );
> > >
> > >
> > > +  return TranslateError (Ret.Error);
> > >
> > >
> > > +}
> > >
> > >
> > > +
> > >
> > >
> > > +/**
> > >
> > >
> > > +  Instructs the remote harts to execute one or more
> > > SFENCE.VVMA instructions.
> > >
> > >
> > > +
> > >
> > >
> > > +  The SFENCE.GVMA covers the range of virtual addresses
> > > between StartAaddr and Size.
> > >
> > >
> > > +  Covers only the given ASID.
> > >
> > >
> > > +  This function call is only valid for harts
> > > implementing the hypervisor extension.
> > >
> > >
> > > +
> > >
> > >
> > > +  The remote fence function acts as a full tlb flush if
> > > * StartAddr and size
> > >
> > >
> > > +  are both 0 * size is equal to 2^XLEN-1
> > >
> > >
> > > +
> > >
> > >
> > > +  @param[in]  HartMask             Scalar bit-vector
> > > containing hart ids
> > >
> > >
> > > +  @param[in]  HartMaskBase         The starting hartid
> > > from which the bit-vector
> > >
> > >
> > > +                                   must be computed. If
> > > set to -1, HartMask is
> > >
> > >
> > > +                                   ignored and all
> > > harts are considered.
> > >
> > >
> > > +  @param[in]  StartAddr            The first address of
> > > the affected range.
> > >
> > >
> > > +  @param[in]  Size                 How many addresses
> > > are affected.
> > >
> > >
> > > +  @retval EFI_SUCCESS              IPI was sent to all
> > > the targeted harts.
> > >
> > >
> > > +  @retval EFI_LOAD_ERROR           StartAddr or Size is
> > > not valid.
> > >
> > >
> > > +  @retval EFI_UNSUPPORTED          SBI does not
> > > implement this function or one
> > >
> > >
> > > +                                   of the target harts
> > > does not support the
> > >
> > >
> > > +                                   hypervisor
> > > extension.
> > >
> > >
> > > +  @retval EFI_INVALID_PARAMETER    Either
> > > hart_mask_base or any of the hartid
> > >
> > >
> > > +                                   from hart_mask is
> > > not valid i.e. either the
> > >
> > >
> > > +                                   hartid is not
> > > enabled by the platform or is
> > >
> > >
> > > +                                   not available to the
> > > supervisor.
> > >
> > >
> > > +**/
> > >
> > >
> > > +EFI_STATUS
> > >
> > >
> > > +EFIAPI
> > >
> > >
> > > +SbiRemoteHFenceVvmaAsid (
> > >
> > >
> > > +  IN  UINTN                         *HartMask,
> > >
> > >
> > > +  IN  UINTN                          HartMaskBase,
> > >
> > >
> > > +  IN  UINTN                          StartAddr,
> > >
> > >
> > > +  IN  UINTN                          Size,
> > >
> > >
> > > +  IN  UINTN                          Asid
> > >
> > >
> > > +  )
> > >
> > >
> > > +{
> > >
> > >
> > > +  SbiRet Ret = SbiCall (
> > >
> > >
> > > +                 SBI_EXT_RFENCE,
> > >
> > >
> > > +                 SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA,
> > >
> > >
> > > +                 5,
> > >
> > >
> > > +                 (UINTN)HartMask,
> > >
> > >
> > > +                 HartMaskBase,
> > >
> > >
> > > +                 StartAddr,
> > >
> > >
> > > +                 Size,
> > >
> > >
> > > +                 Asid
> > >
> > >
> > > +                 );
> > >
> > >
> > > +  return TranslateError (Ret.Error);
> > >
> > >
> > > +}
> > >
> > >
> > > +
> > >
> > >
> > > +/**
> > >
> > >
> > > +  Instructs the remote harts to execute one or more
> > > SFENCE.VVMA instructions.
> > >
> > >
> > > +
> > >
> > >
> > > +  The SFENCE.GVMA covers the range of virtual addresses
> > > between StartAaddr and Size.
> > >
> > >
> > > +  This function call is only valid for harts
> > > implementing the hypervisor extension.
> > >
> > >
> > > +
> > >
> > >
> > > +  The remote fence function acts as a full tlb flush if
> > > * StartAddr and size
> > >
> > >
> > > +  are both 0 * size is equal to 2^XLEN-1
> > >
> > >
> > > +
> > >
> > >
> > > +  @param[in]  HartMask             Scalar bit-vector
> > > containing hart ids
> > >
> > >
> > > +  @param[in]  HartMaskBase         The starting hartid
> > > from which the bit-vector
> > >
> > >
> > > +                                   must be computed. If
> > > set to -1, HartMask is
> > >
> > >
> > > +                                   ignored and all
> > > harts are considered.
> > >
> > >
> > > +  @param[in]  StartAddr            The first address of
> > > the affected range.
> > >
> > >
> > > +  @param[in]  Size                 How many addresses
> > > are affected.
> > >
> > >
> > > +  @retval EFI_SUCCESS              IPI was sent to all
> > > the targeted harts.
> > >
> > >
> > > +  @retval EFI_LOAD_ERROR           StartAddr or Size is
> > > not valid.
> > >
> > >
> > > +  @retval EFI_UNSUPPORTED          SBI does not
> > > implement this function or one
> > >
> > >
> > > +                                   of the target harts
> > > does not support the
> > >
> > >
> > > +                                   hypervisor
> > > extension.
> > >
> > >
> > > +  @retval EFI_INVALID_PARAMETER    Either
> > > hart_mask_base or any of the hartid
> > >
> > >
> > > +                                   from hart_mask is
> > > not valid i.e. either the
> > >
> > >
> > > +                                   hartid is not
> > > enabled by the platform or is
> > >
> > >
> > > +                                   not available to the
> > > supervisor.
> > >
> > >
> > > +**/
> > >
> > >
> > > +EFI_STATUS
> > >
> > >
> > > +EFIAPI
> > >
> > >
> > > +SbiRemoteHFenceVvma (
> > >
> > >
> > > +  IN  UINTN                         *HartMask,
> > >
> > >
> > > +  IN  UINTN                          HartMaskBase,
> > >
> > >
> > > +  IN  UINTN                          StartAddr,
> > >
> > >
> > > +  IN  UINTN                          Size
> > >
> > >
> > > +  )
> > >
> > >
> > > +{
> > >
> > >
> > > +  SbiRet Ret = SbiCall (
> > >
> > >
> > > +                 SBI_EXT_RFENCE,
> > >
> > >
> > > +
> > > SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA_ASID,
> > >
> > >
> > > +                 4,
> > >
> > >
> > > +                 (UINTN)HartMask,
> > >
> > >
> > > +                 HartMaskBase,
> > >
> > >
> > > +                 StartAddr,
> > >
> > >
> > > +                 Size
> > >
> > >
> > > +                 );
> > >
> > >
> > > +  return TranslateError (Ret.Error);
> > >
> > >
> > > +}
> > >
> > >
> > > +
> > >
> > >
> > > +//
> > >
> > >
> > > +// SBI interface function for the vendor extension
> > >
> > >
> > > +//
> > >
> > >
> > > +
> > >
> > >
> > > +/**
> > >
> > >
> > > +  Call a function in a vendor defined SBI extension
> > >
> > >
> > > +
> > >
> > >
> > > +  ASSERT() if the ExtensionId is not in the designated
> > > SBI Vendor Extension
> > >
> > >
> > > +  Space or NumArgs exceeds SBI_CALL_MAX_ARGS.
> > >
> > >
> > > +
> > >
> > >
> > > +  @param[in]  ExtensionId          The SBI vendor
> > > extension ID.
> > >
> > >
> > > +  @param[in]  FunctionId           The function ID to
> > > call in this extension.
> > >
> > >
> > > +  @param[in]  NumArgs              How many arguments
> > > are passed.
> > >
> > >
> > > +  @param[in]  ...                  Actual Arguments to
> > > the function.
> > >
> > >
> > > +  @retval EFI_SUCCESS if the SBI function was called
> > > and it was successful
> > >
> > >
> > > +  @retval others if the called SBI function returns an
> > > error
> > >
> > >
> > > +**/
> > >
> > >
> > > +EFI_STATUS
> > >
> > >
> > > +EFIAPI
> > >
> > >
> > > +SbiVendorCall (
> > >
> > >
> > > +  IN  UINTN                          ExtensionId,
> > >
> > >
> > > +  IN  UINTN                          FunctionId,
> > >
> > >
> > > +  IN  UINTN                          NumArgs,
> > >
> > >
> > > +  ...
> > >
> > >
> > > +  )
> > >
> > >
> > > +{
> > >
> > >
> > > +    SbiRet Ret;
> > >
> > >
> > > +    VA_LIST Args;
> > >
> > >
> > > +    VA_START (Args, NumArgs);
> > >
> > >
> > > +
> > >
> > >
> > > +    ASSERT (ExtensionId >= SBI_EXT_VENDOR_START &&
> > > ExtensionId <= SBI_EXT_VENDOR_END);
> > >
> > >
> > > +    ASSERT (NumArgs <= SBI_CALL_MAX_ARGS);
> > >
> > >
> > > +
> > >
> > >
> > > +    switch (NumArgs) {
> > >
> > >
> > > +      case 0:
> > >
> > >
> > > +        Ret = SbiCall (ExtensionId, FunctionId,
> > > NumArgs);
> > >
> > >
> > > +        break;
> > >
> > >
> > > +      case 1:
> > >
> > >
> > > +        Ret = SbiCall (ExtensionId, FunctionId,
> > > NumArgs, VA_ARG (Args, UINTN));
> > >
> > >
> > > +        break;
> > >
> > >
> > > +      case 2:
> > >
> > >
> > > +        Ret = SbiCall (ExtensionId, FunctionId,
> > > NumArgs, VA_ARG (Args, UINTN),
> > >
> > >
> > > +                       VA_ARG (Args, UINTN));
> > >
> > >
> > > +        break;
> > >
> > >
> > > +      case 3:
> > >
> > >
> > > +        Ret = SbiCall (ExtensionId, FunctionId,
> > > NumArgs, VA_ARG (Args, UINTN),
> > >
> > >
> > > +                       VA_ARG (Args, UINTN), VA_ARG
> > > (Args, UINTN));
> > >
> > >
> > > +        break;
> > >
> > >
> > > +      case 4:
> > >
> > >
> > > +        Ret = SbiCall (ExtensionId, FunctionId,
> > > NumArgs, VA_ARG (Args, UINTN),
> > >
> > >
> > > +                       VA_ARG (Args, UINTN), VA_ARG
> > > (Args, UINTN),
> > >
> > >
> > > +                       VA_ARG (Args, UINTN));
> > >
> > >
> > > +        break;
> > >
> > >
> > > +      case 5:
> > >
> > >
> > > +        Ret = SbiCall (ExtensionId, FunctionId,
> > > NumArgs, VA_ARG (Args, UINTN),
> > >
> > >
> > > +                       VA_ARG (Args, UINTN), VA_ARG
> > > (Args, UINTN),
> > >
> > >
> > > +                       VA_ARG (Args, UINTN), VA_ARG
> > > (Args, UINTN));
> > >
> > >
> > > +        break;
> > >
> > >
> > > +      case 6:
> > >
> > >
> > > +        Ret = SbiCall (ExtensionId, FunctionId,
> > > NumArgs, VA_ARG (Args, UINTN),
> > >
> > >
> > > +                       VA_ARG (Args, UINTN), VA_ARG
> > > (Args, UINTN),
> > >
> > >
> > > +                       VA_ARG (Args, UINTN), VA_ARG
> > > (Args, UINTN),
> > >
> > >
> > > +                       VA_ARG (Args, UINTN));
> > >
> > >
> > > +        break;
> > >
> > >
> > > +      default:
> > >
> > >
> > > +        // Too many args. In theory SBI can handle more
> > > arguments when they are
> > >
> > >
> > > +        // passed on the stack but no SBI extension
> > > uses this, therefore it's
> > >
> > >
> > > +        // not yet implemented here.
> > >
> > >
> > > +        return EFI_INVALID_PARAMETER;
> > >
> > >
> > > +     }
> > >
> > >
> > > +
> > >
> > >
> > > +    VA_END(Args);
> > >
> > >
> > > +    return TranslateError (Ret.Error);
> > >
> > >
> > > +}
> > >
> > >
> > > +
> > >
> > >
> > > +//
> > >
> > >
> > > +// SBI Firmware extension
> > >
> > >
> > > +//
> > >
> > >
> > > +
> > >
> > >
> > > +/**
> > >
> > >
> > > +  Get scratch space of the current hart.
> > >
> > >
> > > +
> > >
> > >
> > > +  Please consider using the wrapper
> > > SbiGetFirmwareContext if you only need to
> > >
> > >
> > > +  access the firmware context.
> > >
> > >
> > > +
> > >
> > >
> > > +  @param[out] ScratchSpace         The scratch space
> > > pointer.
> > >
> > >
> > > +  @retval EFI_SUCCESS              The operation
> > > succeeds.
> > >
> > >
> > > +**/
> > >
> > >
> > > +EFI_STATUS
> > >
> > >
> > > +EFIAPI
> > >
> > >
> > > +SbiGetMscratch (
> > >
> > >
> > > +  OUT SBI_SCRATCH                    **ScratchSpace
> > >
> > >
> > > +  )
> > >
> > >
> > > +{
> > >
> > >
> > > +  SbiRet Ret = SbiCall (SBI_EDK2_FW_EXT,
> > > SBI_EXT_FW_MSCRATCH_FUNC, 0);
> > >
> > >
> > > +
> > >
> > >
> > > +  if (!Ret.Error) {
> > >
> > >
> > > +    *ScratchSpace = (SBI_SCRATCH *)Ret.Value;
> > >
> > >
> > > +  }
> > >
> > >
> > > +
> > >
> > >
> > > +  return EFI_SUCCESS;
> > >
> > >
> > > +}
> > >
> > >
> > > +
> > >
> > >
> > > +/**
> > >
> > >
> > > +  Get scratch space of the given hart id.
> > >
> > >
> > > +
> > >
> > >
> > > +  @param[in]  HartId               The hart id.
> > >
> > >
> > > +  @param[out] ScratchSpace         The scratch space
> > > pointer.
> > >
> > >
> > > +  @retval EFI_SUCCESS              The operation
> > > succeeds.
> > >
> > >
> > > +**/
> > >
> > >
> > > +EFI_STATUS
> > >
> > >
> > > +EFIAPI
> > >
> > >
> > > +SbiGetMscratchHartid (
> > >
> > >
> > > +  IN  UINTN                            HartId,
> > >
> > >
> > > +  OUT SBI_SCRATCH                    **ScratchSpace
> > >
> > >
> > > +  )
> > >
> > >
> > > +{
> > >
> > >
> > > +  SbiRet Ret = SbiCall (
> > >
> > >
> > > +                 SBI_EDK2_FW_EXT,
> > >
> > >
> > > +                 SBI_EXT_FW_MSCRATCH_HARTID_FUNC,
> > >
> > >
> > > +                 1,
> > >
> > >
> > > +                 HartId
> > >
> > >
> > > +                 );
> > >
> > >
> > > +
> > >
> > >
> > > +  if (!Ret.Error) {
> > >
> > >
> > > +    *ScratchSpace = (SBI_SCRATCH *)Ret.Value;
> > >
> > >
> > > +  }
> > >
> > >
> > > +
> > >
> > >
> > > +  return EFI_SUCCESS;
> > >
> > >
> > > +}
> > >
> > >
> > > +
> > >
> > >
> > > +/**
> > >
> > >
> > > +  Get firmware context of the calling hart.
> > >
> > >
> > > +
> > >
> > >
> > > +  @param[out] FirmwareContext      The firmware context
> > > pointer.
> > >
> > >
> > > +  @retval EFI_SUCCESS              The operation
> > > succeeds.
> > >
> > >
> > > +**/
> > >
> > >
> > > +EFI_STATUS
> > >
> > >
> > > +EFIAPI
> > >
> > >
> > > +SbiGetFirmwareContext (
> > >
> > >
> > > +  OUT EFI_RISCV_OPENSBI_FIRMWARE_CONTEXT
> > > **FirmwareContext
> > >
> > >
> > > +  )
> > >
> > >
> > > +{
> > >
> > >
> > > +  SBI_SCRATCH  *ScratchSpace;
> > >
> > >
> > > +  SBI_PLATFORM *SbiPlatform;
> > >
> > >
> > > +  SbiRet Ret = SbiCall (SBI_EDK2_FW_EXT,
> > > SBI_EXT_FW_MSCRATCH_FUNC, 0);
> > >
> > >
> > > +
> > >
> > >
> > > +  if (!Ret.Error) {
> > >
> > >
> > > +    ScratchSpace = (SBI_SCRATCH *)Ret.Value;
> > >
> > >
> > > +    SbiPlatform = (SBI_PLATFORM
> > > *)sbi_platform_ptr(ScratchSpace);
> > >
> > >
> > > +    *FirmwareContext =
> > > (EFI_RISCV_OPENSBI_FIRMWARE_CONTEXT *)SbiPlatform-
> > > >firmware_context;
> > >
> > >
> > > +  }
> > >
> > >
> > > +
> > >
> > >
> > > +  return EFI_SUCCESS;
> > >
> > >
> > > +}
> > >
> > >
> > > +
> > >
> > >
> > > +/**
> > >
> > >
> > > +  Set firmware context of the calling hart.
> > >
> > >
> > > +
> > >
> > >
> > > +  @param[in] FirmwareContext       The firmware context
> > > pointer.
> > >
> > >
> > > +  @retval EFI_SUCCESS              The operation
> > > succeeds.
> > >
> > >
> > > +**/
> > >
> > >
> > > +EFI_STATUS
> > >
> > >
> > > +EFIAPI
> > >
> > >
> > > +SbiSetFirmwareContext (
> > >
> > >
> > > +  IN EFI_RISCV_OPENSBI_FIRMWARE_CONTEXT
> > > *FirmwareContext
> > >
> > >
> > > +  )
> > >
> > >
> > > +{
> > >
> > >
> > > +  SBI_SCRATCH  *ScratchSpace;
> > >
> > >
> > > +  SBI_PLATFORM *SbiPlatform;
> > >
> > >
> > > +  SbiRet Ret = SbiCall (SBI_EDK2_FW_EXT,
> > > SBI_EXT_FW_MSCRATCH_FUNC, 0);
> > >
> > >
> > > +
> > >
> > >
> > > +  if (!Ret.Error) {
> > >
> > >
> > > +    ScratchSpace = (SBI_SCRATCH *)Ret.Value;
> > >
> > >
> > > +    SbiPlatform = (SBI_PLATFORM *)sbi_platform_ptr
> > > (ScratchSpace);
> > >
> > >
> > > +    SbiPlatform->firmware_context =
> > > (UINTN)FirmwareContext;
> > >
> > >
> > > +  }
> > >
> > >
> > > +
> > >
> > >
> > > +  return EFI_SUCCESS;
> > >
> > >
> > > +}
> > >
> > >
> > > --
> > > 2.26.1
> > >
> > >
> > >
> 
> 
> 


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [edk2-devel] [PATCH v4 1/1] ProcessorPkg/Library: Add RiscVEdk2SbiLib
  2020-06-02 16:51 ` [PATCH v4 1/1] ProcessorPkg/Library: Add RiscVEdk2SbiLib Daniel Schaefer
  2020-06-02 22:00   ` [edk2-devel] " Michael D Kinney
@ 2020-06-18 16:49   ` Leif Lindholm
  2020-06-23  2:08     ` Abner Chang
  1 sibling, 1 reply; 7+ messages in thread
From: Leif Lindholm @ 2020-06-18 16:49 UTC (permalink / raw)
  To: devel, daniel.schaefer; +Cc: Gilbert Chen, Abner Chang, Michael D . Kinney

On Tue, Jun 02, 2020 at 18:51:52 +0200, Daniel Schaefer wrote:
> Library provides interfaces to invoke SBI ecalls.
> 
> Signed-off-by: Daniel Schaefer <daniel.schaefer@hpe.com>

All of my feedback on previous revision addressed - where to actually
*merge* it remains undecided, but for the contents:
Reviewed-by: Leif Lindholm <leif@nuviainc.com>

Thanks!

> Cc: Leif Lindholm <leif@nuviainc.com>
> Cc: Gilbert Chen <gilbert.chen@hpe.com>
> Cc: Abner Chang <abner.chang@hpe.com>
> Cc: Michael D. Kinney <michael.d.kinney@intel.com>
> ---
>  Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.inf |  28 +
>  Silicon/RISC-V/ProcessorPkg/Include/Library/RiscVEdk2SbiLib.h           | 563 ++++++++++++
>  Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.c   | 897 ++++++++++++++++++++
>  3 files changed, 1488 insertions(+)
> 
> diff --git a/Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.inf b/Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.inf
> new file mode 100644
> index 000000000000..665dcbf40e01
> --- /dev/null
> +++ b/Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.inf
> @@ -0,0 +1,28 @@
> +## @file
> +# RISC-V Library to call SBI ecalls
> +#
> +#  Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
> +#
> +#  SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION    = 0x0001001b
> +  BASE_NAME      = RiscVEdk2SbiLib
> +  FILE_GUID      = 0DF1BBBD-F7E5-4E8A-BCF1-9D63D2DD9FDD
> +  MODULE_TYPE    = BASE
> +  VERSION_STRING = 1.0
> +  LIBRARY_CLASS  = RiscVEdk2SbiLib
> +
> +[Sources]
> +  RiscVEdk2SbiLib.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  Silicon/RISC-V/ProcessorPkg/RiscVProcessorPkg.dec
> +  Platform/RISC-V/PlatformPkg/RiscVPlatformPkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +  RiscVOpensbiLib
> diff --git a/Silicon/RISC-V/ProcessorPkg/Include/Library/RiscVEdk2SbiLib.h b/Silicon/RISC-V/ProcessorPkg/Include/Library/RiscVEdk2SbiLib.h
> new file mode 100644
> index 000000000000..c1ae3176147f
> --- /dev/null
> +++ b/Silicon/RISC-V/ProcessorPkg/Include/Library/RiscVEdk2SbiLib.h
> @@ -0,0 +1,563 @@
> +/** @file
> +  Library to call the RISC-V SBI ecalls
> +
> +  Copyright (c) 2020, Hewlett Packard Development LP. All rights reserved.<BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +  @par Glossary:
> +    - Hart - Hardware Thread, similar to a CPU core
> +**/
> +
> +#ifndef RISCV_SBI_LIB_H_
> +#define RISCV_SBI_LIB_H_
> +
> +#include <Uefi.h>
> +#include <IndustryStandard/RiscVOpensbi.h>
> +#include <sbi/sbi_scratch.h>
> +#include <sbi/sbi_platform.h>
> +
> +//
> +// EDK2 OpenSBI Firmware extension.
> +//
> +#define SBI_EDK2_FW_EXT (SBI_EXT_FIRMWARE_CODE_BASE_START | SBI_OPENSBI_IMPID)
> +//
> +// EDK2 OpenSBI Firmware extension functions.
> +//
> +#define SBI_EXT_FW_MSCRATCH_FUNC        0
> +#define SBI_EXT_FW_MSCRATCH_HARTID_FUNC 1
> +
> +//
> +// EDK2 OpenSBI firmware extension return status.
> +//
> +typedef struct {
> +  UINTN Error;   ///< SBI status code
> +  UINTN Value;   ///< Value returned
> +} SbiRet;
> +
> +/**
> +  Get the implemented SBI specification version
> +
> +  The minor number of the SBI specification is encoded in the low 24 bits,
> +  with the major number encoded in the next 7 bits.  Bit 32 must be 0 and is
> +  reserved for future expansion.
> +
> +  @param[out] SpecVersion          The Version of the SBI specification.
> +**/
> +VOID
> +EFIAPI
> +SbiGetSpecVersion (
> +  OUT UINTN                       *SpecVersion
> +  );
> +
> +/**
> +  Get the SBI implementation ID
> +
> +  This ID is used to idenetify a specific SBI implementation in order to work
> +  around any quirks it might have.
> +
> +  @param[out] ImplId               The ID of the SBI implementation.
> +**/
> +VOID
> +EFIAPI
> +SbiGetImplId (
> +  OUT UINTN                      *ImplId
> +  );
> +
> +/**
> +  Get the SBI implementation version
> +
> +  The version of this SBI implementation.
> +  The encoding of this number is determined by the specific SBI implementation.
> +
> +  @param[out] ImplVersion          The version of the SBI implementation.
> +**/
> +VOID
> +EFIAPI
> +SbiGetImplVersion (
> +  OUT UINTN                       *ImplVersion
> +  );
> +
> +/**
> +  Probe whether an SBI extension is available
> +
> +  ProbeResult is set to 0 if the extension is not available or to an extension
> +  specified value if it is available.
> +
> +  @param[in]  ExtensionId          The extension ID.
> +  @param[out] ProbeResult          The return value of the probe.
> +**/
> +VOID
> +EFIAPI
> +SbiProbeExtension (
> +  IN  INTN                         ExtensionId,
> +  OUT INTN                        *ProbeResult
> +  );
> +
> +/**
> +  Get the CPU's vendor ID
> +
> +  Reads the mvendorid CSR.
> +
> +  @param[out] MachineVendorId      The CPU's vendor ID.
> +**/
> +VOID
> +EFIAPI
> +SbiGetMachineVendorId (
> +  OUT UINTN                       *MachineVendorId
> +  );
> +
> +/**
> +  Get the CPU's architecture ID
> +
> +  Reads the marchid CSR.
> +
> +  @param[out] MachineArchId        The CPU's architecture ID.
> +**/
> +VOID
> +EFIAPI
> +SbiGetMachineArchId (
> +  OUT UINTN                       *MachineArchId
> +  );
> +
> +/**
> +  Get the CPU's implementation ID
> +
> +  Reads the mimpid CSR.
> +
> +  @param[out] MachineImplId        The CPU's implementation ID.
> +**/
> +VOID
> +EFIAPI
> +SbiGetMachineImplId (
> +  OUT UINTN                       *MachineImplId
> +  );
> +
> +/**
> +  Politely ask the SBI to start a given hart.
> +
> +  This call may return before the hart has actually started executing, if the
> +  SBI implementation can guarantee that the hart is actually going to start.
> +
> +  Before the hart jumps to StartAddr, the hart MUST configure PMP if present
> +  and switch to S-mode.
> +
> +  @param[in]  HartId               The id of the hart to start.
> +  @param[in]  StartAddr            The physical address, where the hart starts
> +                                   executing from.
> +  @param[in]  Priv                 An XLEN-bit value, which will be in register
> +                                   a1 when the hart starts.
> +  @retval EFI_SUCCESS              Hart was stopped and will start executing from StartAddr.
> +  @retval EFI_LOAD_ERROR           StartAddr is not valid, possibly due to following reasons:
> +                                    - It is not a valid physical address.
> +                                    - The address is prohibited by PMP to run in
> +                                      supervisor mode.
> +  @retval EFI_INVALID_PARAMETER    HartId is not a valid hart id
> +  @retval EFI_ALREADY_STARTED      The hart is already running.
> +  @retval other                    The start request failed for unknown reasons.
> +**/
> +EFI_STATUS
> +EFIAPI
> +SbiHartStart (
> +  IN  UINTN                          HartId,
> +  IN  UINTN                          StartAddr,
> +  IN  UINTN                          Priv
> +  );
> +
> +/**
> +  Return execution of the calling hart to SBI.
> +
> +  MUST be called in S-Mode with user interrupts disabled.
> +  This call is not expected to return, unless a failure occurs.
> +
> +  @retval     EFI_SUCCESS          Never occurs. When successful, the call does not return.
> +  @retval     other                Failed to stop hard for an unknown reason.
> +**/
> +EFI_STATUS
> +EFIAPI
> +SbiHartStop (
> +  );
> +
> +/**
> +  Get the current status of a hart.
> +
> +  Since harts can transition between states at any time, the status retrieved
> +  by this function may already be out of date, once it returns.
> +
> +  Possible values for HartStatus are:
> +  0: STARTED
> +  1: STOPPED
> +  2: START_REQUEST_PENDING
> +  3: STOP_REQUEST_PENDING
> +
> +  @param[out] HartStatus           The pointer in which the hart's status is
> +                                   stored.
> +  @retval EFI_SUCCESS              The operation succeeds.
> +  @retval EFI_INVALID_PARAMETER    A parameter is invalid.
> +**/
> +EFI_STATUS
> +EFIAPI
> +SbiHartGetStatus (
> +  IN  UINTN                          HartId,
> +  OUT UINTN                         *HartStatus
> +  );
> +
> +///
> +/// Timer extension
> +///
> +
> +/**
> +  Clear pending timer interrupt bit and set timer for next event after Time.
> +
> +  To clear the timer without scheduling a timer event, set Time to a
> +  practically infinite value or mask the timer interrupt by clearing sie.STIE.
> +
> +  @param[in]  Time                 The time offset to the next scheduled timer interrupt.
> +**/
> +VOID
> +EFIAPI
> +SbiSetTimer (
> +  IN  UINT64                         Time
> +  );
> +
> +///
> +/// IPI extension
> +///
> +
> +/**
> +  Send IPI to all harts specified in the mask.
> +
> +  The interrupts are registered as supervisor software interrupts at the
> +  receiving hart.
> +
> +  @param[in]  HartMask             Scalar bit-vector containing hart ids
> +  @param[in]  HartMaskBase         The starting hartid from which the bit-vector
> +                                   must be computed. If set to -1, HartMask is
> +                                   ignored and all harts are considered.
> +  @retval EFI_SUCCESS              IPI was sent to all the targeted harts.
> +  @retval EFI_INVALID_PARAMETER    Either hart_mask_base or any of the hartid
> +                                   from hart_mask is not valid i.e. either the
> +                                   hartid is not enabled by the platform or is
> +                                   not available to the supervisor.
> +**/
> +EFI_STATUS
> +EFIAPI
> +SbiSendIpi (
> +  IN  UINTN                         *HartMask,
> +  IN  UINTN                          HartMaskBase
> +  );
> +
> +///
> +/// Remote fence extension
> +///
> +
> +/**
> +  Instructs remote harts to execute a FENCE.I instruction.
> +
> +  @param[in]  HartMask             Scalar bit-vector containing hart ids
> +  @param[in]  HartMaskBase         The starting hartid from which the bit-vector
> +                                   must be computed. If set to -1, HartMask is
> +                                   ignored and all harts are considered.
> +  @retval EFI_SUCCESS              IPI was sent to all the targeted harts.
> +  @retval EFI_INVALID_PARAMETER    Either hart_mask_base or any of the hartid
> +                                   from hart_mask is not valid i.e. either the
> +                                   hartid is not enabled by the platform or is
> +                                   not available to the supervisor.
> +**/
> +EFI_STATUS
> +EFIAPI
> +SbiRemoteFenceI (
> +  IN  UINTN                         *HartMask,
> +  IN  UINTN                          HartMaskBase
> +  );
> +
> +/**
> +  Instructs the remote harts to execute one or more SFENCE.VMA instructions.
> +
> +  The SFENCE.VMA covers the range of virtual addresses between StartAaddr and Size.
> +
> +  The remote fence function acts as a full tlb flush if * StartAddr and size
> +  are both 0 * size is equal to 2^XLEN-1
> +
> +  @param[in]  HartMask             Scalar bit-vector containing hart ids
> +  @param[in]  HartMaskBase         The starting hartid from which the bit-vector
> +                                   must be computed. If set to -1, HartMask is
> +                                   ignored and all harts are considered.
> +  @param[in]  StartAddr            The first address of the affected range.
> +  @param[in]  Size                 How many addresses are affected.
> +  @retval EFI_SUCCESS              IPI was sent to all the targeted harts.
> +  @retval EFI_LOAD_ERROR           StartAddr or Size is not valid.
> +  @retval EFI_INVALID_PARAMETER    Either hart_mask_base or any of the hartid
> +                                   from hart_mask is not valid i.e. either the
> +                                   hartid is not enabled by the platform or is
> +                                   not available to the supervisor.
> +**/
> +EFI_STATUS
> +EFIAPI
> +SbiRemoteSfenceVma (
> +  IN  UINTN                         *HartMask,
> +  IN  UINTN                          HartMaskBase,
> +  IN  UINTN                          StartAddr,
> +  IN  UINTN                          Size
> +  );
> +
> +/**
> +  Instructs the remote harts to execute one or more SFENCE.VMA instructions.
> +
> +  The SFENCE.VMA covers the range of virtual addresses between StartAaddr and Size.
> +  Covers only the given ASID.
> +
> +  The remote fence function acts as a full tlb flush if * StartAddr and size
> +  are both 0 * size is equal to 2^XLEN-1
> +
> +  @param[in]  HartMask             Scalar bit-vector containing hart ids
> +  @param[in]  HartMaskBase         The starting hartid from which the bit-vector
> +                                   must be computed. If set to -1, HartMask is
> +                                   ignored and all harts are considered.
> +  @param[in]  StartAddr            The first address of the affected range.
> +  @param[in]  Size                 How many addresses are affected.
> +  @retval EFI_SUCCESS              IPI was sent to all the targeted harts.
> +  @retval EFI_LOAD_ERROR           StartAddr or Size is not valid.
> +  @retval EFI_INVALID_PARAMETER    Either hart_mask_base or any of the hartid
> +                                   from hart_mask is not valid i.e. either the
> +                                   hartid is not enabled by the platform or is
> +                                   not available to the supervisor.
> +**/
> +EFI_STATUS
> +EFIAPI
> +SbiRemoteSfenceVmaAsid (
> +  IN  UINTN                         *HartMask,
> +  IN  UINTN                          HartMaskBase,
> +  IN  UINTN                          StartAddr,
> +  IN  UINTN                          Size,
> +  IN  UINTN                          Asid
> +  );
> +
> +/**
> +  Instructs the remote harts to execute one or more SFENCE.GVMA instructions.
> +
> +  The SFENCE.GVMA covers the range of virtual addresses between StartAaddr and Size.
> +  Covers only the given VMID.
> +  This function call is only valid for harts implementing the hypervisor extension.
> +
> +  The remote fence function acts as a full tlb flush if * StartAddr and size
> +  are both 0 * size is equal to 2^XLEN-1
> +
> +  @param[in]  HartMask             Scalar bit-vector containing hart ids
> +  @param[in]  HartMaskBase         The starting hartid from which the bit-vector
> +                                   must be computed. If set to -1, HartMask is
> +                                   ignored and all harts are considered.
> +  @param[in]  StartAddr            The first address of the affected range.
> +  @param[in]  Size                 How many addresses are affected.
> +  @retval EFI_SUCCESS              IPI was sent to all the targeted harts.
> +  @retval EFI_LOAD_ERROR           StartAddr or Size is not valid.
> +  @retval EFI_UNSUPPORTED          SBI does not implement this function or one
> +                                   of the target harts does not support the
> +                                   hypervisor extension.
> +  @retval EFI_INVALID_PARAMETER    Either hart_mask_base or any of the hartid
> +                                   from hart_mask is not valid i.e. either the
> +                                   hartid is not enabled by the platform or is
> +                                   not available to the supervisor.
> +**/
> +EFI_STATUS
> +EFIAPI
> +SbiRemoteHfenceGvmaVmid (
> +  IN  UINTN                         *HartMask,
> +  IN  UINTN                          HartMaskBase,
> +  IN  UINTN                          StartAddr,
> +  IN  UINTN                          Size,
> +  IN  UINTN                          Vmid
> +  );
> +
> +/**
> +  Instructs the remote harts to execute one or more SFENCE.GVMA instructions.
> +
> +  The SFENCE.GVMA covers the range of virtual addresses between StartAaddr and Size.
> +  This function call is only valid for harts implementing the hypervisor extension.
> +
> +  The remote fence function acts as a full tlb flush if * StartAddr and size
> +  are both 0 * size is equal to 2^XLEN-1
> +
> +  @param[in]  HartMask             Scalar bit-vector containing hart ids
> +  @param[in]  HartMaskBase         The starting hartid from which the bit-vector
> +                                   must be computed. If set to -1, HartMask is
> +                                   ignored and all harts are considered.
> +  @param[in]  StartAddr            The first address of the affected range.
> +  @param[in]  Size                 How many addresses are affected.
> +  @retval EFI_SUCCESS              IPI was sent to all the targeted harts.
> +  @retval EFI_LOAD_ERROR           StartAddr or Size is not valid.
> +  @retval EFI_UNSUPPORTED          SBI does not implement this function or one
> +                                   of the target harts does not support the
> +                                   hypervisor extension.
> +  @retval EFI_INVALID_PARAMETER    Either hart_mask_base or any of the hartid
> +                                   from hart_mask is not valid i.e. either the
> +                                   hartid is not enabled by the platform or is
> +                                   not available to the supervisor.
> +**/
> +EFI_STATUS
> +EFIAPI
> +SbiRemoteHfenceGvma (
> +  IN  UINTN                         *HartMask,
> +  IN  UINTN                          HartMaskBase,
> +  IN  UINTN                          StartAddr,
> +  IN  UINTN                          Size
> +  );
> +
> +/**
> +  Instructs the remote harts to execute one or more SFENCE.VVMA instructions.
> +
> +  The SFENCE.GVMA covers the range of virtual addresses between StartAaddr and Size.
> +  Covers only the given ASID.
> +  This function call is only valid for harts implementing the hypervisor extension.
> +
> +  The remote fence function acts as a full tlb flush if * StartAddr and size
> +  are both 0 * size is equal to 2^XLEN-1
> +
> +  @param[in]  HartMask             Scalar bit-vector containing hart ids
> +  @param[in]  HartMaskBase         The starting hartid from which the bit-vector
> +                                   must be computed. If set to -1, HartMask is
> +                                   ignored and all harts are considered.
> +  @param[in]  StartAddr            The first address of the affected range.
> +  @param[in]  Size                 How many addresses are affected.
> +  @retval EFI_SUCCESS              IPI was sent to all the targeted harts.
> +  @retval EFI_LOAD_ERROR           StartAddr or Size is not valid.
> +  @retval EFI_UNSUPPORTED          SBI does not implement this function or one
> +                                   of the target harts does not support the
> +                                   hypervisor extension.
> +  @retval EFI_INVALID_PARAMETER    Either hart_mask_base or any of the hartid
> +                                   from hart_mask is not valid i.e. either the
> +                                   hartid is not enabled by the platform or is
> +                                   not available to the supervisor.
> +**/
> +EFI_STATUS
> +EFIAPI
> +SbiRemoteHfenceVvmaAsid (
> +  IN  UINTN                         *HartMask,
> +  IN  UINTN                          HartMaskBase,
> +  IN  UINTN                          StartAddr,
> +  IN  UINTN                          Size,
> +  IN  UINTN                          Asid
> +  );
> +
> +/**
> +  Instructs the remote harts to execute one or more SFENCE.VVMA instructions.
> +
> +  The SFENCE.GVMA covers the range of virtual addresses between StartAaddr and Size.
> +  This function call is only valid for harts implementing the hypervisor extension.
> +
> +  The remote fence function acts as a full tlb flush if * StartAddr and size
> +  are both 0 * size is equal to 2^XLEN-1
> +
> +  @param[in]  HartMask             Scalar bit-vector containing hart ids
> +  @param[in]  HartMaskBase         The starting hartid from which the bit-vector
> +                                   must be computed. If set to -1, HartMask is
> +                                   ignored and all harts are considered.
> +  @param[in]  StartAddr            The first address of the affected range.
> +  @param[in]  Size                 How many addresses are affected.
> +  @retval EFI_SUCCESS              IPI was sent to all the targeted harts.
> +  @retval EFI_LOAD_ERROR           StartAddr or Size is not valid.
> +  @retval EFI_UNSUPPORTED          SBI does not implement this function or one
> +                                   of the target harts does not support the
> +                                   hypervisor extension.
> +  @retval EFI_INVALID_PARAMETER    Either hart_mask_base or any of the hartid
> +                                   from hart_mask is not valid i.e. either the
> +                                   hartid is not enabled by the platform or is
> +                                   not available to the supervisor.
> +**/
> +EFI_STATUS
> +EFIAPI
> +SbiRemoteHfenceVvma (
> +  IN  UINTN                         *HartMask,
> +  IN  UINTN                          HartMaskBase,
> +  IN  UINTN                          StartAddr,
> +  IN  UINTN                          Size
> +  );
> +
> +///
> +/// Vendor Specific extension space: Extension Ids 0x09000000 through 0x09FFFFFF
> +///
> +
> +/**
> +  Call a function in a vendor defined SBI extension
> +
> +  ASSERT() if the ExtensionId is not in the designated SBI Vendor Extension
> +  Space.
> +
> +  @param[in]  ExtensionId          The SBI vendor extension ID.
> +  @param[in]  FunctionId           The function ID to call in this extension.
> +  @param[in]  NumArgs              How many arguments are passed.
> +  @param[in]  ...                  Actual Arguments to the function.
> +  @retval EFI_SUCCESS if the SBI function was called and it was successful
> +  @retval EFI_INVALID_PARAMETER if NumArgs exceeds 6
> +  @retval others if the called SBI function returns an error
> +**/
> +EFI_STATUS
> +EFIAPI
> +SbiVendorCall (
> +  IN  UINTN                          ExtensionId,
> +  IN  UINTN                          FunctionId,
> +  IN  UINTN                          NumArgs,
> +  ...
> +  );
> +
> +///
> +/// Firmware SBI Extension
> +///
> +/// This SBI Extension is defined and used by EDK2 only in order to be able to
> +/// run PI and DXE phase in S-Mode.
> +///
> +
> +/**
> +  Get scratch space of the current hart.
> +
> +  Please consider using the wrapper SbiGetFirmwareContext if you only need to
> +  access the firmware context.
> +
> +  @param[out] ScratchSpace         The scratch space pointer.
> +  @retval EFI_SUCCESS              The operation succeeds.
> +**/
> +EFI_STATUS
> +EFIAPI
> +SbiGetMscratch (
> +  OUT SBI_SCRATCH                    **ScratchSpace
> +  );
> +
> +/**
> +  Get scratch space of the given hart id.
> +
> +  @param[in]  HartId               The hart id.
> +  @param[out] ScratchSpace         The scratch space pointer.
> +  @retval EFI_SUCCESS              The operation succeeds.
> +**/
> +EFI_STATUS
> +EFIAPI
> +SbiGetMscratchHartid (
> +  IN  UINTN                            HartId,
> +  OUT SBI_SCRATCH                    **ScratchSpace
> +  );
> +
> +/**
> +  Get firmware context of the calling hart.
> +
> +  @param[out] FirmwareContext      The firmware context pointer.
> +  @retval EFI_SUCCESS              The operation succeeds.
> +**/
> +EFI_STATUS
> +EFIAPI
> +SbiGetFirmwareContext (
> +  OUT EFI_RISCV_OPENSBI_FIRMWARE_CONTEXT **FirmwareContext
> +  );
> +
> +/**
> +  Set firmware context of the calling hart.
> +
> +  @param[in] FirmwareContext       The firmware context pointer.
> +  @retval EFI_SUCCESS              The operation succeeds.
> +**/
> +EFI_STATUS
> +EFIAPI
> +SbiSetFirmwareContext (
> +  IN EFI_RISCV_OPENSBI_FIRMWARE_CONTEXT *FirmwareContext
> +  );
> +
> +#endif
> diff --git a/Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.c b/Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.c
> new file mode 100644
> index 000000000000..0df505d2675b
> --- /dev/null
> +++ b/Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.c
> @@ -0,0 +1,897 @@
> +/** @file
> +  Instance of the SBI ecall library.
> +
> +  It allows calling an SBI function via an ecall from S-Mode.
> +
> +  The legacy extensions are not included because they are not necessary.
> +  They would be:
> +  - SbiLegacySetTimer            -> Use SbiSetTimer
> +  - SbiLegacyConsolePutChar      -> No replacement - Use regular UEFI functions
> +  - SbiLegacyConsoleGetChar      -> No replacement - Use regular UEFI functions
> +  - SbiLegacyClearIpi            -> Write 0 to SSIP
> +  - SbiLegacySendIpi             -> Use SbiSendIpi
> +  - SbiLegacyRemoteFenceI        -> Use SbiRemoteFenceI
> +  - SbiLegacyRemoteSfenceVma     -> Use SbiRemoteSfenceVma
> +  - SbiLegacyRemoteSfenceVmaAsid -> Use SbiRemoteSfenceVmaAsid
> +  - SbiLegacyShutdown            -> Wait for new System Reset extension
> +
> +  Copyright (c) 2020, Hewlett Packard Development LP. All rights reserved.<BR>
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +  @par Revision Reference:
> +    - OpenSBI Version 0.6
> +**/
> +
> +#include <IndustryStandard/RiscVOpensbi.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/RiscVEdk2SbiLib.h>
> +#include <sbi/riscv_asm.h>
> +#include <sbi/sbi_hart.h>
> +#include <sbi/sbi_types.h>
> +#include <sbi/sbi_init.h>
> +
> +
> +//
> +// Maximum arguments for SBI ecall
> +// It's possible to pass more but no SBI call uses more as of SBI 0.2.
> +// The additional arguments would have to be passed on the stack instead of as
> +// registers, like it's done now.
> +//
> +#define SBI_CALL_MAX_ARGS 6
> +
> +/**
> +  Call SBI call using ecall instruction.
> +
> +  Asserts when NumArgs exceeds SBI_CALL_MAX_ARGS.
> +
> +  @param[in] ExtId    SBI extension ID.
> +  @param[in] FuncId   SBI function ID.
> +  @param[in] NumArgs  Number of arguments to pass to the ecall.
> +  @param[in] ...      Argument list for the ecall.
> +
> +  @retval  Returns SbiRet structure with value and error code.
> +
> +**/
> +STATIC
> +SbiRet
> +EFIAPI
> +SbiCall(
> +  IN  UINTN ExtId,
> +  IN  UINTN FuncId,
> +  IN  UINTN NumArgs,
> +  ...
> +  )
> +{
> +    UINTN I;
> +    SbiRet Ret;
> +    UINTN Args[SBI_CALL_MAX_ARGS];
> +    VA_LIST ArgList;
> +    VA_START (ArgList, NumArgs);
> +
> +    ASSERT (NumArgs <= SBI_CALL_MAX_ARGS);
> +
> +    for (I = 0; I < SBI_CALL_MAX_ARGS; I++) {
> +      if (I < NumArgs) {
> +        Args[I] = VA_ARG (ArgList, UINTN);
> +      } else {
> +        // Default to 0 for all arguments that are not given
> +        Args[I] = 0;
> +      }
> +    }
> +
> +    VA_END(ArgList);
> +
> +    register UINTN a0 asm ("a0") = Args[0];
> +    register UINTN a1 asm ("a1") = Args[1];
> +    register UINTN a2 asm ("a2") = Args[2];
> +    register UINTN a3 asm ("a3") = Args[3];
> +    register UINTN a4 asm ("a4") = Args[4];
> +    register UINTN a5 asm ("a5") = Args[5];
> +    register UINTN a6 asm ("a6") = (UINTN)(FuncId);
> +    register UINTN a7 asm ("a7") = (UINTN)(ExtId);
> +    asm volatile ("ecall" \
> +         : "+r" (a0), "+r" (a1) \
> +         : "r" (a2), "r" (a3), "r" (a4), "r" (a5), "r" (a6), "r" (a7) \
> +         : "memory"); \
> +    Ret.Error = a0;
> +    Ret.Value = a1;
> +    return Ret;
> +}
> +
> +/**
> +  Translate SBI error code to EFI status.
> +
> +  @param[in] SbiError   SBI error code
> +  @retval EFI_STATUS
> +**/
> +
> +STATIC
> +EFI_STATUS
> +EFIAPI
> +TranslateError(
> +  IN  UINTN SbiError
> +  )
> +{
> +  switch (SbiError) {
> +    case SBI_SUCCESS:
> +      return EFI_SUCCESS;
> +    case SBI_ERR_FAILED:
> +      return EFI_DEVICE_ERROR;
> +      break;
> +    case SBI_ERR_NOT_SUPPORTED:
> +      return EFI_UNSUPPORTED;
> +      break;
> +    case SBI_ERR_INVALID_PARAM:
> +      return EFI_INVALID_PARAMETER;
> +      break;
> +    case SBI_ERR_DENIED:
> +      return EFI_ACCESS_DENIED;
> +      break;
> +    case SBI_ERR_INVALID_ADDRESS:
> +      return EFI_LOAD_ERROR;
> +      break;
> +    case SBI_ERR_ALREADY_AVAILABLE:
> +      return EFI_ALREADY_STARTED;
> +      break;
> +    default:
> +      //
> +      // Reaches here only if SBI has defined a new error type
> +      //
> +      ASSERT (FALSE);
> +      return EFI_UNSUPPORTED;
> +      break;
> +  }
> +}
> +
> +//
> +// OpenSBI library interface function for the base extension
> +//
> +
> +/**
> +  Get the implemented SBI specification version
> +
> +  The minor number of the SBI specification is encoded in the low 24 bits,
> +  with the major number encoded in the next 7 bits.  Bit 32 must be 0 and is
> +  reserved for future expansion.
> +
> +  @param[out] SpecVersion          The Version of the SBI specification.
> +**/
> +VOID
> +EFIAPI
> +SbiGetSpecVersion (
> +  OUT UINTN                       *SpecVersion
> +  )
> +{
> +  SbiRet Ret = SbiCall (SBI_EXT_BASE, SBI_EXT_BASE_GET_SPEC_VERSION, 0);
> +
> +  if (!Ret.Error) {
> +    *SpecVersion = (UINTN)Ret.Value;
> +  }
> +}
> +
> +/**
> +  Get the SBI implementation ID
> +
> +  This ID is used to idenetify a specific SBI implementation in order to work
> +  around any quirks it might have.
> +
> +  @param[out] ImplId               The ID of the SBI implementation.
> +**/
> +VOID
> +EFIAPI
> +SbiGetImplId (
> +  OUT UINTN                       *ImplId
> +  )
> +{
> +  SbiRet Ret = SbiCall (SBI_EXT_BASE, SBI_EXT_BASE_GET_IMP_ID, 0);
> +  *ImplId = (UINTN)Ret.Value;
> +}
> +
> +/**
> +  Get the SBI implementation version
> +
> +  The version of this SBI implementation.
> +  The encoding of this number is determined by the specific SBI implementation.
> +
> +  @param[out] ImplVersion          The version of the SBI implementation.
> +**/
> +VOID
> +EFIAPI
> +SbiGetImplVersion (
> +  OUT UINTN                       *ImplVersion
> +  )
> +{
> +  SbiRet Ret = SbiCall (SBI_EXT_BASE, SBI_EXT_BASE_GET_IMP_VERSION, 0);
> +  *ImplVersion = (UINTN)Ret.Value;
> +}
> +
> +/**
> +  Probe whether an SBI extension is available
> +
> +  ProbeResult is set to 0 if the extension is not available or to an extension
> +  specified value if it is available.
> +
> +  @param[in]  ExtensionId          The extension ID.
> +  @param[out] ProbeResult          The return value of the probe.
> +**/
> +VOID
> +EFIAPI
> +SbiProbeExtension (
> +  IN  INTN                         ExtensionId,
> +  OUT INTN                        *ProbeResult
> +  )
> +{
> +  SbiRet Ret = SbiCall (SBI_EXT_BASE, SBI_EXT_BASE_PROBE_EXT, 0);
> +  *ProbeResult = (UINTN)Ret.Value;
> +}
> +
> +/**
> +  Get the CPU's vendor ID
> +
> +  Reads the mvendorid CSR.
> +
> +  @param[out] MachineVendorId      The CPU's vendor ID.
> +**/
> +VOID
> +EFIAPI
> +SbiGetMachineVendorId (
> +  OUT UINTN                       *MachineVendorId
> +  )
> +{
> +  SbiRet Ret = SbiCall (SBI_EXT_BASE, SBI_EXT_BASE_GET_MVENDORID, 0);
> +  *MachineVendorId = (UINTN)Ret.Value;
> +}
> +
> +/**
> +  Get the CPU's architecture ID
> +
> +  Reads the marchid CSR.
> +
> +  @param[out] MachineArchId        The CPU's architecture ID.
> +**/
> +VOID
> +EFIAPI
> +SbiGetMachineArchId (
> +  OUT UINTN                       *MachineArchId
> +  )
> +{
> +  SbiRet Ret = SbiCall (SBI_EXT_BASE, SBI_EXT_BASE_GET_MARCHID, 0);
> +  *MachineArchId = (UINTN)Ret.Value;
> +}
> +
> +/**
> +  Get the CPU's architecture ID
> +
> +  Reads the marchid CSR.
> +
> +  @param[out] MachineImplId        The CPU's implementation ID.
> +**/
> +VOID
> +EFIAPI
> +SbiGetMachineImplId (
> +  OUT UINTN                       *MachineImplId
> +  )
> +{
> +  SbiRet Ret = SbiCall (SBI_EXT_BASE, SBI_EXT_BASE_GET_MIMPID, 0);
> +  *MachineImplId = (UINTN)Ret.Value;
> +}
> +
> +//
> +// SBI interface function for the hart state management extension
> +//
> +
> +/**
> +  Politely ask the SBI to start a given hart.
> +
> +  This call may return before the hart has actually started executing, if the
> +  SBI implementation can guarantee that the hart is actually going to start.
> +
> +  Before the hart jumps to StartAddr, the hart MUST configure PMP if present
> +  and switch to S-mode.
> +
> +  @param[in]  HartId               The id of the hart to start.
> +  @param[in]  StartAddr            The physical address, where the hart starts
> +                                   executing from.
> +  @param[in]  Priv                 An XLEN-bit value, which will be in register
> +                                   a1 when the hart starts.
> +  @retval EFI_SUCCESS              Hart was stopped and will start executing from StartAddr.
> +  @retval EFI_LOAD_ERROR           StartAddr is not valid, possibly due to following reasons:
> +                                     - It is not a valid physical address.
> +                                     - The address is prohibited by PMP to run in
> +                                       supervisor mode.
> +  @retval EFI_INVALID_PARAMETER    HartId is not a valid hart id
> +  @retval EFI_ALREADY_STARTED      The hart is already running.
> +  @retval other                    The start request failed for unknown reasons.
> +**/
> +EFI_STATUS
> +EFIAPI
> +SbiHartStart (
> +  IN  UINTN                          HartId,
> +  IN  UINTN                          StartAddr,
> +  IN  UINTN                          Priv
> +  )
> +{
> +  SbiRet Ret = SbiCall (
> +                 SBI_EXT_HSM,
> +                 SBI_EXT_HSM_HART_START,
> +                 3,
> +                 HartId,
> +                 StartAddr,
> +                 Priv
> +                 );
> +  return TranslateError (Ret.Error);
> +}
> +
> +/**
> +  Return execution of the calling hart to SBI.
> +
> +  MUST be called in S-Mode with user interrupts disabled.
> +  This call is not expected to return, unless a failure occurs.
> +
> +  @retval     EFI_SUCCESS          Never occurs. When successful, the call does not return.
> +  @retval     other                Failed to stop hard for an unknown reason.
> +**/
> +EFI_STATUS
> +EFIAPI
> +SbiHartStop (
> +  )
> +{
> +  SbiRet Ret = SbiCall (SBI_EXT_HSM, SBI_EXT_HSM_HART_STOP, 0);
> +  return TranslateError (Ret.Error);
> +}
> +
> +/**
> +  Get the current status of a hart.
> +
> +  Since harts can transition between states at any time, the status retrieved
> +  by this function may already be out of date, once it returns.
> +
> +  Possible values for HartStatus are:
> +  0: STARTED
> +  1: STOPPED
> +  2: START_REQUEST_PENDING
> +  3: STOP_REQUEST_PENDING
> +
> +  @param[out] HartStatus           The pointer in which the hart's status is
> +                                   stored.
> +  @retval EFI_SUCCESS              The operation succeeds.
> +  @retval EFI_INVALID_PARAMETER    A parameter is invalid.
> +**/
> +EFI_STATUS
> +EFIAPI
> +SbiHartGetStatus (
> +  IN  UINTN                          HartId,
> +  OUT UINTN                         *HartStatus
> +  )
> +{
> +  SbiRet Ret = SbiCall (SBI_EXT_HSM, SBI_EXT_HSM_HART_GET_STATUS, 1, HartId);
> +
> +  if (!Ret.Error) {
> +    *HartStatus = (UINTN)Ret.Value;
> +  }
> +
> +  return TranslateError (Ret.Error);
> +}
> +
> +/**
> +  Clear pending timer interrupt bit and set timer for next event after Time.
> +
> +  To clear the timer without scheduling a timer event, set Time to a
> +  practically infinite value or mask the timer interrupt by clearing sie.STIE.
> +
> +  @param[in]  Time                 The time offset to the next scheduled timer interrupt.
> +**/
> +VOID
> +EFIAPI
> +SbiSetTimer (
> +  IN  UINT64                         Time
> +  )
> +{
> +  SbiCall (SBI_EXT_TIME, SBI_EXT_TIME_SET_TIMER, 1, Time);
> +}
> +
> +EFI_STATUS
> +EFIAPI
> +SbiSendIpi (
> +  IN  UINTN                         *HartMask,
> +  IN  UINTN                          HartMaskBase
> +  )
> +{
> +  SbiRet Ret = SbiCall (
> +                 SBI_EXT_IPI,
> +                 SBI_EXT_IPI_SEND_IPI,
> +                 2,
> +                 (UINTN)HartMask,
> +                 HartMaskBase
> +                 );
> +  return TranslateError (Ret.Error);
> +}
> +
> +/**
> +  Instructs remote harts to execute a FENCE.I instruction.
> +
> +  @param[in]  HartMask             Scalar bit-vector containing hart ids
> +  @param[in]  HartMaskBase         The starting hartid from which the bit-vector
> +                                   must be computed. If set to -1, HartMask is
> +                                   ignored and all harts are considered.
> +  @retval EFI_SUCCESS              IPI was sent to all the targeted harts.
> +  @retval EFI_INVALID_PARAMETER    Either hart_mask_base or any of the hartid
> +                                   from hart_mask is not valid i.e. either the
> +                                   hartid is not enabled by the platform or is
> +                                   not available to the supervisor.
> +**/
> +EFI_STATUS
> +EFIAPI
> +SbiRemoteFenceI (
> +  IN  UINTN                         *HartMask,
> +  IN  UINTN                          HartMaskBase
> +  )
> +{
> +  SbiRet Ret = SbiCall (
> +                 SBI_EXT_RFENCE,
> +                 SBI_EXT_RFENCE_REMOTE_FENCE_I,
> +                 2,
> +                 (UINTN)HartMask,
> +                 HartMaskBase
> +                 );
> +  return TranslateError (Ret.Error);
> +}
> +
> +/**
> +  Instructs the remote harts to execute one or more SFENCE.VMA instructions.
> +
> +  The SFENCE.VMA covers the range of virtual addresses between StartAaddr and Size.
> +
> +  The remote fence function acts as a full tlb flush if * StartAddr and size
> +  are both 0 * size is equal to 2^XLEN-1
> +
> +  @param[in]  HartMask             Scalar bit-vector containing hart ids
> +  @param[in]  HartMaskBase         The starting hartid from which the bit-vector
> +                                   must be computed. If set to -1, HartMask is
> +                                   ignored and all harts are considered.
> +  @param[in]  StartAddr            The first address of the affected range.
> +  @param[in]  Size                 How many addresses are affected.
> +  @retval EFI_SUCCESS              IPI was sent to all the targeted harts.
> +  @retval EFI_LOAD_ERROR           StartAddr or Size is not valid.
> +  @retval EFI_INVALID_PARAMETER    Either hart_mask_base or any of the hartid
> +                                   from hart_mask is not valid i.e. either the
> +                                   hartid is not enabled by the platform or is
> +                                   not available to the supervisor.
> +**/
> +EFI_STATUS
> +EFIAPI
> +SbiRemoteSfenceVma (
> +  IN  UINTN                         *HartMask,
> +  IN  UINTN                          HartMaskBase,
> +  IN  UINTN                          StartAddr,
> +  IN  UINTN                          Size
> +  )
> +{
> +  SbiRet Ret = SbiCall (
> +                 SBI_EXT_RFENCE,
> +                 SBI_EXT_RFENCE_REMOTE_SFENCE_VMA,
> +                 4,
> +                 (UINTN)HartMask,
> +                 HartMaskBase,
> +                 StartAddr,
> +                 Size
> +                 );
> +  return TranslateError (Ret.Error);
> +}
> +
> +/**
> +  Instructs the remote harts to execute one or more SFENCE.VMA instructions.
> +
> +  The SFENCE.VMA covers the range of virtual addresses between StartAaddr and Size.
> +  Covers only the given ASID.
> +
> +  The remote fence function acts as a full tlb flush if * StartAddr and size
> +  are both 0 * size is equal to 2^XLEN-1
> +
> +  @param[in]  HartMask             Scalar bit-vector containing hart ids
> +  @param[in]  HartMaskBase         The starting hartid from which the bit-vector
> +                                   must be computed. If set to -1, HartMask is
> +                                   ignored and all harts are considered.
> +  @param[in]  StartAddr            The first address of the affected range.
> +  @param[in]  Size                 How many addresses are affected.
> +  @retval EFI_SUCCESS              IPI was sent to all the targeted harts.
> +  @retval EFI_LOAD_ERROR           StartAddr or Size is not valid.
> +  @retval EFI_INVALID_PARAMETER    Either hart_mask_base or any of the hartid
> +                                   from hart_mask is not valid i.e. either the
> +                                   hartid is not enabled by the platform or is
> +                                   not available to the supervisor.
> +**/
> +EFI_STATUS
> +EFIAPI
> +SbiRemoteSfenceVmaAsid (
> +  IN  UINTN                         *HartMask,
> +  IN  UINTN                          HartMaskBase,
> +  IN  UINTN                          StartAddr,
> +  IN  UINTN                          Size,
> +  IN  UINTN                          Asid
> +  )
> +{
> +  SbiRet Ret = SbiCall (
> +                 SBI_EXT_RFENCE,
> +                 SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID,
> +                 5,
> +                 (UINTN)HartMask,
> +                 HartMaskBase,
> +                 StartAddr,
> +                 Size,
> +                 Asid
> +                 );
> +  return TranslateError (Ret.Error);
> +}
> +
> +/**
> +  Instructs the remote harts to execute one or more SFENCE.GVMA instructions.
> +
> +  The SFENCE.GVMA covers the range of virtual addresses between StartAaddr and Size.
> +  Covers only the given VMID.
> +  This function call is only valid for harts implementing the hypervisor extension.
> +
> +  The remote fence function acts as a full tlb flush if * StartAddr and size
> +  are both 0 * size is equal to 2^XLEN-1
> +
> +  @param[in]  HartMask             Scalar bit-vector containing hart ids
> +  @param[in]  HartMaskBase         The starting hartid from which the bit-vector
> +                                   must be computed. If set to -1, HartMask is
> +                                   ignored and all harts are considered.
> +  @param[in]  StartAddr            The first address of the affected range.
> +  @param[in]  Size                 How many addresses are affected.
> +  @retval EFI_SUCCESS              IPI was sent to all the targeted harts.
> +  @retval EFI_LOAD_ERROR           StartAddr or Size is not valid.
> +  @retval EFI_UNSUPPORTED          SBI does not implement this function or one
> +                                   of the target harts does not support the
> +                                   hypervisor extension.
> +  @retval EFI_INVALID_PARAMETER    Either hart_mask_base or any of the hartid
> +                                   from hart_mask is not valid i.e. either the
> +                                   hartid is not enabled by the platform or is
> +                                   not available to the supervisor.
> +**/
> +EFI_STATUS
> +EFIAPI
> +SbiRemoteHFenceGvmaVmid (
> +  IN  UINTN                         *HartMask,
> +  IN  UINTN                          HartMaskBase,
> +  IN  UINTN                          StartAddr,
> +  IN  UINTN                          Size,
> +  IN  UINTN                          Vmid
> +  )
> +{
> +  SbiRet Ret = SbiCall (
> +                 SBI_EXT_RFENCE,
> +                 SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA,
> +                 5,
> +                 (UINTN)HartMask,
> +                 HartMaskBase,
> +                 StartAddr,
> +                 Size,
> +                 Vmid
> +                 );
> +  return TranslateError (Ret.Error);
> +}
> +
> +/**
> +  Instructs the remote harts to execute one or more SFENCE.GVMA instructions.
> +
> +  The SFENCE.GVMA covers the range of virtual addresses between StartAaddr and Size.
> +  This function call is only valid for harts implementing the hypervisor extension.
> +
> +  The remote fence function acts as a full tlb flush if * StartAddr and size
> +  are both 0 * size is equal to 2^XLEN-1
> +
> +  @param[in]  HartMask             Scalar bit-vector containing hart ids
> +  @param[in]  HartMaskBase         The starting hartid from which the bit-vector
> +                                   must be computed. If set to -1, HartMask is
> +                                   ignored and all harts are considered.
> +  @param[in]  StartAddr            The first address of the affected range.
> +  @param[in]  Size                 How many addresses are affected.
> +  @retval EFI_SUCCESS              IPI was sent to all the targeted harts.
> +  @retval EFI_LOAD_ERROR           StartAddr or Size is not valid.
> +  @retval EFI_UNSUPPORTED          SBI does not implement this function or one
> +                                   of the target harts does not support the
> +                                   hypervisor extension.
> +  @retval EFI_INVALID_PARAMETER    Either hart_mask_base or any of the hartid
> +                                   from hart_mask is not valid i.e. either the
> +                                   hartid is not enabled by the platform or is
> +                                   not available to the supervisor.
> +**/
> +EFI_STATUS
> +EFIAPI
> +SbiRemoteHFenceGvma (
> +  IN  UINTN                         *HartMask,
> +  IN  UINTN                          HartMaskBase,
> +  IN  UINTN                          StartAddr,
> +  IN  UINTN                          Size
> +  )
> +{
> +  SbiRet Ret = SbiCall (
> +                 SBI_EXT_RFENCE,
> +                 SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA_VMID,
> +                 4,
> +                 (UINTN)HartMask,
> +                 HartMaskBase,
> +                 StartAddr,
> +                 Size
> +                 );
> +  return TranslateError (Ret.Error);
> +}
> +
> +/**
> +  Instructs the remote harts to execute one or more SFENCE.VVMA instructions.
> +
> +  The SFENCE.GVMA covers the range of virtual addresses between StartAaddr and Size.
> +  Covers only the given ASID.
> +  This function call is only valid for harts implementing the hypervisor extension.
> +
> +  The remote fence function acts as a full tlb flush if * StartAddr and size
> +  are both 0 * size is equal to 2^XLEN-1
> +
> +  @param[in]  HartMask             Scalar bit-vector containing hart ids
> +  @param[in]  HartMaskBase         The starting hartid from which the bit-vector
> +                                   must be computed. If set to -1, HartMask is
> +                                   ignored and all harts are considered.
> +  @param[in]  StartAddr            The first address of the affected range.
> +  @param[in]  Size                 How many addresses are affected.
> +  @retval EFI_SUCCESS              IPI was sent to all the targeted harts.
> +  @retval EFI_LOAD_ERROR           StartAddr or Size is not valid.
> +  @retval EFI_UNSUPPORTED          SBI does not implement this function or one
> +                                   of the target harts does not support the
> +                                   hypervisor extension.
> +  @retval EFI_INVALID_PARAMETER    Either hart_mask_base or any of the hartid
> +                                   from hart_mask is not valid i.e. either the
> +                                   hartid is not enabled by the platform or is
> +                                   not available to the supervisor.
> +**/
> +EFI_STATUS
> +EFIAPI
> +SbiRemoteHFenceVvmaAsid (
> +  IN  UINTN                         *HartMask,
> +  IN  UINTN                          HartMaskBase,
> +  IN  UINTN                          StartAddr,
> +  IN  UINTN                          Size,
> +  IN  UINTN                          Asid
> +  )
> +{
> +  SbiRet Ret = SbiCall (
> +                 SBI_EXT_RFENCE,
> +                 SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA,
> +                 5,
> +                 (UINTN)HartMask,
> +                 HartMaskBase,
> +                 StartAddr,
> +                 Size,
> +                 Asid
> +                 );
> +  return TranslateError (Ret.Error);
> +}
> +
> +/**
> +  Instructs the remote harts to execute one or more SFENCE.VVMA instructions.
> +
> +  The SFENCE.GVMA covers the range of virtual addresses between StartAaddr and Size.
> +  This function call is only valid for harts implementing the hypervisor extension.
> +
> +  The remote fence function acts as a full tlb flush if * StartAddr and size
> +  are both 0 * size is equal to 2^XLEN-1
> +
> +  @param[in]  HartMask             Scalar bit-vector containing hart ids
> +  @param[in]  HartMaskBase         The starting hartid from which the bit-vector
> +                                   must be computed. If set to -1, HartMask is
> +                                   ignored and all harts are considered.
> +  @param[in]  StartAddr            The first address of the affected range.
> +  @param[in]  Size                 How many addresses are affected.
> +  @retval EFI_SUCCESS              IPI was sent to all the targeted harts.
> +  @retval EFI_LOAD_ERROR           StartAddr or Size is not valid.
> +  @retval EFI_UNSUPPORTED          SBI does not implement this function or one
> +                                   of the target harts does not support the
> +                                   hypervisor extension.
> +  @retval EFI_INVALID_PARAMETER    Either hart_mask_base or any of the hartid
> +                                   from hart_mask is not valid i.e. either the
> +                                   hartid is not enabled by the platform or is
> +                                   not available to the supervisor.
> +**/
> +EFI_STATUS
> +EFIAPI
> +SbiRemoteHFenceVvma (
> +  IN  UINTN                         *HartMask,
> +  IN  UINTN                          HartMaskBase,
> +  IN  UINTN                          StartAddr,
> +  IN  UINTN                          Size
> +  )
> +{
> +  SbiRet Ret = SbiCall (
> +                 SBI_EXT_RFENCE,
> +                 SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA_ASID,
> +                 4,
> +                 (UINTN)HartMask,
> +                 HartMaskBase,
> +                 StartAddr,
> +                 Size
> +                 );
> +  return TranslateError (Ret.Error);
> +}
> +
> +//
> +// SBI interface function for the vendor extension
> +//
> +
> +/**
> +  Call a function in a vendor defined SBI extension
> +
> +  ASSERT() if the ExtensionId is not in the designated SBI Vendor Extension
> +  Space or NumArgs exceeds SBI_CALL_MAX_ARGS.
> +
> +  @param[in]  ExtensionId          The SBI vendor extension ID.
> +  @param[in]  FunctionId           The function ID to call in this extension.
> +  @param[in]  NumArgs              How many arguments are passed.
> +  @param[in]  ...                  Actual Arguments to the function.
> +  @retval EFI_SUCCESS if the SBI function was called and it was successful
> +  @retval others if the called SBI function returns an error
> +**/
> +EFI_STATUS
> +EFIAPI
> +SbiVendorCall (
> +  IN  UINTN                          ExtensionId,
> +  IN  UINTN                          FunctionId,
> +  IN  UINTN                          NumArgs,
> +  ...
> +  )
> +{
> +    SbiRet Ret;
> +    VA_LIST Args;
> +    VA_START (Args, NumArgs);
> +
> +    ASSERT (ExtensionId >= SBI_EXT_VENDOR_START && ExtensionId <= SBI_EXT_VENDOR_END);
> +    ASSERT (NumArgs <= SBI_CALL_MAX_ARGS);
> +
> +    switch (NumArgs) {
> +      case 0:
> +        Ret = SbiCall (ExtensionId, FunctionId, NumArgs);
> +        break;
> +      case 1:
> +        Ret = SbiCall (ExtensionId, FunctionId, NumArgs, VA_ARG (Args, UINTN));
> +        break;
> +      case 2:
> +        Ret = SbiCall (ExtensionId, FunctionId, NumArgs, VA_ARG (Args, UINTN),
> +                       VA_ARG (Args, UINTN));
> +        break;
> +      case 3:
> +        Ret = SbiCall (ExtensionId, FunctionId, NumArgs, VA_ARG (Args, UINTN),
> +                       VA_ARG (Args, UINTN), VA_ARG (Args, UINTN));
> +        break;
> +      case 4:
> +        Ret = SbiCall (ExtensionId, FunctionId, NumArgs, VA_ARG (Args, UINTN),
> +                       VA_ARG (Args, UINTN), VA_ARG (Args, UINTN),
> +                       VA_ARG (Args, UINTN));
> +        break;
> +      case 5:
> +        Ret = SbiCall (ExtensionId, FunctionId, NumArgs, VA_ARG (Args, UINTN),
> +                       VA_ARG (Args, UINTN), VA_ARG (Args, UINTN),
> +                       VA_ARG (Args, UINTN), VA_ARG (Args, UINTN));
> +        break;
> +      case 6:
> +        Ret = SbiCall (ExtensionId, FunctionId, NumArgs, VA_ARG (Args, UINTN),
> +                       VA_ARG (Args, UINTN), VA_ARG (Args, UINTN),
> +                       VA_ARG (Args, UINTN), VA_ARG (Args, UINTN),
> +                       VA_ARG (Args, UINTN));
> +        break;
> +      default:
> +        // Too many args. In theory SBI can handle more arguments when they are
> +        // passed on the stack but no SBI extension uses this, therefore it's
> +        // not yet implemented here.
> +        return EFI_INVALID_PARAMETER;
> +     }
> +
> +    VA_END(Args);
> +    return TranslateError (Ret.Error);
> +}
> +
> +//
> +// SBI Firmware extension
> +//
> +
> +/**
> +  Get scratch space of the current hart.
> +
> +  Please consider using the wrapper SbiGetFirmwareContext if you only need to
> +  access the firmware context.
> +
> +  @param[out] ScratchSpace         The scratch space pointer.
> +  @retval EFI_SUCCESS              The operation succeeds.
> +**/
> +EFI_STATUS
> +EFIAPI
> +SbiGetMscratch (
> +  OUT SBI_SCRATCH                    **ScratchSpace
> +  )
> +{
> +  SbiRet Ret = SbiCall (SBI_EDK2_FW_EXT, SBI_EXT_FW_MSCRATCH_FUNC, 0);
> +
> +  if (!Ret.Error) {
> +    *ScratchSpace = (SBI_SCRATCH *)Ret.Value;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Get scratch space of the given hart id.
> +
> +  @param[in]  HartId               The hart id.
> +  @param[out] ScratchSpace         The scratch space pointer.
> +  @retval EFI_SUCCESS              The operation succeeds.
> +**/
> +EFI_STATUS
> +EFIAPI
> +SbiGetMscratchHartid (
> +  IN  UINTN                            HartId,
> +  OUT SBI_SCRATCH                    **ScratchSpace
> +  )
> +{
> +  SbiRet Ret = SbiCall (
> +                 SBI_EDK2_FW_EXT,
> +                 SBI_EXT_FW_MSCRATCH_HARTID_FUNC,
> +                 1,
> +                 HartId
> +                 );
> +
> +  if (!Ret.Error) {
> +    *ScratchSpace = (SBI_SCRATCH *)Ret.Value;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Get firmware context of the calling hart.
> +
> +  @param[out] FirmwareContext      The firmware context pointer.
> +  @retval EFI_SUCCESS              The operation succeeds.
> +**/
> +EFI_STATUS
> +EFIAPI
> +SbiGetFirmwareContext (
> +  OUT EFI_RISCV_OPENSBI_FIRMWARE_CONTEXT **FirmwareContext
> +  )
> +{
> +  SBI_SCRATCH  *ScratchSpace;
> +  SBI_PLATFORM *SbiPlatform;
> +  SbiRet Ret = SbiCall (SBI_EDK2_FW_EXT, SBI_EXT_FW_MSCRATCH_FUNC, 0);
> +
> +  if (!Ret.Error) {
> +    ScratchSpace = (SBI_SCRATCH *)Ret.Value;
> +    SbiPlatform = (SBI_PLATFORM *)sbi_platform_ptr(ScratchSpace);
> +    *FirmwareContext = (EFI_RISCV_OPENSBI_FIRMWARE_CONTEXT *)SbiPlatform->firmware_context;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Set firmware context of the calling hart.
> +
> +  @param[in] FirmwareContext       The firmware context pointer.
> +  @retval EFI_SUCCESS              The operation succeeds.
> +**/
> +EFI_STATUS
> +EFIAPI
> +SbiSetFirmwareContext (
> +  IN EFI_RISCV_OPENSBI_FIRMWARE_CONTEXT *FirmwareContext
> +  )
> +{
> +  SBI_SCRATCH  *ScratchSpace;
> +  SBI_PLATFORM *SbiPlatform;
> +  SbiRet Ret = SbiCall (SBI_EDK2_FW_EXT, SBI_EXT_FW_MSCRATCH_FUNC, 0);
> +
> +  if (!Ret.Error) {
> +    ScratchSpace = (SBI_SCRATCH *)Ret.Value;
> +    SbiPlatform = (SBI_PLATFORM *)sbi_platform_ptr (ScratchSpace);
> +    SbiPlatform->firmware_context = (UINTN)FirmwareContext;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> -- 
> 2.26.1
> 
> 
> 
> 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [edk2-devel] [PATCH v4 1/1] ProcessorPkg/Library: Add RiscVEdk2SbiLib
  2020-06-18 16:49   ` Leif Lindholm
@ 2020-06-23  2:08     ` Abner Chang
  0 siblings, 0 replies; 7+ messages in thread
From: Abner Chang @ 2020-06-23  2:08 UTC (permalink / raw)
  To: Leif Lindholm, devel@edk2.groups.io, Schaefer, Daniel (DualStudy)
  Cc: Chen, Gilbert, Michael D . Kinney

Thanks for spent time on reviewing this. Yes, we can have further discussions on where to merge RISC-V code. For now, we will merge those code to edk2-platforms master branch as the temporary home for RISC-V.

Another matter regards to the inconsistent naming of "RISC-V", "RiscV" and etc. brought up by Mike, any one else has the same concerns as  Mike of using "RISC-V" as folder name, however "RiscV" as the leading in file name?
I still don't think it does matter though, but I would like to see more opinions on this.

Thanks
Abner

> -----Original Message-----
> From: Leif Lindholm [mailto:leif@nuviainc.com]
> Sent: Friday, June 19, 2020 12:50 AM
> To: devel@edk2.groups.io; Schaefer, Daniel (DualStudy)
> <daniel.schaefer@hpe.com>
> Cc: Chen, Gilbert <gilbert.chen@hpe.com>; Chang, Abner (HPS SW/FW
> Technologist) <abner.chang@hpe.com>; Michael D . Kinney
> <michael.d.kinney@intel.com>
> Subject: Re: [edk2-devel] [PATCH v4 1/1] ProcessorPkg/Library: Add
> RiscVEdk2SbiLib
> 
> On Tue, Jun 02, 2020 at 18:51:52 +0200, Daniel Schaefer wrote:
> > Library provides interfaces to invoke SBI ecalls.
> >
> > Signed-off-by: Daniel Schaefer <daniel.schaefer@hpe.com>
> 
> All of my feedback on previous revision addressed - where to actually
> *merge* it remains undecided, but for the contents:
> Reviewed-by: Leif Lindholm <leif@nuviainc.com>
> 
> Thanks!
> 
> > Cc: Leif Lindholm <leif@nuviainc.com>
> > Cc: Gilbert Chen <gilbert.chen@hpe.com>
> > Cc: Abner Chang <abner.chang@hpe.com>
> > Cc: Michael D. Kinney <michael.d.kinney@intel.com>
> > ---
> >  Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.inf |
> 28 +
> >  Silicon/RISC-V/ProcessorPkg/Include/Library/RiscVEdk2SbiLib.h           | 563
> ++++++++++++
> >  Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.c   |
> 897 ++++++++++++++++++++
> >  3 files changed, 1488 insertions(+)
> >
> > diff --git a/Silicon/RISC-
> V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.inf b/Silicon/RISC-
> V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.inf
> > new file mode 100644
> > index 000000000000..665dcbf40e01
> > --- /dev/null
> > +++ b/Silicon/RISC-
> V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.inf
> > @@ -0,0 +1,28 @@
> > +## @file
> > +# RISC-V Library to call SBI ecalls
> > +#
> > +#  Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All
> rights reserved.<BR>
> > +#
> > +#  SPDX-License-Identifier: BSD-2-Clause-Patent
> > +#
> > +##
> > +
> > +[Defines]
> > +  INF_VERSION    = 0x0001001b
> > +  BASE_NAME      = RiscVEdk2SbiLib
> > +  FILE_GUID      = 0DF1BBBD-F7E5-4E8A-BCF1-9D63D2DD9FDD
> > +  MODULE_TYPE    = BASE
> > +  VERSION_STRING = 1.0
> > +  LIBRARY_CLASS  = RiscVEdk2SbiLib
> > +
> > +[Sources]
> > +  RiscVEdk2SbiLib.c
> > +
> > +[Packages]
> > +  MdePkg/MdePkg.dec
> > +  Silicon/RISC-V/ProcessorPkg/RiscVProcessorPkg.dec
> > +  Platform/RISC-V/PlatformPkg/RiscVPlatformPkg.dec
> > +
> > +[LibraryClasses]
> > +  BaseLib
> > +  RiscVOpensbiLib
> > diff --git a/Silicon/RISC-V/ProcessorPkg/Include/Library/RiscVEdk2SbiLib.h
> b/Silicon/RISC-V/ProcessorPkg/Include/Library/RiscVEdk2SbiLib.h
> > new file mode 100644
> > index 000000000000..c1ae3176147f
> > --- /dev/null
> > +++ b/Silicon/RISC-V/ProcessorPkg/Include/Library/RiscVEdk2SbiLib.h
> > @@ -0,0 +1,563 @@
> > +/** @file
> > +  Library to call the RISC-V SBI ecalls
> > +
> > +  Copyright (c) 2020, Hewlett Packard Development LP. All rights
> reserved.<BR>
> > +
> > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > +
> > +  @par Glossary:
> > +    - Hart - Hardware Thread, similar to a CPU core
> > +**/
> > +
> > +#ifndef RISCV_SBI_LIB_H_
> > +#define RISCV_SBI_LIB_H_
> > +
> > +#include <Uefi.h>
> > +#include <IndustryStandard/RiscVOpensbi.h>
> > +#include <sbi/sbi_scratch.h>
> > +#include <sbi/sbi_platform.h>
> > +
> > +//
> > +// EDK2 OpenSBI Firmware extension.
> > +//
> > +#define SBI_EDK2_FW_EXT (SBI_EXT_FIRMWARE_CODE_BASE_START |
> SBI_OPENSBI_IMPID)
> > +//
> > +// EDK2 OpenSBI Firmware extension functions.
> > +//
> > +#define SBI_EXT_FW_MSCRATCH_FUNC        0
> > +#define SBI_EXT_FW_MSCRATCH_HARTID_FUNC 1
> > +
> > +//
> > +// EDK2 OpenSBI firmware extension return status.
> > +//
> > +typedef struct {
> > +  UINTN Error;   ///< SBI status code
> > +  UINTN Value;   ///< Value returned
> > +} SbiRet;
> > +
> > +/**
> > +  Get the implemented SBI specification version
> > +
> > +  The minor number of the SBI specification is encoded in the low 24 bits,
> > +  with the major number encoded in the next 7 bits.  Bit 32 must be 0 and
> is
> > +  reserved for future expansion.
> > +
> > +  @param[out] SpecVersion          The Version of the SBI specification.
> > +**/
> > +VOID
> > +EFIAPI
> > +SbiGetSpecVersion (
> > +  OUT UINTN                       *SpecVersion
> > +  );
> > +
> > +/**
> > +  Get the SBI implementation ID
> > +
> > +  This ID is used to idenetify a specific SBI implementation in order to work
> > +  around any quirks it might have.
> > +
> > +  @param[out] ImplId               The ID of the SBI implementation.
> > +**/
> > +VOID
> > +EFIAPI
> > +SbiGetImplId (
> > +  OUT UINTN                      *ImplId
> > +  );
> > +
> > +/**
> > +  Get the SBI implementation version
> > +
> > +  The version of this SBI implementation.
> > +  The encoding of this number is determined by the specific SBI
> implementation.
> > +
> > +  @param[out] ImplVersion          The version of the SBI implementation.
> > +**/
> > +VOID
> > +EFIAPI
> > +SbiGetImplVersion (
> > +  OUT UINTN                       *ImplVersion
> > +  );
> > +
> > +/**
> > +  Probe whether an SBI extension is available
> > +
> > +  ProbeResult is set to 0 if the extension is not available or to an extension
> > +  specified value if it is available.
> > +
> > +  @param[in]  ExtensionId          The extension ID.
> > +  @param[out] ProbeResult          The return value of the probe.
> > +**/
> > +VOID
> > +EFIAPI
> > +SbiProbeExtension (
> > +  IN  INTN                         ExtensionId,
> > +  OUT INTN                        *ProbeResult
> > +  );
> > +
> > +/**
> > +  Get the CPU's vendor ID
> > +
> > +  Reads the mvendorid CSR.
> > +
> > +  @param[out] MachineVendorId      The CPU's vendor ID.
> > +**/
> > +VOID
> > +EFIAPI
> > +SbiGetMachineVendorId (
> > +  OUT UINTN                       *MachineVendorId
> > +  );
> > +
> > +/**
> > +  Get the CPU's architecture ID
> > +
> > +  Reads the marchid CSR.
> > +
> > +  @param[out] MachineArchId        The CPU's architecture ID.
> > +**/
> > +VOID
> > +EFIAPI
> > +SbiGetMachineArchId (
> > +  OUT UINTN                       *MachineArchId
> > +  );
> > +
> > +/**
> > +  Get the CPU's implementation ID
> > +
> > +  Reads the mimpid CSR.
> > +
> > +  @param[out] MachineImplId        The CPU's implementation ID.
> > +**/
> > +VOID
> > +EFIAPI
> > +SbiGetMachineImplId (
> > +  OUT UINTN                       *MachineImplId
> > +  );
> > +
> > +/**
> > +  Politely ask the SBI to start a given hart.
> > +
> > +  This call may return before the hart has actually started executing, if the
> > +  SBI implementation can guarantee that the hart is actually going to start.
> > +
> > +  Before the hart jumps to StartAddr, the hart MUST configure PMP if
> present
> > +  and switch to S-mode.
> > +
> > +  @param[in]  HartId               The id of the hart to start.
> > +  @param[in]  StartAddr            The physical address, where the hart starts
> > +                                   executing from.
> > +  @param[in]  Priv                 An XLEN-bit value, which will be in register
> > +                                   a1 when the hart starts.
> > +  @retval EFI_SUCCESS              Hart was stopped and will start executing
> from StartAddr.
> > +  @retval EFI_LOAD_ERROR           StartAddr is not valid, possibly due to
> following reasons:
> > +                                    - It is not a valid physical address.
> > +                                    - The address is prohibited by PMP to run in
> > +                                      supervisor mode.
> > +  @retval EFI_INVALID_PARAMETER    HartId is not a valid hart id
> > +  @retval EFI_ALREADY_STARTED      The hart is already running.
> > +  @retval other                    The start request failed for unknown reasons.
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +SbiHartStart (
> > +  IN  UINTN                          HartId,
> > +  IN  UINTN                          StartAddr,
> > +  IN  UINTN                          Priv
> > +  );
> > +
> > +/**
> > +  Return execution of the calling hart to SBI.
> > +
> > +  MUST be called in S-Mode with user interrupts disabled.
> > +  This call is not expected to return, unless a failure occurs.
> > +
> > +  @retval     EFI_SUCCESS          Never occurs. When successful, the call does
> not return.
> > +  @retval     other                Failed to stop hard for an unknown reason.
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +SbiHartStop (
> > +  );
> > +
> > +/**
> > +  Get the current status of a hart.
> > +
> > +  Since harts can transition between states at any time, the status
> retrieved
> > +  by this function may already be out of date, once it returns.
> > +
> > +  Possible values for HartStatus are:
> > +  0: STARTED
> > +  1: STOPPED
> > +  2: START_REQUEST_PENDING
> > +  3: STOP_REQUEST_PENDING
> > +
> > +  @param[out] HartStatus           The pointer in which the hart's status is
> > +                                   stored.
> > +  @retval EFI_SUCCESS              The operation succeeds.
> > +  @retval EFI_INVALID_PARAMETER    A parameter is invalid.
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +SbiHartGetStatus (
> > +  IN  UINTN                          HartId,
> > +  OUT UINTN                         *HartStatus
> > +  );
> > +
> > +///
> > +/// Timer extension
> > +///
> > +
> > +/**
> > +  Clear pending timer interrupt bit and set timer for next event after Time.
> > +
> > +  To clear the timer without scheduling a timer event, set Time to a
> > +  practically infinite value or mask the timer interrupt by clearing sie.STIE.
> > +
> > +  @param[in]  Time                 The time offset to the next scheduled timer
> interrupt.
> > +**/
> > +VOID
> > +EFIAPI
> > +SbiSetTimer (
> > +  IN  UINT64                         Time
> > +  );
> > +
> > +///
> > +/// IPI extension
> > +///
> > +
> > +/**
> > +  Send IPI to all harts specified in the mask.
> > +
> > +  The interrupts are registered as supervisor software interrupts at the
> > +  receiving hart.
> > +
> > +  @param[in]  HartMask             Scalar bit-vector containing hart ids
> > +  @param[in]  HartMaskBase         The starting hartid from which the bit-
> vector
> > +                                   must be computed. If set to -1, HartMask is
> > +                                   ignored and all harts are considered.
> > +  @retval EFI_SUCCESS              IPI was sent to all the targeted harts.
> > +  @retval EFI_INVALID_PARAMETER    Either hart_mask_base or any of
> the hartid
> > +                                   from hart_mask is not valid i.e. either the
> > +                                   hartid is not enabled by the platform or is
> > +                                   not available to the supervisor.
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +SbiSendIpi (
> > +  IN  UINTN                         *HartMask,
> > +  IN  UINTN                          HartMaskBase
> > +  );
> > +
> > +///
> > +/// Remote fence extension
> > +///
> > +
> > +/**
> > +  Instructs remote harts to execute a FENCE.I instruction.
> > +
> > +  @param[in]  HartMask             Scalar bit-vector containing hart ids
> > +  @param[in]  HartMaskBase         The starting hartid from which the bit-
> vector
> > +                                   must be computed. If set to -1, HartMask is
> > +                                   ignored and all harts are considered.
> > +  @retval EFI_SUCCESS              IPI was sent to all the targeted harts.
> > +  @retval EFI_INVALID_PARAMETER    Either hart_mask_base or any of
> the hartid
> > +                                   from hart_mask is not valid i.e. either the
> > +                                   hartid is not enabled by the platform or is
> > +                                   not available to the supervisor.
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +SbiRemoteFenceI (
> > +  IN  UINTN                         *HartMask,
> > +  IN  UINTN                          HartMaskBase
> > +  );
> > +
> > +/**
> > +  Instructs the remote harts to execute one or more SFENCE.VMA
> instructions.
> > +
> > +  The SFENCE.VMA covers the range of virtual addresses between
> StartAaddr and Size.
> > +
> > +  The remote fence function acts as a full tlb flush if * StartAddr and size
> > +  are both 0 * size is equal to 2^XLEN-1
> > +
> > +  @param[in]  HartMask             Scalar bit-vector containing hart ids
> > +  @param[in]  HartMaskBase         The starting hartid from which the bit-
> vector
> > +                                   must be computed. If set to -1, HartMask is
> > +                                   ignored and all harts are considered.
> > +  @param[in]  StartAddr            The first address of the affected range.
> > +  @param[in]  Size                 How many addresses are affected.
> > +  @retval EFI_SUCCESS              IPI was sent to all the targeted harts.
> > +  @retval EFI_LOAD_ERROR           StartAddr or Size is not valid.
> > +  @retval EFI_INVALID_PARAMETER    Either hart_mask_base or any of
> the hartid
> > +                                   from hart_mask is not valid i.e. either the
> > +                                   hartid is not enabled by the platform or is
> > +                                   not available to the supervisor.
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +SbiRemoteSfenceVma (
> > +  IN  UINTN                         *HartMask,
> > +  IN  UINTN                          HartMaskBase,
> > +  IN  UINTN                          StartAddr,
> > +  IN  UINTN                          Size
> > +  );
> > +
> > +/**
> > +  Instructs the remote harts to execute one or more SFENCE.VMA
> instructions.
> > +
> > +  The SFENCE.VMA covers the range of virtual addresses between
> StartAaddr and Size.
> > +  Covers only the given ASID.
> > +
> > +  The remote fence function acts as a full tlb flush if * StartAddr and size
> > +  are both 0 * size is equal to 2^XLEN-1
> > +
> > +  @param[in]  HartMask             Scalar bit-vector containing hart ids
> > +  @param[in]  HartMaskBase         The starting hartid from which the bit-
> vector
> > +                                   must be computed. If set to -1, HartMask is
> > +                                   ignored and all harts are considered.
> > +  @param[in]  StartAddr            The first address of the affected range.
> > +  @param[in]  Size                 How many addresses are affected.
> > +  @retval EFI_SUCCESS              IPI was sent to all the targeted harts.
> > +  @retval EFI_LOAD_ERROR           StartAddr or Size is not valid.
> > +  @retval EFI_INVALID_PARAMETER    Either hart_mask_base or any of
> the hartid
> > +                                   from hart_mask is not valid i.e. either the
> > +                                   hartid is not enabled by the platform or is
> > +                                   not available to the supervisor.
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +SbiRemoteSfenceVmaAsid (
> > +  IN  UINTN                         *HartMask,
> > +  IN  UINTN                          HartMaskBase,
> > +  IN  UINTN                          StartAddr,
> > +  IN  UINTN                          Size,
> > +  IN  UINTN                          Asid
> > +  );
> > +
> > +/**
> > +  Instructs the remote harts to execute one or more SFENCE.GVMA
> instructions.
> > +
> > +  The SFENCE.GVMA covers the range of virtual addresses between
> StartAaddr and Size.
> > +  Covers only the given VMID.
> > +  This function call is only valid for harts implementing the hypervisor
> extension.
> > +
> > +  The remote fence function acts as a full tlb flush if * StartAddr and size
> > +  are both 0 * size is equal to 2^XLEN-1
> > +
> > +  @param[in]  HartMask             Scalar bit-vector containing hart ids
> > +  @param[in]  HartMaskBase         The starting hartid from which the bit-
> vector
> > +                                   must be computed. If set to -1, HartMask is
> > +                                   ignored and all harts are considered.
> > +  @param[in]  StartAddr            The first address of the affected range.
> > +  @param[in]  Size                 How many addresses are affected.
> > +  @retval EFI_SUCCESS              IPI was sent to all the targeted harts.
> > +  @retval EFI_LOAD_ERROR           StartAddr or Size is not valid.
> > +  @retval EFI_UNSUPPORTED          SBI does not implement this function or
> one
> > +                                   of the target harts does not support the
> > +                                   hypervisor extension.
> > +  @retval EFI_INVALID_PARAMETER    Either hart_mask_base or any of
> the hartid
> > +                                   from hart_mask is not valid i.e. either the
> > +                                   hartid is not enabled by the platform or is
> > +                                   not available to the supervisor.
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +SbiRemoteHfenceGvmaVmid (
> > +  IN  UINTN                         *HartMask,
> > +  IN  UINTN                          HartMaskBase,
> > +  IN  UINTN                          StartAddr,
> > +  IN  UINTN                          Size,
> > +  IN  UINTN                          Vmid
> > +  );
> > +
> > +/**
> > +  Instructs the remote harts to execute one or more SFENCE.GVMA
> instructions.
> > +
> > +  The SFENCE.GVMA covers the range of virtual addresses between
> StartAaddr and Size.
> > +  This function call is only valid for harts implementing the hypervisor
> extension.
> > +
> > +  The remote fence function acts as a full tlb flush if * StartAddr and size
> > +  are both 0 * size is equal to 2^XLEN-1
> > +
> > +  @param[in]  HartMask             Scalar bit-vector containing hart ids
> > +  @param[in]  HartMaskBase         The starting hartid from which the bit-
> vector
> > +                                   must be computed. If set to -1, HartMask is
> > +                                   ignored and all harts are considered.
> > +  @param[in]  StartAddr            The first address of the affected range.
> > +  @param[in]  Size                 How many addresses are affected.
> > +  @retval EFI_SUCCESS              IPI was sent to all the targeted harts.
> > +  @retval EFI_LOAD_ERROR           StartAddr or Size is not valid.
> > +  @retval EFI_UNSUPPORTED          SBI does not implement this function or
> one
> > +                                   of the target harts does not support the
> > +                                   hypervisor extension.
> > +  @retval EFI_INVALID_PARAMETER    Either hart_mask_base or any of
> the hartid
> > +                                   from hart_mask is not valid i.e. either the
> > +                                   hartid is not enabled by the platform or is
> > +                                   not available to the supervisor.
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +SbiRemoteHfenceGvma (
> > +  IN  UINTN                         *HartMask,
> > +  IN  UINTN                          HartMaskBase,
> > +  IN  UINTN                          StartAddr,
> > +  IN  UINTN                          Size
> > +  );
> > +
> > +/**
> > +  Instructs the remote harts to execute one or more SFENCE.VVMA
> instructions.
> > +
> > +  The SFENCE.GVMA covers the range of virtual addresses between
> StartAaddr and Size.
> > +  Covers only the given ASID.
> > +  This function call is only valid for harts implementing the hypervisor
> extension.
> > +
> > +  The remote fence function acts as a full tlb flush if * StartAddr and size
> > +  are both 0 * size is equal to 2^XLEN-1
> > +
> > +  @param[in]  HartMask             Scalar bit-vector containing hart ids
> > +  @param[in]  HartMaskBase         The starting hartid from which the bit-
> vector
> > +                                   must be computed. If set to -1, HartMask is
> > +                                   ignored and all harts are considered.
> > +  @param[in]  StartAddr            The first address of the affected range.
> > +  @param[in]  Size                 How many addresses are affected.
> > +  @retval EFI_SUCCESS              IPI was sent to all the targeted harts.
> > +  @retval EFI_LOAD_ERROR           StartAddr or Size is not valid.
> > +  @retval EFI_UNSUPPORTED          SBI does not implement this function or
> one
> > +                                   of the target harts does not support the
> > +                                   hypervisor extension.
> > +  @retval EFI_INVALID_PARAMETER    Either hart_mask_base or any of
> the hartid
> > +                                   from hart_mask is not valid i.e. either the
> > +                                   hartid is not enabled by the platform or is
> > +                                   not available to the supervisor.
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +SbiRemoteHfenceVvmaAsid (
> > +  IN  UINTN                         *HartMask,
> > +  IN  UINTN                          HartMaskBase,
> > +  IN  UINTN                          StartAddr,
> > +  IN  UINTN                          Size,
> > +  IN  UINTN                          Asid
> > +  );
> > +
> > +/**
> > +  Instructs the remote harts to execute one or more SFENCE.VVMA
> instructions.
> > +
> > +  The SFENCE.GVMA covers the range of virtual addresses between
> StartAaddr and Size.
> > +  This function call is only valid for harts implementing the hypervisor
> extension.
> > +
> > +  The remote fence function acts as a full tlb flush if * StartAddr and size
> > +  are both 0 * size is equal to 2^XLEN-1
> > +
> > +  @param[in]  HartMask             Scalar bit-vector containing hart ids
> > +  @param[in]  HartMaskBase         The starting hartid from which the bit-
> vector
> > +                                   must be computed. If set to -1, HartMask is
> > +                                   ignored and all harts are considered.
> > +  @param[in]  StartAddr            The first address of the affected range.
> > +  @param[in]  Size                 How many addresses are affected.
> > +  @retval EFI_SUCCESS              IPI was sent to all the targeted harts.
> > +  @retval EFI_LOAD_ERROR           StartAddr or Size is not valid.
> > +  @retval EFI_UNSUPPORTED          SBI does not implement this function or
> one
> > +                                   of the target harts does not support the
> > +                                   hypervisor extension.
> > +  @retval EFI_INVALID_PARAMETER    Either hart_mask_base or any of
> the hartid
> > +                                   from hart_mask is not valid i.e. either the
> > +                                   hartid is not enabled by the platform or is
> > +                                   not available to the supervisor.
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +SbiRemoteHfenceVvma (
> > +  IN  UINTN                         *HartMask,
> > +  IN  UINTN                          HartMaskBase,
> > +  IN  UINTN                          StartAddr,
> > +  IN  UINTN                          Size
> > +  );
> > +
> > +///
> > +/// Vendor Specific extension space: Extension Ids 0x09000000 through
> 0x09FFFFFF
> > +///
> > +
> > +/**
> > +  Call a function in a vendor defined SBI extension
> > +
> > +  ASSERT() if the ExtensionId is not in the designated SBI Vendor Extension
> > +  Space.
> > +
> > +  @param[in]  ExtensionId          The SBI vendor extension ID.
> > +  @param[in]  FunctionId           The function ID to call in this extension.
> > +  @param[in]  NumArgs              How many arguments are passed.
> > +  @param[in]  ...                  Actual Arguments to the function.
> > +  @retval EFI_SUCCESS if the SBI function was called and it was successful
> > +  @retval EFI_INVALID_PARAMETER if NumArgs exceeds 6
> > +  @retval others if the called SBI function returns an error
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +SbiVendorCall (
> > +  IN  UINTN                          ExtensionId,
> > +  IN  UINTN                          FunctionId,
> > +  IN  UINTN                          NumArgs,
> > +  ...
> > +  );
> > +
> > +///
> > +/// Firmware SBI Extension
> > +///
> > +/// This SBI Extension is defined and used by EDK2 only in order to be able
> to
> > +/// run PI and DXE phase in S-Mode.
> > +///
> > +
> > +/**
> > +  Get scratch space of the current hart.
> > +
> > +  Please consider using the wrapper SbiGetFirmwareContext if you only
> need to
> > +  access the firmware context.
> > +
> > +  @param[out] ScratchSpace         The scratch space pointer.
> > +  @retval EFI_SUCCESS              The operation succeeds.
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +SbiGetMscratch (
> > +  OUT SBI_SCRATCH                    **ScratchSpace
> > +  );
> > +
> > +/**
> > +  Get scratch space of the given hart id.
> > +
> > +  @param[in]  HartId               The hart id.
> > +  @param[out] ScratchSpace         The scratch space pointer.
> > +  @retval EFI_SUCCESS              The operation succeeds.
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +SbiGetMscratchHartid (
> > +  IN  UINTN                            HartId,
> > +  OUT SBI_SCRATCH                    **ScratchSpace
> > +  );
> > +
> > +/**
> > +  Get firmware context of the calling hart.
> > +
> > +  @param[out] FirmwareContext      The firmware context pointer.
> > +  @retval EFI_SUCCESS              The operation succeeds.
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +SbiGetFirmwareContext (
> > +  OUT EFI_RISCV_OPENSBI_FIRMWARE_CONTEXT **FirmwareContext
> > +  );
> > +
> > +/**
> > +  Set firmware context of the calling hart.
> > +
> > +  @param[in] FirmwareContext       The firmware context pointer.
> > +  @retval EFI_SUCCESS              The operation succeeds.
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +SbiSetFirmwareContext (
> > +  IN EFI_RISCV_OPENSBI_FIRMWARE_CONTEXT *FirmwareContext
> > +  );
> > +
> > +#endif
> > diff --git a/Silicon/RISC-
> V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.c b/Silicon/RISC-
> V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.c
> > new file mode 100644
> > index 000000000000..0df505d2675b
> > --- /dev/null
> > +++ b/Silicon/RISC-
> V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.c
> > @@ -0,0 +1,897 @@
> > +/** @file
> > +  Instance of the SBI ecall library.
> > +
> > +  It allows calling an SBI function via an ecall from S-Mode.
> > +
> > +  The legacy extensions are not included because they are not necessary.
> > +  They would be:
> > +  - SbiLegacySetTimer            -> Use SbiSetTimer
> > +  - SbiLegacyConsolePutChar      -> No replacement - Use regular UEFI
> functions
> > +  - SbiLegacyConsoleGetChar      -> No replacement - Use regular UEFI
> functions
> > +  - SbiLegacyClearIpi            -> Write 0 to SSIP
> > +  - SbiLegacySendIpi             -> Use SbiSendIpi
> > +  - SbiLegacyRemoteFenceI        -> Use SbiRemoteFenceI
> > +  - SbiLegacyRemoteSfenceVma     -> Use SbiRemoteSfenceVma
> > +  - SbiLegacyRemoteSfenceVmaAsid -> Use SbiRemoteSfenceVmaAsid
> > +  - SbiLegacyShutdown            -> Wait for new System Reset extension
> > +
> > +  Copyright (c) 2020, Hewlett Packard Development LP. All rights
> reserved.<BR>
> > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > +
> > +  @par Revision Reference:
> > +    - OpenSBI Version 0.6
> > +**/
> > +
> > +#include <IndustryStandard/RiscVOpensbi.h>
> > +#include <Library/BaseMemoryLib.h>
> > +#include <Library/DebugLib.h>
> > +#include <Library/RiscVEdk2SbiLib.h>
> > +#include <sbi/riscv_asm.h>
> > +#include <sbi/sbi_hart.h>
> > +#include <sbi/sbi_types.h>
> > +#include <sbi/sbi_init.h>
> > +
> > +
> > +//
> > +// Maximum arguments for SBI ecall
> > +// It's possible to pass more but no SBI call uses more as of SBI 0.2.
> > +// The additional arguments would have to be passed on the stack instead
> of as
> > +// registers, like it's done now.
> > +//
> > +#define SBI_CALL_MAX_ARGS 6
> > +
> > +/**
> > +  Call SBI call using ecall instruction.
> > +
> > +  Asserts when NumArgs exceeds SBI_CALL_MAX_ARGS.
> > +
> > +  @param[in] ExtId    SBI extension ID.
> > +  @param[in] FuncId   SBI function ID.
> > +  @param[in] NumArgs  Number of arguments to pass to the ecall.
> > +  @param[in] ...      Argument list for the ecall.
> > +
> > +  @retval  Returns SbiRet structure with value and error code.
> > +
> > +**/
> > +STATIC
> > +SbiRet
> > +EFIAPI
> > +SbiCall(
> > +  IN  UINTN ExtId,
> > +  IN  UINTN FuncId,
> > +  IN  UINTN NumArgs,
> > +  ...
> > +  )
> > +{
> > +    UINTN I;
> > +    SbiRet Ret;
> > +    UINTN Args[SBI_CALL_MAX_ARGS];
> > +    VA_LIST ArgList;
> > +    VA_START (ArgList, NumArgs);
> > +
> > +    ASSERT (NumArgs <= SBI_CALL_MAX_ARGS);
> > +
> > +    for (I = 0; I < SBI_CALL_MAX_ARGS; I++) {
> > +      if (I < NumArgs) {
> > +        Args[I] = VA_ARG (ArgList, UINTN);
> > +      } else {
> > +        // Default to 0 for all arguments that are not given
> > +        Args[I] = 0;
> > +      }
> > +    }
> > +
> > +    VA_END(ArgList);
> > +
> > +    register UINTN a0 asm ("a0") = Args[0];
> > +    register UINTN a1 asm ("a1") = Args[1];
> > +    register UINTN a2 asm ("a2") = Args[2];
> > +    register UINTN a3 asm ("a3") = Args[3];
> > +    register UINTN a4 asm ("a4") = Args[4];
> > +    register UINTN a5 asm ("a5") = Args[5];
> > +    register UINTN a6 asm ("a6") = (UINTN)(FuncId);
> > +    register UINTN a7 asm ("a7") = (UINTN)(ExtId);
> > +    asm volatile ("ecall" \
> > +         : "+r" (a0), "+r" (a1) \
> > +         : "r" (a2), "r" (a3), "r" (a4), "r" (a5), "r" (a6), "r" (a7) \
> > +         : "memory"); \
> > +    Ret.Error = a0;
> > +    Ret.Value = a1;
> > +    return Ret;
> > +}
> > +
> > +/**
> > +  Translate SBI error code to EFI status.
> > +
> > +  @param[in] SbiError   SBI error code
> > +  @retval EFI_STATUS
> > +**/
> > +
> > +STATIC
> > +EFI_STATUS
> > +EFIAPI
> > +TranslateError(
> > +  IN  UINTN SbiError
> > +  )
> > +{
> > +  switch (SbiError) {
> > +    case SBI_SUCCESS:
> > +      return EFI_SUCCESS;
> > +    case SBI_ERR_FAILED:
> > +      return EFI_DEVICE_ERROR;
> > +      break;
> > +    case SBI_ERR_NOT_SUPPORTED:
> > +      return EFI_UNSUPPORTED;
> > +      break;
> > +    case SBI_ERR_INVALID_PARAM:
> > +      return EFI_INVALID_PARAMETER;
> > +      break;
> > +    case SBI_ERR_DENIED:
> > +      return EFI_ACCESS_DENIED;
> > +      break;
> > +    case SBI_ERR_INVALID_ADDRESS:
> > +      return EFI_LOAD_ERROR;
> > +      break;
> > +    case SBI_ERR_ALREADY_AVAILABLE:
> > +      return EFI_ALREADY_STARTED;
> > +      break;
> > +    default:
> > +      //
> > +      // Reaches here only if SBI has defined a new error type
> > +      //
> > +      ASSERT (FALSE);
> > +      return EFI_UNSUPPORTED;
> > +      break;
> > +  }
> > +}
> > +
> > +//
> > +// OpenSBI library interface function for the base extension
> > +//
> > +
> > +/**
> > +  Get the implemented SBI specification version
> > +
> > +  The minor number of the SBI specification is encoded in the low 24 bits,
> > +  with the major number encoded in the next 7 bits.  Bit 32 must be 0 and
> is
> > +  reserved for future expansion.
> > +
> > +  @param[out] SpecVersion          The Version of the SBI specification.
> > +**/
> > +VOID
> > +EFIAPI
> > +SbiGetSpecVersion (
> > +  OUT UINTN                       *SpecVersion
> > +  )
> > +{
> > +  SbiRet Ret = SbiCall (SBI_EXT_BASE, SBI_EXT_BASE_GET_SPEC_VERSION,
> 0);
> > +
> > +  if (!Ret.Error) {
> > +    *SpecVersion = (UINTN)Ret.Value;
> > +  }
> > +}
> > +
> > +/**
> > +  Get the SBI implementation ID
> > +
> > +  This ID is used to idenetify a specific SBI implementation in order to work
> > +  around any quirks it might have.
> > +
> > +  @param[out] ImplId               The ID of the SBI implementation.
> > +**/
> > +VOID
> > +EFIAPI
> > +SbiGetImplId (
> > +  OUT UINTN                       *ImplId
> > +  )
> > +{
> > +  SbiRet Ret = SbiCall (SBI_EXT_BASE, SBI_EXT_BASE_GET_IMP_ID, 0);
> > +  *ImplId = (UINTN)Ret.Value;
> > +}
> > +
> > +/**
> > +  Get the SBI implementation version
> > +
> > +  The version of this SBI implementation.
> > +  The encoding of this number is determined by the specific SBI
> implementation.
> > +
> > +  @param[out] ImplVersion          The version of the SBI implementation.
> > +**/
> > +VOID
> > +EFIAPI
> > +SbiGetImplVersion (
> > +  OUT UINTN                       *ImplVersion
> > +  )
> > +{
> > +  SbiRet Ret = SbiCall (SBI_EXT_BASE, SBI_EXT_BASE_GET_IMP_VERSION,
> 0);
> > +  *ImplVersion = (UINTN)Ret.Value;
> > +}
> > +
> > +/**
> > +  Probe whether an SBI extension is available
> > +
> > +  ProbeResult is set to 0 if the extension is not available or to an extension
> > +  specified value if it is available.
> > +
> > +  @param[in]  ExtensionId          The extension ID.
> > +  @param[out] ProbeResult          The return value of the probe.
> > +**/
> > +VOID
> > +EFIAPI
> > +SbiProbeExtension (
> > +  IN  INTN                         ExtensionId,
> > +  OUT INTN                        *ProbeResult
> > +  )
> > +{
> > +  SbiRet Ret = SbiCall (SBI_EXT_BASE, SBI_EXT_BASE_PROBE_EXT, 0);
> > +  *ProbeResult = (UINTN)Ret.Value;
> > +}
> > +
> > +/**
> > +  Get the CPU's vendor ID
> > +
> > +  Reads the mvendorid CSR.
> > +
> > +  @param[out] MachineVendorId      The CPU's vendor ID.
> > +**/
> > +VOID
> > +EFIAPI
> > +SbiGetMachineVendorId (
> > +  OUT UINTN                       *MachineVendorId
> > +  )
> > +{
> > +  SbiRet Ret = SbiCall (SBI_EXT_BASE, SBI_EXT_BASE_GET_MVENDORID, 0);
> > +  *MachineVendorId = (UINTN)Ret.Value;
> > +}
> > +
> > +/**
> > +  Get the CPU's architecture ID
> > +
> > +  Reads the marchid CSR.
> > +
> > +  @param[out] MachineArchId        The CPU's architecture ID.
> > +**/
> > +VOID
> > +EFIAPI
> > +SbiGetMachineArchId (
> > +  OUT UINTN                       *MachineArchId
> > +  )
> > +{
> > +  SbiRet Ret = SbiCall (SBI_EXT_BASE, SBI_EXT_BASE_GET_MARCHID, 0);
> > +  *MachineArchId = (UINTN)Ret.Value;
> > +}
> > +
> > +/**
> > +  Get the CPU's architecture ID
> > +
> > +  Reads the marchid CSR.
> > +
> > +  @param[out] MachineImplId        The CPU's implementation ID.
> > +**/
> > +VOID
> > +EFIAPI
> > +SbiGetMachineImplId (
> > +  OUT UINTN                       *MachineImplId
> > +  )
> > +{
> > +  SbiRet Ret = SbiCall (SBI_EXT_BASE, SBI_EXT_BASE_GET_MIMPID, 0);
> > +  *MachineImplId = (UINTN)Ret.Value;
> > +}
> > +
> > +//
> > +// SBI interface function for the hart state management extension
> > +//
> > +
> > +/**
> > +  Politely ask the SBI to start a given hart.
> > +
> > +  This call may return before the hart has actually started executing, if the
> > +  SBI implementation can guarantee that the hart is actually going to start.
> > +
> > +  Before the hart jumps to StartAddr, the hart MUST configure PMP if
> present
> > +  and switch to S-mode.
> > +
> > +  @param[in]  HartId               The id of the hart to start.
> > +  @param[in]  StartAddr            The physical address, where the hart starts
> > +                                   executing from.
> > +  @param[in]  Priv                 An XLEN-bit value, which will be in register
> > +                                   a1 when the hart starts.
> > +  @retval EFI_SUCCESS              Hart was stopped and will start executing
> from StartAddr.
> > +  @retval EFI_LOAD_ERROR           StartAddr is not valid, possibly due to
> following reasons:
> > +                                     - It is not a valid physical address.
> > +                                     - The address is prohibited by PMP to run in
> > +                                       supervisor mode.
> > +  @retval EFI_INVALID_PARAMETER    HartId is not a valid hart id
> > +  @retval EFI_ALREADY_STARTED      The hart is already running.
> > +  @retval other                    The start request failed for unknown reasons.
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +SbiHartStart (
> > +  IN  UINTN                          HartId,
> > +  IN  UINTN                          StartAddr,
> > +  IN  UINTN                          Priv
> > +  )
> > +{
> > +  SbiRet Ret = SbiCall (
> > +                 SBI_EXT_HSM,
> > +                 SBI_EXT_HSM_HART_START,
> > +                 3,
> > +                 HartId,
> > +                 StartAddr,
> > +                 Priv
> > +                 );
> > +  return TranslateError (Ret.Error);
> > +}
> > +
> > +/**
> > +  Return execution of the calling hart to SBI.
> > +
> > +  MUST be called in S-Mode with user interrupts disabled.
> > +  This call is not expected to return, unless a failure occurs.
> > +
> > +  @retval     EFI_SUCCESS          Never occurs. When successful, the call does
> not return.
> > +  @retval     other                Failed to stop hard for an unknown reason.
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +SbiHartStop (
> > +  )
> > +{
> > +  SbiRet Ret = SbiCall (SBI_EXT_HSM, SBI_EXT_HSM_HART_STOP, 0);
> > +  return TranslateError (Ret.Error);
> > +}
> > +
> > +/**
> > +  Get the current status of a hart.
> > +
> > +  Since harts can transition between states at any time, the status
> retrieved
> > +  by this function may already be out of date, once it returns.
> > +
> > +  Possible values for HartStatus are:
> > +  0: STARTED
> > +  1: STOPPED
> > +  2: START_REQUEST_PENDING
> > +  3: STOP_REQUEST_PENDING
> > +
> > +  @param[out] HartStatus           The pointer in which the hart's status is
> > +                                   stored.
> > +  @retval EFI_SUCCESS              The operation succeeds.
> > +  @retval EFI_INVALID_PARAMETER    A parameter is invalid.
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +SbiHartGetStatus (
> > +  IN  UINTN                          HartId,
> > +  OUT UINTN                         *HartStatus
> > +  )
> > +{
> > +  SbiRet Ret = SbiCall (SBI_EXT_HSM, SBI_EXT_HSM_HART_GET_STATUS, 1,
> HartId);
> > +
> > +  if (!Ret.Error) {
> > +    *HartStatus = (UINTN)Ret.Value;
> > +  }
> > +
> > +  return TranslateError (Ret.Error);
> > +}
> > +
> > +/**
> > +  Clear pending timer interrupt bit and set timer for next event after Time.
> > +
> > +  To clear the timer without scheduling a timer event, set Time to a
> > +  practically infinite value or mask the timer interrupt by clearing sie.STIE.
> > +
> > +  @param[in]  Time                 The time offset to the next scheduled timer
> interrupt.
> > +**/
> > +VOID
> > +EFIAPI
> > +SbiSetTimer (
> > +  IN  UINT64                         Time
> > +  )
> > +{
> > +  SbiCall (SBI_EXT_TIME, SBI_EXT_TIME_SET_TIMER, 1, Time);
> > +}
> > +
> > +EFI_STATUS
> > +EFIAPI
> > +SbiSendIpi (
> > +  IN  UINTN                         *HartMask,
> > +  IN  UINTN                          HartMaskBase
> > +  )
> > +{
> > +  SbiRet Ret = SbiCall (
> > +                 SBI_EXT_IPI,
> > +                 SBI_EXT_IPI_SEND_IPI,
> > +                 2,
> > +                 (UINTN)HartMask,
> > +                 HartMaskBase
> > +                 );
> > +  return TranslateError (Ret.Error);
> > +}
> > +
> > +/**
> > +  Instructs remote harts to execute a FENCE.I instruction.
> > +
> > +  @param[in]  HartMask             Scalar bit-vector containing hart ids
> > +  @param[in]  HartMaskBase         The starting hartid from which the bit-
> vector
> > +                                   must be computed. If set to -1, HartMask is
> > +                                   ignored and all harts are considered.
> > +  @retval EFI_SUCCESS              IPI was sent to all the targeted harts.
> > +  @retval EFI_INVALID_PARAMETER    Either hart_mask_base or any of
> the hartid
> > +                                   from hart_mask is not valid i.e. either the
> > +                                   hartid is not enabled by the platform or is
> > +                                   not available to the supervisor.
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +SbiRemoteFenceI (
> > +  IN  UINTN                         *HartMask,
> > +  IN  UINTN                          HartMaskBase
> > +  )
> > +{
> > +  SbiRet Ret = SbiCall (
> > +                 SBI_EXT_RFENCE,
> > +                 SBI_EXT_RFENCE_REMOTE_FENCE_I,
> > +                 2,
> > +                 (UINTN)HartMask,
> > +                 HartMaskBase
> > +                 );
> > +  return TranslateError (Ret.Error);
> > +}
> > +
> > +/**
> > +  Instructs the remote harts to execute one or more SFENCE.VMA
> instructions.
> > +
> > +  The SFENCE.VMA covers the range of virtual addresses between
> StartAaddr and Size.
> > +
> > +  The remote fence function acts as a full tlb flush if * StartAddr and size
> > +  are both 0 * size is equal to 2^XLEN-1
> > +
> > +  @param[in]  HartMask             Scalar bit-vector containing hart ids
> > +  @param[in]  HartMaskBase         The starting hartid from which the bit-
> vector
> > +                                   must be computed. If set to -1, HartMask is
> > +                                   ignored and all harts are considered.
> > +  @param[in]  StartAddr            The first address of the affected range.
> > +  @param[in]  Size                 How many addresses are affected.
> > +  @retval EFI_SUCCESS              IPI was sent to all the targeted harts.
> > +  @retval EFI_LOAD_ERROR           StartAddr or Size is not valid.
> > +  @retval EFI_INVALID_PARAMETER    Either hart_mask_base or any of
> the hartid
> > +                                   from hart_mask is not valid i.e. either the
> > +                                   hartid is not enabled by the platform or is
> > +                                   not available to the supervisor.
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +SbiRemoteSfenceVma (
> > +  IN  UINTN                         *HartMask,
> > +  IN  UINTN                          HartMaskBase,
> > +  IN  UINTN                          StartAddr,
> > +  IN  UINTN                          Size
> > +  )
> > +{
> > +  SbiRet Ret = SbiCall (
> > +                 SBI_EXT_RFENCE,
> > +                 SBI_EXT_RFENCE_REMOTE_SFENCE_VMA,
> > +                 4,
> > +                 (UINTN)HartMask,
> > +                 HartMaskBase,
> > +                 StartAddr,
> > +                 Size
> > +                 );
> > +  return TranslateError (Ret.Error);
> > +}
> > +
> > +/**
> > +  Instructs the remote harts to execute one or more SFENCE.VMA
> instructions.
> > +
> > +  The SFENCE.VMA covers the range of virtual addresses between
> StartAaddr and Size.
> > +  Covers only the given ASID.
> > +
> > +  The remote fence function acts as a full tlb flush if * StartAddr and size
> > +  are both 0 * size is equal to 2^XLEN-1
> > +
> > +  @param[in]  HartMask             Scalar bit-vector containing hart ids
> > +  @param[in]  HartMaskBase         The starting hartid from which the bit-
> vector
> > +                                   must be computed. If set to -1, HartMask is
> > +                                   ignored and all harts are considered.
> > +  @param[in]  StartAddr            The first address of the affected range.
> > +  @param[in]  Size                 How many addresses are affected.
> > +  @retval EFI_SUCCESS              IPI was sent to all the targeted harts.
> > +  @retval EFI_LOAD_ERROR           StartAddr or Size is not valid.
> > +  @retval EFI_INVALID_PARAMETER    Either hart_mask_base or any of
> the hartid
> > +                                   from hart_mask is not valid i.e. either the
> > +                                   hartid is not enabled by the platform or is
> > +                                   not available to the supervisor.
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +SbiRemoteSfenceVmaAsid (
> > +  IN  UINTN                         *HartMask,
> > +  IN  UINTN                          HartMaskBase,
> > +  IN  UINTN                          StartAddr,
> > +  IN  UINTN                          Size,
> > +  IN  UINTN                          Asid
> > +  )
> > +{
> > +  SbiRet Ret = SbiCall (
> > +                 SBI_EXT_RFENCE,
> > +                 SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID,
> > +                 5,
> > +                 (UINTN)HartMask,
> > +                 HartMaskBase,
> > +                 StartAddr,
> > +                 Size,
> > +                 Asid
> > +                 );
> > +  return TranslateError (Ret.Error);
> > +}
> > +
> > +/**
> > +  Instructs the remote harts to execute one or more SFENCE.GVMA
> instructions.
> > +
> > +  The SFENCE.GVMA covers the range of virtual addresses between
> StartAaddr and Size.
> > +  Covers only the given VMID.
> > +  This function call is only valid for harts implementing the hypervisor
> extension.
> > +
> > +  The remote fence function acts as a full tlb flush if * StartAddr and size
> > +  are both 0 * size is equal to 2^XLEN-1
> > +
> > +  @param[in]  HartMask             Scalar bit-vector containing hart ids
> > +  @param[in]  HartMaskBase         The starting hartid from which the bit-
> vector
> > +                                   must be computed. If set to -1, HartMask is
> > +                                   ignored and all harts are considered.
> > +  @param[in]  StartAddr            The first address of the affected range.
> > +  @param[in]  Size                 How many addresses are affected.
> > +  @retval EFI_SUCCESS              IPI was sent to all the targeted harts.
> > +  @retval EFI_LOAD_ERROR           StartAddr or Size is not valid.
> > +  @retval EFI_UNSUPPORTED          SBI does not implement this function or
> one
> > +                                   of the target harts does not support the
> > +                                   hypervisor extension.
> > +  @retval EFI_INVALID_PARAMETER    Either hart_mask_base or any of
> the hartid
> > +                                   from hart_mask is not valid i.e. either the
> > +                                   hartid is not enabled by the platform or is
> > +                                   not available to the supervisor.
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +SbiRemoteHFenceGvmaVmid (
> > +  IN  UINTN                         *HartMask,
> > +  IN  UINTN                          HartMaskBase,
> > +  IN  UINTN                          StartAddr,
> > +  IN  UINTN                          Size,
> > +  IN  UINTN                          Vmid
> > +  )
> > +{
> > +  SbiRet Ret = SbiCall (
> > +                 SBI_EXT_RFENCE,
> > +                 SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA,
> > +                 5,
> > +                 (UINTN)HartMask,
> > +                 HartMaskBase,
> > +                 StartAddr,
> > +                 Size,
> > +                 Vmid
> > +                 );
> > +  return TranslateError (Ret.Error);
> > +}
> > +
> > +/**
> > +  Instructs the remote harts to execute one or more SFENCE.GVMA
> instructions.
> > +
> > +  The SFENCE.GVMA covers the range of virtual addresses between
> StartAaddr and Size.
> > +  This function call is only valid for harts implementing the hypervisor
> extension.
> > +
> > +  The remote fence function acts as a full tlb flush if * StartAddr and size
> > +  are both 0 * size is equal to 2^XLEN-1
> > +
> > +  @param[in]  HartMask             Scalar bit-vector containing hart ids
> > +  @param[in]  HartMaskBase         The starting hartid from which the bit-
> vector
> > +                                   must be computed. If set to -1, HartMask is
> > +                                   ignored and all harts are considered.
> > +  @param[in]  StartAddr            The first address of the affected range.
> > +  @param[in]  Size                 How many addresses are affected.
> > +  @retval EFI_SUCCESS              IPI was sent to all the targeted harts.
> > +  @retval EFI_LOAD_ERROR           StartAddr or Size is not valid.
> > +  @retval EFI_UNSUPPORTED          SBI does not implement this function or
> one
> > +                                   of the target harts does not support the
> > +                                   hypervisor extension.
> > +  @retval EFI_INVALID_PARAMETER    Either hart_mask_base or any of
> the hartid
> > +                                   from hart_mask is not valid i.e. either the
> > +                                   hartid is not enabled by the platform or is
> > +                                   not available to the supervisor.
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +SbiRemoteHFenceGvma (
> > +  IN  UINTN                         *HartMask,
> > +  IN  UINTN                          HartMaskBase,
> > +  IN  UINTN                          StartAddr,
> > +  IN  UINTN                          Size
> > +  )
> > +{
> > +  SbiRet Ret = SbiCall (
> > +                 SBI_EXT_RFENCE,
> > +                 SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA_VMID,
> > +                 4,
> > +                 (UINTN)HartMask,
> > +                 HartMaskBase,
> > +                 StartAddr,
> > +                 Size
> > +                 );
> > +  return TranslateError (Ret.Error);
> > +}
> > +
> > +/**
> > +  Instructs the remote harts to execute one or more SFENCE.VVMA
> instructions.
> > +
> > +  The SFENCE.GVMA covers the range of virtual addresses between
> StartAaddr and Size.
> > +  Covers only the given ASID.
> > +  This function call is only valid for harts implementing the hypervisor
> extension.
> > +
> > +  The remote fence function acts as a full tlb flush if * StartAddr and size
> > +  are both 0 * size is equal to 2^XLEN-1
> > +
> > +  @param[in]  HartMask             Scalar bit-vector containing hart ids
> > +  @param[in]  HartMaskBase         The starting hartid from which the bit-
> vector
> > +                                   must be computed. If set to -1, HartMask is
> > +                                   ignored and all harts are considered.
> > +  @param[in]  StartAddr            The first address of the affected range.
> > +  @param[in]  Size                 How many addresses are affected.
> > +  @retval EFI_SUCCESS              IPI was sent to all the targeted harts.
> > +  @retval EFI_LOAD_ERROR           StartAddr or Size is not valid.
> > +  @retval EFI_UNSUPPORTED          SBI does not implement this function or
> one
> > +                                   of the target harts does not support the
> > +                                   hypervisor extension.
> > +  @retval EFI_INVALID_PARAMETER    Either hart_mask_base or any of
> the hartid
> > +                                   from hart_mask is not valid i.e. either the
> > +                                   hartid is not enabled by the platform or is
> > +                                   not available to the supervisor.
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +SbiRemoteHFenceVvmaAsid (
> > +  IN  UINTN                         *HartMask,
> > +  IN  UINTN                          HartMaskBase,
> > +  IN  UINTN                          StartAddr,
> > +  IN  UINTN                          Size,
> > +  IN  UINTN                          Asid
> > +  )
> > +{
> > +  SbiRet Ret = SbiCall (
> > +                 SBI_EXT_RFENCE,
> > +                 SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA,
> > +                 5,
> > +                 (UINTN)HartMask,
> > +                 HartMaskBase,
> > +                 StartAddr,
> > +                 Size,
> > +                 Asid
> > +                 );
> > +  return TranslateError (Ret.Error);
> > +}
> > +
> > +/**
> > +  Instructs the remote harts to execute one or more SFENCE.VVMA
> instructions.
> > +
> > +  The SFENCE.GVMA covers the range of virtual addresses between
> StartAaddr and Size.
> > +  This function call is only valid for harts implementing the hypervisor
> extension.
> > +
> > +  The remote fence function acts as a full tlb flush if * StartAddr and size
> > +  are both 0 * size is equal to 2^XLEN-1
> > +
> > +  @param[in]  HartMask             Scalar bit-vector containing hart ids
> > +  @param[in]  HartMaskBase         The starting hartid from which the bit-
> vector
> > +                                   must be computed. If set to -1, HartMask is
> > +                                   ignored and all harts are considered.
> > +  @param[in]  StartAddr            The first address of the affected range.
> > +  @param[in]  Size                 How many addresses are affected.
> > +  @retval EFI_SUCCESS              IPI was sent to all the targeted harts.
> > +  @retval EFI_LOAD_ERROR           StartAddr or Size is not valid.
> > +  @retval EFI_UNSUPPORTED          SBI does not implement this function or
> one
> > +                                   of the target harts does not support the
> > +                                   hypervisor extension.
> > +  @retval EFI_INVALID_PARAMETER    Either hart_mask_base or any of
> the hartid
> > +                                   from hart_mask is not valid i.e. either the
> > +                                   hartid is not enabled by the platform or is
> > +                                   not available to the supervisor.
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +SbiRemoteHFenceVvma (
> > +  IN  UINTN                         *HartMask,
> > +  IN  UINTN                          HartMaskBase,
> > +  IN  UINTN                          StartAddr,
> > +  IN  UINTN                          Size
> > +  )
> > +{
> > +  SbiRet Ret = SbiCall (
> > +                 SBI_EXT_RFENCE,
> > +                 SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA_ASID,
> > +                 4,
> > +                 (UINTN)HartMask,
> > +                 HartMaskBase,
> > +                 StartAddr,
> > +                 Size
> > +                 );
> > +  return TranslateError (Ret.Error);
> > +}
> > +
> > +//
> > +// SBI interface function for the vendor extension
> > +//
> > +
> > +/**
> > +  Call a function in a vendor defined SBI extension
> > +
> > +  ASSERT() if the ExtensionId is not in the designated SBI Vendor Extension
> > +  Space or NumArgs exceeds SBI_CALL_MAX_ARGS.
> > +
> > +  @param[in]  ExtensionId          The SBI vendor extension ID.
> > +  @param[in]  FunctionId           The function ID to call in this extension.
> > +  @param[in]  NumArgs              How many arguments are passed.
> > +  @param[in]  ...                  Actual Arguments to the function.
> > +  @retval EFI_SUCCESS if the SBI function was called and it was successful
> > +  @retval others if the called SBI function returns an error
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +SbiVendorCall (
> > +  IN  UINTN                          ExtensionId,
> > +  IN  UINTN                          FunctionId,
> > +  IN  UINTN                          NumArgs,
> > +  ...
> > +  )
> > +{
> > +    SbiRet Ret;
> > +    VA_LIST Args;
> > +    VA_START (Args, NumArgs);
> > +
> > +    ASSERT (ExtensionId >= SBI_EXT_VENDOR_START && ExtensionId <=
> SBI_EXT_VENDOR_END);
> > +    ASSERT (NumArgs <= SBI_CALL_MAX_ARGS);
> > +
> > +    switch (NumArgs) {
> > +      case 0:
> > +        Ret = SbiCall (ExtensionId, FunctionId, NumArgs);
> > +        break;
> > +      case 1:
> > +        Ret = SbiCall (ExtensionId, FunctionId, NumArgs, VA_ARG (Args,
> UINTN));
> > +        break;
> > +      case 2:
> > +        Ret = SbiCall (ExtensionId, FunctionId, NumArgs, VA_ARG (Args,
> UINTN),
> > +                       VA_ARG (Args, UINTN));
> > +        break;
> > +      case 3:
> > +        Ret = SbiCall (ExtensionId, FunctionId, NumArgs, VA_ARG (Args,
> UINTN),
> > +                       VA_ARG (Args, UINTN), VA_ARG (Args, UINTN));
> > +        break;
> > +      case 4:
> > +        Ret = SbiCall (ExtensionId, FunctionId, NumArgs, VA_ARG (Args,
> UINTN),
> > +                       VA_ARG (Args, UINTN), VA_ARG (Args, UINTN),
> > +                       VA_ARG (Args, UINTN));
> > +        break;
> > +      case 5:
> > +        Ret = SbiCall (ExtensionId, FunctionId, NumArgs, VA_ARG (Args,
> UINTN),
> > +                       VA_ARG (Args, UINTN), VA_ARG (Args, UINTN),
> > +                       VA_ARG (Args, UINTN), VA_ARG (Args, UINTN));
> > +        break;
> > +      case 6:
> > +        Ret = SbiCall (ExtensionId, FunctionId, NumArgs, VA_ARG (Args,
> UINTN),
> > +                       VA_ARG (Args, UINTN), VA_ARG (Args, UINTN),
> > +                       VA_ARG (Args, UINTN), VA_ARG (Args, UINTN),
> > +                       VA_ARG (Args, UINTN));
> > +        break;
> > +      default:
> > +        // Too many args. In theory SBI can handle more arguments when
> they are
> > +        // passed on the stack but no SBI extension uses this, therefore it's
> > +        // not yet implemented here.
> > +        return EFI_INVALID_PARAMETER;
> > +     }
> > +
> > +    VA_END(Args);
> > +    return TranslateError (Ret.Error);
> > +}
> > +
> > +//
> > +// SBI Firmware extension
> > +//
> > +
> > +/**
> > +  Get scratch space of the current hart.
> > +
> > +  Please consider using the wrapper SbiGetFirmwareContext if you only
> need to
> > +  access the firmware context.
> > +
> > +  @param[out] ScratchSpace         The scratch space pointer.
> > +  @retval EFI_SUCCESS              The operation succeeds.
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +SbiGetMscratch (
> > +  OUT SBI_SCRATCH                    **ScratchSpace
> > +  )
> > +{
> > +  SbiRet Ret = SbiCall (SBI_EDK2_FW_EXT, SBI_EXT_FW_MSCRATCH_FUNC,
> 0);
> > +
> > +  if (!Ret.Error) {
> > +    *ScratchSpace = (SBI_SCRATCH *)Ret.Value;
> > +  }
> > +
> > +  return EFI_SUCCESS;
> > +}
> > +
> > +/**
> > +  Get scratch space of the given hart id.
> > +
> > +  @param[in]  HartId               The hart id.
> > +  @param[out] ScratchSpace         The scratch space pointer.
> > +  @retval EFI_SUCCESS              The operation succeeds.
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +SbiGetMscratchHartid (
> > +  IN  UINTN                            HartId,
> > +  OUT SBI_SCRATCH                    **ScratchSpace
> > +  )
> > +{
> > +  SbiRet Ret = SbiCall (
> > +                 SBI_EDK2_FW_EXT,
> > +                 SBI_EXT_FW_MSCRATCH_HARTID_FUNC,
> > +                 1,
> > +                 HartId
> > +                 );
> > +
> > +  if (!Ret.Error) {
> > +    *ScratchSpace = (SBI_SCRATCH *)Ret.Value;
> > +  }
> > +
> > +  return EFI_SUCCESS;
> > +}
> > +
> > +/**
> > +  Get firmware context of the calling hart.
> > +
> > +  @param[out] FirmwareContext      The firmware context pointer.
> > +  @retval EFI_SUCCESS              The operation succeeds.
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +SbiGetFirmwareContext (
> > +  OUT EFI_RISCV_OPENSBI_FIRMWARE_CONTEXT **FirmwareContext
> > +  )
> > +{
> > +  SBI_SCRATCH  *ScratchSpace;
> > +  SBI_PLATFORM *SbiPlatform;
> > +  SbiRet Ret = SbiCall (SBI_EDK2_FW_EXT, SBI_EXT_FW_MSCRATCH_FUNC,
> 0);
> > +
> > +  if (!Ret.Error) {
> > +    ScratchSpace = (SBI_SCRATCH *)Ret.Value;
> > +    SbiPlatform = (SBI_PLATFORM *)sbi_platform_ptr(ScratchSpace);
> > +    *FirmwareContext = (EFI_RISCV_OPENSBI_FIRMWARE_CONTEXT
> *)SbiPlatform->firmware_context;
> > +  }
> > +
> > +  return EFI_SUCCESS;
> > +}
> > +
> > +/**
> > +  Set firmware context of the calling hart.
> > +
> > +  @param[in] FirmwareContext       The firmware context pointer.
> > +  @retval EFI_SUCCESS              The operation succeeds.
> > +**/
> > +EFI_STATUS
> > +EFIAPI
> > +SbiSetFirmwareContext (
> > +  IN EFI_RISCV_OPENSBI_FIRMWARE_CONTEXT *FirmwareContext
> > +  )
> > +{
> > +  SBI_SCRATCH  *ScratchSpace;
> > +  SBI_PLATFORM *SbiPlatform;
> > +  SbiRet Ret = SbiCall (SBI_EDK2_FW_EXT, SBI_EXT_FW_MSCRATCH_FUNC,
> 0);
> > +
> > +  if (!Ret.Error) {
> > +    ScratchSpace = (SBI_SCRATCH *)Ret.Value;
> > +    SbiPlatform = (SBI_PLATFORM *)sbi_platform_ptr (ScratchSpace);
> > +    SbiPlatform->firmware_context = (UINTN)FirmwareContext;
> > +  }
> > +
> > +  return EFI_SUCCESS;
> > +}
> > --
> > 2.26.1
> >
> >
> > 
> >

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2020-06-23  2:09 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-06-02 16:51 [PATCH v4 0/1] New RISC-V Patches Daniel Schaefer
2020-06-02 16:51 ` [PATCH v4 1/1] ProcessorPkg/Library: Add RiscVEdk2SbiLib Daniel Schaefer
2020-06-02 22:00   ` [edk2-devel] " Michael D Kinney
2020-06-03  1:24     ` Abner Chang
     [not found]     ` <1614E4344379EB27.21938@groups.io>
2020-06-03  1:33       ` Abner Chang
2020-06-18 16:49   ` Leif Lindholm
2020-06-23  2:08     ` Abner Chang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox