master
c 791 lines 22.9 KB
Raw
1 /*
2 * High Precision Event Timer emulation
3 *
4 * Copyright (c) 2007 Alexander Graf
5 * Copyright (c) 2008 IBM Corporation
6 *
7 * Authors: Beth Kon <bkon@us.ibm.com>
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
21 *
22 * *****************************************************************
23 *
24 * This driver attempts to emulate an HPET device in software.
25 */
26
27 #include "qemu/osdep.h"
28 #include "hw/core/irq.h"
29 #include "qapi/error.h"
30 #include "qemu/error-report.h"
31 #include "qemu/timer.h"
32 #include "hw/core/qdev-properties.h"
33 #include "hw/timer/hpet.h"
34 #include "hw/core/sysbus.h"
35 #include "hw/rtc/mc146818rtc.h"
36 #include "hw/rtc/mc146818rtc_regs.h"
37 #include "migration/vmstate.h"
38 #include "hw/timer/i8254.h"
39 #include "system/address-spaces.h"
40 #include "qom/object.h"
41 #include "qemu/lockable.h"
42 #include "qemu/seqlock.h"
43 #include "qemu/main-loop.h"
44 #include "trace.h"
45
46 struct hpet_fw_config hpet_fw_cfg = {.count = UINT8_MAX};
47
48 #define HPET_MSI_SUPPORT 0
49
50 OBJECT_DECLARE_SIMPLE_TYPE(HPETState, HPET)
51
52 struct HPETState;
53 typedef struct HPETTimer { /* timers */
54 uint8_t tn; /*timer number*/
55 QEMUTimer *qemu_timer;
56 struct HPETState *state;
57 /* Memory-mapped, software visible timer registers */
58 uint64_t config; /* configuration/cap */
59 uint64_t cmp; /* comparator */
60 uint64_t fsb; /* FSB route */
61 /* Hidden register state */
62 uint64_t cmp64; /* comparator (extended to counter width) */
63 uint64_t period; /* Last value written to comparator */
64 uint8_t wrap_flag; /* timer pop will indicate wrap for one-shot 32-bit
65 * mode. Next pop will be actual timer expiration.
66 */
67 uint64_t last; /* last value armed, to avoid timer storms */
68 } HPETTimer;
69
70 struct HPETState {
71 /*< private >*/
72 SysBusDevice parent_obj;
73 /*< public >*/
74
75 QemuMutex lock;
76 MemoryRegion iomem;
77 uint64_t hpet_offset;
78 QemuSeqLock state_version;
79 qemu_irq irqs[HPET_NUM_IRQ_ROUTES];
80 uint32_t flags;
81 uint8_t rtc_irq_level;
82 qemu_irq pit_enabled;
83 uint8_t num_timers;
84 uint8_t num_timers_save;
85 uint32_t intcap;
86 HPETTimer timer[HPET_MAX_TIMERS];
87
88 /* Memory-mapped, software visible registers */
89 uint64_t capability; /* capabilities */
90 uint64_t config; /* configuration */
91 uint64_t isr; /* interrupt status reg */
92 uint64_t hpet_counter; /* main counter */
93 uint8_t hpet_id; /* instance id */
94 };
95
96 static uint32_t hpet_in_legacy_mode(HPETState *s)
97 {
98 return s->config & HPET_CFG_LEGACY;
99 }
100
101 static uint32_t timer_int_route(struct HPETTimer *timer)
102 {
103 return (timer->config & HPET_TN_INT_ROUTE_MASK) >> HPET_TN_INT_ROUTE_SHIFT;
104 }
105
106 static uint32_t timer_fsb_route(HPETTimer *t)
107 {
108 return t->config & HPET_TN_FSB_ENABLE;
109 }
110
111 static uint32_t hpet_enabled(HPETState *s)
112 {
113 return s->config & HPET_CFG_ENABLE;
114 }
115
116 static uint32_t timer_is_periodic(HPETTimer *t)
117 {
118 return t->config & HPET_TN_PERIODIC;
119 }
120
121 static uint32_t timer_enabled(HPETTimer *t)
122 {
123 return t->config & HPET_TN_ENABLE;
124 }
125
126 static uint32_t hpet_time_after(uint64_t a, uint64_t b)
127 {
128 return ((int64_t)(b - a) < 0);
129 }
130
131 static uint64_t ticks_to_ns(uint64_t value)
132 {
133 return value * HPET_CLK_PERIOD;
134 }
135
136 static uint64_t ns_to_ticks(uint64_t value)
137 {
138 return value / HPET_CLK_PERIOD;
139 }
140
141 static uint64_t hpet_fixup_reg(uint64_t new, uint64_t old, uint64_t mask)
142 {
143 new &= mask;
144 new |= old & ~mask;
145 return new;
146 }
147
148 static int activating_bit(uint64_t old, uint64_t new, uint64_t mask)
149 {
150 return (!(old & mask) && (new & mask));
151 }
152
153 static int deactivating_bit(uint64_t old, uint64_t new, uint64_t mask)
154 {
155 return ((old & mask) && !(new & mask));
156 }
157
158 static uint64_t hpet_get_ticks(HPETState *s)
159 {
160 return ns_to_ticks(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + s->hpet_offset);
161 }
162
163 static uint64_t hpet_get_ns(HPETState *s, uint64_t tick)
164 {
165 return ticks_to_ns(tick) - s->hpet_offset;
166 }
167
168 /*
169 * calculate next value of the general counter that matches the
170 * target (either entirely, or the low 32-bit only depending on
171 * the timer mode).
172 */
173 static uint64_t hpet_calculate_cmp64(HPETTimer *t, uint64_t cur_tick, uint64_t target)
174 {
175 if (t->config & HPET_TN_32BIT) {
176 uint64_t result = deposit64(cur_tick, 0, 32, target);
177 if (result < cur_tick) {
178 result += 0x100000000ULL;
179 }
180 return result;
181 } else {
182 return target;
183 }
184 }
185
186 static uint64_t hpet_next_wrap(uint64_t cur_tick)
187 {
188 return (cur_tick | 0xffffffffU) + 1;
189 }
190
191 static void update_irq(struct HPETTimer *timer, int set)
192 {
193 uint64_t mask;
194 HPETState *s;
195 int route;
196
197 if (timer->tn <= 1 && hpet_in_legacy_mode(timer->state)) {
198 /* if LegacyReplacementRoute bit is set, HPET specification requires
199 * timer0 be routed to IRQ0 in NON-APIC or IRQ2 in the I/O APIC,
200 * timer1 be routed to IRQ8 in NON-APIC or IRQ8 in the I/O APIC.
201 */
202 route = (timer->tn == 0) ? 0 : RTC_ISA_IRQ;
203 } else {
204 route = timer_int_route(timer);
205 }
206 s = timer->state;
207 mask = 1 << timer->tn;
208
209 if (set && (timer->config & HPET_TN_TYPE_LEVEL)) {
210 /*
211 * If HPET_TN_ENABLE bit is 0, "the timer will still operate and
212 * generate appropriate status bits, but will not cause an interrupt"
213 */
214 s->isr |= mask;
215 } else {
216 s->isr &= ~mask;
217 }
218
219 if (set && timer_enabled(timer) && hpet_enabled(s)) {
220 if (timer_fsb_route(timer)) {
221 address_space_stl_le(&address_space_memory, timer->fsb >> 32,
222 timer->fsb & 0xffffffff, MEMTXATTRS_UNSPECIFIED,
223 NULL);
224 } else if (timer->config & HPET_TN_TYPE_LEVEL) {
225 BQL_LOCK_GUARD();
226 qemu_irq_raise(s->irqs[route]);
227 } else {
228 BQL_LOCK_GUARD();
229 qemu_irq_pulse(s->irqs[route]);
230 }
231 } else {
232 if (!timer_fsb_route(timer)) {
233 BQL_LOCK_GUARD();
234 qemu_irq_lower(s->irqs[route]);
235 }
236 }
237 }
238
239 static int hpet_pre_save(void *opaque)
240 {
241 HPETState *s = opaque;
242
243 /* save current counter value */
244 if (hpet_enabled(s)) {
245 s->hpet_counter = hpet_get_ticks(s);
246 }
247
248 /*
249 * The number of timers must match on source and destination, but it was
250 * also added to the migration stream. Check that it matches the value
251 * that was configured.
252 */
253 s->num_timers_save = s->num_timers;
254 return 0;
255 }
256
257 static bool hpet_validate_num_timers(void *opaque, int version_id)
258 {
259 HPETState *s = opaque;
260
261 return s->num_timers == s->num_timers_save;
262 }
263
264 static int hpet_post_load(void *opaque, int version_id)
265 {
266 HPETState *s = opaque;
267 int i;
268
269 for (i = 0; i < s->num_timers; i++) {
270 HPETTimer *t = &s->timer[i];
271 t->cmp64 = hpet_calculate_cmp64(t, s->hpet_counter, t->cmp);
272 t->last = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - NANOSECONDS_PER_SECOND;
273 }
274
275 return 0;
276 }
277
278 static bool hpet_offset_needed(void *opaque)
279 {
280 HPETState *s = opaque;
281
282 return hpet_enabled(s);
283 }
284
285 static bool hpet_rtc_irq_level_needed(void *opaque)
286 {
287 HPETState *s = opaque;
288
289 return s->rtc_irq_level != 0;
290 }
291
292 static const VMStateDescription vmstate_hpet_rtc_irq_level = {
293 .name = "hpet/rtc_irq_level",
294 .version_id = 1,
295 .minimum_version_id = 1,
296 .needed = hpet_rtc_irq_level_needed,
297 .fields = (const VMStateField[]) {
298 VMSTATE_UINT8(rtc_irq_level, HPETState),
299 VMSTATE_END_OF_LIST()
300 }
301 };
302
303 static const VMStateDescription vmstate_hpet_offset = {
304 .name = "hpet/offset",
305 .version_id = 1,
306 .minimum_version_id = 1,
307 .needed = hpet_offset_needed,
308 .fields = (const VMStateField[]) {
309 VMSTATE_UINT64(hpet_offset, HPETState),
310 VMSTATE_END_OF_LIST()
311 }
312 };
313
314 static const VMStateDescription vmstate_hpet_timer = {
315 .name = "hpet_timer",
316 .version_id = 1,
317 .minimum_version_id = 1,
318 .fields = (const VMStateField[]) {
319 VMSTATE_UINT8(tn, HPETTimer),
320 VMSTATE_UINT64(config, HPETTimer),
321 VMSTATE_UINT64(cmp, HPETTimer),
322 VMSTATE_UINT64(fsb, HPETTimer),
323 VMSTATE_UINT64(period, HPETTimer),
324 VMSTATE_UINT8(wrap_flag, HPETTimer),
325 VMSTATE_TIMER_PTR(qemu_timer, HPETTimer),
326 VMSTATE_END_OF_LIST()
327 }
328 };
329
330 static const VMStateDescription vmstate_hpet = {
331 .name = "hpet",
332 .version_id = 2,
333 .minimum_version_id = 2,
334 .pre_save = hpet_pre_save,
335 .post_load = hpet_post_load,
336 .fields = (const VMStateField[]) {
337 VMSTATE_UINT64(config, HPETState),
338 VMSTATE_UINT64(isr, HPETState),
339 VMSTATE_UINT64(hpet_counter, HPETState),
340 VMSTATE_UINT8(num_timers_save, HPETState),
341 VMSTATE_VALIDATE("num_timers must match", hpet_validate_num_timers),
342 VMSTATE_STRUCT_VARRAY_UINT8(timer, HPETState, num_timers_save, 0,
343 vmstate_hpet_timer, HPETTimer),
344 VMSTATE_END_OF_LIST()
345 },
346 .subsections = (const VMStateDescription * const []) {
347 &vmstate_hpet_rtc_irq_level,
348 &vmstate_hpet_offset,
349 NULL
350 }
351 };
352
353 static void hpet_arm(HPETTimer *t, uint64_t tick)
354 {
355 uint64_t ns = hpet_get_ns(t->state, tick);
356
357 /* Clamp period to reasonable min value (1 us) */
358 if (timer_is_periodic(t) && ns - t->last < 1000) {
359 ns = t->last + 1000;
360 }
361
362 t->last = ns;
363 timer_mod(t->qemu_timer, ns);
364 }
365
366 /*
367 * timer expiration callback
368 */
369 static void hpet_timer(void *opaque)
370 {
371 HPETTimer *t = opaque;
372 uint64_t period = t->period;
373 uint64_t cur_tick = hpet_get_ticks(t->state);
374
375 if (timer_is_periodic(t) && period != 0) {
376 while (hpet_time_after(cur_tick, t->cmp64)) {
377 t->cmp64 += period;
378 }
379 if (t->config & HPET_TN_32BIT) {
380 t->cmp = (uint32_t)t->cmp64;
381 } else {
382 t->cmp = t->cmp64;
383 }
384 hpet_arm(t, t->cmp64);
385 } else if (t->wrap_flag) {
386 t->wrap_flag = 0;
387 hpet_arm(t, t->cmp64);
388 }
389 update_irq(t, 1);
390 }
391
392 static void hpet_set_timer(HPETTimer *t)
393 {
394 uint64_t cur_tick = hpet_get_ticks(t->state);
395
396 t->wrap_flag = 0;
397 t->cmp64 = hpet_calculate_cmp64(t, cur_tick, t->cmp);
398 if (t->config & HPET_TN_32BIT) {
399
400 /* hpet spec says in one-shot 32-bit mode, generate an interrupt when
401 * counter wraps in addition to an interrupt with comparator match.
402 */
403 if (!timer_is_periodic(t) && t->cmp64 > hpet_next_wrap(cur_tick)) {
404 t->wrap_flag = 1;
405 hpet_arm(t, hpet_next_wrap(cur_tick));
406 return;
407 }
408 }
409 hpet_arm(t, t->cmp64);
410 }
411
412 static void hpet_del_timer(HPETTimer *t)
413 {
414 HPETState *s = t->state;
415 timer_del(t->qemu_timer);
416
417 if (s->isr & (1 << t->tn)) {
418 /* For level-triggered interrupt, this leaves ISR set but lowers irq. */
419 update_irq(t, 1);
420 }
421 }
422
423 static uint64_t hpet_ram_read(void *opaque, hwaddr addr,
424 unsigned size)
425 {
426 HPETState *s = opaque;
427 int shift = (addr & 4) * 8;
428 uint64_t cur_tick;
429
430 trace_hpet_ram_read(addr);
431 addr &= ~4;
432
433 if (addr == HPET_COUNTER) {
434 unsigned version;
435
436 /*
437 * Write update is rare, so busywait here is unlikely to happen
438 */
439 do {
440 version = seqlock_read_begin(&s->state_version);
441 if (unlikely(!hpet_enabled(s))) {
442 cur_tick = s->hpet_counter;
443 } else {
444 cur_tick = hpet_get_ticks(s);
445 }
446 } while (seqlock_read_retry(&s->state_version, version));
447 trace_hpet_ram_read_reading_counter(addr & 4, cur_tick);
448 return cur_tick >> shift;
449 }
450
451 QEMU_LOCK_GUARD(&s->lock);
452 /*address range of all global regs*/
453 if (addr <= 0xff) {
454 switch (addr) {
455 case HPET_ID: // including HPET_PERIOD
456 return s->capability >> shift;
457 case HPET_CFG:
458 return s->config >> shift;
459 case HPET_STATUS:
460 return s->isr >> shift;
461 default:
462 trace_hpet_ram_read_invalid();
463 break;
464 }
465 } else {
466 uint8_t timer_id = (addr - 0x100) / 0x20;
467 HPETTimer *timer;
468
469 if (timer_id >= s->num_timers) {
470 trace_hpet_timer_id_out_of_range(timer_id);
471 return 0;
472 }
473
474 timer = &s->timer[timer_id];
475 switch (addr & 0x1f) {
476 case HPET_TN_CFG: // including interrupt capabilities
477 return timer->config >> shift;
478 case HPET_TN_CMP: // comparator register
479 return timer->cmp >> shift;
480 case HPET_TN_ROUTE:
481 return timer->fsb >> shift;
482 default:
483 trace_hpet_ram_read_invalid();
484 break;
485 }
486 }
487 return 0;
488 }
489
490 static void hpet_ram_write(void *opaque, hwaddr addr,
491 uint64_t value, unsigned size)
492 {
493 int i;
494 HPETState *s = opaque;
495 int shift = (addr & 4) * 8;
496 int len = MIN(size * 8, 64 - shift);
497 uint64_t old_val, new_val, cleared;
498
499 QEMU_LOCK_GUARD(&s->lock);
500 trace_hpet_ram_write(addr, value);
501 addr &= ~4;
502
503 /*address range of all global regs*/
504 if (addr <= 0xff) {
505 switch (addr) {
506 case HPET_ID:
507 return;
508 case HPET_CFG:
509 old_val = s->config;
510 new_val = deposit64(old_val, shift, len, value);
511 new_val = hpet_fixup_reg(new_val, old_val, HPET_CFG_WRITE_MASK);
512 seqlock_write_begin(&s->state_version);
513 s->config = new_val;
514 if (activating_bit(old_val, new_val, HPET_CFG_ENABLE)) {
515 /* Enable main counter and interrupt generation. */
516 s->hpet_offset =
517 ticks_to_ns(s->hpet_counter) - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
518 for (i = 0; i < s->num_timers; i++) {
519 if (timer_enabled(&s->timer[i]) && (s->isr & (1 << i))) {
520 update_irq(&s->timer[i], 1);
521 }
522 hpet_set_timer(&s->timer[i]);
523 }
524 } else if (deactivating_bit(old_val, new_val, HPET_CFG_ENABLE)) {
525 /* Halt main counter and disable interrupt generation. */
526 s->hpet_counter = hpet_get_ticks(s);
527 for (i = 0; i < s->num_timers; i++) {
528 hpet_del_timer(&s->timer[i]);
529 }
530 }
531 seqlock_write_end(&s->state_version);
532
533 /* i8254 and RTC output pins are disabled
534 * when HPET is in legacy mode */
535 if (activating_bit(old_val, new_val, HPET_CFG_LEGACY)) {
536 BQL_LOCK_GUARD();
537 qemu_set_irq(s->pit_enabled, 0);
538 qemu_irq_lower(s->irqs[0]);
539 qemu_irq_lower(s->irqs[RTC_ISA_IRQ]);
540 } else if (deactivating_bit(old_val, new_val, HPET_CFG_LEGACY)) {
541 BQL_LOCK_GUARD();
542 qemu_irq_lower(s->irqs[0]);
543 qemu_set_irq(s->pit_enabled, 1);
544 qemu_set_irq(s->irqs[RTC_ISA_IRQ], s->rtc_irq_level);
545 }
546 break;
547 case HPET_STATUS:
548 new_val = value << shift;
549 cleared = new_val & s->isr;
550 for (i = 0; i < s->num_timers; i++) {
551 if (cleared & (1 << i)) {
552 update_irq(&s->timer[i], 0);
553 }
554 }
555 break;
556 case HPET_COUNTER:
557 if (hpet_enabled(s)) {
558 trace_hpet_ram_write_counter_write_while_enabled();
559 }
560 s->hpet_counter = deposit64(s->hpet_counter, shift, len, value);
561 break;
562 default:
563 trace_hpet_ram_write_invalid();
564 break;
565 }
566 } else {
567 uint8_t timer_id = (addr - 0x100) / 0x20;
568 HPETTimer *timer;
569
570 trace_hpet_ram_write_timer_id(timer_id);
571 if (timer_id >= s->num_timers) {
572 trace_hpet_timer_id_out_of_range(timer_id);
573 return;
574 }
575
576 timer = &s->timer[timer_id];
577 switch (addr & 0x18) {
578 case HPET_TN_CFG:
579 trace_hpet_ram_write_tn_cfg(addr & 4);
580 old_val = timer->config;
581 new_val = deposit64(old_val, shift, len, value);
582 new_val = hpet_fixup_reg(new_val, old_val, HPET_TN_CFG_WRITE_MASK);
583 if (deactivating_bit(old_val, new_val, HPET_TN_TYPE_LEVEL)) {
584 /*
585 * Do this before changing timer->config; otherwise, if
586 * HPET_TN_FSB is set, update_irq will not lower the qemu_irq.
587 */
588 update_irq(timer, 0);
589 }
590 timer->config = new_val;
591 if (activating_bit(old_val, new_val, HPET_TN_ENABLE)
592 && (s->isr & (1 << timer_id))) {
593 update_irq(timer, 1);
594 }
595 if (new_val & HPET_TN_32BIT) {
596 timer->cmp = (uint32_t)timer->cmp;
597 timer->period = (uint32_t)timer->period;
598 }
599 if (hpet_enabled(s)) {
600 hpet_set_timer(timer);
601 }
602 break;
603 case HPET_TN_CMP: // comparator register
604 if (timer->config & HPET_TN_32BIT) {
605 /* High 32-bits are zero, leave them untouched. */
606 if (shift) {
607 trace_hpet_ram_write_invalid_tn_cmp();
608 break;
609 }
610 len = 64;
611 value = (uint32_t) value;
612 }
613 trace_hpet_ram_write_tn_cmp(addr & 4);
614 if (!timer_is_periodic(timer)
615 || (timer->config & HPET_TN_SETVAL)) {
616 timer->cmp = deposit64(timer->cmp, shift, len, value);
617 }
618 if (timer_is_periodic(timer)) {
619 timer->period = deposit64(timer->period, shift, len, value);
620 }
621 timer->config &= ~HPET_TN_SETVAL;
622 if (hpet_enabled(s)) {
623 hpet_set_timer(timer);
624 }
625 break;
626 case HPET_TN_ROUTE:
627 timer->fsb = deposit64(timer->fsb, shift, len, value);
628 break;
629 default:
630 trace_hpet_ram_write_invalid();
631 break;
632 }
633 return;
634 }
635 }
636
637 static const MemoryRegionOps hpet_ram_ops = {
638 .read = hpet_ram_read,
639 .write = hpet_ram_write,
640 .valid = {
641 .min_access_size = 4,
642 .max_access_size = 8,
643 },
644 .impl = {
645 .min_access_size = 4,
646 .max_access_size = 8,
647 },
648 .endianness = DEVICE_LITTLE_ENDIAN,
649 };
650
651 static void hpet_reset(DeviceState *d)
652 {
653 HPETState *s = HPET(d);
654 SysBusDevice *sbd = SYS_BUS_DEVICE(d);
655 int i;
656
657 for (i = 0; i < s->num_timers; i++) {
658 HPETTimer *timer = &s->timer[i];
659
660 hpet_del_timer(timer);
661 timer->cmp = ~0ULL;
662 timer->config = HPET_TN_PERIODIC_CAP | HPET_TN_SIZE_CAP;
663 if (s->flags & (1 << HPET_MSI_SUPPORT)) {
664 timer->config |= HPET_TN_FSB_CAP;
665 }
666 /* advertise availability of ioapic int */
667 timer->config |= (uint64_t)s->intcap << 32;
668 timer->period = 0ULL;
669 timer->wrap_flag = 0;
670 }
671
672 qemu_set_irq(s->pit_enabled, 1);
673 s->hpet_counter = 0ULL;
674 s->hpet_offset = 0ULL;
675 s->config = 0ULL;
676 hpet_fw_cfg.hpet[s->hpet_id].event_timer_block_id = (uint32_t)s->capability;
677 hpet_fw_cfg.hpet[s->hpet_id].address = sbd->mmio[0].addr;
678
679 /* to document that the RTC lowers its output on reset as well */
680 s->rtc_irq_level = 0;
681 }
682
683 static void hpet_handle_legacy_irq(void *opaque, int n, int level)
684 {
685 HPETState *s = HPET(opaque);
686
687 if (n == HPET_LEGACY_PIT_INT) {
688 if (!hpet_in_legacy_mode(s)) {
689 BQL_LOCK_GUARD();
690 qemu_set_irq(s->irqs[0], level);
691 }
692 } else {
693 s->rtc_irq_level = level;
694 if (!hpet_in_legacy_mode(s)) {
695 BQL_LOCK_GUARD();
696 qemu_set_irq(s->irqs[RTC_ISA_IRQ], level);
697 }
698 }
699 }
700
701 static void hpet_init(Object *obj)
702 {
703 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
704 HPETState *s = HPET(obj);
705
706 qemu_mutex_init(&s->lock);
707 seqlock_init(&s->state_version);
708 /* HPET Area */
709 memory_region_init_io(&s->iomem, obj, &hpet_ram_ops, s, "hpet", HPET_LEN);
710 memory_region_enable_lockless_io(&s->iomem);
711 sysbus_init_mmio(sbd, &s->iomem);
712 }
713
714 static void hpet_realize(DeviceState *dev, Error **errp)
715 {
716 SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
717 HPETState *s = HPET(dev);
718 int i;
719 HPETTimer *timer;
720
721 if (s->num_timers < HPET_MIN_TIMERS || s->num_timers > HPET_MAX_TIMERS) {
722 error_setg(errp, "hpet.num_timers must be between %d and %d",
723 HPET_MIN_TIMERS, HPET_MAX_TIMERS);
724 return;
725 }
726 if (!s->intcap) {
727 error_setg(errp, "hpet.hpet-intcap not initialized");
728 return;
729 }
730 if (hpet_fw_cfg.count == UINT8_MAX) {
731 /* first instance */
732 hpet_fw_cfg.count = 0;
733 }
734
735 if (hpet_fw_cfg.count == 8) {
736 error_setg(errp, "Only 8 instances of HPET are allowed");
737 return;
738 }
739
740 s->hpet_id = hpet_fw_cfg.count++;
741
742 for (i = 0; i < HPET_NUM_IRQ_ROUTES; i++) {
743 sysbus_init_irq(sbd, &s->irqs[i]);
744 }
745
746 for (i = 0; i < HPET_MAX_TIMERS; i++) {
747 timer = &s->timer[i];
748 timer->qemu_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, hpet_timer, timer);
749 timer->tn = i;
750 timer->state = s;
751 }
752
753 /* 64-bit General Capabilities and ID Register; LegacyReplacementRoute. */
754 s->capability = 0x8086a001ULL;
755 s->capability |= (s->num_timers - 1) << HPET_ID_NUM_TIM_SHIFT;
756 s->capability |= ((uint64_t)(HPET_CLK_PERIOD * FS_PER_NS) << 32);
757
758 qdev_init_gpio_in(dev, hpet_handle_legacy_irq, 2);
759 qdev_init_gpio_out(dev, &s->pit_enabled, 1);
760 }
761
762 static const Property hpet_device_properties[] = {
763 DEFINE_PROP_UINT8("timers", HPETState, num_timers, HPET_MIN_TIMERS),
764 DEFINE_PROP_BIT("msi", HPETState, flags, HPET_MSI_SUPPORT, false),
765 DEFINE_PROP_UINT32(HPET_INTCAP, HPETState, intcap, 0),
766 };
767
768 static void hpet_device_class_init(ObjectClass *klass, const void *data)
769 {
770 DeviceClass *dc = DEVICE_CLASS(klass);
771
772 dc->realize = hpet_realize;
773 device_class_set_legacy_reset(dc, hpet_reset);
774 dc->vmsd = &vmstate_hpet;
775 device_class_set_props(dc, hpet_device_properties);
776 }
777
778 static const TypeInfo hpet_device_info = {
779 .name = TYPE_HPET,
780 .parent = TYPE_SYS_BUS_DEVICE,
781 .instance_size = sizeof(HPETState),
782 .instance_init = hpet_init,
783 .class_init = hpet_device_class_init,
784 };
785
786 static void hpet_register_types(void)
787 {
788 type_register_static(&hpet_device_info);
789 }
790
791 type_init(hpet_register_types)