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_uint8, 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: u8 = 3; 38 /// Maximum timers in each timer block. 39 const HPET_MAX_TIMERS: u8 = 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 as usize], 563 num_timers: BqlCell<u8>, 564 565 /// Instance id (HPET timer block ID). 566 hpet_id: BqlCell<usize>, 567 } 568 569 impl HPETState { 570 // Get num_timers with `usize` type, which is useful to play with array index. 571 fn get_num_timers(&self) -> usize { 572 self.num_timers.get().into() 573 } 574 575 const fn has_msi_flag(&self) -> bool { 576 self.flags & (1 << HPET_FLAG_MSI_SUPPORT_SHIFT) != 0 577 } 578 579 fn is_legacy_mode(&self) -> bool { 580 self.config.get() & (1 << HPET_CFG_LEG_RT_SHIFT) != 0 581 } 582 583 fn is_hpet_enabled(&self) -> bool { 584 self.config.get() & (1 << HPET_CFG_ENABLE_SHIFT) != 0 585 } 586 587 fn is_timer_int_active(&self, index: usize) -> bool { 588 self.int_status.get() & (1 << index) != 0 589 } 590 591 fn get_ticks(&self) -> u64 { 592 ns_to_ticks(CLOCK_VIRTUAL.get_ns() + self.hpet_offset.get()) 593 } 594 595 fn get_ns(&self, tick: u64) -> u64 { 596 ticks_to_ns(tick) - self.hpet_offset.get() 597 } 598 599 fn handle_legacy_irq(&self, irq: u32, level: u32) { 600 if irq == HPET_LEGACY_PIT_INT { 601 if !self.is_legacy_mode() { 602 self.irqs[0].set(level != 0); 603 } 604 } else { 605 self.rtc_irq_level.set(level); 606 if !self.is_legacy_mode() { 607 self.irqs[RTC_ISA_IRQ].set(level != 0); 608 } 609 } 610 } 611 612 fn init_timer(&self) { 613 for (index, timer) in self.timers.iter().enumerate() { 614 timer.borrow_mut().init(index, self); 615 } 616 } 617 618 fn update_int_status(&self, index: u32, level: bool) { 619 self.int_status 620 .set(self.int_status.get().deposit(index, 1, u64::from(level))); 621 } 622 623 /// General Configuration Register 624 fn set_cfg_reg(&self, shift: u32, len: u32, val: u64) { 625 let old_val = self.config.get(); 626 let mut new_val = old_val.deposit(shift, len, val); 627 628 new_val = hpet_fixup_reg(new_val, old_val, HPET_CFG_WRITE_MASK); 629 self.config.set(new_val); 630 631 if activating_bit(old_val, new_val, HPET_CFG_ENABLE_SHIFT) { 632 // Enable main counter and interrupt generation. 633 self.hpet_offset 634 .set(ticks_to_ns(self.counter.get()) - CLOCK_VIRTUAL.get_ns()); 635 636 for timer in self.timers.iter().take(self.get_num_timers()) { 637 let mut t = timer.borrow_mut(); 638 639 if t.is_int_enabled() && t.is_int_active() { 640 t.update_irq(true); 641 } 642 t.set_timer(); 643 } 644 } else if deactivating_bit(old_val, new_val, HPET_CFG_ENABLE_SHIFT) { 645 // Halt main counter and disable interrupt generation. 646 self.counter.set(self.get_ticks()); 647 648 for timer in self.timers.iter().take(self.get_num_timers()) { 649 timer.borrow_mut().del_timer(); 650 } 651 } 652 653 // i8254 and RTC output pins are disabled when HPET is in legacy mode 654 if activating_bit(old_val, new_val, HPET_CFG_LEG_RT_SHIFT) { 655 self.pit_enabled.set(false); 656 self.irqs[0].lower(); 657 self.irqs[RTC_ISA_IRQ].lower(); 658 } else if deactivating_bit(old_val, new_val, HPET_CFG_LEG_RT_SHIFT) { 659 // TODO: Add irq binding: qemu_irq_lower(s->irqs[0]) 660 self.irqs[0].lower(); 661 self.pit_enabled.set(true); 662 self.irqs[RTC_ISA_IRQ].set(self.rtc_irq_level.get() != 0); 663 } 664 } 665 666 /// General Interrupt Status Register: Read/Write Clear 667 fn set_int_status_reg(&self, shift: u32, _len: u32, val: u64) { 668 let new_val = val << shift; 669 let cleared = new_val & self.int_status.get(); 670 671 for (index, timer) in self.timers.iter().take(self.get_num_timers()).enumerate() { 672 if cleared & (1 << index) != 0 { 673 timer.borrow_mut().update_irq(false); 674 } 675 } 676 } 677 678 /// Main Counter Value Register 679 fn set_counter_reg(&self, shift: u32, len: u32, val: u64) { 680 if self.is_hpet_enabled() { 681 // TODO: Add trace point - 682 // trace_hpet_ram_write_counter_write_while_enabled() 683 // 684 // HPET spec says that writes to this register should only be 685 // done while the counter is halted. So this is an undefined 686 // behavior. There's no need to forbid it, but when HPET is 687 // enabled, the changed counter value will not affect the 688 // tick count (i.e., the previously calculated offset will 689 // not be changed as well). 690 } 691 self.counter 692 .set(self.counter.get().deposit(shift, len, val)); 693 } 694 695 unsafe fn init(&mut self) { 696 static HPET_RAM_OPS: MemoryRegionOps<HPETState> = 697 MemoryRegionOpsBuilder::<HPETState>::new() 698 .read(&HPETState::read) 699 .write(&HPETState::write) 700 .native_endian() 701 .valid_sizes(4, 8) 702 .impl_sizes(4, 8) 703 .build(); 704 705 // SAFETY: 706 // self and self.iomem are guaranteed to be valid at this point since callers 707 // must make sure the `self` reference is valid. 708 MemoryRegion::init_io( 709 unsafe { &mut *addr_of_mut!(self.iomem) }, 710 addr_of_mut!(*self), 711 &HPET_RAM_OPS, 712 "hpet", 713 HPET_REG_SPACE_LEN, 714 ); 715 } 716 717 fn post_init(&self) { 718 self.init_mmio(&self.iomem); 719 for irq in self.irqs.iter() { 720 self.init_irq(irq); 721 } 722 } 723 724 fn realize(&self) { 725 if self.int_route_cap == 0 { 726 // TODO: Add error binding: warn_report() 727 println!("Hpet's hpet-intcap property not initialized"); 728 } 729 730 self.hpet_id.set(HPETFwConfig::assign_hpet_id()); 731 732 if self.num_timers.get() < HPET_MIN_TIMERS { 733 self.num_timers.set(HPET_MIN_TIMERS); 734 } else if self.num_timers.get() > HPET_MAX_TIMERS { 735 self.num_timers.set(HPET_MAX_TIMERS); 736 } 737 738 self.init_timer(); 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.get_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 } 752 753 fn reset_hold(&self, _type: ResetType) { 754 for timer in self.timers.iter().take(self.get_num_timers()) { 755 timer.borrow_mut().reset(); 756 } 757 758 self.counter.set(0); 759 self.config.set(0); 760 self.pit_enabled.set(true); 761 self.hpet_offset.set(0); 762 763 HPETFwConfig::update_hpet_cfg( 764 self.hpet_id.get(), 765 self.capability.get() as u32, 766 self.mmio_addr(0).unwrap(), 767 ); 768 769 // to document that the RTC lowers its output on reset as well 770 self.rtc_irq_level.set(0); 771 } 772 773 fn decode(&self, mut addr: hwaddr, size: u32) -> HPETAddrDecode { 774 let shift = ((addr & 4) * 8) as u32; 775 let len = std::cmp::min(size * 8, 64 - shift); 776 777 addr &= !4; 778 let reg = if (0..=0xff).contains(&addr) { 779 GlobalRegister::try_from(addr).map(HPETRegister::Global) 780 } else { 781 let timer_id: usize = ((addr - 0x100) / 0x20) as usize; 782 if timer_id <= self.get_num_timers() { 783 // TODO: Add trace point - trace_hpet_ram_[read|write]_timer_id(timer_id) 784 TimerRegister::try_from(addr & 0x18) 785 .map(|reg| HPETRegister::Timer(&self.timers[timer_id], reg)) 786 } else { 787 // TODO: Add trace point - trace_hpet_timer_id_out_of_range(timer_id) 788 Err(addr) 789 } 790 }; 791 792 // reg is now a Result<HPETRegister, hwaddr> 793 // convert the Err case into HPETRegister as well 794 let reg = reg.unwrap_or_else(HPETRegister::Unknown); 795 HPETAddrDecode { shift, len, reg } 796 } 797 798 fn read(&self, addr: hwaddr, size: u32) -> u64 { 799 // TODO: Add trace point - trace_hpet_ram_read(addr) 800 let HPETAddrDecode { shift, reg, .. } = self.decode(addr, size); 801 802 use GlobalRegister::*; 803 use HPETRegister::*; 804 (match reg { 805 Timer(timer, tn_reg) => timer.borrow_mut().read(tn_reg), 806 Global(CAP) => self.capability.get(), /* including HPET_PERIOD 0x004 */ 807 Global(CFG) => self.config.get(), 808 Global(INT_STATUS) => self.int_status.get(), 809 Global(COUNTER) => { 810 // TODO: Add trace point 811 // trace_hpet_ram_read_reading_counter(addr & 4, cur_tick) 812 if self.is_hpet_enabled() { 813 self.get_ticks() 814 } else { 815 self.counter.get() 816 } 817 } 818 Unknown(_) => { 819 // TODO: Add trace point- trace_hpet_ram_read_invalid() 820 0 821 } 822 }) >> shift 823 } 824 825 fn write(&self, addr: hwaddr, value: u64, size: u32) { 826 let HPETAddrDecode { shift, len, reg } = self.decode(addr, size); 827 828 // TODO: Add trace point - trace_hpet_ram_write(addr, value) 829 use GlobalRegister::*; 830 use HPETRegister::*; 831 match reg { 832 Timer(timer, tn_reg) => timer.borrow_mut().write(tn_reg, value, shift, len), 833 Global(CAP) => {} // General Capabilities and ID Register: Read Only 834 Global(CFG) => self.set_cfg_reg(shift, len, value), 835 Global(INT_STATUS) => self.set_int_status_reg(shift, len, value), 836 Global(COUNTER) => self.set_counter_reg(shift, len, value), 837 Unknown(_) => { 838 // TODO: Add trace point - trace_hpet_ram_write_invalid() 839 } 840 } 841 } 842 } 843 844 qom_isa!(HPETState: SysBusDevice, DeviceState, Object); 845 846 unsafe impl ObjectType for HPETState { 847 // No need for HPETClass. Just like OBJECT_DECLARE_SIMPLE_TYPE in C. 848 type Class = <SysBusDevice as ObjectType>::Class; 849 const TYPE_NAME: &'static CStr = crate::TYPE_HPET; 850 } 851 852 impl ObjectImpl for HPETState { 853 type ParentType = SysBusDevice; 854 855 const INSTANCE_INIT: Option<unsafe fn(&mut Self)> = Some(Self::init); 856 const INSTANCE_POST_INIT: Option<fn(&Self)> = Some(Self::post_init); 857 const CLASS_INIT: fn(&mut Self::Class) = Self::Class::class_init::<Self>; 858 } 859 860 // TODO: Make these properties user-configurable! 861 qemu_api::declare_properties! { 862 HPET_PROPERTIES, 863 qemu_api::define_property!( 864 c_str!("timers"), 865 HPETState, 866 num_timers, 867 unsafe { &qdev_prop_uint8 }, 868 u8, 869 default = HPET_MIN_TIMERS 870 ), 871 qemu_api::define_property!( 872 c_str!("msi"), 873 HPETState, 874 flags, 875 unsafe { &qdev_prop_bit }, 876 u32, 877 bit = HPET_FLAG_MSI_SUPPORT_SHIFT as u8, 878 default = false, 879 ), 880 qemu_api::define_property!( 881 c_str!("hpet-intcap"), 882 HPETState, 883 int_route_cap, 884 unsafe { &qdev_prop_uint32 }, 885 u32, 886 default = 0 887 ), 888 qemu_api::define_property!( 889 c_str!("hpet-offset-saved"), 890 HPETState, 891 hpet_offset_saved, 892 unsafe { &qdev_prop_bool }, 893 bool, 894 default = true 895 ), 896 } 897 898 impl DeviceImpl for HPETState { 899 fn properties() -> &'static [Property] { 900 &HPET_PROPERTIES 901 } 902 903 const REALIZE: Option<fn(&Self)> = Some(Self::realize); 904 } 905 906 impl ResettablePhasesImpl for HPETState { 907 const HOLD: Option<fn(&Self, ResetType)> = Some(Self::reset_hold); 908 } 909 910 impl SysBusDeviceImpl for HPETState {} 911