time.rs 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. //! Timer programmer extension test suite.
  2. use crate::thread::Thread;
  3. use riscv::register::scause::{self, Trap};
  4. /// Timer programmer extension test cases.
  5. #[derive(Clone, Debug)]
  6. pub enum Case {
  7. /// Can't procceed test for Timer extension does not exist.
  8. NotExist,
  9. /// Test begin.
  10. Begin,
  11. /// Test process for time interval overhead between two reads.
  12. Interval {
  13. /// The time counter value for the first read.
  14. begin: u64,
  15. /// The time counter value for the second read.
  16. end: u64,
  17. },
  18. /// Test failed for can't read `time` register.
  19. ReadFailed,
  20. /// Test failed for time counter has decreased during period of two reads.
  21. TimeDecreased {
  22. /// The time counter value for the first read.
  23. a: u64,
  24. /// The time counter value for the second read.
  25. b: u64,
  26. },
  27. /// Test process for timer has been set.
  28. SetTimer,
  29. /// Test failed for unexpected trap during timer test.
  30. UnexpectedTrap(Trap),
  31. /// All test cases on timer extension has passed.
  32. Pass,
  33. }
  34. /// Test timer extension.
  35. pub fn test(delay: u64, mut f: impl FnMut(Case)) {
  36. use riscv::register::{scause::Interrupt, sie, time};
  37. if sbi::probe_extension(sbi::Timer).is_unavailable() {
  38. f(Case::NotExist);
  39. return;
  40. }
  41. f(Case::Begin);
  42. let begin: u64;
  43. let end: u64;
  44. let mut ok = 0xffusize;
  45. unsafe {
  46. core::arch::asm!(
  47. " la {stvec}, 1f
  48. csrw stvec, {stvec}
  49. csrr {begin}, time
  50. csrr {end}, time
  51. mv {ok}, zero
  52. .align 2
  53. 1:
  54. ",
  55. stvec = out(reg) _,
  56. begin = out(reg) begin,
  57. end = out(reg) end,
  58. ok = inlateout(reg) ok,
  59. );
  60. }
  61. if ok != 0 {
  62. f(Case::ReadFailed);
  63. return;
  64. }
  65. if begin >= end {
  66. f(Case::TimeDecreased { a: begin, b: end });
  67. return;
  68. }
  69. f(Case::Interval { begin, end });
  70. let mut stack = [0usize; 32];
  71. let mut thread = Thread::new(riscv::asm::wfi as _);
  72. *thread.sp_mut() = stack.as_mut_ptr_range().end as _;
  73. sbi::set_timer(time::read64() + delay);
  74. unsafe {
  75. sie::set_stimer();
  76. thread.execute();
  77. }
  78. match scause::read().cause() {
  79. Trap::Interrupt(Interrupt::SupervisorTimer) => {
  80. sbi::set_timer(u64::MAX);
  81. f(Case::SetTimer);
  82. f(Case::Pass);
  83. }
  84. trap => {
  85. f(Case::UnexpectedTrap(trap));
  86. }
  87. }
  88. }