From: "Daniel Schaefer" <daniel.schaefer@hpe.com>
To: <devel@edk2.groups.io>
Cc: Abner Chang <abner.chang@hpe.com>,
Gilbert Chen <gilbert.chen@hpe.com>,
Michael D Kinney <michael.k.kinney@intel.com>,
Leif Lindholm <leif@nuviainc.com>
Subject: [PATCH v2 3/3] ProcessorPkg/Library: Add RiscVEdk2SbiLib
Date: Fri, 15 May 2020 15:39:37 +0200 [thread overview]
Message-ID: <20200515133937.29909-4-daniel.schaefer@hpe.com> (raw)
In-Reply-To: <20200515133937.29909-1-daniel.schaefer@hpe.com>
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
next prev parent reply other threads:[~2020-05-15 13:40 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
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 ` Daniel Schaefer [this message]
2020-05-20 18:27 ` [PATCH v2 3/3] ProcessorPkg/Library: Add RiscVEdk2SbiLib 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
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200515133937.29909-4-daniel.schaefer@hpe.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox