ipi.rs 1.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
  1. use crate::hart_mask::HartMask;
  2. use sbi_spec::binary::SbiRet;
  3. #[cfg(feature = "singleton")]
  4. use crate::util::AmoOnceRef;
  5. /// Inter-processor interrupt support
  6. pub trait Ipi: Send + Sync {
  7. /// Send an inter-processor interrupt to all the harts defined in `hart_mask`.
  8. ///
  9. /// Inter-processor interrupts manifest at the receiving harts as the supervisor software interrupts.
  10. ///
  11. /// # Return value
  12. ///
  13. /// Should return `SbiRet::success()` if IPI was sent to all the targeted harts successfully.
  14. fn send_ipi(&self, hart_mask: HartMask) -> SbiRet;
  15. }
  16. impl<T: Ipi> Ipi for &T {
  17. #[inline]
  18. fn send_ipi(&self, hart_mask: HartMask) -> SbiRet {
  19. T::send_ipi(self, hart_mask)
  20. }
  21. }
  22. #[cfg(feature = "singleton")]
  23. static IPI: AmoOnceRef<dyn Ipi> = AmoOnceRef::new();
  24. /// Init singleton IPI module
  25. #[cfg(feature = "singleton")]
  26. pub fn init_ipi(ipi: &'static dyn Ipi) {
  27. if !IPI.try_call_once(ipi) {
  28. panic!("load sbi module when already loaded")
  29. }
  30. }
  31. #[cfg(feature = "singleton")]
  32. #[inline]
  33. pub(crate) fn probe_ipi() -> bool {
  34. IPI.get().is_some()
  35. }
  36. #[cfg(feature = "singleton")]
  37. #[inline]
  38. pub(crate) fn send_ipi(hart_mask: HartMask) -> SbiRet {
  39. if let Some(ipi) = IPI.get() {
  40. return ipi.send_ipi(hart_mask);
  41. }
  42. SbiRet::not_supported()
  43. }