1*734a1e9eSPaolo Bonzini // Copyright (C) 2024 Intel Corporation. 2*734a1e9eSPaolo Bonzini // Author(s): Zhao Liu <zhao1.liu@intel.com> 3*734a1e9eSPaolo Bonzini // SPDX-License-Identifier: GPL-2.0-or-later 4*734a1e9eSPaolo Bonzini 5*734a1e9eSPaolo Bonzini use std::{ 6*734a1e9eSPaolo Bonzini ffi::{c_int, c_void, CStr}, 7*734a1e9eSPaolo Bonzini pin::Pin, 8*734a1e9eSPaolo Bonzini ptr::{addr_of_mut, null_mut, NonNull}, 9*734a1e9eSPaolo Bonzini slice::from_ref, 10*734a1e9eSPaolo Bonzini }; 11*734a1e9eSPaolo Bonzini 12*734a1e9eSPaolo Bonzini use qemu_api::{ 13*734a1e9eSPaolo Bonzini bindings::{ 14*734a1e9eSPaolo Bonzini address_space_memory, address_space_stl_le, qdev_prop_bit, qdev_prop_bool, 15*734a1e9eSPaolo Bonzini qdev_prop_uint32, qdev_prop_uint8, 16*734a1e9eSPaolo Bonzini }, 17*734a1e9eSPaolo Bonzini cell::{BqlCell, BqlRefCell}, 18*734a1e9eSPaolo Bonzini irq::InterruptSource, 19*734a1e9eSPaolo Bonzini memory::{ 20*734a1e9eSPaolo Bonzini hwaddr, MemoryRegion, MemoryRegionOps, MemoryRegionOpsBuilder, MEMTXATTRS_UNSPECIFIED, 21*734a1e9eSPaolo Bonzini }, 22*734a1e9eSPaolo Bonzini prelude::*, 23*734a1e9eSPaolo Bonzini qdev::{DeviceImpl, DeviceMethods, DeviceState, Property, ResetType, ResettablePhasesImpl}, 24*734a1e9eSPaolo Bonzini qom::{ObjectImpl, ObjectType, ParentField}, 25*734a1e9eSPaolo Bonzini qom_isa, 26*734a1e9eSPaolo Bonzini sysbus::{SysBusDevice, SysBusDeviceImpl}, 27*734a1e9eSPaolo Bonzini timer::{Timer, CLOCK_VIRTUAL, NANOSECONDS_PER_SECOND}, 28*734a1e9eSPaolo Bonzini vmstate::VMStateDescription, 29*734a1e9eSPaolo Bonzini vmstate_fields, vmstate_of, vmstate_struct, vmstate_subsections, vmstate_validate, 30*734a1e9eSPaolo Bonzini zeroable::Zeroable, 31*734a1e9eSPaolo Bonzini }; 32*734a1e9eSPaolo Bonzini 33*734a1e9eSPaolo Bonzini use crate::fw_cfg::HPETFwConfig; 34*734a1e9eSPaolo Bonzini 35*734a1e9eSPaolo Bonzini /// Register space for each timer block (`HPET_BASE` is defined in hpet.h). 36*734a1e9eSPaolo Bonzini const HPET_REG_SPACE_LEN: u64 = 0x400; // 1024 bytes 37*734a1e9eSPaolo Bonzini 38*734a1e9eSPaolo Bonzini /// Minimum recommended hardware implementation. 39*734a1e9eSPaolo Bonzini const HPET_MIN_TIMERS: u8 = 3; 40*734a1e9eSPaolo Bonzini /// Maximum timers in each timer block. 41*734a1e9eSPaolo Bonzini const HPET_MAX_TIMERS: u8 = 32; 42*734a1e9eSPaolo Bonzini 43*734a1e9eSPaolo Bonzini /// Flags that HPETState.flags supports. 44*734a1e9eSPaolo Bonzini const HPET_FLAG_MSI_SUPPORT_SHIFT: usize = 0; 45*734a1e9eSPaolo Bonzini 46*734a1e9eSPaolo Bonzini const HPET_NUM_IRQ_ROUTES: usize = 32; 47*734a1e9eSPaolo Bonzini const HPET_LEGACY_PIT_INT: u32 = 0; // HPET_LEGACY_RTC_INT isn't defined here. 48*734a1e9eSPaolo Bonzini const RTC_ISA_IRQ: usize = 8; 49*734a1e9eSPaolo Bonzini 50*734a1e9eSPaolo Bonzini const HPET_CLK_PERIOD: u64 = 10; // 10 ns 51*734a1e9eSPaolo Bonzini const FS_PER_NS: u64 = 1000000; // 1000000 femtoseconds == 1 ns 52*734a1e9eSPaolo Bonzini 53*734a1e9eSPaolo Bonzini /// Revision ID (bits 0:7). Revision 1 is implemented (refer to v1.0a spec). 54*734a1e9eSPaolo Bonzini const HPET_CAP_REV_ID_VALUE: u64 = 0x1; 55*734a1e9eSPaolo Bonzini const HPET_CAP_REV_ID_SHIFT: usize = 0; 56*734a1e9eSPaolo Bonzini /// Number of Timers (bits 8:12) 57*734a1e9eSPaolo Bonzini const HPET_CAP_NUM_TIM_SHIFT: usize = 8; 58*734a1e9eSPaolo Bonzini /// Counter Size (bit 13) 59*734a1e9eSPaolo Bonzini const HPET_CAP_COUNT_SIZE_CAP_SHIFT: usize = 13; 60*734a1e9eSPaolo Bonzini /// Legacy Replacement Route Capable (bit 15) 61*734a1e9eSPaolo Bonzini const HPET_CAP_LEG_RT_CAP_SHIFT: usize = 15; 62*734a1e9eSPaolo Bonzini /// Vendor ID (bits 16:31) 63*734a1e9eSPaolo Bonzini const HPET_CAP_VENDER_ID_VALUE: u64 = 0x8086; 64*734a1e9eSPaolo Bonzini const HPET_CAP_VENDER_ID_SHIFT: usize = 16; 65*734a1e9eSPaolo Bonzini /// Main Counter Tick Period (bits 32:63) 66*734a1e9eSPaolo Bonzini const HPET_CAP_CNT_CLK_PERIOD_SHIFT: usize = 32; 67*734a1e9eSPaolo Bonzini 68*734a1e9eSPaolo Bonzini /// Overall Enable (bit 0) 69*734a1e9eSPaolo Bonzini const HPET_CFG_ENABLE_SHIFT: usize = 0; 70*734a1e9eSPaolo Bonzini /// Legacy Replacement Route (bit 1) 71*734a1e9eSPaolo Bonzini const HPET_CFG_LEG_RT_SHIFT: usize = 1; 72*734a1e9eSPaolo Bonzini /// Other bits are reserved. 73*734a1e9eSPaolo Bonzini const HPET_CFG_WRITE_MASK: u64 = 0x003; 74*734a1e9eSPaolo Bonzini 75*734a1e9eSPaolo Bonzini /// bit 0, 7, and bits 16:31 are reserved. 76*734a1e9eSPaolo Bonzini /// bit 4, 5, 15, and bits 32:64 are read-only. 77*734a1e9eSPaolo Bonzini const HPET_TN_CFG_WRITE_MASK: u64 = 0x7f4e; 78*734a1e9eSPaolo Bonzini /// Timer N Interrupt Type (bit 1) 79*734a1e9eSPaolo Bonzini const HPET_TN_CFG_INT_TYPE_SHIFT: usize = 1; 80*734a1e9eSPaolo Bonzini /// Timer N Interrupt Enable (bit 2) 81*734a1e9eSPaolo Bonzini const HPET_TN_CFG_INT_ENABLE_SHIFT: usize = 2; 82*734a1e9eSPaolo Bonzini /// Timer N Type (Periodic enabled or not, bit 3) 83*734a1e9eSPaolo Bonzini const HPET_TN_CFG_PERIODIC_SHIFT: usize = 3; 84*734a1e9eSPaolo Bonzini /// Timer N Periodic Interrupt Capable (support Periodic or not, bit 4) 85*734a1e9eSPaolo Bonzini const HPET_TN_CFG_PERIODIC_CAP_SHIFT: usize = 4; 86*734a1e9eSPaolo Bonzini /// Timer N Size (timer size is 64-bits or 32 bits, bit 5) 87*734a1e9eSPaolo Bonzini const HPET_TN_CFG_SIZE_CAP_SHIFT: usize = 5; 88*734a1e9eSPaolo Bonzini /// Timer N Value Set (bit 6) 89*734a1e9eSPaolo Bonzini const HPET_TN_CFG_SETVAL_SHIFT: usize = 6; 90*734a1e9eSPaolo Bonzini /// Timer N 32-bit Mode (bit 8) 91*734a1e9eSPaolo Bonzini const HPET_TN_CFG_32BIT_SHIFT: usize = 8; 92*734a1e9eSPaolo Bonzini /// Timer N Interrupt Rout (bits 9:13) 93*734a1e9eSPaolo Bonzini const HPET_TN_CFG_INT_ROUTE_MASK: u64 = 0x3e00; 94*734a1e9eSPaolo Bonzini const HPET_TN_CFG_INT_ROUTE_SHIFT: usize = 9; 95*734a1e9eSPaolo Bonzini /// Timer N FSB Interrupt Enable (bit 14) 96*734a1e9eSPaolo Bonzini const HPET_TN_CFG_FSB_ENABLE_SHIFT: usize = 14; 97*734a1e9eSPaolo Bonzini /// Timer N FSB Interrupt Delivery (bit 15) 98*734a1e9eSPaolo Bonzini const HPET_TN_CFG_FSB_CAP_SHIFT: usize = 15; 99*734a1e9eSPaolo Bonzini /// Timer N Interrupt Routing Capability (bits 32:63) 100*734a1e9eSPaolo Bonzini const HPET_TN_CFG_INT_ROUTE_CAP_SHIFT: usize = 32; 101*734a1e9eSPaolo Bonzini 102*734a1e9eSPaolo Bonzini #[derive(qemu_api_macros::TryInto)] 103*734a1e9eSPaolo Bonzini #[repr(u64)] 104*734a1e9eSPaolo Bonzini #[allow(non_camel_case_types)] 105*734a1e9eSPaolo Bonzini /// Timer registers, masked by 0x18 106*734a1e9eSPaolo Bonzini enum TimerRegister { 107*734a1e9eSPaolo Bonzini /// Timer N Configuration and Capability Register 108*734a1e9eSPaolo Bonzini CFG = 0, 109*734a1e9eSPaolo Bonzini /// Timer N Comparator Value Register 110*734a1e9eSPaolo Bonzini CMP = 8, 111*734a1e9eSPaolo Bonzini /// Timer N FSB Interrupt Route Register 112*734a1e9eSPaolo Bonzini ROUTE = 16, 113*734a1e9eSPaolo Bonzini } 114*734a1e9eSPaolo Bonzini 115*734a1e9eSPaolo Bonzini #[derive(qemu_api_macros::TryInto)] 116*734a1e9eSPaolo Bonzini #[repr(u64)] 117*734a1e9eSPaolo Bonzini #[allow(non_camel_case_types)] 118*734a1e9eSPaolo Bonzini /// Global registers 119*734a1e9eSPaolo Bonzini enum GlobalRegister { 120*734a1e9eSPaolo Bonzini /// General Capabilities and ID Register 121*734a1e9eSPaolo Bonzini CAP = 0, 122*734a1e9eSPaolo Bonzini /// General Configuration Register 123*734a1e9eSPaolo Bonzini CFG = 0x10, 124*734a1e9eSPaolo Bonzini /// General Interrupt Status Register 125*734a1e9eSPaolo Bonzini INT_STATUS = 0x20, 126*734a1e9eSPaolo Bonzini /// Main Counter Value Register 127*734a1e9eSPaolo Bonzini COUNTER = 0xF0, 128*734a1e9eSPaolo Bonzini } 129*734a1e9eSPaolo Bonzini 130*734a1e9eSPaolo Bonzini enum HPETRegister<'a> { 131*734a1e9eSPaolo Bonzini /// Global register in the range from `0` to `0xff` 132*734a1e9eSPaolo Bonzini Global(GlobalRegister), 133*734a1e9eSPaolo Bonzini 134*734a1e9eSPaolo Bonzini /// Register in the timer block `0x100`...`0x3ff` 135*734a1e9eSPaolo Bonzini Timer(&'a BqlRefCell<HPETTimer>, TimerRegister), 136*734a1e9eSPaolo Bonzini 137*734a1e9eSPaolo Bonzini /// Invalid address 138*734a1e9eSPaolo Bonzini #[allow(dead_code)] 139*734a1e9eSPaolo Bonzini Unknown(hwaddr), 140*734a1e9eSPaolo Bonzini } 141*734a1e9eSPaolo Bonzini 142*734a1e9eSPaolo Bonzini struct HPETAddrDecode<'a> { 143*734a1e9eSPaolo Bonzini shift: u32, 144*734a1e9eSPaolo Bonzini len: u32, 145*734a1e9eSPaolo Bonzini reg: HPETRegister<'a>, 146*734a1e9eSPaolo Bonzini } 147*734a1e9eSPaolo Bonzini 148*734a1e9eSPaolo Bonzini const fn hpet_next_wrap(cur_tick: u64) -> u64 { 149*734a1e9eSPaolo Bonzini (cur_tick | 0xffffffff) + 1 150*734a1e9eSPaolo Bonzini } 151*734a1e9eSPaolo Bonzini 152*734a1e9eSPaolo Bonzini const fn hpet_time_after(a: u64, b: u64) -> bool { 153*734a1e9eSPaolo Bonzini ((b - a) as i64) < 0 154*734a1e9eSPaolo Bonzini } 155*734a1e9eSPaolo Bonzini 156*734a1e9eSPaolo Bonzini const fn ticks_to_ns(value: u64) -> u64 { 157*734a1e9eSPaolo Bonzini value * HPET_CLK_PERIOD 158*734a1e9eSPaolo Bonzini } 159*734a1e9eSPaolo Bonzini 160*734a1e9eSPaolo Bonzini const fn ns_to_ticks(value: u64) -> u64 { 161*734a1e9eSPaolo Bonzini value / HPET_CLK_PERIOD 162*734a1e9eSPaolo Bonzini } 163*734a1e9eSPaolo Bonzini 164*734a1e9eSPaolo Bonzini // Avoid touching the bits that cannot be written. 165*734a1e9eSPaolo Bonzini const fn hpet_fixup_reg(new: u64, old: u64, mask: u64) -> u64 { 166*734a1e9eSPaolo Bonzini (new & mask) | (old & !mask) 167*734a1e9eSPaolo Bonzini } 168*734a1e9eSPaolo Bonzini 169*734a1e9eSPaolo Bonzini const fn activating_bit(old: u64, new: u64, shift: usize) -> bool { 170*734a1e9eSPaolo Bonzini let mask: u64 = 1 << shift; 171*734a1e9eSPaolo Bonzini (old & mask == 0) && (new & mask != 0) 172*734a1e9eSPaolo Bonzini } 173*734a1e9eSPaolo Bonzini 174*734a1e9eSPaolo Bonzini const fn deactivating_bit(old: u64, new: u64, shift: usize) -> bool { 175*734a1e9eSPaolo Bonzini let mask: u64 = 1 << shift; 176*734a1e9eSPaolo Bonzini (old & mask != 0) && (new & mask == 0) 177*734a1e9eSPaolo Bonzini } 178*734a1e9eSPaolo Bonzini 179*734a1e9eSPaolo Bonzini fn timer_handler(timer_cell: &BqlRefCell<HPETTimer>) { 180*734a1e9eSPaolo Bonzini timer_cell.borrow_mut().callback() 181*734a1e9eSPaolo Bonzini } 182*734a1e9eSPaolo Bonzini 183*734a1e9eSPaolo Bonzini /// HPET Timer Abstraction 184*734a1e9eSPaolo Bonzini #[repr(C)] 185*734a1e9eSPaolo Bonzini #[derive(Debug)] 186*734a1e9eSPaolo Bonzini pub struct HPETTimer { 187*734a1e9eSPaolo Bonzini /// timer N index within the timer block (`HPETState`) 188*734a1e9eSPaolo Bonzini #[doc(alias = "tn")] 189*734a1e9eSPaolo Bonzini index: u8, 190*734a1e9eSPaolo Bonzini qemu_timer: Timer, 191*734a1e9eSPaolo Bonzini /// timer block abstraction containing this timer 192*734a1e9eSPaolo Bonzini state: NonNull<HPETState>, 193*734a1e9eSPaolo Bonzini 194*734a1e9eSPaolo Bonzini // Memory-mapped, software visible timer registers 195*734a1e9eSPaolo Bonzini /// Timer N Configuration and Capability Register 196*734a1e9eSPaolo Bonzini config: u64, 197*734a1e9eSPaolo Bonzini /// Timer N Comparator Value Register 198*734a1e9eSPaolo Bonzini cmp: u64, 199*734a1e9eSPaolo Bonzini /// Timer N FSB Interrupt Route Register 200*734a1e9eSPaolo Bonzini fsb: u64, 201*734a1e9eSPaolo Bonzini 202*734a1e9eSPaolo Bonzini // Hidden register state 203*734a1e9eSPaolo Bonzini /// comparator (extended to counter width) 204*734a1e9eSPaolo Bonzini cmp64: u64, 205*734a1e9eSPaolo Bonzini /// Last value written to comparator 206*734a1e9eSPaolo Bonzini period: u64, 207*734a1e9eSPaolo Bonzini /// timer pop will indicate wrap for one-shot 32-bit 208*734a1e9eSPaolo Bonzini /// mode. Next pop will be actual timer expiration. 209*734a1e9eSPaolo Bonzini wrap_flag: u8, 210*734a1e9eSPaolo Bonzini /// last value armed, to avoid timer storms 211*734a1e9eSPaolo Bonzini last: u64, 212*734a1e9eSPaolo Bonzini } 213*734a1e9eSPaolo Bonzini 214*734a1e9eSPaolo Bonzini impl HPETTimer { 215*734a1e9eSPaolo Bonzini fn init(&mut self, index: u8, state: &HPETState) { 216*734a1e9eSPaolo Bonzini *self = HPETTimer { 217*734a1e9eSPaolo Bonzini index, 218*734a1e9eSPaolo Bonzini // SAFETY: the HPETTimer will only be used after the timer 219*734a1e9eSPaolo Bonzini // is initialized below. 220*734a1e9eSPaolo Bonzini qemu_timer: unsafe { Timer::new() }, 221*734a1e9eSPaolo Bonzini state: NonNull::new((state as *const HPETState).cast_mut()).unwrap(), 222*734a1e9eSPaolo Bonzini config: 0, 223*734a1e9eSPaolo Bonzini cmp: 0, 224*734a1e9eSPaolo Bonzini fsb: 0, 225*734a1e9eSPaolo Bonzini cmp64: 0, 226*734a1e9eSPaolo Bonzini period: 0, 227*734a1e9eSPaolo Bonzini wrap_flag: 0, 228*734a1e9eSPaolo Bonzini last: 0, 229*734a1e9eSPaolo Bonzini }; 230*734a1e9eSPaolo Bonzini 231*734a1e9eSPaolo Bonzini // SAFETY: HPETTimer is only used as part of HPETState, which is 232*734a1e9eSPaolo Bonzini // always pinned. 233*734a1e9eSPaolo Bonzini let qemu_timer = unsafe { Pin::new_unchecked(&mut self.qemu_timer) }; 234*734a1e9eSPaolo Bonzini qemu_timer.init_full( 235*734a1e9eSPaolo Bonzini None, 236*734a1e9eSPaolo Bonzini CLOCK_VIRTUAL, 237*734a1e9eSPaolo Bonzini Timer::NS, 238*734a1e9eSPaolo Bonzini 0, 239*734a1e9eSPaolo Bonzini timer_handler, 240*734a1e9eSPaolo Bonzini &state.timers[self.index as usize], 241*734a1e9eSPaolo Bonzini ) 242*734a1e9eSPaolo Bonzini } 243*734a1e9eSPaolo Bonzini 244*734a1e9eSPaolo Bonzini fn get_state(&self) -> &HPETState { 245*734a1e9eSPaolo Bonzini // SAFETY: 246*734a1e9eSPaolo Bonzini // the pointer is convertible to a reference 247*734a1e9eSPaolo Bonzini unsafe { self.state.as_ref() } 248*734a1e9eSPaolo Bonzini } 249*734a1e9eSPaolo Bonzini 250*734a1e9eSPaolo Bonzini fn is_int_active(&self) -> bool { 251*734a1e9eSPaolo Bonzini self.get_state().is_timer_int_active(self.index.into()) 252*734a1e9eSPaolo Bonzini } 253*734a1e9eSPaolo Bonzini 254*734a1e9eSPaolo Bonzini const fn is_fsb_route_enabled(&self) -> bool { 255*734a1e9eSPaolo Bonzini self.config & (1 << HPET_TN_CFG_FSB_ENABLE_SHIFT) != 0 256*734a1e9eSPaolo Bonzini } 257*734a1e9eSPaolo Bonzini 258*734a1e9eSPaolo Bonzini const fn is_periodic(&self) -> bool { 259*734a1e9eSPaolo Bonzini self.config & (1 << HPET_TN_CFG_PERIODIC_SHIFT) != 0 260*734a1e9eSPaolo Bonzini } 261*734a1e9eSPaolo Bonzini 262*734a1e9eSPaolo Bonzini const fn is_int_enabled(&self) -> bool { 263*734a1e9eSPaolo Bonzini self.config & (1 << HPET_TN_CFG_INT_ENABLE_SHIFT) != 0 264*734a1e9eSPaolo Bonzini } 265*734a1e9eSPaolo Bonzini 266*734a1e9eSPaolo Bonzini const fn is_32bit_mod(&self) -> bool { 267*734a1e9eSPaolo Bonzini self.config & (1 << HPET_TN_CFG_32BIT_SHIFT) != 0 268*734a1e9eSPaolo Bonzini } 269*734a1e9eSPaolo Bonzini 270*734a1e9eSPaolo Bonzini const fn is_valset_enabled(&self) -> bool { 271*734a1e9eSPaolo Bonzini self.config & (1 << HPET_TN_CFG_SETVAL_SHIFT) != 0 272*734a1e9eSPaolo Bonzini } 273*734a1e9eSPaolo Bonzini 274*734a1e9eSPaolo Bonzini fn clear_valset(&mut self) { 275*734a1e9eSPaolo Bonzini self.config &= !(1 << HPET_TN_CFG_SETVAL_SHIFT); 276*734a1e9eSPaolo Bonzini } 277*734a1e9eSPaolo Bonzini 278*734a1e9eSPaolo Bonzini /// True if timer interrupt is level triggered; otherwise, edge triggered. 279*734a1e9eSPaolo Bonzini const fn is_int_level_triggered(&self) -> bool { 280*734a1e9eSPaolo Bonzini self.config & (1 << HPET_TN_CFG_INT_TYPE_SHIFT) != 0 281*734a1e9eSPaolo Bonzini } 282*734a1e9eSPaolo Bonzini 283*734a1e9eSPaolo Bonzini /// calculate next value of the general counter that matches the 284*734a1e9eSPaolo Bonzini /// target (either entirely, or the low 32-bit only depending on 285*734a1e9eSPaolo Bonzini /// the timer mode). 286*734a1e9eSPaolo Bonzini fn calculate_cmp64(&self, cur_tick: u64, target: u64) -> u64 { 287*734a1e9eSPaolo Bonzini if self.is_32bit_mod() { 288*734a1e9eSPaolo Bonzini let mut result: u64 = cur_tick.deposit(0, 32, target); 289*734a1e9eSPaolo Bonzini if result < cur_tick { 290*734a1e9eSPaolo Bonzini result += 0x100000000; 291*734a1e9eSPaolo Bonzini } 292*734a1e9eSPaolo Bonzini result 293*734a1e9eSPaolo Bonzini } else { 294*734a1e9eSPaolo Bonzini target 295*734a1e9eSPaolo Bonzini } 296*734a1e9eSPaolo Bonzini } 297*734a1e9eSPaolo Bonzini 298*734a1e9eSPaolo Bonzini const fn get_individual_route(&self) -> usize { 299*734a1e9eSPaolo Bonzini ((self.config & HPET_TN_CFG_INT_ROUTE_MASK) >> HPET_TN_CFG_INT_ROUTE_SHIFT) as usize 300*734a1e9eSPaolo Bonzini } 301*734a1e9eSPaolo Bonzini 302*734a1e9eSPaolo Bonzini fn get_int_route(&self) -> usize { 303*734a1e9eSPaolo Bonzini if self.index <= 1 && self.get_state().is_legacy_mode() { 304*734a1e9eSPaolo Bonzini // If LegacyReplacement Route bit is set, HPET specification requires 305*734a1e9eSPaolo Bonzini // timer0 be routed to IRQ0 in NON-APIC or IRQ2 in the I/O APIC, 306*734a1e9eSPaolo Bonzini // timer1 be routed to IRQ8 in NON-APIC or IRQ8 in the I/O APIC. 307*734a1e9eSPaolo Bonzini // 308*734a1e9eSPaolo Bonzini // If the LegacyReplacement Route bit is set, the individual routing 309*734a1e9eSPaolo Bonzini // bits for timers 0 and 1 (APIC or FSB) will have no impact. 310*734a1e9eSPaolo Bonzini // 311*734a1e9eSPaolo Bonzini // FIXME: Consider I/O APIC case. 312*734a1e9eSPaolo Bonzini if self.index == 0 { 313*734a1e9eSPaolo Bonzini 0 314*734a1e9eSPaolo Bonzini } else { 315*734a1e9eSPaolo Bonzini RTC_ISA_IRQ 316*734a1e9eSPaolo Bonzini } 317*734a1e9eSPaolo Bonzini } else { 318*734a1e9eSPaolo Bonzini // (If the LegacyReplacement Route bit is set) Timer 2-n will be 319*734a1e9eSPaolo Bonzini // routed as per the routing in the timer n config registers. 320*734a1e9eSPaolo Bonzini // ... 321*734a1e9eSPaolo Bonzini // If the LegacyReplacement Route bit is not set, the individual 322*734a1e9eSPaolo Bonzini // routing bits for each of the timers are used. 323*734a1e9eSPaolo Bonzini self.get_individual_route() 324*734a1e9eSPaolo Bonzini } 325*734a1e9eSPaolo Bonzini } 326*734a1e9eSPaolo Bonzini 327*734a1e9eSPaolo Bonzini fn set_irq(&mut self, set: bool) { 328*734a1e9eSPaolo Bonzini let route = self.get_int_route(); 329*734a1e9eSPaolo Bonzini 330*734a1e9eSPaolo Bonzini if set && self.is_int_enabled() && self.get_state().is_hpet_enabled() { 331*734a1e9eSPaolo Bonzini if self.is_fsb_route_enabled() { 332*734a1e9eSPaolo Bonzini // SAFETY: 333*734a1e9eSPaolo Bonzini // the parameters are valid. 334*734a1e9eSPaolo Bonzini unsafe { 335*734a1e9eSPaolo Bonzini address_space_stl_le( 336*734a1e9eSPaolo Bonzini addr_of_mut!(address_space_memory), 337*734a1e9eSPaolo Bonzini self.fsb >> 32, // Timer N FSB int addr 338*734a1e9eSPaolo Bonzini self.fsb as u32, // Timer N FSB int value, truncate! 339*734a1e9eSPaolo Bonzini MEMTXATTRS_UNSPECIFIED, 340*734a1e9eSPaolo Bonzini null_mut(), 341*734a1e9eSPaolo Bonzini ); 342*734a1e9eSPaolo Bonzini } 343*734a1e9eSPaolo Bonzini } else if self.is_int_level_triggered() { 344*734a1e9eSPaolo Bonzini self.get_state().irqs[route].raise(); 345*734a1e9eSPaolo Bonzini } else { 346*734a1e9eSPaolo Bonzini self.get_state().irqs[route].pulse(); 347*734a1e9eSPaolo Bonzini } 348*734a1e9eSPaolo Bonzini } else if !self.is_fsb_route_enabled() { 349*734a1e9eSPaolo Bonzini self.get_state().irqs[route].lower(); 350*734a1e9eSPaolo Bonzini } 351*734a1e9eSPaolo Bonzini } 352*734a1e9eSPaolo Bonzini 353*734a1e9eSPaolo Bonzini fn update_irq(&mut self, set: bool) { 354*734a1e9eSPaolo Bonzini // If Timer N Interrupt Enable bit is 0, "the timer will 355*734a1e9eSPaolo Bonzini // still operate and generate appropriate status bits, but 356*734a1e9eSPaolo Bonzini // will not cause an interrupt" 357*734a1e9eSPaolo Bonzini self.get_state() 358*734a1e9eSPaolo Bonzini .update_int_status(self.index.into(), set && self.is_int_level_triggered()); 359*734a1e9eSPaolo Bonzini self.set_irq(set); 360*734a1e9eSPaolo Bonzini } 361*734a1e9eSPaolo Bonzini 362*734a1e9eSPaolo Bonzini fn arm_timer(&mut self, tick: u64) { 363*734a1e9eSPaolo Bonzini let mut ns = self.get_state().get_ns(tick); 364*734a1e9eSPaolo Bonzini 365*734a1e9eSPaolo Bonzini // Clamp period to reasonable min value (1 us) 366*734a1e9eSPaolo Bonzini if self.is_periodic() && ns - self.last < 1000 { 367*734a1e9eSPaolo Bonzini ns = self.last + 1000; 368*734a1e9eSPaolo Bonzini } 369*734a1e9eSPaolo Bonzini 370*734a1e9eSPaolo Bonzini self.last = ns; 371*734a1e9eSPaolo Bonzini self.qemu_timer.modify(self.last); 372*734a1e9eSPaolo Bonzini } 373*734a1e9eSPaolo Bonzini 374*734a1e9eSPaolo Bonzini fn set_timer(&mut self) { 375*734a1e9eSPaolo Bonzini let cur_tick: u64 = self.get_state().get_ticks(); 376*734a1e9eSPaolo Bonzini 377*734a1e9eSPaolo Bonzini self.wrap_flag = 0; 378*734a1e9eSPaolo Bonzini self.cmp64 = self.calculate_cmp64(cur_tick, self.cmp); 379*734a1e9eSPaolo Bonzini if self.is_32bit_mod() { 380*734a1e9eSPaolo Bonzini // HPET spec says in one-shot 32-bit mode, generate an interrupt when 381*734a1e9eSPaolo Bonzini // counter wraps in addition to an interrupt with comparator match. 382*734a1e9eSPaolo Bonzini if !self.is_periodic() && self.cmp64 > hpet_next_wrap(cur_tick) { 383*734a1e9eSPaolo Bonzini self.wrap_flag = 1; 384*734a1e9eSPaolo Bonzini self.arm_timer(hpet_next_wrap(cur_tick)); 385*734a1e9eSPaolo Bonzini return; 386*734a1e9eSPaolo Bonzini } 387*734a1e9eSPaolo Bonzini } 388*734a1e9eSPaolo Bonzini self.arm_timer(self.cmp64); 389*734a1e9eSPaolo Bonzini } 390*734a1e9eSPaolo Bonzini 391*734a1e9eSPaolo Bonzini fn del_timer(&mut self) { 392*734a1e9eSPaolo Bonzini // Just remove the timer from the timer_list without destroying 393*734a1e9eSPaolo Bonzini // this timer instance. 394*734a1e9eSPaolo Bonzini self.qemu_timer.delete(); 395*734a1e9eSPaolo Bonzini 396*734a1e9eSPaolo Bonzini if self.is_int_active() { 397*734a1e9eSPaolo Bonzini // For level-triggered interrupt, this leaves interrupt status 398*734a1e9eSPaolo Bonzini // register set but lowers irq. 399*734a1e9eSPaolo Bonzini self.update_irq(true); 400*734a1e9eSPaolo Bonzini } 401*734a1e9eSPaolo Bonzini } 402*734a1e9eSPaolo Bonzini 403*734a1e9eSPaolo Bonzini /// Configuration and Capability Register 404*734a1e9eSPaolo Bonzini fn set_tn_cfg_reg(&mut self, shift: u32, len: u32, val: u64) { 405*734a1e9eSPaolo Bonzini // TODO: Add trace point - trace_hpet_ram_write_tn_cfg(addr & 4) 406*734a1e9eSPaolo Bonzini let old_val: u64 = self.config; 407*734a1e9eSPaolo Bonzini let mut new_val: u64 = old_val.deposit(shift, len, val); 408*734a1e9eSPaolo Bonzini new_val = hpet_fixup_reg(new_val, old_val, HPET_TN_CFG_WRITE_MASK); 409*734a1e9eSPaolo Bonzini 410*734a1e9eSPaolo Bonzini // Switch level-type interrupt to edge-type. 411*734a1e9eSPaolo Bonzini if deactivating_bit(old_val, new_val, HPET_TN_CFG_INT_TYPE_SHIFT) { 412*734a1e9eSPaolo Bonzini // Do this before changing timer.config; otherwise, if 413*734a1e9eSPaolo Bonzini // HPET_TN_FSB is set, update_irq will not lower the qemu_irq. 414*734a1e9eSPaolo Bonzini self.update_irq(false); 415*734a1e9eSPaolo Bonzini } 416*734a1e9eSPaolo Bonzini 417*734a1e9eSPaolo Bonzini self.config = new_val; 418*734a1e9eSPaolo Bonzini 419*734a1e9eSPaolo Bonzini if activating_bit(old_val, new_val, HPET_TN_CFG_INT_ENABLE_SHIFT) && self.is_int_active() { 420*734a1e9eSPaolo Bonzini self.update_irq(true); 421*734a1e9eSPaolo Bonzini } 422*734a1e9eSPaolo Bonzini 423*734a1e9eSPaolo Bonzini if self.is_32bit_mod() { 424*734a1e9eSPaolo Bonzini self.cmp = u64::from(self.cmp as u32); // truncate! 425*734a1e9eSPaolo Bonzini self.period = u64::from(self.period as u32); // truncate! 426*734a1e9eSPaolo Bonzini } 427*734a1e9eSPaolo Bonzini 428*734a1e9eSPaolo Bonzini if self.get_state().is_hpet_enabled() { 429*734a1e9eSPaolo Bonzini self.set_timer(); 430*734a1e9eSPaolo Bonzini } 431*734a1e9eSPaolo Bonzini } 432*734a1e9eSPaolo Bonzini 433*734a1e9eSPaolo Bonzini /// Comparator Value Register 434*734a1e9eSPaolo Bonzini fn set_tn_cmp_reg(&mut self, shift: u32, len: u32, val: u64) { 435*734a1e9eSPaolo Bonzini let mut length = len; 436*734a1e9eSPaolo Bonzini let mut value = val; 437*734a1e9eSPaolo Bonzini 438*734a1e9eSPaolo Bonzini // TODO: Add trace point - trace_hpet_ram_write_tn_cmp(addr & 4) 439*734a1e9eSPaolo Bonzini if self.is_32bit_mod() { 440*734a1e9eSPaolo Bonzini // High 32-bits are zero, leave them untouched. 441*734a1e9eSPaolo Bonzini if shift != 0 { 442*734a1e9eSPaolo Bonzini // TODO: Add trace point - trace_hpet_ram_write_invalid_tn_cmp() 443*734a1e9eSPaolo Bonzini return; 444*734a1e9eSPaolo Bonzini } 445*734a1e9eSPaolo Bonzini length = 64; 446*734a1e9eSPaolo Bonzini value = u64::from(value as u32); // truncate! 447*734a1e9eSPaolo Bonzini } 448*734a1e9eSPaolo Bonzini 449*734a1e9eSPaolo Bonzini if !self.is_periodic() || self.is_valset_enabled() { 450*734a1e9eSPaolo Bonzini self.cmp = self.cmp.deposit(shift, length, value); 451*734a1e9eSPaolo Bonzini } 452*734a1e9eSPaolo Bonzini 453*734a1e9eSPaolo Bonzini if self.is_periodic() { 454*734a1e9eSPaolo Bonzini self.period = self.period.deposit(shift, length, value); 455*734a1e9eSPaolo Bonzini } 456*734a1e9eSPaolo Bonzini 457*734a1e9eSPaolo Bonzini self.clear_valset(); 458*734a1e9eSPaolo Bonzini if self.get_state().is_hpet_enabled() { 459*734a1e9eSPaolo Bonzini self.set_timer(); 460*734a1e9eSPaolo Bonzini } 461*734a1e9eSPaolo Bonzini } 462*734a1e9eSPaolo Bonzini 463*734a1e9eSPaolo Bonzini /// FSB Interrupt Route Register 464*734a1e9eSPaolo Bonzini fn set_tn_fsb_route_reg(&mut self, shift: u32, len: u32, val: u64) { 465*734a1e9eSPaolo Bonzini self.fsb = self.fsb.deposit(shift, len, val); 466*734a1e9eSPaolo Bonzini } 467*734a1e9eSPaolo Bonzini 468*734a1e9eSPaolo Bonzini fn reset(&mut self) { 469*734a1e9eSPaolo Bonzini self.del_timer(); 470*734a1e9eSPaolo Bonzini self.cmp = u64::MAX; // Comparator Match Registers reset to all 1's. 471*734a1e9eSPaolo Bonzini self.config = (1 << HPET_TN_CFG_PERIODIC_CAP_SHIFT) | (1 << HPET_TN_CFG_SIZE_CAP_SHIFT); 472*734a1e9eSPaolo Bonzini if self.get_state().has_msi_flag() { 473*734a1e9eSPaolo Bonzini self.config |= 1 << HPET_TN_CFG_FSB_CAP_SHIFT; 474*734a1e9eSPaolo Bonzini } 475*734a1e9eSPaolo Bonzini // advertise availability of ioapic int 476*734a1e9eSPaolo Bonzini self.config |= 477*734a1e9eSPaolo Bonzini (u64::from(self.get_state().int_route_cap)) << HPET_TN_CFG_INT_ROUTE_CAP_SHIFT; 478*734a1e9eSPaolo Bonzini self.period = 0; 479*734a1e9eSPaolo Bonzini self.wrap_flag = 0; 480*734a1e9eSPaolo Bonzini } 481*734a1e9eSPaolo Bonzini 482*734a1e9eSPaolo Bonzini /// timer expiration callback 483*734a1e9eSPaolo Bonzini fn callback(&mut self) { 484*734a1e9eSPaolo Bonzini let period: u64 = self.period; 485*734a1e9eSPaolo Bonzini let cur_tick: u64 = self.get_state().get_ticks(); 486*734a1e9eSPaolo Bonzini 487*734a1e9eSPaolo Bonzini if self.is_periodic() && period != 0 { 488*734a1e9eSPaolo Bonzini while hpet_time_after(cur_tick, self.cmp64) { 489*734a1e9eSPaolo Bonzini self.cmp64 += period; 490*734a1e9eSPaolo Bonzini } 491*734a1e9eSPaolo Bonzini if self.is_32bit_mod() { 492*734a1e9eSPaolo Bonzini self.cmp = u64::from(self.cmp64 as u32); // truncate! 493*734a1e9eSPaolo Bonzini } else { 494*734a1e9eSPaolo Bonzini self.cmp = self.cmp64; 495*734a1e9eSPaolo Bonzini } 496*734a1e9eSPaolo Bonzini self.arm_timer(self.cmp64); 497*734a1e9eSPaolo Bonzini } else if self.wrap_flag != 0 { 498*734a1e9eSPaolo Bonzini self.wrap_flag = 0; 499*734a1e9eSPaolo Bonzini self.arm_timer(self.cmp64); 500*734a1e9eSPaolo Bonzini } 501*734a1e9eSPaolo Bonzini self.update_irq(true); 502*734a1e9eSPaolo Bonzini } 503*734a1e9eSPaolo Bonzini 504*734a1e9eSPaolo Bonzini const fn read(&self, reg: TimerRegister) -> u64 { 505*734a1e9eSPaolo Bonzini use TimerRegister::*; 506*734a1e9eSPaolo Bonzini match reg { 507*734a1e9eSPaolo Bonzini CFG => self.config, // including interrupt capabilities 508*734a1e9eSPaolo Bonzini CMP => self.cmp, // comparator register 509*734a1e9eSPaolo Bonzini ROUTE => self.fsb, 510*734a1e9eSPaolo Bonzini } 511*734a1e9eSPaolo Bonzini } 512*734a1e9eSPaolo Bonzini 513*734a1e9eSPaolo Bonzini fn write(&mut self, reg: TimerRegister, value: u64, shift: u32, len: u32) { 514*734a1e9eSPaolo Bonzini use TimerRegister::*; 515*734a1e9eSPaolo Bonzini match reg { 516*734a1e9eSPaolo Bonzini CFG => self.set_tn_cfg_reg(shift, len, value), 517*734a1e9eSPaolo Bonzini CMP => self.set_tn_cmp_reg(shift, len, value), 518*734a1e9eSPaolo Bonzini ROUTE => self.set_tn_fsb_route_reg(shift, len, value), 519*734a1e9eSPaolo Bonzini } 520*734a1e9eSPaolo Bonzini } 521*734a1e9eSPaolo Bonzini } 522*734a1e9eSPaolo Bonzini 523*734a1e9eSPaolo Bonzini /// HPET Event Timer Block Abstraction 524*734a1e9eSPaolo Bonzini #[repr(C)] 525*734a1e9eSPaolo Bonzini #[derive(qemu_api_macros::Object)] 526*734a1e9eSPaolo Bonzini pub struct HPETState { 527*734a1e9eSPaolo Bonzini parent_obj: ParentField<SysBusDevice>, 528*734a1e9eSPaolo Bonzini iomem: MemoryRegion, 529*734a1e9eSPaolo Bonzini 530*734a1e9eSPaolo Bonzini // HPET block Registers: Memory-mapped, software visible registers 531*734a1e9eSPaolo Bonzini /// General Capabilities and ID Register 532*734a1e9eSPaolo Bonzini capability: BqlCell<u64>, 533*734a1e9eSPaolo Bonzini /// General Configuration Register 534*734a1e9eSPaolo Bonzini config: BqlCell<u64>, 535*734a1e9eSPaolo Bonzini /// General Interrupt Status Register 536*734a1e9eSPaolo Bonzini #[doc(alias = "isr")] 537*734a1e9eSPaolo Bonzini int_status: BqlCell<u64>, 538*734a1e9eSPaolo Bonzini /// Main Counter Value Register 539*734a1e9eSPaolo Bonzini #[doc(alias = "hpet_counter")] 540*734a1e9eSPaolo Bonzini counter: BqlCell<u64>, 541*734a1e9eSPaolo Bonzini 542*734a1e9eSPaolo Bonzini // Internal state 543*734a1e9eSPaolo Bonzini /// Capabilities that QEMU HPET supports. 544*734a1e9eSPaolo Bonzini /// bit 0: MSI (or FSB) support. 545*734a1e9eSPaolo Bonzini flags: u32, 546*734a1e9eSPaolo Bonzini 547*734a1e9eSPaolo Bonzini /// Offset of main counter relative to qemu clock. 548*734a1e9eSPaolo Bonzini hpet_offset: BqlCell<u64>, 549*734a1e9eSPaolo Bonzini hpet_offset_saved: bool, 550*734a1e9eSPaolo Bonzini 551*734a1e9eSPaolo Bonzini irqs: [InterruptSource; HPET_NUM_IRQ_ROUTES], 552*734a1e9eSPaolo Bonzini rtc_irq_level: BqlCell<u32>, 553*734a1e9eSPaolo Bonzini pit_enabled: InterruptSource, 554*734a1e9eSPaolo Bonzini 555*734a1e9eSPaolo Bonzini /// Interrupt Routing Capability. 556*734a1e9eSPaolo Bonzini /// This field indicates to which interrupts in the I/O (x) APIC 557*734a1e9eSPaolo Bonzini /// the timers' interrupt can be routed, and is encoded in the 558*734a1e9eSPaolo Bonzini /// bits 32:64 of timer N's config register: 559*734a1e9eSPaolo Bonzini #[doc(alias = "intcap")] 560*734a1e9eSPaolo Bonzini int_route_cap: u32, 561*734a1e9eSPaolo Bonzini 562*734a1e9eSPaolo Bonzini /// HPET timer array managed by this timer block. 563*734a1e9eSPaolo Bonzini #[doc(alias = "timer")] 564*734a1e9eSPaolo Bonzini timers: [BqlRefCell<HPETTimer>; HPET_MAX_TIMERS as usize], 565*734a1e9eSPaolo Bonzini num_timers: BqlCell<u8>, 566*734a1e9eSPaolo Bonzini num_timers_save: BqlCell<u8>, 567*734a1e9eSPaolo Bonzini 568*734a1e9eSPaolo Bonzini /// Instance id (HPET timer block ID). 569*734a1e9eSPaolo Bonzini hpet_id: BqlCell<usize>, 570*734a1e9eSPaolo Bonzini } 571*734a1e9eSPaolo Bonzini 572*734a1e9eSPaolo Bonzini impl HPETState { 573*734a1e9eSPaolo Bonzini // Get num_timers with `usize` type, which is useful to play with array index. 574*734a1e9eSPaolo Bonzini fn get_num_timers(&self) -> usize { 575*734a1e9eSPaolo Bonzini self.num_timers.get().into() 576*734a1e9eSPaolo Bonzini } 577*734a1e9eSPaolo Bonzini 578*734a1e9eSPaolo Bonzini const fn has_msi_flag(&self) -> bool { 579*734a1e9eSPaolo Bonzini self.flags & (1 << HPET_FLAG_MSI_SUPPORT_SHIFT) != 0 580*734a1e9eSPaolo Bonzini } 581*734a1e9eSPaolo Bonzini 582*734a1e9eSPaolo Bonzini fn is_legacy_mode(&self) -> bool { 583*734a1e9eSPaolo Bonzini self.config.get() & (1 << HPET_CFG_LEG_RT_SHIFT) != 0 584*734a1e9eSPaolo Bonzini } 585*734a1e9eSPaolo Bonzini 586*734a1e9eSPaolo Bonzini fn is_hpet_enabled(&self) -> bool { 587*734a1e9eSPaolo Bonzini self.config.get() & (1 << HPET_CFG_ENABLE_SHIFT) != 0 588*734a1e9eSPaolo Bonzini } 589*734a1e9eSPaolo Bonzini 590*734a1e9eSPaolo Bonzini fn is_timer_int_active(&self, index: usize) -> bool { 591*734a1e9eSPaolo Bonzini self.int_status.get() & (1 << index) != 0 592*734a1e9eSPaolo Bonzini } 593*734a1e9eSPaolo Bonzini 594*734a1e9eSPaolo Bonzini fn get_ticks(&self) -> u64 { 595*734a1e9eSPaolo Bonzini ns_to_ticks(CLOCK_VIRTUAL.get_ns() + self.hpet_offset.get()) 596*734a1e9eSPaolo Bonzini } 597*734a1e9eSPaolo Bonzini 598*734a1e9eSPaolo Bonzini fn get_ns(&self, tick: u64) -> u64 { 599*734a1e9eSPaolo Bonzini ticks_to_ns(tick) - self.hpet_offset.get() 600*734a1e9eSPaolo Bonzini } 601*734a1e9eSPaolo Bonzini 602*734a1e9eSPaolo Bonzini fn handle_legacy_irq(&self, irq: u32, level: u32) { 603*734a1e9eSPaolo Bonzini if irq == HPET_LEGACY_PIT_INT { 604*734a1e9eSPaolo Bonzini if !self.is_legacy_mode() { 605*734a1e9eSPaolo Bonzini self.irqs[0].set(level != 0); 606*734a1e9eSPaolo Bonzini } 607*734a1e9eSPaolo Bonzini } else { 608*734a1e9eSPaolo Bonzini self.rtc_irq_level.set(level); 609*734a1e9eSPaolo Bonzini if !self.is_legacy_mode() { 610*734a1e9eSPaolo Bonzini self.irqs[RTC_ISA_IRQ].set(level != 0); 611*734a1e9eSPaolo Bonzini } 612*734a1e9eSPaolo Bonzini } 613*734a1e9eSPaolo Bonzini } 614*734a1e9eSPaolo Bonzini 615*734a1e9eSPaolo Bonzini fn init_timer(&self) { 616*734a1e9eSPaolo Bonzini for (index, timer) in self.timers.iter().enumerate() { 617*734a1e9eSPaolo Bonzini timer.borrow_mut().init(index.try_into().unwrap(), self); 618*734a1e9eSPaolo Bonzini } 619*734a1e9eSPaolo Bonzini } 620*734a1e9eSPaolo Bonzini 621*734a1e9eSPaolo Bonzini fn update_int_status(&self, index: u32, level: bool) { 622*734a1e9eSPaolo Bonzini self.int_status 623*734a1e9eSPaolo Bonzini .set(self.int_status.get().deposit(index, 1, u64::from(level))); 624*734a1e9eSPaolo Bonzini } 625*734a1e9eSPaolo Bonzini 626*734a1e9eSPaolo Bonzini /// General Configuration Register 627*734a1e9eSPaolo Bonzini fn set_cfg_reg(&self, shift: u32, len: u32, val: u64) { 628*734a1e9eSPaolo Bonzini let old_val = self.config.get(); 629*734a1e9eSPaolo Bonzini let mut new_val = old_val.deposit(shift, len, val); 630*734a1e9eSPaolo Bonzini 631*734a1e9eSPaolo Bonzini new_val = hpet_fixup_reg(new_val, old_val, HPET_CFG_WRITE_MASK); 632*734a1e9eSPaolo Bonzini self.config.set(new_val); 633*734a1e9eSPaolo Bonzini 634*734a1e9eSPaolo Bonzini if activating_bit(old_val, new_val, HPET_CFG_ENABLE_SHIFT) { 635*734a1e9eSPaolo Bonzini // Enable main counter and interrupt generation. 636*734a1e9eSPaolo Bonzini self.hpet_offset 637*734a1e9eSPaolo Bonzini .set(ticks_to_ns(self.counter.get()) - CLOCK_VIRTUAL.get_ns()); 638*734a1e9eSPaolo Bonzini 639*734a1e9eSPaolo Bonzini for timer in self.timers.iter().take(self.get_num_timers()) { 640*734a1e9eSPaolo Bonzini let mut t = timer.borrow_mut(); 641*734a1e9eSPaolo Bonzini 642*734a1e9eSPaolo Bonzini if t.is_int_enabled() && t.is_int_active() { 643*734a1e9eSPaolo Bonzini t.update_irq(true); 644*734a1e9eSPaolo Bonzini } 645*734a1e9eSPaolo Bonzini t.set_timer(); 646*734a1e9eSPaolo Bonzini } 647*734a1e9eSPaolo Bonzini } else if deactivating_bit(old_val, new_val, HPET_CFG_ENABLE_SHIFT) { 648*734a1e9eSPaolo Bonzini // Halt main counter and disable interrupt generation. 649*734a1e9eSPaolo Bonzini self.counter.set(self.get_ticks()); 650*734a1e9eSPaolo Bonzini 651*734a1e9eSPaolo Bonzini for timer in self.timers.iter().take(self.get_num_timers()) { 652*734a1e9eSPaolo Bonzini timer.borrow_mut().del_timer(); 653*734a1e9eSPaolo Bonzini } 654*734a1e9eSPaolo Bonzini } 655*734a1e9eSPaolo Bonzini 656*734a1e9eSPaolo Bonzini // i8254 and RTC output pins are disabled when HPET is in legacy mode 657*734a1e9eSPaolo Bonzini if activating_bit(old_val, new_val, HPET_CFG_LEG_RT_SHIFT) { 658*734a1e9eSPaolo Bonzini self.pit_enabled.set(false); 659*734a1e9eSPaolo Bonzini self.irqs[0].lower(); 660*734a1e9eSPaolo Bonzini self.irqs[RTC_ISA_IRQ].lower(); 661*734a1e9eSPaolo Bonzini } else if deactivating_bit(old_val, new_val, HPET_CFG_LEG_RT_SHIFT) { 662*734a1e9eSPaolo Bonzini // TODO: Add irq binding: qemu_irq_lower(s->irqs[0]) 663*734a1e9eSPaolo Bonzini self.irqs[0].lower(); 664*734a1e9eSPaolo Bonzini self.pit_enabled.set(true); 665*734a1e9eSPaolo Bonzini self.irqs[RTC_ISA_IRQ].set(self.rtc_irq_level.get() != 0); 666*734a1e9eSPaolo Bonzini } 667*734a1e9eSPaolo Bonzini } 668*734a1e9eSPaolo Bonzini 669*734a1e9eSPaolo Bonzini /// General Interrupt Status Register: Read/Write Clear 670*734a1e9eSPaolo Bonzini fn set_int_status_reg(&self, shift: u32, _len: u32, val: u64) { 671*734a1e9eSPaolo Bonzini let new_val = val << shift; 672*734a1e9eSPaolo Bonzini let cleared = new_val & self.int_status.get(); 673*734a1e9eSPaolo Bonzini 674*734a1e9eSPaolo Bonzini for (index, timer) in self.timers.iter().take(self.get_num_timers()).enumerate() { 675*734a1e9eSPaolo Bonzini if cleared & (1 << index) != 0 { 676*734a1e9eSPaolo Bonzini timer.borrow_mut().update_irq(false); 677*734a1e9eSPaolo Bonzini } 678*734a1e9eSPaolo Bonzini } 679*734a1e9eSPaolo Bonzini } 680*734a1e9eSPaolo Bonzini 681*734a1e9eSPaolo Bonzini /// Main Counter Value Register 682*734a1e9eSPaolo Bonzini fn set_counter_reg(&self, shift: u32, len: u32, val: u64) { 683*734a1e9eSPaolo Bonzini if self.is_hpet_enabled() { 684*734a1e9eSPaolo Bonzini // TODO: Add trace point - 685*734a1e9eSPaolo Bonzini // trace_hpet_ram_write_counter_write_while_enabled() 686*734a1e9eSPaolo Bonzini // 687*734a1e9eSPaolo Bonzini // HPET spec says that writes to this register should only be 688*734a1e9eSPaolo Bonzini // done while the counter is halted. So this is an undefined 689*734a1e9eSPaolo Bonzini // behavior. There's no need to forbid it, but when HPET is 690*734a1e9eSPaolo Bonzini // enabled, the changed counter value will not affect the 691*734a1e9eSPaolo Bonzini // tick count (i.e., the previously calculated offset will 692*734a1e9eSPaolo Bonzini // not be changed as well). 693*734a1e9eSPaolo Bonzini } 694*734a1e9eSPaolo Bonzini self.counter 695*734a1e9eSPaolo Bonzini .set(self.counter.get().deposit(shift, len, val)); 696*734a1e9eSPaolo Bonzini } 697*734a1e9eSPaolo Bonzini 698*734a1e9eSPaolo Bonzini unsafe fn init(&mut self) { 699*734a1e9eSPaolo Bonzini static HPET_RAM_OPS: MemoryRegionOps<HPETState> = 700*734a1e9eSPaolo Bonzini MemoryRegionOpsBuilder::<HPETState>::new() 701*734a1e9eSPaolo Bonzini .read(&HPETState::read) 702*734a1e9eSPaolo Bonzini .write(&HPETState::write) 703*734a1e9eSPaolo Bonzini .native_endian() 704*734a1e9eSPaolo Bonzini .valid_sizes(4, 8) 705*734a1e9eSPaolo Bonzini .impl_sizes(4, 8) 706*734a1e9eSPaolo Bonzini .build(); 707*734a1e9eSPaolo Bonzini 708*734a1e9eSPaolo Bonzini // SAFETY: 709*734a1e9eSPaolo Bonzini // self and self.iomem are guaranteed to be valid at this point since callers 710*734a1e9eSPaolo Bonzini // must make sure the `self` reference is valid. 711*734a1e9eSPaolo Bonzini MemoryRegion::init_io( 712*734a1e9eSPaolo Bonzini unsafe { &mut *addr_of_mut!(self.iomem) }, 713*734a1e9eSPaolo Bonzini addr_of_mut!(*self), 714*734a1e9eSPaolo Bonzini &HPET_RAM_OPS, 715*734a1e9eSPaolo Bonzini "hpet", 716*734a1e9eSPaolo Bonzini HPET_REG_SPACE_LEN, 717*734a1e9eSPaolo Bonzini ); 718*734a1e9eSPaolo Bonzini } 719*734a1e9eSPaolo Bonzini 720*734a1e9eSPaolo Bonzini fn post_init(&self) { 721*734a1e9eSPaolo Bonzini self.init_mmio(&self.iomem); 722*734a1e9eSPaolo Bonzini for irq in self.irqs.iter() { 723*734a1e9eSPaolo Bonzini self.init_irq(irq); 724*734a1e9eSPaolo Bonzini } 725*734a1e9eSPaolo Bonzini } 726*734a1e9eSPaolo Bonzini 727*734a1e9eSPaolo Bonzini fn realize(&self) { 728*734a1e9eSPaolo Bonzini if self.int_route_cap == 0 { 729*734a1e9eSPaolo Bonzini // TODO: Add error binding: warn_report() 730*734a1e9eSPaolo Bonzini println!("Hpet's hpet-intcap property not initialized"); 731*734a1e9eSPaolo Bonzini } 732*734a1e9eSPaolo Bonzini 733*734a1e9eSPaolo Bonzini self.hpet_id.set(HPETFwConfig::assign_hpet_id()); 734*734a1e9eSPaolo Bonzini 735*734a1e9eSPaolo Bonzini if self.num_timers.get() < HPET_MIN_TIMERS { 736*734a1e9eSPaolo Bonzini self.num_timers.set(HPET_MIN_TIMERS); 737*734a1e9eSPaolo Bonzini } else if self.num_timers.get() > HPET_MAX_TIMERS { 738*734a1e9eSPaolo Bonzini self.num_timers.set(HPET_MAX_TIMERS); 739*734a1e9eSPaolo Bonzini } 740*734a1e9eSPaolo Bonzini 741*734a1e9eSPaolo Bonzini self.init_timer(); 742*734a1e9eSPaolo Bonzini // 64-bit General Capabilities and ID Register; LegacyReplacementRoute. 743*734a1e9eSPaolo Bonzini self.capability.set( 744*734a1e9eSPaolo Bonzini HPET_CAP_REV_ID_VALUE << HPET_CAP_REV_ID_SHIFT | 745*734a1e9eSPaolo Bonzini 1 << HPET_CAP_COUNT_SIZE_CAP_SHIFT | 746*734a1e9eSPaolo Bonzini 1 << HPET_CAP_LEG_RT_CAP_SHIFT | 747*734a1e9eSPaolo Bonzini HPET_CAP_VENDER_ID_VALUE << HPET_CAP_VENDER_ID_SHIFT | 748*734a1e9eSPaolo Bonzini ((self.get_num_timers() - 1) as u64) << HPET_CAP_NUM_TIM_SHIFT | // indicate the last timer 749*734a1e9eSPaolo Bonzini (HPET_CLK_PERIOD * FS_PER_NS) << HPET_CAP_CNT_CLK_PERIOD_SHIFT, // 10 ns 750*734a1e9eSPaolo Bonzini ); 751*734a1e9eSPaolo Bonzini 752*734a1e9eSPaolo Bonzini self.init_gpio_in(2, HPETState::handle_legacy_irq); 753*734a1e9eSPaolo Bonzini self.init_gpio_out(from_ref(&self.pit_enabled)); 754*734a1e9eSPaolo Bonzini } 755*734a1e9eSPaolo Bonzini 756*734a1e9eSPaolo Bonzini fn reset_hold(&self, _type: ResetType) { 757*734a1e9eSPaolo Bonzini for timer in self.timers.iter().take(self.get_num_timers()) { 758*734a1e9eSPaolo Bonzini timer.borrow_mut().reset(); 759*734a1e9eSPaolo Bonzini } 760*734a1e9eSPaolo Bonzini 761*734a1e9eSPaolo Bonzini self.counter.set(0); 762*734a1e9eSPaolo Bonzini self.config.set(0); 763*734a1e9eSPaolo Bonzini self.pit_enabled.set(true); 764*734a1e9eSPaolo Bonzini self.hpet_offset.set(0); 765*734a1e9eSPaolo Bonzini 766*734a1e9eSPaolo Bonzini HPETFwConfig::update_hpet_cfg( 767*734a1e9eSPaolo Bonzini self.hpet_id.get(), 768*734a1e9eSPaolo Bonzini self.capability.get() as u32, 769*734a1e9eSPaolo Bonzini self.mmio_addr(0).unwrap(), 770*734a1e9eSPaolo Bonzini ); 771*734a1e9eSPaolo Bonzini 772*734a1e9eSPaolo Bonzini // to document that the RTC lowers its output on reset as well 773*734a1e9eSPaolo Bonzini self.rtc_irq_level.set(0); 774*734a1e9eSPaolo Bonzini } 775*734a1e9eSPaolo Bonzini 776*734a1e9eSPaolo Bonzini fn decode(&self, mut addr: hwaddr, size: u32) -> HPETAddrDecode { 777*734a1e9eSPaolo Bonzini let shift = ((addr & 4) * 8) as u32; 778*734a1e9eSPaolo Bonzini let len = std::cmp::min(size * 8, 64 - shift); 779*734a1e9eSPaolo Bonzini 780*734a1e9eSPaolo Bonzini addr &= !4; 781*734a1e9eSPaolo Bonzini let reg = if (0..=0xff).contains(&addr) { 782*734a1e9eSPaolo Bonzini GlobalRegister::try_from(addr).map(HPETRegister::Global) 783*734a1e9eSPaolo Bonzini } else { 784*734a1e9eSPaolo Bonzini let timer_id: usize = ((addr - 0x100) / 0x20) as usize; 785*734a1e9eSPaolo Bonzini if timer_id <= self.get_num_timers() { 786*734a1e9eSPaolo Bonzini // TODO: Add trace point - trace_hpet_ram_[read|write]_timer_id(timer_id) 787*734a1e9eSPaolo Bonzini TimerRegister::try_from(addr & 0x18) 788*734a1e9eSPaolo Bonzini .map(|reg| HPETRegister::Timer(&self.timers[timer_id], reg)) 789*734a1e9eSPaolo Bonzini } else { 790*734a1e9eSPaolo Bonzini // TODO: Add trace point - trace_hpet_timer_id_out_of_range(timer_id) 791*734a1e9eSPaolo Bonzini Err(addr) 792*734a1e9eSPaolo Bonzini } 793*734a1e9eSPaolo Bonzini }; 794*734a1e9eSPaolo Bonzini 795*734a1e9eSPaolo Bonzini // reg is now a Result<HPETRegister, hwaddr> 796*734a1e9eSPaolo Bonzini // convert the Err case into HPETRegister as well 797*734a1e9eSPaolo Bonzini let reg = reg.unwrap_or_else(HPETRegister::Unknown); 798*734a1e9eSPaolo Bonzini HPETAddrDecode { shift, len, reg } 799*734a1e9eSPaolo Bonzini } 800*734a1e9eSPaolo Bonzini 801*734a1e9eSPaolo Bonzini fn read(&self, addr: hwaddr, size: u32) -> u64 { 802*734a1e9eSPaolo Bonzini // TODO: Add trace point - trace_hpet_ram_read(addr) 803*734a1e9eSPaolo Bonzini let HPETAddrDecode { shift, reg, .. } = self.decode(addr, size); 804*734a1e9eSPaolo Bonzini 805*734a1e9eSPaolo Bonzini use GlobalRegister::*; 806*734a1e9eSPaolo Bonzini use HPETRegister::*; 807*734a1e9eSPaolo Bonzini (match reg { 808*734a1e9eSPaolo Bonzini Timer(timer, tn_reg) => timer.borrow_mut().read(tn_reg), 809*734a1e9eSPaolo Bonzini Global(CAP) => self.capability.get(), /* including HPET_PERIOD 0x004 */ 810*734a1e9eSPaolo Bonzini Global(CFG) => self.config.get(), 811*734a1e9eSPaolo Bonzini Global(INT_STATUS) => self.int_status.get(), 812*734a1e9eSPaolo Bonzini Global(COUNTER) => { 813*734a1e9eSPaolo Bonzini // TODO: Add trace point 814*734a1e9eSPaolo Bonzini // trace_hpet_ram_read_reading_counter(addr & 4, cur_tick) 815*734a1e9eSPaolo Bonzini if self.is_hpet_enabled() { 816*734a1e9eSPaolo Bonzini self.get_ticks() 817*734a1e9eSPaolo Bonzini } else { 818*734a1e9eSPaolo Bonzini self.counter.get() 819*734a1e9eSPaolo Bonzini } 820*734a1e9eSPaolo Bonzini } 821*734a1e9eSPaolo Bonzini Unknown(_) => { 822*734a1e9eSPaolo Bonzini // TODO: Add trace point- trace_hpet_ram_read_invalid() 823*734a1e9eSPaolo Bonzini 0 824*734a1e9eSPaolo Bonzini } 825*734a1e9eSPaolo Bonzini }) >> shift 826*734a1e9eSPaolo Bonzini } 827*734a1e9eSPaolo Bonzini 828*734a1e9eSPaolo Bonzini fn write(&self, addr: hwaddr, value: u64, size: u32) { 829*734a1e9eSPaolo Bonzini let HPETAddrDecode { shift, len, reg } = self.decode(addr, size); 830*734a1e9eSPaolo Bonzini 831*734a1e9eSPaolo Bonzini // TODO: Add trace point - trace_hpet_ram_write(addr, value) 832*734a1e9eSPaolo Bonzini use GlobalRegister::*; 833*734a1e9eSPaolo Bonzini use HPETRegister::*; 834*734a1e9eSPaolo Bonzini match reg { 835*734a1e9eSPaolo Bonzini Timer(timer, tn_reg) => timer.borrow_mut().write(tn_reg, value, shift, len), 836*734a1e9eSPaolo Bonzini Global(CAP) => {} // General Capabilities and ID Register: Read Only 837*734a1e9eSPaolo Bonzini Global(CFG) => self.set_cfg_reg(shift, len, value), 838*734a1e9eSPaolo Bonzini Global(INT_STATUS) => self.set_int_status_reg(shift, len, value), 839*734a1e9eSPaolo Bonzini Global(COUNTER) => self.set_counter_reg(shift, len, value), 840*734a1e9eSPaolo Bonzini Unknown(_) => { 841*734a1e9eSPaolo Bonzini // TODO: Add trace point - trace_hpet_ram_write_invalid() 842*734a1e9eSPaolo Bonzini } 843*734a1e9eSPaolo Bonzini } 844*734a1e9eSPaolo Bonzini } 845*734a1e9eSPaolo Bonzini 846*734a1e9eSPaolo Bonzini fn pre_save(&self) -> i32 { 847*734a1e9eSPaolo Bonzini if self.is_hpet_enabled() { 848*734a1e9eSPaolo Bonzini self.counter.set(self.get_ticks()); 849*734a1e9eSPaolo Bonzini } 850*734a1e9eSPaolo Bonzini 851*734a1e9eSPaolo Bonzini /* 852*734a1e9eSPaolo Bonzini * The number of timers must match on source and destination, but it was 853*734a1e9eSPaolo Bonzini * also added to the migration stream. Check that it matches the value 854*734a1e9eSPaolo Bonzini * that was configured. 855*734a1e9eSPaolo Bonzini */ 856*734a1e9eSPaolo Bonzini self.num_timers_save.set(self.num_timers.get()); 857*734a1e9eSPaolo Bonzini 0 858*734a1e9eSPaolo Bonzini } 859*734a1e9eSPaolo Bonzini 860*734a1e9eSPaolo Bonzini fn post_load(&self, _version_id: u8) -> i32 { 861*734a1e9eSPaolo Bonzini for timer in self.timers.iter().take(self.get_num_timers()) { 862*734a1e9eSPaolo Bonzini let mut t = timer.borrow_mut(); 863*734a1e9eSPaolo Bonzini 864*734a1e9eSPaolo Bonzini t.cmp64 = t.calculate_cmp64(t.get_state().counter.get(), t.cmp); 865*734a1e9eSPaolo Bonzini t.last = CLOCK_VIRTUAL.get_ns() - NANOSECONDS_PER_SECOND; 866*734a1e9eSPaolo Bonzini } 867*734a1e9eSPaolo Bonzini 868*734a1e9eSPaolo Bonzini // Recalculate the offset between the main counter and guest time 869*734a1e9eSPaolo Bonzini if !self.hpet_offset_saved { 870*734a1e9eSPaolo Bonzini self.hpet_offset 871*734a1e9eSPaolo Bonzini .set(ticks_to_ns(self.counter.get()) - CLOCK_VIRTUAL.get_ns()); 872*734a1e9eSPaolo Bonzini } 873*734a1e9eSPaolo Bonzini 874*734a1e9eSPaolo Bonzini 0 875*734a1e9eSPaolo Bonzini } 876*734a1e9eSPaolo Bonzini 877*734a1e9eSPaolo Bonzini fn is_rtc_irq_level_needed(&self) -> bool { 878*734a1e9eSPaolo Bonzini self.rtc_irq_level.get() != 0 879*734a1e9eSPaolo Bonzini } 880*734a1e9eSPaolo Bonzini 881*734a1e9eSPaolo Bonzini fn is_offset_needed(&self) -> bool { 882*734a1e9eSPaolo Bonzini self.is_hpet_enabled() && self.hpet_offset_saved 883*734a1e9eSPaolo Bonzini } 884*734a1e9eSPaolo Bonzini 885*734a1e9eSPaolo Bonzini fn validate_num_timers(&self, _version_id: u8) -> bool { 886*734a1e9eSPaolo Bonzini self.num_timers.get() == self.num_timers_save.get() 887*734a1e9eSPaolo Bonzini } 888*734a1e9eSPaolo Bonzini } 889*734a1e9eSPaolo Bonzini 890*734a1e9eSPaolo Bonzini qom_isa!(HPETState: SysBusDevice, DeviceState, Object); 891*734a1e9eSPaolo Bonzini 892*734a1e9eSPaolo Bonzini unsafe impl ObjectType for HPETState { 893*734a1e9eSPaolo Bonzini // No need for HPETClass. Just like OBJECT_DECLARE_SIMPLE_TYPE in C. 894*734a1e9eSPaolo Bonzini type Class = <SysBusDevice as ObjectType>::Class; 895*734a1e9eSPaolo Bonzini const TYPE_NAME: &'static CStr = crate::TYPE_HPET; 896*734a1e9eSPaolo Bonzini } 897*734a1e9eSPaolo Bonzini 898*734a1e9eSPaolo Bonzini impl ObjectImpl for HPETState { 899*734a1e9eSPaolo Bonzini type ParentType = SysBusDevice; 900*734a1e9eSPaolo Bonzini 901*734a1e9eSPaolo Bonzini const INSTANCE_INIT: Option<unsafe fn(&mut Self)> = Some(Self::init); 902*734a1e9eSPaolo Bonzini const INSTANCE_POST_INIT: Option<fn(&Self)> = Some(Self::post_init); 903*734a1e9eSPaolo Bonzini const CLASS_INIT: fn(&mut Self::Class) = Self::Class::class_init::<Self>; 904*734a1e9eSPaolo Bonzini } 905*734a1e9eSPaolo Bonzini 906*734a1e9eSPaolo Bonzini // TODO: Make these properties user-configurable! 907*734a1e9eSPaolo Bonzini qemu_api::declare_properties! { 908*734a1e9eSPaolo Bonzini HPET_PROPERTIES, 909*734a1e9eSPaolo Bonzini qemu_api::define_property!( 910*734a1e9eSPaolo Bonzini c"timers", 911*734a1e9eSPaolo Bonzini HPETState, 912*734a1e9eSPaolo Bonzini num_timers, 913*734a1e9eSPaolo Bonzini unsafe { &qdev_prop_uint8 }, 914*734a1e9eSPaolo Bonzini u8, 915*734a1e9eSPaolo Bonzini default = HPET_MIN_TIMERS 916*734a1e9eSPaolo Bonzini ), 917*734a1e9eSPaolo Bonzini qemu_api::define_property!( 918*734a1e9eSPaolo Bonzini c"msi", 919*734a1e9eSPaolo Bonzini HPETState, 920*734a1e9eSPaolo Bonzini flags, 921*734a1e9eSPaolo Bonzini unsafe { &qdev_prop_bit }, 922*734a1e9eSPaolo Bonzini u32, 923*734a1e9eSPaolo Bonzini bit = HPET_FLAG_MSI_SUPPORT_SHIFT as u8, 924*734a1e9eSPaolo Bonzini default = false, 925*734a1e9eSPaolo Bonzini ), 926*734a1e9eSPaolo Bonzini qemu_api::define_property!( 927*734a1e9eSPaolo Bonzini c"hpet-intcap", 928*734a1e9eSPaolo Bonzini HPETState, 929*734a1e9eSPaolo Bonzini int_route_cap, 930*734a1e9eSPaolo Bonzini unsafe { &qdev_prop_uint32 }, 931*734a1e9eSPaolo Bonzini u32, 932*734a1e9eSPaolo Bonzini default = 0 933*734a1e9eSPaolo Bonzini ), 934*734a1e9eSPaolo Bonzini qemu_api::define_property!( 935*734a1e9eSPaolo Bonzini c"hpet-offset-saved", 936*734a1e9eSPaolo Bonzini HPETState, 937*734a1e9eSPaolo Bonzini hpet_offset_saved, 938*734a1e9eSPaolo Bonzini unsafe { &qdev_prop_bool }, 939*734a1e9eSPaolo Bonzini bool, 940*734a1e9eSPaolo Bonzini default = true 941*734a1e9eSPaolo Bonzini ), 942*734a1e9eSPaolo Bonzini } 943*734a1e9eSPaolo Bonzini 944*734a1e9eSPaolo Bonzini unsafe extern "C" fn hpet_rtc_irq_level_needed(opaque: *mut c_void) -> bool { 945*734a1e9eSPaolo Bonzini // SAFETY: 946*734a1e9eSPaolo Bonzini // the pointer is convertible to a reference 947*734a1e9eSPaolo Bonzini let state: &HPETState = unsafe { NonNull::new(opaque.cast::<HPETState>()).unwrap().as_ref() }; 948*734a1e9eSPaolo Bonzini state.is_rtc_irq_level_needed() 949*734a1e9eSPaolo Bonzini } 950*734a1e9eSPaolo Bonzini 951*734a1e9eSPaolo Bonzini unsafe extern "C" fn hpet_offset_needed(opaque: *mut c_void) -> bool { 952*734a1e9eSPaolo Bonzini // SAFETY: 953*734a1e9eSPaolo Bonzini // the pointer is convertible to a reference 954*734a1e9eSPaolo Bonzini let state: &HPETState = unsafe { NonNull::new(opaque.cast::<HPETState>()).unwrap().as_ref() }; 955*734a1e9eSPaolo Bonzini state.is_offset_needed() 956*734a1e9eSPaolo Bonzini } 957*734a1e9eSPaolo Bonzini 958*734a1e9eSPaolo Bonzini unsafe extern "C" fn hpet_pre_save(opaque: *mut c_void) -> c_int { 959*734a1e9eSPaolo Bonzini // SAFETY: 960*734a1e9eSPaolo Bonzini // the pointer is convertible to a reference 961*734a1e9eSPaolo Bonzini let state: &mut HPETState = 962*734a1e9eSPaolo Bonzini unsafe { NonNull::new(opaque.cast::<HPETState>()).unwrap().as_mut() }; 963*734a1e9eSPaolo Bonzini state.pre_save() as c_int 964*734a1e9eSPaolo Bonzini } 965*734a1e9eSPaolo Bonzini 966*734a1e9eSPaolo Bonzini unsafe extern "C" fn hpet_post_load(opaque: *mut c_void, version_id: c_int) -> c_int { 967*734a1e9eSPaolo Bonzini // SAFETY: 968*734a1e9eSPaolo Bonzini // the pointer is convertible to a reference 969*734a1e9eSPaolo Bonzini let state: &mut HPETState = 970*734a1e9eSPaolo Bonzini unsafe { NonNull::new(opaque.cast::<HPETState>()).unwrap().as_mut() }; 971*734a1e9eSPaolo Bonzini let version: u8 = version_id.try_into().unwrap(); 972*734a1e9eSPaolo Bonzini state.post_load(version) as c_int 973*734a1e9eSPaolo Bonzini } 974*734a1e9eSPaolo Bonzini 975*734a1e9eSPaolo Bonzini static VMSTATE_HPET_RTC_IRQ_LEVEL: VMStateDescription = VMStateDescription { 976*734a1e9eSPaolo Bonzini name: c"hpet/rtc_irq_level".as_ptr(), 977*734a1e9eSPaolo Bonzini version_id: 1, 978*734a1e9eSPaolo Bonzini minimum_version_id: 1, 979*734a1e9eSPaolo Bonzini needed: Some(hpet_rtc_irq_level_needed), 980*734a1e9eSPaolo Bonzini fields: vmstate_fields! { 981*734a1e9eSPaolo Bonzini vmstate_of!(HPETState, rtc_irq_level), 982*734a1e9eSPaolo Bonzini }, 983*734a1e9eSPaolo Bonzini ..Zeroable::ZERO 984*734a1e9eSPaolo Bonzini }; 985*734a1e9eSPaolo Bonzini 986*734a1e9eSPaolo Bonzini static VMSTATE_HPET_OFFSET: VMStateDescription = VMStateDescription { 987*734a1e9eSPaolo Bonzini name: c"hpet/offset".as_ptr(), 988*734a1e9eSPaolo Bonzini version_id: 1, 989*734a1e9eSPaolo Bonzini minimum_version_id: 1, 990*734a1e9eSPaolo Bonzini needed: Some(hpet_offset_needed), 991*734a1e9eSPaolo Bonzini fields: vmstate_fields! { 992*734a1e9eSPaolo Bonzini vmstate_of!(HPETState, hpet_offset), 993*734a1e9eSPaolo Bonzini }, 994*734a1e9eSPaolo Bonzini ..Zeroable::ZERO 995*734a1e9eSPaolo Bonzini }; 996*734a1e9eSPaolo Bonzini 997*734a1e9eSPaolo Bonzini static VMSTATE_HPET_TIMER: VMStateDescription = VMStateDescription { 998*734a1e9eSPaolo Bonzini name: c"hpet_timer".as_ptr(), 999*734a1e9eSPaolo Bonzini version_id: 1, 1000*734a1e9eSPaolo Bonzini minimum_version_id: 1, 1001*734a1e9eSPaolo Bonzini fields: vmstate_fields! { 1002*734a1e9eSPaolo Bonzini vmstate_of!(HPETTimer, index), 1003*734a1e9eSPaolo Bonzini vmstate_of!(HPETTimer, config), 1004*734a1e9eSPaolo Bonzini vmstate_of!(HPETTimer, cmp), 1005*734a1e9eSPaolo Bonzini vmstate_of!(HPETTimer, fsb), 1006*734a1e9eSPaolo Bonzini vmstate_of!(HPETTimer, period), 1007*734a1e9eSPaolo Bonzini vmstate_of!(HPETTimer, wrap_flag), 1008*734a1e9eSPaolo Bonzini vmstate_of!(HPETTimer, qemu_timer), 1009*734a1e9eSPaolo Bonzini }, 1010*734a1e9eSPaolo Bonzini ..Zeroable::ZERO 1011*734a1e9eSPaolo Bonzini }; 1012*734a1e9eSPaolo Bonzini 1013*734a1e9eSPaolo Bonzini const VALIDATE_TIMERS_NAME: &CStr = c"num_timers must match"; 1014*734a1e9eSPaolo Bonzini 1015*734a1e9eSPaolo Bonzini static VMSTATE_HPET: VMStateDescription = VMStateDescription { 1016*734a1e9eSPaolo Bonzini name: c"hpet".as_ptr(), 1017*734a1e9eSPaolo Bonzini version_id: 2, 1018*734a1e9eSPaolo Bonzini minimum_version_id: 1, 1019*734a1e9eSPaolo Bonzini pre_save: Some(hpet_pre_save), 1020*734a1e9eSPaolo Bonzini post_load: Some(hpet_post_load), 1021*734a1e9eSPaolo Bonzini fields: vmstate_fields! { 1022*734a1e9eSPaolo Bonzini vmstate_of!(HPETState, config), 1023*734a1e9eSPaolo Bonzini vmstate_of!(HPETState, int_status), 1024*734a1e9eSPaolo Bonzini vmstate_of!(HPETState, counter), 1025*734a1e9eSPaolo Bonzini vmstate_of!(HPETState, num_timers_save).with_version_id(2), 1026*734a1e9eSPaolo Bonzini vmstate_validate!(HPETState, VALIDATE_TIMERS_NAME, HPETState::validate_num_timers), 1027*734a1e9eSPaolo Bonzini vmstate_struct!(HPETState, timers[0 .. num_timers], &VMSTATE_HPET_TIMER, BqlRefCell<HPETTimer>, HPETState::validate_num_timers).with_version_id(0), 1028*734a1e9eSPaolo Bonzini }, 1029*734a1e9eSPaolo Bonzini subsections: vmstate_subsections! { 1030*734a1e9eSPaolo Bonzini VMSTATE_HPET_RTC_IRQ_LEVEL, 1031*734a1e9eSPaolo Bonzini VMSTATE_HPET_OFFSET, 1032*734a1e9eSPaolo Bonzini }, 1033*734a1e9eSPaolo Bonzini ..Zeroable::ZERO 1034*734a1e9eSPaolo Bonzini }; 1035*734a1e9eSPaolo Bonzini 1036*734a1e9eSPaolo Bonzini impl DeviceImpl for HPETState { 1037*734a1e9eSPaolo Bonzini fn properties() -> &'static [Property] { 1038*734a1e9eSPaolo Bonzini &HPET_PROPERTIES 1039*734a1e9eSPaolo Bonzini } 1040*734a1e9eSPaolo Bonzini 1041*734a1e9eSPaolo Bonzini fn vmsd() -> Option<&'static VMStateDescription> { 1042*734a1e9eSPaolo Bonzini Some(&VMSTATE_HPET) 1043*734a1e9eSPaolo Bonzini } 1044*734a1e9eSPaolo Bonzini 1045*734a1e9eSPaolo Bonzini const REALIZE: Option<fn(&Self)> = Some(Self::realize); 1046*734a1e9eSPaolo Bonzini } 1047*734a1e9eSPaolo Bonzini 1048*734a1e9eSPaolo Bonzini impl ResettablePhasesImpl for HPETState { 1049*734a1e9eSPaolo Bonzini const HOLD: Option<fn(&Self, ResetType)> = Some(Self::reset_hold); 1050*734a1e9eSPaolo Bonzini } 1051*734a1e9eSPaolo Bonzini 1052*734a1e9eSPaolo Bonzini impl SysBusDeviceImpl for HPETState {} 1053