ipi.rs 1.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849
  1. use crate::ecall::SbiRet;
  2. use crate::hart_mask::HartMask;
  3. use crate::util::OnceFatBox;
  4. use alloc::boxed::Box;
  5. /// Inter-processor interrupt support
  6. pub trait Ipi: Send {
  7. /// Get the maximum hart id available by this IPI support module
  8. fn max_hart_id(&self) -> usize;
  9. /// Send an inter-processor interrupt to all the harts defined in `hart_mask`.
  10. ///
  11. /// Interprocessor interrupts manifest at the receiving harts as the supervisor software interrupts.
  12. ///
  13. /// # Return value
  14. ///
  15. /// Should return error code `SBI_SUCCESS` if IPI was sent to all the targeted harts successfully.
  16. fn send_ipi_many(&self, hart_mask: HartMask) -> SbiRet;
  17. }
  18. static IPI: OnceFatBox<dyn Ipi + Sync + 'static> = OnceFatBox::new();
  19. #[doc(hidden)] // use through a macro
  20. pub fn init_ipi<T: Ipi + Sync + 'static>(ipi: T) {
  21. let result = IPI.set(Box::new(ipi));
  22. if result.is_err() {
  23. panic!("load sbi module when already loaded")
  24. }
  25. }
  26. #[inline]
  27. pub(crate) fn probe_ipi() -> bool {
  28. IPI.get().is_some()
  29. }
  30. pub(crate) fn send_ipi_many(hart_mask: HartMask) -> SbiRet {
  31. if let Some(ipi) = IPI.get() {
  32. ipi.send_ipi_many(hart_mask)
  33. } else {
  34. SbiRet::not_supported()
  35. }
  36. }
  37. pub(crate) fn max_hart_id() -> Option<usize> {
  38. if let Some(ipi) = IPI.get() {
  39. Some(ipi.max_hart_id())
  40. } else {
  41. None
  42. }
  43. }