sbi.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  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 <rtthread.h>
  38. #include <stdbool.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 sbi_get_spec_version(void)
  49. {
  50. return (SBI_CALL0(SBI_EXT_ID_BASE, SBI_BASE_GET_SPEC_VERSION));
  51. }
  52. static struct sbi_ret sbi_get_impl_id(void)
  53. {
  54. return (SBI_CALL0(SBI_EXT_ID_BASE, SBI_BASE_GET_IMPL_ID));
  55. }
  56. static struct sbi_ret sbi_get_impl_version(void)
  57. {
  58. return (SBI_CALL0(SBI_EXT_ID_BASE, SBI_BASE_GET_IMPL_VERSION));
  59. }
  60. void sbi_print_version(void)
  61. {
  62. unsigned int major;
  63. unsigned int minor;
  64. /* For legacy SBI implementations. */
  65. if (sbi_spec_version == 0)
  66. {
  67. rt_kprintf("SBI: Unknown (Legacy) Implementation\n");
  68. rt_kprintf("SBI Specification Version: 0.1\n");
  69. return;
  70. }
  71. switch (sbi_impl_id)
  72. {
  73. case (SBI_IMPL_ID_BBL):
  74. rt_kprintf("SBI: Berkely Boot Loader %lu\n", sbi_impl_version);
  75. break;
  76. case (SBI_IMPL_ID_XVISOR):
  77. rt_kprintf("SBI: eXtensible Versatile hypervISOR %lu\n",
  78. sbi_impl_version);
  79. break;
  80. case (SBI_IMPL_ID_KVM):
  81. rt_kprintf("SBI: Kernel-based Virtual Machine %lu\n", sbi_impl_version);
  82. break;
  83. case (SBI_IMPL_ID_RUSTSBI):
  84. rt_kprintf("SBI: RustSBI %lu\n", sbi_impl_version);
  85. break;
  86. case (SBI_IMPL_ID_DIOSIX):
  87. rt_kprintf("SBI: Diosix %lu\n", sbi_impl_version);
  88. break;
  89. case (SBI_IMPL_ID_OPENSBI):
  90. major = sbi_impl_version >> OPENSBI_VERSION_MAJOR_OFFSET;
  91. minor = sbi_impl_version & OPENSBI_VERSION_MINOR_MASK;
  92. rt_kprintf("SBI: OpenSBI v%u.%u\n", major, minor);
  93. break;
  94. default:
  95. rt_kprintf("SBI: Unrecognized Implementation: %lu\n", sbi_impl_id);
  96. break;
  97. }
  98. major = (sbi_spec_version & SBI_SPEC_VERS_MAJOR_MASK) >>
  99. SBI_SPEC_VERS_MAJOR_OFFSET;
  100. minor = (sbi_spec_version & SBI_SPEC_VERS_MINOR_MASK);
  101. rt_kprintf("SBI Specification Version: %u.%u\n", major, minor);
  102. }
  103. void sbi_set_timer(uint64_t val)
  104. {
  105. struct sbi_ret ret;
  106. /* Use the TIME legacy replacement extension, if available. */
  107. if (has_time_extension)
  108. {
  109. ret = SBI_CALL1(SBI_EXT_ID_TIME, SBI_TIME_SET_TIMER, val);
  110. RT_ASSERT(ret.error == SBI_SUCCESS);
  111. }
  112. else
  113. {
  114. (void)SBI_CALL1(SBI_SET_TIMER, 0, val);
  115. }
  116. }
  117. void sbi_send_ipi(const unsigned long *hart_mask)
  118. {
  119. struct sbi_ret ret;
  120. /* Use the IPI legacy replacement extension, if available. */
  121. if (has_ipi_extension)
  122. {
  123. ret = SBI_CALL2(SBI_EXT_ID_IPI, SBI_IPI_SEND_IPI, *hart_mask, 0);
  124. RT_ASSERT(ret.error == SBI_SUCCESS);
  125. }
  126. else
  127. {
  128. (void)SBI_CALL1(SBI_SEND_IPI, 0, (uint64_t)hart_mask);
  129. }
  130. }
  131. void sbi_remote_fence_i(const unsigned long *hart_mask)
  132. {
  133. struct sbi_ret ret;
  134. /* Use the RFENCE legacy replacement extension, if available. */
  135. if (has_rfnc_extension)
  136. {
  137. ret =
  138. SBI_CALL2(SBI_EXT_ID_RFNC, SBI_RFNC_REMOTE_FENCE_I, *hart_mask, 0);
  139. RT_ASSERT(ret.error == SBI_SUCCESS);
  140. }
  141. else
  142. {
  143. (void)SBI_CALL1(SBI_REMOTE_FENCE_I, 0, (uint64_t)hart_mask);
  144. }
  145. }
  146. int sbi_remote_sfence_vma(const unsigned long *hart_mask,
  147. const unsigned long hart_mask_base,
  148. unsigned long start, unsigned long size)
  149. {
  150. struct sbi_ret ret = {.error = SBI_SUCCESS};
  151. /* Use the RFENCE legacy replacement extension, if available. */
  152. if (has_rfnc_extension)
  153. {
  154. ret = SBI_CALL4(SBI_EXT_ID_RFNC, SBI_RFNC_REMOTE_SFENCE_VMA, *hart_mask,
  155. hart_mask_base, start, size);
  156. }
  157. else
  158. {
  159. (void)SBI_CALL3(SBI_REMOTE_SFENCE_VMA, 0, (uint64_t)hart_mask, start,
  160. size);
  161. }
  162. return ret.error;
  163. }
  164. void sbi_remote_sfence_vma_asid(const unsigned long *hart_mask,
  165. unsigned long start, unsigned long size,
  166. unsigned long asid)
  167. {
  168. struct sbi_ret ret;
  169. /* Use the RFENCE legacy replacement extension, if available. */
  170. if (has_rfnc_extension)
  171. {
  172. ret = SBI_CALL5(SBI_EXT_ID_RFNC, SBI_RFNC_REMOTE_SFENCE_VMA_ASID,
  173. *hart_mask, 0, start, size, asid);
  174. RT_ASSERT(ret.error == SBI_SUCCESS);
  175. }
  176. else
  177. {
  178. (void)SBI_CALL4(SBI_REMOTE_SFENCE_VMA_ASID, 0, (uint64_t)hart_mask,
  179. start, size, asid);
  180. }
  181. }
  182. int sbi_hsm_hart_start(unsigned long hart, unsigned long start_addr,
  183. unsigned long priv)
  184. {
  185. struct sbi_ret ret;
  186. ret = SBI_CALL3(SBI_EXT_ID_HSM, SBI_HSM_HART_START, hart, start_addr, priv);
  187. return (ret.error != 0 ? (int)ret.error : 0);
  188. }
  189. void sbi_hsm_hart_stop(void)
  190. {
  191. (void)SBI_CALL0(SBI_EXT_ID_HSM, SBI_HSM_HART_STOP);
  192. }
  193. int sbi_hsm_hart_status(unsigned long hart)
  194. {
  195. struct sbi_ret ret;
  196. ret = SBI_CALL1(SBI_EXT_ID_HSM, SBI_HSM_HART_STATUS, hart);
  197. return (ret.error != 0 ? (int)ret.error : (int)ret.value);
  198. }
  199. void sbi_init(void)
  200. {
  201. struct sbi_ret sret;
  202. /*
  203. * Get the spec version. For legacy SBI implementations this will
  204. * return an error, otherwise it is guaranteed to succeed.
  205. */
  206. sret = sbi_get_spec_version();
  207. if (sret.error != 0)
  208. {
  209. /* We are running a legacy SBI implementation. */
  210. sbi_spec_version = 0;
  211. return;
  212. }
  213. /* Set the SBI implementation info. */
  214. sbi_spec_version = sret.value;
  215. sbi_impl_id = sbi_get_impl_id().value;
  216. sbi_impl_version = sbi_get_impl_version().value;
  217. /* Probe for legacy replacement extensions. */
  218. if (sbi_probe_extension(SBI_EXT_ID_TIME) != 0)
  219. has_time_extension = true;
  220. if (sbi_probe_extension(SBI_EXT_ID_IPI) != 0)
  221. has_ipi_extension = true;
  222. if (sbi_probe_extension(SBI_EXT_ID_RFNC) != 0)
  223. has_rfnc_extension = true;
  224. }
  225. void rt_hw_console_output(const char *str)
  226. {
  227. while (*str)
  228. {
  229. sbi_console_putchar(*str++);
  230. }
  231. }