xref: /DragonOS/kernel/src/arch/riscv64/time.rs (revision 2eab6dd743e94a86a685f1f3c01e599adf86610a)
1 use log::{debug, info};
2 
3 use crate::{
4     driver::open_firmware::fdt::open_firmware_fdt_driver,
5     time::{clocksource::HZ, TimeArch},
6 };
7 pub struct RiscV64TimeArch;
8 
9 /// 这个是系统jiffies时钟源的固有频率(不是调频之后的)
10 pub const CLOCK_TICK_RATE: u32 = HZ as u32 * 1000000;
11 
12 static mut TIME_FREQ: usize = 0;
13 
14 /// 获取CPU的time寄存器频率
15 ///
16 /// todo: 支持从acpi中获取
init_time_freq()17 fn init_time_freq() {
18     debug!("init_time_freq: init");
19     let fdt = open_firmware_fdt_driver().fdt_ref();
20     if fdt.is_err() {
21         panic!("init_time_freq: failed to get fdt");
22     }
23     debug!("init_time_freq: get fdt");
24     let fdt = fdt.unwrap();
25     let cpu_node = fdt.find_node("/cpus");
26     if cpu_node.is_none() {
27         panic!("init_time_freq: failed to find /cpus node");
28     }
29 
30     let cpu_node = cpu_node.unwrap();
31     let time_freq = cpu_node
32         .property("timebase-frequency")
33         .map(|prop| prop.as_usize())
34         .flatten();
35     if time_freq.is_none() {
36         panic!("init_time_freq: failed to get timebase-frequency");
37     }
38 
39     let time_freq: usize = time_freq.unwrap();
40     info!("init_time_freq: timebase-frequency: {}", time_freq);
41     unsafe {
42         TIME_FREQ = time_freq;
43     }
44 }
45 
time_init()46 pub fn time_init() {
47     // 初始化cpu time register频率
48     init_time_freq();
49 }
50 
51 impl TimeArch for RiscV64TimeArch {
get_cycles() -> usize52     fn get_cycles() -> usize {
53         riscv::register::time::read()
54     }
55 
cal_expire_cycles(ns: usize) -> usize56     fn cal_expire_cycles(ns: usize) -> usize {
57         Self::get_cycles() + ns * unsafe { TIME_FREQ } / 1000000000
58     }
59 
60     /// 将CPU的时钟周期数转换为纳秒
61     #[inline(always)]
cycles2ns(cycles: usize) -> usize62     fn cycles2ns(cycles: usize) -> usize {
63         if unsafe { TIME_FREQ == 0 } {
64             return 0;
65         }
66 
67         cycles * 1000000000 / unsafe { TIME_FREQ }
68     }
69 }
70 
riscv_time_base_freq() -> usize71 pub fn riscv_time_base_freq() -> usize {
72     unsafe { TIME_FREQ }
73 }
74