spi.rs 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. //! Inter-processor interrupt extension test suite.
  2. use crate::thread::Thread;
  3. use riscv::register::{
  4. scause::Interrupt,
  5. scause::{self, Trap},
  6. sie,
  7. };
  8. use sbi::HartMask;
  9. /// Inter-processor Interrupt extension test cases.
  10. #[derive(Clone, Debug)]
  11. pub enum Case {
  12. /// Can't procceed test for inter-processor interrupt extension does not exist.
  13. NotExist,
  14. /// Test begin.
  15. Begin,
  16. /// Test process for an inter-processor interrupt has been received.
  17. SendIpi,
  18. /// Test failed for unexpected trap occurred upon tests.
  19. UnexpectedTrap(Trap),
  20. /// All test cases on inter-processor interrupt extension has passed.
  21. Pass,
  22. }
  23. /// Test inter-processor interrupt extension.
  24. pub fn test(hart_id: usize, mut f: impl FnMut(Case)) {
  25. if sbi::probe_extension(sbi::Timer).is_unavailable() {
  26. f(Case::NotExist);
  27. return;
  28. }
  29. fn ipi(hart_id: usize) -> ! {
  30. sbi::send_ipi(HartMask::from_mask_base(1 << hart_id, 0));
  31. // 必须立即触发中断,即使是一个指令的延迟,也会触发另一个异常
  32. unsafe { core::arch::asm!("unimp", options(noreturn, nomem)) };
  33. }
  34. f(Case::Begin);
  35. let mut stack = [0usize; 32];
  36. let mut thread = Thread::new(ipi as _);
  37. *thread.sp_mut() = stack.as_mut_ptr_range().end as _;
  38. *thread.a_mut(0) = hart_id;
  39. unsafe {
  40. sie::set_ssoft();
  41. thread.execute();
  42. }
  43. match scause::read().cause() {
  44. Trap::Interrupt(Interrupt::SupervisorSoft) => {
  45. f(Case::SendIpi);
  46. f(Case::Pass);
  47. }
  48. trap => {
  49. f(Case::UnexpectedTrap(trap));
  50. }
  51. }
  52. }