xref: /DragonOS/kernel/src/driver/clocksource/timer_riscv.rs (revision bde4a334c1ff2ae27989de4f6f8b45f5154b684d)
1 use core::sync::atomic::{compiler_fence, fence, Ordering};
2 
3 use alloc::{string::ToString, sync::Arc};
4 use bitmap::{traits::BitMapOps, StaticBitmap};
5 use system_error::SystemError;
6 
7 use crate::{
8     arch::{interrupt::TrapFrame, time::riscv_time_base_freq, CurrentIrqArch, CurrentTimeArch},
9     driver::base::device::DeviceId,
10     exception::{
11         irqdata::{IrqHandlerData, IrqLineStatus},
12         irqdesc::{
13             irq_desc_manager, IrqDesc, IrqFlowHandler, IrqHandleFlags, IrqHandler, IrqReturn,
14         },
15         manage::irq_manager,
16         InterruptArch, IrqNumber,
17     },
18     libs::spinlock::SpinLock,
19     mm::percpu::PerCpu,
20     process::ProcessManager,
21     smp::core::smp_get_processor_id,
22     time::{
23         clocksource::HZ,
24         jiffies::NSEC_PER_JIFFY,
25         timer::{try_raise_timer_softirq, update_timer_jiffies},
26         TimeArch,
27     },
28 };
29 
30 pub struct RiscVSbiTimer;
31 
32 static SBI_TIMER_INIT_BMP: SpinLock<StaticBitmap<{ PerCpu::MAX_CPU_NUM as usize }>> =
33     SpinLock::new(StaticBitmap::new());
34 
35 static mut INTERVAL_CNT: usize = 0;
36 
37 /// 已经过去的纳秒数
38 ///
39 /// 0号核心用这个值来更新墙上时钟,他只能被0号核心访问
40 static mut HART0_NSEC_PASSED: usize = 0;
41 /// hart0上一次更新墙上时钟的时间
42 static mut HART0_LAST_UPDATED: u64 = 0;
43 
44 impl RiscVSbiTimer {
45     pub const TIMER_IRQ: IrqNumber = IrqNumber::from(5);
46 
47     fn handle_irq(trap_frame: &mut TrapFrame) -> Result<(), SystemError> {
48         // 更新下一次中断时间
49         // kdebug!(
50         //     "riscv_sbi_timer: handle_irq: cpu_id: {}, time: {}",
51         //     smp_get_processor_id().data(),
52         //     CurrentTimeArch::get_cycles() as u64
53         // );
54         ProcessManager::update_process_times(trap_frame.is_from_user());
55         Self::update_nsec_passed_and_walltime();
56         sbi_rt::set_timer(CurrentTimeArch::get_cycles() as u64 + unsafe { INTERVAL_CNT } as u64);
57         Ok(())
58     }
59 
60     fn enable() {
61         unsafe { riscv::register::sie::set_stimer() };
62     }
63 
64     #[allow(dead_code)]
65     fn disable() {
66         unsafe { riscv::register::sie::clear_stimer() };
67     }
68 
69     fn update_nsec_passed_and_walltime() {
70         if smp_get_processor_id().data() != 0 {
71             return;
72         }
73 
74         let cycles = CurrentTimeArch::get_cycles() as u64;
75         let nsec_passed =
76             CurrentTimeArch::cycles2ns((cycles - unsafe { HART0_LAST_UPDATED }) as usize);
77         unsafe {
78             HART0_LAST_UPDATED = cycles;
79             HART0_NSEC_PASSED += nsec_passed;
80         }
81 
82         let jiffies = unsafe { HART0_NSEC_PASSED } / NSEC_PER_JIFFY as usize;
83         unsafe { HART0_NSEC_PASSED %= NSEC_PER_JIFFY as usize };
84 
85         update_timer_jiffies(
86             jiffies as u64,
87             (jiffies * NSEC_PER_JIFFY as usize / 1000) as i64,
88         );
89         try_raise_timer_softirq();
90         compiler_fence(Ordering::SeqCst);
91     }
92 }
93 
94 /// riscv 初始化本地调度时钟源
95 #[inline(never)]
96 pub fn riscv_sbi_timer_init_local() {
97     assert_eq!(CurrentIrqArch::is_irq_enabled(), false);
98 
99     if unsafe { INTERVAL_CNT } == 0 {
100         let new = riscv_time_base_freq() / HZ as usize;
101         if new == 0 {
102             panic!("riscv_sbi_timer_init: failed to get timebase-frequency");
103         }
104         unsafe {
105             INTERVAL_CNT = new;
106         }
107     }
108 
109     let mut guard = SBI_TIMER_INIT_BMP.lock();
110     // 如果已经初始化过了,直接返回。或者cpu id不存在
111     if guard
112         .get(smp_get_processor_id().data() as usize)
113         .unwrap_or(true)
114     {
115         return;
116     }
117 
118     irq_manager()
119         .request_irq(
120             RiscVSbiTimer::TIMER_IRQ,
121             "riscv_clocksource".to_string(),
122             &RiscvSbiTimerHandler,
123             IrqHandleFlags::IRQF_SHARED | IrqHandleFlags::IRQF_PERCPU,
124             Some(DeviceId::new(Some("riscv sbi timer"), None).unwrap()),
125         )
126         .expect("Apic timer init failed");
127 
128     // 设置第一次中断
129     sbi_rt::set_timer(CurrentTimeArch::get_cycles() as u64);
130 
131     RiscVSbiTimer::enable();
132     guard
133         .set(smp_get_processor_id().data() as usize, true)
134         .unwrap();
135 }
136 
137 #[inline(never)]
138 pub fn riscv_sbi_timer_irq_desc_init() {
139     let desc = irq_desc_manager().lookup(RiscVSbiTimer::TIMER_IRQ).unwrap();
140 
141     desc.modify_status(IrqLineStatus::IRQ_LEVEL, IrqLineStatus::empty());
142     desc.set_handler(&RiscvSbiTimerIrqFlowHandler);
143 }
144 
145 #[derive(Debug)]
146 struct RiscvSbiTimerHandler;
147 
148 impl IrqHandler for RiscvSbiTimerHandler {
149     fn handle(
150         &self,
151         _irq: IrqNumber,
152         _static_data: Option<&dyn IrqHandlerData>,
153         _dynamic_data: Option<Arc<dyn IrqHandlerData>>,
154     ) -> Result<IrqReturn, SystemError> {
155         // empty (只是为了让编译通过,不会被调用到。真正的处理函数在 RiscvSbiTimerIrqFlowHandler 中)
156         Ok(IrqReturn::NotHandled)
157     }
158 }
159 
160 #[derive(Debug)]
161 struct RiscvSbiTimerIrqFlowHandler;
162 
163 impl IrqFlowHandler for RiscvSbiTimerIrqFlowHandler {
164     fn handle(&self, _irq_desc: &Arc<IrqDesc>, trap_frame: &mut TrapFrame) {
165         RiscVSbiTimer::handle_irq(trap_frame).unwrap();
166         fence(Ordering::SeqCst)
167     }
168 }
169