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 "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 = 2, 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(num_timers_save, HPETState), 339 VMSTATE_VALIDATE("num_timers must match", hpet_validate_num_timers), 340 VMSTATE_STRUCT_VARRAY_UINT8(timer, HPETState, num_timers_save, 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 addr &= ~4; 430 431 /*address range of all global regs*/ 432 if (addr <= 0xff) { 433 switch (addr) { 434 case HPET_ID: // including HPET_PERIOD 435 return s->capability >> shift; 436 case HPET_CFG: 437 return s->config >> shift; 438 case HPET_COUNTER: 439 if (hpet_enabled(s)) { 440 cur_tick = hpet_get_ticks(s); 441 } else { 442 cur_tick = s->hpet_counter; 443 } 444 trace_hpet_ram_read_reading_counter(addr & 4, cur_tick); 445 return cur_tick >> shift; 446 case HPET_STATUS: 447 return s->isr >> shift; 448 default: 449 trace_hpet_ram_read_invalid(); 450 break; 451 } 452 } else { 453 uint8_t timer_id = (addr - 0x100) / 0x20; 454 HPETTimer *timer = &s->timer[timer_id]; 455 456 if (timer_id > s->num_timers) { 457 trace_hpet_timer_id_out_of_range(timer_id); 458 return 0; 459 } 460 461 switch (addr & 0x1f) { 462 case HPET_TN_CFG: // including interrupt capabilities 463 return timer->config >> shift; 464 case HPET_TN_CMP: // comparator register 465 return timer->cmp >> shift; 466 case HPET_TN_ROUTE: 467 return timer->fsb >> shift; 468 default: 469 trace_hpet_ram_read_invalid(); 470 break; 471 } 472 } 473 return 0; 474 } 475 476 static void hpet_ram_write(void *opaque, hwaddr addr, 477 uint64_t value, unsigned size) 478 { 479 int i; 480 HPETState *s = opaque; 481 int shift = (addr & 4) * 8; 482 int len = MIN(size * 8, 64 - shift); 483 uint64_t old_val, new_val, cleared; 484 485 trace_hpet_ram_write(addr, value); 486 addr &= ~4; 487 488 /*address range of all global regs*/ 489 if (addr <= 0xff) { 490 switch (addr) { 491 case HPET_ID: 492 return; 493 case HPET_CFG: 494 old_val = s->config; 495 new_val = deposit64(old_val, shift, len, value); 496 new_val = hpet_fixup_reg(new_val, old_val, HPET_CFG_WRITE_MASK); 497 s->config = new_val; 498 if (activating_bit(old_val, new_val, HPET_CFG_ENABLE)) { 499 /* Enable main counter and interrupt generation. */ 500 s->hpet_offset = 501 ticks_to_ns(s->hpet_counter) - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); 502 for (i = 0; i < s->num_timers; i++) { 503 if (timer_enabled(&s->timer[i]) && (s->isr & (1 << i))) { 504 update_irq(&s->timer[i], 1); 505 } 506 hpet_set_timer(&s->timer[i]); 507 } 508 } else if (deactivating_bit(old_val, new_val, HPET_CFG_ENABLE)) { 509 /* Halt main counter and disable interrupt generation. */ 510 s->hpet_counter = hpet_get_ticks(s); 511 for (i = 0; i < s->num_timers; i++) { 512 hpet_del_timer(&s->timer[i]); 513 } 514 } 515 /* i8254 and RTC output pins are disabled 516 * when HPET is in legacy mode */ 517 if (activating_bit(old_val, new_val, HPET_CFG_LEGACY)) { 518 qemu_set_irq(s->pit_enabled, 0); 519 qemu_irq_lower(s->irqs[0]); 520 qemu_irq_lower(s->irqs[RTC_ISA_IRQ]); 521 } else if (deactivating_bit(old_val, new_val, HPET_CFG_LEGACY)) { 522 qemu_irq_lower(s->irqs[0]); 523 qemu_set_irq(s->pit_enabled, 1); 524 qemu_set_irq(s->irqs[RTC_ISA_IRQ], s->rtc_irq_level); 525 } 526 break; 527 case HPET_STATUS: 528 new_val = value << shift; 529 cleared = new_val & s->isr; 530 for (i = 0; i < s->num_timers; i++) { 531 if (cleared & (1 << i)) { 532 update_irq(&s->timer[i], 0); 533 } 534 } 535 break; 536 case HPET_COUNTER: 537 if (hpet_enabled(s)) { 538 trace_hpet_ram_write_counter_write_while_enabled(); 539 } 540 s->hpet_counter = deposit64(s->hpet_counter, shift, len, value); 541 break; 542 default: 543 trace_hpet_ram_write_invalid(); 544 break; 545 } 546 } else { 547 uint8_t timer_id = (addr - 0x100) / 0x20; 548 HPETTimer *timer = &s->timer[timer_id]; 549 550 trace_hpet_ram_write_timer_id(timer_id); 551 if (timer_id > s->num_timers) { 552 trace_hpet_timer_id_out_of_range(timer_id); 553 return; 554 } 555 switch (addr & 0x18) { 556 case HPET_TN_CFG: 557 trace_hpet_ram_write_tn_cfg(addr & 4); 558 old_val = timer->config; 559 new_val = deposit64(old_val, shift, len, value); 560 new_val = hpet_fixup_reg(new_val, old_val, HPET_TN_CFG_WRITE_MASK); 561 if (deactivating_bit(old_val, new_val, HPET_TN_TYPE_LEVEL)) { 562 /* 563 * Do this before changing timer->config; otherwise, if 564 * HPET_TN_FSB is set, update_irq will not lower the qemu_irq. 565 */ 566 update_irq(timer, 0); 567 } 568 timer->config = new_val; 569 if (activating_bit(old_val, new_val, HPET_TN_ENABLE) 570 && (s->isr & (1 << timer_id))) { 571 update_irq(timer, 1); 572 } 573 if (new_val & HPET_TN_32BIT) { 574 timer->cmp = (uint32_t)timer->cmp; 575 timer->period = (uint32_t)timer->period; 576 } 577 if (hpet_enabled(s)) { 578 hpet_set_timer(timer); 579 } 580 break; 581 case HPET_TN_CMP: // comparator register 582 if (timer->config & HPET_TN_32BIT) { 583 /* High 32-bits are zero, leave them untouched. */ 584 if (shift) { 585 trace_hpet_ram_write_invalid_tn_cmp(); 586 break; 587 } 588 len = 64; 589 value = (uint32_t) value; 590 } 591 trace_hpet_ram_write_tn_cmp(addr & 4); 592 if (!timer_is_periodic(timer) 593 || (timer->config & HPET_TN_SETVAL)) { 594 timer->cmp = deposit64(timer->cmp, shift, len, value); 595 } 596 if (timer_is_periodic(timer)) { 597 timer->period = deposit64(timer->period, shift, len, value); 598 } 599 timer->config &= ~HPET_TN_SETVAL; 600 if (hpet_enabled(s)) { 601 hpet_set_timer(timer); 602 } 603 break; 604 case HPET_TN_ROUTE: 605 timer->fsb = deposit64(timer->fsb, shift, len, value); 606 break; 607 default: 608 trace_hpet_ram_write_invalid(); 609 break; 610 } 611 return; 612 } 613 } 614 615 static const MemoryRegionOps hpet_ram_ops = { 616 .read = hpet_ram_read, 617 .write = hpet_ram_write, 618 .valid = { 619 .min_access_size = 4, 620 .max_access_size = 8, 621 }, 622 .impl = { 623 .min_access_size = 4, 624 .max_access_size = 8, 625 }, 626 .endianness = DEVICE_NATIVE_ENDIAN, 627 }; 628 629 static void hpet_reset(DeviceState *d) 630 { 631 HPETState *s = HPET(d); 632 SysBusDevice *sbd = SYS_BUS_DEVICE(d); 633 int i; 634 635 for (i = 0; i < s->num_timers; i++) { 636 HPETTimer *timer = &s->timer[i]; 637 638 hpet_del_timer(timer); 639 timer->cmp = ~0ULL; 640 timer->config = HPET_TN_PERIODIC_CAP | HPET_TN_SIZE_CAP; 641 if (s->flags & (1 << HPET_MSI_SUPPORT)) { 642 timer->config |= HPET_TN_FSB_CAP; 643 } 644 /* advertise availability of ioapic int */ 645 timer->config |= (uint64_t)s->intcap << 32; 646 timer->period = 0ULL; 647 timer->wrap_flag = 0; 648 } 649 650 qemu_set_irq(s->pit_enabled, 1); 651 s->hpet_counter = 0ULL; 652 s->hpet_offset = 0ULL; 653 s->config = 0ULL; 654 hpet_fw_cfg.hpet[s->hpet_id].event_timer_block_id = (uint32_t)s->capability; 655 hpet_fw_cfg.hpet[s->hpet_id].address = sbd->mmio[0].addr; 656 657 /* to document that the RTC lowers its output on reset as well */ 658 s->rtc_irq_level = 0; 659 } 660 661 static void hpet_handle_legacy_irq(void *opaque, int n, int level) 662 { 663 HPETState *s = HPET(opaque); 664 665 if (n == HPET_LEGACY_PIT_INT) { 666 if (!hpet_in_legacy_mode(s)) { 667 qemu_set_irq(s->irqs[0], level); 668 } 669 } else { 670 s->rtc_irq_level = level; 671 if (!hpet_in_legacy_mode(s)) { 672 qemu_set_irq(s->irqs[RTC_ISA_IRQ], level); 673 } 674 } 675 } 676 677 static void hpet_init(Object *obj) 678 { 679 SysBusDevice *sbd = SYS_BUS_DEVICE(obj); 680 HPETState *s = HPET(obj); 681 682 /* HPET Area */ 683 memory_region_init_io(&s->iomem, obj, &hpet_ram_ops, s, "hpet", HPET_LEN); 684 sysbus_init_mmio(sbd, &s->iomem); 685 } 686 687 static void hpet_realize(DeviceState *dev, Error **errp) 688 { 689 SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 690 HPETState *s = HPET(dev); 691 int i; 692 HPETTimer *timer; 693 694 if (s->num_timers < HPET_MIN_TIMERS || s->num_timers > HPET_MAX_TIMERS) { 695 error_setg(errp, "hpet.num_timers must be between %d and %d", 696 HPET_MIN_TIMERS, HPET_MAX_TIMERS); 697 return; 698 } 699 if (!s->intcap) { 700 error_setg(errp, "hpet.hpet-intcap not initialized"); 701 return; 702 } 703 if (hpet_fw_cfg.count == UINT8_MAX) { 704 /* first instance */ 705 hpet_fw_cfg.count = 0; 706 } 707 708 if (hpet_fw_cfg.count == 8) { 709 error_setg(errp, "Only 8 instances of HPET are allowed"); 710 return; 711 } 712 713 s->hpet_id = hpet_fw_cfg.count++; 714 715 for (i = 0; i < HPET_NUM_IRQ_ROUTES; i++) { 716 sysbus_init_irq(sbd, &s->irqs[i]); 717 } 718 719 for (i = 0; i < HPET_MAX_TIMERS; i++) { 720 timer = &s->timer[i]; 721 timer->qemu_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, hpet_timer, timer); 722 timer->tn = i; 723 timer->state = s; 724 } 725 726 /* 64-bit General Capabilities and ID Register; LegacyReplacementRoute. */ 727 s->capability = 0x8086a001ULL; 728 s->capability |= (s->num_timers - 1) << HPET_ID_NUM_TIM_SHIFT; 729 s->capability |= ((uint64_t)(HPET_CLK_PERIOD * FS_PER_NS) << 32); 730 731 qdev_init_gpio_in(dev, hpet_handle_legacy_irq, 2); 732 qdev_init_gpio_out(dev, &s->pit_enabled, 1); 733 } 734 735 static const Property hpet_device_properties[] = { 736 DEFINE_PROP_UINT8("timers", HPETState, num_timers, HPET_MIN_TIMERS), 737 DEFINE_PROP_BIT("msi", HPETState, flags, HPET_MSI_SUPPORT, false), 738 DEFINE_PROP_UINT32(HPET_INTCAP, HPETState, intcap, 0), 739 DEFINE_PROP_BOOL("hpet-offset-saved", HPETState, hpet_offset_saved, true), 740 }; 741 742 static void hpet_device_class_init(ObjectClass *klass, const void *data) 743 { 744 DeviceClass *dc = DEVICE_CLASS(klass); 745 746 dc->realize = hpet_realize; 747 device_class_set_legacy_reset(dc, hpet_reset); 748 dc->vmsd = &vmstate_hpet; 749 device_class_set_props(dc, hpet_device_properties); 750 } 751 752 static const TypeInfo hpet_device_info = { 753 .name = TYPE_HPET, 754 .parent = TYPE_SYS_BUS_DEVICE, 755 .instance_size = sizeof(HPETState), 756 .instance_init = hpet_init, 757 .class_init = hpet_device_class_init, 758 }; 759 760 static void hpet_register_types(void) 761 { 762 type_register_static(&hpet_device_info); 763 } 764 765 type_init(hpet_register_types) 766