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