xref: /qemu/rust/qemu-api/src/timer.rs (revision eadb83f9a3722045e291b6a73994004007dc4657)
1*eadb83f9SZhao Liu // Copyright (C) 2024 Intel Corporation.
2*eadb83f9SZhao Liu // Author(s): Zhao Liu <zhai1.liu@intel.com>
3*eadb83f9SZhao Liu // SPDX-License-Identifier: GPL-2.0-or-later
4*eadb83f9SZhao Liu 
5*eadb83f9SZhao Liu use std::os::raw::{c_int, c_void};
6*eadb83f9SZhao Liu 
7*eadb83f9SZhao Liu use crate::{
8*eadb83f9SZhao Liu     bindings::{self, qemu_clock_get_ns, timer_del, timer_init_full, timer_mod, QEMUClockType},
9*eadb83f9SZhao Liu     callbacks::FnCall,
10*eadb83f9SZhao Liu };
11*eadb83f9SZhao Liu 
12*eadb83f9SZhao Liu pub type Timer = bindings::QEMUTimer;
13*eadb83f9SZhao Liu pub type TimerListGroup = bindings::QEMUTimerListGroup;
14*eadb83f9SZhao Liu 
15*eadb83f9SZhao Liu impl Timer {
16*eadb83f9SZhao Liu     pub const MS: u32 = bindings::SCALE_MS;
17*eadb83f9SZhao Liu     pub const US: u32 = bindings::SCALE_US;
18*eadb83f9SZhao Liu     pub const NS: u32 = bindings::SCALE_NS;
19*eadb83f9SZhao Liu 
20*eadb83f9SZhao Liu     pub fn new() -> Self {
21*eadb83f9SZhao Liu         Default::default()
22*eadb83f9SZhao Liu     }
23*eadb83f9SZhao Liu 
24*eadb83f9SZhao Liu     const fn as_mut_ptr(&self) -> *mut Self {
25*eadb83f9SZhao Liu         self as *const Timer as *mut _
26*eadb83f9SZhao Liu     }
27*eadb83f9SZhao Liu 
28*eadb83f9SZhao Liu     pub fn init_full<'timer, 'opaque: 'timer, T, F>(
29*eadb83f9SZhao Liu         &'timer mut self,
30*eadb83f9SZhao Liu         timer_list_group: Option<&TimerListGroup>,
31*eadb83f9SZhao Liu         clk_type: ClockType,
32*eadb83f9SZhao Liu         scale: u32,
33*eadb83f9SZhao Liu         attributes: u32,
34*eadb83f9SZhao Liu         _cb: F,
35*eadb83f9SZhao Liu         opaque: &'opaque T,
36*eadb83f9SZhao Liu     ) where
37*eadb83f9SZhao Liu         F: for<'a> FnCall<(&'a T,)>,
38*eadb83f9SZhao Liu     {
39*eadb83f9SZhao Liu         let _: () = F::ASSERT_IS_SOME;
40*eadb83f9SZhao Liu 
41*eadb83f9SZhao Liu         /// timer expiration callback
42*eadb83f9SZhao Liu         unsafe extern "C" fn rust_timer_handler<T, F: for<'a> FnCall<(&'a T,)>>(
43*eadb83f9SZhao Liu             opaque: *mut c_void,
44*eadb83f9SZhao Liu         ) {
45*eadb83f9SZhao Liu             // SAFETY: the opaque was passed as a reference to `T`.
46*eadb83f9SZhao Liu             F::call((unsafe { &*(opaque.cast::<T>()) },))
47*eadb83f9SZhao Liu         }
48*eadb83f9SZhao Liu 
49*eadb83f9SZhao Liu         let timer_cb: unsafe extern "C" fn(*mut c_void) = rust_timer_handler::<T, F>;
50*eadb83f9SZhao Liu 
51*eadb83f9SZhao Liu         // SAFETY: the opaque outlives the timer
52*eadb83f9SZhao Liu         unsafe {
53*eadb83f9SZhao Liu             timer_init_full(
54*eadb83f9SZhao Liu                 self,
55*eadb83f9SZhao Liu                 if let Some(g) = timer_list_group {
56*eadb83f9SZhao Liu                     g as *const TimerListGroup as *mut _
57*eadb83f9SZhao Liu                 } else {
58*eadb83f9SZhao Liu                     ::core::ptr::null_mut()
59*eadb83f9SZhao Liu                 },
60*eadb83f9SZhao Liu                 clk_type.id,
61*eadb83f9SZhao Liu                 scale as c_int,
62*eadb83f9SZhao Liu                 attributes as c_int,
63*eadb83f9SZhao Liu                 Some(timer_cb),
64*eadb83f9SZhao Liu                 (opaque as *const T).cast::<c_void>() as *mut c_void,
65*eadb83f9SZhao Liu             )
66*eadb83f9SZhao Liu         }
67*eadb83f9SZhao Liu     }
68*eadb83f9SZhao Liu 
69*eadb83f9SZhao Liu     pub fn modify(&self, expire_time: u64) {
70*eadb83f9SZhao Liu         unsafe { timer_mod(self.as_mut_ptr(), expire_time as i64) }
71*eadb83f9SZhao Liu     }
72*eadb83f9SZhao Liu 
73*eadb83f9SZhao Liu     pub fn delete(&self) {
74*eadb83f9SZhao Liu         unsafe { timer_del(self.as_mut_ptr()) }
75*eadb83f9SZhao Liu     }
76*eadb83f9SZhao Liu }
77*eadb83f9SZhao Liu 
78*eadb83f9SZhao Liu impl Drop for Timer {
79*eadb83f9SZhao Liu     fn drop(&mut self) {
80*eadb83f9SZhao Liu         self.delete()
81*eadb83f9SZhao Liu     }
82*eadb83f9SZhao Liu }
83*eadb83f9SZhao Liu 
84*eadb83f9SZhao Liu pub struct ClockType {
85*eadb83f9SZhao Liu     id: QEMUClockType,
86*eadb83f9SZhao Liu }
87*eadb83f9SZhao Liu 
88*eadb83f9SZhao Liu impl ClockType {
89*eadb83f9SZhao Liu     pub fn get_ns(&self) -> u64 {
90*eadb83f9SZhao Liu         // SAFETY: cannot be created outside this module, therefore id
91*eadb83f9SZhao Liu         // is valid
92*eadb83f9SZhao Liu         (unsafe { qemu_clock_get_ns(self.id) }) as u64
93*eadb83f9SZhao Liu     }
94*eadb83f9SZhao Liu }
95*eadb83f9SZhao Liu 
96*eadb83f9SZhao Liu pub const CLOCK_VIRTUAL: ClockType = ClockType {
97*eadb83f9SZhao Liu     id: QEMUClockType::QEMU_CLOCK_VIRTUAL,
98*eadb83f9SZhao Liu };
99