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