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.web11.33814.1590756246681843353 for ; Fri, 29 May 2020 05:44:06 -0700 Authentication-Results: mx.groups.io; dkim=missing; spf=pass (domain: hpe.com, ip: 148.163.147.86, mailfrom: prvs=041837a23b=daniel.schaefer@hpe.com) Received: from pps.filterd (m0134421.ppops.net [127.0.0.1]) by mx0b-002e3701.pphosted.com (8.16.0.42/8.16.0.42) with SMTP id 04TCeQHE019882; Fri, 29 May 2020 12:44:06 GMT Received: from g4t3427.houston.hpe.com (g4t3427.houston.hpe.com [15.241.140.73]) by mx0b-002e3701.pphosted.com with ESMTP id 319x3g0mv0-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 29 May 2020 12:44:05 +0000 Received: from G1W8106.americas.hpqcorp.net (g1w8106.austin.hp.com [16.193.72.61]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384 (256/256 bits)) (No client certificate requested) by g4t3427.houston.hpe.com (Postfix) with ESMTPS id F29E457; Fri, 29 May 2020 12:44:04 +0000 (UTC) Received: from G9W8674.americas.hpqcorp.net (16.220.49.0) by G1W8106.americas.hpqcorp.net (16.193.72.61) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Fri, 29 May 2020 12:43:51 +0000 Received: from G2W6311.americas.hpqcorp.net (16.197.64.53) by G9W8674.americas.hpqcorp.net (16.220.49.0) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Fri, 29 May 2020 12:43:50 +0000 Received: from NAM10-DM6-obe.outbound.protection.outlook.com (15.241.52.11) by G2W6311.americas.hpqcorp.net (16.197.64.53) with Microsoft SMTP Server (TLS) id 15.0.1497.2 via Frontend Transport; Fri, 29 May 2020 12:43:50 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=SRkC52LbCKjPkq3mAb2mUIVLvSkndtgjLnp8b3cn7scR8k35mhrWSHwYrbaxLN0tR0DOn9H5rLwJh28Ju9YjsyHcTuI69Vrk0Dc1qrXysnfB2Pbup92TDfinhkjEPzXOU7pK3s7So53RyzeIjr7yxXNEfIuJWfw61yJlM07V2p7sthBUKn4avRTAreEFsZtofT2pmMmw5qYc8CC1gFkbxES8wZ7Svx6jjYDGLfNwM8F1AjYDcK9yXGoyBS/6IPVdst5LDgBZ0qLHdOnxbOFCdbZboiA7hRC9b/o2GJJ1z/u2zpZkH9MXj+cnLQGXU4ZKRqmuQUEeMYofZA7EYOMWpQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=1/FLIOhwGud/a3aVMbMp9wyZk6sYl+mdgUWBdYIRev8=; b=nxRUHjRMcPQRjwmA+RocqMAk8Av1Y1h1U/de+q26Dyunl++qE6Y52MkR2wCYmYD6IAp2bzA4BmHLXOKhi/lRglSeh4GIz022YBIPD0M139r2euKyiYJTxOt6mG+WBW+zCcgx8zzyVXDMed6O8y4z5ovTfwnEJbROog4ta/hKl7EB5lrJT/M3mhpfU8/lUFxXja1MylWa7fy+foXygjiPKTNwyM8t4pAQS06eaAMBVaNVxJNL77KVasO2uPiDYAuyfJM8n9UvRhyyifTBE501GSnG9KQYeYj6+/LdU0NR/JyFa3Z2Z8J5LKhyt+vSvi/Wniu1OLo+vOy9OOxusn9bVg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=hpe.com; dmarc=pass action=none header.from=hpe.com; dkim=pass header.d=hpe.com; arc=none Authentication-Results: intel.com; dkim=none (message not signed) header.d=none;intel.com; dmarc=none action=none header.from=hpe.com; Received: from DF4PR8401MB0474.NAMPRD84.PROD.OUTLOOK.COM (2a01:111:e400:7607::10) by DF4PR8401MB1004.NAMPRD84.PROD.OUTLOOK.COM (2a01:111:e400:760f::8) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3021.24; Fri, 29 May 2020 12:43:48 +0000 Received: from DF4PR8401MB0474.NAMPRD84.PROD.OUTLOOK.COM ([fe80::c4c5:a5a7:6deb:da30]) by DF4PR8401MB0474.NAMPRD84.PROD.OUTLOOK.COM ([fe80::c4c5:a5a7:6deb:da30%9]) with mapi id 15.20.3021.030; Fri, 29 May 2020 12:43:48 +0000 Subject: Re: [edk2-devel] [PATCH v2 3/3] ProcessorPkg/Library: Add RiscVEdk2SbiLib To: , CC: Abner Chang , Gilbert Chen , Michael D Kinney References: <20200515133937.29909-1-daniel.schaefer@hpe.com> <20200515133937.29909-4-daniel.schaefer@hpe.com> <20200520182729.GN1923@vanye> From: "Daniel Schaefer" Message-ID: <492edaee-f3a1-9d36-0dc0-c70564912d2c@hpe.com> Date: Fri, 29 May 2020 14:43:43 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.7.0 In-Reply-To: <20200520182729.GN1923@vanye> X-ClientProxiedBy: DM5PR13CA0056.namprd13.prod.outlook.com (2603:10b6:3:117::18) To DF4PR8401MB0474.NAMPRD84.PROD.OUTLOOK.COM (2a01:111:e400:7607::10) X-MS-Exchange-MessageSentRepresentingType: 1 Received: from [192.168.178.165] (93.215.216.32) by DM5PR13CA0056.namprd13.prod.outlook.com (2603:10b6:3:117::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3066.7 via Frontend Transport; Fri, 29 May 2020 12:43:46 +0000 X-Originating-IP: [93.215.216.32] X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-HT: Tenant X-MS-Office365-Filtering-Correlation-Id: d06d0525-278c-493e-48b9-08d803cdee7d X-MS-TrafficTypeDiagnostic: DF4PR8401MB1004: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:4303; X-Forefront-PRVS: 04180B6720 X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: SefHo6FlPkXMaWCpVFOvkeZfI30teR/L3+FoxpCulqQ2hCHpEql2coSF+YSDvs29Fzj5IQkTrtYVJD55m53iVGOkNx35+gHqSKBH3gbDe8J4vNEENcfg2lIco3wXMpVLnVGyGu9sPT8svwua67OMvW3OnOT2+T9jhybR89MAWpQx4eKuNObMsUiyPKEkp7OkSabTT4QVcQwRNyWOpJSdFzfj78WAmyV7FW25defsllV2HdFeBsXdwsP+3gkZFmierz2oSzz9pFtMcZbaoUKoIRUvj3vTcCWPRCch9CWlPlJYSq/ihPtyUUWG6o8P2zoCSPiqQwtwCyKRjgggXHudEC92RrQagMjGI7UgAfR9GnZmQS+L+/FoitPj9fSsXutQEdgXk9wa6wW/t7WpwvFpmZqDvzdPtx9jgjJguAhgVy/KlfqF61BeGukKdaSNMAVUwtVsYRmtZDZ92JKg8PJhdg== X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:DF4PR8401MB0474.NAMPRD84.PROD.OUTLOOK.COM;PTR:;CAT:NONE;SFTY:;SFS:(136003)(39860400002)(366004)(396003)(376002)(346002)(6486002)(52116002)(6666004)(26005)(966005)(316002)(53546011)(16576012)(478600001)(54906003)(86362001)(30864003)(2906002)(36756003)(66946007)(4326008)(8676002)(2616005)(66574014)(186003)(31696002)(31686004)(956004)(66556008)(66476007)(5660300002)(83380400001)(44832011)(16526019)(8936002)(43740500002)(579004)(559001);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData: GLEM8/C1Lw7gqrrlbt7g8NT9uSavY0+BRl+xINAGpwm1ICEqUYfstv599MLMeuAHeyVQid8YX5f0ZoZkGLLsVTTG5HfuA39ffT7FdynffYyQ5m6wgxZT+GJpLGsr685xs4gVPK16J6iY/z3dHO2hOnY/cB62ZdlewImV/JCw5c69aULor0JVrQho4rWPUXRIhx7JMrThlJnsQssxll2Yit8pxbSQ4FAU/Q8E2GlRLwdH768b1nhiykUR7nhaRIa6OR3Iu+i1xEBIcT/cmacNwf/COgb4C2xiqraBbaPgwbiTzAHANJUu551ymc7bLOyTsN4EbCrccLymJyPxo+xsEcqtrUyZlLKeCmAP9grxKnU7bw6t6wgRCWU3QUqg0NGnOopF9r8eDdELYFf0m8L2VK5JClSMgAePHLsjonkweEdGc80N7gDgOpIdgNydIKeW5dZOcXmWmAL+DndnjM09GMQ2Ry2xMq5dTvU/MpJphh3erQ0Mcq1f6LT7uhA3bFc8 X-MS-Exchange-CrossTenant-Network-Message-Id: d06d0525-278c-493e-48b9-08d803cdee7d X-MS-Exchange-CrossTenant-OriginalArrivalTime: 29 May 2020 12:43:48.3629 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 105b2061-b669-4b31-92ac-24d304d195dc X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: oB58xR9Ld6psofWt4J1Hh6JtBqqDBc2rIdmFyRjaIIHBtfYNFE4fEss2UsqKtJ+igobjfk1/BBApq+M2gxQjhQ== X-MS-Exchange-Transport-CrossTenantHeadersStamped: DF4PR8401MB1004 X-OriginatorOrg: hpe.com X-Proofpoint-UnRewURL: 4 URL's were un-rewritten MIME-Version: 1.0 X-HPE-SCL: -1 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.216,18.0.687 definitions=2020-05-29_07:2020-05-28,2020-05-29 signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 cotscore=-2147483648 mlxscore=0 adultscore=0 malwarescore=0 mlxlogscore=999 bulkscore=0 spamscore=0 lowpriorityscore=0 phishscore=0 priorityscore=1501 clxscore=1015 impostorscore=0 suspectscore=1 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2004280000 definitions=main-2005290101 X-MIME-Autoconverted: from 8bit to quoted-printable by mx0b-002e3701.pphosted.com id 04TCeQHE019882 Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: en-US Content-Transfer-Encoding: quoted-printable Hi Leif, thanks for this super careful review! Comments and one question inline. - Daniel On 5/20/20 8:27 PM, Leif Lindholm wrote: > On Fri, May 15, 2020 at 15:39:37 +0200, Daniel Schaefer wrote: >> Library provides interfaces to invoke SBI extensions. >> >> Signed-off-by: Daniel Schaefer >> >> Cc: Abner Chang >> Cc: Gilbert Chen >> Cc: Michael D Kinney >> Cc: Leif Lindholm >> --- >> Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.i= nf | 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/RiscVE= dk2SbiLib.inf b/Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEd= k2SbiLib.inf >> new file mode 100644 >> index 000000000000..665dcbf40e01 >> --- /dev/null >> +++ b/Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiL= ib.inf >> @@ -0,0 +1,28 @@ >> +## @file >> +# RISC-V Library to call SBI ecalls >> +# >> +# Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All = rights reserved.
>> +# >> +# SPDX-License-Identifier: BSD-2-Clause-Patent >> +# >> +## >> + >> +[Defines] >> + INF_VERSION =3D 0x0001001b >> + BASE_NAME =3D RiscVEdk2SbiLib >> + FILE_GUID =3D 0DF1BBBD-F7E5-4E8A-BCF1-9D63D2DD9FDD >> + MODULE_TYPE =3D BASE >> + VERSION_STRING =3D 1.0 >> + LIBRARY_CLASS =3D 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/RiscV= Opensbi.h b/Silicon/RISC-V/ProcessorPkg/Include/IndustryStandard/RiscVOpens= bi.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_ >> =20 >> -#include // Reference to header file in open= sbi >> #include >> +#include // Reference to header file in opensbi >=20 > I don't see anything in *this* patch requiring this change - does this > belong squashed into 2/3? Yes... I'll fix it in the next patchset. >=20 >> +#include >> +#include >> #include // Reference to header file wrapper >> =20 >> -#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 >=20 > Ah, right, see my confusion from reviewing 2/3. > Please move this to 2/3, adding a comment on why > SBI_ERR_ALREADY_AVAILABLE needs to be locally defined here. See above, comment added. >=20 >> =20 >> -#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 >=20 > Why do we add these in 2/3 only to delete them again here? See above. >=20 >> +// 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 >> =20 >> // >> // Below two definitions should be defined in OpenSBI. >> +// Submitted to upstream, waiting for merge and release. >=20 > Good call out. This isn't pretty, but it is the right thing to do. >=20 >> // >> #define SBI_EXT_FIRMWARE_CODE_BASE_START 0x0A000000 >> #define SBI_EXT_FIRMWARE_CODE_BASE_END 0x0AFFFFFF >> =20 >> -#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 >> - >=20 > Why do we add these in 2/3 only to delete them again here? See above. >=20 >> #define RISC_V_MAX_HART_SUPPORTED 16 >> =20 >> typedef >> diff --git a/Silicon/RISC-V/ProcessorPkg/Include/Library/RiscVEdk2SbiLi= b.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 reserve= d.
>> + >> +SPDX-License-Identifier: BSD-2-Clause-Patent >> + >> +**/ >> + >> +#ifndef RISCV_SBI_LIB_H_ >> +#define RISCV_SBI_LIB_H_ >> + >> +#include >> +#include >> +#include >> +#include >> + >> +// >> +// EDK2 OpenSBI Firmware extension. >> +// >> +#define SBI_EDK2_FW_EXT (SBI_EXT_FIRMWARE_CODE_BASE_START | SBI_OPENSB= I_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 { >=20 > This struct appears only to be referenceed outside the opensbi > submodule, so name should conform to EDK2 coding style (and preferably > with a typedef). Okidoki. >=20 >> + long error; ///< SBI status code >> + long value; ///< Value returned >=20 > This looks like a maintenance hazard (means different things to GCC > and VS for example). Can we use UINT32? I'll use UINTN because it's bigger than 32bits on RISCV64 >=20 >> +}; >> + >> +#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) >=20 > Ugh. This looks way too much like pre-EFIAPI x86 code. >=20 > Is this a pattern used across multiple codebases? > If not, could we make this a simple argc/argv instead and do the > unpacking inside SbiCall()? Hmm, maybe that would make the call sites > even worse. >=20 > If we need to keep these, coding style says all macros should use > UPPERCASE_AND_UNDERSCORES. >=20 Yeah, I think argc/argv is going to make the callsites worse. What about= =20 vararg, like I used in SbiVendorCall in Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiLib.c ? Or does that have a performance impact? Maybe an architecture specific= =20 one? >> + >> +/** >> + EDK2 SbiCall to invoke SBI extensions. >> + >> + @param[in] ext_id Sbi extension ID. >> + @param[in] func_id Sbi functions ID. >> + @param[in] arg0 Arg0 to function. >> + @param[in] arg1 Arg1 to function. >> + @param[in] arg2 Arg2 to function. >> + @param[in] arg3 Arg3 to function. >> + @param[in] arg4 Arg4 to function. >> + @param[in] arg5 Arg5 to function. >> + >> + @retval Returns sbiret structure. >> + >> +**/ >> +inline >> +EFIAPI >> +struct sbiret SbiCall(UINTN ext_id, UINTN func_id, UINTN arg0, UINTN a= rg1, >=20 > Function name starts in the first column of a new line. > But please drop the entire forward-declaration. >=20 >> + UINTN arg2, UINTN arg3, UINTN arg4, UINTN a= rg5) >> +__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 >=20 > Technically, the coding standard bans function definitions in header > files[1]. If you can give me a good reason for why this function > should be here, I may consider to consider making an exception. > If I do, make it just STATIC (let the compiler worry about the > inlining). When I first wrote this library, it was necessary but it's not anymore. I moved it to the .c file, because it's not used anywhere else. >=20 > If it is just by habit from other projects of putting helper functions > into headers, please move them to a .c file. >=20 > [1] https://edk2-docs.gitbook.io/edk-ii-c-coding-standards-specification= /5_source_files/53_include_files#5-3-7-include-files-shall-not-generate-cod= e-or-define-data-variables >=20 >> +EFIAPI >> +struct sbiret SbiCall(UINTN ext_id, UINTN func_id, UINTN arg0, UINTN a= rg1, >> + UINTN arg2, UINTN arg3, UINTN arg4, UINTN a= rg5) { >> + register uintptr_t a0 asm ("a0") =3D (uintptr_t)(arg0); >> + register uintptr_t a1 asm ("a1") =3D (uintptr_t)(arg1); >> + register uintptr_t a2 asm ("a2") =3D (uintptr_t)(arg2); >> + register uintptr_t a3 asm ("a3") =3D (uintptr_t)(arg3); >> + register uintptr_t a4 asm ("a4") =3D (uintptr_t)(arg4); >> + register uintptr_t a5 asm ("a5") =3D (uintptr_t)(arg5); >> + register uintptr_t a6 asm ("a6") =3D (uintptr_t)(func_id); >> + register uintptr_t a7 asm ("a7") =3D (uintptr_t)(ext_id); >=20 > I would *prefer* UINTN over uintptr_t here. >=20 >> + asm volatile ("ecall" \ >> + : "+r" (a0) \ >=20 > Isn't a1 also an input/output operand here? Yes, you're right. >=20 >> + : "r" (a1), "r" (a2), "r" (a3), "r" (a4), "r" (a5), "r" (a6),= "r" (a7) \ >> + : "memory"); \ >> + struct sbiret ret =3D { a0, a1 }; >> + return ret; >=20 > CamelCase naming. Will change it everywhere. >=20 >> +} >> + >> +/** >> + Get the implemented SBI specification version >> + >> + The minor number of the SBI specification is encoded in the low 24 b= its, >> + 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 specificatio= n. >> +**/ >> +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 implem= entation. >> + >> + @param[out] ImplVersion The version of the SBI implementati= on. >> +**/ >> +VOID >> +EFIAPI >> +SbiGetImplversion ( >=20 > Uppercase V for CamelCase (and matching the argument name below). Oops. >=20 >> + OUT UINTN *ImplVersion >> + ); >> + >> +/** >> + Probe whether an SBI extension is available >> + >> + ProbeResult is set to 0 if the extension is not available or to an e= xtension >> + 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. >=20 > What is an MvendorId? MachineVendorId? > Even if an official register name, I would prefer function and > arguments to be given proper descriptive CamelCase names. Yes, it's the official register name. Alright, will change it. >=20 >> + >> + @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. >=20 > This should probebly be MArchId (or MachineArchId?)? Yes, changed it to MachineArchId. >=20 >> +**/ >> +VOID >> +EFIAPI >> +SbiGetMarchId ( >> + OUT UINTN *MarchId >> + ); >> + >> +/** >> + Get the CPU's implementation ID >> + >> + Reads the mimpid CSR. >> + >> + @param[out] MimpId The CPU's implementation ID. >=20 > Above "Impl" is used for "Impelentation". *Strictly* speaking, "Impl" > doesn't fall in the pretty small group of abbreviations permitted > without a glossary section in the source file, but it's clear enough > to me I'll let it slip. > The same cannot be said for "Imp". > MachineImplId? Sounds good. Should it be added to the permitted abbreviations? If I spell it out fully here, it becomes quite long. >=20 >> +**/ >> +VOID >> +EFIAPI >> +SbiGetMimpId ( >> + OUT UINTN *Mimpid >> + ); >> + >> +/** >> + Politely ask the SBI to start a given hart. >=20 > I know hart is a pretty fundamental concept in RISC-V. > Still, I would request to have it added in a glossary section in the > top-of-file comment header. Cool, didn't know that existed! Will do. >=20 >> + >> + 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 p= resent >> + and switch to S-mode. >> + >> + @param[in] HartId The id of the hart to start. >> + @param[in] StartAddr The physical address, where the har= t 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 exe= cuting from StartAddr. >> + @retval EFI_LOAD_ERROR StartAddr is not valid, possibly du= e to following reasons: >> + - It is not a valid physical addre= ss. >> + - 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 unknow= n reasons. >> +**/ >> +EFI_STATUS >> +EFIAPI >> +SbiHartStart ( >=20 > (With great effort, I suppress a M=C3=B6tley Cr=C3=BCe joke.) >=20 >> + 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 re= trieved >> + 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 sta= tus 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. >=20 > What does the S stand for in Stime? That's what they call it in the spec: stime_value. I guess it stands for supervisor. Should we change it to just `Time`? >=20 >> + >> + To clear the timer without scheduling a timer event, set StimeValue = to a >> + practically infinite value or mask the timer interrupt by clearing s= ie.STIE. >> + >> + @param[in] StimeValue The time offset to the next schedul= ed 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 t= he >> + receiving hart. >> + >> + @param[in] HartMask Scalar bit-vector containing hart i= ds >> + @param[in] HartMaskBase The starting hartid from which the = bit-vector >> + must be computed. If set to -1, Har= tMask is >> + ignored and all harts are considere= d. >> + @retval EFI_SUCCESS IPI was sent to all the targeted ha= rts. >> + @retval EFI_INVALID_PARAMETER Either hart_mask_base or any of the= hartid >> + from hart_mask is not valid i.e. ei= ther the >> + hartid is not enabled by the platfo= rm 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 i= ds >> + @param[in] HartMaskBase The starting hartid from which the = bit-vector >> + must be computed. If set to -1, Har= tMask is >> + ignored and all harts are considere= d. >> + @retval EFI_SUCCESS IPI was sent to all the targeted ha= rts. >> + @retval EFI_INVALID_PARAMETER Either hart_mask_base or any of the= hartid >> + from hart_mask is not valid i.e. ei= ther the >> + hartid is not enabled by the platfo= rm 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 instruc= tions. >> + >> + The SFENCE.VMA covers the range of virtual addresses between StartAa= ddr and Size. >> + >> + The remote fence function acts as a full tlb flush if * StartAddr an= d size >> + are both 0 * size is equal to 2^XLEN-1 >> + >> + @param[in] HartMask Scalar bit-vector containing hart i= ds >> + @param[in] HartMaskBase The starting hartid from which the = bit-vector >> + must be computed. If set to -1, Har= tMask is >> + ignored and all harts are considere= d. >> + @param[in] StartAddr The first address of the affected r= ange. >> + @param[in] Size How many addresses are affected. >> + @retval EFI_SUCCESS IPI was sent to all the targeted ha= rts. >> + @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. ei= ther the >> + hartid is not enabled by the platfo= rm 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 instruc= tions. >> + >> + The SFENCE.VMA covers the range of virtual addresses between StartAa= ddr and Size. >> + Covers only the given ASID. >> + >> + The remote fence function acts as a full tlb flush if * StartAddr an= d size >> + are both 0 * size is equal to 2^XLEN-1 >> + >> + @param[in] HartMask Scalar bit-vector containing hart i= ds >> + @param[in] HartMaskBase The starting hartid from which the = bit-vector >> + must be computed. If set to -1, Har= tMask is >> + ignored and all harts are considere= d. >> + @param[in] StartAddr The first address of the affected r= ange. >> + @param[in] Size How many addresses are affected. >> + @retval EFI_SUCCESS IPI was sent to all the targeted ha= rts. >> + @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. ei= ther the >> + hartid is not enabled by the platfo= rm 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 instru= ctions. >> + >> + The SFENCE.GVMA covers the range of virtual addresses between StartA= addr and Size. >> + Covers only the given VMID. >> + This function call is only valid for harts implementing the hypervis= or extension. >> + >> + The remote fence function acts as a full tlb flush if * StartAddr an= d size >> + are both 0 * size is equal to 2^XLEN-1 >> + >> + @param[in] HartMask Scalar bit-vector containing hart i= ds >> + @param[in] HartMaskBase The starting hartid from which the = bit-vector >> + must be computed. If set to -1, Har= tMask is >> + ignored and all harts are considere= d. >> + @param[in] StartAddr The first address of the affected r= ange. >> + @param[in] Size How many addresses are affected. >> + @retval EFI_SUCCESS IPI was sent to all the targeted ha= rts. >> + @retval EFI_LOAD_ERROR StartAddr or Size is not valid. >> + @retval EFI_UNSUPPORTED SBI does not implement this functio= n or one >> + of the target harts does not suppor= t the >> + hypervisor extension. >> + @retval EFI_INVALID_PARAMETER Either hart_mask_base or any of the= hartid >> + from hart_mask is not valid i.e. ei= ther the >> + hartid is not enabled by the platfo= rm 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 instru= ctions. >> + >> + The SFENCE.GVMA covers the range of virtual addresses between StartA= addr and Size. >> + This function call is only valid for harts implementing the hypervis= or extension. >> + >> + The remote fence function acts as a full tlb flush if * StartAddr an= d size >> + are both 0 * size is equal to 2^XLEN-1 >> + >> + @param[in] HartMask Scalar bit-vector containing hart i= ds >> + @param[in] HartMaskBase The starting hartid from which the = bit-vector >> + must be computed. If set to -1, Har= tMask is >> + ignored and all harts are considere= d. >> + @param[in] StartAddr The first address of the affected r= ange. >> + @param[in] Size How many addresses are affected. >> + @retval EFI_SUCCESS IPI was sent to all the targeted ha= rts. >> + @retval EFI_LOAD_ERROR StartAddr or Size is not valid. >> + @retval EFI_UNSUPPORTED SBI does not implement this functio= n or one >> + of the target harts does not suppor= t the >> + hypervisor extension. >> + @retval EFI_INVALID_PARAMETER Either hart_mask_base or any of the= hartid >> + from hart_mask is not valid i.e. ei= ther the >> + hartid is not enabled by the platfo= rm 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 instru= ctions. >> + >> + The SFENCE.GVMA covers the range of virtual addresses between StartA= addr and Size. >> + Covers only the given ASID. >> + This function call is only valid for harts implementing the hypervis= or extension. >> + >> + The remote fence function acts as a full tlb flush if * StartAddr an= d size >> + are both 0 * size is equal to 2^XLEN-1 >> + >> + @param[in] HartMask Scalar bit-vector containing hart i= ds >> + @param[in] HartMaskBase The starting hartid from which the = bit-vector >> + must be computed. If set to -1, Har= tMask is >> + ignored and all harts are considere= d. >> + @param[in] StartAddr The first address of the affected r= ange. >> + @param[in] Size How many addresses are affected. >> + @retval EFI_SUCCESS IPI was sent to all the targeted ha= rts. >> + @retval EFI_LOAD_ERROR StartAddr or Size is not valid. >> + @retval EFI_UNSUPPORTED SBI does not implement this functio= n or one >> + of the target harts does not suppor= t the >> + hypervisor extension. >> + @retval EFI_INVALID_PARAMETER Either hart_mask_base or any of the= hartid >> + from hart_mask is not valid i.e. ei= ther the >> + hartid is not enabled by the platfo= rm 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 instru= ctions. >> + >> + The SFENCE.GVMA covers the range of virtual addresses between StartA= addr and Size. >> + This function call is only valid for harts implementing the hypervis= or extension. >> + >> + The remote fence function acts as a full tlb flush if * StartAddr an= d size >> + are both 0 * size is equal to 2^XLEN-1 >> + >> + @param[in] HartMask Scalar bit-vector containing hart i= ds >> + @param[in] HartMaskBase The starting hartid from which the = bit-vector >> + must be computed. If set to -1, Har= tMask is >> + ignored and all harts are considere= d. >> + @param[in] StartAddr The first address of the affected r= ange. >> + @param[in] Size How many addresses are affected. >> + @retval EFI_SUCCESS IPI was sent to all the targeted ha= rts. >> + @retval EFI_LOAD_ERROR StartAddr or Size is not valid. >> + @retval EFI_UNSUPPORTED SBI does not implement this functio= n or one >> + of the target harts does not suppor= t the >> + hypervisor extension. >> + @retval EFI_INVALID_PARAMETER Either hart_mask_base or any of the= hartid >> + from hart_mask is not valid i.e. ei= ther the >> + hartid is not enabled by the platfo= rm 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 Exte= nsion >> + Space. >> + >> + @param[in] ExtensionId The SBI vendor extension ID. >> + @param[in] FunctionId The function ID to call in this ext= ension. >> + @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 succes= sful >> + @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 >=20 > Could we add a typedef for "struct sbi_scratch" to make the code more > style compliant? Yeah, will do. Then I'll also do one for `struct sbi_platform`, which is= =20 used in the .c file. >=20 >> + ); >> + >> +/** >> + 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/RiscVE= dk2SbiLib.c b/Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2= SbiLib.c >> new file mode 100644 >> index 000000000000..bbe006a78af8 >> --- /dev/null >> +++ b/Silicon/RISC-V/ProcessorPkg/Library/RiscVEdk2SbiLib/RiscVEdk2SbiL= ib.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 necessar= y. >> + 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 extensio= n >> + >> + Copyright (c) 2020, Hewlett Packard Development LP. All rights reser= ved.
>> + >> + SPDX-License-Identifier: BSD-2-Clause-Patent >> +**/ >> + >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> + >> +/** >> + 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 b= its, >> + 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 specificatio= n. >> +**/ >> +VOID >> +EFIAPI >> +SbiGetSpecVersion ( >> + OUT UINTN *SpecVersion >> + ) >> +{ >> + struct sbiret ret =3D SbiCall0 (SBI_EXT_BASE, SBI_EXT_BASE_GET_SPEC_= VERSION); >> + >> + if (!ret.error) { >> + *SpecVersion =3D (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 =3D SbiCall0 (SBI_EXT_BASE, SBI_EXT_BASE_GET_IMP_I= D); >> + *ImplId =3D (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 implem= entation. >> + >> + @param[out] ImplVersion The version of the SBI implementati= on. >> +**/ >> +VOID >> +EFIAPI >> +SbiGetImplVersion ( >> + OUT UINTN *ImplVersion >> + ) >> +{ >> + struct sbiret ret =3D SbiCall0 (SBI_EXT_BASE, SBI_EXT_BASE_GET_IMP_V= ERSION); >> + *ImplVersion =3D (UINTN) ret.value; >> +} >> + >> +/** >> + Probe whether an SBI extension is available >> + >> + ProbeResult is set to 0 if the extension is not available or to an e= xtension >> + 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 =3D SbiCall0 (SBI_EXT_BASE, SBI_EXT_BASE_PROBE_EXT= ); >> + *ProbeResult =3D (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 =3D SbiCall0 (SBI_EXT_BASE, SBI_EXT_BASE_GET_MVEND= ORID); >> + *MvendorId =3D (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 =3D SbiCall0 (SBI_EXT_BASE, SBI_EXT_BASE_GET_MARCH= ID); >> + *MarchId =3D (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 =3D SbiCall0 (SBI_EXT_BASE, SBI_EXT_BASE_GET_MIMPI= D); >> + *MimpId =3D (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 p= resent >> + and switch to S-mode. >> + >> + @param[in] HartId The id of the hart to start. >> + @param[in] StartAddr The physical address, where the har= t 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 exe= cuting from StartAddr. >> + @retval EFI_LOAD_ERROR StartAddr is not valid, possibly du= e to following reasons: >> + - It is not a valid physical addr= ess. >> + - The address is prohibited by PM= P 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 unknow= n reasons. >> +**/ >> +EFI_STATUS >> +EFIAPI >> +SbiHartStart ( >> + IN UINTN HartId, >> + IN UINTN StartAddr, >> + IN UINTN Priv >> + ) >> +{ >> + struct sbiret ret =3D 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 =3D 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 re= trieved >> + 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 sta= tus 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 =3D SbiCall1 (SBI_EXT_HSM, SBI_EXT_HSM_HART_GET_ST= ATUS, HartId); >> + >> + if (!ret.error) { >> + *HartStatus =3D (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 s= ie.STIE. >> + >> + @param[in] StimeValue The time offset to the next schedul= ed 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 =3D 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 i= ds >> + @param[in] HartMaskBase The starting hartid from which the = bit-vector >> + must be computed. If set to -1, Har= tMask is >> + ignored and all harts are considere= d. >> + @retval EFI_SUCCESS IPI was sent to all the targeted ha= rts. >> + @retval EFI_INVALID_PARAMETER Either hart_mask_base or any of the= hartid >> + from hart_mask is not valid i.e. ei= ther the >> + hartid is not enabled by the platfo= rm or is >> + not available to the supervisor. >> +**/ >> +EFI_STATUS >> +EFIAPI >> +SbiRemoteFenceI ( >> + IN UINTN *HartMask, >> + IN UINTN HartMaskBase >> + ) >> +{ >> + struct sbiret ret =3D 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 instruc= tions. >> + >> + The SFENCE.VMA covers the range of virtual addresses between StartAa= ddr and Size. >> + >> + The remote fence function acts as a full tlb flush if * StartAddr an= d size >> + are both 0 * size is equal to 2^XLEN-1 >> + >> + @param[in] HartMask Scalar bit-vector containing hart i= ds >> + @param[in] HartMaskBase The starting hartid from which the = bit-vector >> + must be computed. If set to -1, Har= tMask is >> + ignored and all harts are considere= d. >> + @param[in] StartAddr The first address of the affected r= ange. >> + @param[in] Size How many addresses are affected. >> + @retval EFI_SUCCESS IPI was sent to all the targeted ha= rts. >> + @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. ei= ther the >> + hartid is not enabled by the platfo= rm 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 =3D 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 instruc= tions. >> + >> + The SFENCE.VMA covers the range of virtual addresses between StartAa= ddr and Size. >> + Covers only the given ASID. >> + >> + The remote fence function acts as a full tlb flush if * StartAddr an= d size >> + are both 0 * size is equal to 2^XLEN-1 >> + >> + @param[in] HartMask Scalar bit-vector containing hart i= ds >> + @param[in] HartMaskBase The starting hartid from which the = bit-vector >> + must be computed. If set to -1, Har= tMask is >> + ignored and all harts are considere= d. >> + @param[in] StartAddr The first address of the affected r= ange. >> + @param[in] Size How many addresses are affected. >> + @retval EFI_SUCCESS IPI was sent to all the targeted ha= rts. >> + @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. ei= ther the >> + hartid is not enabled by the platfo= rm 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 =3D 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 instru= ctions. >> + >> + The SFENCE.GVMA covers the range of virtual addresses between StartA= addr and Size. >> + Covers only the given VMID. >> + This function call is only valid for harts implementing the hypervis= or extension. >> + >> + The remote fence function acts as a full tlb flush if * StartAddr an= d size >> + are both 0 * size is equal to 2^XLEN-1 >> + >> + @param[in] HartMask Scalar bit-vector containing hart i= ds >> + @param[in] HartMaskBase The starting hartid from which the = bit-vector >> + must be computed. If set to -1, Har= tMask is >> + ignored and all harts are considere= d. >> + @param[in] StartAddr The first address of the affected r= ange. >> + @param[in] Size How many addresses are affected. >> + @retval EFI_SUCCESS IPI was sent to all the targeted ha= rts. >> + @retval EFI_LOAD_ERROR StartAddr or Size is not valid. >> + @retval EFI_UNSUPPORTED SBI does not implement this functio= n or one >> + of the target harts does not suppor= t the >> + hypervisor extension. >> + @retval EFI_INVALID_PARAMETER Either hart_mask_base or any of the= hartid >> + from hart_mask is not valid i.e. ei= ther the >> + hartid is not enabled by the platfo= rm 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 =3D 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 instru= ctions. >> + >> + The SFENCE.GVMA covers the range of virtual addresses between StartA= addr and Size. >> + This function call is only valid for harts implementing the hypervis= or extension. >> + >> + The remote fence function acts as a full tlb flush if * StartAddr an= d size >> + are both 0 * size is equal to 2^XLEN-1 >> + >> + @param[in] HartMask Scalar bit-vector containing hart i= ds >> + @param[in] HartMaskBase The starting hartid from which the = bit-vector >> + must be computed. If set to -1, Har= tMask is >> + ignored and all harts are considere= d. >> + @param[in] StartAddr The first address of the affected r= ange. >> + @param[in] Size How many addresses are affected. >> + @retval EFI_SUCCESS IPI was sent to all the targeted ha= rts. >> + @retval EFI_LOAD_ERROR StartAddr or Size is not valid. >> + @retval EFI_UNSUPPORTED SBI does not implement this functio= n or one >> + of the target harts does not suppor= t the >> + hypervisor extension. >> + @retval EFI_INVALID_PARAMETER Either hart_mask_base or any of the= hartid >> + from hart_mask is not valid i.e. ei= ther the >> + hartid is not enabled by the platfo= rm 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 =3D 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 instru= ctions. >> + >> + The SFENCE.GVMA covers the range of virtual addresses between StartA= addr and Size. >> + Covers only the given ASID. >> + This function call is only valid for harts implementing the hypervis= or extension. >> + >> + The remote fence function acts as a full tlb flush if * StartAddr an= d size >> + are both 0 * size is equal to 2^XLEN-1 >> + >> + @param[in] HartMask Scalar bit-vector containing hart i= ds >> + @param[in] HartMaskBase The starting hartid from which the = bit-vector >> + must be computed. If set to -1, Har= tMask is >> + ignored and all harts are considere= d. >> + @param[in] StartAddr The first address of the affected r= ange. >> + @param[in] Size How many addresses are affected. >> + @retval EFI_SUCCESS IPI was sent to all the targeted ha= rts. >> + @retval EFI_LOAD_ERROR StartAddr or Size is not valid. >> + @retval EFI_UNSUPPORTED SBI does not implement this functio= n or one >> + of the target harts does not suppor= t the >> + hypervisor extension. >> + @retval EFI_INVALID_PARAMETER Either hart_mask_base or any of the= hartid >> + from hart_mask is not valid i.e. ei= ther the >> + hartid is not enabled by the platfo= rm 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 =3D 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 instru= ctions. >> + >> + The SFENCE.GVMA covers the range of virtual addresses between StartA= addr and Size. >> + This function call is only valid for harts implementing the hypervis= or extension. >> + >> + The remote fence function acts as a full tlb flush if * StartAddr an= d size >> + are both 0 * size is equal to 2^XLEN-1 >> + >> + @param[in] HartMask Scalar bit-vector containing hart i= ds >> + @param[in] HartMaskBase The starting hartid from which the = bit-vector >> + must be computed. If set to -1, Har= tMask is >> + ignored and all harts are considere= d. >> + @param[in] StartAddr The first address of the affected r= ange. >> + @param[in] Size How many addresses are affected. >> + @retval EFI_SUCCESS IPI was sent to all the targeted ha= rts. >> + @retval EFI_LOAD_ERROR StartAddr or Size is not valid. >> + @retval EFI_UNSUPPORTED SBI does not implement this functio= n or one >> + of the target harts does not suppor= t the >> + hypervisor extension. >> + @retval EFI_INVALID_PARAMETER Either hart_mask_base or any of the= hartid >> + from hart_mask is not valid i.e. ei= ther the >> + hartid is not enabled by the platfo= rm 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 =3D 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 Exte= nsion >> + Space. >> + >> + @param[in] ExtensionId The SBI vendor extension ID. >> + @param[in] FunctionId The function ID to call in this ext= ension. >> + @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 succes= sful >> + @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 >=3D 0x09000000 && ExtensionId <=3D 0x09FFFFFF= ); >> + >> + switch (NumArgs) { >> + case 0: >> + ret =3D SbiCall0 (ExtensionId, FunctionId); >> + break; >> + case 1: >> + ret =3D SbiCall1 (ExtensionId, FunctionId, VA_ARG(Args, UINTN)= ); >> + break; >> + case 2: >> + ret =3D SbiCall2 (ExtensionId, FunctionId, VA_ARG(Args, UINTN)= , VA_ARG(Args, UINTN)); >> + break; >> + case 3: >> + ret =3D SbiCall3 (ExtensionId, FunctionId, VA_ARG(Args, UINTN)= , VA_ARG(Args, UINTN), VA_ARG(Args, UINTN)); >> + break; >> + case 4: >> + ret =3D SbiCall4 (ExtensionId, FunctionId, VA_ARG(Args, UINTN)= , VA_ARG(Args, UINTN), VA_ARG(Args, UINTN), VA_ARG(Args, UINTN)); >> + break; >> + case 5: >> + ret =3D SbiCall5 (ExtensionId, FunctionId, VA_ARG(Args, UINTN)= , VA_ARG(Args, UINTN), VA_ARG(Args, UINTN), VA_ARG(Args, UINTN), VA_ARG(Arg= s, UINTN)); >> + break; >> + case 6: >> + ret =3D SbiCall6 (ExtensionId, FunctionId, VA_ARG(Args, UINTN)= , VA_ARG(Args, UINTN), VA_ARG(Args, UINTN), VA_ARG(Args, UINTN), VA_ARG(Arg= s, 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, therefo= re 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 =3D SbiCall0 (SBI_EDK2_FW_EXT, SBI_EXT_FW_MSCRATCH= _FUNC); >> + >> + if (!ret.error) { >> + *ScratchSpace =3D (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 =3D SbiCall1 (SBI_EDK2_FW_EXT, >> + SBI_EXT_FW_MSCRATCH_HARTID_FUNC, >> + HartId); >> + >> + if (!ret.error) { >> + *ScratchSpace =3D (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 =3D SbiCall0 (SBI_EDK2_FW_EXT, SBI_EXT_FW_MSCRATCH= _FUNC); >> + >> + if (!ret.error) { >> + ScratchSpace =3D (struct sbi_scratch *) ret.value; >> + SbiPlatform =3D (struct sbi_platform *) sbi_platform_ptr(ScratchSp= ace); >> + *FirmwareContext =3D (EFI_RISCV_OPENSBI_FIRMWARE_CONTEXT *) SbiPla= tform->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 =3D SbiCall0 (SBI_EDK2_FW_EXT, SBI_EXT_FW_MSCRATCH= _FUNC); >> + >> + if (!ret.error) { >> + ScratchSpace =3D (struct sbi_scratch *) ret.value; >> + SbiPlatform =3D (struct sbi_platform *) sbi_platform_ptr(ScratchSp= ace); >> + SbiPlatform->firmware_context =3D (long unsigned int) FirmwareCont= ext; >=20 > UINT64? UINTN for compatibility with 32bits. >=20 > / > Leif >=20 >> + } >> + >> + return EFI_SUCCESS; >> +} >> --=20 >> 2.26.1 >> >=20 >=20 >=20