public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH v2 0/3] New RISC-V Patches
@ 2020-05-15 13:39 Daniel Schaefer
  2020-05-15 13:39 ` [PATCH v2 1/3] ProcessorPkg/RiscVOpensbLib: Add opensbi submodule Daniel Schaefer
                   ` (3 more replies)
  0 siblings, 4 replies; 19+ messages in thread
From: Daniel Schaefer @ 2020-05-15 13:39 UTC (permalink / raw)
  To: devel; +Cc: Abner Chang, Gilbert Chen, Michael D Kinney, Leif Lindholm

In this updated version I addressed Leif's comments and made the following
changes:

- Refactor sbi_call* to SbiCall* (EDKII style)
- Use OpenSBI constants if possible
- Include Base.h in OpensbiTypes.h
- Only use __builtin_expect with Clang and GCC (not MSVC)

I'm sorry, I hadn't explained the new branches properly.
Previously we had all code going to EDK2 via the RISC-V-V2 branch.

Now we're only making the least amount of necessary changes in edk2 and
everything else in edk2-platforms.
Those changes to edk2 can be grouped into different categories:

- Patches for RISC-V EDK2 CI enablement
- Patches for edk2 modules other than RISC-V ones, to allow building them with the RISC-V toolchain
- Other RISC-V enablement like PE/COFF relocation

Those have all been reviewed and merged to edk2 master.

Previously we had two packages just for RISC-V on our edk2 branch:
  RiscVPkg and RiscVPlatformPkg
They are now under
  Platform/RISC-V/PlatformPkg and Silicon/RISC-V/ProcessorPkg
in edk2-platforms.
You, Leif, have previously reviewed those. In addition to this old code, which
was moved, we need some more patches to allow running PEI in S-Mode and
building in edk2-platforms. That's what this patch series is about.

In the previous version of this patchseries I forgot to attach the biggest new
commit, which adds RiscVEdk2SbiLib. It wraps the ecall interface for calling
SBI in a C API and lets PEI and DXE call SBI interfaces. Because we need more
M-Mode capabilities in PEI and DXE than SBI gives us, we register another SBI
extension, that gives us access to the mscratch register.

I hope now it makes more sense.

- Daniel

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

Abner Chang (1):
  ProcessorPkg/Library: Add RiscVOpensbiLib

Daniel Schaefer (2):
  ProcessorPkg/RiscVOpensbLib: Add opensbi submodule
  ProcessorPkg/Library: Add RiscVEdk2SbiLib

 Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.inf |  28 +
 Silicon/RISC-V/ProcessorPkg/Library/RiscVOpensbiLib/RiscVOpensbiLib.inf |  60 ++
 Silicon/RISC-V/ProcessorPkg/Include/IndustryStandard/RiscVOpensbi.h     |  72 ++
 Silicon/RISC-V/ProcessorPkg/Include/Library/RiscVEdk2SbiLib.h           | 631 ++++++++++++++++
 Silicon/RISC-V/ProcessorPkg/Include/OpensbiTypes.h                      |  73 ++
 Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.c   | 789 ++++++++++++++++++++
 .gitmodules                                                             |   3 +
 Readme.md                                                               |  36 +
 Silicon/RISC-V/ProcessorPkg/Library/RiscVOpensbiLib/opensbi             |   1 +
 9 files changed, 1693 insertions(+)
 create mode 100644 Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.inf
 create mode 100644 Silicon/RISC-V/ProcessorPkg/Library/RiscVOpensbiLib/RiscVOpensbiLib.inf
 create mode 100644 Silicon/RISC-V/ProcessorPkg/Include/IndustryStandard/RiscVOpensbi.h
 create mode 100644 Silicon/RISC-V/ProcessorPkg/Include/Library/RiscVEdk2SbiLib.h
 create mode 100644 Silicon/RISC-V/ProcessorPkg/Include/OpensbiTypes.h
 create mode 100644 Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.c
 create mode 100644 .gitmodules
 create mode 160000 Silicon/RISC-V/ProcessorPkg/Library/RiscVOpensbiLib/opensbi

-- 
2.26.1


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

* [PATCH v2 1/3] ProcessorPkg/RiscVOpensbLib: Add opensbi submodule
  2020-05-15 13:39 [PATCH v2 0/3] New RISC-V Patches Daniel Schaefer
@ 2020-05-15 13:39 ` Daniel Schaefer
  2020-05-20 11:51   ` Leif Lindholm
  2020-05-15 13:39 ` [PATCH v2 2/3] ProcessorPkg/Library: Add RiscVOpensbiLib Daniel Schaefer
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 19+ messages in thread
From: Daniel Schaefer @ 2020-05-15 13:39 UTC (permalink / raw)
  To: devel; +Cc: Gilbert Chen, Abner Chang, Michael D Kinney, Leif Lindholm

Add submodule opensbi under
Silicon/RISC-V/ProcessorPkg/Library/RiscVOpensbLlib.
The current supported opensbi version for RISC-V edk2 port is tags/v0.6.

Signed-off-by: Daniel Schaefer <daniel.schaefer@hpe.com>
Co-authored-by: Gilbert Chen <gilbert.chen@hpe.com>
Co-authored-by: Abner Chang <abner.chang@hpe.com>

Cc: Abner Chang <abner.chang@hpe.com>
Cc: Gilbert Chen <gilbert.chen@hpe.com>
Cc: Michael D Kinney <michael.k.kinney@intel.com>
Cc: Leif Lindholm <leif@nuviainc.com>
---
 .gitmodules                                                 |  3 ++
 Readme.md                                                   | 36 ++++++++++++++++++++
 Silicon/RISC-V/ProcessorPkg/Library/RiscVOpensbiLib/opensbi |  1 +
 3 files changed, 40 insertions(+)

diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 000000000000..88aafaf15820
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "Silicon/RISC-V/ProcessorPkg/Library/RiscVOpensbiLib/opensbi"]
+  path = Silicon/RISC-V/ProcessorPkg/Library/RiscVOpensbiLib/opensbi
+  url = https://github.com/riscv/opensbi
diff --git a/Readme.md b/Readme.md
index 8f9522659d7b..8f7317e6b029 100644
--- a/Readme.md
+++ b/Readme.md
@@ -10,6 +10,10 @@ The majority of the content in the EDK II open source project uses a
 [BSD-2-Clause Plus Patent License](License.txt).  Additional details on EDK II
 open source project code contributions can be found in the edk2 repository
 [Readme.md](https://github.com/tianocore/edk2/blob/master/Readme.md).
+The EDK II Platforms open source project contains the following components that
+are covered by additional licenses:
+
+- [`Silicon/RISC-V/ProcessorPkg/Library/RiscVOpensbiLib/opensbi`](https://github.com/riscv/opensbi/blob/master/COPYING.BSD)
 
 # INDEX
 * [Overview](#overview)
@@ -260,3 +264,35 @@ For more information, see the
 # Maintainers
 
 See [Maintainers.txt](Maintainers.txt).
+
+# Submodules
+
+Submodule in EDK II Platforms is allowed but submodule chain should be avoided
+as possible as we can. Currently EDK II Platforms contains the following
+submodules
+
+- Silicon/RISC-V/ProcessorPkg/Library/RiscVOpensbiLib/opensbi
+
+To get a full, buildable EDK II repository, use following steps of git command
+
+```bash
+  git clone https://github.com/tianocore/edk2-platforms.git
+  cd edk2-platforms
+  git submodule update --init
+  cd ..
+```
+
+If there's update for submodules, use following git commands to get the latest
+submodules code.
+
+```bash
+  cd edk2-platforms
+  git pull
+  git submodule update
+```
+
+Note: When cloning submodule repos, '--recursive' option is not recommended.
+EDK II Platforms itself will not use any code/feature from submodules in above
+submodules. So using '--recursive' adds a dependency on being able to reach
+servers we do not actually want any code from, as well as needlessly
+downloading code we will not use.
diff --git a/Silicon/RISC-V/ProcessorPkg/Library/RiscVOpensbiLib/opensbi b/Silicon/RISC-V/ProcessorPkg/Library/RiscVOpensbiLib/opensbi
new file mode 160000
index 000000000000..ac5e821d50be
--- /dev/null
+++ b/Silicon/RISC-V/ProcessorPkg/Library/RiscVOpensbiLib/opensbi
@@ -0,0 +1 @@
+Subproject commit ac5e821d50be631f26274765a59bc1b444ffd862
-- 
2.26.1


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

* [PATCH v2 2/3] ProcessorPkg/Library: Add RiscVOpensbiLib
  2020-05-15 13:39 [PATCH v2 0/3] New RISC-V Patches Daniel Schaefer
  2020-05-15 13:39 ` [PATCH v2 1/3] ProcessorPkg/RiscVOpensbLib: Add opensbi submodule Daniel Schaefer
@ 2020-05-15 13:39 ` Daniel Schaefer
  2020-05-20 12:00   ` Leif Lindholm
  2020-05-15 13:39 ` [PATCH v2 3/3] ProcessorPkg/Library: Add RiscVEdk2SbiLib Daniel Schaefer
  2020-05-20 11:43 ` [edk2-devel] [PATCH v2 0/3] New RISC-V Patches Leif Lindholm
  3 siblings, 1 reply; 19+ messages in thread
From: Daniel Schaefer @ 2020-05-15 13:39 UTC (permalink / raw)
  To: devel
  Cc: Gilbert Chen, Leif Lindholm, Abner Chang, Michael D Kinney,
	Leif Lindholm

From: Abner Chang <abner.chang@hpe.com>

EDK2 RISC-V OpenSBI library which pull in external source files under
RISC-V/ProcessorPkg/Library/RiscVOpensbiLib/opensbi to the build process.

Signed-off-by: Abner Chang <abner.chang@hpe.com>
Co-authored-by: Daniel Schaefer <daniel.schaefer@hpe.com>
Co-authored-by: Gilbert Chen <gilbert.chen@hpe.com>
Reviewed-by: Leif Lindholm <leif.lindholm@linaro.org>

Cc: Abner Chang <abner.chang@hpe.com>
Cc: Gilbert Chen <gilbert.chen@hpe.com>
Cc: Michael D Kinney <michael.k.kinney@intel.com>
Cc: Leif Lindholm <leif@nuviainc.com>
---
 Silicon/RISC-V/ProcessorPkg/Library/RiscVOpensbiLib/RiscVOpensbiLib.inf | 60 +++++++++++++++
 Silicon/RISC-V/ProcessorPkg/Include/IndustryStandard/RiscVOpensbi.h     | 79 ++++++++++++++++++++
 Silicon/RISC-V/ProcessorPkg/Include/OpensbiTypes.h                      | 73 ++++++++++++++++++
 3 files changed, 212 insertions(+)

diff --git a/Silicon/RISC-V/ProcessorPkg/Library/RiscVOpensbiLib/RiscVOpensbiLib.inf b/Silicon/RISC-V/ProcessorPkg/Library/RiscVOpensbiLib/RiscVOpensbiLib.inf
new file mode 100644
index 000000000000..59dbd67d8e03
--- /dev/null
+++ b/Silicon/RISC-V/ProcessorPkg/Library/RiscVOpensbiLib/RiscVOpensbiLib.inf
@@ -0,0 +1,60 @@
+## @file
+# RISC-V Opensbi Library Instance.
+#
+#  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      = RiscVOpensbiLib
+  FILE_GUID      = 6EF0C812-66F6-11E9-93CE-3F5D5F0DF0A7
+  MODULE_TYPE    = BASE
+  VERSION_STRING = 1.0
+  LIBRARY_CLASS  = RiscVOpensbiLib
+
+[Sources]
+  opensbi/lib/sbi/riscv_asm.c
+  opensbi/lib/sbi/riscv_atomic.c
+  opensbi/lib/sbi/riscv_hardfp.S
+  opensbi/lib/sbi/riscv_locks.c
+  opensbi/lib/sbi/sbi_console.c
+  opensbi/lib/sbi/sbi_ecall.c
+  opensbi/lib/sbi/sbi_ecall_vendor.c
+  opensbi/lib/sbi/sbi_ecall_replace.c
+  opensbi/lib/sbi/sbi_ecall_legacy.c
+  opensbi/lib/sbi/sbi_ecall_base.c
+  opensbi/lib/sbi/sbi_emulate_csr.c
+  opensbi/lib/sbi/sbi_fifo.c
+  opensbi/lib/sbi/sbi_hart.c
+  opensbi/lib/sbi/sbi_hfence.S
+  opensbi/lib/sbi/sbi_illegal_insn.c
+  opensbi/lib/sbi/sbi_init.c
+  opensbi/lib/sbi/sbi_ipi.c
+  opensbi/lib/sbi/sbi_misaligned_ldst.c
+  opensbi/lib/sbi/sbi_scratch.c
+  opensbi/lib/sbi/sbi_string.c
+  opensbi/lib/sbi/sbi_system.c
+  opensbi/lib/sbi/sbi_timer.c
+  opensbi/lib/sbi/sbi_tlb.c
+  opensbi/lib/sbi/sbi_trap.c
+  opensbi/lib/sbi/sbi_unpriv.c
+  opensbi/lib/utils/sys/clint.c
+  opensbi/lib/utils/irqchip/plic.c
+  opensbi/lib/utils/serial/sifive-uart.c
+  opensbi/lib/utils/serial/uart8250.c
+
+[Packages]
+  EmbeddedPkg/EmbeddedPkg.dec   # For libfdt.
+  MdePkg/MdePkg.dec
+  Silicon/RISC-V/ProcessorPkg/RiscVProcessorPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  PcdLib
+  RiscVCpuLib
+
+
+
diff --git a/Silicon/RISC-V/ProcessorPkg/Include/IndustryStandard/RiscVOpensbi.h b/Silicon/RISC-V/ProcessorPkg/Include/IndustryStandard/RiscVOpensbi.h
new file mode 100644
index 000000000000..c5c0bd6d9b01
--- /dev/null
+++ b/Silicon/RISC-V/ProcessorPkg/Include/IndustryStandard/RiscVOpensbi.h
@@ -0,0 +1,79 @@
+/** @file
+  SBI inline function calls.
+
+  Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef EDK2_SBI_H_
+#define EDK2_SBI_H_
+
+#include <include/sbi/riscv_asm.h> // Reference to header file in opensbi
+#include <RiscVImpl.h>
+#include <sbi/sbi_types.h>  // Reference to header file wrapper
+
+#define SBI_SUCCESS                    0
+#define SBI_ERR_FAILED                -1
+#define SBI_ERR_NOT_SUPPORTED         -2
+#define SBI_ERR_INVALID_PARAM         -3
+#define SBI_ERR_DENIED                -4
+#define SBI_ERR_INVALID_ADDRESS       -5
+#define SBI_ERR_ALREADY_AVAILABLE     -6
+
+#define SBI_BASE_EXT                   0x10
+#define SBI_HSM_EXT                    0x48534D
+#define SBI_TIME_EXT                   0x54494D45
+#define SBI_IPI_EXT                    0x735049
+#define SBI_RFNC_EXT                   0x52464E43
+
+//
+// Below two definitions should be defined in OpenSBI.
+//
+#define SBI_EXT_FIRMWARE_CODE_BASE_START 0x0A000000
+#define SBI_EXT_FIRMWARE_CODE_BASE_END   0x0AFFFFFF
+
+#define SBI_GET_SPEC_VERSION_FUNC      0
+#define SBI_GET_IMPL_ID_FUNC           1
+#define SBI_GET_IMPL_VERSION_FUNC      2
+#define SBI_PROBE_EXTENSION_FUNC       3
+#define SBI_GET_MVENDORID_FUNC         4
+#define SBI_GET_MARCHID_FUNC           5
+#define SBI_GET_MIMPID_FUNC            6
+
+#define SBI_HART_START_FUNC            0
+#define SBI_HART_STOP_FUNC             1
+#define SBI_HART_GET_STATUS_FUNC       2
+
+#define RISC_V_MAX_HART_SUPPORTED 16
+
+typedef
+VOID
+(EFIAPI *RISCV_HART_SWITCH_MODE)(
+  IN  UINTN   FuncArg0,
+  IN  UINTN   FuncArg1,
+  IN  UINTN   NextAddr,
+  IN  UINTN   NextMode,
+  IN  BOOLEAN NextVirt
+  );
+
+//
+// Keep the structure member in 64-bit alignment.
+//
+typedef struct {
+    UINT64                 IsaExtensionSupported;  // The ISA extension this core supported.
+    RISCV_UINT128          MachineVendorId;        // Machine vendor ID
+    RISCV_UINT128          MachineArchId;          // Machine Architecture ID
+    RISCV_UINT128          MachineImplId;          // Machine Implementation ID
+    RISCV_HART_SWITCH_MODE HartSwitchMode;         // OpenSBI's function to switch the mode of a hart
+} EFI_RISCV_FIRMWARE_CONTEXT_HART_SPECIFIC;
+#define FIRMWARE_CONTEXT_HART_SPECIFIC_SIZE  (64 * 8) // This is the size of EFI_RISCV_FIRMWARE_CONTEXT_HART_SPECIFIC
+                                                      // structure. Referred by both C code and assembly code.
+
+typedef struct {
+  VOID            *PeiServiceTable;       // PEI Service table
+  EFI_RISCV_FIRMWARE_CONTEXT_HART_SPECIFIC  *HartSpecific[RISC_V_MAX_HART_SUPPORTED];
+} EFI_RISCV_OPENSBI_FIRMWARE_CONTEXT;
+
+#endif
diff --git a/Silicon/RISC-V/ProcessorPkg/Include/OpensbiTypes.h b/Silicon/RISC-V/ProcessorPkg/Include/OpensbiTypes.h
new file mode 100644
index 000000000000..5f3278e8461f
--- /dev/null
+++ b/Silicon/RISC-V/ProcessorPkg/Include/OpensbiTypes.h
@@ -0,0 +1,73 @@
+/** @file
+  RISC-V OpesbSBI header file reference.
+
+  Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#ifndef EDK2_SBI_TYPES_H_
+#define EDK2_SBI_TYPES_H_
+
+#include <Base.h>
+
+typedef INT8    s8;
+typedef UINT8   u8;
+typedef UINT8   uint8_t;
+
+typedef INT16   s16;
+typedef UINT16  u16;
+typedef INT16   int16_t;
+typedef UINT16  uint16_t;
+
+typedef INT32   s32;
+typedef UINT32  u32;
+typedef INT32   int32_t;
+typedef UINT32  uint32_t;
+
+typedef INT64   s64;
+typedef UINT64  u64;
+typedef INT64   int64_t;
+typedef UINT64  uint64_t;
+
+#define PRILX   "016lx"
+
+typedef BOOLEAN  bool;
+typedef unsigned long   ulong;
+typedef UINT64   uintptr_t;
+typedef UINT64   size_t;
+typedef INT64    ssize_t;
+typedef UINT64   virtual_addr_t;
+typedef UINT64   virtual_size_t;
+typedef UINT64   physical_addr_t;
+typedef UINT64   physical_size_t;
+
+#define __packed        __attribute__((packed))
+#define __noreturn      __attribute__((noreturn))
+
+#if defined(__GNUC__) || defined(__clang__)
+  #define likely(x) __builtin_expect((x), 1)
+  #define unlikely(x) __builtin_expect((x), 0)
+#else
+  #define likely(x) (x)
+  #define unlikely(x) (x)
+#endif
+
+#undef offsetof
+#ifdef __compiler_offsetof
+#define offsetof(TYPE, MEMBER) __compiler_offsetof(TYPE,MEMBER)
+#else
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+#endif
+
+#define container_of(ptr, type, member) ({            \
+  const typeof(((type *)0)->member) * __mptr = (ptr); \
+  (type *)((char *)__mptr - offsetof(type, member)); })
+
+#define CLAMP(a, lo, hi) MIN(MAX(a, lo), hi)
+#define ROUNDUP(a, b) ((((a)-1) / (b) + 1) * (b))
+#define ROUNDDOWN(a, b) ((a) / (b) * (b))
+
+/* clang-format on */
+
+#endif
-- 
2.26.1


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

* [PATCH v2 3/3] ProcessorPkg/Library: Add RiscVEdk2SbiLib
  2020-05-15 13:39 [PATCH v2 0/3] New RISC-V Patches Daniel Schaefer
  2020-05-15 13:39 ` [PATCH v2 1/3] ProcessorPkg/RiscVOpensbLib: Add opensbi submodule Daniel Schaefer
  2020-05-15 13:39 ` [PATCH v2 2/3] ProcessorPkg/Library: Add RiscVOpensbiLib Daniel Schaefer
@ 2020-05-15 13:39 ` Daniel Schaefer
  2020-05-20 18:27   ` Leif Lindholm
  2020-05-20 11:43 ` [edk2-devel] [PATCH v2 0/3] New RISC-V Patches Leif Lindholm
  3 siblings, 1 reply; 19+ messages in thread
From: Daniel Schaefer @ 2020-05-15 13:39 UTC (permalink / raw)
  To: devel; +Cc: Abner Chang, Gilbert Chen, Michael D Kinney, Leif Lindholm

Library provides interfaces to invoke SBI extensions.

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

Cc: Abner Chang <abner.chang@hpe.com>
Cc: Gilbert Chen <gilbert.chen@hpe.com>
Cc: Michael D Kinney <michael.k.kinney@intel.com>
Cc: Leif Lindholm <leif@nuviainc.com>
---
 Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.inf |  28 +
 Silicon/RISC-V/ProcessorPkg/Include/IndustryStandard/RiscVOpensbi.h     |  43 +-
 Silicon/RISC-V/ProcessorPkg/Include/Library/RiscVEdk2SbiLib.h           | 631 ++++++++++++++++
 Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.c   | 789 ++++++++++++++++++++
 4 files changed, 1466 insertions(+), 25 deletions(-)

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/IndustryStandard/RiscVOpensbi.h b/Silicon/RISC-V/ProcessorPkg/Include/IndustryStandard/RiscVOpensbi.h
index c5c0bd6d9b01..18a85e2238d2 100644
--- a/Silicon/RISC-V/ProcessorPkg/Include/IndustryStandard/RiscVOpensbi.h
+++ b/Silicon/RISC-V/ProcessorPkg/Include/IndustryStandard/RiscVOpensbi.h
@@ -10,42 +10,35 @@
 #ifndef EDK2_SBI_H_
 #define EDK2_SBI_H_
 
-#include <include/sbi/riscv_asm.h> // Reference to header file in opensbi
 #include <RiscVImpl.h>
+#include <sbi/riscv_asm.h> // Reference to header file in opensbi
+#include <sbi/sbi_ecall_interface.h>
+#include <sbi/sbi_error.h>
 #include <sbi/sbi_types.h>  // Reference to header file wrapper
 
-#define SBI_SUCCESS                    0
-#define SBI_ERR_FAILED                -1
-#define SBI_ERR_NOT_SUPPORTED         -2
-#define SBI_ERR_INVALID_PARAM         -3
-#define SBI_ERR_DENIED                -4
-#define SBI_ERR_INVALID_ADDRESS       -5
-#define SBI_ERR_ALREADY_AVAILABLE     -6
+// Translation from OpenSBI constants to SBI names
+#define SBI_SUCCESS               SBI_OK
+#define SBI_ERR_FAILED            SBI_EFAIL
+#define SBI_ERR_NOT_SUPPORTED     SBI_ENOTSUPP
+#define SBI_ERR_INVALID_PARAM     SBI_EINVAL
+#define SBI_ERR_DENIED            SBI_DENIED
+#define SBI_ERR_INVALID_ADDRESS   SBI_INVALID_ADDR
+#define SBI_ERR_ALREADY_AVAILABLE -6
 
-#define SBI_BASE_EXT                   0x10
-#define SBI_HSM_EXT                    0x48534D
-#define SBI_TIME_EXT                   0x54494D45
-#define SBI_IPI_EXT                    0x735049
-#define SBI_RFNC_EXT                   0x52464E43
+// Included in OpenSBI 0.7
+// Can be removed, once we upgrade
+#define SBI_EXT_HSM               0x48534D
+#define SBI_EXT_HSM_HART_START    0x0
+#define SBI_EXT_HSM_HART_STOP     0x1
+#define SBI_EXT_HSM_HART_GET_STATUS 0x2
 
 //
 // Below two definitions should be defined in OpenSBI.
+// Submitted to upstream, waiting for merge and release.
 //
 #define SBI_EXT_FIRMWARE_CODE_BASE_START 0x0A000000
 #define SBI_EXT_FIRMWARE_CODE_BASE_END   0x0AFFFFFF
 
-#define SBI_GET_SPEC_VERSION_FUNC      0
-#define SBI_GET_IMPL_ID_FUNC           1
-#define SBI_GET_IMPL_VERSION_FUNC      2
-#define SBI_PROBE_EXTENSION_FUNC       3
-#define SBI_GET_MVENDORID_FUNC         4
-#define SBI_GET_MARCHID_FUNC           5
-#define SBI_GET_MIMPID_FUNC            6
-
-#define SBI_HART_START_FUNC            0
-#define SBI_HART_STOP_FUNC             1
-#define SBI_HART_GET_STATUS_FUNC       2
-
 #define RISC_V_MAX_HART_SUPPORTED 16
 
 typedef
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..cf77814e3bbc
--- /dev/null
+++ b/Silicon/RISC-V/ProcessorPkg/Include/Library/RiscVEdk2SbiLib.h
@@ -0,0 +1,631 @@
+/** @file Defines the PPIs to let PEIMs call SBI
+
+Copyright (c) 2020, Hewlett Packard Development LP. All rights reserved.<BR>
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#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.
+//
+struct sbiret {
+  long error;   ///< SBI status code
+  long value;   ///< Value returned
+};
+
+#define SbiCall0(ext_id, func_id) \
+  SbiCall(ext_id, func_id, 0, 0, 0, 0, 0, 0)
+#define SbiCall1(ext_id, func_id, arg0) \
+  SbiCall(ext_id, func_id, arg0, 0, 0, 0, 0, 0)
+#define SbiCall2(ext_id, func_id, arg0, arg1) \
+  SbiCall(ext_id, func_id, arg0, arg1, 0, 0, 0, 0)
+#define SbiCall3(ext_id, func_id, arg0, arg1, arg2) \
+  SbiCall(ext_id, func_id, arg0, arg1, arg2, 0, 0, 0)
+#define SbiCall4(ext_id, func_id, arg0, arg1, arg2, arg3) \
+  SbiCall(ext_id, func_id, arg0, arg1, arg2, arg3, 0, 0)
+#define SbiCall5(ext_id, func_id, arg0, arg1, arg2, arg3, arg4) \
+  SbiCall(ext_id, func_id, arg0, arg1, arg2, arg3, arg4, 0)
+#define SbiCall6(ext_id, func_id, arg0, arg1, arg2, arg3, arg4, arg5) \
+  SbiCall(ext_id, func_id, arg0, arg1, arg2, arg3, arg4, arg5)
+
+/**
+  EDK2 SbiCall to invoke SBI extensions.
+
+  @param[in] ext_id   Sbi extension ID.
+  @param[in] func_id  Sbi functions ID.
+  @param[in] arg0     Arg0 to function.
+  @param[in] arg1     Arg1 to function.
+  @param[in] arg2     Arg2 to function.
+  @param[in] arg3     Arg3 to function.
+  @param[in] arg4     Arg4 to function.
+  @param[in] arg5     Arg5 to function.
+
+  @retval  Returns sbiret structure.
+
+**/
+inline
+EFIAPI
+struct sbiret SbiCall(UINTN ext_id, UINTN func_id, UINTN arg0, UINTN arg1,
+                           UINTN arg2, UINTN arg3, UINTN arg4, UINTN arg5)
+__attribute__((always_inline));
+
+/**
+  EDK2 SbiCall to invoke SBI extensions.
+
+  @param[in] ext_id   Sbi extension ID.
+  @param[in] func_id  Sbi functions ID.
+  @param[in] arg0     Arg0 to function.
+  @param[in] arg1     Arg1 to function.
+  @param[in] arg2     Arg2 to function.
+  @param[in] arg3     Arg3 to function.
+  @param[in] arg4     Arg4 to function.
+  @param[in] arg5     Arg5 to function.
+
+  @retval  Returns sbiret structure.
+
+**/
+inline
+EFIAPI
+struct sbiret SbiCall(UINTN ext_id, UINTN func_id, UINTN arg0, UINTN arg1,
+                           UINTN arg2, UINTN arg3, UINTN arg4, UINTN arg5) {
+    register uintptr_t a0 asm ("a0") = (uintptr_t)(arg0);
+    register uintptr_t a1 asm ("a1") = (uintptr_t)(arg1);
+    register uintptr_t a2 asm ("a2") = (uintptr_t)(arg2);
+    register uintptr_t a3 asm ("a3") = (uintptr_t)(arg3);
+    register uintptr_t a4 asm ("a4") = (uintptr_t)(arg4);
+    register uintptr_t a5 asm ("a5") = (uintptr_t)(arg5);
+    register uintptr_t a6 asm ("a6") = (uintptr_t)(func_id);
+    register uintptr_t a7 asm ("a7") = (uintptr_t)(ext_id);
+    asm volatile ("ecall" \
+         : "+r" (a0) \
+         : "r" (a1), "r" (a2), "r" (a3), "r" (a4), "r" (a5), "r" (a6), "r" (a7) \
+         : "memory"); \
+    struct sbiret ret = { a0, a1 };
+    return ret;
+}
+
+/**
+  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] MvendorId            The CPU's vendor ID.
+**/
+VOID
+EFIAPI
+SbiGetMvendorId (
+  OUT UINTN                       *MvendorId
+  );
+
+/**
+  Get the CPU's architecture ID
+
+  Reads the marchid CSR.
+
+  @param[out] MarchId              The CPU's architecture ID.
+**/
+VOID
+EFIAPI
+SbiGetMarchId (
+  OUT UINTN                       *MarchId
+  );
+
+/**
+  Get the CPU's implementation ID
+
+  Reads the mimpid CSR.
+
+  @param[out] MimpId               The CPU's implementation ID.
+**/
+VOID
+EFIAPI
+SbiGetMimpId (
+  OUT UINTN                       *Mimpid
+  );
+
+/**
+  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 StimeValue.
+
+  To clear the timer without scheduling a timer event, set StimeValue to a
+  practically infinite value or mask the timer interrupt by clearing sie.STIE.
+
+  @param[in]  StimeValue           The time offset to the next scheduled timer interrupt.
+**/
+VOID
+EFIAPI
+SbiSetTimer (
+  IN  UINT64                         StimeValue
+  );
+
+///
+/// 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 struct 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 struct 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..bbe006a78af8
--- /dev/null
+++ b/Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.c
@@ -0,0 +1,789 @@
+/** @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
+**/
+
+#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_platform.h>
+#include <sbi/sbi_init.h>
+
+/**
+  Translate SBI error code to EFI status.
+
+  @param[in] SbiError   SBI error code
+  @retval EFI_STATUS
+**/
+
+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 libraary 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
+  )
+{
+  struct sbiret ret = SbiCall0 (SBI_EXT_BASE, SBI_EXT_BASE_GET_SPEC_VERSION);
+
+  if (!ret.error) {
+    *SpecVersion = (UINTN) ret.value;
+  }
+
+  //return TranslateError(ret.error);
+}
+
+/**
+  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
+  )
+{
+  struct sbiret ret = SbiCall0 (SBI_EXT_BASE, SBI_EXT_BASE_GET_IMP_ID);
+  *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
+  )
+{
+  struct sbiret ret = SbiCall0 (SBI_EXT_BASE, SBI_EXT_BASE_GET_IMP_VERSION);
+  *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
+  )
+{
+  struct sbiret ret = SbiCall0 (SBI_EXT_BASE, SBI_EXT_BASE_PROBE_EXT);
+  *ProbeResult = (UINTN) ret.value;
+}
+
+/**
+  Get the CPU's vendor ID
+
+  Reads the mvendorid CSR.
+
+  @param[out] MvendorId            The CPU's vendor ID.
+**/
+VOID
+EFIAPI
+SbiGetMvendorId (
+  OUT UINTN                       *MvendorId
+  )
+{
+  struct sbiret ret = SbiCall0 (SBI_EXT_BASE, SBI_EXT_BASE_GET_MVENDORID);
+  *MvendorId = (UINTN) ret.value;
+}
+
+/**
+  Get the CPU's vendor ID
+
+  Reads the mvendorid CSR.
+
+  @param[out] MvendorId            The CPU's vendor ID.
+**/
+VOID
+EFIAPI
+SbiGetMarchId (
+  OUT UINTN                       *MarchId
+  )
+{
+  struct sbiret ret = SbiCall0 (SBI_EXT_BASE, SBI_EXT_BASE_GET_MARCHID);
+  *MarchId = (UINTN) ret.value;
+}
+
+/**
+  Get the CPU's architecture ID
+
+  Reads the marchid CSR.
+
+  @param[out] MarchId              The CPU's architecture ID.
+**/
+VOID
+EFIAPI
+SbiGetMimpId (
+  OUT UINTN                       *MimpId
+  )
+{
+  struct sbiret ret = SbiCall0 (SBI_EXT_BASE, SBI_EXT_BASE_GET_MIMPID);
+  *MimpId = (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
+  )
+{
+  struct sbiret ret = SbiCall3 (SBI_EXT_HSM,
+                                SBI_EXT_HSM_HART_START,
+                                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 (
+  )
+{
+  struct sbiret Ret = SbiCall0 (SBI_EXT_HSM, SBI_EXT_HSM_HART_STOP);
+  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
+  )
+{
+  struct sbiret ret = SbiCall1 (SBI_EXT_HSM, SBI_EXT_HSM_HART_GET_STATUS, HartId);
+
+  if (!ret.error) {
+    *HartStatus = (UINTN) ret.value;
+  }
+
+  return TranslateError(ret.error);
+}
+
+/**
+  Clear pending timer interrupt bit and set timer for next event after StimeValue.
+
+  To clear the timer without scheduling a timer event, set StimeValue to a
+  practically infinite value or mask the timer interrupt by clearing sie.STIE.
+
+  @param[in]  StimeValue           The time offset to the next scheduled timer interrupt.
+**/
+VOID
+EFIAPI
+SbiSetTimer (
+  IN  UINT64                         StimeValue
+  )
+{
+  SbiCall1 (SBI_EXT_TIME, SBI_EXT_TIME_SET_TIMER, StimeValue);
+}
+
+EFI_STATUS
+EFIAPI
+SbiSendIpi (
+  IN  UINTN                         *HartMask,
+  IN  UINTN                          HartMaskBase
+  )
+{
+  struct sbiret ret = SbiCall2 (SBI_EXT_IPI,
+                                SBI_EXT_IPI_SEND_IPI,
+                                (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
+  )
+{
+  struct sbiret ret = SbiCall2 (SBI_EXT_RFENCE,
+                                SBI_EXT_RFENCE_REMOTE_FENCE_I,
+                                (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
+  )
+{
+  struct sbiret ret = SbiCall4 (SBI_EXT_RFENCE,
+                                SBI_EXT_RFENCE_REMOTE_SFENCE_VMA,
+                                (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
+  )
+{
+  struct sbiret ret = SbiCall5 (SBI_EXT_RFENCE,
+                                SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID,
+                                (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
+  )
+{
+  struct sbiret ret = SbiCall5 (SBI_EXT_RFENCE,
+                                SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA,
+                                (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
+  )
+{
+  struct sbiret ret = SbiCall4 (SBI_EXT_RFENCE,
+                                SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA_VMID,
+                                (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
+  )
+{
+  struct sbiret ret = SbiCall5 (SBI_EXT_RFENCE,
+                                SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA,
+                                (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
+  )
+{
+  struct sbiret ret = SbiCall4 (SBI_EXT_RFENCE,
+                                SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA_ASID,
+                                (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.
+
+  @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,
+  ...
+  )
+{
+    struct sbiret ret;
+    VA_LIST Args;
+    VA_START(Args, NumArgs);
+
+    ASSERT (ExtensionId >= 0x09000000 && ExtensionId <= 0x09FFFFFF);
+
+    switch (NumArgs) {
+      case 0:
+        ret = SbiCall0 (ExtensionId, FunctionId);
+        break;
+      case 1:
+        ret = SbiCall1 (ExtensionId, FunctionId, VA_ARG(Args, UINTN));
+        break;
+      case 2:
+        ret = SbiCall2 (ExtensionId, FunctionId, VA_ARG(Args, UINTN), VA_ARG(Args, UINTN));
+        break;
+      case 3:
+        ret = SbiCall3 (ExtensionId, FunctionId, VA_ARG(Args, UINTN), VA_ARG(Args, UINTN), VA_ARG(Args, UINTN));
+        break;
+      case 4:
+        ret = SbiCall4 (ExtensionId, FunctionId, VA_ARG(Args, UINTN), VA_ARG(Args, UINTN), VA_ARG(Args, UINTN), VA_ARG(Args, UINTN));
+        break;
+      case 5:
+        ret = SbiCall5 (ExtensionId, FunctionId, VA_ARG(Args, UINTN), VA_ARG(Args, UINTN), VA_ARG(Args, UINTN), VA_ARG(Args, UINTN), VA_ARG(Args, UINTN));
+        break;
+      case 6:
+        ret = SbiCall6 (ExtensionId, FunctionId, 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 struct sbi_scratch             **ScratchSpace
+  )
+{
+  struct sbiret ret = SbiCall0 (SBI_EDK2_FW_EXT, SBI_EXT_FW_MSCRATCH_FUNC);
+
+  if (!ret.error) {
+    *ScratchSpace = (struct 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 struct sbi_scratch             **ScratchSpace
+  )
+{
+  struct sbiret ret = SbiCall1 (SBI_EDK2_FW_EXT,
+                                SBI_EXT_FW_MSCRATCH_HARTID_FUNC,
+                                HartId);
+
+  if (!ret.error) {
+    *ScratchSpace = (struct 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
+  )
+{
+  struct sbi_scratch *ScratchSpace;
+  struct sbi_platform *SbiPlatform;
+  struct sbiret ret = SbiCall0 (SBI_EDK2_FW_EXT, SBI_EXT_FW_MSCRATCH_FUNC);
+
+  if (!ret.error) {
+    ScratchSpace = (struct sbi_scratch *) ret.value;
+    SbiPlatform = (struct 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
+  )
+{
+  struct sbi_scratch *ScratchSpace;
+  struct sbi_platform *SbiPlatform;
+  struct sbiret ret = SbiCall0 (SBI_EDK2_FW_EXT, SBI_EXT_FW_MSCRATCH_FUNC);
+
+  if (!ret.error) {
+    ScratchSpace = (struct sbi_scratch *) ret.value;
+    SbiPlatform = (struct sbi_platform *) sbi_platform_ptr(ScratchSpace);
+    SbiPlatform->firmware_context = (long unsigned int) FirmwareContext;
+  }
+
+  return EFI_SUCCESS;
+}
-- 
2.26.1


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

* Re: [edk2-devel] [PATCH v2 0/3] New RISC-V Patches
  2020-05-15 13:39 [PATCH v2 0/3] New RISC-V Patches Daniel Schaefer
                   ` (2 preceding siblings ...)
  2020-05-15 13:39 ` [PATCH v2 3/3] ProcessorPkg/Library: Add RiscVEdk2SbiLib Daniel Schaefer
@ 2020-05-20 11:43 ` Leif Lindholm
  2020-05-20 16:03   ` [edk2-devel] [PATCH v2 0/3] New RISC-V Patches - Why in edk2-platforms Daniel Schaefer
  3 siblings, 1 reply; 19+ messages in thread
From: Leif Lindholm @ 2020-05-20 11:43 UTC (permalink / raw)
  To: devel, daniel.schaefer; +Cc: Abner Chang, Gilbert Chen, Michael D Kinney

On Fri, May 15, 2020 at 15:39:34 +0200, Daniel Schaefer wrote:
> In this updated version I addressed Leif's comments and made the following
> changes:
> 
> - Refactor sbi_call* to SbiCall* (EDKII style)
> - Use OpenSBI constants if possible
> - Include Base.h in OpensbiTypes.h
> - Only use __builtin_expect with Clang and GCC (not MSVC)
> 
> I'm sorry, I hadn't explained the new branches properly.
> Previously we had all code going to EDK2 via the RISC-V-V2 branch.
> 
> Now we're only making the least amount of necessary changes in edk2 and
> everything else in edk2-platforms.
> Those changes to edk2 can be grouped into different categories:
> 
> - Patches for RISC-V EDK2 CI enablement
> - Patches for edk2 modules other than RISC-V ones, to allow building them with the RISC-V toolchain
> - Other RISC-V enablement like PE/COFF relocation
> 
> Those have all been reviewed and merged to edk2 master.
> 
> Previously we had two packages just for RISC-V on our edk2 branch:
>   RiscVPkg and RiscVPlatformPkg
> They are now under
>   Platform/RISC-V/PlatformPkg and Silicon/RISC-V/ProcessorPkg
> in edk2-platforms.

Understood. I took my eye off the ball there for a while, but I'm a
bit confused as to why RiscVPkg isn't going into EDK2. That is very
counterintuitive. And clearly it will need revisiting if we are to add
first-class CI checks like those we do with OvmfPkg/ArmVirtPkg.

> You, Leif, have previously reviewed those. In addition to this old code, which
> was moved, we need some more patches to allow running PEI in S-Mode and
> building in edk2-platforms. That's what this patch series is about.

I *did* have some outstanding comments specifically with regards to
large amounts of code duplication between the SMBIOS implementation of
some closely related RISC-V platforms. That now needs to be revisited.

> In the previous version of this patchseries I forgot to attach the biggest new
> commit, which adds RiscVEdk2SbiLib. It wraps the ecall interface for calling
> SBI in a C API and lets PEI and DXE call SBI interfaces. Because we need more
> M-Mode capabilities in PEI and DXE than SBI gives us, we register another SBI
> extension, that gives us access to the mscratch register.

Without looking at it yet, it sounds like that may resolve the only
remaining major issue I had with RiscVPkg.

> I hope now it makes more sense.

It is more clear, as per above I am not sure it makes more sense :)
Thanks!

Best Regards,

Leif

> - Daniel
> 
> Cc: Abner Chang <abner.chang@hpe.com>
> Cc: Gilbert Chen <gilbert.chen@hpe.com>
> Cc: Michael D Kinney <michael.k.kinney@intel.com>
> Cc: Leif Lindholm <leif@nuviainc.com>
> 
> Abner Chang (1):
>   ProcessorPkg/Library: Add RiscVOpensbiLib
> 
> Daniel Schaefer (2):
>   ProcessorPkg/RiscVOpensbLib: Add opensbi submodule
>   ProcessorPkg/Library: Add RiscVEdk2SbiLib
> 
>  Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.inf |  28 +
>  Silicon/RISC-V/ProcessorPkg/Library/RiscVOpensbiLib/RiscVOpensbiLib.inf |  60 ++
>  Silicon/RISC-V/ProcessorPkg/Include/IndustryStandard/RiscVOpensbi.h     |  72 ++
>  Silicon/RISC-V/ProcessorPkg/Include/Library/RiscVEdk2SbiLib.h           | 631 ++++++++++++++++
>  Silicon/RISC-V/ProcessorPkg/Include/OpensbiTypes.h                      |  73 ++
>  Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.c   | 789 ++++++++++++++++++++
>  .gitmodules                                                             |   3 +
>  Readme.md                                                               |  36 +
>  Silicon/RISC-V/ProcessorPkg/Library/RiscVOpensbiLib/opensbi             |   1 +
>  9 files changed, 1693 insertions(+)
>  create mode 100644 Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.inf
>  create mode 100644 Silicon/RISC-V/ProcessorPkg/Library/RiscVOpensbiLib/RiscVOpensbiLib.inf
>  create mode 100644 Silicon/RISC-V/ProcessorPkg/Include/IndustryStandard/RiscVOpensbi.h
>  create mode 100644 Silicon/RISC-V/ProcessorPkg/Include/Library/RiscVEdk2SbiLib.h
>  create mode 100644 Silicon/RISC-V/ProcessorPkg/Include/OpensbiTypes.h
>  create mode 100644 Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.c
>  create mode 100644 .gitmodules
>  create mode 160000 Silicon/RISC-V/ProcessorPkg/Library/RiscVOpensbiLib/opensbi
> 
> -- 
> 2.26.1
> 
> 
> 
> 

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

* Re: [PATCH v2 1/3] ProcessorPkg/RiscVOpensbLib: Add opensbi submodule
  2020-05-15 13:39 ` [PATCH v2 1/3] ProcessorPkg/RiscVOpensbLib: Add opensbi submodule Daniel Schaefer
@ 2020-05-20 11:51   ` Leif Lindholm
  0 siblings, 0 replies; 19+ messages in thread
From: Leif Lindholm @ 2020-05-20 11:51 UTC (permalink / raw)
  To: Daniel Schaefer; +Cc: devel, Gilbert Chen, Abner Chang, Michael D Kinney

On Fri, May 15, 2020 at 15:39:35 +0200, Daniel Schaefer wrote:
> Add submodule opensbi under
> Silicon/RISC-V/ProcessorPkg/Library/RiscVOpensbLlib.
> The current supported opensbi version for RISC-V edk2 port is tags/v0.6.
> 
> Signed-off-by: Daniel Schaefer <daniel.schaefer@hpe.com>
> Co-authored-by: Gilbert Chen <gilbert.chen@hpe.com>
> Co-authored-by: Abner Chang <abner.chang@hpe.com>

Please drop the above two lines.
>From a project standpoint they are no-ops and I don't really mind
keeping them in 2-3/3 (I appreciate the sentiment), but this patch
isn't interesting enough to justify it, and mainly duplicates/modifies
content already in edk2/ReadMe.rst.

With that:
Reviewed-by: Leif Lindholm <leif@nuviainc.com>

> 
> Cc: Abner Chang <abner.chang@hpe.com>
> Cc: Gilbert Chen <gilbert.chen@hpe.com>
> Cc: Michael D Kinney <michael.k.kinney@intel.com>
> Cc: Leif Lindholm <leif@nuviainc.com>
> ---
>  .gitmodules                                                 |  3 ++
>  Readme.md                                                   | 36 ++++++++++++++++++++
>  Silicon/RISC-V/ProcessorPkg/Library/RiscVOpensbiLib/opensbi |  1 +
>  3 files changed, 40 insertions(+)
> 
> diff --git a/.gitmodules b/.gitmodules
> new file mode 100644
> index 000000000000..88aafaf15820
> --- /dev/null
> +++ b/.gitmodules
> @@ -0,0 +1,3 @@
> +[submodule "Silicon/RISC-V/ProcessorPkg/Library/RiscVOpensbiLib/opensbi"]
> +  path = Silicon/RISC-V/ProcessorPkg/Library/RiscVOpensbiLib/opensbi
> +  url = https://github.com/riscv/opensbi
> diff --git a/Readme.md b/Readme.md
> index 8f9522659d7b..8f7317e6b029 100644
> --- a/Readme.md
> +++ b/Readme.md
> @@ -10,6 +10,10 @@ The majority of the content in the EDK II open source project uses a
>  [BSD-2-Clause Plus Patent License](License.txt).  Additional details on EDK II
>  open source project code contributions can be found in the edk2 repository
>  [Readme.md](https://github.com/tianocore/edk2/blob/master/Readme.md).
> +The EDK II Platforms open source project contains the following components that
> +are covered by additional licenses:
> +
> +- [`Silicon/RISC-V/ProcessorPkg/Library/RiscVOpensbiLib/opensbi`](https://github.com/riscv/opensbi/blob/master/COPYING.BSD)
>  
>  # INDEX
>  * [Overview](#overview)
> @@ -260,3 +264,35 @@ For more information, see the
>  # Maintainers
>  
>  See [Maintainers.txt](Maintainers.txt).
> +
> +# Submodules
> +
> +Submodule in EDK II Platforms is allowed but submodule chain should be avoided
> +as possible as we can. Currently EDK II Platforms contains the following
> +submodules
> +
> +- Silicon/RISC-V/ProcessorPkg/Library/RiscVOpensbiLib/opensbi
> +
> +To get a full, buildable EDK II repository, use following steps of git command
> +
> +```bash
> +  git clone https://github.com/tianocore/edk2-platforms.git
> +  cd edk2-platforms
> +  git submodule update --init
> +  cd ..
> +```
> +
> +If there's update for submodules, use following git commands to get the latest
> +submodules code.
> +
> +```bash
> +  cd edk2-platforms
> +  git pull
> +  git submodule update
> +```
> +
> +Note: When cloning submodule repos, '--recursive' option is not recommended.
> +EDK II Platforms itself will not use any code/feature from submodules in above
> +submodules. So using '--recursive' adds a dependency on being able to reach
> +servers we do not actually want any code from, as well as needlessly
> +downloading code we will not use.
> diff --git a/Silicon/RISC-V/ProcessorPkg/Library/RiscVOpensbiLib/opensbi b/Silicon/RISC-V/ProcessorPkg/Library/RiscVOpensbiLib/opensbi
> new file mode 160000
> index 000000000000..ac5e821d50be
> --- /dev/null
> +++ b/Silicon/RISC-V/ProcessorPkg/Library/RiscVOpensbiLib/opensbi
> @@ -0,0 +1 @@
> +Subproject commit ac5e821d50be631f26274765a59bc1b444ffd862
> -- 
> 2.26.1
> 

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

* Re: [PATCH v2 2/3] ProcessorPkg/Library: Add RiscVOpensbiLib
  2020-05-15 13:39 ` [PATCH v2 2/3] ProcessorPkg/Library: Add RiscVOpensbiLib Daniel Schaefer
@ 2020-05-20 12:00   ` Leif Lindholm
  2020-05-20 14:44     ` Daniel Schaefer
  0 siblings, 1 reply; 19+ messages in thread
From: Leif Lindholm @ 2020-05-20 12:00 UTC (permalink / raw)
  To: Daniel Schaefer
  Cc: devel, Gilbert Chen, Leif Lindholm, Abner Chang, Michael D Kinney

(Fixing Mike's email in reply)

On Fri, May 15, 2020 at 15:39:36 +0200, Daniel Schaefer wrote:
> From: Abner Chang <abner.chang@hpe.com>
> 
> EDK2 RISC-V OpenSBI library which pull in external source files under
> RISC-V/ProcessorPkg/Library/RiscVOpensbiLib/opensbi to the build process.
> 
> Signed-off-by: Abner Chang <abner.chang@hpe.com>
> Co-authored-by: Daniel Schaefer <daniel.schaefer@hpe.com>

These two fields have flipped contents since v1 (without being
mentioned in either cover letter or below --- of this one).

The v1 form was correct - only the contributor can certify the
adherence of the contribution to https://developercertificate.org/.

> Co-authored-by: Gilbert Chen <gilbert.chen@hpe.com>
> Reviewed-by: Leif Lindholm <leif.lindholm@linaro.org>
> 
> Cc: Abner Chang <abner.chang@hpe.com>
> Cc: Gilbert Chen <gilbert.chen@hpe.com>
> Cc: Michael D Kinney <michael.k.kinney@intel.com>
> Cc: Leif Lindholm <leif@nuviainc.com>
> ---
>  Silicon/RISC-V/ProcessorPkg/Library/RiscVOpensbiLib/RiscVOpensbiLib.inf | 60 +++++++++++++++
>  Silicon/RISC-V/ProcessorPkg/Include/IndustryStandard/RiscVOpensbi.h     | 79 ++++++++++++++++++++
>  Silicon/RISC-V/ProcessorPkg/Include/OpensbiTypes.h                      | 73 ++++++++++++++++++
>  3 files changed, 212 insertions(+)
> 
> diff --git a/Silicon/RISC-V/ProcessorPkg/Library/RiscVOpensbiLib/RiscVOpensbiLib.inf b/Silicon/RISC-V/ProcessorPkg/Library/RiscVOpensbiLib/RiscVOpensbiLib.inf
> new file mode 100644
> index 000000000000..59dbd67d8e03
> --- /dev/null
> +++ b/Silicon/RISC-V/ProcessorPkg/Library/RiscVOpensbiLib/RiscVOpensbiLib.inf
> @@ -0,0 +1,60 @@
> +## @file
> +# RISC-V Opensbi Library Instance.
> +#
> +#  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      = RiscVOpensbiLib
> +  FILE_GUID      = 6EF0C812-66F6-11E9-93CE-3F5D5F0DF0A7
> +  MODULE_TYPE    = BASE
> +  VERSION_STRING = 1.0
> +  LIBRARY_CLASS  = RiscVOpensbiLib
> +
> +[Sources]
> +  opensbi/lib/sbi/riscv_asm.c
> +  opensbi/lib/sbi/riscv_atomic.c
> +  opensbi/lib/sbi/riscv_hardfp.S
> +  opensbi/lib/sbi/riscv_locks.c
> +  opensbi/lib/sbi/sbi_console.c
> +  opensbi/lib/sbi/sbi_ecall.c
> +  opensbi/lib/sbi/sbi_ecall_vendor.c
> +  opensbi/lib/sbi/sbi_ecall_replace.c
> +  opensbi/lib/sbi/sbi_ecall_legacy.c
> +  opensbi/lib/sbi/sbi_ecall_base.c
> +  opensbi/lib/sbi/sbi_emulate_csr.c
> +  opensbi/lib/sbi/sbi_fifo.c
> +  opensbi/lib/sbi/sbi_hart.c
> +  opensbi/lib/sbi/sbi_hfence.S
> +  opensbi/lib/sbi/sbi_illegal_insn.c
> +  opensbi/lib/sbi/sbi_init.c
> +  opensbi/lib/sbi/sbi_ipi.c
> +  opensbi/lib/sbi/sbi_misaligned_ldst.c
> +  opensbi/lib/sbi/sbi_scratch.c
> +  opensbi/lib/sbi/sbi_string.c
> +  opensbi/lib/sbi/sbi_system.c
> +  opensbi/lib/sbi/sbi_timer.c
> +  opensbi/lib/sbi/sbi_tlb.c
> +  opensbi/lib/sbi/sbi_trap.c
> +  opensbi/lib/sbi/sbi_unpriv.c
> +  opensbi/lib/utils/sys/clint.c
> +  opensbi/lib/utils/irqchip/plic.c
> +  opensbi/lib/utils/serial/sifive-uart.c
> +  opensbi/lib/utils/serial/uart8250.c
> +
> +[Packages]
> +  EmbeddedPkg/EmbeddedPkg.dec   # For libfdt.
> +  MdePkg/MdePkg.dec
> +  Silicon/RISC-V/ProcessorPkg/RiscVProcessorPkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +  PcdLib
> +  RiscVCpuLib
> +
> +
> +
> diff --git a/Silicon/RISC-V/ProcessorPkg/Include/IndustryStandard/RiscVOpensbi.h b/Silicon/RISC-V/ProcessorPkg/Include/IndustryStandard/RiscVOpensbi.h
> new file mode 100644
> index 000000000000..c5c0bd6d9b01
> --- /dev/null
> +++ b/Silicon/RISC-V/ProcessorPkg/Include/IndustryStandard/RiscVOpensbi.h
> @@ -0,0 +1,79 @@
> +/** @file
> +  SBI inline function calls.
> +
> +  Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#ifndef EDK2_SBI_H_
> +#define EDK2_SBI_H_
> +
> +#include <include/sbi/riscv_asm.h> // Reference to header file in opensbi
> +#include <RiscVImpl.h>
> +#include <sbi/sbi_types.h>  // Reference to header file wrapper
> +
> +#define SBI_SUCCESS                    0
> +#define SBI_ERR_FAILED                -1
> +#define SBI_ERR_NOT_SUPPORTED         -2
> +#define SBI_ERR_INVALID_PARAM         -3
> +#define SBI_ERR_DENIED                -4
> +#define SBI_ERR_INVALID_ADDRESS       -5
> +#define SBI_ERR_ALREADY_AVAILABLE     -6

Did the cover-letter changelog not suggest these had been changed from
local definitions to redefining the existing ones from Opensbi?
If this was "not possible" (the exception stated in cover letter), I
would have expected a comment above (below ---) on why. Or a reply to
my feedback on v1.

> +
> +#define SBI_BASE_EXT                   0x10
> +#define SBI_HSM_EXT                    0x48534D
> +#define SBI_TIME_EXT                   0x54494D45
> +#define SBI_IPI_EXT                    0x735049
> +#define SBI_RFNC_EXT                   0x52464E43
> +
> +//
> +// Below two definitions should be defined in OpenSBI.
> +//
> +#define SBI_EXT_FIRMWARE_CODE_BASE_START 0x0A000000
> +#define SBI_EXT_FIRMWARE_CODE_BASE_END   0x0AFFFFFF
> +
> +#define SBI_GET_SPEC_VERSION_FUNC      0
> +#define SBI_GET_IMPL_ID_FUNC           1
> +#define SBI_GET_IMPL_VERSION_FUNC      2
> +#define SBI_PROBE_EXTENSION_FUNC       3
> +#define SBI_GET_MVENDORID_FUNC         4
> +#define SBI_GET_MARCHID_FUNC           5
> +#define SBI_GET_MIMPID_FUNC            6
> +
> +#define SBI_HART_START_FUNC            0
> +#define SBI_HART_STOP_FUNC             1
> +#define SBI_HART_GET_STATUS_FUNC       2
> +
> +#define RISC_V_MAX_HART_SUPPORTED 16
> +
> +typedef
> +VOID
> +(EFIAPI *RISCV_HART_SWITCH_MODE)(
> +  IN  UINTN   FuncArg0,
> +  IN  UINTN   FuncArg1,
> +  IN  UINTN   NextAddr,
> +  IN  UINTN   NextMode,
> +  IN  BOOLEAN NextVirt
> +  );
> +
> +//
> +// Keep the structure member in 64-bit alignment.
> +//
> +typedef struct {
> +    UINT64                 IsaExtensionSupported;  // The ISA extension this core supported.
> +    RISCV_UINT128          MachineVendorId;        // Machine vendor ID
> +    RISCV_UINT128          MachineArchId;          // Machine Architecture ID
> +    RISCV_UINT128          MachineImplId;          // Machine Implementation ID
> +    RISCV_HART_SWITCH_MODE HartSwitchMode;         // OpenSBI's function to switch the mode of a hart
> +} EFI_RISCV_FIRMWARE_CONTEXT_HART_SPECIFIC;
> +#define FIRMWARE_CONTEXT_HART_SPECIFIC_SIZE  (64 * 8) // This is the size of EFI_RISCV_FIRMWARE_CONTEXT_HART_SPECIFIC
> +                                                      // structure. Referred by both C code and assembly code.
> +
> +typedef struct {
> +  VOID            *PeiServiceTable;       // PEI Service table
> +  EFI_RISCV_FIRMWARE_CONTEXT_HART_SPECIFIC  *HartSpecific[RISC_V_MAX_HART_SUPPORTED];
> +} EFI_RISCV_OPENSBI_FIRMWARE_CONTEXT;
> +
> +#endif
> diff --git a/Silicon/RISC-V/ProcessorPkg/Include/OpensbiTypes.h b/Silicon/RISC-V/ProcessorPkg/Include/OpensbiTypes.h
> new file mode 100644
> index 000000000000..5f3278e8461f
> --- /dev/null
> +++ b/Silicon/RISC-V/ProcessorPkg/Include/OpensbiTypes.h
> @@ -0,0 +1,73 @@
> +/** @file
> +  RISC-V OpesbSBI header file reference.
> +
> +  Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +#ifndef EDK2_SBI_TYPES_H_
> +#define EDK2_SBI_TYPES_H_
> +
> +#include <Base.h>
> +
> +typedef INT8    s8;
> +typedef UINT8   u8;
> +typedef UINT8   uint8_t;
> +
> +typedef INT16   s16;
> +typedef UINT16  u16;
> +typedef INT16   int16_t;
> +typedef UINT16  uint16_t;
> +
> +typedef INT32   s32;
> +typedef UINT32  u32;
> +typedef INT32   int32_t;
> +typedef UINT32  uint32_t;
> +
> +typedef INT64   s64;
> +typedef UINT64  u64;
> +typedef INT64   int64_t;
> +typedef UINT64  uint64_t;
> +
> +#define PRILX   "016lx"

Feedback on PRILX not addressed, or commented on.

/
    Leif

> +
> +typedef BOOLEAN  bool;
> +typedef unsigned long   ulong;
> +typedef UINT64   uintptr_t;
> +typedef UINT64   size_t;
> +typedef INT64    ssize_t;
> +typedef UINT64   virtual_addr_t;
> +typedef UINT64   virtual_size_t;
> +typedef UINT64   physical_addr_t;
> +typedef UINT64   physical_size_t;
> +
> +#define __packed        __attribute__((packed))
> +#define __noreturn      __attribute__((noreturn))
> +
> +#if defined(__GNUC__) || defined(__clang__)
> +  #define likely(x) __builtin_expect((x), 1)
> +  #define unlikely(x) __builtin_expect((x), 0)
> +#else
> +  #define likely(x) (x)
> +  #define unlikely(x) (x)
> +#endif
> +
> +#undef offsetof
> +#ifdef __compiler_offsetof
> +#define offsetof(TYPE, MEMBER) __compiler_offsetof(TYPE,MEMBER)
> +#else
> +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
> +#endif
> +
> +#define container_of(ptr, type, member) ({            \
> +  const typeof(((type *)0)->member) * __mptr = (ptr); \
> +  (type *)((char *)__mptr - offsetof(type, member)); })
> +
> +#define CLAMP(a, lo, hi) MIN(MAX(a, lo), hi)
> +#define ROUNDUP(a, b) ((((a)-1) / (b) + 1) * (b))
> +#define ROUNDDOWN(a, b) ((a) / (b) * (b))
> +
> +/* clang-format on */
> +
> +#endif
> -- 
> 2.26.1
> 

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

* Re: [PATCH v2 2/3] ProcessorPkg/Library: Add RiscVOpensbiLib
  2020-05-20 12:00   ` Leif Lindholm
@ 2020-05-20 14:44     ` Daniel Schaefer
  0 siblings, 0 replies; 19+ messages in thread
From: Daniel Schaefer @ 2020-05-20 14:44 UTC (permalink / raw)
  To: Leif Lindholm
  Cc: devel, Gilbert Chen, Leif Lindholm, Abner Chang, Michael D Kinney

On 5/20/20 2:00 PM, Leif Lindholm wrote:
> (Fixing Mike's email in reply)
> 
> On Fri, May 15, 2020 at 15:39:36 +0200, Daniel Schaefer wrote:
>> From: Abner Chang <abner.chang@hpe.com>
>>
>> EDK2 RISC-V OpenSBI library which pull in external source files under
>> RISC-V/ProcessorPkg/Library/RiscVOpensbiLib/opensbi to the build process.
>>
>> Signed-off-by: Abner Chang <abner.chang@hpe.com>
>> Co-authored-by: Daniel Schaefer <daniel.schaefer@hpe.com>
> 
> These two fields have flipped contents since v1 (without being
> mentioned in either cover letter or below --- of this one).
> 
> The v1 form was correct - only the contributor can certify the
> adherence of the contribution to https://developercertificate.org/ .
> 
Meaning if the commit says Signed-off-by: Abner, I can't send it to the 
list?
>> Co-authored-by: Gilbert Chen <gilbert.chen@hpe.com>
>> Reviewed-by: Leif Lindholm <leif.lindholm@linaro.org>
>>
>> Cc: Abner Chang <abner.chang@hpe.com>
>> Cc: Gilbert Chen <gilbert.chen@hpe.com>
>> Cc: Michael D Kinney <michael.k.kinney@intel.com>
>> Cc: Leif Lindholm <leif@nuviainc.com>
>> ---
>>   Silicon/RISC-V/ProcessorPkg/Library/RiscVOpensbiLib/RiscVOpensbiLib.inf | 60 +++++++++++++++
>>   Silicon/RISC-V/ProcessorPkg/Include/IndustryStandard/RiscVOpensbi.h     | 79 ++++++++++++++++++++
>>   Silicon/RISC-V/ProcessorPkg/Include/OpensbiTypes.h                      | 73 ++++++++++++++++++
>>   3 files changed, 212 insertions(+)
>>
>> diff --git a/Silicon/RISC-V/ProcessorPkg/Library/RiscVOpensbiLib/RiscVOpensbiLib.inf b/Silicon/RISC-V/ProcessorPkg/Library/RiscVOpensbiLib/RiscVOpensbiLib.inf
>> new file mode 100644
>> index 000000000000..59dbd67d8e03
>> --- /dev/null
>> +++ b/Silicon/RISC-V/ProcessorPkg/Library/RiscVOpensbiLib/RiscVOpensbiLib.inf
>> @@ -0,0 +1,60 @@
>> +## @file
>> +# RISC-V Opensbi Library Instance.
>> +#
>> +#  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      = RiscVOpensbiLib
>> +  FILE_GUID      = 6EF0C812-66F6-11E9-93CE-3F5D5F0DF0A7
>> +  MODULE_TYPE    = BASE
>> +  VERSION_STRING = 1.0
>> +  LIBRARY_CLASS  = RiscVOpensbiLib
>> +
>> +[Sources]
>> +  opensbi/lib/sbi/riscv_asm.c
>> +  opensbi/lib/sbi/riscv_atomic.c
>> +  opensbi/lib/sbi/riscv_hardfp.S
>> +  opensbi/lib/sbi/riscv_locks.c
>> +  opensbi/lib/sbi/sbi_console.c
>> +  opensbi/lib/sbi/sbi_ecall.c
>> +  opensbi/lib/sbi/sbi_ecall_vendor.c
>> +  opensbi/lib/sbi/sbi_ecall_replace.c
>> +  opensbi/lib/sbi/sbi_ecall_legacy.c
>> +  opensbi/lib/sbi/sbi_ecall_base.c
>> +  opensbi/lib/sbi/sbi_emulate_csr.c
>> +  opensbi/lib/sbi/sbi_fifo.c
>> +  opensbi/lib/sbi/sbi_hart.c
>> +  opensbi/lib/sbi/sbi_hfence.S
>> +  opensbi/lib/sbi/sbi_illegal_insn.c
>> +  opensbi/lib/sbi/sbi_init.c
>> +  opensbi/lib/sbi/sbi_ipi.c
>> +  opensbi/lib/sbi/sbi_misaligned_ldst.c
>> +  opensbi/lib/sbi/sbi_scratch.c
>> +  opensbi/lib/sbi/sbi_string.c
>> +  opensbi/lib/sbi/sbi_system.c
>> +  opensbi/lib/sbi/sbi_timer.c
>> +  opensbi/lib/sbi/sbi_tlb.c
>> +  opensbi/lib/sbi/sbi_trap.c
>> +  opensbi/lib/sbi/sbi_unpriv.c
>> +  opensbi/lib/utils/sys/clint.c
>> +  opensbi/lib/utils/irqchip/plic.c
>> +  opensbi/lib/utils/serial/sifive-uart.c
>> +  opensbi/lib/utils/serial/uart8250.c
>> +
>> +[Packages]
>> +  EmbeddedPkg/EmbeddedPkg.dec   # For libfdt.
>> +  MdePkg/MdePkg.dec
>> +  Silicon/RISC-V/ProcessorPkg/RiscVProcessorPkg.dec
>> +
>> +[LibraryClasses]
>> +  BaseLib
>> +  PcdLib
>> +  RiscVCpuLib
>> +
I talked to Abner about this and we're going to remove this 
LibraryClasses section. It's not needed.
>> +
>> +
>> diff --git a/Silicon/RISC-V/ProcessorPkg/Include/IndustryStandard/RiscVOpensbi.h b/Silicon/RISC-V/ProcessorPkg/Include/IndustryStandard/RiscVOpensbi.h
>> new file mode 100644
>> index 000000000000..c5c0bd6d9b01
>> --- /dev/null
>> +++ b/Silicon/RISC-V/ProcessorPkg/Include/IndustryStandard/RiscVOpensbi.h
>> @@ -0,0 +1,79 @@
>> +/** @file
>> +  SBI inline function calls.
>> +
>> +  Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
>> +
>> +  SPDX-License-Identifier: BSD-2-Clause-Patent
>> +
>> +**/
>> +
>> +#ifndef EDK2_SBI_H_
>> +#define EDK2_SBI_H_
>> +
>> +#include <include/sbi/riscv_asm.h> // Reference to header file in opensbi
>> +#include <RiscVImpl.h>
>> +#include <sbi/sbi_types.h>  // Reference to header file wrapper
>> +
>> +#define SBI_SUCCESS                    0
>> +#define SBI_ERR_FAILED                -1
>> +#define SBI_ERR_NOT_SUPPORTED         -2
>> +#define SBI_ERR_INVALID_PARAM         -3
>> +#define SBI_ERR_DENIED                -4
>> +#define SBI_ERR_INVALID_ADDRESS       -5
>> +#define SBI_ERR_ALREADY_AVAILABLE     -6
> 
> Did the cover-letter changelog not suggest these had been changed from
> local definitions to redefining the existing ones from Opensbi?
> If this was "not possible" (the exception stated in cover letter), I
> would have expected a comment above (below ---) on why. Or a reply to
> my feedback on v1.
Oh, I squashed it into the other commit:
ProcessorPkg/Library: Add RiscVEdk2SbiLib
> 
>> +
>> +#define SBI_BASE_EXT                   0x10
>> +#define SBI_HSM_EXT                    0x48534D
>> +#define SBI_TIME_EXT                   0x54494D45
>> +#define SBI_IPI_EXT                    0x735049
>> +#define SBI_RFNC_EXT                   0x52464E43
>> +
>> +//
>> +// Below two definitions should be defined in OpenSBI.
>> +//
>> +#define SBI_EXT_FIRMWARE_CODE_BASE_START 0x0A000000
>> +#define SBI_EXT_FIRMWARE_CODE_BASE_END   0x0AFFFFFF
>> +
>> +#define SBI_GET_SPEC_VERSION_FUNC      0
>> +#define SBI_GET_IMPL_ID_FUNC           1
>> +#define SBI_GET_IMPL_VERSION_FUNC      2
>> +#define SBI_PROBE_EXTENSION_FUNC       3
>> +#define SBI_GET_MVENDORID_FUNC         4
>> +#define SBI_GET_MARCHID_FUNC           5
>> +#define SBI_GET_MIMPID_FUNC            6
>> +
>> +#define SBI_HART_START_FUNC            0
>> +#define SBI_HART_STOP_FUNC             1
>> +#define SBI_HART_GET_STATUS_FUNC       2
>> +
>> +#define RISC_V_MAX_HART_SUPPORTED 16
>> +
>> +typedef
>> +VOID
>> +(EFIAPI *RISCV_HART_SWITCH_MODE)(
>> +  IN  UINTN   FuncArg0,
>> +  IN  UINTN   FuncArg1,
>> +  IN  UINTN   NextAddr,
>> +  IN  UINTN   NextMode,
>> +  IN  BOOLEAN NextVirt
>> +  );
>> +
>> +//
>> +// Keep the structure member in 64-bit alignment.
>> +//
>> +typedef struct {
>> +    UINT64                 IsaExtensionSupported;  // The ISA extension this core supported.
>> +    RISCV_UINT128          MachineVendorId;        // Machine vendor ID
>> +    RISCV_UINT128          MachineArchId;          // Machine Architecture ID
>> +    RISCV_UINT128          MachineImplId;          // Machine Implementation ID
>> +    RISCV_HART_SWITCH_MODE HartSwitchMode;         // OpenSBI's function to switch the mode of a hart
>> +} EFI_RISCV_FIRMWARE_CONTEXT_HART_SPECIFIC;
>> +#define FIRMWARE_CONTEXT_HART_SPECIFIC_SIZE  (64 * 8) // This is the size of EFI_RISCV_FIRMWARE_CONTEXT_HART_SPECIFIC
>> +                                                      // structure. Referred by both C code and assembly code.
>> +
>> +typedef struct {
>> +  VOID            *PeiServiceTable;       // PEI Service table
>> +  EFI_RISCV_FIRMWARE_CONTEXT_HART_SPECIFIC  *HartSpecific[RISC_V_MAX_HART_SUPPORTED];
>> +} EFI_RISCV_OPENSBI_FIRMWARE_CONTEXT;
>> +
>> +#endif
>> diff --git a/Silicon/RISC-V/ProcessorPkg/Include/OpensbiTypes.h b/Silicon/RISC-V/ProcessorPkg/Include/OpensbiTypes.h
>> new file mode 100644
>> index 000000000000..5f3278e8461f
>> --- /dev/null
>> +++ b/Silicon/RISC-V/ProcessorPkg/Include/OpensbiTypes.h
>> @@ -0,0 +1,73 @@
>> +/** @file
>> +  RISC-V OpesbSBI header file reference.
>> +
>> +  Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
>> +
>> +  SPDX-License-Identifier: BSD-2-Clause-Patent
>> +
>> +**/
>> +#ifndef EDK2_SBI_TYPES_H_
>> +#define EDK2_SBI_TYPES_H_
>> +
>> +#include <Base.h>
>> +
>> +typedef INT8    s8;
>> +typedef UINT8   u8;
>> +typedef UINT8   uint8_t;
>> +
>> +typedef INT16   s16;
>> +typedef UINT16  u16;
>> +typedef INT16   int16_t;
>> +typedef UINT16  uint16_t;
>> +
>> +typedef INT32   s32;
>> +typedef UINT32  u32;
>> +typedef INT32   int32_t;
>> +typedef UINT32  uint32_t;
>> +
>> +typedef INT64   s64;
>> +typedef UINT64  u64;
>> +typedef INT64   int64_t;
>> +typedef UINT64  uint64_t;
>> +
>> +#define PRILX   "016lx"
> 
> Feedback on PRILX not addressed, or commented on.> /
>      Leif
> 
In addition to the cover letter, I also responded to your previous 
review, see:
https://edk2.groups.io/g/devel/message/59681
TLDR; we need to keep it.


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

* Re: [edk2-devel] [PATCH v2 0/3] New RISC-V Patches - Why in edk2-platforms
  2020-05-20 11:43 ` [edk2-devel] [PATCH v2 0/3] New RISC-V Patches Leif Lindholm
@ 2020-05-20 16:03   ` Daniel Schaefer
  2020-05-20 16:07     ` Daniel Schaefer
  0 siblings, 1 reply; 19+ messages in thread
From: Daniel Schaefer @ 2020-05-20 16:03 UTC (permalink / raw)
  To: Leif Lindholm, devel
  Cc: Abner Chang, Gilbert Chen, Michael D Kinney, Bret.Barkelew,
	sean.brogan

On 5/20/20 1:43 PM, Leif Lindholm wrote:
> On Fri, May 15, 2020 at 15:39:34 +0200, Daniel Schaefer wrote:
>> Previously we had two packages just for RISC-V on our edk2 branch:
>>    RiscVPkg and RiscVPlatformPkg
>> They are now under
>>    Platform/RISC-V/PlatformPkg and Silicon/RISC-V/ProcessorPkg
>> in edk2-platforms.
> 
> Understood. I took my eye off the ball there for a while, but I'm a
> bit confused as to why RiscVPkg isn't going into EDK2. That is very
> counterintuitive. And clearly it will need revisiting if we are to add
> first-class CI checks like those we do with OvmfPkg/ArmVirtPkg.

Yes, I understand your concern. Personally I'd like it also to be in 
EDK2 straight away, however Mike, Bret and Sean have raised valid concerns:

1. RISC-V is very new and potentially unstable - it's quicker to make 
changes in edk2-platforms.

2. If we define new interfaces and libraries in edk2, we can't remove 
them easily because it would be a backwards-incompatible change. 
edk2-platforms isn't quite as strict.

3. Long-term, I think many agree, we should aim to move much of the 
RISC-V code into UefiCpuPkg and OvmfPkg. Mike mentioned that would need 
coordination with ARM maintainers because it might make sense to move 
their code there as well.

Maybe Mike, Bret or Sean would like to provide some more comments?

> I *did* have some outstanding comments specifically with regards to
> large amounts of code duplication between the SMBIOS implementation of
> some closely related RISC-V platforms. That now needs to be revisited.

The SMBIOS code hasn't changed. It has moved to
   Silicon/SiFive/{E51,U54,U54MCCoreplex}/Library/PeiCoreInfoHobLib
You're referring to this library, right?

They build the SMBIOS entries for a particular processor. Yes, the 
values do have a lot of overlap but these files are like configuration 
files. They don't do much, they only set the values of the properties.

Currently it is not possible to let the UEFI firmware get this 
information from the hardware at runtime, especially now, since we're 
running in S-Mode.
To allow that, we created a RISC-V working group to be able to retrieve 
all of this information dynamically from the processor (among other 
goals). Then the vendor will not have to modify these files and hardcode 
the values anymore. Which enables us to create a single library for all 
processors.
See: https://github.com/riscv/configuration-structure

I hope I described everything properly, please correct me otherwise, Abner.

> 
>> In the previous version of this patchseries I forgot to attach the biggest new
>> commit, which adds RiscVEdk2SbiLib. It wraps the ecall interface for calling
>> SBI in a C API and lets PEI and DXE call SBI interfaces. Because we need more
>> M-Mode capabilities in PEI and DXE than SBI gives us, we register another SBI
>> extension, that gives us access to the mscratch register.
> 
> Without looking at it yet, it sounds like that may resolve the only
> remaining major issue I had with RiscVPkg.
> 
>> I hope now it makes more sense.
> 
> It is more clear, as per above I am not sure it makes more sense :)
> Thanks!

Your concerns are very valid, however due to the mentioned trade-offs it 
might not make sense to address them.

- Daniel

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

* Re: [edk2-devel] [PATCH v2 0/3] New RISC-V Patches - Why in edk2-platforms
  2020-05-20 16:03   ` [edk2-devel] [PATCH v2 0/3] New RISC-V Patches - Why in edk2-platforms Daniel Schaefer
@ 2020-05-20 16:07     ` Daniel Schaefer
  2020-05-20 16:17       ` Daniel Schaefer
  0 siblings, 1 reply; 19+ messages in thread
From: Daniel Schaefer @ 2020-05-20 16:07 UTC (permalink / raw)
  To: Leif Lindholm, devel
  Cc: Abner Chang, Gilbert Chen, Michael D Kinney, Bret.Barkelew,
	sean.brogan

please reply here, fixed Mike's email address, sorry...

On 5/20/20 6:03 PM, Daniel Schaefer wrote:
> On 5/20/20 1:43 PM, Leif Lindholm wrote:
>> On Fri, May 15, 2020 at 15:39:34 +0200, Daniel Schaefer wrote:
>>> Previously we had two packages just for RISC-V on our edk2 branch:
>>>    RiscVPkg and RiscVPlatformPkg
>>> They are now under
>>>    Platform/RISC-V/PlatformPkg and Silicon/RISC-V/ProcessorPkg
>>> in edk2-platforms.
>>
>> Understood. I took my eye off the ball there for a while, but I'm a
>> bit confused as to why RiscVPkg isn't going into EDK2. That is very
>> counterintuitive. And clearly it will need revisiting if we are to add
>> first-class CI checks like those we do with OvmfPkg/ArmVirtPkg.
> 
> Yes, I understand your concern. Personally I'd like it also to be in 
> EDK2 straight away, however Mike, Bret and Sean have raised valid concerns:
> 
> 1. RISC-V is very new and potentially unstable - it's quicker to make 
> changes in edk2-platforms.
> 
> 2. If we define new interfaces and libraries in edk2, we can't remove 
> them easily because it would be a backwards-incompatible change. 
> edk2-platforms isn't quite as strict.
> 
> 3. Long-term, I think many agree, we should aim to move much of the 
> RISC-V code into UefiCpuPkg and OvmfPkg. Mike mentioned that would need 
> coordination with ARM maintainers because it might make sense to move 
> their code there as well.
> 
> Maybe Mike, Bret or Sean would like to provide some more comments?
> 
>> I *did* have some outstanding comments specifically with regards to
>> large amounts of code duplication between the SMBIOS implementation of
>> some closely related RISC-V platforms. That now needs to be revisited.
> 
> The SMBIOS code hasn't changed. It has moved to
>    Silicon/SiFive/{E51,U54,U54MCCoreplex}/Library/PeiCoreInfoHobLib
> You're referring to this library, right?
> 
> They build the SMBIOS entries for a particular processor. Yes, the 
> values do have a lot of overlap but these files are like configuration 
> files. They don't do much, they only set the values of the properties.
> 
> Currently it is not possible to let the UEFI firmware get this 
> information from the hardware at runtime, especially now, since we're 
> running in S-Mode.
> To allow that, we created a RISC-V working group to be able to retrieve 
> all of this information dynamically from the processor (among other 
> goals). Then the vendor will not have to modify these files and hardcode 
> the values anymore. Which enables us to create a single library for all 
> processors.
> See: https://github.com/riscv/configuration-structure
> 
> I hope I described everything properly, please correct me otherwise, Abner.
> 
>>
>>> In the previous version of this patchseries I forgot to attach the 
>>> biggest new
>>> commit, which adds RiscVEdk2SbiLib. It wraps the ecall interface for 
>>> calling
>>> SBI in a C API and lets PEI and DXE call SBI interfaces. Because we 
>>> need more
>>> M-Mode capabilities in PEI and DXE than SBI gives us, we register 
>>> another SBI
>>> extension, that gives us access to the mscratch register.
>>
>> Without looking at it yet, it sounds like that may resolve the only
>> remaining major issue I had with RiscVPkg.
>>
>>> I hope now it makes more sense.
>>
>> It is more clear, as per above I am not sure it makes more sense :)
>> Thanks!
> 
> Your concerns are very valid, however due to the mentioned trade-offs it 
> might not make sense to address them.
> 
> - Daniel

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

* Re: [edk2-devel] [PATCH v2 0/3] New RISC-V Patches - Why in edk2-platforms
  2020-05-20 16:07     ` Daniel Schaefer
@ 2020-05-20 16:17       ` Daniel Schaefer
  2020-05-21  6:59         ` Abner Chang
  0 siblings, 1 reply; 19+ messages in thread
From: Daniel Schaefer @ 2020-05-20 16:17 UTC (permalink / raw)
  To: Leif Lindholm, devel
  Cc: Abner Chang, Gilbert Chen, Kinney, Michael D, Bret.Barkelew,
	sean.brogan



On 5/20/20 6:07 PM, Daniel Schaefer wrote:
> please reply here, fixed Mike's email address, sorry...
> 
> On 5/20/20 6:03 PM, Daniel Schaefer wrote:
>> On 5/20/20 1:43 PM, Leif Lindholm wrote:
>>> On Fri, May 15, 2020 at 15:39:34 +0200, Daniel Schaefer wrote:
>>>> Previously we had two packages just for RISC-V on our edk2 branch:
>>>>    RiscVPkg and RiscVPlatformPkg
>>>> They are now under
>>>>    Platform/RISC-V/PlatformPkg and Silicon/RISC-V/ProcessorPkg
>>>> in edk2-platforms.
>>>
>>> Understood. I took my eye off the ball there for a while, but I'm a
>>> bit confused as to why RiscVPkg isn't going into EDK2. That is very
>>> counterintuitive. And clearly it will need revisiting if we are to add
>>> first-class CI checks like those we do with OvmfPkg/ArmVirtPkg.
>>
>> Yes, I understand your concern. Personally I'd like it also to be in 
>> EDK2 straight away, however Mike, Bret and Sean have raised valid 
>> concerns:
>>
>> 1. RISC-V is very new and potentially unstable - it's quicker to make 
>> changes in edk2-platforms.
>>
>> 2. If we define new interfaces and libraries in edk2, we can't remove 
>> them easily because it would be a backwards-incompatible change. 
>> edk2-platforms isn't quite as strict.
>>
>> 3. Long-term, I think many agree, we should aim to move much of the 
>> RISC-V code into UefiCpuPkg and OvmfPkg. Mike mentioned that would 
>> need coordination with ARM maintainers because it might make sense to 
>> move their code there as well.
>>
>> Maybe Mike, Bret or Sean would like to provide some more comments?
>>
>>> I *did* have some outstanding comments specifically with regards to
>>> large amounts of code duplication between the SMBIOS implementation of
>>> some closely related RISC-V platforms. That now needs to be revisited.
>>
>> The SMBIOS code hasn't changed. It has moved to
>>    Silicon/SiFive/{E51,U54,U54MCCoreplex}/Library/PeiCoreInfoHobLib
>> You're referring to this library, right?
>>
>> They build the SMBIOS entries for a particular processor. Yes, the 
>> values do have a lot of overlap but these files are like configuration 
>> files. They don't do much, they only set the values of the properties.
>>
>> Currently it is not possible to let the UEFI firmware get this 
>> information from the hardware at runtime, especially now, since we're 
>> running in S-Mode.
>> To allow that, we created a RISC-V working group to be able to 
>> retrieve all of this information dynamically from the processor (among 
>> other goals). Then the vendor will not have to modify these files and 
>> hardcode the values anymore. Which enables us to create a single 
>> library for all processors.
>> See: https://github.com/riscv/configuration-structure
>>
>> I hope I described everything properly, please correct me otherwise, 
>> Abner.
>>
>>>
>>>> In the previous version of this patchseries I forgot to attach the 
>>>> biggest new
>>>> commit, which adds RiscVEdk2SbiLib. It wraps the ecall interface for 
>>>> calling
>>>> SBI in a C API and lets PEI and DXE call SBI interfaces. Because we 
>>>> need more
>>>> M-Mode capabilities in PEI and DXE than SBI gives us, we register 
>>>> another SBI
>>>> extension, that gives us access to the mscratch register.
>>>
>>> Without looking at it yet, it sounds like that may resolve the only
>>> remaining major issue I had with RiscVPkg.
>>>
>>>> I hope now it makes more sense.
>>>
>>> It is more clear, as per above I am not sure it makes more sense :)
>>> Thanks!
>>
>> Your concerns are very valid, however due to the mentioned trade-offs 
>> it might not make sense to address them.
>>
>> - Daniel

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

* Re: [PATCH v2 3/3] ProcessorPkg/Library: Add RiscVEdk2SbiLib
  2020-05-15 13:39 ` [PATCH v2 3/3] ProcessorPkg/Library: Add RiscVEdk2SbiLib Daniel Schaefer
@ 2020-05-20 18:27   ` Leif Lindholm
  2020-05-29 12:43     ` [edk2-devel] " Daniel Schaefer
  0 siblings, 1 reply; 19+ messages in thread
From: Leif Lindholm @ 2020-05-20 18:27 UTC (permalink / raw)
  To: Daniel Schaefer; +Cc: devel, Abner Chang, Gilbert Chen, Michael D Kinney

On Fri, May 15, 2020 at 15:39:37 +0200, Daniel Schaefer wrote:
> Library provides interfaces to invoke SBI extensions.
> 
> Signed-off-by: Daniel Schaefer <daniel.schaefer@hpe.com>
> 
> Cc: Abner Chang <abner.chang@hpe.com>
> Cc: Gilbert Chen <gilbert.chen@hpe.com>
> Cc: Michael D Kinney <michael.k.kinney@intel.com>
> Cc: Leif Lindholm <leif@nuviainc.com>
> ---
>  Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.inf |  28 +
>  Silicon/RISC-V/ProcessorPkg/Include/IndustryStandard/RiscVOpensbi.h     |  43 +-
>  Silicon/RISC-V/ProcessorPkg/Include/Library/RiscVEdk2SbiLib.h           | 631 ++++++++++++++++
>  Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.c   | 789 ++++++++++++++++++++
>  4 files changed, 1466 insertions(+), 25 deletions(-)
> 
> 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/IndustryStandard/RiscVOpensbi.h b/Silicon/RISC-V/ProcessorPkg/Include/IndustryStandard/RiscVOpensbi.h
> index c5c0bd6d9b01..18a85e2238d2 100644
> --- a/Silicon/RISC-V/ProcessorPkg/Include/IndustryStandard/RiscVOpensbi.h
> +++ b/Silicon/RISC-V/ProcessorPkg/Include/IndustryStandard/RiscVOpensbi.h
> @@ -10,42 +10,35 @@
>  #ifndef EDK2_SBI_H_
>  #define EDK2_SBI_H_
>  
> -#include <include/sbi/riscv_asm.h> // Reference to header file in opensbi
>  #include <RiscVImpl.h>
> +#include <sbi/riscv_asm.h> // Reference to header file in opensbi

I don't see anything in *this* patch requiring this change - does this
belong squashed into 2/3?

> +#include <sbi/sbi_ecall_interface.h>
> +#include <sbi/sbi_error.h>
>  #include <sbi/sbi_types.h>  // Reference to header file wrapper
>  
> -#define SBI_SUCCESS                    0
> -#define SBI_ERR_FAILED                -1
> -#define SBI_ERR_NOT_SUPPORTED         -2
> -#define SBI_ERR_INVALID_PARAM         -3
> -#define SBI_ERR_DENIED                -4
> -#define SBI_ERR_INVALID_ADDRESS       -5
> -#define SBI_ERR_ALREADY_AVAILABLE     -6
> +// Translation from OpenSBI constants to SBI names
> +#define SBI_SUCCESS               SBI_OK
> +#define SBI_ERR_FAILED            SBI_EFAIL
> +#define SBI_ERR_NOT_SUPPORTED     SBI_ENOTSUPP
> +#define SBI_ERR_INVALID_PARAM     SBI_EINVAL
> +#define SBI_ERR_DENIED            SBI_DENIED
> +#define SBI_ERR_INVALID_ADDRESS   SBI_INVALID_ADDR
> +#define SBI_ERR_ALREADY_AVAILABLE -6

Ah, right, see my confusion from reviewing 2/3.
Please move this to 2/3, adding a comment on why
SBI_ERR_ALREADY_AVAILABLE needs to be locally defined here.

>  
> -#define SBI_BASE_EXT                   0x10
> -#define SBI_HSM_EXT                    0x48534D
> -#define SBI_TIME_EXT                   0x54494D45
> -#define SBI_IPI_EXT                    0x735049
> -#define SBI_RFNC_EXT                   0x52464E43

Why do we add these in 2/3 only to delete them again here?

> +// Included in OpenSBI 0.7
> +// Can be removed, once we upgrade
> +#define SBI_EXT_HSM               0x48534D
> +#define SBI_EXT_HSM_HART_START    0x0
> +#define SBI_EXT_HSM_HART_STOP     0x1
> +#define SBI_EXT_HSM_HART_GET_STATUS 0x2
>  
>  //
>  // Below two definitions should be defined in OpenSBI.
> +// Submitted to upstream, waiting for merge and release.

Good call out. This isn't pretty, but it is the right thing to do.

>  //
>  #define SBI_EXT_FIRMWARE_CODE_BASE_START 0x0A000000
>  #define SBI_EXT_FIRMWARE_CODE_BASE_END   0x0AFFFFFF
>  
> -#define SBI_GET_SPEC_VERSION_FUNC      0
> -#define SBI_GET_IMPL_ID_FUNC           1
> -#define SBI_GET_IMPL_VERSION_FUNC      2
> -#define SBI_PROBE_EXTENSION_FUNC       3
> -#define SBI_GET_MVENDORID_FUNC         4
> -#define SBI_GET_MARCHID_FUNC           5
> -#define SBI_GET_MIMPID_FUNC            6
> -
> -#define SBI_HART_START_FUNC            0
> -#define SBI_HART_STOP_FUNC             1
> -#define SBI_HART_GET_STATUS_FUNC       2
> -

Why do we add these in 2/3 only to delete them again here?

>  #define RISC_V_MAX_HART_SUPPORTED 16
>  
>  typedef
> 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..cf77814e3bbc
> --- /dev/null
> +++ b/Silicon/RISC-V/ProcessorPkg/Include/Library/RiscVEdk2SbiLib.h
> @@ -0,0 +1,631 @@
> +/** @file Defines the PPIs to let PEIMs call SBI
> +
> +Copyright (c) 2020, Hewlett Packard Development LP. All rights reserved.<BR>
> +
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#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.
> +//
> +struct sbiret {

This struct appears only to be referenceed outside the opensbi
submodule, so name should conform to EDK2 coding style (and preferably
with a typedef).

> +  long error;   ///< SBI status code
> +  long value;   ///< Value returned

This looks like a maintenance hazard (means different things to GCC
and VS for example). Can we use UINT32?

> +};
> +
> +#define SbiCall0(ext_id, func_id) \
> +  SbiCall(ext_id, func_id, 0, 0, 0, 0, 0, 0)
> +#define SbiCall1(ext_id, func_id, arg0) \
> +  SbiCall(ext_id, func_id, arg0, 0, 0, 0, 0, 0)
> +#define SbiCall2(ext_id, func_id, arg0, arg1) \
> +  SbiCall(ext_id, func_id, arg0, arg1, 0, 0, 0, 0)
> +#define SbiCall3(ext_id, func_id, arg0, arg1, arg2) \
> +  SbiCall(ext_id, func_id, arg0, arg1, arg2, 0, 0, 0)
> +#define SbiCall4(ext_id, func_id, arg0, arg1, arg2, arg3) \
> +  SbiCall(ext_id, func_id, arg0, arg1, arg2, arg3, 0, 0)
> +#define SbiCall5(ext_id, func_id, arg0, arg1, arg2, arg3, arg4) \
> +  SbiCall(ext_id, func_id, arg0, arg1, arg2, arg3, arg4, 0)
> +#define SbiCall6(ext_id, func_id, arg0, arg1, arg2, arg3, arg4, arg5) \
> +  SbiCall(ext_id, func_id, arg0, arg1, arg2, arg3, arg4, arg5)

Ugh. This looks way too much like pre-EFIAPI x86 code.

Is this a pattern used across multiple codebases?
If not, could we make this a simple argc/argv instead and do the
unpacking inside SbiCall()? Hmm, maybe that would make the call sites
even worse.

If we need to keep these, coding style says all macros should use
UPPERCASE_AND_UNDERSCORES.

> +
> +/**
> +  EDK2 SbiCall to invoke SBI extensions.
> +
> +  @param[in] ext_id   Sbi extension ID.
> +  @param[in] func_id  Sbi functions ID.
> +  @param[in] arg0     Arg0 to function.
> +  @param[in] arg1     Arg1 to function.
> +  @param[in] arg2     Arg2 to function.
> +  @param[in] arg3     Arg3 to function.
> +  @param[in] arg4     Arg4 to function.
> +  @param[in] arg5     Arg5 to function.
> +
> +  @retval  Returns sbiret structure.
> +
> +**/
> +inline
> +EFIAPI
> +struct sbiret SbiCall(UINTN ext_id, UINTN func_id, UINTN arg0, UINTN arg1,

Function name starts in the first column of a new line.
But please drop the entire forward-declaration.

> +                           UINTN arg2, UINTN arg3, UINTN arg4, UINTN arg5)
> +__attribute__((always_inline));
> +
> +/**
> +  EDK2 SbiCall to invoke SBI extensions.
> +
> +  @param[in] ext_id   Sbi extension ID.
> +  @param[in] func_id  Sbi functions ID.
> +  @param[in] arg0     Arg0 to function.
> +  @param[in] arg1     Arg1 to function.
> +  @param[in] arg2     Arg2 to function.
> +  @param[in] arg3     Arg3 to function.
> +  @param[in] arg4     Arg4 to function.
> +  @param[in] arg5     Arg5 to function.
> +
> +  @retval  Returns sbiret structure.
> +
> +**/
> +inline

Technically, the coding standard bans function definitions in header
files[1]. If you can give me a good reason for why this function
should be here, I may consider to consider making an exception.
If I do, make it just STATIC (let the compiler worry about the
inlining).

If it is just by habit from other projects of putting helper functions
into headers, please move them to a .c file.

[1] https://edk2-docs.gitbook.io/edk-ii-c-coding-standards-specification/5_source_files/53_include_files#5-3-7-include-files-shall-not-generate-code-or-define-data-variables

> +EFIAPI
> +struct sbiret SbiCall(UINTN ext_id, UINTN func_id, UINTN arg0, UINTN arg1,
> +                           UINTN arg2, UINTN arg3, UINTN arg4, UINTN arg5) {
> +    register uintptr_t a0 asm ("a0") = (uintptr_t)(arg0);
> +    register uintptr_t a1 asm ("a1") = (uintptr_t)(arg1);
> +    register uintptr_t a2 asm ("a2") = (uintptr_t)(arg2);
> +    register uintptr_t a3 asm ("a3") = (uintptr_t)(arg3);
> +    register uintptr_t a4 asm ("a4") = (uintptr_t)(arg4);
> +    register uintptr_t a5 asm ("a5") = (uintptr_t)(arg5);
> +    register uintptr_t a6 asm ("a6") = (uintptr_t)(func_id);
> +    register uintptr_t a7 asm ("a7") = (uintptr_t)(ext_id);

I would *prefer* UINTN over uintptr_t here.

> +    asm volatile ("ecall" \
> +         : "+r" (a0) \

Isn't a1 also an input/output operand here?

> +         : "r" (a1), "r" (a2), "r" (a3), "r" (a4), "r" (a5), "r" (a6), "r" (a7) \
> +         : "memory"); \
> +    struct sbiret ret = { a0, a1 };
> +    return ret;

CamelCase naming.

> +}
> +
> +/**
> +  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 (

Uppercase V for CamelCase (and matching the argument name below).

> +  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.

What is an MvendorId? MachineVendorId?
Even if an official register name, I would prefer function and
arguments to be given proper descriptive CamelCase names.

> +
> +  @param[out] MvendorId            The CPU's vendor ID.
> +**/
> +VOID
> +EFIAPI
> +SbiGetMvendorId (
> +  OUT UINTN                       *MvendorId
> +  );
> +
> +/**
> +  Get the CPU's architecture ID
> +
> +  Reads the marchid CSR.
> +
> +  @param[out] MarchId              The CPU's architecture ID.

This should probebly be MArchId (or MachineArchId?)?

> +**/
> +VOID
> +EFIAPI
> +SbiGetMarchId (
> +  OUT UINTN                       *MarchId
> +  );
> +
> +/**
> +  Get the CPU's implementation ID
> +
> +  Reads the mimpid CSR.
> +
> +  @param[out] MimpId               The CPU's implementation ID.

Above "Impl" is used for "Impelentation". *Strictly* speaking, "Impl"
doesn't fall in the pretty small group of abbreviations permitted
without a glossary section in the source file, but it's clear enough
to me I'll let it slip.
The same cannot be said for "Imp".
MachineImplId?

> +**/
> +VOID
> +EFIAPI
> +SbiGetMimpId (
> +  OUT UINTN                       *Mimpid
> +  );
> +
> +/**
> +  Politely ask the SBI to start a given hart.

I know hart is a pretty fundamental concept in RISC-V.
Still, I would request to have it added in a glossary section in the
top-of-file comment header.

> +
> +  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 (

(With great effort, I suppress a Mötley Crüe joke.)

> +  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 StimeValue.

What does the S stand for in Stime?

> +
> +  To clear the timer without scheduling a timer event, set StimeValue to a
> +  practically infinite value or mask the timer interrupt by clearing sie.STIE.
> +
> +  @param[in]  StimeValue           The time offset to the next scheduled timer interrupt.
> +**/
> +VOID
> +EFIAPI
> +SbiSetTimer (
> +  IN  UINT64                         StimeValue
> +  );
> +
> +///
> +/// 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 struct sbi_scratch             **ScratchSpace

Could we add a typedef for "struct sbi_scratch" to make the code more
style compliant?

> +  );
> +
> +/**
> +  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 struct 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..bbe006a78af8
> --- /dev/null
> +++ b/Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.c
> @@ -0,0 +1,789 @@
> +/** @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
> +**/
> +
> +#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_platform.h>
> +#include <sbi/sbi_init.h>
> +
> +/**
> +  Translate SBI error code to EFI status.
> +
> +  @param[in] SbiError   SBI error code
> +  @retval EFI_STATUS
> +**/
> +
> +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 libraary 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
> +  )
> +{
> +  struct sbiret ret = SbiCall0 (SBI_EXT_BASE, SBI_EXT_BASE_GET_SPEC_VERSION);
> +
> +  if (!ret.error) {
> +    *SpecVersion = (UINTN) ret.value;
> +  }
> +
> +  //return TranslateError(ret.error);
> +}
> +
> +/**
> +  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
> +  )
> +{
> +  struct sbiret ret = SbiCall0 (SBI_EXT_BASE, SBI_EXT_BASE_GET_IMP_ID);
> +  *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
> +  )
> +{
> +  struct sbiret ret = SbiCall0 (SBI_EXT_BASE, SBI_EXT_BASE_GET_IMP_VERSION);
> +  *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
> +  )
> +{
> +  struct sbiret ret = SbiCall0 (SBI_EXT_BASE, SBI_EXT_BASE_PROBE_EXT);
> +  *ProbeResult = (UINTN) ret.value;
> +}
> +
> +/**
> +  Get the CPU's vendor ID
> +
> +  Reads the mvendorid CSR.
> +
> +  @param[out] MvendorId            The CPU's vendor ID.
> +**/
> +VOID
> +EFIAPI
> +SbiGetMvendorId (
> +  OUT UINTN                       *MvendorId
> +  )
> +{
> +  struct sbiret ret = SbiCall0 (SBI_EXT_BASE, SBI_EXT_BASE_GET_MVENDORID);
> +  *MvendorId = (UINTN) ret.value;
> +}
> +
> +/**
> +  Get the CPU's vendor ID
> +
> +  Reads the mvendorid CSR.
> +
> +  @param[out] MvendorId            The CPU's vendor ID.
> +**/
> +VOID
> +EFIAPI
> +SbiGetMarchId (
> +  OUT UINTN                       *MarchId
> +  )
> +{
> +  struct sbiret ret = SbiCall0 (SBI_EXT_BASE, SBI_EXT_BASE_GET_MARCHID);
> +  *MarchId = (UINTN) ret.value;
> +}
> +
> +/**
> +  Get the CPU's architecture ID
> +
> +  Reads the marchid CSR.
> +
> +  @param[out] MarchId              The CPU's architecture ID.
> +**/
> +VOID
> +EFIAPI
> +SbiGetMimpId (
> +  OUT UINTN                       *MimpId
> +  )
> +{
> +  struct sbiret ret = SbiCall0 (SBI_EXT_BASE, SBI_EXT_BASE_GET_MIMPID);
> +  *MimpId = (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
> +  )
> +{
> +  struct sbiret ret = SbiCall3 (SBI_EXT_HSM,
> +                                SBI_EXT_HSM_HART_START,
> +                                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 (
> +  )
> +{
> +  struct sbiret Ret = SbiCall0 (SBI_EXT_HSM, SBI_EXT_HSM_HART_STOP);
> +  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
> +  )
> +{
> +  struct sbiret ret = SbiCall1 (SBI_EXT_HSM, SBI_EXT_HSM_HART_GET_STATUS, HartId);
> +
> +  if (!ret.error) {
> +    *HartStatus = (UINTN) ret.value;
> +  }
> +
> +  return TranslateError(ret.error);
> +}
> +
> +/**
> +  Clear pending timer interrupt bit and set timer for next event after StimeValue.
> +
> +  To clear the timer without scheduling a timer event, set StimeValue to a
> +  practically infinite value or mask the timer interrupt by clearing sie.STIE.
> +
> +  @param[in]  StimeValue           The time offset to the next scheduled timer interrupt.
> +**/
> +VOID
> +EFIAPI
> +SbiSetTimer (
> +  IN  UINT64                         StimeValue
> +  )
> +{
> +  SbiCall1 (SBI_EXT_TIME, SBI_EXT_TIME_SET_TIMER, StimeValue);
> +}
> +
> +EFI_STATUS
> +EFIAPI
> +SbiSendIpi (
> +  IN  UINTN                         *HartMask,
> +  IN  UINTN                          HartMaskBase
> +  )
> +{
> +  struct sbiret ret = SbiCall2 (SBI_EXT_IPI,
> +                                SBI_EXT_IPI_SEND_IPI,
> +                                (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
> +  )
> +{
> +  struct sbiret ret = SbiCall2 (SBI_EXT_RFENCE,
> +                                SBI_EXT_RFENCE_REMOTE_FENCE_I,
> +                                (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
> +  )
> +{
> +  struct sbiret ret = SbiCall4 (SBI_EXT_RFENCE,
> +                                SBI_EXT_RFENCE_REMOTE_SFENCE_VMA,
> +                                (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
> +  )
> +{
> +  struct sbiret ret = SbiCall5 (SBI_EXT_RFENCE,
> +                                SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID,
> +                                (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
> +  )
> +{
> +  struct sbiret ret = SbiCall5 (SBI_EXT_RFENCE,
> +                                SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA,
> +                                (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
> +  )
> +{
> +  struct sbiret ret = SbiCall4 (SBI_EXT_RFENCE,
> +                                SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA_VMID,
> +                                (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
> +  )
> +{
> +  struct sbiret ret = SbiCall5 (SBI_EXT_RFENCE,
> +                                SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA,
> +                                (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
> +  )
> +{
> +  struct sbiret ret = SbiCall4 (SBI_EXT_RFENCE,
> +                                SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA_ASID,
> +                                (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.
> +
> +  @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,
> +  ...
> +  )
> +{
> +    struct sbiret ret;
> +    VA_LIST Args;
> +    VA_START(Args, NumArgs);
> +
> +    ASSERT (ExtensionId >= 0x09000000 && ExtensionId <= 0x09FFFFFF);
> +
> +    switch (NumArgs) {
> +      case 0:
> +        ret = SbiCall0 (ExtensionId, FunctionId);
> +        break;
> +      case 1:
> +        ret = SbiCall1 (ExtensionId, FunctionId, VA_ARG(Args, UINTN));
> +        break;
> +      case 2:
> +        ret = SbiCall2 (ExtensionId, FunctionId, VA_ARG(Args, UINTN), VA_ARG(Args, UINTN));
> +        break;
> +      case 3:
> +        ret = SbiCall3 (ExtensionId, FunctionId, VA_ARG(Args, UINTN), VA_ARG(Args, UINTN), VA_ARG(Args, UINTN));
> +        break;
> +      case 4:
> +        ret = SbiCall4 (ExtensionId, FunctionId, VA_ARG(Args, UINTN), VA_ARG(Args, UINTN), VA_ARG(Args, UINTN), VA_ARG(Args, UINTN));
> +        break;
> +      case 5:
> +        ret = SbiCall5 (ExtensionId, FunctionId, VA_ARG(Args, UINTN), VA_ARG(Args, UINTN), VA_ARG(Args, UINTN), VA_ARG(Args, UINTN), VA_ARG(Args, UINTN));
> +        break;
> +      case 6:
> +        ret = SbiCall6 (ExtensionId, FunctionId, 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 struct sbi_scratch             **ScratchSpace
> +  )
> +{
> +  struct sbiret ret = SbiCall0 (SBI_EDK2_FW_EXT, SBI_EXT_FW_MSCRATCH_FUNC);
> +
> +  if (!ret.error) {
> +    *ScratchSpace = (struct 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 struct sbi_scratch             **ScratchSpace
> +  )
> +{
> +  struct sbiret ret = SbiCall1 (SBI_EDK2_FW_EXT,
> +                                SBI_EXT_FW_MSCRATCH_HARTID_FUNC,
> +                                HartId);
> +
> +  if (!ret.error) {
> +    *ScratchSpace = (struct 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
> +  )
> +{
> +  struct sbi_scratch *ScratchSpace;
> +  struct sbi_platform *SbiPlatform;
> +  struct sbiret ret = SbiCall0 (SBI_EDK2_FW_EXT, SBI_EXT_FW_MSCRATCH_FUNC);
> +
> +  if (!ret.error) {
> +    ScratchSpace = (struct sbi_scratch *) ret.value;
> +    SbiPlatform = (struct 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
> +  )
> +{
> +  struct sbi_scratch *ScratchSpace;
> +  struct sbi_platform *SbiPlatform;
> +  struct sbiret ret = SbiCall0 (SBI_EDK2_FW_EXT, SBI_EXT_FW_MSCRATCH_FUNC);
> +
> +  if (!ret.error) {
> +    ScratchSpace = (struct sbi_scratch *) ret.value;
> +    SbiPlatform = (struct sbi_platform *) sbi_platform_ptr(ScratchSpace);
> +    SbiPlatform->firmware_context = (long unsigned int) FirmwareContext;

UINT64?

/
    Leif

> +  }
> +
> +  return EFI_SUCCESS;
> +}
> -- 
> 2.26.1
> 

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

* Re: [edk2-devel] [PATCH v2 0/3] New RISC-V Patches - Why in edk2-platforms
  2020-05-20 16:17       ` Daniel Schaefer
@ 2020-05-21  6:59         ` Abner Chang
  2020-05-28 11:54           ` Leif Lindholm
  0 siblings, 1 reply; 19+ messages in thread
From: Abner Chang @ 2020-05-21  6:59 UTC (permalink / raw)
  To: Schaefer, Daniel (DualStudy), Leif Lindholm, devel@edk2.groups.io
  Cc: Chen, Gilbert, Kinney, Michael D, Bret.Barkelew@microsoft.com,
	sean.brogan@microsoft.com



> -----Original Message-----
> From: Schaefer, Daniel (DualStudy)
> Sent: Thursday, May 21, 2020 12:18 AM
> To: Leif Lindholm <leif@nuviainc.com>; devel@edk2.groups.io
> Cc: Chang, Abner (HPS SW/FW Technologist) <abner.chang@hpe.com>;
> Chen, Gilbert <gilbert.chen@hpe.com>; Kinney, Michael D
> <michael.d.kinney@intel.com>; Bret.Barkelew@microsoft.com;
> sean.brogan@microsoft.com
> Subject: Re: [edk2-devel] [PATCH v2 0/3] New RISC-V Patches - Why in edk2-
> platforms
> 
> 
> 
> On 5/20/20 6:07 PM, Daniel Schaefer wrote:
> > please reply here, fixed Mike's email address, sorry...
> >
> > On 5/20/20 6:03 PM, Daniel Schaefer wrote:
> >> On 5/20/20 1:43 PM, Leif Lindholm wrote:
> >>> On Fri, May 15, 2020 at 15:39:34 +0200, Daniel Schaefer wrote:
> >>>> Previously we had two packages just for RISC-V on our edk2 branch:
> >>>>    RiscVPkg and RiscVPlatformPkg
> >>>> They are now under
> >>>>    Platform/RISC-V/PlatformPkg and Silicon/RISC-V/ProcessorPkg in
> >>>> edk2-platforms.
> >>>
> >>> Understood. I took my eye off the ball there for a while, but I'm a
> >>> bit confused as to why RiscVPkg isn't going into EDK2. That is very
> >>> counterintuitive. And clearly it will need revisiting if we are to
> >>> add first-class CI checks like those we do with OvmfPkg/ArmVirtPkg.
> >>
> >> Yes, I understand your concern. Personally I'd like it also to be in
> >> EDK2 straight away, however Mike, Bret and Sean have raised valid
> >> concerns:
> >>
> >> 1. RISC-V is very new and potentially unstable - it's quicker to make
> >> changes in edk2-platforms.
> >>
> >> 2. If we define new interfaces and libraries in edk2, we can't remove
> >> them easily because it would be a backwards-incompatible change.
> >> edk2-platforms isn't quite as strict.
> >>
> >> 3. Long-term, I think many agree, we should aim to move much of the
> >> RISC-V code into UefiCpuPkg and OvmfPkg. Mike mentioned that would
> >> need coordination with ARM maintainers because it might make sense to
> >> move their code there as well.
> >>
> >> Maybe Mike, Bret or Sean would like to provide some more comments?
> >>
> >>> I *did* have some outstanding comments specifically with regards to
> >>> large amounts of code duplication between the SMBIOS implementation
> >>> of some closely related RISC-V platforms. That now needs to be revisited.
> >>
> >> The SMBIOS code hasn't changed. It has moved to
> >>    Silicon/SiFive/{E51,U54,U54MCCoreplex}/Library/PeiCoreInfoHobLib
> >> You're referring to this library, right?
> >>
> >> They build the SMBIOS entries for a particular processor. Yes, the
> >> values do have a lot of overlap but these files are like
> >> configuration files. They don't do much, they only set the values of the
> properties.
> >>
> >> Currently it is not possible to let the UEFI firmware get this
> >> information from the hardware at runtime, especially now, since we're
> >> running in S-Mode.
> >> To allow that, we created a RISC-V working group to be able to
> >> retrieve all of this information dynamically from the processor
> >> (among other goals). Then the vendor will not have to modify these
> >> files and hardcode the values anymore. Which enables us to create a
> >> single library for all processors.
> >> See: https://github.com/riscv/configuration-structure
> >>
> >> I hope I described everything properly, please correct me otherwise,
> >> Abner.
[Abner]  Yes almost. Thanks Daniel.
One thing I would like to add,
If you take a look on SiFive Core IP https://www.sifive.com/risc-v-core-ip you can see there are different SKUs of RISC-V core. Just take some as example,
S51 - Single core
U54 - Single core
S76 - Single core
U74- single core
U54-MC - Multicore which is 4*U54 cores +1*S51 core
U74-MC - Multicore which is 4*U74 core + 1*S7 core

Those are the combinations of core IP. Silicon vendor can get those core IPs and combine them to the RISC-V processor. To have CoreInfoHobLib libraries for each different core (not multicore) to build up the core capability is reasonable and makes sense. For the multicore, it just pulling the single core CoreInfoHobLib to build up the SMBIOS table for the multicore processor. Those libraries look duplicate in logically, however only one instance of CoreInfoHobLib is built in for multiple identical cores in physically view. Maybe we still can move some identical core into the core-specific library but it is not worthwhile.

Abner

> >>
> >>>
> >>>> In the previous version of this patchseries I forgot to attach the
> >>>> biggest new commit, which adds RiscVEdk2SbiLib. It wraps the ecall
> >>>> interface for calling SBI in a C API and lets PEI and DXE call SBI
> >>>> interfaces. Because we need more M-Mode capabilities in PEI and DXE
> >>>> than SBI gives us, we register another SBI extension, that gives us
> >>>> access to the mscratch register.
> >>>
> >>> Without looking at it yet, it sounds like that may resolve the only
> >>> remaining major issue I had with RiscVPkg.
> >>>
> >>>> I hope now it makes more sense.
> >>>
> >>> It is more clear, as per above I am not sure it makes more sense :)
> >>> Thanks!
> >>
> >> Your concerns are very valid, however due to the mentioned trade-offs
> >> it might not make sense to address them.
> >>
> >> - Daniel

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

* Re: [edk2-devel] [PATCH v2 0/3] New RISC-V Patches - Why in edk2-platforms
  2020-05-21  6:59         ` Abner Chang
@ 2020-05-28 11:54           ` Leif Lindholm
  2020-05-29 14:41             ` Abner Chang
       [not found]             ` <b55ee3ec-74de-532e-01f7-bd24a327d00b@hpe.com>
  0 siblings, 2 replies; 19+ messages in thread
From: Leif Lindholm @ 2020-05-28 11:54 UTC (permalink / raw)
  To: Chang, Abner (HPS SW/FW Technologist)
  Cc: Schaefer, Daniel (DualStudy), devel@edk2.groups.io, Chen, Gilbert,
	Kinney, Michael D, Bret.Barkelew@microsoft.com,
	sean.brogan@microsoft.com

Hi Abner,

Sorry, I should have followed up on this sooner.

On Thu, May 21, 2020 at 06:59:20 +0000, Chang, Abner (HPS SW/FW Technologist) wrote:
> > On 5/20/20 6:07 PM, Daniel Schaefer wrote:
> > > please reply here, fixed Mike's email address, sorry...
> > >
> > > On 5/20/20 6:03 PM, Daniel Schaefer wrote:
> > >> On 5/20/20 1:43 PM, Leif Lindholm wrote:
> > >>> On Fri, May 15, 2020 at 15:39:34 +0200, Daniel Schaefer wrote:
> > >>>> Previously we had two packages just for RISC-V on our edk2 branch:
> > >>>>    RiscVPkg and RiscVPlatformPkg
> > >>>> They are now under
> > >>>>    Platform/RISC-V/PlatformPkg and Silicon/RISC-V/ProcessorPkg in
> > >>>> edk2-platforms.
> > >>>
> > >>> Understood. I took my eye off the ball there for a while, but I'm a
> > >>> bit confused as to why RiscVPkg isn't going into EDK2. That is very
> > >>> counterintuitive. And clearly it will need revisiting if we are to
> > >>> add first-class CI checks like those we do with OvmfPkg/ArmVirtPkg.
> > >>
> > >> Yes, I understand your concern. Personally I'd like it also to be in
> > >> EDK2 straight away, however Mike, Bret and Sean have raised valid
> > >> concerns:

Can you point me to the conversation I have missed?

> > >> 1. RISC-V is very new and potentially unstable - it's quicker to make
> > >> changes in edk2-platforms.

I don't see this as a valid argument.
It's not edk2-unstable, it is edk2-platforms.

edk2-platforms exists because there used to be strong feelings against
holding *real* platforms in edk2, with edk2 being originally intended
only as a code library for IBV/ISV to cherry-pick from.

But fundamentally, if code is too immature to go into the master
branch of edk2, it is too immature to go into the master branch of
edk2-platforms. If we want edk2-might-be-a-bit-shaky-but-who-cares,
then someone will have to create it.

> > >> 2. If we define new interfaces and libraries in edk2, we can't remove
> > >> them easily because it would be a backwards-incompatible change.
> > >> edk2-platforms isn't quite as strict.

Yes it is.
The only thing making it less strict is its contents - platform ports
and device drivers. The changes tend to be self-contained. Where they
are not, they need to be carefully managed.

> > >> 3. Long-term, I think many agree, we should aim to move much of the
> > >> RISC-V code into UefiCpuPkg and OvmfPkg. Mike mentioned that would
> > >> need coordination with ARM maintainers because it might make sense to
> > >> move their code there as well.

I don't think there is any need to tie the two together.
Yes, UefiCpuPkg should be a generic place where not only x86 support
can be contained, but the paths for ARM* and RISC-V into there do not
have any interdependencies.

> > >>> I *did* have some outstanding comments specifically with regards to
> > >>> large amounts of code duplication between the SMBIOS implementation
> > >>> of some closely related RISC-V platforms. That now needs to be revisited.
> > >>
> > >> The SMBIOS code hasn't changed. It has moved to
> > >>    Silicon/SiFive/{E51,U54,U54MCCoreplex}/Library/PeiCoreInfoHobLib
> > >> You're referring to this library, right?
> > >>
> > >> They build the SMBIOS entries for a particular processor. Yes, the
> > >> values do have a lot of overlap but these files are like
> > >> configuration files. They don't do much, they only set the values of the
> > properties.
> > >>
> > >> Currently it is not possible to let the UEFI firmware get this
> > >> information from the hardware at runtime, especially now, since we're
> > >> running in S-Mode.
> > >> To allow that, we created a RISC-V working group to be able to
> > >> retrieve all of this information dynamically from the processor
> > >> (among other goals). Then the vendor will not have to modify these
> > >> files and hardcode the values anymore. Which enables us to create a
> > >> single library for all processors.
> > >> See: https://github.com/riscv/configuration-structure
> > >>
> > >> I hope I described everything properly, please correct me otherwise,
> > >> Abner.
> [Abner]  Yes almost. Thanks Daniel.
> One thing I would like to add,
> If you take a look on SiFive Core IP
> > >> https://www.sifive.com/risc-v-core-ip you can see there are
> > >> different SKUs of RISC-V core. Just take some as exampl,e
> S51 - Single core
> U54 - Single core
> S76 - Single core
> U74- single core
> U54-MC - Multicore which is 4*U54 cores +1*S51 core
> U74-MC - Multicore which is 4*U74 core + 1*S7 core
> 
> Those are the combinations of core IP. Silicon vendor can get those
> core IPs and combine them to the RISC-V processor. To have
> CoreInfoHobLib libraries for each different core (not multicore) to
> build up the core capability is reasonable and makes sense. For the
> multicore, it just pulling the single core CoreInfoHobLib to build
> up the SMBIOS table for the multicore processor. Those libraries
> look duplicate in logically, however only one instance of
> CoreInfoHobLib is built in for multiple identical cores in
> physically view. Maybe we still can move some identical core into
> the core-specific library but it is not worthwhile.

OK, lets start with the *full* diff of E51 and U54 from the
(admittedly slightly dated) devel-riscvplatforms branch:

<<<
--- ./E51/Library/PeiCoreInfoHobLib/CoreInfoHob.c	2020-05-28 12:12:11.211028141 +0100
+++ ./U54/Library/PeiCoreInfoHobLib/CoreInfoHob.c	2020-05-28 12:12:11.211028141 +0100
@@ -7,6 +7,8 @@
 
 **/
 
+#include <IndustryStandard/RiscVOpensbi.h>
+

[LL]
U54 inserts this file in a different location, this is not actual divergence.

//
 // The package level header files this module uses
 //
@@ -19,21 +21,15 @@
 #include <Library/DebugLib.h>
 #include <Library/FirmwareContextProcessorSpecificLib.h>
 #include <Library/HobLib.h>
-#include <Library/PcdLib.h>

[LL]
Interestingly, only E51 actually includes this, but both files *use*
it - this is a bug in U54 caused by the separation.

-#include <IndustryStandard/RiscVOpensbi.h>

[LL]
This is the other end of the files placing this inlude in a different location.

-#include <Library/ResourcePublicationLib.h>
-

[LL]
This header is irrelevant and unused. Present only in E51.

 #include <Library/RiscVEdk2SbiLib.h>
-#include <ProcessorSpecificHobData.h>
-#include <RiscVImpl.h>

[LL]
Included in different location for E51/U54.

 #include <sbi/sbi_hart.h>
-#include <sbi/sbi_scratch.h>
 #include <sbi/sbi_platform.h>
+#include <sbi/sbi_scratch.h>

[LL]
sbi_scratch.h included in different order between platforms.

+#include <RiscVImpl.h>

[LL]
Included in different location for E51/U54 (other end of).

#include <SmbiosProcessorSpecificData.h>
 
 /**
-  Function to build core specific information HOB. RISC-V SMBIOS DXE driver collect
-  this information and build SMBIOS Type44.
+  Function to build core specific information HOB.

[LL]
Different documentation description for the otherwise identical functions.


   @param  ParentProcessorGuid    Parent processor od this core. ParentProcessorGuid
                                  could be the same as CoreGuid if one processor has
@@ -41,19 +37,19 @@
   @param  ParentProcessorUid     Unique ID of pysical processor which owns this core.
   @param  HartId                 Hart ID of this core.
   @param  IsBootHart             TRUE means this is the boot HART.
-  @param  GuidHobData            Pointer to receive   EFI_HOB_GUID_TYPE.
+  @param  GuidHobdata            Pointer to RISC_V_PROCESSOR_SPECIFIC_HOB_DATA.

[LL]
Different capitalisation of input variable and different documentation
for the same parameter in the identical functions. E51 gets the former
correct, U54 the latter.

 
   @return EFI_SUCCESS     The PEIM initialized successfully.
 
 **/
 EFI_STATUS
 EFIAPI
-CreateE51CoreProcessorSpecificDataHob (
+CreateU54CoreProcessorSpecificDataHob (

[LL]
We reach the first *real* difference between the two - the name of the function.
This could have been addressed with different .inf files with
different -D cflags.

   IN EFI_GUID  *ParentProcessorGuid,
   IN UINTN     ParentProcessorUid,
   IN UINTN     HartId,
   IN BOOLEAN   IsBootHart,
-  OUT RISC_V_PROCESSOR_SPECIFIC_HOB_DATA **GuidHobData
+  OUT RISC_V_PROCESSOR_SPECIFIC_HOB_DATA **GuidHobdata

[LL]
Again, difference only in capitalisation.

   )
 {
   RISC_V_PROCESSOR_SPECIFIC_HOB_DATA *CoreGuidHob;
@@ -64,7 +60,7 @@
 
   DEBUG ((DEBUG_INFO, "%a: Entry.\n", __FUNCTION__));
 
-  if (GuidHobData == NULL) {
+  if (GuidHobdata == NULL) {

[LL]
Again, difference only in capitalisation.

     return EFI_INVALID_PARAMETER;
   }
 
@@ -80,7 +76,7 @@
       FirmwareContextHartSpecific,
       ParentProcessorGuid,
       ParentProcessorUid,
-      (EFI_GUID *)PcdGetPtr (PcdSiFiveE51CoreGuid),
+      (EFI_GUID *)PcdGetPtr (PcdSiFiveU54CoreGuid),

[LL]
Different Pcd names.

       HartId,
       IsBootHart,
       &ProcessorSpecDataHob
@@ -109,7 +105,7 @@
   DEBUG ((DEBUG_INFO, "        *MachineImplId = 0x%x\n", ProcessorSpecDataHob.ProcessorSpecificData.MachineImplId.Value64_L));
 
   //
-  // Build GUID HOB for E51 core, this is for SMBIOS type 44
+  // Build GUID HOB for U54 core.

[LL]
Different comments for identical code.

   //
   ProcessorSpecDataHobGuid = PcdGetPtr (PcdProcessorSpecificDataGuidHobGuid);
   CoreGuidHob = (RISC_V_PROCESSOR_SPECIFIC_HOB_DATA *)BuildGuidDataHob (ProcessorSpecDataHobGuid, (VOID *)&ProcessorSpecDataHob, sizeof (RISC_V_PROCESSOR_SPECIFIC_HOB_DATA));
@@ -117,7 +113,7 @@
     DEBUG ((DEBUG_ERROR, "Fail to create GUID HOB of SiFive E51 core.\n"));
     ASSERT (FALSE);
   }
-  *GuidHobData = CoreGuidHob;
+  *GuidHobdata = CoreGuidHob;

[LL]
Again, difference only in capitalisation.

 return EFI_SUCCESS;
 }
 
@@ -135,17 +131,21 @@
 **/
 EFI_STATUS
 EFIAPI
-CreateE51ProcessorSmbiosDataHob (
+CreateU54ProcessorSmbiosDataHob (

[LL]
Difference in name only.

   IN UINTN     ProcessorUid,
-  OUT RISC_V_PROCESSOR_SMBIOS_HOB_DATA **SmbiosHobPtr
+  IN RISC_V_PROCESSOR_SMBIOS_HOB_DATA **SmbiosHobPtr

[LL]
I am going to go out on a limb here and suggest one of the above is
incorrect, and once that is corrected, these two lines would be identical.

   )
 {
   EFI_GUID *GuidPtr;
   RISC_V_PROCESSOR_TYPE4_HOB_DATA ProcessorDataHob;
   RISC_V_PROCESSOR_TYPE7_HOB_DATA L1InstCacheDataHob;
+  RISC_V_PROCESSOR_TYPE7_HOB_DATA L1DataCacheDataHob;
+  RISC_V_PROCESSOR_TYPE7_HOB_DATA L2CacheDataHob;

[LL]
Here is the first functional difference.

   RISC_V_PROCESSOR_SMBIOS_HOB_DATA SmbiosDataHob;
   RISC_V_PROCESSOR_TYPE4_HOB_DATA *ProcessorDataHobPtr;
   RISC_V_PROCESSOR_TYPE7_HOB_DATA *L1InstCacheDataHobPtr;
+  RISC_V_PROCESSOR_TYPE7_HOB_DATA *L1DataCacheDataHobPtr;
+  RISC_V_PROCESSOR_TYPE7_HOB_DATA *L2CacheDataHobPtr;

[LL]
Which could be merged with this inside an ifdef.

   RISC_V_PROCESSOR_SMBIOS_HOB_DATA *SmbiosDataHobPtr;
 
   if (SmbiosHobPtr == NULL) {
@@ -155,7 +155,7 @@
   // Build up SMBIOS type 7 L1 instruction cache record.
   //
   ZeroMem((VOID *)&L1InstCacheDataHob, sizeof (RISC_V_PROCESSOR_TYPE7_HOB_DATA));
-  CopyGuid (&L1InstCacheDataHob.PrcessorGuid, (EFI_GUID *)PcdGetPtr (PcdSiFiveE51CoreGuid));
+  CopyGuid (&L1InstCacheDataHob.PrcessorGuid, (EFI_GUID *)PcdGetPtr (PcdSiFiveU54CoreGuid));

[LL]
Difference in name only.

   L1InstCacheDataHob.ProcessorUid = ProcessorUid;
   L1InstCacheDataHob.SmbiosType7Cache.SocketDesignation = TO_BE_FILLED_BY_VENDOR;
   L1InstCacheDataHob.SmbiosType7Cache.CacheConfiguration = RISC_V_CACHE_CONFIGURATION_CACHE_LEVEL_1 | \
@@ -173,7 +173,59 @@
   GuidPtr = (EFI_GUID *)PcdGetPtr (PcdProcessorSmbiosType7GuidHobGuid);
   L1InstCacheDataHobPtr = (RISC_V_PROCESSOR_TYPE7_HOB_DATA *)BuildGuidDataHob (GuidPtr, (VOID *)&L1InstCacheDataHob, sizeof (RISC_V_PROCESSOR_TYPE7_HOB_DATA));
   if (L1InstCacheDataHobPtr == NULL) {
-    DEBUG ((DEBUG_ERROR, "Fail to create GUID HOB of SiFive E51 core L1 instruction cache RISC_V_PROCESSOR_TYPE7_HOB_DATA.\n"));
+    DEBUG ((DEBUG_ERROR, "Fail to create GUID HOB of SiFive U54 core L1 instruction cache RISC_V_PROCESSOR_TYPE7_HOB_DATA.\n"));

[LL]
Difference in name only.

+    ASSERT (FALSE);
+  }
+

[LL]
Below starts the fundamental difference between the two:

+  //
+  // Build up SMBIOS type 7 L1 data cache record.
+  //
+  ZeroMem((VOID *)&L1DataCacheDataHob, sizeof (RISC_V_PROCESSOR_TYPE7_HOB_DATA));
+  CopyGuid (&L1DataCacheDataHob.PrcessorGuid, (EFI_GUID *)PcdGetPtr (PcdSiFiveU54CoreGuid));
+  L1DataCacheDataHob.ProcessorUid = ProcessorUid;
+  L1DataCacheDataHob.SmbiosType7Cache.SocketDesignation = TO_BE_FILLED_BY_VENDOR;
+  L1DataCacheDataHob.SmbiosType7Cache.CacheConfiguration = RISC_V_CACHE_CONFIGURATION_CACHE_LEVEL_1 | \
+      RISC_V_CACHE_CONFIGURATION_LOCATION_INTERNAL | \
+      RISC_V_CACHE_CONFIGURATION_ENABLED | \
+      RISC_V_CACHE_CONFIGURATION_MODE_UNKNOWN;
+  L1DataCacheDataHob.SmbiosType7Cache.MaximumCacheSize = TO_BE_FILLED_BY_VENDOR;
+  L1DataCacheDataHob.SmbiosType7Cache.InstalledSize = TO_BE_FILLED_BY_VENDOR;
+  L1DataCacheDataHob.SmbiosType7Cache.SupportedSRAMType.Unknown = 1;
+  L1DataCacheDataHob.SmbiosType7Cache.CurrentSRAMType.Unknown = 1;
+  L1DataCacheDataHob.SmbiosType7Cache.CacheSpeed = TO_BE_FILLED_BY_VENDOR;
+  L1DataCacheDataHob.SmbiosType7Cache.ErrorCorrectionType = TO_BE_FILLED_BY_VENDOR;
+  L1DataCacheDataHob.SmbiosType7Cache.SystemCacheType = CacheTypeData;
+  L1DataCacheDataHob.SmbiosType7Cache.Associativity = TO_BE_FILLED_BY_VENDOR;
+  GuidPtr = (EFI_GUID *)PcdGetPtr (PcdProcessorSmbiosType7GuidHobGuid);
+  L1DataCacheDataHobPtr = (RISC_V_PROCESSOR_TYPE7_HOB_DATA *)BuildGuidDataHob (GuidPtr, (VOID *)&L1DataCacheDataHob, sizeof (RISC_V_PROCESSOR_TYPE7_HOB_DATA));
+  if (L1DataCacheDataHobPtr == NULL) {
+    DEBUG ((DEBUG_ERROR, "Fail to create GUID HOB of SiFive U54 core L1 data cache RISC_V_PROCESSOR_TYPE7_HOB_DATA.\n"));
+    ASSERT (FALSE);
+  }
+
+  //
+  // Build up SMBIOS type 7 L2 cache record.
+  //
+  ZeroMem((VOID *)&L2CacheDataHob, sizeof (RISC_V_PROCESSOR_TYPE7_HOB_DATA));
+  CopyGuid (&L2CacheDataHob.PrcessorGuid, (EFI_GUID *)PcdGetPtr (PcdSiFiveU54CoreGuid));
+  L2CacheDataHob.ProcessorUid = ProcessorUid;
+  L2CacheDataHob.SmbiosType7Cache.SocketDesignation = TO_BE_FILLED_BY_VENDOR;
+  L2CacheDataHob.SmbiosType7Cache.CacheConfiguration = RISC_V_CACHE_CONFIGURATION_CACHE_LEVEL_2 | \
+      RISC_V_CACHE_CONFIGURATION_LOCATION_EXTERNAL | \
+      RISC_V_CACHE_CONFIGURATION_ENABLED | \
+      RISC_V_CACHE_CONFIGURATION_MODE_UNKNOWN;
+  L2CacheDataHob.SmbiosType7Cache.MaximumCacheSize = TO_BE_FILLED_BY_VENDOR;
+  L2CacheDataHob.SmbiosType7Cache.InstalledSize = TO_BE_FILLED_BY_VENDOR;
+  L2CacheDataHob.SmbiosType7Cache.SupportedSRAMType.Unknown = 1;
+  L2CacheDataHob.SmbiosType7Cache.CurrentSRAMType.Unknown = 1;
+  L2CacheDataHob.SmbiosType7Cache.CacheSpeed = TO_BE_FILLED_BY_VENDOR;
+  L2CacheDataHob.SmbiosType7Cache.ErrorCorrectionType = TO_BE_FILLED_BY_VENDOR;
+  L2CacheDataHob.SmbiosType7Cache.SystemCacheType = CacheTypeUnified;
+  L2CacheDataHob.SmbiosType7Cache.Associativity = TO_BE_FILLED_BY_VENDOR;
+  GuidPtr = (EFI_GUID *)PcdGetPtr (PcdProcessorSmbiosType7GuidHobGuid);
+  L2CacheDataHobPtr = (RISC_V_PROCESSOR_TYPE7_HOB_DATA *)BuildGuidDataHob (GuidPtr, (VOID *)&L2CacheDataHob, sizeof (RISC_V_PROCESSOR_TYPE7_HOB_DATA));
+  if (L2CacheDataHobPtr == NULL) {
+    DEBUG ((DEBUG_ERROR, "Fail to create GUID HOB of SiFive U54 core L2 cache RISC_V_PROCESSOR_TYPE7_HOB_DATA.\n"));
     ASSERT (FALSE);
   }
 

[LL]
And the funamental difference ends here.

@@ -181,7 +233,7 @@
   // Build up SMBIOS type 4 record.
   //
   ZeroMem((VOID *)&ProcessorDataHob, sizeof (RISC_V_PROCESSOR_TYPE4_HOB_DATA));
-  CopyGuid (&ProcessorDataHob.PrcessorGuid, (EFI_GUID *)PcdGetPtr (PcdSiFiveE51CoreGuid));
+  CopyGuid (&ProcessorDataHob.PrcessorGuid, (EFI_GUID *)PcdGetPtr (PcdSiFiveU54CoreGuid));

[LL]
Differ in name only.

   ProcessorDataHob.ProcessorUid = ProcessorUid;
   ProcessorDataHob.SmbiosType4Processor.Socket = TO_BE_FILLED_BY_VENDOR;
   ProcessorDataHob.SmbiosType4Processor.ProcessorType = CentralProcessor;
@@ -196,7 +248,7 @@
   ProcessorDataHob.SmbiosType4Processor.Status = TO_BE_FILLED_BY_CODE;
   ProcessorDataHob.SmbiosType4Processor.ProcessorUpgrade = TO_BE_FILLED_BY_VENDOR;
   ProcessorDataHob.SmbiosType4Processor.L1CacheHandle = TO_BE_FILLED_BY_RISC_V_SMBIOS_DXE_DRIVER;
-  ProcessorDataHob.SmbiosType4Processor.L2CacheHandle = 0xffff;
+  ProcessorDataHob.SmbiosType4Processor.L2CacheHandle = TO_BE_FILLED_BY_RISC_V_SMBIOS_DXE_DRIVER;

[LL]
Real diff.

   ProcessorDataHob.SmbiosType4Processor.L3CacheHandle = 0xffff;
   ProcessorDataHob.SmbiosType4Processor.SerialNumber = TO_BE_FILLED_BY_CODE;
   ProcessorDataHob.SmbiosType4Processor.AssetTag = TO_BE_FILLED_BY_VENDOR;
@@ -212,24 +264,23 @@
   GuidPtr = (EFI_GUID *)PcdGetPtr (PcdProcessorSmbiosType4GuidHobGuid);
   ProcessorDataHobPtr = (RISC_V_PROCESSOR_TYPE4_HOB_DATA *)BuildGuidDataHob (GuidPtr, (VOID *)&ProcessorDataHob, sizeof (RISC_V_PROCESSOR_TYPE4_HOB_DATA));
   if (ProcessorDataHobPtr == NULL) {
-    DEBUG ((DEBUG_ERROR, "Fail to create GUID HOB of SiFive E51 core RISC_V_PROCESSOR_TYPE4_HOB_DATA.\n"));
+    DEBUG ((DEBUG_ERROR, "Fail to create GUID HOB of SiFive U54 core RISC_V_PROCESSOR_TYPE4_HOB_DATA.\n"));

[LL]
Difference in name only.

     ASSERT (FALSE);
   }
 
   ZeroMem((VOID *)&SmbiosDataHob, sizeof (RISC_V_PROCESSOR_SMBIOS_HOB_DATA));
   SmbiosDataHob.Processor = ProcessorDataHobPtr;
   SmbiosDataHob.L1InstCache = L1InstCacheDataHobPtr;
-  SmbiosDataHob.L1DataCache = NULL;
-  SmbiosDataHob.L2Cache = NULL;
+  SmbiosDataHob.L1DataCache = L1DataCacheDataHobPtr;
+  SmbiosDataHob.L2Cache = L2CacheDataHobPtr;

[LL]
Real diff.

   SmbiosDataHob.L3Cache = NULL;
   GuidPtr = (EFI_GUID *)PcdGetPtr (PcdProcessorSmbiosGuidHobGuid);
   SmbiosDataHobPtr = (RISC_V_PROCESSOR_SMBIOS_HOB_DATA *)BuildGuidDataHob (GuidPtr, (VOID *)&SmbiosDataHob, sizeof (RISC_V_PROCESSOR_SMBIOS_HOB_DATA));
   if (SmbiosDataHobPtr == NULL) {
-    DEBUG ((DEBUG_ERROR, "Fail to create GUID HOB of SiFive E51 core RISC_V_PROCESSOR_SMBIOS_HOB_DATA.\n"));
+    DEBUG ((DEBUG_ERROR, "Fail to create GUID HOB of SiFive U54 core RISC_V_PROCESSOR_SMBIOS_HOB_DATA.\n"));

[LL]
Difference in name only.

     ASSERT (FALSE);
   }
   *SmbiosHobPtr = SmbiosDataHobPtr;
   return EFI_SUCCESS;
 }
 
-

>>>

The meat of the difference between these two is less than 20% of the
lines of code in each file - and it is mutually exclusive, not some
horrific tangle of interdependencies.

The story with the difference between U54 and U54MCCoreplex isn't much
better, only works along a different axis.

"It isn't worthwhile" in an open source project isn't a question of
"how quickly can I create *one* new platform by copying instead of
refactoring/reusing", but a judgement call between:
- How many mistakes do I risk inserting while editing a new file as
  opposed to being directly able to see the differences I have caused
  while editing an existing file.
- How much do I increase reviewing effort by doing this?
- How much do I increase ongoing maintainership (or affect quality) by
  requiring bugs to be fixed in multiple places instead of one.

Not to mention:
- How many common pattern that could be broken out into common helper
  libraries do we miss when we need to compare every SoC/platform
  combination ever created, as opposed to being able to look at least
  at implementations covering families.

If it isn't important enough to take that into consideration, it
isn't important enough to upstream the SMBIOS support.

/
    Leif

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

* Re: [edk2-devel] [PATCH v2 3/3] ProcessorPkg/Library: Add RiscVEdk2SbiLib
  2020-05-20 18:27   ` Leif Lindholm
@ 2020-05-29 12:43     ` Daniel Schaefer
  2020-05-29 13:15       ` Leif Lindholm
  0 siblings, 1 reply; 19+ messages in thread
From: Daniel Schaefer @ 2020-05-29 12:43 UTC (permalink / raw)
  To: devel, leif; +Cc: Abner Chang, Gilbert Chen, Michael D Kinney

Hi Leif,

thanks for this super careful review!
Comments and one question inline.

- Daniel

On 5/20/20 8:27 PM, Leif Lindholm wrote:
> On Fri, May 15, 2020 at 15:39:37 +0200, Daniel Schaefer wrote:
>> Library provides interfaces to invoke SBI extensions.
>>
>> Signed-off-by: Daniel Schaefer <daniel.schaefer@hpe.com>
>>
>> Cc: Abner Chang <abner.chang@hpe.com>
>> Cc: Gilbert Chen <gilbert.chen@hpe.com>
>> Cc: Michael D Kinney <michael.k.kinney@intel.com>
>> Cc: Leif Lindholm <leif@nuviainc.com>
>> ---
>>   Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.inf |  28 +
>>   Silicon/RISC-V/ProcessorPkg/Include/IndustryStandard/RiscVOpensbi.h     |  43 +-
>>   Silicon/RISC-V/ProcessorPkg/Include/Library/RiscVEdk2SbiLib.h           | 631 ++++++++++++++++
>>   Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.c   | 789 ++++++++++++++++++++
>>   4 files changed, 1466 insertions(+), 25 deletions(-)
>>
>> 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/IndustryStandard/RiscVOpensbi.h b/Silicon/RISC-V/ProcessorPkg/Include/IndustryStandard/RiscVOpensbi.h
>> index c5c0bd6d9b01..18a85e2238d2 100644
>> --- a/Silicon/RISC-V/ProcessorPkg/Include/IndustryStandard/RiscVOpensbi.h
>> +++ b/Silicon/RISC-V/ProcessorPkg/Include/IndustryStandard/RiscVOpensbi.h
>> @@ -10,42 +10,35 @@
>>   #ifndef EDK2_SBI_H_
>>   #define EDK2_SBI_H_
>>   
>> -#include <include/sbi/riscv_asm.h> // Reference to header file in opensbi
>>   #include <RiscVImpl.h>
>> +#include <sbi/riscv_asm.h> // Reference to header file in opensbi
> 
> I don't see anything in *this* patch requiring this change - does this
> belong squashed into 2/3?

Yes... I'll fix it in the next patchset.

> 
>> +#include <sbi/sbi_ecall_interface.h>
>> +#include <sbi/sbi_error.h>
>>   #include <sbi/sbi_types.h>  // Reference to header file wrapper
>>   
>> -#define SBI_SUCCESS                    0
>> -#define SBI_ERR_FAILED                -1
>> -#define SBI_ERR_NOT_SUPPORTED         -2
>> -#define SBI_ERR_INVALID_PARAM         -3
>> -#define SBI_ERR_DENIED                -4
>> -#define SBI_ERR_INVALID_ADDRESS       -5
>> -#define SBI_ERR_ALREADY_AVAILABLE     -6
>> +// Translation from OpenSBI constants to SBI names
>> +#define SBI_SUCCESS               SBI_OK
>> +#define SBI_ERR_FAILED            SBI_EFAIL
>> +#define SBI_ERR_NOT_SUPPORTED     SBI_ENOTSUPP
>> +#define SBI_ERR_INVALID_PARAM     SBI_EINVAL
>> +#define SBI_ERR_DENIED            SBI_DENIED
>> +#define SBI_ERR_INVALID_ADDRESS   SBI_INVALID_ADDR
>> +#define SBI_ERR_ALREADY_AVAILABLE -6
> 
> Ah, right, see my confusion from reviewing 2/3.
> Please move this to 2/3, adding a comment on why
> SBI_ERR_ALREADY_AVAILABLE needs to be locally defined here.

See above, comment added.

> 
>>   
>> -#define SBI_BASE_EXT                   0x10
>> -#define SBI_HSM_EXT                    0x48534D
>> -#define SBI_TIME_EXT                   0x54494D45
>> -#define SBI_IPI_EXT                    0x735049
>> -#define SBI_RFNC_EXT                   0x52464E43
> 
> Why do we add these in 2/3 only to delete them again here?

See above.

> 
>> +// Included in OpenSBI 0.7
>> +// Can be removed, once we upgrade
>> +#define SBI_EXT_HSM               0x48534D
>> +#define SBI_EXT_HSM_HART_START    0x0
>> +#define SBI_EXT_HSM_HART_STOP     0x1
>> +#define SBI_EXT_HSM_HART_GET_STATUS 0x2
>>   
>>   //
>>   // Below two definitions should be defined in OpenSBI.
>> +// Submitted to upstream, waiting for merge and release.
> 
> Good call out. This isn't pretty, but it is the right thing to do.
> 
>>   //
>>   #define SBI_EXT_FIRMWARE_CODE_BASE_START 0x0A000000
>>   #define SBI_EXT_FIRMWARE_CODE_BASE_END   0x0AFFFFFF
>>   
>> -#define SBI_GET_SPEC_VERSION_FUNC      0
>> -#define SBI_GET_IMPL_ID_FUNC           1
>> -#define SBI_GET_IMPL_VERSION_FUNC      2
>> -#define SBI_PROBE_EXTENSION_FUNC       3
>> -#define SBI_GET_MVENDORID_FUNC         4
>> -#define SBI_GET_MARCHID_FUNC           5
>> -#define SBI_GET_MIMPID_FUNC            6
>> -
>> -#define SBI_HART_START_FUNC            0
>> -#define SBI_HART_STOP_FUNC             1
>> -#define SBI_HART_GET_STATUS_FUNC       2
>> -
> 
> Why do we add these in 2/3 only to delete them again here?

See above.

> 
>>   #define RISC_V_MAX_HART_SUPPORTED 16
>>   
>>   typedef
>> 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..cf77814e3bbc
>> --- /dev/null
>> +++ b/Silicon/RISC-V/ProcessorPkg/Include/Library/RiscVEdk2SbiLib.h
>> @@ -0,0 +1,631 @@
>> +/** @file Defines the PPIs to let PEIMs call SBI
>> +
>> +Copyright (c) 2020, Hewlett Packard Development LP. All rights reserved.<BR>
>> +
>> +SPDX-License-Identifier: BSD-2-Clause-Patent
>> +
>> +**/
>> +
>> +#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.
>> +//
>> +struct sbiret {
> 
> This struct appears only to be referenceed outside the opensbi
> submodule, so name should conform to EDK2 coding style (and preferably
> with a typedef).

Okidoki.

> 
>> +  long error;   ///< SBI status code
>> +  long value;   ///< Value returned
> 
> This looks like a maintenance hazard (means different things to GCC
> and VS for example). Can we use UINT32?

I'll use UINTN because it's bigger than 32bits on RISCV64

> 
>> +};
>> +
>> +#define SbiCall0(ext_id, func_id) \
>> +  SbiCall(ext_id, func_id, 0, 0, 0, 0, 0, 0)
>> +#define SbiCall1(ext_id, func_id, arg0) \
>> +  SbiCall(ext_id, func_id, arg0, 0, 0, 0, 0, 0)
>> +#define SbiCall2(ext_id, func_id, arg0, arg1) \
>> +  SbiCall(ext_id, func_id, arg0, arg1, 0, 0, 0, 0)
>> +#define SbiCall3(ext_id, func_id, arg0, arg1, arg2) \
>> +  SbiCall(ext_id, func_id, arg0, arg1, arg2, 0, 0, 0)
>> +#define SbiCall4(ext_id, func_id, arg0, arg1, arg2, arg3) \
>> +  SbiCall(ext_id, func_id, arg0, arg1, arg2, arg3, 0, 0)
>> +#define SbiCall5(ext_id, func_id, arg0, arg1, arg2, arg3, arg4) \
>> +  SbiCall(ext_id, func_id, arg0, arg1, arg2, arg3, arg4, 0)
>> +#define SbiCall6(ext_id, func_id, arg0, arg1, arg2, arg3, arg4, arg5) \
>> +  SbiCall(ext_id, func_id, arg0, arg1, arg2, arg3, arg4, arg5)
> 
> Ugh. This looks way too much like pre-EFIAPI x86 code.
> 
> Is this a pattern used across multiple codebases?
> If not, could we make this a simple argc/argv instead and do the
> unpacking inside SbiCall()? Hmm, maybe that would make the call sites
> even worse.
> 
> If we need to keep these, coding style says all macros should use
> UPPERCASE_AND_UNDERSCORES.
> 

Yeah, I think argc/argv is going to make the callsites worse. What about 
vararg, like I used in SbiVendorCall in
Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.c
? Or does that have a performance impact? Maybe an architecture specific 
one?

>> +
>> +/**
>> +  EDK2 SbiCall to invoke SBI extensions.
>> +
>> +  @param[in] ext_id   Sbi extension ID.
>> +  @param[in] func_id  Sbi functions ID.
>> +  @param[in] arg0     Arg0 to function.
>> +  @param[in] arg1     Arg1 to function.
>> +  @param[in] arg2     Arg2 to function.
>> +  @param[in] arg3     Arg3 to function.
>> +  @param[in] arg4     Arg4 to function.
>> +  @param[in] arg5     Arg5 to function.
>> +
>> +  @retval  Returns sbiret structure.
>> +
>> +**/
>> +inline
>> +EFIAPI
>> +struct sbiret SbiCall(UINTN ext_id, UINTN func_id, UINTN arg0, UINTN arg1,
> 
> Function name starts in the first column of a new line.
> But please drop the entire forward-declaration.
> 
>> +                           UINTN arg2, UINTN arg3, UINTN arg4, UINTN arg5)
>> +__attribute__((always_inline));
>> +
>> +/**
>> +  EDK2 SbiCall to invoke SBI extensions.
>> +
>> +  @param[in] ext_id   Sbi extension ID.
>> +  @param[in] func_id  Sbi functions ID.
>> +  @param[in] arg0     Arg0 to function.
>> +  @param[in] arg1     Arg1 to function.
>> +  @param[in] arg2     Arg2 to function.
>> +  @param[in] arg3     Arg3 to function.
>> +  @param[in] arg4     Arg4 to function.
>> +  @param[in] arg5     Arg5 to function.
>> +
>> +  @retval  Returns sbiret structure.
>> +
>> +**/
>> +inline
> 
> Technically, the coding standard bans function definitions in header
> files[1]. If you can give me a good reason for why this function
> should be here, I may consider to consider making an exception.
> If I do, make it just STATIC (let the compiler worry about the
> inlining).

When I first wrote this library, it was necessary but it's not anymore.
I moved it to the .c file, because it's not used anywhere else.

> 
> If it is just by habit from other projects of putting helper functions
> into headers, please move them to a .c file.
> 
> [1] https://edk2-docs.gitbook.io/edk-ii-c-coding-standards-specification/5_source_files/53_include_files#5-3-7-include-files-shall-not-generate-code-or-define-data-variables
> 
>> +EFIAPI
>> +struct sbiret SbiCall(UINTN ext_id, UINTN func_id, UINTN arg0, UINTN arg1,
>> +                           UINTN arg2, UINTN arg3, UINTN arg4, UINTN arg5) {
>> +    register uintptr_t a0 asm ("a0") = (uintptr_t)(arg0);
>> +    register uintptr_t a1 asm ("a1") = (uintptr_t)(arg1);
>> +    register uintptr_t a2 asm ("a2") = (uintptr_t)(arg2);
>> +    register uintptr_t a3 asm ("a3") = (uintptr_t)(arg3);
>> +    register uintptr_t a4 asm ("a4") = (uintptr_t)(arg4);
>> +    register uintptr_t a5 asm ("a5") = (uintptr_t)(arg5);
>> +    register uintptr_t a6 asm ("a6") = (uintptr_t)(func_id);
>> +    register uintptr_t a7 asm ("a7") = (uintptr_t)(ext_id);
> 
> I would *prefer* UINTN over uintptr_t here.
> 
>> +    asm volatile ("ecall" \
>> +         : "+r" (a0) \
> 
> Isn't a1 also an input/output operand here?

Yes, you're right.

> 
>> +         : "r" (a1), "r" (a2), "r" (a3), "r" (a4), "r" (a5), "r" (a6), "r" (a7) \
>> +         : "memory"); \
>> +    struct sbiret ret = { a0, a1 };
>> +    return ret;
> 
> CamelCase naming.

Will change it everywhere.

> 
>> +}
>> +
>> +/**
>> +  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 (
> 
> Uppercase V for CamelCase (and matching the argument name below).

Oops.

> 
>> +  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.
> 
> What is an MvendorId? MachineVendorId?
> Even if an official register name, I would prefer function and
> arguments to be given proper descriptive CamelCase names.

Yes, it's the official register name. Alright, will change it.

> 
>> +
>> +  @param[out] MvendorId            The CPU's vendor ID.
>> +**/
>> +VOID
>> +EFIAPI
>> +SbiGetMvendorId (
>> +  OUT UINTN                       *MvendorId
>> +  );
>> +
>> +/**
>> +  Get the CPU's architecture ID
>> +
>> +  Reads the marchid CSR.
>> +
>> +  @param[out] MarchId              The CPU's architecture ID.
> 
> This should probebly be MArchId (or MachineArchId?)?

Yes, changed it to MachineArchId.

> 
>> +**/
>> +VOID
>> +EFIAPI
>> +SbiGetMarchId (
>> +  OUT UINTN                       *MarchId
>> +  );
>> +
>> +/**
>> +  Get the CPU's implementation ID
>> +
>> +  Reads the mimpid CSR.
>> +
>> +  @param[out] MimpId               The CPU's implementation ID.
> 
> Above "Impl" is used for "Impelentation". *Strictly* speaking, "Impl"
> doesn't fall in the pretty small group of abbreviations permitted
> without a glossary section in the source file, but it's clear enough
> to me I'll let it slip.
> The same cannot be said for "Imp".
> MachineImplId?

Sounds good. Should it be added to the permitted abbreviations?
If I spell it out fully here, it becomes quite long.

> 
>> +**/
>> +VOID
>> +EFIAPI
>> +SbiGetMimpId (
>> +  OUT UINTN                       *Mimpid
>> +  );
>> +
>> +/**
>> +  Politely ask the SBI to start a given hart.
> 
> I know hart is a pretty fundamental concept in RISC-V.
> Still, I would request to have it added in a glossary section in the
> top-of-file comment header.

Cool, didn't know that existed! Will do.

> 
>> +
>> +  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 (
> 
> (With great effort, I suppress a Mötley Crüe joke.)
> 
>> +  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 StimeValue.
> 
> What does the S stand for in Stime?

That's what they call it in the spec: stime_value.
I guess it stands for supervisor. Should we change it to just `Time`?

> 
>> +
>> +  To clear the timer without scheduling a timer event, set StimeValue to a
>> +  practically infinite value or mask the timer interrupt by clearing sie.STIE.
>> +
>> +  @param[in]  StimeValue           The time offset to the next scheduled timer interrupt.
>> +**/
>> +VOID
>> +EFIAPI
>> +SbiSetTimer (
>> +  IN  UINT64                         StimeValue
>> +  );
>> +
>> +///
>> +/// 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 struct sbi_scratch             **ScratchSpace
> 
> Could we add a typedef for "struct sbi_scratch" to make the code more
> style compliant?

Yeah, will do. Then I'll also do one for `struct sbi_platform`, which is 
used in the .c file.

> 
>> +  );
>> +
>> +/**
>> +  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 struct 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..bbe006a78af8
>> --- /dev/null
>> +++ b/Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.c
>> @@ -0,0 +1,789 @@
>> +/** @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
>> +**/
>> +
>> +#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_platform.h>
>> +#include <sbi/sbi_init.h>
>> +
>> +/**
>> +  Translate SBI error code to EFI status.
>> +
>> +  @param[in] SbiError   SBI error code
>> +  @retval EFI_STATUS
>> +**/
>> +
>> +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 libraary 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
>> +  )
>> +{
>> +  struct sbiret ret = SbiCall0 (SBI_EXT_BASE, SBI_EXT_BASE_GET_SPEC_VERSION);
>> +
>> +  if (!ret.error) {
>> +    *SpecVersion = (UINTN) ret.value;
>> +  }
>> +
>> +  //return TranslateError(ret.error);
>> +}
>> +
>> +/**
>> +  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
>> +  )
>> +{
>> +  struct sbiret ret = SbiCall0 (SBI_EXT_BASE, SBI_EXT_BASE_GET_IMP_ID);
>> +  *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
>> +  )
>> +{
>> +  struct sbiret ret = SbiCall0 (SBI_EXT_BASE, SBI_EXT_BASE_GET_IMP_VERSION);
>> +  *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
>> +  )
>> +{
>> +  struct sbiret ret = SbiCall0 (SBI_EXT_BASE, SBI_EXT_BASE_PROBE_EXT);
>> +  *ProbeResult = (UINTN) ret.value;
>> +}
>> +
>> +/**
>> +  Get the CPU's vendor ID
>> +
>> +  Reads the mvendorid CSR.
>> +
>> +  @param[out] MvendorId            The CPU's vendor ID.
>> +**/
>> +VOID
>> +EFIAPI
>> +SbiGetMvendorId (
>> +  OUT UINTN                       *MvendorId
>> +  )
>> +{
>> +  struct sbiret ret = SbiCall0 (SBI_EXT_BASE, SBI_EXT_BASE_GET_MVENDORID);
>> +  *MvendorId = (UINTN) ret.value;
>> +}
>> +
>> +/**
>> +  Get the CPU's vendor ID
>> +
>> +  Reads the mvendorid CSR.
>> +
>> +  @param[out] MvendorId            The CPU's vendor ID.
>> +**/
>> +VOID
>> +EFIAPI
>> +SbiGetMarchId (
>> +  OUT UINTN                       *MarchId
>> +  )
>> +{
>> +  struct sbiret ret = SbiCall0 (SBI_EXT_BASE, SBI_EXT_BASE_GET_MARCHID);
>> +  *MarchId = (UINTN) ret.value;
>> +}
>> +
>> +/**
>> +  Get the CPU's architecture ID
>> +
>> +  Reads the marchid CSR.
>> +
>> +  @param[out] MarchId              The CPU's architecture ID.
>> +**/
>> +VOID
>> +EFIAPI
>> +SbiGetMimpId (
>> +  OUT UINTN                       *MimpId
>> +  )
>> +{
>> +  struct sbiret ret = SbiCall0 (SBI_EXT_BASE, SBI_EXT_BASE_GET_MIMPID);
>> +  *MimpId = (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
>> +  )
>> +{
>> +  struct sbiret ret = SbiCall3 (SBI_EXT_HSM,
>> +                                SBI_EXT_HSM_HART_START,
>> +                                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 (
>> +  )
>> +{
>> +  struct sbiret Ret = SbiCall0 (SBI_EXT_HSM, SBI_EXT_HSM_HART_STOP);
>> +  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
>> +  )
>> +{
>> +  struct sbiret ret = SbiCall1 (SBI_EXT_HSM, SBI_EXT_HSM_HART_GET_STATUS, HartId);
>> +
>> +  if (!ret.error) {
>> +    *HartStatus = (UINTN) ret.value;
>> +  }
>> +
>> +  return TranslateError(ret.error);
>> +}
>> +
>> +/**
>> +  Clear pending timer interrupt bit and set timer for next event after StimeValue.
>> +
>> +  To clear the timer without scheduling a timer event, set StimeValue to a
>> +  practically infinite value or mask the timer interrupt by clearing sie.STIE.
>> +
>> +  @param[in]  StimeValue           The time offset to the next scheduled timer interrupt.
>> +**/
>> +VOID
>> +EFIAPI
>> +SbiSetTimer (
>> +  IN  UINT64                         StimeValue
>> +  )
>> +{
>> +  SbiCall1 (SBI_EXT_TIME, SBI_EXT_TIME_SET_TIMER, StimeValue);
>> +}
>> +
>> +EFI_STATUS
>> +EFIAPI
>> +SbiSendIpi (
>> +  IN  UINTN                         *HartMask,
>> +  IN  UINTN                          HartMaskBase
>> +  )
>> +{
>> +  struct sbiret ret = SbiCall2 (SBI_EXT_IPI,
>> +                                SBI_EXT_IPI_SEND_IPI,
>> +                                (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
>> +  )
>> +{
>> +  struct sbiret ret = SbiCall2 (SBI_EXT_RFENCE,
>> +                                SBI_EXT_RFENCE_REMOTE_FENCE_I,
>> +                                (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
>> +  )
>> +{
>> +  struct sbiret ret = SbiCall4 (SBI_EXT_RFENCE,
>> +                                SBI_EXT_RFENCE_REMOTE_SFENCE_VMA,
>> +                                (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
>> +  )
>> +{
>> +  struct sbiret ret = SbiCall5 (SBI_EXT_RFENCE,
>> +                                SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID,
>> +                                (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
>> +  )
>> +{
>> +  struct sbiret ret = SbiCall5 (SBI_EXT_RFENCE,
>> +                                SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA,
>> +                                (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
>> +  )
>> +{
>> +  struct sbiret ret = SbiCall4 (SBI_EXT_RFENCE,
>> +                                SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA_VMID,
>> +                                (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
>> +  )
>> +{
>> +  struct sbiret ret = SbiCall5 (SBI_EXT_RFENCE,
>> +                                SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA,
>> +                                (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
>> +  )
>> +{
>> +  struct sbiret ret = SbiCall4 (SBI_EXT_RFENCE,
>> +                                SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA_ASID,
>> +                                (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.
>> +
>> +  @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,
>> +  ...
>> +  )
>> +{
>> +    struct sbiret ret;
>> +    VA_LIST Args;
>> +    VA_START(Args, NumArgs);
>> +
>> +    ASSERT (ExtensionId >= 0x09000000 && ExtensionId <= 0x09FFFFFF);
>> +
>> +    switch (NumArgs) {
>> +      case 0:
>> +        ret = SbiCall0 (ExtensionId, FunctionId);
>> +        break;
>> +      case 1:
>> +        ret = SbiCall1 (ExtensionId, FunctionId, VA_ARG(Args, UINTN));
>> +        break;
>> +      case 2:
>> +        ret = SbiCall2 (ExtensionId, FunctionId, VA_ARG(Args, UINTN), VA_ARG(Args, UINTN));
>> +        break;
>> +      case 3:
>> +        ret = SbiCall3 (ExtensionId, FunctionId, VA_ARG(Args, UINTN), VA_ARG(Args, UINTN), VA_ARG(Args, UINTN));
>> +        break;
>> +      case 4:
>> +        ret = SbiCall4 (ExtensionId, FunctionId, VA_ARG(Args, UINTN), VA_ARG(Args, UINTN), VA_ARG(Args, UINTN), VA_ARG(Args, UINTN));
>> +        break;
>> +      case 5:
>> +        ret = SbiCall5 (ExtensionId, FunctionId, VA_ARG(Args, UINTN), VA_ARG(Args, UINTN), VA_ARG(Args, UINTN), VA_ARG(Args, UINTN), VA_ARG(Args, UINTN));
>> +        break;
>> +      case 6:
>> +        ret = SbiCall6 (ExtensionId, FunctionId, 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 struct sbi_scratch             **ScratchSpace
>> +  )
>> +{
>> +  struct sbiret ret = SbiCall0 (SBI_EDK2_FW_EXT, SBI_EXT_FW_MSCRATCH_FUNC);
>> +
>> +  if (!ret.error) {
>> +    *ScratchSpace = (struct 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 struct sbi_scratch             **ScratchSpace
>> +  )
>> +{
>> +  struct sbiret ret = SbiCall1 (SBI_EDK2_FW_EXT,
>> +                                SBI_EXT_FW_MSCRATCH_HARTID_FUNC,
>> +                                HartId);
>> +
>> +  if (!ret.error) {
>> +    *ScratchSpace = (struct 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
>> +  )
>> +{
>> +  struct sbi_scratch *ScratchSpace;
>> +  struct sbi_platform *SbiPlatform;
>> +  struct sbiret ret = SbiCall0 (SBI_EDK2_FW_EXT, SBI_EXT_FW_MSCRATCH_FUNC);
>> +
>> +  if (!ret.error) {
>> +    ScratchSpace = (struct sbi_scratch *) ret.value;
>> +    SbiPlatform = (struct 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
>> +  )
>> +{
>> +  struct sbi_scratch *ScratchSpace;
>> +  struct sbi_platform *SbiPlatform;
>> +  struct sbiret ret = SbiCall0 (SBI_EDK2_FW_EXT, SBI_EXT_FW_MSCRATCH_FUNC);
>> +
>> +  if (!ret.error) {
>> +    ScratchSpace = (struct sbi_scratch *) ret.value;
>> +    SbiPlatform = (struct sbi_platform *) sbi_platform_ptr(ScratchSpace);
>> +    SbiPlatform->firmware_context = (long unsigned int) FirmwareContext;
> 
> UINT64?

UINTN for compatibility with 32bits.

> 
> /
>      Leif
> 
>> +  }
>> +
>> +  return EFI_SUCCESS;
>> +}
>> -- 
>> 2.26.1
>>
> 
> 
> 

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

* Re: [edk2-devel] [PATCH v2 3/3] ProcessorPkg/Library: Add RiscVEdk2SbiLib
  2020-05-29 12:43     ` [edk2-devel] " Daniel Schaefer
@ 2020-05-29 13:15       ` Leif Lindholm
  0 siblings, 0 replies; 19+ messages in thread
From: Leif Lindholm @ 2020-05-29 13:15 UTC (permalink / raw)
  To: Daniel Schaefer; +Cc: devel, Abner Chang, Gilbert Chen, Michael D Kinney

On Fri, May 29, 2020 at 14:43:43 +0200, Daniel Schaefer wrote:
> Hi Leif,
> 
> thanks for this super careful review!
> Comments and one question inline.
> 
> - Daniel
> 
> On 5/20/20 8:27 PM, Leif Lindholm wrote:
> > On Fri, May 15, 2020 at 15:39:37 +0200, Daniel Schaefer wrote:
> > > Library provides interfaces to invoke SBI extensions.
> > > 
> > > Signed-off-by: Daniel Schaefer <daniel.schaefer@hpe.com>
> > > 
> > > Cc: Abner Chang <abner.chang@hpe.com>
> > > Cc: Gilbert Chen <gilbert.chen@hpe.com>
> > > Cc: Michael D Kinney <michael.k.kinney@intel.com>
> > > Cc: Leif Lindholm <leif@nuviainc.com>
> > > ---
> > >   Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.inf |  28 +
> > >   Silicon/RISC-V/ProcessorPkg/Include/IndustryStandard/RiscVOpensbi.h     |  43 +-
> > >   Silicon/RISC-V/ProcessorPkg/Include/Library/RiscVEdk2SbiLib.h           | 631 ++++++++++++++++
> > >   Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.c   | 789 ++++++++++++++++++++
> > >   4 files changed, 1466 insertions(+), 25 deletions(-)
> > > 

> > > 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..cf77814e3bbc
> > > --- /dev/null
> > > +++ b/Silicon/RISC-V/ProcessorPkg/Include/Library/RiscVEdk2SbiLib.h
> > 

> > > +  long error;   ///< SBI status code
> > > +  long value;   ///< Value returned
> > 
> > This looks like a maintenance hazard (means different things to GCC
> > and VS for example). Can we use UINT32?
> 
> I'll use UINTN because it's bigger than 32bits on RISCV64

Oh, then definitely that, yes.

> > 
> > > +};
> > > +
> > > +#define SbiCall0(ext_id, func_id) \
> > > +  SbiCall(ext_id, func_id, 0, 0, 0, 0, 0, 0)
> > > +#define SbiCall1(ext_id, func_id, arg0) \
> > > +  SbiCall(ext_id, func_id, arg0, 0, 0, 0, 0, 0)
> > > +#define SbiCall2(ext_id, func_id, arg0, arg1) \
> > > +  SbiCall(ext_id, func_id, arg0, arg1, 0, 0, 0, 0)
> > > +#define SbiCall3(ext_id, func_id, arg0, arg1, arg2) \
> > > +  SbiCall(ext_id, func_id, arg0, arg1, arg2, 0, 0, 0)
> > > +#define SbiCall4(ext_id, func_id, arg0, arg1, arg2, arg3) \
> > > +  SbiCall(ext_id, func_id, arg0, arg1, arg2, arg3, 0, 0)
> > > +#define SbiCall5(ext_id, func_id, arg0, arg1, arg2, arg3, arg4) \
> > > +  SbiCall(ext_id, func_id, arg0, arg1, arg2, arg3, arg4, 0)
> > > +#define SbiCall6(ext_id, func_id, arg0, arg1, arg2, arg3, arg4, arg5) \
> > > +  SbiCall(ext_id, func_id, arg0, arg1, arg2, arg3, arg4, arg5)
> > 
> > Ugh. This looks way too much like pre-EFIAPI x86 code.
> > 
> > Is this a pattern used across multiple codebases?
> > If not, could we make this a simple argc/argv instead and do the
> > unpacking inside SbiCall()? Hmm, maybe that would make the call sites
> > even worse.
> > 
> > If we need to keep these, coding style says all macros should use
> > UPPERCASE_AND_UNDERSCORES.
> > 
> 
> Yeah, I think argc/argv is going to make the callsites worse. What about
> vararg, like I used in SbiVendorCall in
> Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.c
> ? Or does that have a performance impact? Maybe an architecture specific
> one?

It *might* have a performance impact, but I'd be astonished if it is
noticeable.

Yes please, if you don't mind, I think that would really improve the
readability.


> > > +/**
> > > +  Get the CPU's vendor ID
> > > +
> > > +  Reads the mvendorid CSR.
> > 
> > What is an MvendorId? MachineVendorId?
> > Even if an official register name, I would prefer function and
> > arguments to be given proper descriptive CamelCase names.
> 
> Yes, it's the official register name. Alright, will change it.

If it *is* the official register name, adding it to the glossary
section is also OK.

> > > +**/
> > > +VOID
> > > +EFIAPI
> > > +SbiGetMarchId (
> > > +  OUT UINTN                       *MarchId
> > > +  );
> > > +
> > > +/**
> > > +  Get the CPU's implementation ID
> > > +
> > > +  Reads the mimpid CSR.
> > > +
> > > +  @param[out] MimpId               The CPU's implementation ID.
> > 
> > Above "Impl" is used for "Impelentation". *Strictly* speaking, "Impl"
> > doesn't fall in the pretty small group of abbreviations permitted
> > without a glossary section in the source file, but it's clear enough
> > to me I'll let it slip.
> > The same cannot be said for "Imp".
> > MachineImplId?
> 
> Sounds good. Should it be added to the permitted abbreviations?
> If I spell it out fully here, it becomes quite long.

I'm OK with Impl. We should consider adding it to the list.

> > > +**/
> > > +EFI_STATUS
> > > +EFIAPI
> > > +SbiHartGetStatus (
> > > +  IN  UINTN                          HartId,
> > > +  OUT UINTN                         *HartStatus
> > > +  );
> > > +
> > > +///
> > > +/// Timer extension
> > > +///
> > > +
> > > +/**
> > > +  Clear pending timer interrupt bit and set timer for next event after StimeValue.
> > 
> > What does the S stand for in Stime?
> 
> That's what they call it in the spec: stime_value.
> I guess it stands for supervisor. Should we change it to just `Time`?

That would be a valid thing to do.
Another would be to add it to the glossary.

> > > +  if (!ret.error) {
> > > +    ScratchSpace = (struct sbi_scratch *) ret.value;
> > > +    SbiPlatform = (struct sbi_platform *) sbi_platform_ptr(ScratchSpace);
> > > +    SbiPlatform->firmware_context = (long unsigned int) FirmwareContext;
> > 
> > UINT64?
> 
> UINTN for compatibility with 32bits.

Of course.

Thanks!

/
    Leif

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

* Re: [edk2-devel] [PATCH v2 0/3] New RISC-V Patches - Why in edk2-platforms
  2020-05-28 11:54           ` Leif Lindholm
@ 2020-05-29 14:41             ` Abner Chang
       [not found]             ` <b55ee3ec-74de-532e-01f7-bd24a327d00b@hpe.com>
  1 sibling, 0 replies; 19+ messages in thread
From: Abner Chang @ 2020-05-29 14:41 UTC (permalink / raw)
  To: Leif Lindholm
  Cc: Schaefer, Daniel (DualStudy), devel@edk2.groups.io, Chen, Gilbert,
	Kinney, Michael D, Bret.Barkelew@microsoft.com,
	sean.brogan@microsoft.com



> -----Original Message-----
> From: Leif Lindholm [mailto:leif@nuviainc.com]
> Sent: Thursday, May 28, 2020 7:55 PM
> To: Chang, Abner (HPS SW/FW Technologist) <abner.chang@hpe.com>
> Cc: Schaefer, Daniel (DualStudy) <daniel.schaefer@hpe.com>;
> devel@edk2.groups.io; Chen, Gilbert <gilbert.chen@hpe.com>; Kinney,
> Michael D <michael.d.kinney@intel.com>; Bret.Barkelew@microsoft.com;
> sean.brogan@microsoft.com
> Subject: Re: [edk2-devel] [PATCH v2 0/3] New RISC-V Patches - Why in edk2-
> platforms
> 
> Hi Abner,
> 
> Sorry, I should have followed up on this sooner.
> 
> On Thu, May 21, 2020 at 06:59:20 +0000, Chang, Abner (HPS SW/FW
> Technologist) wrote:
> > > On 5/20/20 6:07 PM, Daniel Schaefer wrote:
> > > > please reply here, fixed Mike's email address, sorry...
> > > >
> > > > On 5/20/20 6:03 PM, Daniel Schaefer wrote:
> > > >> On 5/20/20 1:43 PM, Leif Lindholm wrote:
> > > >>> On Fri, May 15, 2020 at 15:39:34 +0200, Daniel Schaefer wrote:
> > > >>>> Previously we had two packages just for RISC-V on our edk2 branch:
> > > >>>>    RiscVPkg and RiscVPlatformPkg They are now under
> > > >>>>    Platform/RISC-V/PlatformPkg and Silicon/RISC-V/ProcessorPkg
> > > >>>> in edk2-platforms.
> > > >>>
> > > >>> Understood. I took my eye off the ball there for a while, but
> > > >>> I'm a bit confused as to why RiscVPkg isn't going into EDK2.
> > > >>> That is very counterintuitive. And clearly it will need
> > > >>> revisiting if we are to add first-class CI checks like those we do with
> OvmfPkg/ArmVirtPkg.
> > > >>
> > > >> Yes, I understand your concern. Personally I'd like it also to be
> > > >> in
> > > >> EDK2 straight away, however Mike, Bret and Sean have raised valid
> > > >> concerns:
> 
> Can you point me to the conversation I have missed?
> 
> > > >> 1. RISC-V is very new and potentially unstable - it's quicker to
> > > >> make changes in edk2-platforms.
> 
> I don't see this as a valid argument.
> It's not edk2-unstable, it is edk2-platforms.
> 
> edk2-platforms exists because there used to be strong feelings against
> holding *real* platforms in edk2, with edk2 being originally intended only as
> a code library for IBV/ISV to cherry-pick from.
> 
> But fundamentally, if code is too immature to go into the master branch of
> edk2, it is too immature to go into the master branch of edk2-platforms. If
> we want edk2-might-be-a-bit-shaky-but-who-cares,
> then someone will have to create it.
> 
> > > >> 2. If we define new interfaces and libraries in edk2, we can't
> > > >> remove them easily because it would be a backwards-incompatible
> change.
> > > >> edk2-platforms isn't quite as strict.
> 
> Yes it is.
> The only thing making it less strict is its contents - platform ports and device
> drivers. The changes tend to be self-contained. Where they are not, they
> need to be carefully managed.
> 
> > > >> 3. Long-term, I think many agree, we should aim to move much of
> > > >> the RISC-V code into UefiCpuPkg and OvmfPkg. Mike mentioned that
> > > >> would need coordination with ARM maintainers because it might
> > > >> make sense to move their code there as well.
> 
> I don't think there is any need to tie the two together.
> Yes, UefiCpuPkg should be a generic place where not only x86 support can be
> contained, but the paths for ARM* and RISC-V into there do not have any
> interdependencies.
> 
> > > >>> I *did* have some outstanding comments specifically with regards
> > > >>> to large amounts of code duplication between the SMBIOS
> > > >>> implementation of some closely related RISC-V platforms. That now
> needs to be revisited.
> > > >>
> > > >> The SMBIOS code hasn't changed. It has moved to
> > > >>
> > > >> Silicon/SiFive/{E51,U54,U54MCCoreplex}/Library/PeiCoreInfoHobLib
> > > >> You're referring to this library, right?
> > > >>
> > > >> They build the SMBIOS entries for a particular processor. Yes,
> > > >> the values do have a lot of overlap but these files are like
> > > >> configuration files. They don't do much, they only set the values
> > > >> of the
> > > properties.
> > > >>
> > > >> Currently it is not possible to let the UEFI firmware get this
> > > >> information from the hardware at runtime, especially now, since
> > > >> we're running in S-Mode.
> > > >> To allow that, we created a RISC-V working group to be able to
> > > >> retrieve all of this information dynamically from the processor
> > > >> (among other goals). Then the vendor will not have to modify
> > > >> these files and hardcode the values anymore. Which enables us to
> > > >> create a single library for all processors.
> > > >> See: https://github.com/riscv/configuration-structure
> > > >>
> > > >> I hope I described everything properly, please correct me
> > > >> otherwise, Abner.
> > [Abner]  Yes almost. Thanks Daniel.
> > One thing I would like to add,
> > If you take a look on SiFive Core IP
> > > >> INVALID URI REMOVED
> > > >> om_risc-2Dv-2Dcore-
> 2Dip&d=DwIDAw&c=C5b8zRQO1miGmBeVZ2LFWg&r=_SN6F
> > > >>
> ZBN4Vgi4Ulkskz6qU3NYRO03nHp9P7Z5q59A3E&m=CYgLjPyxDUeKYpXV_283
> 3iYF
> > > >>
> 0_kR2PGdGoEVD7Qare0&s=OQvDbn7xhejlUpQrBMNReCLl1WGUoPKdIp5Y3
> 6-6e8E
> > > >> &e=  you can see there are different SKUs of RISC-V core. Just
> > > >> take some as exampl,e
> > S51 - Single core
> > U54 - Single core
> > S76 - Single core
> > U74- single core
> > U54-MC - Multicore which is 4*U54 cores +1*S51 core U74-MC - Multicore
> > which is 4*U74 core + 1*S7 core
> >
> > Those are the combinations of core IP. Silicon vendor can get those
> > core IPs and combine them to the RISC-V processor. To have
> > CoreInfoHobLib libraries for each different core (not multicore) to
> > build up the core capability is reasonable and makes sense. For the
> > multicore, it just pulling the single core CoreInfoHobLib to build up
> > the SMBIOS table for the multicore processor. Those libraries look
> > duplicate in logically, however only one instance of CoreInfoHobLib is
> > built in for multiple identical cores in physically view. Maybe we
> > still can move some identical core into the core-specific library but
> > it is not worthwhile.
> 
> OK, lets start with the *full* diff of E51 and U54 from the (admittedly slightly
> dated) devel-riscvplatforms branch:
> 
> <<<
> --- ./E51/Library/PeiCoreInfoHobLib/CoreInfoHob.c	2020-05-28
> 12:12:11.211028141 +0100
> +++ ./U54/Library/PeiCoreInfoHobLib/CoreInfoHob.c	2020-05-28
> 12:12:11.211028141 +0100
> @@ -7,6 +7,8 @@
> 
>  **/
> 
> +#include <IndustryStandard/RiscVOpensbi.h>
> +
> 
> [LL]
> U54 inserts this file in a different location, this is not actual divergence.
> 
> //
>  // The package level header files this module uses  // @@ -19,21 +21,15 @@
> #include <Library/DebugLib.h>  #include
> <Library/FirmwareContextProcessorSpecificLib.h>
>  #include <Library/HobLib.h>
> -#include <Library/PcdLib.h>
> 
> [LL]
> Interestingly, only E51 actually includes this, but both files *use* it - this is a
> bug in U54 caused by the separation.
> 
> -#include <IndustryStandard/RiscVOpensbi.h>
> 
> [LL]
> This is the other end of the files placing this inlude in a different location.
> 
> -#include <Library/ResourcePublicationLib.h>
> -
> 
> [LL]
> This header is irrelevant and unused. Present only in E51.
> 
>  #include <Library/RiscVEdk2SbiLib.h>
> -#include <ProcessorSpecificHobData.h>
> -#include <RiscVImpl.h>
> 
> [LL]
> Included in different location for E51/U54.
> 
>  #include <sbi/sbi_hart.h>
> -#include <sbi/sbi_scratch.h>
>  #include <sbi/sbi_platform.h>
> +#include <sbi/sbi_scratch.h>
> 
> [LL]
> sbi_scratch.h included in different order between platforms.
> 
> +#include <RiscVImpl.h>
> 
> [LL]
> Included in different location for E51/U54 (other end of).
> 
> #include <SmbiosProcessorSpecificData.h>
> 
>  /**
> -  Function to build core specific information HOB. RISC-V SMBIOS DXE driver
> collect
> -  this information and build SMBIOS Type44.
> +  Function to build core specific information HOB.
> 
> [LL]
> Different documentation description for the otherwise identical functions.
> 
> 
>    @param  ParentProcessorGuid    Parent processor od this core.
> ParentProcessorGuid
>                                   could be the same as CoreGuid if one processor has @@ -
> 41,19 +37,19 @@
>    @param  ParentProcessorUid     Unique ID of pysical processor which owns
> this core.
>    @param  HartId                 Hart ID of this core.
>    @param  IsBootHart             TRUE means this is the boot HART.
> -  @param  GuidHobData            Pointer to receive   EFI_HOB_GUID_TYPE.
> +  @param  GuidHobdata            Pointer to
> RISC_V_PROCESSOR_SPECIFIC_HOB_DATA.
> 
> [LL]
> Different capitalisation of input variable and different documentation for the
> same parameter in the identical functions. E51 gets the former correct, U54
> the latter.
> 
> 
>    @return EFI_SUCCESS     The PEIM initialized successfully.
> 
>  **/
>  EFI_STATUS
>  EFIAPI
> -CreateE51CoreProcessorSpecificDataHob (
> +CreateU54CoreProcessorSpecificDataHob (
> 
> [LL]
> We reach the first *real* difference between the two - the name of the
> function.
> This could have been addressed with different .inf files with different -D
> cflags.
> 
>    IN EFI_GUID  *ParentProcessorGuid,
>    IN UINTN     ParentProcessorUid,
>    IN UINTN     HartId,
>    IN BOOLEAN   IsBootHart,
> -  OUT RISC_V_PROCESSOR_SPECIFIC_HOB_DATA **GuidHobData
> +  OUT RISC_V_PROCESSOR_SPECIFIC_HOB_DATA **GuidHobdata
> 
> [LL]
> Again, difference only in capitalisation.
> 
>    )
>  {
>    RISC_V_PROCESSOR_SPECIFIC_HOB_DATA *CoreGuidHob; @@ -64,7 +60,7
> @@
> 
>    DEBUG ((DEBUG_INFO, "%a: Entry.\n", __FUNCTION__));
> 
> -  if (GuidHobData == NULL) {
> +  if (GuidHobdata == NULL) {
> 
> [LL]
> Again, difference only in capitalisation.
> 
>      return EFI_INVALID_PARAMETER;
>    }
> 
> @@ -80,7 +76,7 @@
>        FirmwareContextHartSpecific,
>        ParentProcessorGuid,
>        ParentProcessorUid,
> -      (EFI_GUID *)PcdGetPtr (PcdSiFiveE51CoreGuid),
> +      (EFI_GUID *)PcdGetPtr (PcdSiFiveU54CoreGuid),
> 
> [LL]
> Different Pcd names.
> 
>        HartId,
>        IsBootHart,
>        &ProcessorSpecDataHob
> @@ -109,7 +105,7 @@
>    DEBUG ((DEBUG_INFO, "        *MachineImplId = 0x%x\n",
> ProcessorSpecDataHob.ProcessorSpecificData.MachineImplId.Value64_L));
> 
>    //
> -  // Build GUID HOB for E51 core, this is for SMBIOS type 44
> +  // Build GUID HOB for U54 core.
> 
> [LL]
> Different comments for identical code.
> 
>    //
>    ProcessorSpecDataHobGuid = PcdGetPtr
> (PcdProcessorSpecificDataGuidHobGuid);
>    CoreGuidHob = (RISC_V_PROCESSOR_SPECIFIC_HOB_DATA
> *)BuildGuidDataHob (ProcessorSpecDataHobGuid, (VOID
> *)&ProcessorSpecDataHob, sizeof
> (RISC_V_PROCESSOR_SPECIFIC_HOB_DATA));
> @@ -117,7 +113,7 @@
>      DEBUG ((DEBUG_ERROR, "Fail to create GUID HOB of SiFive E51 core.\n"));
>      ASSERT (FALSE);
>    }
> -  *GuidHobData = CoreGuidHob;
> +  *GuidHobdata = CoreGuidHob;
> 
> [LL]
> Again, difference only in capitalisation.
> 
>  return EFI_SUCCESS;
>  }
> 
> @@ -135,17 +131,21 @@
>  **/
>  EFI_STATUS
>  EFIAPI
> -CreateE51ProcessorSmbiosDataHob (
> +CreateU54ProcessorSmbiosDataHob (
> 
> [LL]
> Difference in name only.
> 
>    IN UINTN     ProcessorUid,
> -  OUT RISC_V_PROCESSOR_SMBIOS_HOB_DATA **SmbiosHobPtr
> +  IN RISC_V_PROCESSOR_SMBIOS_HOB_DATA **SmbiosHobPtr
> 
> [LL]
> I am going to go out on a limb here and suggest one of the above is incorrect,
> and once that is corrected, these two lines would be identical.
> 
>    )
>  {
>    EFI_GUID *GuidPtr;
>    RISC_V_PROCESSOR_TYPE4_HOB_DATA ProcessorDataHob;
>    RISC_V_PROCESSOR_TYPE7_HOB_DATA L1InstCacheDataHob;
> +  RISC_V_PROCESSOR_TYPE7_HOB_DATA L1DataCacheDataHob;
> + RISC_V_PROCESSOR_TYPE7_HOB_DATA L2CacheDataHob;
> 
> [LL]
> Here is the first functional difference.
> 
>    RISC_V_PROCESSOR_SMBIOS_HOB_DATA SmbiosDataHob;
>    RISC_V_PROCESSOR_TYPE4_HOB_DATA *ProcessorDataHobPtr;
>    RISC_V_PROCESSOR_TYPE7_HOB_DATA *L1InstCacheDataHobPtr;
> +  RISC_V_PROCESSOR_TYPE7_HOB_DATA *L1DataCacheDataHobPtr;
> + RISC_V_PROCESSOR_TYPE7_HOB_DATA *L2CacheDataHobPtr;
> 
> [LL]
> Which could be merged with this inside an ifdef.
> 
>    RISC_V_PROCESSOR_SMBIOS_HOB_DATA *SmbiosDataHobPtr;
> 
>    if (SmbiosHobPtr == NULL) {
> @@ -155,7 +155,7 @@
>    // Build up SMBIOS type 7 L1 instruction cache record.
>    //
>    ZeroMem((VOID *)&L1InstCacheDataHob, sizeof
> (RISC_V_PROCESSOR_TYPE7_HOB_DATA));
> -  CopyGuid (&L1InstCacheDataHob.PrcessorGuid, (EFI_GUID *)PcdGetPtr
> (PcdSiFiveE51CoreGuid));
> +  CopyGuid (&L1InstCacheDataHob.PrcessorGuid, (EFI_GUID *)PcdGetPtr
> + (PcdSiFiveU54CoreGuid));
> 
> [LL]
> Difference in name only.
> 
>    L1InstCacheDataHob.ProcessorUid = ProcessorUid;
>    L1InstCacheDataHob.SmbiosType7Cache.SocketDesignation =
> TO_BE_FILLED_BY_VENDOR;
>    L1InstCacheDataHob.SmbiosType7Cache.CacheConfiguration =
> RISC_V_CACHE_CONFIGURATION_CACHE_LEVEL_1 | \ @@ -173,7 +173,59
> @@
>    GuidPtr = (EFI_GUID *)PcdGetPtr
> (PcdProcessorSmbiosType7GuidHobGuid);
>    L1InstCacheDataHobPtr = (RISC_V_PROCESSOR_TYPE7_HOB_DATA
> *)BuildGuidDataHob (GuidPtr, (VOID *)&L1InstCacheDataHob, sizeof
> (RISC_V_PROCESSOR_TYPE7_HOB_DATA));
>    if (L1InstCacheDataHobPtr == NULL) {
> -    DEBUG ((DEBUG_ERROR, "Fail to create GUID HOB of SiFive E51 core L1
> instruction cache RISC_V_PROCESSOR_TYPE7_HOB_DATA.\n"));
> +    DEBUG ((DEBUG_ERROR, "Fail to create GUID HOB of SiFive U54 core L1
> + instruction cache RISC_V_PROCESSOR_TYPE7_HOB_DATA.\n"));
> 
> [LL]
> Difference in name only.
> 
> +    ASSERT (FALSE);
> +  }
> +
> 
> [LL]
> Below starts the fundamental difference between the two:
> 
> +  //
> +  // Build up SMBIOS type 7 L1 data cache record.
> +  //
> +  ZeroMem((VOID *)&L1DataCacheDataHob, sizeof
> + (RISC_V_PROCESSOR_TYPE7_HOB_DATA));
> +  CopyGuid (&L1DataCacheDataHob.PrcessorGuid, (EFI_GUID *)PcdGetPtr
> + (PcdSiFiveU54CoreGuid));  L1DataCacheDataHob.ProcessorUid =
> + ProcessorUid;
> L1DataCacheDataHob.SmbiosType7Cache.SocketDesignation =
> + TO_BE_FILLED_BY_VENDOR;
> L1DataCacheDataHob.SmbiosType7Cache.CacheConfiguration =
> RISC_V_CACHE_CONFIGURATION_CACHE_LEVEL_1 | \
> +      RISC_V_CACHE_CONFIGURATION_LOCATION_INTERNAL | \
> +      RISC_V_CACHE_CONFIGURATION_ENABLED | \
> +      RISC_V_CACHE_CONFIGURATION_MODE_UNKNOWN;
> +  L1DataCacheDataHob.SmbiosType7Cache.MaximumCacheSize =
> + TO_BE_FILLED_BY_VENDOR;
> + L1DataCacheDataHob.SmbiosType7Cache.InstalledSize =
> + TO_BE_FILLED_BY_VENDOR;
> + L1DataCacheDataHob.SmbiosType7Cache.SupportedSRAMType.Unknown
> = 1;
> + L1DataCacheDataHob.SmbiosType7Cache.CurrentSRAMType.Unknown = 1;
> + L1DataCacheDataHob.SmbiosType7Cache.CacheSpeed =
> + TO_BE_FILLED_BY_VENDOR;
> + L1DataCacheDataHob.SmbiosType7Cache.ErrorCorrectionType =
> + TO_BE_FILLED_BY_VENDOR;
> + L1DataCacheDataHob.SmbiosType7Cache.SystemCacheType =
> CacheTypeData;
> + L1DataCacheDataHob.SmbiosType7Cache.Associativity =
> + TO_BE_FILLED_BY_VENDOR;  GuidPtr = (EFI_GUID *)PcdGetPtr
> + (PcdProcessorSmbiosType7GuidHobGuid);
> +  L1DataCacheDataHobPtr = (RISC_V_PROCESSOR_TYPE7_HOB_DATA
> + *)BuildGuidDataHob (GuidPtr, (VOID *)&L1DataCacheDataHob, sizeof
> + (RISC_V_PROCESSOR_TYPE7_HOB_DATA));
> +  if (L1DataCacheDataHobPtr == NULL) {
> +    DEBUG ((DEBUG_ERROR, "Fail to create GUID HOB of SiFive U54 core L1
> data cache RISC_V_PROCESSOR_TYPE7_HOB_DATA.\n"));
> +    ASSERT (FALSE);
> +  }
> +
> +  //
> +  // Build up SMBIOS type 7 L2 cache record.
> +  //
> +  ZeroMem((VOID *)&L2CacheDataHob, sizeof
> + (RISC_V_PROCESSOR_TYPE7_HOB_DATA));
> +  CopyGuid (&L2CacheDataHob.PrcessorGuid, (EFI_GUID *)PcdGetPtr
> + (PcdSiFiveU54CoreGuid));  L2CacheDataHob.ProcessorUid = ProcessorUid;
> + L2CacheDataHob.SmbiosType7Cache.SocketDesignation =
> + TO_BE_FILLED_BY_VENDOR;
> L2CacheDataHob.SmbiosType7Cache.CacheConfiguration =
> RISC_V_CACHE_CONFIGURATION_CACHE_LEVEL_2 | \
> +      RISC_V_CACHE_CONFIGURATION_LOCATION_EXTERNAL | \
> +      RISC_V_CACHE_CONFIGURATION_ENABLED | \
> +      RISC_V_CACHE_CONFIGURATION_MODE_UNKNOWN;
> +  L2CacheDataHob.SmbiosType7Cache.MaximumCacheSize =
> + TO_BE_FILLED_BY_VENDOR;
> L2CacheDataHob.SmbiosType7Cache.InstalledSize
> + = TO_BE_FILLED_BY_VENDOR;
> + L2CacheDataHob.SmbiosType7Cache.SupportedSRAMType.Unknown = 1;
> + L2CacheDataHob.SmbiosType7Cache.CurrentSRAMType.Unknown = 1;
> + L2CacheDataHob.SmbiosType7Cache.CacheSpeed =
> TO_BE_FILLED_BY_VENDOR;
> + L2CacheDataHob.SmbiosType7Cache.ErrorCorrectionType =
> + TO_BE_FILLED_BY_VENDOR;
> + L2CacheDataHob.SmbiosType7Cache.SystemCacheType =
> CacheTypeUnified;
> + L2CacheDataHob.SmbiosType7Cache.Associativity =
> + TO_BE_FILLED_BY_VENDOR;  GuidPtr = (EFI_GUID *)PcdGetPtr
> + (PcdProcessorSmbiosType7GuidHobGuid);
> +  L2CacheDataHobPtr = (RISC_V_PROCESSOR_TYPE7_HOB_DATA
> + *)BuildGuidDataHob (GuidPtr, (VOID *)&L2CacheDataHob, sizeof
> + (RISC_V_PROCESSOR_TYPE7_HOB_DATA));
> +  if (L2CacheDataHobPtr == NULL) {
> +    DEBUG ((DEBUG_ERROR, "Fail to create GUID HOB of SiFive U54 core L2
> + cache RISC_V_PROCESSOR_TYPE7_HOB_DATA.\n"));
>      ASSERT (FALSE);
>    }
> 
> 
> [LL]
> And the funamental difference ends here.
> 
> @@ -181,7 +233,7 @@
>    // Build up SMBIOS type 4 record.
>    //
>    ZeroMem((VOID *)&ProcessorDataHob, sizeof
> (RISC_V_PROCESSOR_TYPE4_HOB_DATA));
> -  CopyGuid (&ProcessorDataHob.PrcessorGuid, (EFI_GUID *)PcdGetPtr
> (PcdSiFiveE51CoreGuid));
> +  CopyGuid (&ProcessorDataHob.PrcessorGuid, (EFI_GUID *)PcdGetPtr
> + (PcdSiFiveU54CoreGuid));
> 
> [LL]
> Differ in name only.
> 
>    ProcessorDataHob.ProcessorUid = ProcessorUid;
>    ProcessorDataHob.SmbiosType4Processor.Socket =
> TO_BE_FILLED_BY_VENDOR;
>    ProcessorDataHob.SmbiosType4Processor.ProcessorType =
> CentralProcessor; @@ -196,7 +248,7 @@
>    ProcessorDataHob.SmbiosType4Processor.Status =
> TO_BE_FILLED_BY_CODE;
>    ProcessorDataHob.SmbiosType4Processor.ProcessorUpgrade =
> TO_BE_FILLED_BY_VENDOR;
>    ProcessorDataHob.SmbiosType4Processor.L1CacheHandle =
> TO_BE_FILLED_BY_RISC_V_SMBIOS_DXE_DRIVER;
> -  ProcessorDataHob.SmbiosType4Processor.L2CacheHandle = 0xffff;
> +  ProcessorDataHob.SmbiosType4Processor.L2CacheHandle =
> + TO_BE_FILLED_BY_RISC_V_SMBIOS_DXE_DRIVER;
> 
> [LL]
> Real diff.
> 
>    ProcessorDataHob.SmbiosType4Processor.L3CacheHandle = 0xffff;
>    ProcessorDataHob.SmbiosType4Processor.SerialNumber =
> TO_BE_FILLED_BY_CODE;
>    ProcessorDataHob.SmbiosType4Processor.AssetTag =
> TO_BE_FILLED_BY_VENDOR; @@ -212,24 +264,23 @@
>    GuidPtr = (EFI_GUID *)PcdGetPtr
> (PcdProcessorSmbiosType4GuidHobGuid);
>    ProcessorDataHobPtr = (RISC_V_PROCESSOR_TYPE4_HOB_DATA
> *)BuildGuidDataHob (GuidPtr, (VOID *)&ProcessorDataHob, sizeof
> (RISC_V_PROCESSOR_TYPE4_HOB_DATA));
>    if (ProcessorDataHobPtr == NULL) {
> -    DEBUG ((DEBUG_ERROR, "Fail to create GUID HOB of SiFive E51 core
> RISC_V_PROCESSOR_TYPE4_HOB_DATA.\n"));
> +    DEBUG ((DEBUG_ERROR, "Fail to create GUID HOB of SiFive U54 core
> + RISC_V_PROCESSOR_TYPE4_HOB_DATA.\n"));
> 
> [LL]
> Difference in name only.
> 
>      ASSERT (FALSE);
>    }
> 
>    ZeroMem((VOID *)&SmbiosDataHob, sizeof
> (RISC_V_PROCESSOR_SMBIOS_HOB_DATA));
>    SmbiosDataHob.Processor = ProcessorDataHobPtr;
>    SmbiosDataHob.L1InstCache = L1InstCacheDataHobPtr;
> -  SmbiosDataHob.L1DataCache = NULL;
> -  SmbiosDataHob.L2Cache = NULL;
> +  SmbiosDataHob.L1DataCache = L1DataCacheDataHobPtr;
> + SmbiosDataHob.L2Cache = L2CacheDataHobPtr;
> 
> [LL]
> Real diff.
> 
>    SmbiosDataHob.L3Cache = NULL;
>    GuidPtr = (EFI_GUID *)PcdGetPtr (PcdProcessorSmbiosGuidHobGuid);
>    SmbiosDataHobPtr = (RISC_V_PROCESSOR_SMBIOS_HOB_DATA
> *)BuildGuidDataHob (GuidPtr, (VOID *)&SmbiosDataHob, sizeof
> (RISC_V_PROCESSOR_SMBIOS_HOB_DATA));
>    if (SmbiosDataHobPtr == NULL) {
> -    DEBUG ((DEBUG_ERROR, "Fail to create GUID HOB of SiFive E51 core
> RISC_V_PROCESSOR_SMBIOS_HOB_DATA.\n"));
> +    DEBUG ((DEBUG_ERROR, "Fail to create GUID HOB of SiFive U54 core
> + RISC_V_PROCESSOR_SMBIOS_HOB_DATA.\n"));
> 
> [LL]
> Difference in name only.
> 
>      ASSERT (FALSE);
>    }
>    *SmbiosHobPtr = SmbiosDataHobPtr;
>    return EFI_SUCCESS;
>  }
> 
> -
> 
> >>>
> 
> The meat of the difference between these two is less than 20% of the lines
> of code in each file - and it is mutually exclusive, not some horrific tangle of
> interdependencies.
> 
> The story with the difference between U54 and U54MCCoreplex isn't much
> better, only works along a different axis.
> 
> "It isn't worthwhile" in an open source project isn't a question of "how
> quickly can I create *one* new platform by copying instead of
> refactoring/reusing", but a judgement call between:
> - How many mistakes do I risk inserting while editing a new file as
>   opposed to being directly able to see the differences I have caused
>   while editing an existing file.
> - How much do I increase reviewing effort by doing this?
> - How much do I increase ongoing maintainership (or affect quality) by
>   requiring bugs to be fixed in multiple places instead of one.
> 
> Not to mention:
> - How many common pattern that could be broken out into common helper
>   libraries do we miss when we need to compare every SoC/platform
>   combination ever created, as opposed to being able to look at least
>   at implementations covering families.
> 
> If it isn't important enough to take that into consideration, it isn't important
> enough to upstream the SMBIOS support.

Ok Leif, Daniel will evaluate which code could be leveraged and put it in the library under either Silicon vendor's  folder or under RiscVPlatformPkg base on the functionality.
Many thanks for this.
Abner
> 
> /
>     Leif

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

* [edk2-devel] Where to put RISC-V packages
       [not found]                       ` <MW2PR2101MB092494AB8318628E06B62089E18F0@MW2PR2101MB0924.namprd21.prod.outlook.com>
@ 2020-06-03 11:57                         ` Daniel Schaefer
  2020-06-03 15:02                           ` Abner Chang
  0 siblings, 1 reply; 19+ messages in thread
From: Daniel Schaefer @ 2020-06-03 11:57 UTC (permalink / raw)
  To: Sean Brogan, Kinney, Michael D,
	Chang, Abner (HPS SW/FW Technologist), Bret Barkelew,
	Ard Biesheuvel (ard.biesheuvel@linaro.org), Zimmer, Vincent,
	Leif Lindholm
  Cc: devel@edk2.groups.io

Hi all,

(CC edk2 devel ML - shouldn't be a private discussion again)

let me try to summarize the points of each:

- edk2-platforms isn't a less stable edk2 per se
- edk2-platforms can be used for architectural decisions that are not
   stable yet and therefore different platforms might implement them
   differently
- Still we'd rather put unstable things in edk2-platforms for now
- In the future CPU Init shouldn't be totally separate packages but the
   overlapping code should be combined in
   UefiCpuPkg/MdePkg/MdeModulePkg/...
   - This applies to RISC-V, as well as ARM
   - UefiCpuPkg is too x86 focused
     -> needs lots of work and RISC-V shouldn't wait for that
- RISC-V changes should preferably be integrated into existing packages
   instead of building an entirely separate hierarchy
   -> We have done this. For example DxeIpl is now in edk2 in
      MdeModulePkg.

I hope everyone can agree with this summary.
I suggest that we do the following:

- Merge all of the RISC-V code to edk2-platforms
- Evaluate the packages individually and move them to edk2 one by one,
   or to merge them into existing edk2 packages
- In the end in edk2-platforms should only remain code for specific
   platforms, like the SiFive Unleashed board. No generic RISC-V code,
   right?

I'm not experienced enough with EDK2 to evaluate whether packages might
fit into EDK2 directly. Maybe we should have a call and have a look at
each on individually? Below I looked into the libraries and drivers of
every package that we want to upstream with our branch. I describe, what
they do and if they are platform specific. Then I issue my guess for
where it would belong.
I hope that gives everyone a bit more insight into all of the code we'd
like to merge.

Again: Would it be okay to merge everything as is into edk2-platforms. 
(DxeIpl
was previously merged into edk2). And then slowly migrate them over into 
edk2?
Or should be evaluate each package individually now instead of merging
everything at once.

- Platform/RISC-V/PlatformPkg
   - FirmwareContextProcessorSpecificLib
     Take processors specific data from SMBIOS and put in HOB
     => edk2
   - OpensbiPlatformLibNull
     Null library for platform provided OpenSBI functions.
     Those functions are defined in the SiFive directories
     => edk2
   - PlatformBootManagerLib
     I'm not sure why this is there. It doesn't look RISC-V specific.
     cc: Abner
     => ???
   - PlatformMemoryTestLibNull
     Same as above
     => ???
   - PlatformUpdateProgressLibNull
     Same as above
     => ???
   - RiscVPlatformTempMemoryInitLibNull
     Initialize temporary RAM on stack. Same on every RISC-V CPU
     Depends on platform's PCD values
     => edk2
   - Sec
     SEC Phase, same for every RISC-V CPU
     => edk2
- Silicon/RISC-V/ProcessorPkg
   - PeiServicesTablePointerLibOpenSbi
     Saving/loading PeiServicesTable in RISC-V scratch space with OpenSBI
     On every RISC-V CPU
     => edk2
   - RiscVCpuLib
     ASM functions to read RISC-V CSRs on every RISC-V CPU
     For UefiCpuPkg?
     => edk2
   - RiscVEdk2SbiLib
     Wrapper library to call the SBI ecalls on every RISC-V CPU
     => edk2
   - RiscVExceptionLib
     CpuExceptionHandlerLib implementation for RISC-V
     Currently only uses CSR accesses
     cc Abner: Will this be platform specific with the CLIC proposals?
     => edk2/edk2-platforms??
   - RiscVOpensbiLib
     OpenSBI library
     Needs to be called in early init on every RISC-V CPU
     => edk2?
   - RiscVPlatformTimerLibNull,RiscVTimerLib
     TimerLib implementation for RISC-V
     Depends on platform specific PCDs only
     => edk2?
   - CpuDxe
     Produces: gEfiCpuArchProtocolGuid
     Would go into UefiCpuPkg
     => edk2
   - SmbiosDxe
     Create SMBIOS entries type 4, type 7 and type 44
     Values need to be set by platform
     => edk2-platforms

All packages under edk2-platforms/{Silicon,Platform}/SiFive/ are not
included here, as they are obviously platform specific and need to go
into edk2-platforms.

Thanks,
Daniel



On 5/29/20 7:25 AM, Sean Brogan wrote:
> Sorry was just getting to this.  You guys are fast.  This is mostly to 
> Daniel’s original email but I think it lines up with Abner’s questions 
> and Mike’s response.
> 
> Daniel,
> 
> I think both Mike and Bret said most everything needed but I'll clarify 
> just in case.
> 
> I don't think the conversations below (Daniels) is accurate for my 
> concerns about RiscV support or my view of edk2-platforms.
> 
> In my view Edk2 packages are best when they are functionality based.  
> This allows for proper code base layering and makes sure that 
> abstractions are created in a way that will facilitate cross platform 
> core development.  For packages that are based on other characteristics, 
> like architecture, dependencies at the package level usually become 
> tangled and brittle which slowly leaks out into the rest of the code 
> base and then makes the entire repository harder to work with.
> 
> For that reason I advocated that the RiscV support be integrated into 
> the appropriate packages and modules.  Where there is unique 
> functionality that then needs to be evaluated to determine if its core 
> functionality or platform functionality. Depending on that it would then 
> land in the appropriate edk2 package or something in edk2-platforms.
> 
> Thanks
> 
> Sean
> 
> *From:* Kinney, Michael D <michael.d.kinney@intel.com>
> *Sent:* Thursday, May 28, 2020 10:18 PM
> *To:* Chang, Abner (HPS SW/FW Technologist) <abner.chang@hpe.com>; Bret 
> Barkelew <Bret.Barkelew@microsoft.com>; Schaefer, Daniel (DualStudy) 
> <daniel.schaefer@hpe.com>; Sean Brogan <sean.brogan@microsoft.com>; Ard 
> Biesheuvel (ard.biesheuvel@linaro.org) <ard.biesheuvel@linaro.org>; 
> Zimmer, Vincent <vincent.zimmer@intel.com>; Kinney, Michael D 
> <michael.d.kinney@intel.com>
> *Cc:* Leif Lindholm <leif@nuviainc.com>
> *Subject:* [EXTERNAL] RE: Re: [edk2-devel] [PATCH v2 0/3] New RISC-V 
> Patches - Why in edk2-platforms
> 
> Abner,
> 
> The architectural RISCV CPU content that does not change between RISCV 
> CPU implementations would be a candidate for MdePkg, MdeModulePkg, or 
> UefiCpuPkg.  We would need to do another review of the content along 
> with the ARM/AARCH64 content to see how best to organize the CPU related 
> content for now and future.
> 
> RISCV platform content would still need to go into edk2-platforms.  
> Non-architectural RISCV CPU content would also need to go into 
> edk2-platforms.
> 
> Mike
> 
> *From:* Chang, Abner (HPS SW/FW Technologist) <abner.chang@hpe.com 
> <mailto:abner.chang@hpe.com>>
> *Sent:* Thursday, May 28, 2020 10:01 PM
> *To:* Kinney, Michael D <michael.d.kinney@intel.com 
> <mailto:michael.d.kinney@intel.com>>; Bret Barkelew 
> <Bret.Barkelew@microsoft.com <mailto:Bret.Barkelew@microsoft.com>>; 
> Schaefer, Daniel (DualStudy) <daniel.schaefer@hpe.com 
> <mailto:daniel.schaefer@hpe.com>>; Sean Brogan 
> <sean.brogan@microsoft.com <mailto:sean.brogan@microsoft.com>>; Ard 
> Biesheuvel (ard.biesheuvel@linaro.org 
> <mailto:ard.biesheuvel@linaro.org>) <ard.biesheuvel@linaro.org 
> <mailto:ard.biesheuvel@linaro.org>>; Zimmer, Vincent 
> <vincent.zimmer@intel.com <mailto:vincent.zimmer@intel.com>>
> *Cc:* Leif Lindholm <leif@nuviainc.com <mailto:leif@nuviainc.com>>
> *Subject:* RE: Re: [edk2-devel] [PATCH v2 0/3] New RISC-V Patches - Why 
> in edk2-platforms
> 
> *From:* Kinney, Michael D [mailto:michael.d.kinney@intel.com]
> *Sent:* Friday, May 29, 2020 12:36 PM
> *To:* Bret Barkelew <Bret.Barkelew@microsoft.com 
> <mailto:Bret.Barkelew@microsoft.com>>; Schaefer, Daniel (DualStudy) 
> <daniel.schaefer@hpe.com <mailto:daniel.schaefer@hpe.com>>; Sean Brogan 
> <sean.brogan@microsoft.com <mailto:sean.brogan@microsoft.com>>; Ard 
> Biesheuvel (ard.biesheuvel@linaro.org 
> <mailto:ard.biesheuvel@linaro.org>) <ard.biesheuvel@linaro.org 
> <mailto:ard.biesheuvel@linaro.org>>; Kinney, Michael D 
> <michael.d.kinney@intel.com <mailto:michael.d.kinney@intel.com>>; 
> Zimmer, Vincent <vincent.zimmer@intel.com <mailto:vincent.zimmer@intel.com>>
> *Cc:* Leif Lindholm <leif@nuviainc.com <mailto:leif@nuviainc.com>>; 
> Chang, Abner (HPS SW/FW Technologist) <abner.chang@hpe.com 
> <mailto:abner.chang@hpe.com>>
> *Subject:* RE: [EXTERNAL] Re: [edk2-devel] [PATCH v2 0/3] New RISC-V 
> Patches - Why in edk2-platforms
> 
> We did a community review meeting.  I recall Ard and Vincent being present.
> 
> We discuss the CPU execution mode for PEI and DXE and there was a 
> discussion that RISCV has 2 modes and they want flexibility to use 
> both.  This choice is not defined in the PI spec yet.  We suggested that 
> it could follow the ARM/Thumb model and RISCV could choose a single mode 
> for all PEIMs and DXE drivers and choose to go into the other mode in 
> the module implementation as needed.
> 
> */[Abner] Yes. we done this as we discussed in the community meeting. 
> Those code are belong to RiscV*pkg and currently lay on 
> devel-riscvplatfoms which Leif is reviewing now./*
> 
> Given that these fundamental CPU execution mode design choices were 
> still in flux, it did not seem like it was ready for edk2 yet.
> 
> */[Abner] The current implementation is PEI/DXE are in the same mode./*
> 
> edk2-staging or an edk2-platforms branch seemed more appropriate until 
> all that was worked out.
> 
> */[Abner] Seems like that work is done. Maybe I have to review PI/UEFI 
> spec for the necessary changes./*
> 
> edk2-platforms/master seemed ok as well if different RISCV CPU modes 
> would be used for different platform solutions until a unified approach 
> by the RISCV vendors could be determined  Once that was solidified, 
> promoting to edk2 would be possible.
> 
> */[Abner] this means RicsVPkg and RicsVPlatformPkg eventually will be 
> located in edk2 but not edk2-platforms if above issues are addressed? We 
> don’t have to consider UefiCpuPkg for each arch now? We are good with 
> this though./*
> 
> Hopefully this clarifies for Leif why there was some resistance to edk2 
> repo right now.  Still on deck for the future.
> 
> Mike
> 
> *From:* Bret Barkelew <Bret.Barkelew@microsoft.com 
> <mailto:Bret.Barkelew@microsoft.com>>
> *Sent:* Thursday, May 28, 2020 8:11 PM
> *To:* Daniel Schaefer <daniel.schaefer@hpe.com 
> <mailto:daniel.schaefer@hpe.com>>; Kinney, Michael D 
> <michael.d.kinney@intel.com <mailto:michael.d.kinney@intel.com>>; Sean 
> Brogan <sean.brogan@microsoft.com <mailto:sean.brogan@microsoft.com>>
> *Cc:* Leif Lindholm <leif@nuviainc.com <mailto:leif@nuviainc.com>>; 
> Chang, Abner (HPS SW/FW Technologist) <abner.chang@hpe.com 
> <mailto:abner.chang@hpe.com>>
> *Subject:* RE: [EXTERNAL] Re: [edk2-devel] [PATCH v2 0/3] New RISC-V 
> Patches - Why in edk2-platforms
> 
> I think Sean has his own feedback, but my response to Abner was that 
> that I didn’t like the idea of continuing a pattern of separate packages 
> for significant portions of the CPU init. There have been a few times 
> where it has created unnecessary divergence that made it very difficult 
> to write cross-architecture code. I, personally, wasn’t fighting the 
> code landing in edk2 (except for RiscVPlatform, because it had platform 
> in the name), but I was inquiring to see whether it made more sense to 
> break things up among Mde, UefiCpu, and a couple other packages to 
> encourage adhering to similar patterns and interfaces between all the 
> different architectures. I’ve previously wondered openly whether it made 
> sense to do the same with the Arm packages.
> 
> I’ll be honest about not being super familiar with the RISCV code and it 
> would be easy for me to just shrug and say put it wherever, but I know 
> that architecture mobility/agility is important for us and wouldn’t be 
> surprised if I had to use RISCV in the future, and so wanted to make 
> sure that it was as close to what I was familiar with as possible.
> 
> - Bret
> 
> *From: *Daniel Schaefer <mailto:daniel.schaefer@hpe.com>
> *Sent: *Thursday, May 28, 2020 8:44 AM
> *To: *Kinney, Michael D <mailto:michael.d.kinney@intel.com>; Bret 
> Barkelew <mailto:Bret.Barkelew@microsoft.com>; Sean Brogan 
> <mailto:sean.brogan@microsoft.com>
> *Cc: *Leif Lindholm <mailto:leif@nuviainc.com>; Chang, Abner (HPS SW/FW 
> Technologist) <mailto:abner.chang@hpe.com>
> *Subject: *[EXTERNAL] Re: [edk2-devel] [PATCH v2 0/3] New RISC-V Patches 
> - Why in edk2-platforms
> 
> Hi Mike, Bret and Sean,
> 
> you have previously expressed concern about merging HPE's RISC-V code
> into edk2 and suggested merging it into edk2-platforms. Apparently you
> discussed this with Abner in a private email thread. According to that
> information I tried to summarize your points in an email on the edk2 ML.
> I hope I got it right.
> 
> As you can see, we have followed that suggestion and sent the new
> patches required for that to the ML.
> 
> Leif, and I, are still not convinced it's the right choice to not
> include it in edk2 proper.
> We would appreciate if you could address the concerns Leif has mentioned
> in the below email on the public ML.
> 
> Thanks!
> Daniel
> 
> On 5/28/20 1:54 PM, Leif Lindholm wrote:
>  > Hi Abner,
>  >
>  > Sorry, I should have followed up on this sooner.
>  >
>  > On Thu, May 21, 2020 at 06:59:20 +0000, Chang, Abner (HPS SW/FW 
> Technologist) wrote:
>  >>> On 5/20/20 6:07 PM, Daniel Schaefer wrote:
>  >>>> please reply here, fixed Mike's email address, sorry...
>  >>>>
>  >>>> On 5/20/20 6:03 PM, Daniel Schaefer wrote:
>  >>>>> On 5/20/20 1:43 PM, Leif Lindholm wrote:
>  >>>>>> On Fri, May 15, 2020 at 15:39:34 +0200, Daniel Schaefer wrote:
>  >>>>>>> Previously we had two packages just for RISC-V on our edk2 branch:
>  >>>>>>>     RiscVPkg and RiscVPlatformPkg
>  >>>>>>> They are now under
>  >>>>>>>     Platform/RISC-V/PlatformPkg and Silicon/RISC-V/ProcessorPkg in
>  >>>>>>> edk2-platforms.
>  >>>>>>
>  >>>>>> Understood. I took my eye off the ball there for a while, but I'm a
>  >>>>>> bit confused as to why RiscVPkg isn't going into EDK2. That is very
>  >>>>>> counterintuitive. And clearly it will need revisiting if we are to
>  >>>>>> add first-class CI checks like those we do with OvmfPkg/ArmVirtPkg.
>  >>>>>
>  >>>>> Yes, I understand your concern. Personally I'd like it also to be in
>  >>>>> EDK2 straight away, however Mike, Bret and Sean have raised valid
>  >>>>> concerns:
>  >
>  > Can you point me to the conversation I have missed?
>  >
>  >>>>> 1. RISC-V is very new and potentially unstable - it's quicker to make
>  >>>>> changes in edk2-platforms.
>  >
>  > I don't see this as a valid argument.
>  > It's not edk2-unstable, it is edk2-platforms.
>  >
>  > edk2-platforms exists because there used to be strong feelings against
>  > holding *real* platforms in edk2, with edk2 being originally intended
>  > only as a code library for IBV/ISV to cherry-pick from.
>  >
>  > But fundamentally, if code is too immature to go into the master
>  > branch of edk2, it is too immature to go into the master branch of
>  > edk2-platforms. If we want edk2-might-be-a-bit-shaky-but-who-cares,
>  > then someone will have to create it.
>  >
>  >>>>> 2. If we define new interfaces and libraries in edk2, we can't remove
>  >>>>> them easily because it would be a backwards-incompatible change.
>  >>>>> edk2-platforms isn't quite as strict.
>  >
>  > Yes it is.
>  > The only thing making it less strict is its contents - platform ports
>  > and device drivers. The changes tend to be self-contained. Where they
>  > are not, they need to be carefully managed.
>  >
>  >>>>> 3. Long-term, I think many agree, we should aim to move much of the
>  >>>>> RISC-V code into UefiCpuPkg and OvmfPkg. Mike mentioned that would
>  >>>>> need coordination with ARM maintainers because it might make sense to
>  >>>>> move their code there as well.
>  >
>  > I don't think there is any need to tie the two together.
>  > Yes, UefiCpuPkg should be a generic place where not only x86 support
>  > can be contained, but the paths for ARM* and RISC-V into there do not
>  > have any interdependencies.
> 

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

* Re: [edk2-devel] Where to put RISC-V packages
  2020-06-03 11:57                         ` [edk2-devel] Where to put RISC-V packages Daniel Schaefer
@ 2020-06-03 15:02                           ` Abner Chang
  0 siblings, 0 replies; 19+ messages in thread
From: Abner Chang @ 2020-06-03 15:02 UTC (permalink / raw)
  To: Schaefer, Daniel (DualStudy), Sean Brogan, Kinney, Michael D,
	Bret Barkelew, Ard Biesheuvel (ard.biesheuvel@linaro.org),
	Zimmer, Vincent, Leif Lindholm
  Cc: devel@edk2.groups.io



> -----Original Message-----
> From: Schaefer, Daniel (DualStudy)
> Sent: Wednesday, June 3, 2020 7:57 PM
> To: Sean Brogan <sean.brogan@microsoft.com>; Kinney, Michael D
> <michael.d.kinney@intel.com>; Chang, Abner (HPS SW/FW Technologist)
> <abner.chang@hpe.com>; Bret Barkelew <Bret.Barkelew@microsoft.com>;
> Ard Biesheuvel (ard.biesheuvel@linaro.org) <ard.biesheuvel@linaro.org>;
> Zimmer, Vincent <vincent.zimmer@intel.com>; Leif Lindholm
> <leif@nuviainc.com>
> Cc: devel@edk2.groups.io
> Subject: [edk2-devel] Where to put RISC-V packages
> 
> Hi all,
> 
> (CC edk2 devel ML - shouldn't be a private discussion again)
> 
> let me try to summarize the points of each:
> 
> - edk2-platforms isn't a less stable edk2 per se
> - edk2-platforms can be used for architectural decisions that are not
>    stable yet and therefore different platforms might implement them
>    differently
> - Still we'd rather put unstable things in edk2-platforms for now
> - In the future CPU Init shouldn't be totally separate packages but the
>    overlapping code should be combined in
>    UefiCpuPkg/MdePkg/MdeModulePkg/...
>    - This applies to RISC-V, as well as ARM
>    - UefiCpuPkg is too x86 focused
>      -> needs lots of work and RISC-V shouldn't wait for that
> - RISC-V changes should preferably be integrated into existing packages
>    instead of building an entirely separate hierarchy
>    -> We have done this. For example DxeIpl is now in edk2 in
>       MdeModulePkg.
> 
> I hope everyone can agree with this summary.
> I suggest that we do the following:
> 
> - Merge all of the RISC-V code to edk2-platforms
Agree. This is the first step after those new changes get "Reviewed-by".
> - Evaluate the packages individually and move them to edk2 one by one,
>    or to merge them into existing edk2 packages
> - In the end in edk2-platforms should only remain code for specific
>    platforms, like the SiFive Unleashed board. No generic RISC-V code,
>    right?
I agree with above. But those architecture-specific drivers may still stay in their own package.
> 
> I'm not experienced enough with EDK2 to evaluate whether packages might
> fit into EDK2 directly. Maybe we should have a call and have a look at each on
> individually? Below I looked into the libraries and drivers of every package
> that we want to upstream with our branch. I describe, what they do and if
> they are platform specific. Then I issue my guess for where it would belong.
> I hope that gives everyone a bit more insight into all of the code we'd like to
> merge.
> 
> Again: Would it be okay to merge everything as is into edk2-platforms.
> (DxeIpl
> was previously merged into edk2). And then slowly migrate them over into
> edk2?
> Or should be evaluate each package individually now instead of merging
> everything at once.
> 
> - Platform/RISC-V/PlatformPkg
>    - FirmwareContextProcessorSpecificLib
>      Take processors specific data from SMBIOS and put in HOB
>      => edk2
>    - OpensbiPlatformLibNull
>      Null library for platform provided OpenSBI functions.
>      Those functions are defined in the SiFive directories
>      => edk2
>    - PlatformBootManagerLib
>      I'm not sure why this is there. It doesn't look RISC-V specific.
>      cc: Abner
>      => ???
>    - PlatformMemoryTestLibNull
>      Same as above
>      => ???
>    - PlatformUpdateProgressLibNull
>      Same as above
>      => ???
>    - RiscVPlatformTempMemoryInitLibNull
>      Initialize temporary RAM on stack. Same on every RISC-V CPU
>      Depends on platform's PCD values
>      => edk2
>    - Sec
>      SEC Phase, same for every RISC-V CPU
>      => edk2
> - Silicon/RISC-V/ProcessorPkg
>    - PeiServicesTablePointerLibOpenSbi
>      Saving/loading PeiServicesTable in RISC-V scratch space with OpenSBI
>      On every RISC-V CPU
>      => edk2
>    - RiscVCpuLib
>      ASM functions to read RISC-V CSRs on every RISC-V CPU
>      For UefiCpuPkg?
>      => edk2
>    - RiscVEdk2SbiLib
>      Wrapper library to call the SBI ecalls on every RISC-V CPU
>      => edk2
>    - RiscVExceptionLib
>      CpuExceptionHandlerLib implementation for RISC-V
>      Currently only uses CSR accesses
>      cc Abner: Will this be platform specific with the CLIC proposals?
>      => edk2/edk2-platforms??
>    - RiscVOpensbiLib
>      OpenSBI library
>      Needs to be called in early init on every RISC-V CPU
>      => edk2?
>    - RiscVPlatformTimerLibNull,RiscVTimerLib
>      TimerLib implementation for RISC-V
>      Depends on platform specific PCDs only
>      => edk2?
>    - CpuDxe
>      Produces: gEfiCpuArchProtocolGuid
>      Would go into UefiCpuPkg
>      => edk2
>    - SmbiosDxe
>      Create SMBIOS entries type 4, type 7 and type 44
>      Values need to be set by platform
>      => edk2-platforms
Yes, we will have to review above modules and move those to UefiCpuPkg/MdePkg/MdeModulePkg as many as we can. But I guess some maybe still have to stay in RiscVPkg under edk2, unless we can move those RISC-V specific definitions to MdePkg/Include. We can discuss this later and create another branch as POC code based on edk2/edk2-platform RISC-V port.
> 
> All packages under edk2-platforms/{Silicon,Platform}/SiFive/ are not
> included here, as they are obviously platform specific and need to go into
> edk2-platforms.
> 
> Thanks,
> Daniel
> 
> 
> 
> On 5/29/20 7:25 AM, Sean Brogan wrote:
> > Sorry was just getting to this.  You guys are fast.  This is mostly to
> > Daniel’s original email but I think it lines up with Abner’s questions
> > and Mike’s response.
> >
> > Daniel,
> >
> > I think both Mike and Bret said most everything needed but I'll
> > clarify just in case.
> >
> > I don't think the conversations below (Daniels) is accurate for my
> > concerns about RiscV support or my view of edk2-platforms.
> >
> > In my view Edk2 packages are best when they are functionality based.
> > This allows for proper code base layering and makes sure that
> > abstractions are created in a way that will facilitate cross platform
> > core development.  For packages that are based on other
> > characteristics, like architecture, dependencies at the package level
> > usually become tangled and brittle which slowly leaks out into the
> > rest of the code base and then makes the entire repository harder to work
> with.
> >
> > For that reason I advocated that the RiscV support be integrated into
> > the appropriate packages and modules.  Where there is unique
> > functionality that then needs to be evaluated to determine if its core
> > functionality or platform functionality. Depending on that it would
> > then land in the appropriate edk2 package or something in edk2-platforms.
> >
> > Thanks
> >
> > Sean
> >
> > *From:* Kinney, Michael D <michael.d.kinney@intel.com>
> > *Sent:* Thursday, May 28, 2020 10:18 PM
> > *To:* Chang, Abner (HPS SW/FW Technologist) <abner.chang@hpe.com>;
> > Bret Barkelew <Bret.Barkelew@microsoft.com>; Schaefer, Daniel
> > (DualStudy) <daniel.schaefer@hpe.com>; Sean Brogan
> > <sean.brogan@microsoft.com>; Ard Biesheuvel
> > (ard.biesheuvel@linaro.org) <ard.biesheuvel@linaro.org>; Zimmer,
> > Vincent <vincent.zimmer@intel.com>; Kinney, Michael D
> > <michael.d.kinney@intel.com>
> > *Cc:* Leif Lindholm <leif@nuviainc.com>
> > *Subject:* [EXTERNAL] RE: Re: [edk2-devel] [PATCH v2 0/3] New RISC-V
> > Patches - Why in edk2-platforms
> >
> > Abner,
> >
> > The architectural RISCV CPU content that does not change between RISCV
> > CPU implementations would be a candidate for MdePkg, MdeModulePkg,
> or
> > UefiCpuPkg.  We would need to do another review of the content along
> > with the ARM/AARCH64 content to see how best to organize the CPU
> > related content for now and future.
> >
> > RISCV platform content would still need to go into edk2-platforms.
> > Non-architectural RISCV CPU content would also need to go into
> > edk2-platforms.
> >
> > Mike
> >
> > *From:* Chang, Abner (HPS SW/FW Technologist) <abner.chang@hpe.com
> > <mailto:abner.chang@hpe.com>>
> > *Sent:* Thursday, May 28, 2020 10:01 PM
> > *To:* Kinney, Michael D <michael.d.kinney@intel.com
> > <mailto:michael.d.kinney@intel.com>>; Bret Barkelew
> > <Bret.Barkelew@microsoft.com <mailto:Bret.Barkelew@microsoft.com>>;
> > Schaefer, Daniel (DualStudy) <daniel.schaefer@hpe.com
> > <mailto:daniel.schaefer@hpe.com>>; Sean Brogan
> > <sean.brogan@microsoft.com <mailto:sean.brogan@microsoft.com>>;
> Ard
> > Biesheuvel (ard.biesheuvel@linaro.org
> > <mailto:ard.biesheuvel@linaro.org>) <ard.biesheuvel@linaro.org
> > <mailto:ard.biesheuvel@linaro.org>>; Zimmer, Vincent
> > <vincent.zimmer@intel.com <mailto:vincent.zimmer@intel.com>>
> > *Cc:* Leif Lindholm <leif@nuviainc.com <mailto:leif@nuviainc.com>>
> > *Subject:* RE: Re: [edk2-devel] [PATCH v2 0/3] New RISC-V Patches -
> > Why in edk2-platforms
> >
> > *From:* Kinney, Michael D [mailto:michael.d.kinney@intel.com]
> > *Sent:* Friday, May 29, 2020 12:36 PM
> > *To:* Bret Barkelew <Bret.Barkelew@microsoft.com
> > <mailto:Bret.Barkelew@microsoft.com>>; Schaefer, Daniel (DualStudy)
> > <daniel.schaefer@hpe.com <mailto:daniel.schaefer@hpe.com>>; Sean
> > Brogan <sean.brogan@microsoft.com
> <mailto:sean.brogan@microsoft.com>>;
> > Ard Biesheuvel (ard.biesheuvel@linaro.org
> > <mailto:ard.biesheuvel@linaro.org>) <ard.biesheuvel@linaro.org
> > <mailto:ard.biesheuvel@linaro.org>>; Kinney, Michael D
> > <michael.d.kinney@intel.com <mailto:michael.d.kinney@intel.com>>;
> > Zimmer, Vincent <vincent.zimmer@intel.com
> > <mailto:vincent.zimmer@intel.com>>
> > *Cc:* Leif Lindholm <leif@nuviainc.com <mailto:leif@nuviainc.com>>;
> > Chang, Abner (HPS SW/FW Technologist) <abner.chang@hpe.com
> > <mailto:abner.chang@hpe.com>>
> > *Subject:* RE: [EXTERNAL] Re: [edk2-devel] [PATCH v2 0/3] New RISC-V
> > Patches - Why in edk2-platforms
> >
> > We did a community review meeting.  I recall Ard and Vincent being
> present.
> >
> > We discuss the CPU execution mode for PEI and DXE and there was a
> > discussion that RISCV has 2 modes and they want flexibility to use
> > both.  This choice is not defined in the PI spec yet.  We suggested
> > that it could follow the ARM/Thumb model and RISCV could choose a
> > single mode for all PEIMs and DXE drivers and choose to go into the
> > other mode in the module implementation as needed.
> >
> > */[Abner] Yes. we done this as we discussed in the community meeting.
> > Those code are belong to RiscV*pkg and currently lay on
> > devel-riscvplatfoms which Leif is reviewing now./*
> >
> > Given that these fundamental CPU execution mode design choices were
> > still in flux, it did not seem like it was ready for edk2 yet.
> >
> > */[Abner] The current implementation is PEI/DXE are in the same
> > mode./*
> >
> > edk2-staging or an edk2-platforms branch seemed more appropriate until
> > all that was worked out.
> >
> > */[Abner] Seems like that work is done. Maybe I have to review PI/UEFI
> > spec for the necessary changes./*
> >
> > edk2-platforms/master seemed ok as well if different RISCV CPU modes
> > would be used for different platform solutions until a unified
> > approach by the RISCV vendors could be determined  Once that was
> > solidified, promoting to edk2 would be possible.
> >
> > */[Abner] this means RicsVPkg and RicsVPlatformPkg eventually will be
> > located in edk2 but not edk2-platforms if above issues are addressed?
> > We don’t have to consider UefiCpuPkg for each arch now? We are good
> > with this though./*
> >
> > Hopefully this clarifies for Leif why there was some resistance to
> > edk2 repo right now.  Still on deck for the future.
> >
> > Mike
> >
> > *From:* Bret Barkelew <Bret.Barkelew@microsoft.com
> > <mailto:Bret.Barkelew@microsoft.com>>
> > *Sent:* Thursday, May 28, 2020 8:11 PM
> > *To:* Daniel Schaefer <daniel.schaefer@hpe.com
> > <mailto:daniel.schaefer@hpe.com>>; Kinney, Michael D
> > <michael.d.kinney@intel.com <mailto:michael.d.kinney@intel.com>>;
> Sean
> > Brogan <sean.brogan@microsoft.com
> <mailto:sean.brogan@microsoft.com>>
> > *Cc:* Leif Lindholm <leif@nuviainc.com <mailto:leif@nuviainc.com>>;
> > Chang, Abner (HPS SW/FW Technologist) <abner.chang@hpe.com
> > <mailto:abner.chang@hpe.com>>
> > *Subject:* RE: [EXTERNAL] Re: [edk2-devel] [PATCH v2 0/3] New RISC-V
> > Patches - Why in edk2-platforms
> >
> > I think Sean has his own feedback, but my response to Abner was that
> > that I didn’t like the idea of continuing a pattern of separate
> > packages for significant portions of the CPU init. There have been a
> > few times where it has created unnecessary divergence that made it
> > very difficult to write cross-architecture code. I, personally, wasn’t
> > fighting the code landing in edk2 (except for RiscVPlatform, because
> > it had platform in the name), but I was inquiring to see whether it
> > made more sense to break things up among Mde, UefiCpu, and a couple
> > other packages to encourage adhering to similar patterns and
> > interfaces between all the different architectures. I’ve previously
> > wondered openly whether it made sense to do the same with the Arm
> packages.
> >
> > I’ll be honest about not being super familiar with the RISCV code and
> > it would be easy for me to just shrug and say put it wherever, but I
> > know that architecture mobility/agility is important for us and
> > wouldn’t be surprised if I had to use RISCV in the future, and so
> > wanted to make sure that it was as close to what I was familiar with as
> possible.
> >
> > - Bret
> >
> > *From: *Daniel Schaefer <mailto:daniel.schaefer@hpe.com>
> > *Sent: *Thursday, May 28, 2020 8:44 AM
> > *To: *Kinney, Michael D <mailto:michael.d.kinney@intel.com>; Bret
> > Barkelew <mailto:Bret.Barkelew@microsoft.com>; Sean Brogan
> > <mailto:sean.brogan@microsoft.com>
> > *Cc: *Leif Lindholm <mailto:leif@nuviainc.com>; Chang, Abner (HPS
> > SW/FW
> > Technologist) <mailto:abner.chang@hpe.com>
> > *Subject: *[EXTERNAL] Re: [edk2-devel] [PATCH v2 0/3] New RISC-V
> > Patches
> > - Why in edk2-platforms
> >
> > Hi Mike, Bret and Sean,
> >
> > you have previously expressed concern about merging HPE's RISC-V code
> > into edk2 and suggested merging it into edk2-platforms. Apparently you
> > discussed this with Abner in a private email thread. According to that
> > information I tried to summarize your points in an email on the edk2 ML.
> > I hope I got it right.
> >
> > As you can see, we have followed that suggestion and sent the new
> > patches required for that to the ML.
> >
> > Leif, and I, are still not convinced it's the right choice to not
> > include it in edk2 proper.
> > We would appreciate if you could address the concerns Leif has
> > mentioned in the below email on the public ML.
> >
> > Thanks!
> > Daniel
> >
> > On 5/28/20 1:54 PM, Leif Lindholm wrote:
> >  > Hi Abner,
> >  >
> >  > Sorry, I should have followed up on this sooner.
> >  >
> >  > On Thu, May 21, 2020 at 06:59:20 +0000, Chang, Abner (HPS SW/FW
> > Technologist) wrote:
> >  >>> On 5/20/20 6:07 PM, Daniel Schaefer wrote:
> >  >>>> please reply here, fixed Mike's email address, sorry...
> >  >>>>
> >  >>>> On 5/20/20 6:03 PM, Daniel Schaefer wrote:
> >  >>>>> On 5/20/20 1:43 PM, Leif Lindholm wrote:
> >  >>>>>> On Fri, May 15, 2020 at 15:39:34 +0200, Daniel Schaefer wrote:
> >  >>>>>>> Previously we had two packages just for RISC-V on our edk2
> branch:
> >  >>>>>>>     RiscVPkg and RiscVPlatformPkg  >>>>>>> They are now under
> > >>>>>>>     Platform/RISC-V/PlatformPkg and
> > Silicon/RISC-V/ProcessorPkg in  >>>>>>> edk2-platforms.
> >  >>>>>>
> >  >>>>>> Understood. I took my eye off the ball there for a while, but
> > I'm a  >>>>>> bit confused as to why RiscVPkg isn't going into EDK2.
> > That is very  >>>>>> counterintuitive. And clearly it will need
> > revisiting if we are to  >>>>>> add first-class CI checks like those we do with
> OvmfPkg/ArmVirtPkg.
> >  >>>>>
> >  >>>>> Yes, I understand your concern. Personally I'd like it also to
> > be in  >>>>> EDK2 straight away, however Mike, Bret and Sean have
> > raised valid  >>>>> concerns:
> >  >
> >  > Can you point me to the conversation I have missed?
> >  >
> >  >>>>> 1. RISC-V is very new and potentially unstable - it's quicker
> > to make  >>>>> changes in edk2-platforms.
> >  >
> >  > I don't see this as a valid argument.
> >  > It's not edk2-unstable, it is edk2-platforms.
> >  >
> >  > edk2-platforms exists because there used to be strong feelings
> > against  > holding *real* platforms in edk2, with edk2 being
> > originally intended  > only as a code library for IBV/ISV to cherry-pick from.
> >  >
> >  > But fundamentally, if code is too immature to go into the master  >
> > branch of edk2, it is too immature to go into the master branch of  >
> > edk2-platforms. If we want edk2-might-be-a-bit-shaky-but-who-cares,
> >  > then someone will have to create it.
> >  >
> >  >>>>> 2. If we define new interfaces and libraries in edk2, we can't
> > remove  >>>>> them easily because it would be a backwards-incompatible
> change.
> >  >>>>> edk2-platforms isn't quite as strict.
> >  >
> >  > Yes it is.
> >  > The only thing making it less strict is its contents - platform
> > ports  > and device drivers. The changes tend to be self-contained.
> > Where they  > are not, they need to be carefully managed.
> >  >
> >  >>>>> 3. Long-term, I think many agree, we should aim to move much of
> > the  >>>>> RISC-V code into UefiCpuPkg and OvmfPkg. Mike mentioned
> > that would  >>>>> need coordination with ARM maintainers because it
> > might make sense to  >>>>> move their code there as well.
> >  >
> >  > I don't think there is any need to tie the two together.
> >  > Yes, UefiCpuPkg should be a generic place where not only x86
> > support  > can be contained, but the paths for ARM* and RISC-V into
> > there do not  > have any interdependencies.
> >

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

end of thread, other threads:[~2020-06-03 15:02 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-05-15 13:39 [PATCH v2 0/3] New RISC-V Patches Daniel Schaefer
2020-05-15 13:39 ` [PATCH v2 1/3] ProcessorPkg/RiscVOpensbLib: Add opensbi submodule Daniel Schaefer
2020-05-20 11:51   ` Leif Lindholm
2020-05-15 13:39 ` [PATCH v2 2/3] ProcessorPkg/Library: Add RiscVOpensbiLib Daniel Schaefer
2020-05-20 12:00   ` Leif Lindholm
2020-05-20 14:44     ` Daniel Schaefer
2020-05-15 13:39 ` [PATCH v2 3/3] ProcessorPkg/Library: Add RiscVEdk2SbiLib Daniel Schaefer
2020-05-20 18:27   ` Leif Lindholm
2020-05-29 12:43     ` [edk2-devel] " Daniel Schaefer
2020-05-29 13:15       ` Leif Lindholm
2020-05-20 11:43 ` [edk2-devel] [PATCH v2 0/3] New RISC-V Patches Leif Lindholm
2020-05-20 16:03   ` [edk2-devel] [PATCH v2 0/3] New RISC-V Patches - Why in edk2-platforms Daniel Schaefer
2020-05-20 16:07     ` Daniel Schaefer
2020-05-20 16:17       ` Daniel Schaefer
2020-05-21  6:59         ` Abner Chang
2020-05-28 11:54           ` Leif Lindholm
2020-05-29 14:41             ` Abner Chang
     [not found]             ` <b55ee3ec-74de-532e-01f7-bd24a327d00b@hpe.com>
     [not found]               ` <CY4PR21MB0743421F39A05298FBCFBAA0EF8F0@CY4PR21MB0743.namprd21.prod.outlook.com>
     [not found]                 ` <MN2PR11MB4461D8666DE6DA1E7D4B5B9BD28F0@MN2PR11MB4461.namprd11.prod.outlook.com>
     [not found]                   ` <TU4PR8401MB1182F755F76709FF1D46D3F2FF8F0@TU4PR8401MB1182.NAMPRD84.PROD.OUTLOOK.COM>
     [not found]                     ` <MN2PR11MB4461442E7462457D6C20F6F2D28F0@MN2PR11MB4461.namprd11.prod.outlook.com>
     [not found]                       ` <MW2PR2101MB092494AB8318628E06B62089E18F0@MW2PR2101MB0924.namprd21.prod.outlook.com>
2020-06-03 11:57                         ` [edk2-devel] Where to put RISC-V packages Daniel Schaefer
2020-06-03 15:02                           ` Abner Chang

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