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