From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mx0a-002e3701.pphosted.com (mx0a-002e3701.pphosted.com [148.163.147.86]) by mx.groups.io with SMTP id smtpd.web12.2690.1641618749446576958 for ; Fri, 07 Jan 2022 21:12:29 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@hpe.com header.s=pps0720 header.b=Heqg0wCL; spf=permerror, err=parse error for token &{10 18 %{ir}.%{v}.%{d}.spf.has.pphosted.com}: invalid domain name (domain: hpe.com, ip: 148.163.147.86, mailfrom: prvs=000704d8ca=abner.chang@hpe.com) Received: from pps.filterd (m0134420.ppops.net [127.0.0.1]) by mx0b-002e3701.pphosted.com (8.16.1.2/8.16.1.2) with ESMTP id 2081WGUY030485 for ; Sat, 8 Jan 2022 05:12:28 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=hpe.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding; s=pps0720; bh=21LddD549naC2LS2ToeTD2kJK+D0/fOtlHn9N6Ql6a8=; b=Heqg0wCLddehYbJAmmdWDVW2ic33M9ydgA+YrifAr+Q7ftbl75MjGnlFwmx2ry6gmugY fLrsW+MA1YprmaSPHR5WJ0gQpQtMfQXugca+FAYofTqs4nMYr/qKaAC1qkcKMFaTifhC h1qY6NX3XcdierzEAmOxJrTZQg1gXqXqiW/fbQ0gWUR+OSp2LmDMU2l93j2ROlxUAgY6 Xcj3b9Alie9D8RNfSbmUI/vc199/2staOXAhs2GTjIoiX5ZaLJrbiLjtHXgIbWwPpAnD VIykqUuMkk8wWCSH1NBpvG1wZFHHwlAGNTRkDys0JgqL1Ct4E+Zr632ZqsP3Q7mVykR6 LQ== Received: from g2t2354.austin.hpe.com (g2t2354.austin.hpe.com [15.233.44.27]) by mx0b-002e3701.pphosted.com (PPS) with ESMTPS id 3df0049337-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Sat, 08 Jan 2022 05:12:28 +0000 Received: from g2t2360.austin.hpecorp.net (g2t2360.austin.hpecorp.net [16.196.225.135]) by g2t2354.austin.hpe.com (Postfix) with ESMTP id AC08083 for ; Sat, 8 Jan 2022 05:12:27 +0000 (UTC) Received: from UB16Abner.asiapacific.hpqcorp.net (ub16abner.asiapacific.hpqcorp.net [15.119.209.229]) by g2t2360.austin.hpecorp.net (Postfix) with ESMTP id AF13A3D; Sat, 8 Jan 2022 05:12:26 +0000 (UTC) From: "Abner Chang" To: devel@edk2.groups.io Cc: abner.chang@hpe.com Subject: [PATCH 07/79] ProcessorPkg/Library: Add RiscVEdk2SbiLib Date: Sat, 8 Jan 2022 12:10:27 +0800 Message-Id: <20220108041121.16005-6-abner.chang@hpe.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20220108041121.16005-1-abner.chang@hpe.com> References: <20220108041121.16005-1-abner.chang@hpe.com> MIME-Version: 1.0 X-Proofpoint-GUID: O9i4dj2oNL8JbPwz_5AudMYJgCVNNn2N X-Proofpoint-ORIG-GUID: O9i4dj2oNL8JbPwz_5AudMYJgCVNNn2N X-HPE-SCL: -1 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.790,Hydra:6.0.425,FMLib:17.11.62.513 definitions=2022-01-08_01,2022-01-07_01,2021-12-02_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 phishscore=0 mlxlogscore=999 bulkscore=0 impostorscore=0 lowpriorityscore=0 clxscore=1015 priorityscore=1501 suspectscore=0 malwarescore=0 adultscore=0 mlxscore=0 spamscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2110150000 definitions=main-2201080036 Content-Transfer-Encoding: quoted-printable From: Daniel Schaefer (This is migrated from edk2-platforms:Silicon/RISC-V) Library provides interfaces to invoke SBI ecalls. Signed-off-by: Daniel Schaefer Reviewed-by: Leif Lindholm Cc: Leif Lindholm Cc: Gilbert Chen Cc: Abner Chang --- .../RiscVEdk2SbiLib/RiscVEdk2SbiLib.inf | 28 + .../Include/Library/RiscVEdk2SbiLib.h | 563 +++++++++++ .../Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.c | 897 ++++++++++++++++++ 3 files changed, 1488 insertions(+) create mode 100644 Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/Ris= cVEdk2SbiLib.inf create mode 100644 Silicon/RISC-V/ProcessorPkg/Include/Library/RiscVEdk2Sb= iLib.h create mode 100644 Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/Ris= cVEdk2SbiLib.c diff --git a/Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2S= biLib.inf b/Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2Sb= iLib.inf new file mode 100644 index 0000000000..18d6ebc2ac --- /dev/null +++ b/Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.i= nf @@ -0,0 +1,28 @@ +## @file=0D +# RISC-V Library to call SBI ecalls=0D +#=0D +# Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All righ= ts reserved.
=0D +#=0D +# SPDX-License-Identifier: BSD-2-Clause-Patent=0D +#=0D +##=0D +=0D +[Defines]=0D + INF_VERSION =3D 0x0001001b=0D + BASE_NAME =3D RiscVEdk2SbiLib=0D + FILE_GUID =3D 0DF1BBBD-F7E5-4E8A-BCF1-9D63D2DD9FDD=0D + MODULE_TYPE =3D BASE=0D + VERSION_STRING =3D 1.0=0D + LIBRARY_CLASS =3D RiscVEdk2SbiLib=0D +=0D +[Sources]=0D + RiscVEdk2SbiLib.c=0D +=0D +[Packages]=0D + MdePkg/MdePkg.dec=0D + Silicon/RISC-V/ProcessorPkg/RiscVProcessorPkg.dec=0D + Platform/RISC-V/PlatformPkg/RiscVPlatformPkg.dec=0D +=0D +[LibraryClasses]=0D + BaseLib=0D +=0D 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 0000000000..558841a970 --- /dev/null +++ b/Silicon/RISC-V/ProcessorPkg/Include/Library/RiscVEdk2SbiLib.h @@ -0,0 +1,563 @@ +/** @file=0D + Library to call the RISC-V SBI ecalls=0D +=0D + Copyright (c) 2020, Hewlett Packard Development LP. All rights reserved.=
=0D +=0D + SPDX-License-Identifier: BSD-2-Clause-Patent=0D +=0D + @par Glossary:=0D + - Hart - Hardware Thread, similar to a CPU core=0D +**/=0D +=0D +#ifndef RISCV_SBI_LIB_H_=0D +#define RISCV_SBI_LIB_H_=0D +=0D +#include =0D +#include =0D +#include =0D +#include =0D +=0D +//=0D +// EDK2 OpenSBI Firmware extension.=0D +//=0D +#define SBI_EDK2_FW_EXT (SBI_EXT_FIRMWARE_START | SBI_OPENSBI_IMPID)=0D +//=0D +// EDK2 OpenSBI Firmware extension functions.=0D +//=0D +#define SBI_EXT_FW_MSCRATCH_FUNC 0=0D +#define SBI_EXT_FW_MSCRATCH_HARTID_FUNC 1=0D +=0D +//=0D +// EDK2 OpenSBI firmware extension return status.=0D +//=0D +typedef struct {=0D + UINTN Error; ///< SBI status code=0D + UINTN Value; ///< Value returned=0D +} SbiRet;=0D +=0D +/**=0D + Get the implemented SBI specification version=0D +=0D + The minor number of the SBI specification is encoded in the low 24 bits,= =0D + with the major number encoded in the next 7 bits. Bit 32 must be 0 and = is=0D + reserved for future expansion.=0D +=0D + @param[out] SpecVersion The Version of the SBI specification.=0D +**/=0D +VOID=0D +EFIAPI=0D +SbiGetSpecVersion (=0D + OUT UINTN *SpecVersion=0D + );=0D +=0D +/**=0D + Get the SBI implementation ID=0D +=0D + This ID is used to idenetify a specific SBI implementation in order to w= ork=0D + around any quirks it might have.=0D +=0D + @param[out] ImplId The ID of the SBI implementation.=0D +**/=0D +VOID=0D +EFIAPI=0D +SbiGetImplId (=0D + OUT UINTN *ImplId=0D + );=0D +=0D +/**=0D + Get the SBI implementation version=0D +=0D + The version of this SBI implementation.=0D + The encoding of this number is determined by the specific SBI implementa= tion.=0D +=0D + @param[out] ImplVersion The version of the SBI implementation.= =0D +**/=0D +VOID=0D +EFIAPI=0D +SbiGetImplVersion (=0D + OUT UINTN *ImplVersion=0D + );=0D +=0D +/**=0D + Probe whether an SBI extension is available=0D +=0D + ProbeResult is set to 0 if the extension is not available or to an exten= sion=0D + specified value if it is available.=0D +=0D + @param[in] ExtensionId The extension ID.=0D + @param[out] ProbeResult The return value of the probe.=0D +**/=0D +VOID=0D +EFIAPI=0D +SbiProbeExtension (=0D + IN INTN ExtensionId,=0D + OUT INTN *ProbeResult=0D + );=0D +=0D +/**=0D + Get the CPU's vendor ID=0D +=0D + Reads the mvendorid CSR.=0D +=0D + @param[out] MachineVendorId The CPU's vendor ID.=0D +**/=0D +VOID=0D +EFIAPI=0D +SbiGetMachineVendorId (=0D + OUT UINTN *MachineVendorId=0D + );=0D +=0D +/**=0D + Get the CPU's architecture ID=0D +=0D + Reads the marchid CSR.=0D +=0D + @param[out] MachineArchId The CPU's architecture ID.=0D +**/=0D +VOID=0D +EFIAPI=0D +SbiGetMachineArchId (=0D + OUT UINTN *MachineArchId=0D + );=0D +=0D +/**=0D + Get the CPU's implementation ID=0D +=0D + Reads the mimpid CSR.=0D +=0D + @param[out] MachineImplId The CPU's implementation ID.=0D +**/=0D +VOID=0D +EFIAPI=0D +SbiGetMachineImplId (=0D + OUT UINTN *MachineImplId=0D + );=0D +=0D +/**=0D + Politely ask the SBI to start a given hart.=0D +=0D + This call may return before the hart has actually started executing, if = the=0D + SBI implementation can guarantee that the hart is actually going to star= t.=0D +=0D + Before the hart jumps to StartAddr, the hart MUST configure PMP if prese= nt=0D + and switch to S-mode.=0D +=0D + @param[in] HartId The id of the hart to start.=0D + @param[in] StartAddr The physical address, where the hart st= arts=0D + executing from.=0D + @param[in] Priv An XLEN-bit value, which will be in reg= ister=0D + a1 when the hart starts.=0D + @retval EFI_SUCCESS Hart was stopped and will start executi= ng from StartAddr.=0D + @retval EFI_LOAD_ERROR StartAddr is not valid, possibly due to= following reasons:=0D + - It is not a valid physical address.= =0D + - The address is prohibited by PMP to = run in=0D + supervisor mode.=0D + @retval EFI_INVALID_PARAMETER HartId is not a valid hart id=0D + @retval EFI_ALREADY_STARTED The hart is already running.=0D + @retval other The start request failed for unknown re= asons.=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +SbiHartStart (=0D + IN UINTN HartId,=0D + IN UINTN StartAddr,=0D + IN UINTN Priv=0D + );=0D +=0D +/**=0D + Return execution of the calling hart to SBI.=0D +=0D + MUST be called in S-Mode with user interrupts disabled.=0D + This call is not expected to return, unless a failure occurs.=0D +=0D + @retval EFI_SUCCESS Never occurs. When successful, the call= does not return.=0D + @retval other Failed to stop hard for an unknown reas= on.=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +SbiHartStop (=0D + );=0D +=0D +/**=0D + Get the current status of a hart.=0D +=0D + Since harts can transition between states at any time, the status retrie= ved=0D + by this function may already be out of date, once it returns.=0D +=0D + Possible values for HartStatus are:=0D + 0: STARTED=0D + 1: STOPPED=0D + 2: START_REQUEST_PENDING=0D + 3: STOP_REQUEST_PENDING=0D +=0D + @param[out] HartStatus The pointer in which the hart's status = is=0D + stored.=0D + @retval EFI_SUCCESS The operation succeeds.=0D + @retval EFI_INVALID_PARAMETER A parameter is invalid.=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +SbiHartGetStatus (=0D + IN UINTN HartId,=0D + OUT UINTN *HartStatus=0D + );=0D +=0D +///=0D +/// Timer extension=0D +///=0D +=0D +/**=0D + Clear pending timer interrupt bit and set timer for next event after Tim= e.=0D +=0D + To clear the timer without scheduling a timer event, set Time to a=0D + practically infinite value or mask the timer interrupt by clearing sie.S= TIE.=0D +=0D + @param[in] Time The time offset to the next scheduled t= imer interrupt.=0D +**/=0D +VOID=0D +EFIAPI=0D +SbiSetTimer (=0D + IN UINT64 Time=0D + );=0D +=0D +///=0D +/// IPI extension=0D +///=0D +=0D +/**=0D + Send IPI to all harts specified in the mask.=0D +=0D + The interrupts are registered as supervisor software interrupts at the=0D + receiving hart.=0D +=0D + @param[in] HartMask Scalar bit-vector containing hart ids=0D + @param[in] HartMaskBase The starting hartid from which the bit-= vector=0D + must be computed. If set to -1, HartMas= k is=0D + ignored and all harts are considered.=0D + @retval EFI_SUCCESS IPI was sent to all the targeted harts.= =0D + @retval EFI_INVALID_PARAMETER Either hart_mask_base or any of the har= tid=0D + from hart_mask is not valid i.e. either= the=0D + hartid is not enabled by the platform o= r is=0D + not available to the supervisor.=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +SbiSendIpi (=0D + IN UINTN *HartMask,=0D + IN UINTN HartMaskBase=0D + );=0D +=0D +///=0D +/// Remote fence extension=0D +///=0D +=0D +/**=0D + Instructs remote harts to execute a FENCE.I instruction.=0D +=0D + @param[in] HartMask Scalar bit-vector containing hart ids=0D + @param[in] HartMaskBase The starting hartid from which the bit-= vector=0D + must be computed. If set to -1, HartMas= k is=0D + ignored and all harts are considered.=0D + @retval EFI_SUCCESS IPI was sent to all the targeted harts.= =0D + @retval EFI_INVALID_PARAMETER Either hart_mask_base or any of the har= tid=0D + from hart_mask is not valid i.e. either= the=0D + hartid is not enabled by the platform o= r is=0D + not available to the supervisor.=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +SbiRemoteFenceI (=0D + IN UINTN *HartMask,=0D + IN UINTN HartMaskBase=0D + );=0D +=0D +/**=0D + Instructs the remote harts to execute one or more SFENCE.VMA instruction= s.=0D +=0D + The SFENCE.VMA covers the range of virtual addresses between StartAaddr = and Size.=0D +=0D + The remote fence function acts as a full tlb flush if * StartAddr and si= ze=0D + are both 0 * size is equal to 2^XLEN-1=0D +=0D + @param[in] HartMask Scalar bit-vector containing hart ids=0D + @param[in] HartMaskBase The starting hartid from which the bit-= vector=0D + must be computed. If set to -1, HartMas= k is=0D + ignored and all harts are considered.=0D + @param[in] StartAddr The first address of the affected range= .=0D + @param[in] Size How many addresses are affected.=0D + @retval EFI_SUCCESS IPI was sent to all the targeted harts.= =0D + @retval EFI_LOAD_ERROR StartAddr or Size is not valid.=0D + @retval EFI_INVALID_PARAMETER Either hart_mask_base or any of the har= tid=0D + from hart_mask is not valid i.e. either= the=0D + hartid is not enabled by the platform o= r is=0D + not available to the supervisor.=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +SbiRemoteSfenceVma (=0D + IN UINTN *HartMask,=0D + IN UINTN HartMaskBase,=0D + IN UINTN StartAddr,=0D + IN UINTN Size=0D + );=0D +=0D +/**=0D + Instructs the remote harts to execute one or more SFENCE.VMA instruction= s.=0D +=0D + The SFENCE.VMA covers the range of virtual addresses between StartAaddr = and Size.=0D + Covers only the given ASID.=0D +=0D + The remote fence function acts as a full tlb flush if * StartAddr and si= ze=0D + are both 0 * size is equal to 2^XLEN-1=0D +=0D + @param[in] HartMask Scalar bit-vector containing hart ids=0D + @param[in] HartMaskBase The starting hartid from which the bit-= vector=0D + must be computed. If set to -1, HartMas= k is=0D + ignored and all harts are considered.=0D + @param[in] StartAddr The first address of the affected range= .=0D + @param[in] Size How many addresses are affected.=0D + @retval EFI_SUCCESS IPI was sent to all the targeted harts.= =0D + @retval EFI_LOAD_ERROR StartAddr or Size is not valid.=0D + @retval EFI_INVALID_PARAMETER Either hart_mask_base or any of the har= tid=0D + from hart_mask is not valid i.e. either= the=0D + hartid is not enabled by the platform o= r is=0D + not available to the supervisor.=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +SbiRemoteSfenceVmaAsid (=0D + IN UINTN *HartMask,=0D + IN UINTN HartMaskBase,=0D + IN UINTN StartAddr,=0D + IN UINTN Size,=0D + IN UINTN Asid=0D + );=0D +=0D +/**=0D + Instructs the remote harts to execute one or more SFENCE.GVMA instructio= ns.=0D +=0D + The SFENCE.GVMA covers the range of virtual addresses between StartAaddr= and Size.=0D + Covers only the given VMID.=0D + This function call is only valid for harts implementing the hypervisor e= xtension.=0D +=0D + The remote fence function acts as a full tlb flush if * StartAddr and si= ze=0D + are both 0 * size is equal to 2^XLEN-1=0D +=0D + @param[in] HartMask Scalar bit-vector containing hart ids=0D + @param[in] HartMaskBase The starting hartid from which the bit-= vector=0D + must be computed. If set to -1, HartMas= k is=0D + ignored and all harts are considered.=0D + @param[in] StartAddr The first address of the affected range= .=0D + @param[in] Size How many addresses are affected.=0D + @retval EFI_SUCCESS IPI was sent to all the targeted harts.= =0D + @retval EFI_LOAD_ERROR StartAddr or Size is not valid.=0D + @retval EFI_UNSUPPORTED SBI does not implement this function or= one=0D + of the target harts does not support th= e=0D + hypervisor extension.=0D + @retval EFI_INVALID_PARAMETER Either hart_mask_base or any of the har= tid=0D + from hart_mask is not valid i.e. either= the=0D + hartid is not enabled by the platform o= r is=0D + not available to the supervisor.=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +SbiRemoteHfenceGvmaVmid (=0D + IN UINTN *HartMask,=0D + IN UINTN HartMaskBase,=0D + IN UINTN StartAddr,=0D + IN UINTN Size,=0D + IN UINTN Vmid=0D + );=0D +=0D +/**=0D + Instructs the remote harts to execute one or more SFENCE.GVMA instructio= ns.=0D +=0D + The SFENCE.GVMA covers the range of virtual addresses between StartAaddr= and Size.=0D + This function call is only valid for harts implementing the hypervisor e= xtension.=0D +=0D + The remote fence function acts as a full tlb flush if * StartAddr and si= ze=0D + are both 0 * size is equal to 2^XLEN-1=0D +=0D + @param[in] HartMask Scalar bit-vector containing hart ids=0D + @param[in] HartMaskBase The starting hartid from which the bit-= vector=0D + must be computed. If set to -1, HartMas= k is=0D + ignored and all harts are considered.=0D + @param[in] StartAddr The first address of the affected range= .=0D + @param[in] Size How many addresses are affected.=0D + @retval EFI_SUCCESS IPI was sent to all the targeted harts.= =0D + @retval EFI_LOAD_ERROR StartAddr or Size is not valid.=0D + @retval EFI_UNSUPPORTED SBI does not implement this function or= one=0D + of the target harts does not support th= e=0D + hypervisor extension.=0D + @retval EFI_INVALID_PARAMETER Either hart_mask_base or any of the har= tid=0D + from hart_mask is not valid i.e. either= the=0D + hartid is not enabled by the platform o= r is=0D + not available to the supervisor.=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +SbiRemoteHfenceGvma (=0D + IN UINTN *HartMask,=0D + IN UINTN HartMaskBase,=0D + IN UINTN StartAddr,=0D + IN UINTN Size=0D + );=0D +=0D +/**=0D + Instructs the remote harts to execute one or more SFENCE.VVMA instructio= ns.=0D +=0D + The SFENCE.GVMA covers the range of virtual addresses between StartAaddr= and Size.=0D + Covers only the given ASID.=0D + This function call is only valid for harts implementing the hypervisor e= xtension.=0D +=0D + The remote fence function acts as a full tlb flush if * StartAddr and si= ze=0D + are both 0 * size is equal to 2^XLEN-1=0D +=0D + @param[in] HartMask Scalar bit-vector containing hart ids=0D + @param[in] HartMaskBase The starting hartid from which the bit-= vector=0D + must be computed. If set to -1, HartMas= k is=0D + ignored and all harts are considered.=0D + @param[in] StartAddr The first address of the affected range= .=0D + @param[in] Size How many addresses are affected.=0D + @retval EFI_SUCCESS IPI was sent to all the targeted harts.= =0D + @retval EFI_LOAD_ERROR StartAddr or Size is not valid.=0D + @retval EFI_UNSUPPORTED SBI does not implement this function or= one=0D + of the target harts does not support th= e=0D + hypervisor extension.=0D + @retval EFI_INVALID_PARAMETER Either hart_mask_base or any of the har= tid=0D + from hart_mask is not valid i.e. either= the=0D + hartid is not enabled by the platform o= r is=0D + not available to the supervisor.=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +SbiRemoteHfenceVvmaAsid (=0D + IN UINTN *HartMask,=0D + IN UINTN HartMaskBase,=0D + IN UINTN StartAddr,=0D + IN UINTN Size,=0D + IN UINTN Asid=0D + );=0D +=0D +/**=0D + Instructs the remote harts to execute one or more SFENCE.VVMA instructio= ns.=0D +=0D + The SFENCE.GVMA covers the range of virtual addresses between StartAaddr= and Size.=0D + This function call is only valid for harts implementing the hypervisor e= xtension.=0D +=0D + The remote fence function acts as a full tlb flush if * StartAddr and si= ze=0D + are both 0 * size is equal to 2^XLEN-1=0D +=0D + @param[in] HartMask Scalar bit-vector containing hart ids=0D + @param[in] HartMaskBase The starting hartid from which the bit-= vector=0D + must be computed. If set to -1, HartMas= k is=0D + ignored and all harts are considered.=0D + @param[in] StartAddr The first address of the affected range= .=0D + @param[in] Size How many addresses are affected.=0D + @retval EFI_SUCCESS IPI was sent to all the targeted harts.= =0D + @retval EFI_LOAD_ERROR StartAddr or Size is not valid.=0D + @retval EFI_UNSUPPORTED SBI does not implement this function or= one=0D + of the target harts does not support th= e=0D + hypervisor extension.=0D + @retval EFI_INVALID_PARAMETER Either hart_mask_base or any of the har= tid=0D + from hart_mask is not valid i.e. either= the=0D + hartid is not enabled by the platform o= r is=0D + not available to the supervisor.=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +SbiRemoteHfenceVvma (=0D + IN UINTN *HartMask,=0D + IN UINTN HartMaskBase,=0D + IN UINTN StartAddr,=0D + IN UINTN Size=0D + );=0D +=0D +///=0D +/// Vendor Specific extension space: Extension Ids 0x09000000 through 0x09= FFFFFF=0D +///=0D +=0D +/**=0D + Call a function in a vendor defined SBI extension=0D +=0D + ASSERT() if the ExtensionId is not in the designated SBI Vendor Extensio= n=0D + Space.=0D +=0D + @param[in] ExtensionId The SBI vendor extension ID.=0D + @param[in] FunctionId The function ID to call in this extensi= on.=0D + @param[in] NumArgs How many arguments are passed.=0D + @param[in] ... Actual Arguments to the function.=0D + @retval EFI_SUCCESS if the SBI function was called and it was successful= =0D + @retval EFI_INVALID_PARAMETER if NumArgs exceeds 6=0D + @retval others if the called SBI function returns an error=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +SbiVendorCall (=0D + IN UINTN ExtensionId,=0D + IN UINTN FunctionId,=0D + IN UINTN NumArgs,=0D + ...=0D + );=0D +=0D +///=0D +/// Firmware SBI Extension=0D +///=0D +/// This SBI Extension is defined and used by EDK2 only in order to be abl= e to=0D +/// run PI and DXE phase in S-Mode.=0D +///=0D +=0D +/**=0D + Get scratch space of the current hart.=0D +=0D + Please consider using the wrapper SbiGetFirmwareContext if you only need= to=0D + access the firmware context.=0D +=0D + @param[out] ScratchSpace The scratch space pointer.=0D + @retval EFI_SUCCESS The operation succeeds.=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +SbiGetMscratch (=0D + OUT SBI_SCRATCH **ScratchSpace=0D + );=0D +=0D +/**=0D + Get scratch space of the given hart id.=0D +=0D + @param[in] HartId The hart id.=0D + @param[out] ScratchSpace The scratch space pointer.=0D + @retval EFI_SUCCESS The operation succeeds.=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +SbiGetMscratchHartid (=0D + IN UINTN HartId,=0D + OUT SBI_SCRATCH **ScratchSpace=0D + );=0D +=0D +/**=0D + Get firmware context of the calling hart.=0D +=0D + @param[out] FirmwareContext The firmware context pointer.=0D + @retval EFI_SUCCESS The operation succeeds.=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +SbiGetFirmwareContext (=0D + OUT EFI_RISCV_OPENSBI_FIRMWARE_CONTEXT **FirmwareContext=0D + );=0D +=0D +/**=0D + Set firmware context of the calling hart.=0D +=0D + @param[in] FirmwareContext The firmware context pointer.=0D + @retval EFI_SUCCESS The operation succeeds.=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +SbiSetFirmwareContext (=0D + IN EFI_RISCV_OPENSBI_FIRMWARE_CONTEXT *FirmwareContext=0D + );=0D +=0D +#endif=0D diff --git a/Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2S= biLib.c b/Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiL= ib.c new file mode 100644 index 0000000000..0df505d267 --- /dev/null +++ b/Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.c @@ -0,0 +1,897 @@ +/** @file=0D + Instance of the SBI ecall library.=0D +=0D + It allows calling an SBI function via an ecall from S-Mode.=0D +=0D + The legacy extensions are not included because they are not necessary.=0D + They would be:=0D + - SbiLegacySetTimer -> Use SbiSetTimer=0D + - SbiLegacyConsolePutChar -> No replacement - Use regular UEFI func= tions=0D + - SbiLegacyConsoleGetChar -> No replacement - Use regular UEFI func= tions=0D + - SbiLegacyClearIpi -> Write 0 to SSIP=0D + - SbiLegacySendIpi -> Use SbiSendIpi=0D + - SbiLegacyRemoteFenceI -> Use SbiRemoteFenceI=0D + - SbiLegacyRemoteSfenceVma -> Use SbiRemoteSfenceVma=0D + - SbiLegacyRemoteSfenceVmaAsid -> Use SbiRemoteSfenceVmaAsid=0D + - SbiLegacyShutdown -> Wait for new System Reset extension=0D +=0D + Copyright (c) 2020, Hewlett Packard Development LP. All rights reserved.=
=0D + SPDX-License-Identifier: BSD-2-Clause-Patent=0D +=0D + @par Revision Reference:=0D + - OpenSBI Version 0.6=0D +**/=0D +=0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +=0D +=0D +//=0D +// Maximum arguments for SBI ecall=0D +// It's possible to pass more but no SBI call uses more as of SBI 0.2.=0D +// The additional arguments would have to be passed on the stack instead o= f as=0D +// registers, like it's done now.=0D +//=0D +#define SBI_CALL_MAX_ARGS 6=0D +=0D +/**=0D + Call SBI call using ecall instruction.=0D +=0D + Asserts when NumArgs exceeds SBI_CALL_MAX_ARGS.=0D +=0D + @param[in] ExtId SBI extension ID.=0D + @param[in] FuncId SBI function ID.=0D + @param[in] NumArgs Number of arguments to pass to the ecall.=0D + @param[in] ... Argument list for the ecall.=0D +=0D + @retval Returns SbiRet structure with value and error code.=0D +=0D +**/=0D +STATIC=0D +SbiRet=0D +EFIAPI=0D +SbiCall(=0D + IN UINTN ExtId,=0D + IN UINTN FuncId,=0D + IN UINTN NumArgs,=0D + ...=0D + )=0D +{=0D + UINTN I;=0D + SbiRet Ret;=0D + UINTN Args[SBI_CALL_MAX_ARGS];=0D + VA_LIST ArgList;=0D + VA_START (ArgList, NumArgs);=0D +=0D + ASSERT (NumArgs <=3D SBI_CALL_MAX_ARGS);=0D +=0D + for (I =3D 0; I < SBI_CALL_MAX_ARGS; I++) {=0D + if (I < NumArgs) {=0D + Args[I] =3D VA_ARG (ArgList, UINTN);=0D + } else {=0D + // Default to 0 for all arguments that are not given=0D + Args[I] =3D 0;=0D + }=0D + }=0D +=0D + VA_END(ArgList);=0D +=0D + register UINTN a0 asm ("a0") =3D Args[0];=0D + register UINTN a1 asm ("a1") =3D Args[1];=0D + register UINTN a2 asm ("a2") =3D Args[2];=0D + register UINTN a3 asm ("a3") =3D Args[3];=0D + register UINTN a4 asm ("a4") =3D Args[4];=0D + register UINTN a5 asm ("a5") =3D Args[5];=0D + register UINTN a6 asm ("a6") =3D (UINTN)(FuncId);=0D + register UINTN a7 asm ("a7") =3D (UINTN)(ExtId);=0D + asm volatile ("ecall" \=0D + : "+r" (a0), "+r" (a1) \=0D + : "r" (a2), "r" (a3), "r" (a4), "r" (a5), "r" (a6), "r" (a7) \=0D + : "memory"); \=0D + Ret.Error =3D a0;=0D + Ret.Value =3D a1;=0D + return Ret;=0D +}=0D +=0D +/**=0D + Translate SBI error code to EFI status.=0D +=0D + @param[in] SbiError SBI error code=0D + @retval EFI_STATUS=0D +**/=0D +=0D +STATIC=0D +EFI_STATUS=0D +EFIAPI=0D +TranslateError(=0D + IN UINTN SbiError=0D + )=0D +{=0D + switch (SbiError) {=0D + case SBI_SUCCESS:=0D + return EFI_SUCCESS;=0D + case SBI_ERR_FAILED:=0D + return EFI_DEVICE_ERROR;=0D + break;=0D + case SBI_ERR_NOT_SUPPORTED:=0D + return EFI_UNSUPPORTED;=0D + break;=0D + case SBI_ERR_INVALID_PARAM:=0D + return EFI_INVALID_PARAMETER;=0D + break;=0D + case SBI_ERR_DENIED:=0D + return EFI_ACCESS_DENIED;=0D + break;=0D + case SBI_ERR_INVALID_ADDRESS:=0D + return EFI_LOAD_ERROR;=0D + break;=0D + case SBI_ERR_ALREADY_AVAILABLE:=0D + return EFI_ALREADY_STARTED;=0D + break;=0D + default:=0D + //=0D + // Reaches here only if SBI has defined a new error type=0D + //=0D + ASSERT (FALSE);=0D + return EFI_UNSUPPORTED;=0D + break;=0D + }=0D +}=0D +=0D +//=0D +// OpenSBI library interface function for the base extension=0D +//=0D +=0D +/**=0D + Get the implemented SBI specification version=0D +=0D + The minor number of the SBI specification is encoded in the low 24 bits,= =0D + with the major number encoded in the next 7 bits. Bit 32 must be 0 and = is=0D + reserved for future expansion.=0D +=0D + @param[out] SpecVersion The Version of the SBI specification.=0D +**/=0D +VOID=0D +EFIAPI=0D +SbiGetSpecVersion (=0D + OUT UINTN *SpecVersion=0D + )=0D +{=0D + SbiRet Ret =3D SbiCall (SBI_EXT_BASE, SBI_EXT_BASE_GET_SPEC_VERSION, 0);= =0D +=0D + if (!Ret.Error) {=0D + *SpecVersion =3D (UINTN)Ret.Value;=0D + }=0D +}=0D +=0D +/**=0D + Get the SBI implementation ID=0D +=0D + This ID is used to idenetify a specific SBI implementation in order to w= ork=0D + around any quirks it might have.=0D +=0D + @param[out] ImplId The ID of the SBI implementation.=0D +**/=0D +VOID=0D +EFIAPI=0D +SbiGetImplId (=0D + OUT UINTN *ImplId=0D + )=0D +{=0D + SbiRet Ret =3D SbiCall (SBI_EXT_BASE, SBI_EXT_BASE_GET_IMP_ID, 0);=0D + *ImplId =3D (UINTN)Ret.Value;=0D +}=0D +=0D +/**=0D + Get the SBI implementation version=0D +=0D + The version of this SBI implementation.=0D + The encoding of this number is determined by the specific SBI implementa= tion.=0D +=0D + @param[out] ImplVersion The version of the SBI implementation.= =0D +**/=0D +VOID=0D +EFIAPI=0D +SbiGetImplVersion (=0D + OUT UINTN *ImplVersion=0D + )=0D +{=0D + SbiRet Ret =3D SbiCall (SBI_EXT_BASE, SBI_EXT_BASE_GET_IMP_VERSION, 0);= =0D + *ImplVersion =3D (UINTN)Ret.Value;=0D +}=0D +=0D +/**=0D + Probe whether an SBI extension is available=0D +=0D + ProbeResult is set to 0 if the extension is not available or to an exten= sion=0D + specified value if it is available.=0D +=0D + @param[in] ExtensionId The extension ID.=0D + @param[out] ProbeResult The return value of the probe.=0D +**/=0D +VOID=0D +EFIAPI=0D +SbiProbeExtension (=0D + IN INTN ExtensionId,=0D + OUT INTN *ProbeResult=0D + )=0D +{=0D + SbiRet Ret =3D SbiCall (SBI_EXT_BASE, SBI_EXT_BASE_PROBE_EXT, 0);=0D + *ProbeResult =3D (UINTN)Ret.Value;=0D +}=0D +=0D +/**=0D + Get the CPU's vendor ID=0D +=0D + Reads the mvendorid CSR.=0D +=0D + @param[out] MachineVendorId The CPU's vendor ID.=0D +**/=0D +VOID=0D +EFIAPI=0D +SbiGetMachineVendorId (=0D + OUT UINTN *MachineVendorId=0D + )=0D +{=0D + SbiRet Ret =3D SbiCall (SBI_EXT_BASE, SBI_EXT_BASE_GET_MVENDORID, 0);=0D + *MachineVendorId =3D (UINTN)Ret.Value;=0D +}=0D +=0D +/**=0D + Get the CPU's architecture ID=0D +=0D + Reads the marchid CSR.=0D +=0D + @param[out] MachineArchId The CPU's architecture ID.=0D +**/=0D +VOID=0D +EFIAPI=0D +SbiGetMachineArchId (=0D + OUT UINTN *MachineArchId=0D + )=0D +{=0D + SbiRet Ret =3D SbiCall (SBI_EXT_BASE, SBI_EXT_BASE_GET_MARCHID, 0);=0D + *MachineArchId =3D (UINTN)Ret.Value;=0D +}=0D +=0D +/**=0D + Get the CPU's architecture ID=0D +=0D + Reads the marchid CSR.=0D +=0D + @param[out] MachineImplId The CPU's implementation ID.=0D +**/=0D +VOID=0D +EFIAPI=0D +SbiGetMachineImplId (=0D + OUT UINTN *MachineImplId=0D + )=0D +{=0D + SbiRet Ret =3D SbiCall (SBI_EXT_BASE, SBI_EXT_BASE_GET_MIMPID, 0);=0D + *MachineImplId =3D (UINTN)Ret.Value;=0D +}=0D +=0D +//=0D +// SBI interface function for the hart state management extension=0D +//=0D +=0D +/**=0D + Politely ask the SBI to start a given hart.=0D +=0D + This call may return before the hart has actually started executing, if = the=0D + SBI implementation can guarantee that the hart is actually going to star= t.=0D +=0D + Before the hart jumps to StartAddr, the hart MUST configure PMP if prese= nt=0D + and switch to S-mode.=0D +=0D + @param[in] HartId The id of the hart to start.=0D + @param[in] StartAddr The physical address, where the hart st= arts=0D + executing from.=0D + @param[in] Priv An XLEN-bit value, which will be in reg= ister=0D + a1 when the hart starts.=0D + @retval EFI_SUCCESS Hart was stopped and will start executi= ng from StartAddr.=0D + @retval EFI_LOAD_ERROR StartAddr is not valid, possibly due to= following reasons:=0D + - It is not a valid physical address.= =0D + - The address is prohibited by PMP to= run in=0D + supervisor mode.=0D + @retval EFI_INVALID_PARAMETER HartId is not a valid hart id=0D + @retval EFI_ALREADY_STARTED The hart is already running.=0D + @retval other The start request failed for unknown re= asons.=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +SbiHartStart (=0D + IN UINTN HartId,=0D + IN UINTN StartAddr,=0D + IN UINTN Priv=0D + )=0D +{=0D + SbiRet Ret =3D SbiCall (=0D + SBI_EXT_HSM,=0D + SBI_EXT_HSM_HART_START,=0D + 3,=0D + HartId,=0D + StartAddr,=0D + Priv=0D + );=0D + return TranslateError (Ret.Error);=0D +}=0D +=0D +/**=0D + Return execution of the calling hart to SBI.=0D +=0D + MUST be called in S-Mode with user interrupts disabled.=0D + This call is not expected to return, unless a failure occurs.=0D +=0D + @retval EFI_SUCCESS Never occurs. When successful, the call= does not return.=0D + @retval other Failed to stop hard for an unknown reas= on.=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +SbiHartStop (=0D + )=0D +{=0D + SbiRet Ret =3D SbiCall (SBI_EXT_HSM, SBI_EXT_HSM_HART_STOP, 0);=0D + return TranslateError (Ret.Error);=0D +}=0D +=0D +/**=0D + Get the current status of a hart.=0D +=0D + Since harts can transition between states at any time, the status retrie= ved=0D + by this function may already be out of date, once it returns.=0D +=0D + Possible values for HartStatus are:=0D + 0: STARTED=0D + 1: STOPPED=0D + 2: START_REQUEST_PENDING=0D + 3: STOP_REQUEST_PENDING=0D +=0D + @param[out] HartStatus The pointer in which the hart's status = is=0D + stored.=0D + @retval EFI_SUCCESS The operation succeeds.=0D + @retval EFI_INVALID_PARAMETER A parameter is invalid.=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +SbiHartGetStatus (=0D + IN UINTN HartId,=0D + OUT UINTN *HartStatus=0D + )=0D +{=0D + SbiRet Ret =3D SbiCall (SBI_EXT_HSM, SBI_EXT_HSM_HART_GET_STATUS, 1, Har= tId);=0D +=0D + if (!Ret.Error) {=0D + *HartStatus =3D (UINTN)Ret.Value;=0D + }=0D +=0D + return TranslateError (Ret.Error);=0D +}=0D +=0D +/**=0D + Clear pending timer interrupt bit and set timer for next event after Tim= e.=0D +=0D + To clear the timer without scheduling a timer event, set Time to a=0D + practically infinite value or mask the timer interrupt by clearing sie.S= TIE.=0D +=0D + @param[in] Time The time offset to the next scheduled t= imer interrupt.=0D +**/=0D +VOID=0D +EFIAPI=0D +SbiSetTimer (=0D + IN UINT64 Time=0D + )=0D +{=0D + SbiCall (SBI_EXT_TIME, SBI_EXT_TIME_SET_TIMER, 1, Time);=0D +}=0D +=0D +EFI_STATUS=0D +EFIAPI=0D +SbiSendIpi (=0D + IN UINTN *HartMask,=0D + IN UINTN HartMaskBase=0D + )=0D +{=0D + SbiRet Ret =3D SbiCall (=0D + SBI_EXT_IPI,=0D + SBI_EXT_IPI_SEND_IPI,=0D + 2,=0D + (UINTN)HartMask,=0D + HartMaskBase=0D + );=0D + return TranslateError (Ret.Error);=0D +}=0D +=0D +/**=0D + Instructs remote harts to execute a FENCE.I instruction.=0D +=0D + @param[in] HartMask Scalar bit-vector containing hart ids=0D + @param[in] HartMaskBase The starting hartid from which the bit-= vector=0D + must be computed. If set to -1, HartMas= k is=0D + ignored and all harts are considered.=0D + @retval EFI_SUCCESS IPI was sent to all the targeted harts.= =0D + @retval EFI_INVALID_PARAMETER Either hart_mask_base or any of the har= tid=0D + from hart_mask is not valid i.e. either= the=0D + hartid is not enabled by the platform o= r is=0D + not available to the supervisor.=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +SbiRemoteFenceI (=0D + IN UINTN *HartMask,=0D + IN UINTN HartMaskBase=0D + )=0D +{=0D + SbiRet Ret =3D SbiCall (=0D + SBI_EXT_RFENCE,=0D + SBI_EXT_RFENCE_REMOTE_FENCE_I,=0D + 2,=0D + (UINTN)HartMask,=0D + HartMaskBase=0D + );=0D + return TranslateError (Ret.Error);=0D +}=0D +=0D +/**=0D + Instructs the remote harts to execute one or more SFENCE.VMA instruction= s.=0D +=0D + The SFENCE.VMA covers the range of virtual addresses between StartAaddr = and Size.=0D +=0D + The remote fence function acts as a full tlb flush if * StartAddr and si= ze=0D + are both 0 * size is equal to 2^XLEN-1=0D +=0D + @param[in] HartMask Scalar bit-vector containing hart ids=0D + @param[in] HartMaskBase The starting hartid from which the bit-= vector=0D + must be computed. If set to -1, HartMas= k is=0D + ignored and all harts are considered.=0D + @param[in] StartAddr The first address of the affected range= .=0D + @param[in] Size How many addresses are affected.=0D + @retval EFI_SUCCESS IPI was sent to all the targeted harts.= =0D + @retval EFI_LOAD_ERROR StartAddr or Size is not valid.=0D + @retval EFI_INVALID_PARAMETER Either hart_mask_base or any of the har= tid=0D + from hart_mask is not valid i.e. either= the=0D + hartid is not enabled by the platform o= r is=0D + not available to the supervisor.=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +SbiRemoteSfenceVma (=0D + IN UINTN *HartMask,=0D + IN UINTN HartMaskBase,=0D + IN UINTN StartAddr,=0D + IN UINTN Size=0D + )=0D +{=0D + SbiRet Ret =3D SbiCall (=0D + SBI_EXT_RFENCE,=0D + SBI_EXT_RFENCE_REMOTE_SFENCE_VMA,=0D + 4,=0D + (UINTN)HartMask,=0D + HartMaskBase,=0D + StartAddr,=0D + Size=0D + );=0D + return TranslateError (Ret.Error);=0D +}=0D +=0D +/**=0D + Instructs the remote harts to execute one or more SFENCE.VMA instruction= s.=0D +=0D + The SFENCE.VMA covers the range of virtual addresses between StartAaddr = and Size.=0D + Covers only the given ASID.=0D +=0D + The remote fence function acts as a full tlb flush if * StartAddr and si= ze=0D + are both 0 * size is equal to 2^XLEN-1=0D +=0D + @param[in] HartMask Scalar bit-vector containing hart ids=0D + @param[in] HartMaskBase The starting hartid from which the bit-= vector=0D + must be computed. If set to -1, HartMas= k is=0D + ignored and all harts are considered.=0D + @param[in] StartAddr The first address of the affected range= .=0D + @param[in] Size How many addresses are affected.=0D + @retval EFI_SUCCESS IPI was sent to all the targeted harts.= =0D + @retval EFI_LOAD_ERROR StartAddr or Size is not valid.=0D + @retval EFI_INVALID_PARAMETER Either hart_mask_base or any of the har= tid=0D + from hart_mask is not valid i.e. either= the=0D + hartid is not enabled by the platform o= r is=0D + not available to the supervisor.=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +SbiRemoteSfenceVmaAsid (=0D + IN UINTN *HartMask,=0D + IN UINTN HartMaskBase,=0D + IN UINTN StartAddr,=0D + IN UINTN Size,=0D + IN UINTN Asid=0D + )=0D +{=0D + SbiRet Ret =3D SbiCall (=0D + SBI_EXT_RFENCE,=0D + SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID,=0D + 5,=0D + (UINTN)HartMask,=0D + HartMaskBase,=0D + StartAddr,=0D + Size,=0D + Asid=0D + );=0D + return TranslateError (Ret.Error);=0D +}=0D +=0D +/**=0D + Instructs the remote harts to execute one or more SFENCE.GVMA instructio= ns.=0D +=0D + The SFENCE.GVMA covers the range of virtual addresses between StartAaddr= and Size.=0D + Covers only the given VMID.=0D + This function call is only valid for harts implementing the hypervisor e= xtension.=0D +=0D + The remote fence function acts as a full tlb flush if * StartAddr and si= ze=0D + are both 0 * size is equal to 2^XLEN-1=0D +=0D + @param[in] HartMask Scalar bit-vector containing hart ids=0D + @param[in] HartMaskBase The starting hartid from which the bit-= vector=0D + must be computed. If set to -1, HartMas= k is=0D + ignored and all harts are considered.=0D + @param[in] StartAddr The first address of the affected range= .=0D + @param[in] Size How many addresses are affected.=0D + @retval EFI_SUCCESS IPI was sent to all the targeted harts.= =0D + @retval EFI_LOAD_ERROR StartAddr or Size is not valid.=0D + @retval EFI_UNSUPPORTED SBI does not implement this function or= one=0D + of the target harts does not support th= e=0D + hypervisor extension.=0D + @retval EFI_INVALID_PARAMETER Either hart_mask_base or any of the har= tid=0D + from hart_mask is not valid i.e. either= the=0D + hartid is not enabled by the platform o= r is=0D + not available to the supervisor.=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +SbiRemoteHFenceGvmaVmid (=0D + IN UINTN *HartMask,=0D + IN UINTN HartMaskBase,=0D + IN UINTN StartAddr,=0D + IN UINTN Size,=0D + IN UINTN Vmid=0D + )=0D +{=0D + SbiRet Ret =3D SbiCall (=0D + SBI_EXT_RFENCE,=0D + SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA,=0D + 5,=0D + (UINTN)HartMask,=0D + HartMaskBase,=0D + StartAddr,=0D + Size,=0D + Vmid=0D + );=0D + return TranslateError (Ret.Error);=0D +}=0D +=0D +/**=0D + Instructs the remote harts to execute one or more SFENCE.GVMA instructio= ns.=0D +=0D + The SFENCE.GVMA covers the range of virtual addresses between StartAaddr= and Size.=0D + This function call is only valid for harts implementing the hypervisor e= xtension.=0D +=0D + The remote fence function acts as a full tlb flush if * StartAddr and si= ze=0D + are both 0 * size is equal to 2^XLEN-1=0D +=0D + @param[in] HartMask Scalar bit-vector containing hart ids=0D + @param[in] HartMaskBase The starting hartid from which the bit-= vector=0D + must be computed. If set to -1, HartMas= k is=0D + ignored and all harts are considered.=0D + @param[in] StartAddr The first address of the affected range= .=0D + @param[in] Size How many addresses are affected.=0D + @retval EFI_SUCCESS IPI was sent to all the targeted harts.= =0D + @retval EFI_LOAD_ERROR StartAddr or Size is not valid.=0D + @retval EFI_UNSUPPORTED SBI does not implement this function or= one=0D + of the target harts does not support th= e=0D + hypervisor extension.=0D + @retval EFI_INVALID_PARAMETER Either hart_mask_base or any of the har= tid=0D + from hart_mask is not valid i.e. either= the=0D + hartid is not enabled by the platform o= r is=0D + not available to the supervisor.=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +SbiRemoteHFenceGvma (=0D + IN UINTN *HartMask,=0D + IN UINTN HartMaskBase,=0D + IN UINTN StartAddr,=0D + IN UINTN Size=0D + )=0D +{=0D + SbiRet Ret =3D SbiCall (=0D + SBI_EXT_RFENCE,=0D + SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA_VMID,=0D + 4,=0D + (UINTN)HartMask,=0D + HartMaskBase,=0D + StartAddr,=0D + Size=0D + );=0D + return TranslateError (Ret.Error);=0D +}=0D +=0D +/**=0D + Instructs the remote harts to execute one or more SFENCE.VVMA instructio= ns.=0D +=0D + The SFENCE.GVMA covers the range of virtual addresses between StartAaddr= and Size.=0D + Covers only the given ASID.=0D + This function call is only valid for harts implementing the hypervisor e= xtension.=0D +=0D + The remote fence function acts as a full tlb flush if * StartAddr and si= ze=0D + are both 0 * size is equal to 2^XLEN-1=0D +=0D + @param[in] HartMask Scalar bit-vector containing hart ids=0D + @param[in] HartMaskBase The starting hartid from which the bit-= vector=0D + must be computed. If set to -1, HartMas= k is=0D + ignored and all harts are considered.=0D + @param[in] StartAddr The first address of the affected range= .=0D + @param[in] Size How many addresses are affected.=0D + @retval EFI_SUCCESS IPI was sent to all the targeted harts.= =0D + @retval EFI_LOAD_ERROR StartAddr or Size is not valid.=0D + @retval EFI_UNSUPPORTED SBI does not implement this function or= one=0D + of the target harts does not support th= e=0D + hypervisor extension.=0D + @retval EFI_INVALID_PARAMETER Either hart_mask_base or any of the har= tid=0D + from hart_mask is not valid i.e. either= the=0D + hartid is not enabled by the platform o= r is=0D + not available to the supervisor.=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +SbiRemoteHFenceVvmaAsid (=0D + IN UINTN *HartMask,=0D + IN UINTN HartMaskBase,=0D + IN UINTN StartAddr,=0D + IN UINTN Size,=0D + IN UINTN Asid=0D + )=0D +{=0D + SbiRet Ret =3D SbiCall (=0D + SBI_EXT_RFENCE,=0D + SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA,=0D + 5,=0D + (UINTN)HartMask,=0D + HartMaskBase,=0D + StartAddr,=0D + Size,=0D + Asid=0D + );=0D + return TranslateError (Ret.Error);=0D +}=0D +=0D +/**=0D + Instructs the remote harts to execute one or more SFENCE.VVMA instructio= ns.=0D +=0D + The SFENCE.GVMA covers the range of virtual addresses between StartAaddr= and Size.=0D + This function call is only valid for harts implementing the hypervisor e= xtension.=0D +=0D + The remote fence function acts as a full tlb flush if * StartAddr and si= ze=0D + are both 0 * size is equal to 2^XLEN-1=0D +=0D + @param[in] HartMask Scalar bit-vector containing hart ids=0D + @param[in] HartMaskBase The starting hartid from which the bit-= vector=0D + must be computed. If set to -1, HartMas= k is=0D + ignored and all harts are considered.=0D + @param[in] StartAddr The first address of the affected range= .=0D + @param[in] Size How many addresses are affected.=0D + @retval EFI_SUCCESS IPI was sent to all the targeted harts.= =0D + @retval EFI_LOAD_ERROR StartAddr or Size is not valid.=0D + @retval EFI_UNSUPPORTED SBI does not implement this function or= one=0D + of the target harts does not support th= e=0D + hypervisor extension.=0D + @retval EFI_INVALID_PARAMETER Either hart_mask_base or any of the har= tid=0D + from hart_mask is not valid i.e. either= the=0D + hartid is not enabled by the platform o= r is=0D + not available to the supervisor.=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +SbiRemoteHFenceVvma (=0D + IN UINTN *HartMask,=0D + IN UINTN HartMaskBase,=0D + IN UINTN StartAddr,=0D + IN UINTN Size=0D + )=0D +{=0D + SbiRet Ret =3D SbiCall (=0D + SBI_EXT_RFENCE,=0D + SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA_ASID,=0D + 4,=0D + (UINTN)HartMask,=0D + HartMaskBase,=0D + StartAddr,=0D + Size=0D + );=0D + return TranslateError (Ret.Error);=0D +}=0D +=0D +//=0D +// SBI interface function for the vendor extension=0D +//=0D +=0D +/**=0D + Call a function in a vendor defined SBI extension=0D +=0D + ASSERT() if the ExtensionId is not in the designated SBI Vendor Extensio= n=0D + Space or NumArgs exceeds SBI_CALL_MAX_ARGS.=0D +=0D + @param[in] ExtensionId The SBI vendor extension ID.=0D + @param[in] FunctionId The function ID to call in this extensi= on.=0D + @param[in] NumArgs How many arguments are passed.=0D + @param[in] ... Actual Arguments to the function.=0D + @retval EFI_SUCCESS if the SBI function was called and it was successful= =0D + @retval others if the called SBI function returns an error=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +SbiVendorCall (=0D + IN UINTN ExtensionId,=0D + IN UINTN FunctionId,=0D + IN UINTN NumArgs,=0D + ...=0D + )=0D +{=0D + SbiRet Ret;=0D + VA_LIST Args;=0D + VA_START (Args, NumArgs);=0D +=0D + ASSERT (ExtensionId >=3D SBI_EXT_VENDOR_START && ExtensionId <=3D SBI_= EXT_VENDOR_END);=0D + ASSERT (NumArgs <=3D SBI_CALL_MAX_ARGS);=0D +=0D + switch (NumArgs) {=0D + case 0:=0D + Ret =3D SbiCall (ExtensionId, FunctionId, NumArgs);=0D + break;=0D + case 1:=0D + Ret =3D SbiCall (ExtensionId, FunctionId, NumArgs, VA_ARG (Args, U= INTN));=0D + break;=0D + case 2:=0D + Ret =3D SbiCall (ExtensionId, FunctionId, NumArgs, VA_ARG (Args, U= INTN),=0D + VA_ARG (Args, UINTN));=0D + break;=0D + case 3:=0D + Ret =3D SbiCall (ExtensionId, FunctionId, NumArgs, VA_ARG (Args, U= INTN),=0D + VA_ARG (Args, UINTN), VA_ARG (Args, UINTN));=0D + break;=0D + case 4:=0D + Ret =3D SbiCall (ExtensionId, FunctionId, NumArgs, VA_ARG (Args, U= INTN),=0D + VA_ARG (Args, UINTN), VA_ARG (Args, UINTN),=0D + VA_ARG (Args, UINTN));=0D + break;=0D + case 5:=0D + Ret =3D SbiCall (ExtensionId, FunctionId, NumArgs, VA_ARG (Args, U= INTN),=0D + VA_ARG (Args, UINTN), VA_ARG (Args, UINTN),=0D + VA_ARG (Args, UINTN), VA_ARG (Args, UINTN));=0D + break;=0D + case 6:=0D + Ret =3D SbiCall (ExtensionId, FunctionId, NumArgs, VA_ARG (Args, U= INTN),=0D + VA_ARG (Args, UINTN), VA_ARG (Args, UINTN),=0D + VA_ARG (Args, UINTN), VA_ARG (Args, UINTN),=0D + VA_ARG (Args, UINTN));=0D + break;=0D + default:=0D + // Too many args. In theory SBI can handle more arguments when the= y are=0D + // passed on the stack but no SBI extension uses this, therefore i= t's=0D + // not yet implemented here.=0D + return EFI_INVALID_PARAMETER;=0D + }=0D +=0D + VA_END(Args);=0D + return TranslateError (Ret.Error);=0D +}=0D +=0D +//=0D +// SBI Firmware extension=0D +//=0D +=0D +/**=0D + Get scratch space of the current hart.=0D +=0D + Please consider using the wrapper SbiGetFirmwareContext if you only need= to=0D + access the firmware context.=0D +=0D + @param[out] ScratchSpace The scratch space pointer.=0D + @retval EFI_SUCCESS The operation succeeds.=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +SbiGetMscratch (=0D + OUT SBI_SCRATCH **ScratchSpace=0D + )=0D +{=0D + SbiRet Ret =3D SbiCall (SBI_EDK2_FW_EXT, SBI_EXT_FW_MSCRATCH_FUNC, 0);=0D +=0D + if (!Ret.Error) {=0D + *ScratchSpace =3D (SBI_SCRATCH *)Ret.Value;=0D + }=0D +=0D + return EFI_SUCCESS;=0D +}=0D +=0D +/**=0D + Get scratch space of the given hart id.=0D +=0D + @param[in] HartId The hart id.=0D + @param[out] ScratchSpace The scratch space pointer.=0D + @retval EFI_SUCCESS The operation succeeds.=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +SbiGetMscratchHartid (=0D + IN UINTN HartId,=0D + OUT SBI_SCRATCH **ScratchSpace=0D + )=0D +{=0D + SbiRet Ret =3D SbiCall (=0D + SBI_EDK2_FW_EXT,=0D + SBI_EXT_FW_MSCRATCH_HARTID_FUNC,=0D + 1,=0D + HartId=0D + );=0D +=0D + if (!Ret.Error) {=0D + *ScratchSpace =3D (SBI_SCRATCH *)Ret.Value;=0D + }=0D +=0D + return EFI_SUCCESS;=0D +}=0D +=0D +/**=0D + Get firmware context of the calling hart.=0D +=0D + @param[out] FirmwareContext The firmware context pointer.=0D + @retval EFI_SUCCESS The operation succeeds.=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +SbiGetFirmwareContext (=0D + OUT EFI_RISCV_OPENSBI_FIRMWARE_CONTEXT **FirmwareContext=0D + )=0D +{=0D + SBI_SCRATCH *ScratchSpace;=0D + SBI_PLATFORM *SbiPlatform;=0D + SbiRet Ret =3D SbiCall (SBI_EDK2_FW_EXT, SBI_EXT_FW_MSCRATCH_FUNC, 0);=0D +=0D + if (!Ret.Error) {=0D + ScratchSpace =3D (SBI_SCRATCH *)Ret.Value;=0D + SbiPlatform =3D (SBI_PLATFORM *)sbi_platform_ptr(ScratchSpace);=0D + *FirmwareContext =3D (EFI_RISCV_OPENSBI_FIRMWARE_CONTEXT *)SbiPlatform= ->firmware_context;=0D + }=0D +=0D + return EFI_SUCCESS;=0D +}=0D +=0D +/**=0D + Set firmware context of the calling hart.=0D +=0D + @param[in] FirmwareContext The firmware context pointer.=0D + @retval EFI_SUCCESS The operation succeeds.=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +SbiSetFirmwareContext (=0D + IN EFI_RISCV_OPENSBI_FIRMWARE_CONTEXT *FirmwareContext=0D + )=0D +{=0D + SBI_SCRATCH *ScratchSpace;=0D + SBI_PLATFORM *SbiPlatform;=0D + SbiRet Ret =3D SbiCall (SBI_EDK2_FW_EXT, SBI_EXT_FW_MSCRATCH_FUNC, 0);=0D +=0D + if (!Ret.Error) {=0D + ScratchSpace =3D (SBI_SCRATCH *)Ret.Value;=0D + SbiPlatform =3D (SBI_PLATFORM *)sbi_platform_ptr (ScratchSpace);=0D + SbiPlatform->firmware_context =3D (UINTN)FirmwareContext;=0D + }=0D +=0D + return EFI_SUCCESS;=0D +}=0D --=20 2.31.1