clint.rs 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. use aclint::SifiveClint;
  2. use core::{
  3. ptr::null_mut,
  4. sync::atomic::{
  5. AtomicPtr,
  6. Ordering::{Relaxed, Release},
  7. },
  8. };
  9. use rustsbi::SbiRet;
  10. use crate::riscv_spec::{stimecmp,current_hartid};
  11. use crate::hsm::remote_hsm;
  12. pub(crate) static SIFIVECLINT: AtomicPtr<SifiveClint> = AtomicPtr::new(null_mut());
  13. pub(crate) fn init(base: usize) {
  14. SIFIVECLINT.store(base as _, Release);
  15. }
  16. #[inline]
  17. pub fn clear() {
  18. let hart_id = current_hartid();
  19. loop {
  20. if let Some(clint) = unsafe { SIFIVECLINT.load(Relaxed).as_ref() } {
  21. clint.clear_msip(hart_id);
  22. clint.write_mtimecmp(hart_id, u64::MAX);
  23. break;
  24. } else {
  25. continue;
  26. }
  27. }
  28. }
  29. #[inline]
  30. pub fn clear_msip() {
  31. loop {
  32. if let Some(clint) = unsafe { SIFIVECLINT.load(Relaxed).as_ref() } {
  33. clint.clear_msip(current_hartid());
  34. break;
  35. } else {
  36. continue;
  37. }
  38. }
  39. }
  40. #[inline]
  41. pub fn set_msip(hart_id: usize) {
  42. loop {
  43. if let Some(clint) = unsafe { SIFIVECLINT.load(Relaxed).as_ref() } {
  44. clint.set_msip(hart_id);
  45. break;
  46. } else {
  47. continue;
  48. }
  49. }
  50. }
  51. pub struct ClintDevice<'a> {
  52. pub clint: &'a AtomicPtr<SifiveClint>,
  53. pub max_hart_id: usize,
  54. }
  55. impl<'a> ClintDevice<'a> {
  56. pub fn new(clint: &'a AtomicPtr<SifiveClint>, max_hart_id: usize) -> Self {
  57. Self { clint, max_hart_id }
  58. }
  59. }
  60. impl<'a> ClintDevice<'a> {
  61. #[inline]
  62. pub fn get_time(&self) -> usize {
  63. unsafe { (*self.clint.load(Relaxed)).read_mtime() as u32 as usize }
  64. }
  65. #[inline]
  66. pub fn get_timeh(&self) -> usize {
  67. unsafe { ((*self.clint.load(Relaxed)).read_mtime() >> 32) as usize }
  68. }
  69. }
  70. impl<'a> rustsbi::Timer for ClintDevice<'a> {
  71. #[inline]
  72. fn set_timer(&self, stime_value: u64) {
  73. unsafe {
  74. // TODO: 添加CPU拓展探测机制,补充无Sstc拓展时的定时器设置
  75. stimecmp::set(stime_value);
  76. riscv::register::mie::set_mtimer();
  77. // (*self.clint.load(Relaxed)).write_mtimecmp(current_hart_id, stime_value);
  78. }
  79. }
  80. }
  81. impl<'a> rustsbi::Ipi for ClintDevice<'a> {
  82. #[inline]
  83. fn send_ipi(&self, hart_mask: rustsbi::HartMask) -> SbiRet {
  84. for hart_id in 0..=self.max_hart_id {
  85. if hart_mask.has_bit(hart_id) && remote_hsm(hart_id).unwrap().allow_ipi() {
  86. unsafe {
  87. (*self.clint.load(Relaxed)).set_msip(hart_id);
  88. }
  89. }
  90. }
  91. SbiRet::success(0)
  92. }
  93. }