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