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