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