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