4
0

spi.rs 1.7 KB

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