sbi_ecall_replace.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. /*
  2. * SPDX-License-Identifier: BSD-2-Clause
  3. *
  4. * Copyright (c) 2020 Western Digital Corporation or its affiliates.
  5. *
  6. * Authors:
  7. * Anup Patel <anup.patel@wdc.com>
  8. * Atish Patra <atish.patra@wdc.com>
  9. */
  10. #include <sbi/riscv_asm.h>
  11. #include <sbi/sbi_ecall.h>
  12. #include <sbi/sbi_ecall_interface.h>
  13. #include <sbi/sbi_error.h>
  14. #include <sbi/sbi_hart.h>
  15. #include <sbi/sbi_ipi.h>
  16. #include <sbi/sbi_system.h>
  17. #include <sbi/sbi_timer.h>
  18. #include <sbi/sbi_tlb.h>
  19. #include <sbi/sbi_trap.h>
  20. #ifdef CONFIG_SBI_ECALL_TIME
  21. static int sbi_ecall_time_handler(unsigned long extid, unsigned long funcid,
  22. const struct sbi_trap_regs *regs,
  23. unsigned long *out_val,
  24. struct sbi_trap_info *out_trap)
  25. {
  26. int ret = 0;
  27. if (funcid == SBI_EXT_TIME_SET_TIMER) {
  28. #if __riscv_xlen == 32
  29. sbi_timer_event_start((((u64)regs->a1 << 32) | (u64)regs->a0));
  30. #else
  31. sbi_timer_event_start((u64)regs->a0);
  32. #endif
  33. } else
  34. ret = SBI_ENOTSUPP;
  35. return ret;
  36. }
  37. struct sbi_ecall_extension ecall_time = {
  38. .extid_start = SBI_EXT_TIME,
  39. .extid_end = SBI_EXT_TIME,
  40. .handle = sbi_ecall_time_handler,
  41. };
  42. #endif
  43. #ifdef CONFIG_SBI_ECALL_RFENCE
  44. static int sbi_ecall_rfence_handler(unsigned long extid, unsigned long funcid,
  45. const struct sbi_trap_regs *regs,
  46. unsigned long *out_val,
  47. struct sbi_trap_info *out_trap)
  48. {
  49. int ret = 0;
  50. unsigned long vmid;
  51. struct sbi_tlb_info tlb_info;
  52. u32 source_hart = current_hartid();
  53. if (funcid >= SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA_VMID &&
  54. funcid <= SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA)
  55. if (!misa_extension('H'))
  56. return SBI_ENOTSUPP;
  57. switch (funcid) {
  58. case SBI_EXT_RFENCE_REMOTE_FENCE_I:
  59. SBI_TLB_INFO_INIT(&tlb_info, 0, 0, 0, 0,
  60. sbi_tlb_local_fence_i, source_hart);
  61. ret = sbi_tlb_request(regs->a0, regs->a1, &tlb_info);
  62. break;
  63. case SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA:
  64. SBI_TLB_INFO_INIT(&tlb_info, regs->a2, regs->a3, 0, 0,
  65. sbi_tlb_local_hfence_gvma, source_hart);
  66. ret = sbi_tlb_request(regs->a0, regs->a1, &tlb_info);
  67. break;
  68. case SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA_VMID:
  69. SBI_TLB_INFO_INIT(&tlb_info, regs->a2, regs->a3, 0, regs->a4,
  70. sbi_tlb_local_hfence_gvma_vmid,
  71. source_hart);
  72. ret = sbi_tlb_request(regs->a0, regs->a1, &tlb_info);
  73. break;
  74. case SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA:
  75. vmid = (csr_read(CSR_HGATP) & HGATP_VMID_MASK);
  76. vmid = vmid >> HGATP_VMID_SHIFT;
  77. SBI_TLB_INFO_INIT(&tlb_info, regs->a2, regs->a3, 0, vmid,
  78. sbi_tlb_local_hfence_vvma, source_hart);
  79. ret = sbi_tlb_request(regs->a0, regs->a1, &tlb_info);
  80. break;
  81. case SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA_ASID:
  82. vmid = (csr_read(CSR_HGATP) & HGATP_VMID_MASK);
  83. vmid = vmid >> HGATP_VMID_SHIFT;
  84. SBI_TLB_INFO_INIT(&tlb_info, regs->a2, regs->a3, regs->a4,
  85. vmid, sbi_tlb_local_hfence_vvma_asid,
  86. source_hart);
  87. ret = sbi_tlb_request(regs->a0, regs->a1, &tlb_info);
  88. break;
  89. case SBI_EXT_RFENCE_REMOTE_SFENCE_VMA:
  90. SBI_TLB_INFO_INIT(&tlb_info, regs->a2, regs->a3, 0, 0,
  91. sbi_tlb_local_sfence_vma, source_hart);
  92. ret = sbi_tlb_request(regs->a0, regs->a1, &tlb_info);
  93. break;
  94. case SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID:
  95. SBI_TLB_INFO_INIT(&tlb_info, regs->a2, regs->a3, regs->a4, 0,
  96. sbi_tlb_local_sfence_vma_asid, source_hart);
  97. ret = sbi_tlb_request(regs->a0, regs->a1, &tlb_info);
  98. break;
  99. default:
  100. ret = SBI_ENOTSUPP;
  101. };
  102. return ret;
  103. }
  104. struct sbi_ecall_extension ecall_rfence = {
  105. .extid_start = SBI_EXT_RFENCE,
  106. .extid_end = SBI_EXT_RFENCE,
  107. .handle = sbi_ecall_rfence_handler,
  108. };
  109. #endif
  110. #ifdef CONFIG_SBI_ECALL_IPI
  111. static int sbi_ecall_ipi_handler(unsigned long extid, unsigned long funcid,
  112. const struct sbi_trap_regs *regs,
  113. unsigned long *out_val,
  114. struct sbi_trap_info *out_trap)
  115. {
  116. int ret = 0;
  117. if (funcid == SBI_EXT_IPI_SEND_IPI)
  118. ret = sbi_ipi_send_smode(regs->a0, regs->a1);
  119. else
  120. ret = SBI_ENOTSUPP;
  121. return ret;
  122. }
  123. struct sbi_ecall_extension ecall_ipi = {
  124. .extid_start = SBI_EXT_IPI,
  125. .extid_end = SBI_EXT_IPI,
  126. .handle = sbi_ecall_ipi_handler,
  127. };
  128. #endif
  129. #ifdef CONFIG_SBI_ECALL_SRST
  130. static int sbi_ecall_srst_handler(unsigned long extid, unsigned long funcid,
  131. const struct sbi_trap_regs *regs,
  132. unsigned long *out_val,
  133. struct sbi_trap_info *out_trap)
  134. {
  135. if (funcid == SBI_EXT_SRST_RESET) {
  136. if ((((u32)-1U) <= ((u64)regs->a0)) ||
  137. (((u32)-1U) <= ((u64)regs->a1)))
  138. return SBI_EINVAL;
  139. switch (regs->a0) {
  140. case SBI_SRST_RESET_TYPE_SHUTDOWN:
  141. case SBI_SRST_RESET_TYPE_COLD_REBOOT:
  142. case SBI_SRST_RESET_TYPE_WARM_REBOOT:
  143. break;
  144. default:
  145. return SBI_EINVAL;
  146. }
  147. switch (regs->a1) {
  148. case SBI_SRST_RESET_REASON_NONE:
  149. case SBI_SRST_RESET_REASON_SYSFAIL:
  150. break;
  151. default:
  152. return SBI_EINVAL;
  153. }
  154. if (sbi_system_reset_supported(regs->a0, regs->a1))
  155. sbi_system_reset(regs->a0, regs->a1);
  156. }
  157. return SBI_ENOTSUPP;
  158. }
  159. static int sbi_ecall_srst_probe(unsigned long extid, unsigned long *out_val)
  160. {
  161. u32 type, count = 0;
  162. /*
  163. * At least one standard reset types should be supported by
  164. * the platform for SBI SRST extension to be usable.
  165. */
  166. for (type = 0; type <= SBI_SRST_RESET_TYPE_LAST; type++) {
  167. if (sbi_system_reset_supported(type,
  168. SBI_SRST_RESET_REASON_NONE))
  169. count++;
  170. }
  171. *out_val = (count) ? 1 : 0;
  172. return 0;
  173. }
  174. struct sbi_ecall_extension ecall_srst = {
  175. .extid_start = SBI_EXT_SRST,
  176. .extid_end = SBI_EXT_SRST,
  177. .handle = sbi_ecall_srst_handler,
  178. .probe = sbi_ecall_srst_probe,
  179. };
  180. #endif