sbi.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2021-05-18 Bernard port from FreeBSD
  9. */
  10. /*-
  11. * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
  12. *
  13. * Copyright (c) 2019 Mitchell Horne <mhorne@FreeBSD.org>
  14. *
  15. * Redistribution and use in source and binary forms, with or without
  16. * modification, are permitted provided that the following conditions
  17. * are met:
  18. * 1. Redistributions of source code must retain the above copyright
  19. * notice, this list of conditions and the following disclaimer.
  20. * 2. Redistributions in binary form must reproduce the above copyright
  21. * notice, this list of conditions and the following disclaimer in the
  22. * documentation and/or other materials provided with the distribution.
  23. *
  24. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  25. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  28. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34. * SUCH DAMAGE.
  35. */
  36. #include "sbi.h"
  37. #include <stdbool.h>
  38. #include <rtthread.h>
  39. /* SBI Implementation-Specific Definitions */
  40. #define OPENSBI_VERSION_MAJOR_OFFSET 16
  41. #define OPENSBI_VERSION_MINOR_MASK 0xFFFF
  42. unsigned long sbi_spec_version;
  43. unsigned long sbi_impl_id;
  44. unsigned long sbi_impl_version;
  45. static bool has_time_extension = false;
  46. static bool has_ipi_extension = false;
  47. static bool has_rfnc_extension = false;
  48. static struct sbi_ret
  49. sbi_get_spec_version(void)
  50. {
  51. return (SBI_CALL0(SBI_EXT_ID_BASE, SBI_BASE_GET_SPEC_VERSION));
  52. }
  53. static struct sbi_ret
  54. sbi_get_impl_id(void)
  55. {
  56. return (SBI_CALL0(SBI_EXT_ID_BASE, SBI_BASE_GET_IMPL_ID));
  57. }
  58. static struct sbi_ret
  59. sbi_get_impl_version(void)
  60. {
  61. return (SBI_CALL0(SBI_EXT_ID_BASE, SBI_BASE_GET_IMPL_VERSION));
  62. }
  63. void
  64. sbi_print_version(void)
  65. {
  66. int major;
  67. int minor;
  68. /* For legacy SBI implementations. */
  69. if (sbi_spec_version == 0)
  70. {
  71. rt_kprintf("SBI: Unknown (Legacy) Implementation\n");
  72. rt_kprintf("SBI Specification Version: 0.1\n");
  73. return;
  74. }
  75. switch (sbi_impl_id)
  76. {
  77. case (SBI_IMPL_ID_BBL):
  78. rt_kprintf("SBI: Berkely Boot Loader %lu\n", sbi_impl_version);
  79. break;
  80. case (SBI_IMPL_ID_XVISOR):
  81. rt_kprintf("SBI: eXtensible Versatile hypervISOR %lu\n", sbi_impl_version);
  82. break;
  83. case (SBI_IMPL_ID_KVM):
  84. rt_kprintf("SBI: Kernel-based Virtual Machine %lu\n", sbi_impl_version);
  85. break;
  86. case (SBI_IMPL_ID_RUSTSBI):
  87. rt_kprintf("SBI: RustSBI %lu\n", sbi_impl_version);
  88. break;
  89. case (SBI_IMPL_ID_DIOSIX):
  90. rt_kprintf("SBI: Diosix %lu\n", sbi_impl_version);
  91. break;
  92. case (SBI_IMPL_ID_OPENSBI):
  93. major = sbi_impl_version >> OPENSBI_VERSION_MAJOR_OFFSET;
  94. minor = sbi_impl_version & OPENSBI_VERSION_MINOR_MASK;
  95. rt_kprintf("SBI: OpenSBI v%u.%u\n", major, minor);
  96. break;
  97. default:
  98. rt_kprintf("SBI: Unrecognized Implementation: %lu\n", sbi_impl_id);
  99. break;
  100. }
  101. major = (sbi_spec_version & SBI_SPEC_VERS_MAJOR_MASK) >>
  102. SBI_SPEC_VERS_MAJOR_OFFSET;
  103. minor = (sbi_spec_version & SBI_SPEC_VERS_MINOR_MASK);
  104. rt_kprintf("SBI Specification Version: %u.%u\n", major, minor);
  105. }
  106. void
  107. sbi_set_timer(uint64_t val)
  108. {
  109. struct sbi_ret ret;
  110. /* Use the TIME legacy replacement extension, if available. */
  111. if (has_time_extension)
  112. {
  113. ret = SBI_CALL1(SBI_EXT_ID_TIME, SBI_TIME_SET_TIMER, val);
  114. RT_ASSERT(ret.error == SBI_SUCCESS);
  115. }
  116. else
  117. {
  118. (void)SBI_CALL1(SBI_SET_TIMER, 0, val);
  119. }
  120. }
  121. void
  122. sbi_send_ipi(const unsigned long *hart_mask)
  123. {
  124. struct sbi_ret ret;
  125. /* Use the IPI legacy replacement extension, if available. */
  126. if (has_ipi_extension)
  127. {
  128. ret = SBI_CALL2(SBI_EXT_ID_IPI, SBI_IPI_SEND_IPI,
  129. *hart_mask, 0);
  130. RT_ASSERT(ret.error == SBI_SUCCESS);
  131. }
  132. else
  133. {
  134. (void)SBI_CALL1(SBI_SEND_IPI, 0, (uint64_t)hart_mask);
  135. }
  136. }
  137. void
  138. sbi_remote_fence_i(const unsigned long *hart_mask)
  139. {
  140. struct sbi_ret ret;
  141. /* Use the RFENCE legacy replacement extension, if available. */
  142. if (has_rfnc_extension)
  143. {
  144. ret = SBI_CALL2(SBI_EXT_ID_RFNC, SBI_RFNC_REMOTE_FENCE_I,
  145. *hart_mask, 0);
  146. RT_ASSERT(ret.error == SBI_SUCCESS);
  147. }
  148. else
  149. {
  150. (void)SBI_CALL1(SBI_REMOTE_FENCE_I, 0, (uint64_t)hart_mask);
  151. }
  152. }
  153. void
  154. sbi_remote_sfence_vma(const unsigned long *hart_mask, unsigned long start, unsigned long size)
  155. {
  156. struct sbi_ret ret;
  157. /* Use the RFENCE legacy replacement extension, if available. */
  158. if (has_rfnc_extension)
  159. {
  160. ret = SBI_CALL4(SBI_EXT_ID_RFNC, SBI_RFNC_REMOTE_SFENCE_VMA,
  161. *hart_mask, 0, start, size);
  162. RT_ASSERT(ret.error == SBI_SUCCESS);
  163. }
  164. else
  165. {
  166. (void)SBI_CALL3(SBI_REMOTE_SFENCE_VMA, 0, (uint64_t)hart_mask,
  167. start, size);
  168. }
  169. }
  170. void
  171. sbi_remote_sfence_vma_asid(const unsigned long *hart_mask, unsigned long start, unsigned long size,
  172. unsigned long asid)
  173. {
  174. struct sbi_ret ret;
  175. /* Use the RFENCE legacy replacement extension, if available. */
  176. if (has_rfnc_extension)
  177. {
  178. ret = SBI_CALL5(SBI_EXT_ID_RFNC, SBI_RFNC_REMOTE_SFENCE_VMA_ASID,
  179. *hart_mask, 0, start, size, asid);
  180. RT_ASSERT(ret.error == SBI_SUCCESS);
  181. }
  182. else
  183. {
  184. (void)SBI_CALL4(SBI_REMOTE_SFENCE_VMA_ASID, 0,
  185. (uint64_t)hart_mask, start, size, asid);
  186. }
  187. }
  188. int
  189. sbi_hsm_hart_start(unsigned long hart, unsigned long start_addr, unsigned long priv)
  190. {
  191. struct sbi_ret ret;
  192. ret = SBI_CALL3(SBI_EXT_ID_HSM, SBI_HSM_HART_START, hart, start_addr, priv);
  193. return (ret.error != 0 ? (int)ret.error : 0);
  194. }
  195. void
  196. sbi_hsm_hart_stop(void)
  197. {
  198. (void)SBI_CALL0(SBI_EXT_ID_HSM, SBI_HSM_HART_STOP);
  199. }
  200. int
  201. sbi_hsm_hart_status(unsigned long hart)
  202. {
  203. struct sbi_ret ret;
  204. ret = SBI_CALL1(SBI_EXT_ID_HSM, SBI_HSM_HART_STATUS, hart);
  205. return (ret.error != 0 ? (int)ret.error : (int)ret.value);
  206. }
  207. void
  208. sbi_init(void)
  209. {
  210. struct sbi_ret sret;
  211. /*
  212. * Get the spec version. For legacy SBI implementations this will
  213. * return an error, otherwise it is guaranteed to succeed.
  214. */
  215. sret = sbi_get_spec_version();
  216. if (sret.error != 0)
  217. {
  218. /* We are running a legacy SBI implementation. */
  219. sbi_spec_version = 0;
  220. return;
  221. }
  222. /* Set the SBI implementation info. */
  223. sbi_spec_version = sret.value;
  224. sbi_impl_id = sbi_get_impl_id().value;
  225. sbi_impl_version = sbi_get_impl_version().value;
  226. /* Probe for legacy replacement extensions. */
  227. if (sbi_probe_extension(SBI_EXT_ID_TIME) != 0)
  228. has_time_extension = true;
  229. if (sbi_probe_extension(SBI_EXT_ID_IPI) != 0)
  230. has_ipi_extension = true;
  231. if (sbi_probe_extension(SBI_EXT_ID_RFNC) != 0)
  232. has_rfnc_extension = true;
  233. }