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