time.rs 2.8 KB

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