1 // Copyright (C) 2024 Intel Corporation. 2 // Author(s): Zhao Liu <zhai1.liu@intel.com> 3 // SPDX-License-Identifier: GPL-2.0-or-later 4 5 use std::{ 6 ffi::CStr, 7 pin::Pin, 8 ptr::{addr_of_mut, null_mut, NonNull}, 9 slice::from_ref, 10 }; 11 12 use qemu_api::{ 13 bindings::{ 14 address_space_memory, address_space_stl_le, qdev_prop_bit, qdev_prop_bool, 15 qdev_prop_uint32, qdev_prop_usize, 16 }, 17 c_str, 18 cell::{BqlCell, BqlRefCell}, 19 irq::InterruptSource, 20 memory::{ 21 hwaddr, MemoryRegion, MemoryRegionOps, MemoryRegionOpsBuilder, MEMTXATTRS_UNSPECIFIED, 22 }, 23 prelude::*, 24 qdev::{DeviceImpl, DeviceMethods, DeviceState, Property, ResetType, ResettablePhasesImpl}, 25 qom::{ObjectImpl, ObjectType, ParentField}, 26 qom_isa, 27 sysbus::{SysBusDevice, SysBusDeviceImpl}, 28 timer::{Timer, CLOCK_VIRTUAL}, 29 }; 30 31 use crate::fw_cfg::HPETFwConfig; 32 33 /// Register space for each timer block (`HPET_BASE` is defined in hpet.h). 34 const HPET_REG_SPACE_LEN: u64 = 0x400; // 1024 bytes 35 36 /// Minimum recommended hardware implementation. 37 const HPET_MIN_TIMERS: usize = 3; 38 /// Maximum timers in each timer block. 39 const HPET_MAX_TIMERS: usize = 32; 40 41 /// Flags that HPETState.flags supports. 42 const HPET_FLAG_MSI_SUPPORT_SHIFT: usize = 0; 43 44 const HPET_NUM_IRQ_ROUTES: usize = 32; 45 const HPET_LEGACY_PIT_INT: u32 = 0; // HPET_LEGACY_RTC_INT isn't defined here. 46 const RTC_ISA_IRQ: usize = 8; 47 48 const HPET_CLK_PERIOD: u64 = 10; // 10 ns 49 const FS_PER_NS: u64 = 1000000; // 1000000 femtoseconds == 1 ns 50 51 /// Revision ID (bits 0:7). Revision 1 is implemented (refer to v1.0a spec). 52 const HPET_CAP_REV_ID_VALUE: u64 = 0x1; 53 const HPET_CAP_REV_ID_SHIFT: usize = 0; 54 /// Number of Timers (bits 8:12) 55 const HPET_CAP_NUM_TIM_SHIFT: usize = 8; 56 /// Counter Size (bit 13) 57 const HPET_CAP_COUNT_SIZE_CAP_SHIFT: usize = 13; 58 /// Legacy Replacement Route Capable (bit 15) 59 const HPET_CAP_LEG_RT_CAP_SHIFT: usize = 15; 60 /// Vendor ID (bits 16:31) 61 const HPET_CAP_VENDER_ID_VALUE: u64 = 0x8086; 62 const HPET_CAP_VENDER_ID_SHIFT: usize = 16; 63 /// Main Counter Tick Period (bits 32:63) 64 const HPET_CAP_CNT_CLK_PERIOD_SHIFT: usize = 32; 65 66 /// Overall Enable (bit 0) 67 const HPET_CFG_ENABLE_SHIFT: usize = 0; 68 /// Legacy Replacement Route (bit 1) 69 const HPET_CFG_LEG_RT_SHIFT: usize = 1; 70 /// Other bits are reserved. 71 const HPET_CFG_WRITE_MASK: u64 = 0x003; 72 73 /// bit 0, 7, and bits 16:31 are reserved. 74 /// bit 4, 5, 15, and bits 32:64 are read-only. 75 const HPET_TN_CFG_WRITE_MASK: u64 = 0x7f4e; 76 /// Timer N Interrupt Type (bit 1) 77 const HPET_TN_CFG_INT_TYPE_SHIFT: usize = 1; 78 /// Timer N Interrupt Enable (bit 2) 79 const HPET_TN_CFG_INT_ENABLE_SHIFT: usize = 2; 80 /// Timer N Type (Periodic enabled or not, bit 3) 81 const HPET_TN_CFG_PERIODIC_SHIFT: usize = 3; 82 /// Timer N Periodic Interrupt Capable (support Periodic or not, bit 4) 83 const HPET_TN_CFG_PERIODIC_CAP_SHIFT: usize = 4; 84 /// Timer N Size (timer size is 64-bits or 32 bits, bit 5) 85 const HPET_TN_CFG_SIZE_CAP_SHIFT: usize = 5; 86 /// Timer N Value Set (bit 6) 87 const HPET_TN_CFG_SETVAL_SHIFT: usize = 6; 88 /// Timer N 32-bit Mode (bit 8) 89 const HPET_TN_CFG_32BIT_SHIFT: usize = 8; 90 /// Timer N Interrupt Rout (bits 9:13) 91 const HPET_TN_CFG_INT_ROUTE_MASK: u64 = 0x3e00; 92 const HPET_TN_CFG_INT_ROUTE_SHIFT: usize = 9; 93 /// Timer N FSB Interrupt Enable (bit 14) 94 const HPET_TN_CFG_FSB_ENABLE_SHIFT: usize = 14; 95 /// Timer N FSB Interrupt Delivery (bit 15) 96 const HPET_TN_CFG_FSB_CAP_SHIFT: usize = 15; 97 /// Timer N Interrupt Routing Capability (bits 32:63) 98 const HPET_TN_CFG_INT_ROUTE_CAP_SHIFT: usize = 32; 99 100 #[derive(qemu_api_macros::TryInto)] 101 #[repr(u64)] 102 #[allow(non_camel_case_types)] 103 /// Timer registers, masked by 0x18 104 enum TimerRegister { 105 /// Timer N Configuration and Capability Register 106 CFG = 0, 107 /// Timer N Comparator Value Register 108 CMP = 8, 109 /// Timer N FSB Interrupt Route Register 110 ROUTE = 16, 111 } 112 113 #[derive(qemu_api_macros::TryInto)] 114 #[repr(u64)] 115 #[allow(non_camel_case_types)] 116 /// Global registers 117 enum GlobalRegister { 118 /// General Capabilities and ID Register 119 CAP = 0, 120 /// General Configuration Register 121 CFG = 0x10, 122 /// General Interrupt Status Register 123 INT_STATUS = 0x20, 124 /// Main Counter Value Register 125 COUNTER = 0xF0, 126 } 127 128 enum HPETRegister<'a> { 129 /// Global register in the range from `0` to `0xff` 130 Global(GlobalRegister), 131 132 /// Register in the timer block `0x100`...`0x3ff` 133 Timer(&'a BqlRefCell<HPETTimer>, TimerRegister), 134 135 /// Invalid address 136 #[allow(dead_code)] 137 Unknown(hwaddr), 138 } 139 140 struct HPETAddrDecode<'a> { 141 shift: u32, 142 len: u32, 143 reg: HPETRegister<'a>, 144 } 145 146 const fn hpet_next_wrap(cur_tick: u64) -> u64 { 147 (cur_tick | 0xffffffff) + 1 148 } 149 150 const fn hpet_time_after(a: u64, b: u64) -> bool { 151 ((b - a) as i64) < 0 152 } 153 154 const fn ticks_to_ns(value: u64) -> u64 { 155 value * HPET_CLK_PERIOD 156 } 157 158 const fn ns_to_ticks(value: u64) -> u64 { 159 value / HPET_CLK_PERIOD 160 } 161 162 // Avoid touching the bits that cannot be written. 163 const fn hpet_fixup_reg(new: u64, old: u64, mask: u64) -> u64 { 164 (new & mask) | (old & !mask) 165 } 166 167 const fn activating_bit(old: u64, new: u64, shift: usize) -> bool { 168 let mask: u64 = 1 << shift; 169 (old & mask == 0) && (new & mask != 0) 170 } 171 172 const fn deactivating_bit(old: u64, new: u64, shift: usize) -> bool { 173 let mask: u64 = 1 << shift; 174 (old & mask != 0) && (new & mask == 0) 175 } 176 177 fn timer_handler(timer_cell: &BqlRefCell<HPETTimer>) { 178 timer_cell.borrow_mut().callback() 179 } 180 181 /// HPET Timer Abstraction 182 #[repr(C)] 183 #[derive(Debug, qemu_api_macros::offsets)] 184 pub struct HPETTimer { 185 /// timer N index within the timer block (`HPETState`) 186 #[doc(alias = "tn")] 187 index: usize, 188 qemu_timer: Timer, 189 /// timer block abstraction containing this timer 190 state: NonNull<HPETState>, 191 192 // Memory-mapped, software visible timer registers 193 /// Timer N Configuration and Capability Register 194 config: u64, 195 /// Timer N Comparator Value Register 196 cmp: u64, 197 /// Timer N FSB Interrupt Route Register 198 fsb: u64, 199 200 // Hidden register state 201 /// comparator (extended to counter width) 202 cmp64: u64, 203 /// Last value written to comparator 204 period: u64, 205 /// timer pop will indicate wrap for one-shot 32-bit 206 /// mode. Next pop will be actual timer expiration. 207 wrap_flag: u8, 208 /// last value armed, to avoid timer storms 209 last: u64, 210 } 211 212 impl HPETTimer { 213 fn init(&mut self, index: usize, state: &HPETState) { 214 *self = HPETTimer { 215 index, 216 // SAFETY: the HPETTimer will only be used after the timer 217 // is initialized below. 218 qemu_timer: unsafe { Timer::new() }, 219 state: NonNull::new(state as *const _ as *mut _).unwrap(), 220 config: 0, 221 cmp: 0, 222 fsb: 0, 223 cmp64: 0, 224 period: 0, 225 wrap_flag: 0, 226 last: 0, 227 }; 228 229 // SAFETY: HPETTimer is only used as part of HPETState, which is 230 // always pinned. 231 let qemu_timer = unsafe { Pin::new_unchecked(&mut self.qemu_timer) }; 232 qemu_timer.init_full( 233 None, 234 CLOCK_VIRTUAL, 235 Timer::NS, 236 0, 237 timer_handler, 238 &state.timers[self.index], 239 ) 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) 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 as u32, 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, qemu_api_macros::offsets)] 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: BqlCell<usize>, 564 565 /// Instance id (HPET timer block ID). 566 hpet_id: BqlCell<usize>, 567 } 568 569 impl HPETState { 570 const fn has_msi_flag(&self) -> bool { 571 self.flags & (1 << HPET_FLAG_MSI_SUPPORT_SHIFT) != 0 572 } 573 574 fn is_legacy_mode(&self) -> bool { 575 self.config.get() & (1 << HPET_CFG_LEG_RT_SHIFT) != 0 576 } 577 578 fn is_hpet_enabled(&self) -> bool { 579 self.config.get() & (1 << HPET_CFG_ENABLE_SHIFT) != 0 580 } 581 582 fn is_timer_int_active(&self, index: usize) -> bool { 583 self.int_status.get() & (1 << index) != 0 584 } 585 586 fn get_ticks(&self) -> u64 { 587 ns_to_ticks(CLOCK_VIRTUAL.get_ns() + self.hpet_offset.get()) 588 } 589 590 fn get_ns(&self, tick: u64) -> u64 { 591 ticks_to_ns(tick) - self.hpet_offset.get() 592 } 593 594 fn handle_legacy_irq(&self, irq: u32, level: u32) { 595 if irq == HPET_LEGACY_PIT_INT { 596 if !self.is_legacy_mode() { 597 self.irqs[0].set(level != 0); 598 } 599 } else { 600 self.rtc_irq_level.set(level); 601 if !self.is_legacy_mode() { 602 self.irqs[RTC_ISA_IRQ].set(level != 0); 603 } 604 } 605 } 606 607 fn init_timer(&self) { 608 for (index, timer) in self.timers.iter().enumerate() { 609 timer.borrow_mut().init(index, self); 610 } 611 } 612 613 fn update_int_status(&self, index: u32, level: bool) { 614 self.int_status 615 .set(self.int_status.get().deposit(index, 1, u64::from(level))); 616 } 617 618 /// General Configuration Register 619 fn set_cfg_reg(&self, shift: u32, len: u32, val: u64) { 620 let old_val = self.config.get(); 621 let mut new_val = old_val.deposit(shift, len, val); 622 623 new_val = hpet_fixup_reg(new_val, old_val, HPET_CFG_WRITE_MASK); 624 self.config.set(new_val); 625 626 if activating_bit(old_val, new_val, HPET_CFG_ENABLE_SHIFT) { 627 // Enable main counter and interrupt generation. 628 self.hpet_offset 629 .set(ticks_to_ns(self.counter.get()) - CLOCK_VIRTUAL.get_ns()); 630 631 for timer in self.timers.iter().take(self.num_timers.get()) { 632 let mut t = timer.borrow_mut(); 633 634 if t.is_int_enabled() && t.is_int_active() { 635 t.update_irq(true); 636 } 637 t.set_timer(); 638 } 639 } else if deactivating_bit(old_val, new_val, HPET_CFG_ENABLE_SHIFT) { 640 // Halt main counter and disable interrupt generation. 641 self.counter.set(self.get_ticks()); 642 643 for timer in self.timers.iter().take(self.num_timers.get()) { 644 timer.borrow_mut().del_timer(); 645 } 646 } 647 648 // i8254 and RTC output pins are disabled when HPET is in legacy mode 649 if activating_bit(old_val, new_val, HPET_CFG_LEG_RT_SHIFT) { 650 self.pit_enabled.set(false); 651 self.irqs[0].lower(); 652 self.irqs[RTC_ISA_IRQ].lower(); 653 } else if deactivating_bit(old_val, new_val, HPET_CFG_LEG_RT_SHIFT) { 654 // TODO: Add irq binding: qemu_irq_lower(s->irqs[0]) 655 self.irqs[0].lower(); 656 self.pit_enabled.set(true); 657 self.irqs[RTC_ISA_IRQ].set(self.rtc_irq_level.get() != 0); 658 } 659 } 660 661 /// General Interrupt Status Register: Read/Write Clear 662 fn set_int_status_reg(&self, shift: u32, _len: u32, val: u64) { 663 let new_val = val << shift; 664 let cleared = new_val & self.int_status.get(); 665 666 for (index, timer) in self.timers.iter().take(self.num_timers.get()).enumerate() { 667 if cleared & (1 << index) != 0 { 668 timer.borrow_mut().update_irq(false); 669 } 670 } 671 } 672 673 /// Main Counter Value Register 674 fn set_counter_reg(&self, shift: u32, len: u32, val: u64) { 675 if self.is_hpet_enabled() { 676 // TODO: Add trace point - 677 // trace_hpet_ram_write_counter_write_while_enabled() 678 // 679 // HPET spec says that writes to this register should only be 680 // done while the counter is halted. So this is an undefined 681 // behavior. There's no need to forbid it, but when HPET is 682 // enabled, the changed counter value will not affect the 683 // tick count (i.e., the previously calculated offset will 684 // not be changed as well). 685 } 686 self.counter 687 .set(self.counter.get().deposit(shift, len, val)); 688 } 689 690 unsafe fn init(&mut self) { 691 static HPET_RAM_OPS: MemoryRegionOps<HPETState> = 692 MemoryRegionOpsBuilder::<HPETState>::new() 693 .read(&HPETState::read) 694 .write(&HPETState::write) 695 .native_endian() 696 .valid_sizes(4, 8) 697 .impl_sizes(4, 8) 698 .build(); 699 700 // SAFETY: 701 // self and self.iomem are guaranteed to be valid at this point since callers 702 // must make sure the `self` reference is valid. 703 MemoryRegion::init_io( 704 unsafe { &mut *addr_of_mut!(self.iomem) }, 705 addr_of_mut!(*self), 706 &HPET_RAM_OPS, 707 "hpet", 708 HPET_REG_SPACE_LEN, 709 ); 710 } 711 712 fn post_init(&self) { 713 self.init_mmio(&self.iomem); 714 for irq in self.irqs.iter() { 715 self.init_irq(irq); 716 } 717 } 718 719 fn realize(&self) { 720 if self.int_route_cap == 0 { 721 // TODO: Add error binding: warn_report() 722 println!("Hpet's hpet-intcap property not initialized"); 723 } 724 725 self.hpet_id.set(HPETFwConfig::assign_hpet_id()); 726 727 if self.num_timers.get() < HPET_MIN_TIMERS { 728 self.num_timers.set(HPET_MIN_TIMERS); 729 } else if self.num_timers.get() > HPET_MAX_TIMERS { 730 self.num_timers.set(HPET_MAX_TIMERS); 731 } 732 733 self.init_timer(); 734 // 64-bit General Capabilities and ID Register; LegacyReplacementRoute. 735 self.capability.set( 736 HPET_CAP_REV_ID_VALUE << HPET_CAP_REV_ID_SHIFT | 737 1 << HPET_CAP_COUNT_SIZE_CAP_SHIFT | 738 1 << HPET_CAP_LEG_RT_CAP_SHIFT | 739 HPET_CAP_VENDER_ID_VALUE << HPET_CAP_VENDER_ID_SHIFT | 740 ((self.num_timers.get() - 1) as u64) << HPET_CAP_NUM_TIM_SHIFT | // indicate the last timer 741 (HPET_CLK_PERIOD * FS_PER_NS) << HPET_CAP_CNT_CLK_PERIOD_SHIFT, // 10 ns 742 ); 743 744 self.init_gpio_in(2, HPETState::handle_legacy_irq); 745 self.init_gpio_out(from_ref(&self.pit_enabled)); 746 } 747 748 fn reset_hold(&self, _type: ResetType) { 749 for timer in self.timers.iter().take(self.num_timers.get()) { 750 timer.borrow_mut().reset(); 751 } 752 753 self.counter.set(0); 754 self.config.set(0); 755 self.pit_enabled.set(true); 756 self.hpet_offset.set(0); 757 758 HPETFwConfig::update_hpet_cfg( 759 self.hpet_id.get(), 760 self.capability.get() as u32, 761 self.mmio_addr(0).unwrap(), 762 ); 763 764 // to document that the RTC lowers its output on reset as well 765 self.rtc_irq_level.set(0); 766 } 767 768 fn decode(&self, mut addr: hwaddr, size: u32) -> HPETAddrDecode { 769 let shift = ((addr & 4) * 8) as u32; 770 let len = std::cmp::min(size * 8, 64 - shift); 771 772 addr &= !4; 773 let reg = if (0..=0xff).contains(&addr) { 774 GlobalRegister::try_from(addr).map(HPETRegister::Global) 775 } else { 776 let timer_id: usize = ((addr - 0x100) / 0x20) as usize; 777 if timer_id <= self.num_timers.get() { 778 // TODO: Add trace point - trace_hpet_ram_[read|write]_timer_id(timer_id) 779 TimerRegister::try_from(addr) 780 .map(|reg| HPETRegister::Timer(&self.timers[timer_id], reg)) 781 } else { 782 // TODO: Add trace point - trace_hpet_timer_id_out_of_range(timer_id) 783 Err(addr) 784 } 785 }; 786 787 // reg is now a Result<HPETRegister, hwaddr> 788 // convert the Err case into HPETRegister as well 789 let reg = reg.unwrap_or_else(HPETRegister::Unknown); 790 HPETAddrDecode { shift, len, reg } 791 } 792 793 fn read(&self, addr: hwaddr, size: u32) -> u64 { 794 // TODO: Add trace point - trace_hpet_ram_read(addr) 795 let HPETAddrDecode { shift, reg, .. } = self.decode(addr, size); 796 797 use GlobalRegister::*; 798 use HPETRegister::*; 799 (match reg { 800 Timer(timer, tn_reg) => timer.borrow_mut().read(tn_reg), 801 Global(CAP) => self.capability.get(), /* including HPET_PERIOD 0x004 */ 802 Global(CFG) => self.config.get(), 803 Global(INT_STATUS) => self.int_status.get(), 804 Global(COUNTER) => { 805 // TODO: Add trace point 806 // trace_hpet_ram_read_reading_counter(addr & 4, cur_tick) 807 if self.is_hpet_enabled() { 808 self.get_ticks() 809 } else { 810 self.counter.get() 811 } 812 } 813 Unknown(_) => { 814 // TODO: Add trace point- trace_hpet_ram_read_invalid() 815 0 816 } 817 }) >> shift 818 } 819 820 fn write(&self, addr: hwaddr, value: u64, size: u32) { 821 let HPETAddrDecode { shift, len, reg } = self.decode(addr, size); 822 823 // TODO: Add trace point - trace_hpet_ram_write(addr, value) 824 use GlobalRegister::*; 825 use HPETRegister::*; 826 match reg { 827 Timer(timer, tn_reg) => timer.borrow_mut().write(tn_reg, value, shift, len), 828 Global(CAP) => {} // General Capabilities and ID Register: Read Only 829 Global(CFG) => self.set_cfg_reg(shift, len, value), 830 Global(INT_STATUS) => self.set_int_status_reg(shift, len, value), 831 Global(COUNTER) => self.set_counter_reg(shift, len, value), 832 Unknown(_) => { 833 // TODO: Add trace point - trace_hpet_ram_write_invalid() 834 } 835 } 836 } 837 } 838 839 qom_isa!(HPETState: SysBusDevice, DeviceState, Object); 840 841 unsafe impl ObjectType for HPETState { 842 // No need for HPETClass. Just like OBJECT_DECLARE_SIMPLE_TYPE in C. 843 type Class = <SysBusDevice as ObjectType>::Class; 844 const TYPE_NAME: &'static CStr = crate::TYPE_HPET; 845 } 846 847 impl ObjectImpl for HPETState { 848 type ParentType = SysBusDevice; 849 850 const INSTANCE_INIT: Option<unsafe fn(&mut Self)> = Some(Self::init); 851 const INSTANCE_POST_INIT: Option<fn(&Self)> = Some(Self::post_init); 852 const CLASS_INIT: fn(&mut Self::Class) = Self::Class::class_init::<Self>; 853 } 854 855 // TODO: Make these properties user-configurable! 856 qemu_api::declare_properties! { 857 HPET_PROPERTIES, 858 qemu_api::define_property!( 859 c_str!("timers"), 860 HPETState, 861 num_timers, 862 unsafe { &qdev_prop_usize }, 863 usize, 864 default = HPET_MIN_TIMERS 865 ), 866 qemu_api::define_property!( 867 c_str!("msi"), 868 HPETState, 869 flags, 870 unsafe { &qdev_prop_bit }, 871 u32, 872 bit = HPET_FLAG_MSI_SUPPORT_SHIFT as u8, 873 default = false, 874 ), 875 qemu_api::define_property!( 876 c_str!("hpet-intcap"), 877 HPETState, 878 int_route_cap, 879 unsafe { &qdev_prop_uint32 }, 880 u32, 881 default = 0 882 ), 883 qemu_api::define_property!( 884 c_str!("hpet-offset-saved"), 885 HPETState, 886 hpet_offset_saved, 887 unsafe { &qdev_prop_bool }, 888 bool, 889 default = true 890 ), 891 } 892 893 impl DeviceImpl for HPETState { 894 fn properties() -> &'static [Property] { 895 &HPET_PROPERTIES 896 } 897 898 const REALIZE: Option<fn(&Self)> = Some(Self::realize); 899 } 900 901 impl ResettablePhasesImpl for HPETState { 902 const HOLD: Option<fn(&Self, ResetType)> = Some(Self::reset_hold); 903 } 904 905 impl SysBusDeviceImpl for HPETState {} 906