RiscVEdk2SbiLib.c 29 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016
  1. /** @file
  2. Instance of the SBI ecall library.
  3. It allows calling an SBI function via an ecall from S-Mode.
  4. The legacy extensions are not included because they are not necessary.
  5. They would be:
  6. - SbiLegacySetTimer -> Use SbiSetTimer
  7. - SbiLegacyConsolePutChar -> No replacement - Use regular UEFI functions
  8. - SbiLegacyConsoleGetChar -> No replacement - Use regular UEFI functions
  9. - SbiLegacyClearIpi -> Write 0 to SSIP
  10. - SbiLegacySendIpi -> Use SbiSendIpi
  11. - SbiLegacyRemoteFenceI -> Use SbiRemoteFenceI
  12. - SbiLegacyRemoteSfenceVma -> Use SbiRemoteSfenceVma
  13. - SbiLegacyRemoteSfenceVmaAsid -> Use SbiRemoteSfenceVmaAsid
  14. - SbiLegacyShutdown -> Wait for new System Reset extension
  15. Copyright (c) 2021-2022, Hewlett Packard Development LP. All rights reserved.<BR>
  16. SPDX-License-Identifier: BSD-2-Clause-Patent
  17. @par Revision Reference:
  18. - OpenSBI Version 0.6
  19. **/
  20. #include <IndustryStandard/RiscVOpensbi.h>
  21. #include <Library/BaseMemoryLib.h>
  22. #include <Library/DebugLib.h>
  23. #include <Library/RiscVEdk2SbiLib.h>
  24. #include <sbi/riscv_asm.h>
  25. #include <sbi/sbi_hart.h>
  26. #include <sbi/sbi_types.h>
  27. #include <sbi/sbi_init.h>
  28. //
  29. // Maximum arguments for SBI ecall
  30. // It's possible to pass more but no SBI call uses more as of SBI 0.2.
  31. // The additional arguments would have to be passed on the stack instead of as
  32. // registers, like it's done now.
  33. //
  34. #define SBI_CALL_MAX_ARGS 6
  35. /**
  36. Call SBI call using ecall instruction.
  37. Asserts when NumArgs exceeds SBI_CALL_MAX_ARGS.
  38. @param[in] ExtId SBI extension ID.
  39. @param[in] FuncId SBI function ID.
  40. @param[in] NumArgs Number of arguments to pass to the ecall.
  41. @param[in] ... Argument list for the ecall.
  42. @retval Returns SBI_RET structure with value and error code.
  43. **/
  44. STATIC
  45. SBI_RET
  46. EFIAPI
  47. SbiCall (
  48. IN UINTN ExtId,
  49. IN UINTN FuncId,
  50. IN UINTN NumArgs,
  51. ...
  52. )
  53. {
  54. UINTN I;
  55. SBI_RET Ret;
  56. UINTN Args[SBI_CALL_MAX_ARGS];
  57. VA_LIST ArgList;
  58. VA_START (ArgList, NumArgs);
  59. ASSERT (NumArgs <= SBI_CALL_MAX_ARGS);
  60. for (I = 0; I < SBI_CALL_MAX_ARGS; I++) {
  61. if (I < NumArgs) {
  62. Args[I] = VA_ARG (ArgList, UINTN);
  63. } else {
  64. // Default to 0 for all arguments that are not given
  65. Args[I] = 0;
  66. }
  67. }
  68. VA_END (ArgList);
  69. register UINTN a0 asm ("a0") = Args[0];
  70. register UINTN a1 asm ("a1") = Args[1];
  71. register UINTN a2 asm ("a2") = Args[2];
  72. register UINTN a3 asm ("a3") = Args[3];
  73. register UINTN a4 asm ("a4") = Args[4];
  74. register UINTN a5 asm ("a5") = Args[5];
  75. register UINTN a6 asm ("a6") = (UINTN)(FuncId);
  76. register UINTN a7 asm ("a7") = (UINTN)(ExtId);
  77. asm volatile ("ecall" \
  78. : "+r" (a0), "+r" (a1) \
  79. : "r" (a2), "r" (a3), "r" (a4), "r" (a5), "r" (a6), "r" (a7) \
  80. : "memory"); \
  81. Ret.Error = a0;
  82. Ret.Value = a1;
  83. return Ret;
  84. }
  85. /**
  86. Translate SBI error code to EFI status.
  87. @param[in] SbiError SBI error code
  88. @retval EFI_STATUS
  89. **/
  90. STATIC
  91. EFI_STATUS
  92. EFIAPI
  93. TranslateError (
  94. IN UINTN SbiError
  95. )
  96. {
  97. switch (SbiError) {
  98. case SBI_SUCCESS:
  99. return EFI_SUCCESS;
  100. case SBI_ERR_FAILED:
  101. return EFI_DEVICE_ERROR;
  102. break;
  103. case SBI_ERR_NOT_SUPPORTED:
  104. return EFI_UNSUPPORTED;
  105. break;
  106. case SBI_ERR_INVALID_PARAM:
  107. return EFI_INVALID_PARAMETER;
  108. break;
  109. case SBI_ERR_DENIED:
  110. return EFI_ACCESS_DENIED;
  111. break;
  112. case SBI_ERR_INVALID_ADDRESS:
  113. return EFI_LOAD_ERROR;
  114. break;
  115. case SBI_ERR_ALREADY_AVAILABLE:
  116. return EFI_ALREADY_STARTED;
  117. break;
  118. default:
  119. //
  120. // Reaches here only if SBI has defined a new error type
  121. //
  122. ASSERT (FALSE);
  123. return EFI_UNSUPPORTED;
  124. break;
  125. }
  126. }
  127. //
  128. // OpenSBI library interface function for the base extension
  129. //
  130. /**
  131. Get the implemented SBI specification version
  132. The minor number of the SBI specification is encoded in the low 24 bits,
  133. with the major number encoded in the next 7 bits. Bit 32 must be 0 and is
  134. reserved for future expansion.
  135. @param[out] SpecVersion The Version of the SBI specification.
  136. **/
  137. VOID
  138. EFIAPI
  139. SbiGetSpecVersion (
  140. OUT UINTN *SpecVersion
  141. )
  142. {
  143. SBI_RET Ret;
  144. Ret = SbiCall (SBI_EXT_BASE, SBI_EXT_BASE_GET_SPEC_VERSION, 0);
  145. if (!Ret.Error) {
  146. *SpecVersion = (UINTN)Ret.Value;
  147. }
  148. }
  149. /**
  150. Get the SBI implementation ID
  151. This ID is used to identify a specific SBI implementation in order to work
  152. around any quirks it might have.
  153. @param[out] ImplId The ID of the SBI implementation.
  154. **/
  155. VOID
  156. EFIAPI
  157. SbiGetImplId (
  158. OUT UINTN *ImplId
  159. )
  160. {
  161. SBI_RET Ret;
  162. Ret = SbiCall (SBI_EXT_BASE, SBI_EXT_BASE_GET_IMP_ID, 0);
  163. *ImplId = (UINTN)Ret.Value;
  164. }
  165. /**
  166. Get the SBI implementation version
  167. The version of this SBI implementation.
  168. The encoding of this number is determined by the specific SBI implementation.
  169. @param[out] ImplVersion The version of the SBI implementation.
  170. **/
  171. VOID
  172. EFIAPI
  173. SbiGetImplVersion (
  174. OUT UINTN *ImplVersion
  175. )
  176. {
  177. SBI_RET Ret;
  178. Ret = SbiCall (SBI_EXT_BASE, SBI_EXT_BASE_GET_IMP_VERSION, 0);
  179. *ImplVersion = (UINTN)Ret.Value;
  180. }
  181. /**
  182. Probe whether an SBI extension is available
  183. ProbeResult is set to 0 if the extension is not available or to an extension
  184. specified value if it is available.
  185. @param[in] ExtensionId The extension ID.
  186. @param[out] ProbeResult The return value of the probe.
  187. **/
  188. VOID
  189. EFIAPI
  190. SbiProbeExtension (
  191. IN INTN ExtensionId,
  192. OUT INTN *ProbeResult
  193. )
  194. {
  195. SBI_RET Ret;
  196. Ret = SbiCall (SBI_EXT_BASE, SBI_EXT_BASE_PROBE_EXT, 0);
  197. *ProbeResult = (UINTN)Ret.Value;
  198. }
  199. /**
  200. Get the CPU's vendor ID
  201. Reads the mvendorid CSR.
  202. @param[out] MachineVendorId The CPU's vendor ID.
  203. **/
  204. VOID
  205. EFIAPI
  206. SbiGetMachineVendorId (
  207. OUT UINTN *MachineVendorId
  208. )
  209. {
  210. SBI_RET Ret;
  211. Ret = SbiCall (SBI_EXT_BASE, SBI_EXT_BASE_GET_MVENDORID, 0);
  212. *MachineVendorId = (UINTN)Ret.Value;
  213. }
  214. /**
  215. Get the CPU's architecture ID
  216. Reads the marchid CSR.
  217. @param[out] MachineArchId The CPU's architecture ID.
  218. **/
  219. VOID
  220. EFIAPI
  221. SbiGetMachineArchId (
  222. OUT UINTN *MachineArchId
  223. )
  224. {
  225. SBI_RET Ret;
  226. Ret = SbiCall (SBI_EXT_BASE, SBI_EXT_BASE_GET_MARCHID, 0);
  227. *MachineArchId = (UINTN)Ret.Value;
  228. }
  229. /**
  230. Get the CPU's architecture ID
  231. Reads the marchid CSR.
  232. @param[out] MachineImplId The CPU's implementation ID.
  233. **/
  234. VOID
  235. EFIAPI
  236. SbiGetMachineImplId (
  237. OUT UINTN *MachineImplId
  238. )
  239. {
  240. SBI_RET Ret;
  241. Ret = SbiCall (SBI_EXT_BASE, SBI_EXT_BASE_GET_MIMPID, 0);
  242. *MachineImplId = (UINTN)Ret.Value;
  243. }
  244. //
  245. // SBI interface function for the hart state management extension
  246. //
  247. /**
  248. Politely ask the SBI to start a given hart.
  249. This call may return before the hart has actually started executing, if the
  250. SBI implementation can guarantee that the hart is actually going to start.
  251. Before the hart jumps to StartAddr, the hart MUST configure PMP if present
  252. and switch to S-mode.
  253. @param[in] HartId The id of the hart to start.
  254. @param[in] StartAddr The physical address, where the hart starts
  255. executing from.
  256. @param[in] Priv An XLEN-bit value, which will be in register
  257. a1 when the hart starts.
  258. @retval EFI_SUCCESS Hart was stopped and will start executing from StartAddr.
  259. @retval EFI_LOAD_ERROR StartAddr is not valid, possibly due to following reasons:
  260. - It is not a valid physical address.
  261. - The address is prohibited by PMP to run in
  262. supervisor mode.
  263. @retval EFI_INVALID_PARAMETER HartId is not a valid hart id
  264. @retval EFI_ALREADY_STARTED The hart is already running.
  265. @retval other The start request failed for unknown reasons.
  266. **/
  267. EFI_STATUS
  268. EFIAPI
  269. SbiHartStart (
  270. IN UINTN HartId,
  271. IN UINTN StartAddr,
  272. IN UINTN Priv
  273. )
  274. {
  275. SBI_RET Ret;
  276. Ret = SbiCall (
  277. SBI_EXT_HSM,
  278. SBI_EXT_HSM_HART_START,
  279. 3,
  280. HartId,
  281. StartAddr,
  282. Priv
  283. );
  284. return TranslateError (Ret.Error);
  285. }
  286. /**
  287. Return execution of the calling hart to SBI.
  288. MUST be called in S-Mode with user interrupts disabled.
  289. This call is not expected to return, unless a failure occurs.
  290. @retval EFI_SUCCESS Never occurs. When successful, the call does not return.
  291. @retval other Failed to stop hard for an unknown reason.
  292. **/
  293. EFI_STATUS
  294. EFIAPI
  295. SbiHartStop (
  296. )
  297. {
  298. SBI_RET Ret;
  299. Ret = SbiCall (SBI_EXT_HSM, SBI_EXT_HSM_HART_STOP, 0);
  300. return TranslateError (Ret.Error);
  301. }
  302. /**
  303. Get the current status of a hart.
  304. Since harts can transition between states at any time, the status retrieved
  305. by this function may already be out of date, once it returns.
  306. Possible values for HartStatus are:
  307. 0: STARTED
  308. 1: STOPPED
  309. 2: START_REQUEST_PENDING
  310. 3: STOP_REQUEST_PENDING
  311. @param[out] HartStatus The pointer in which the hart's status is
  312. stored.
  313. @retval EFI_SUCCESS The operation succeeds.
  314. @retval EFI_INVALID_PARAMETER A parameter is invalid.
  315. **/
  316. EFI_STATUS
  317. EFIAPI
  318. SbiHartGetStatus (
  319. IN UINTN HartId,
  320. OUT UINTN *HartStatus
  321. )
  322. {
  323. SBI_RET Ret;
  324. Ret = SbiCall (SBI_EXT_HSM, SBI_EXT_HSM_HART_GET_STATUS, 1, HartId);
  325. if (!Ret.Error) {
  326. *HartStatus = (UINTN)Ret.Value;
  327. }
  328. return TranslateError (Ret.Error);
  329. }
  330. /**
  331. Clear pending timer interrupt bit and set timer for next event after Time.
  332. To clear the timer without scheduling a timer event, set Time to a
  333. practically infinite value or mask the timer interrupt by clearing sie.STIE.
  334. @param[in] Time The time offset to the next scheduled timer interrupt.
  335. **/
  336. VOID
  337. EFIAPI
  338. SbiSetTimer (
  339. IN UINT64 Time
  340. )
  341. {
  342. SbiCall (SBI_EXT_TIME, SBI_EXT_TIME_SET_TIMER, 1, Time);
  343. }
  344. EFI_STATUS
  345. EFIAPI
  346. SbiSendIpi (
  347. IN UINTN *HartMask,
  348. IN UINTN HartMaskBase
  349. )
  350. {
  351. SBI_RET Ret;
  352. Ret = SbiCall (
  353. SBI_EXT_IPI,
  354. SBI_EXT_IPI_SEND_IPI,
  355. 2,
  356. (UINTN)HartMask,
  357. HartMaskBase
  358. );
  359. return TranslateError (Ret.Error);
  360. }
  361. /**
  362. Instructs remote harts to execute a FENCE.I instruction.
  363. @param[in] HartMask Scalar bit-vector containing hart ids
  364. @param[in] HartMaskBase The starting hartid from which the bit-vector
  365. must be computed. If set to -1, HartMask is
  366. ignored and all harts are considered.
  367. @retval EFI_SUCCESS IPI was sent to all the targeted harts.
  368. @retval EFI_INVALID_PARAMETER Either hart_mask_base or any of the hartid
  369. from hart_mask is not valid i.e. either the
  370. hartid is not enabled by the platform or is
  371. not available to the supervisor.
  372. **/
  373. EFI_STATUS
  374. EFIAPI
  375. SbiRemoteFenceI (
  376. IN UINTN *HartMask,
  377. IN UINTN HartMaskBase
  378. )
  379. {
  380. SBI_RET Ret;
  381. Ret = SbiCall (
  382. SBI_EXT_RFENCE,
  383. SBI_EXT_RFENCE_REMOTE_FENCE_I,
  384. 2,
  385. (UINTN)HartMask,
  386. HartMaskBase
  387. );
  388. return TranslateError (Ret.Error);
  389. }
  390. /**
  391. Instructs the remote harts to execute one or more SFENCE.VMA instructions.
  392. The SFENCE.VMA covers the range of virtual addresses between StartAddr and Size.
  393. The remote fence function acts as a full tlb flush if * StartAddr and size
  394. are both 0 * size is equal to 2^XLEN-1
  395. @param[in] HartMask Scalar bit-vector containing hart ids
  396. @param[in] HartMaskBase The starting hartid from which the bit-vector
  397. must be computed. If set to -1, HartMask is
  398. ignored and all harts are considered.
  399. @param[in] StartAddr The first address of the affected range.
  400. @param[in] Size How many addresses are affected.
  401. @retval EFI_SUCCESS IPI was sent to all the targeted harts.
  402. @retval EFI_LOAD_ERROR StartAddr or Size is not valid.
  403. @retval EFI_INVALID_PARAMETER Either hart_mask_base or any of the hartid
  404. from hart_mask is not valid i.e. either the
  405. hartid is not enabled by the platform or is
  406. not available to the supervisor.
  407. **/
  408. EFI_STATUS
  409. EFIAPI
  410. SbiRemoteSfenceVma (
  411. IN UINTN *HartMask,
  412. IN UINTN HartMaskBase,
  413. IN UINTN StartAddr,
  414. IN UINTN Size
  415. )
  416. {
  417. SBI_RET Ret;
  418. Ret = SbiCall (
  419. SBI_EXT_RFENCE,
  420. SBI_EXT_RFENCE_REMOTE_SFENCE_VMA,
  421. 4,
  422. (UINTN)HartMask,
  423. HartMaskBase,
  424. StartAddr,
  425. Size
  426. );
  427. return TranslateError (Ret.Error);
  428. }
  429. /**
  430. Instructs the remote harts to execute one or more SFENCE.VMA instructions.
  431. The SFENCE.VMA covers the range of virtual addresses between StartAddr and Size.
  432. Covers only the given ASID.
  433. The remote fence function acts as a full tlb flush if * StartAddr and size
  434. are both 0 * size is equal to 2^XLEN-1
  435. @param[in] HartMask Scalar bit-vector containing hart ids
  436. @param[in] HartMaskBase The starting hartid from which the bit-vector
  437. must be computed. If set to -1, HartMask is
  438. ignored and all harts are considered.
  439. @param[in] StartAddr The first address of the affected range.
  440. @param[in] Size How many addresses are affected.
  441. @retval EFI_SUCCESS IPI was sent to all the targeted harts.
  442. @retval EFI_LOAD_ERROR StartAddr or Size is not valid.
  443. @retval EFI_INVALID_PARAMETER Either hart_mask_base or any of the hartid
  444. from hart_mask is not valid i.e. either the
  445. hartid is not enabled by the platform or is
  446. not available to the supervisor.
  447. **/
  448. EFI_STATUS
  449. EFIAPI
  450. SbiRemoteSfenceVmaAsid (
  451. IN UINTN *HartMask,
  452. IN UINTN HartMaskBase,
  453. IN UINTN StartAddr,
  454. IN UINTN Size,
  455. IN UINTN Asid
  456. )
  457. {
  458. SBI_RET Ret;
  459. Ret = SbiCall (
  460. SBI_EXT_RFENCE,
  461. SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID,
  462. 5,
  463. (UINTN)HartMask,
  464. HartMaskBase,
  465. StartAddr,
  466. Size,
  467. Asid
  468. );
  469. return TranslateError (Ret.Error);
  470. }
  471. /**
  472. Instructs the remote harts to execute one or more SFENCE.GVMA instructions.
  473. The SFENCE.GVMA covers the range of virtual addresses between StartAddr and Size.
  474. Covers only the given VMID.
  475. This function call is only valid for harts implementing the hypervisor extension.
  476. The remote fence function acts as a full tlb flush if * StartAddr and size
  477. are both 0 * size is equal to 2^XLEN-1
  478. @param[in] HartMask Scalar bit-vector containing hart ids
  479. @param[in] HartMaskBase The starting hartid from which the bit-vector
  480. must be computed. If set to -1, HartMask is
  481. ignored and all harts are considered.
  482. @param[in] StartAddr The first address of the affected range.
  483. @param[in] Size How many addresses are affected.
  484. @retval EFI_SUCCESS IPI was sent to all the targeted harts.
  485. @retval EFI_LOAD_ERROR StartAddr or Size is not valid.
  486. @retval EFI_UNSUPPORTED SBI does not implement this function or one
  487. of the target harts does not support the
  488. hypervisor extension.
  489. @retval EFI_INVALID_PARAMETER Either hart_mask_base or any of the hartid
  490. from hart_mask is not valid i.e. either the
  491. hartid is not enabled by the platform or is
  492. not available to the supervisor.
  493. **/
  494. EFI_STATUS
  495. EFIAPI
  496. SbiRemoteHFenceGvmaVmid (
  497. IN UINTN *HartMask,
  498. IN UINTN HartMaskBase,
  499. IN UINTN StartAddr,
  500. IN UINTN Size,
  501. IN UINTN Vmid
  502. )
  503. {
  504. SBI_RET Ret;
  505. Ret = SbiCall (
  506. SBI_EXT_RFENCE,
  507. SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA,
  508. 5,
  509. (UINTN)HartMask,
  510. HartMaskBase,
  511. StartAddr,
  512. Size,
  513. Vmid
  514. );
  515. return TranslateError (Ret.Error);
  516. }
  517. /**
  518. Instructs the remote harts to execute one or more SFENCE.GVMA instructions.
  519. The SFENCE.GVMA covers the range of virtual addresses between StartAddr and Size.
  520. This function call is only valid for harts implementing the hypervisor extension.
  521. The remote fence function acts as a full tlb flush if * StartAddr and size
  522. are both 0 * size is equal to 2^XLEN-1
  523. @param[in] HartMask Scalar bit-vector containing hart ids
  524. @param[in] HartMaskBase The starting hartid from which the bit-vector
  525. must be computed. If set to -1, HartMask is
  526. ignored and all harts are considered.
  527. @param[in] StartAddr The first address of the affected range.
  528. @param[in] Size How many addresses are affected.
  529. @retval EFI_SUCCESS IPI was sent to all the targeted harts.
  530. @retval EFI_LOAD_ERROR StartAddr or Size is not valid.
  531. @retval EFI_UNSUPPORTED SBI does not implement this function or one
  532. of the target harts does not support the
  533. hypervisor extension.
  534. @retval EFI_INVALID_PARAMETER Either hart_mask_base or any of the hartid
  535. from hart_mask is not valid i.e. either the
  536. hartid is not enabled by the platform or is
  537. not available to the supervisor.
  538. **/
  539. EFI_STATUS
  540. EFIAPI
  541. SbiRemoteHFenceGvma (
  542. IN UINTN *HartMask,
  543. IN UINTN HartMaskBase,
  544. IN UINTN StartAddr,
  545. IN UINTN Size
  546. )
  547. {
  548. SBI_RET Ret;
  549. Ret = SbiCall (
  550. SBI_EXT_RFENCE,
  551. SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA_VMID,
  552. 4,
  553. (UINTN)HartMask,
  554. HartMaskBase,
  555. StartAddr,
  556. Size
  557. );
  558. return TranslateError (Ret.Error);
  559. }
  560. /**
  561. Instructs the remote harts to execute one or more SFENCE.VVMA instructions.
  562. The SFENCE.GVMA covers the range of virtual addresses between StartAddr and Size.
  563. Covers only the given ASID.
  564. This function call is only valid for harts implementing the hypervisor extension.
  565. The remote fence function acts as a full tlb flush if * StartAddr and size
  566. are both 0 * size is equal to 2^XLEN-1
  567. @param[in] HartMask Scalar bit-vector containing hart ids
  568. @param[in] HartMaskBase The starting hartid from which the bit-vector
  569. must be computed. If set to -1, HartMask is
  570. ignored and all harts are considered.
  571. @param[in] StartAddr The first address of the affected range.
  572. @param[in] Size How many addresses are affected.
  573. @retval EFI_SUCCESS IPI was sent to all the targeted harts.
  574. @retval EFI_LOAD_ERROR StartAddr or Size is not valid.
  575. @retval EFI_UNSUPPORTED SBI does not implement this function or one
  576. of the target harts does not support the
  577. hypervisor extension.
  578. @retval EFI_INVALID_PARAMETER Either hart_mask_base or any of the hartid
  579. from hart_mask is not valid i.e. either the
  580. hartid is not enabled by the platform or is
  581. not available to the supervisor.
  582. **/
  583. EFI_STATUS
  584. EFIAPI
  585. SbiRemoteHFenceVvmaAsid (
  586. IN UINTN *HartMask,
  587. IN UINTN HartMaskBase,
  588. IN UINTN StartAddr,
  589. IN UINTN Size,
  590. IN UINTN Asid
  591. )
  592. {
  593. SBI_RET Ret;
  594. Ret = SbiCall (
  595. SBI_EXT_RFENCE,
  596. SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA,
  597. 5,
  598. (UINTN)HartMask,
  599. HartMaskBase,
  600. StartAddr,
  601. Size,
  602. Asid
  603. );
  604. return TranslateError (Ret.Error);
  605. }
  606. /**
  607. Instructs the remote harts to execute one or more SFENCE.VVMA instructions.
  608. The SFENCE.GVMA covers the range of virtual addresses between StartAddr and Size.
  609. This function call is only valid for harts implementing the hypervisor extension.
  610. The remote fence function acts as a full tlb flush if * StartAddr and size
  611. are both 0 * size is equal to 2^XLEN-1
  612. @param[in] HartMask Scalar bit-vector containing hart ids
  613. @param[in] HartMaskBase The starting hartid from which the bit-vector
  614. must be computed. If set to -1, HartMask is
  615. ignored and all harts are considered.
  616. @param[in] StartAddr The first address of the affected range.
  617. @param[in] Size How many addresses are affected.
  618. @retval EFI_SUCCESS IPI was sent to all the targeted harts.
  619. @retval EFI_LOAD_ERROR StartAddr or Size is not valid.
  620. @retval EFI_UNSUPPORTED SBI does not implement this function or one
  621. of the target harts does not support the
  622. hypervisor extension.
  623. @retval EFI_INVALID_PARAMETER Either hart_mask_base or any of the hartid
  624. from hart_mask is not valid i.e. either the
  625. hartid is not enabled by the platform or is
  626. not available to the supervisor.
  627. **/
  628. EFI_STATUS
  629. EFIAPI
  630. SbiRemoteHFenceVvma (
  631. IN UINTN *HartMask,
  632. IN UINTN HartMaskBase,
  633. IN UINTN StartAddr,
  634. IN UINTN Size
  635. )
  636. {
  637. SBI_RET Ret;
  638. Ret = SbiCall (
  639. SBI_EXT_RFENCE,
  640. SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA_ASID,
  641. 4,
  642. (UINTN)HartMask,
  643. HartMaskBase,
  644. StartAddr,
  645. Size
  646. );
  647. return TranslateError (Ret.Error);
  648. }
  649. /**
  650. Reset the system
  651. The System Reset Extension provides a function that allow the supervisor
  652. software to request system-level reboot or shutdown. The term "system" refers
  653. to the world-view of supervisor software and the underlying SBI
  654. implementation could be machine mode firmware or hypervisor.
  655. Valid parameters for ResetType and ResetReason are defined in sbi_ecall_interface.h
  656. #define SBI_SRST_RESET_TYPE_SHUTDOWN 0x0
  657. #define SBI_SRST_RESET_TYPE_COLD_REBOOT 0x1
  658. #define SBI_SRST_RESET_TYPE_WARM_REBOOT 0x2
  659. #define SBI_SRST_RESET_REASON_NONE 0x0
  660. #define SBI_SRST_RESET_REASON_SYSFAIL 0x1
  661. When the call is successful, it will not return.
  662. @param[in] ResetType Typ of reset: Shutdown, cold-, or warm-reset.
  663. @param[in] ResetReason Why the system resets. No reason or system failure.
  664. @retval EFI_INVALID_PARAMETER Either ResetType or ResetReason is invalid.
  665. @retval EFI_UNSUPPORTED ResetType is valid but not implemented on the platform.
  666. @retval EFI_DEVICE_ERROR Unknown error.
  667. **/
  668. EFI_STATUS
  669. EFIAPI
  670. SbiSystemReset (
  671. IN UINTN ResetType,
  672. IN UINTN ResetReason
  673. )
  674. {
  675. SBI_RET Ret;
  676. Ret = SbiCall (
  677. SBI_EXT_SRST,
  678. SBI_EXT_SRST_RESET,
  679. 2,
  680. ResetType,
  681. ResetReason
  682. );
  683. return TranslateError (Ret.Error);
  684. }
  685. //
  686. // SBI interface function for the vendor extension
  687. //
  688. /**
  689. Call a function in a vendor defined SBI extension
  690. ASSERT() if the ExtensionId is not in the designated SBI Vendor Extension
  691. Space or NumArgs exceeds SBI_CALL_MAX_ARGS.
  692. @param[in] ExtensionId The SBI vendor extension ID.
  693. @param[in] FunctionId The function ID to call in this extension.
  694. @param[in] NumArgs How many arguments are passed.
  695. @param[in] ... Actual Arguments to the function.
  696. @retval EFI_SUCCESS if the SBI function was called and it was successful
  697. @retval others if the called SBI function returns an error
  698. **/
  699. EFI_STATUS
  700. EFIAPI
  701. SbiVendorCall (
  702. IN UINTN ExtensionId,
  703. IN UINTN FunctionId,
  704. IN UINTN NumArgs,
  705. ...
  706. )
  707. {
  708. SBI_RET Ret;
  709. VA_LIST Args;
  710. VA_START (Args, NumArgs);
  711. ASSERT (ExtensionId >= SBI_EXT_VENDOR_START && ExtensionId <= SBI_EXT_VENDOR_END);
  712. ASSERT (NumArgs <= SBI_CALL_MAX_ARGS);
  713. switch (NumArgs) {
  714. case 0:
  715. Ret = SbiCall (ExtensionId, FunctionId, NumArgs);
  716. break;
  717. case 1:
  718. Ret = SbiCall (ExtensionId, FunctionId, NumArgs, VA_ARG (Args, UINTN));
  719. break;
  720. case 2:
  721. Ret = SbiCall (
  722. ExtensionId,
  723. FunctionId,
  724. NumArgs,
  725. VA_ARG (Args, UINTN),
  726. VA_ARG (Args, UINTN)
  727. );
  728. break;
  729. case 3:
  730. Ret = SbiCall (
  731. ExtensionId,
  732. FunctionId,
  733. NumArgs,
  734. VA_ARG (Args, UINTN),
  735. VA_ARG (Args, UINTN),
  736. VA_ARG (Args, UINTN)
  737. );
  738. break;
  739. case 4:
  740. Ret = SbiCall (
  741. ExtensionId,
  742. FunctionId,
  743. NumArgs,
  744. VA_ARG (Args, UINTN),
  745. VA_ARG (Args, UINTN),
  746. VA_ARG (Args, UINTN),
  747. VA_ARG (Args, UINTN)
  748. );
  749. break;
  750. case 5:
  751. Ret = SbiCall (
  752. ExtensionId,
  753. FunctionId,
  754. NumArgs,
  755. VA_ARG (Args, UINTN),
  756. VA_ARG (Args, UINTN),
  757. VA_ARG (Args, UINTN),
  758. VA_ARG (Args, UINTN),
  759. VA_ARG (Args, UINTN)
  760. );
  761. break;
  762. case 6:
  763. Ret = SbiCall (
  764. ExtensionId,
  765. FunctionId,
  766. NumArgs,
  767. VA_ARG (Args, UINTN),
  768. VA_ARG (Args, UINTN),
  769. VA_ARG (Args, UINTN),
  770. VA_ARG (Args, UINTN),
  771. VA_ARG (Args, UINTN),
  772. VA_ARG (Args, UINTN)
  773. );
  774. break;
  775. default:
  776. // Too many args. In theory SBI can handle more arguments when they are
  777. // passed on the stack but no SBI extension uses this, therefore it's
  778. // not yet implemented here.
  779. return EFI_INVALID_PARAMETER;
  780. }
  781. VA_END (Args);
  782. return TranslateError (Ret.Error);
  783. }
  784. //
  785. // SBI Firmware extension
  786. //
  787. /**
  788. Get scratch space of the current hart.
  789. Please consider using the wrapper SbiGetFirmwareContext if you only need to
  790. access the firmware context.
  791. @param[out] ScratchSpace The scratch space pointer.
  792. **/
  793. VOID
  794. EFIAPI
  795. SbiGetMscratch (
  796. OUT SBI_SCRATCH **ScratchSpace
  797. )
  798. {
  799. SBI_RET Ret;
  800. Ret = SbiCall (SBI_EDK2_FW_EXT, SBI_EXT_FW_MSCRATCH_FUNC, 0);
  801. // Our ecall handler never returns an error, only when the func id is invalid
  802. ASSERT (Ret.Error == SBI_OK);
  803. *ScratchSpace = (SBI_SCRATCH *)Ret.Value;
  804. }
  805. /**
  806. Get scratch space of the given hart id.
  807. @param[in] HartId The hart id.
  808. @param[out] ScratchSpace The scratch space pointer.
  809. **/
  810. VOID
  811. EFIAPI
  812. SbiGetMscratchHartid (
  813. IN UINTN HartId,
  814. OUT SBI_SCRATCH **ScratchSpace
  815. )
  816. {
  817. SBI_RET Ret;
  818. Ret = SbiCall (
  819. SBI_EDK2_FW_EXT,
  820. SBI_EXT_FW_MSCRATCH_HARTID_FUNC,
  821. 1,
  822. HartId
  823. );
  824. // Our ecall handler never returns an error, only when the func id is invalid
  825. ASSERT (Ret.Error == SBI_OK);
  826. *ScratchSpace = (SBI_SCRATCH *)Ret.Value;
  827. }
  828. /**
  829. Get firmware context of the calling hart.
  830. @param[out] FirmwareContext The firmware context pointer.
  831. @retval EFI_SUCCESS The operation succeeds.
  832. **/
  833. VOID
  834. EFIAPI
  835. SbiGetFirmwareContext (
  836. OUT EFI_RISCV_OPENSBI_FIRMWARE_CONTEXT **FirmwareContext
  837. )
  838. {
  839. SBI_SCRATCH *ScratchSpace;
  840. SBI_PLATFORM *SbiPlatform;
  841. SbiGetMscratch (&ScratchSpace);
  842. SbiPlatform = (SBI_PLATFORM *)sbi_platform_ptr (ScratchSpace);
  843. *FirmwareContext = (EFI_RISCV_OPENSBI_FIRMWARE_CONTEXT *)SbiPlatform->firmware_context;
  844. }
  845. /**
  846. Set firmware context of the calling hart.
  847. @param[in] FirmwareContext The firmware context pointer.
  848. **/
  849. VOID
  850. EFIAPI
  851. SbiSetFirmwareContext (
  852. IN EFI_RISCV_OPENSBI_FIRMWARE_CONTEXT *FirmwareContext
  853. )
  854. {
  855. SBI_SCRATCH *ScratchSpace;
  856. SBI_PLATFORM *SbiPlatform;
  857. SbiGetMscratch (&ScratchSpace);
  858. SbiPlatform = (SBI_PLATFORM *)sbi_platform_ptr (ScratchSpace);
  859. SbiPlatform->firmware_context = (UINTN)FirmwareContext;
  860. }