clint.rs 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. use super::super::config::platform::virt::*;
  2. use core::ptr;
  3. use sbi::{
  4. ipi::send_ipi,
  5. timer::set_timer,
  6. HartMask,
  7. SbiError
  8. };
  9. use riscv::register::mie;
  10. /// CLINT (Core Local Interruptor) driver
  11. /// This struct now owns the base address and hart_id.
  12. pub struct ClintDriver {
  13. base_addr: usize,
  14. hart_id: usize,
  15. }
  16. impl ClintDriver {
  17. pub fn new(base_addr: usize, hart_id: usize) -> Self {
  18. let driver = ClintDriver { base_addr, hart_id };
  19. driver.clear_soft_interrupt_pending(hart_id);
  20. // Enable Supervisor-mode Software Interrupts (SSIE)
  21. // and Supervisor-mode Timer Interrupts (STIE) in the `mie` CSR.
  22. unsafe {
  23. mie::set_ssoft(); // Enable S-mode Software Interrupts
  24. mie::set_stimer(); // Enable S-mode Timer Interrupts
  25. }
  26. driver
  27. }
  28. /// Reads the current value of the global MTIME (Machine Timer) counter.
  29. pub fn get_time(&self) -> u64 {
  30. unsafe {
  31. // MTIME is a 64-bit counter at CLINT_BASE + CLINT_MTIME_OFFSET
  32. ptr::read_volatile((self.base_addr + CLINT_MTIME_OFFSET) as *mut u64)
  33. }
  34. }
  35. /// Sets the next timer interrupt trigger point using SBI.
  36. pub fn set_timer(&self, time_value: u64) -> Result<(), SbiError> {
  37. set_timer(time_value)
  38. }
  39. /// Sends an Inter-Processor Interrupt (IPI) to the specified Hart(s).
  40. pub fn send_ipi(&self, hart_id_mask: usize) -> Result<(), SbiError> {
  41. // This utilizes the SBI `send_ipi` call.
  42. send_ipi(HartMask::from(hart_id_mask))
  43. }
  44. /// Clears the software interrupt pending bit for the specified Hart.
  45. pub fn clear_soft_interrupt_pending(&self, hart_id: usize) {
  46. unsafe {
  47. // MSIP registers are typically located at CLINT_BASE + 4 * hart_id.
  48. // Writing 0 to the register clears the pending bit.
  49. ptr::write_volatile((self.base_addr + CLINT_MSIP_OFFSET + hart_id * 4) as *mut u32, 0);
  50. }
  51. }
  52. }