xref: /DragonOS/kernel/src/driver/clocksource/timer_riscv.rs (revision 9fab312ea9921618629924ab15c28c2d255b21c6)
1 use core::sync::atomic::{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::TimeArch,
23 };
24 
25 pub struct RiscVSbiTimer;
26 
27 static SBI_TIMER_INIT_BMP: SpinLock<StaticBitmap<{ PerCpu::MAX_CPU_NUM as usize }>> =
28     SpinLock::new(StaticBitmap::new());
29 
30 static mut INTERVAL_CNT: usize = 0;
31 
32 impl RiscVSbiTimer {
33     pub const TIMER_IRQ: IrqNumber = IrqNumber::from(5);
34 
35     fn handle_irq(trap_frame: &mut TrapFrame) -> Result<(), SystemError> {
36         // 更新下一次中断时间
37         kdebug!(
38             "riscv_sbi_timer: handle_irq: cpu_id: {}, time: {}",
39             smp_get_processor_id().data(),
40             CurrentTimeArch::get_cycles() as u64
41         );
42         sbi_rt::set_timer(CurrentTimeArch::get_cycles() as u64 + unsafe { INTERVAL_CNT } as u64);
43         ProcessManager::update_process_times(trap_frame.is_from_user());
44         Ok(())
45     }
46 
47     fn enable() {
48         unsafe { riscv::register::sie::set_stimer() };
49     }
50 
51     fn disable() {
52         unsafe { riscv::register::sie::clear_stimer() };
53     }
54 }
55 
56 /// riscv 初始化本地调度时钟源
57 #[inline(never)]
58 pub fn riscv_sbi_timer_init_local() {
59     assert_eq!(CurrentIrqArch::is_irq_enabled(), false);
60 
61     if unsafe { INTERVAL_CNT } == 0 {
62         // todo: 将来正式实现时,需要除以HZ
63         let new = riscv_time_base_freq();
64         if new == 0 {
65             panic!("riscv_sbi_timer_init: failed to get timebase-frequency");
66         }
67         unsafe {
68             INTERVAL_CNT = new;
69         }
70     }
71 
72     let mut guard = SBI_TIMER_INIT_BMP.lock();
73     // 如果已经初始化过了,直接返回。或者cpu id不存在
74     if guard
75         .get(smp_get_processor_id().data() as usize)
76         .unwrap_or(true)
77     {
78         return;
79     }
80 
81     irq_manager()
82         .request_irq(
83             RiscVSbiTimer::TIMER_IRQ,
84             "riscv_clocksource".to_string(),
85             &RiscvSbiTimerHandler,
86             IrqHandleFlags::IRQF_SHARED | IrqHandleFlags::IRQF_PERCPU,
87             Some(DeviceId::new(Some("riscv sbi timer"), None).unwrap()),
88         )
89         .expect("Apic timer init failed");
90 
91     // 设置第一次中断
92     sbi_rt::set_timer(CurrentTimeArch::get_cycles() as u64);
93 
94     RiscVSbiTimer::enable();
95     guard
96         .set(smp_get_processor_id().data() as usize, true)
97         .unwrap();
98 }
99 
100 #[inline(never)]
101 pub fn riscv_sbi_timer_irq_desc_init() {
102     let desc = irq_desc_manager().lookup(RiscVSbiTimer::TIMER_IRQ).unwrap();
103 
104     desc.modify_status(IrqLineStatus::IRQ_LEVEL, IrqLineStatus::empty());
105     desc.set_handler(&RiscvSbiTimerIrqFlowHandler);
106 }
107 
108 #[derive(Debug)]
109 struct RiscvSbiTimerHandler;
110 
111 impl IrqHandler for RiscvSbiTimerHandler {
112     fn handle(
113         &self,
114         _irq: IrqNumber,
115         _static_data: Option<&dyn IrqHandlerData>,
116         _dynamic_data: Option<Arc<dyn IrqHandlerData>>,
117     ) -> Result<IrqReturn, SystemError> {
118         // empty (只是为了让编译通过,不会被调用到。真正的处理函数在 RiscvSbiTimerIrqFlowHandler 中)
119         Ok(IrqReturn::NotHandled)
120     }
121 }
122 
123 #[derive(Debug)]
124 struct RiscvSbiTimerIrqFlowHandler;
125 
126 impl IrqFlowHandler for RiscvSbiTimerIrqFlowHandler {
127     fn handle(&self, _irq_desc: &Arc<IrqDesc>, trap_frame: &mut TrapFrame) {
128         RiscVSbiTimer::handle_irq(trap_frame).unwrap();
129         fence(Ordering::SeqCst)
130     }
131 }
132