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 main counter; 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 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 DEFINE_PROP_END_OF_LIST(), 754 }; 755 756 static void hpet_device_class_init(ObjectClass *klass, void *data) 757 { 758 DeviceClass *dc = DEVICE_CLASS(klass); 759 760 dc->realize = hpet_realize; 761 dc->reset = hpet_reset; 762 dc->vmsd = &vmstate_hpet; 763 device_class_set_props(dc, hpet_device_properties); 764 } 765 766 static const TypeInfo hpet_device_info = { 767 .name = TYPE_HPET, 768 .parent = TYPE_SYS_BUS_DEVICE, 769 .instance_size = sizeof(HPETState), 770 .instance_init = hpet_init, 771 .class_init = hpet_device_class_init, 772 }; 773 774 static void hpet_register_types(void) 775 { 776 type_register_static(&hpet_device_info); 777 } 778 779 type_init(hpet_register_types) 780