Lines Matching +full:timer +full:-

1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
57 /* Timer N Configuration and Capabilities Register */
91 } timer[VHPET_NUM_TIMERS]; member
94 #define VHPET_LOCK(vhp) mtx_lock(&((vhp)->mtx))
95 #define VHPET_UNLOCK(vhp) mtx_unlock(&((vhp)->mtx))
106 cap |= (VHPET_NUM_TIMERS - 1) << 8; /* number of timers */ in vhpet_capabilities()
108 cap &= ~HPET_CAP_COUNT_SIZE; /* 32-bit timer */ in vhpet_capabilities()
120 return ((vhpet->config & HPET_CNF_ENABLE) ? true : false); in vhpet_counter_enabled()
128 if ((vhpet->timer[n].cap_config & msi_enable) == msi_enable) in vhpet_timer_msi_enabled()
138 * If the timer is configured to use MSI then treat it as if the in vhpet_timer_ioapic_pin()
139 * timer is not connected to the ioapic. in vhpet_timer_ioapic_pin()
144 return ((vhpet->timer[n].cap_config & HPET_TCNF_INT_ROUTE) >> 9); in vhpet_timer_ioapic_pin()
153 val = vhpet->countbase; in vhpet_counter()
156 delta = now - vhpet->countbase_sbt; in vhpet_counter()
158 "%#lx to %#lx", vhpet->countbase_sbt, now)); in vhpet_counter()
159 val += delta / vhpet->freq_sbt; in vhpet_counter()
178 if (vhpet->isr & (1 << n)) { in vhpet_timer_clear_isr()
180 KASSERT(pin != 0, ("vhpet timer %d irq incorrectly routed", n)); in vhpet_timer_clear_isr()
181 vioapic_deassert_irq(vhpet->vm, pin); in vhpet_timer_clear_isr()
182 vhpet->isr &= ~(1 << n); in vhpet_timer_clear_isr()
190 return ((vhpet->timer[n].cap_config & HPET_TCNF_TYPE) != 0); in vhpet_periodic_timer()
197 return ((vhpet->timer[n].cap_config & HPET_TCNF_INT_ENB) != 0); in vhpet_timer_interrupt_enabled()
205 "timer %d is using MSI", n)); in vhpet_timer_edge_trig()
207 if ((vhpet->timer[n].cap_config & HPET_TCNF_INT_TYPE) == 0) in vhpet_timer_edge_trig()
218 /* If interrupts are not enabled for this timer then just return. */ in vhpet_timer_interrupt()
225 if ((vhpet->isr & (1 << n)) != 0) { in vhpet_timer_interrupt()
226 VM_CTR1(vhpet->vm, "hpet t%d intr is already asserted", n); in vhpet_timer_interrupt()
231 lapic_intr_msi(vhpet->vm, vhpet->timer[n].msireg >> 32, in vhpet_timer_interrupt()
232 vhpet->timer[n].msireg & 0xffffffff); in vhpet_timer_interrupt()
238 VM_CTR1(vhpet->vm, "hpet t%d intr is not routed to ioapic", n); in vhpet_timer_interrupt()
243 vioapic_pulse_irq(vhpet->vm, pin); in vhpet_timer_interrupt()
245 vhpet->isr |= 1 << n; in vhpet_timer_interrupt()
246 vioapic_assert_irq(vhpet->vm, pin); in vhpet_timer_interrupt()
255 KASSERT(vhpet->timer[n].comprate != 0, ("hpet t%d is not periodic", n)); in vhpet_adjust_compval()
257 compval = vhpet->timer[n].compval; in vhpet_adjust_compval()
258 comprate = vhpet->timer[n].comprate; in vhpet_adjust_compval()
271 compnext = compval + ((counter - compval) / comprate + 1) * comprate; in vhpet_adjust_compval()
273 vhpet->timer[n].compval = compnext; in vhpet_adjust_compval()
287 vhpet = arg->vhpet; in vhpet_handler()
288 n = arg->timer_num; in vhpet_handler()
289 callout = &vhpet->timer[n].callout; in vhpet_handler()
291 VM_CTR1(vhpet->vm, "hpet t%d fired", n); in vhpet_handler()
318 VM_CTR1(vhpet->vm, "hpet t%d stopped", n); in vhpet_stop_timer()
319 callout_stop(&vhpet->timer[n].callout); in vhpet_stop_timer()
323 * had a chance to execute yet then trigger the timer interrupt in vhpet_stop_timer()
324 * here. Failing to do so will result in a missed timer interrupt in vhpet_stop_timer()
325 * in the guest. This is especially bad in one-shot mode because in vhpet_stop_timer()
328 if (vhpet->timer[n].callout_sbt < now) { in vhpet_stop_timer()
329 VM_CTR1(vhpet->vm, "hpet t%d interrupt triggered after " in vhpet_stop_timer()
330 "stopping timer", n); in vhpet_stop_timer()
340 if (vhpet->timer[n].comprate != 0) in vhpet_start_timer()
344 * In one-shot mode it is the guest's responsibility to make in vhpet_start_timer()
346 * hardware doesn't have any belt-and-suspenders to deal with in vhpet_start_timer()
351 delta = (vhpet->timer[n].compval - counter) * vhpet->freq_sbt; in vhpet_start_timer()
353 vhpet->timer[n].callout_sbt = now + delta; in vhpet_start_timer()
354 callout_reset_sbt(&vhpet->timer[n].callout, vhpet->timer[n].callout_sbt, in vhpet_start_timer()
355 precision, vhpet_handler, &vhpet->timer[n].arg, C_ABSOLUTE); in vhpet_start_timer()
363 vhpet->countbase_sbt = sbinuptime(); in vhpet_start_counting()
369 vhpet_start_timer(vhpet, i, vhpet->countbase, in vhpet_start_counting()
370 vhpet->countbase_sbt); in vhpet_start_counting()
379 vhpet->countbase = counter; in vhpet_stop_counting()
403 if (vhpet->isr & (1 << n)) in vhpet_timer_update_config()
404 panic("vhpet timer %d isr should not be asserted", n); in vhpet_timer_update_config()
407 oldval = vhpet->timer[n].cap_config; in vhpet_timer_update_config()
417 vhpet->timer[n].cap_config = newval; in vhpet_timer_update_config()
418 VM_CTR2(vhpet->vm, "hpet t%d cap_config set to 0x%016x", n, newval); in vhpet_timer_update_config()
425 allowed_irqs = vhpet->timer[n].cap_config >> 32; in vhpet_timer_update_config()
428 VM_CTR3(vhpet->vm, "hpet t%d configured invalid irq %d, " in vhpet_timer_update_config()
431 vhpet->timer[n].cap_config &= ~HPET_TCNF_INT_ROUTE; in vhpet_timer_update_config()
435 vhpet->timer[n].comprate = 0; in vhpet_timer_update_config()
438 * If the timer's ISR bit is set then clear it in the following cases: in vhpet_timer_update_config()
439 * - interrupt is disabled in vhpet_timer_update_config()
440 * - interrupt type is changed from level to edge or fsb. in vhpet_timer_update_config()
441 * - interrupt routing is changed in vhpet_timer_update_config()
443 * This is to ensure that this timer's level triggered interrupt does in vhpet_timer_update_config()
446 if (vhpet->isr & (1 << n)) { in vhpet_timer_update_config()
447 KASSERT(old_pin != 0, ("timer %d isr asserted to ioapic pin %d", in vhpet_timer_update_config()
461 VM_CTR1(vhpet->vm, "hpet t%d isr cleared due to " in vhpet_timer_update_config()
463 vioapic_deassert_irq(vhpet->vm, old_pin); in vhpet_timer_update_config()
464 vhpet->isr &= ~(1 << n); in vhpet_timer_update_config()
480 offset = gpa - VHPET_BASE; in vhpet_mmio_write()
499 VM_CTR2(vhpet->vm, "hpet invalid mmio write: " in vhpet_mmio_write()
505 if (offset & (size - 1)) { in vhpet_mmio_write()
506 VM_CTR2(vhpet->vm, "hpet invalid mmio write: " in vhpet_mmio_write()
520 oldval = vhpet->config; in vhpet_mmio_write()
521 update_register(&vhpet->config, data, mask); in vhpet_mmio_write()
527 vhpet->config &= ~HPET_CNF_LEG_RT; in vhpet_mmio_write()
529 if ((oldval ^ vhpet->config) & HPET_CNF_ENABLE) { in vhpet_mmio_write()
532 VM_CTR0(vhpet->vm, "hpet enabled"); in vhpet_mmio_write()
535 VM_CTR0(vhpet->vm, "hpet disabled"); in vhpet_mmio_write()
542 isr_clear_mask = vhpet->isr & data; in vhpet_mmio_write()
545 VM_CTR1(vhpet->vm, "hpet t%d isr cleared", i); in vhpet_mmio_write()
553 /* Zero-extend the counter to 64-bits before updating it */ in vhpet_mmio_write()
556 vhpet->countbase = val64; in vhpet_mmio_write()
571 old_compval = vhpet->timer[i].compval; in vhpet_mmio_write()
572 old_comprate = vhpet->timer[i].comprate; in vhpet_mmio_write()
580 val64 = vhpet->timer[i].comprate; in vhpet_mmio_write()
582 vhpet->timer[i].comprate = val64; in vhpet_mmio_write()
583 if ((vhpet->timer[i].cap_config & in vhpet_mmio_write()
585 vhpet->timer[i].compval = val64; in vhpet_mmio_write()
588 KASSERT(vhpet->timer[i].comprate == 0, in vhpet_mmio_write()
589 ("vhpet one-shot timer %d has invalid " in vhpet_mmio_write()
590 "rate %u", i, vhpet->timer[i].comprate)); in vhpet_mmio_write()
591 val64 = vhpet->timer[i].compval; in vhpet_mmio_write()
593 vhpet->timer[i].compval = val64; in vhpet_mmio_write()
595 vhpet->timer[i].cap_config &= ~HPET_TCNF_VAL_SET; in vhpet_mmio_write()
597 if (vhpet->timer[i].compval != old_compval || in vhpet_mmio_write()
598 vhpet->timer[i].comprate != old_comprate) { in vhpet_mmio_write()
610 update_register(&vhpet->timer[i].msireg, data, mask); in vhpet_mmio_write()
628 offset = gpa - VHPET_BASE; in vhpet_mmio_read()
634 VM_CTR2(vhpet->vm, "hpet invalid mmio read: " in vhpet_mmio_read()
641 if (offset & (size - 1)) { in vhpet_mmio_read()
642 VM_CTR2(vhpet->vm, "hpet invalid mmio read: " in vhpet_mmio_read()
654 data = vhpet->config; in vhpet_mmio_read()
659 data = vhpet->isr; in vhpet_mmio_read()
671 data = vhpet->timer[i].cap_config; in vhpet_mmio_read()
677 data = vhpet->timer[i].compval; in vhpet_mmio_read()
683 data = vhpet->timer[i].msireg; in vhpet_mmio_read()
711 vhpet->vm = vm; in vhpet_init()
712 mtx_init(&vhpet->mtx, "vhpet lock", NULL, MTX_DEF); in vhpet_init()
715 vhpet->freq_sbt = bttosbt(bt); in vhpet_init()
719 allowed_irqs = 0xff000000; /* irqs 24-31 */ in vhpet_init()
721 allowed_irqs = 0xf << (pincount - 4); /* 4 upper irqs */ in vhpet_init()
726 * Initialize HPET timer hardware state. in vhpet_init()
729 vhpet->timer[i].cap_config = allowed_irqs << 32; in vhpet_init()
730 vhpet->timer[i].cap_config |= HPET_TCAP_PER_INT; in vhpet_init()
731 vhpet->timer[i].cap_config |= HPET_TCAP_FSB_INT_DEL; in vhpet_init()
733 vhpet->timer[i].compval = 0xffffffff; in vhpet_init()
734 callout_init(&vhpet->timer[i].callout, 1); in vhpet_init()
736 arg = &vhpet->timer[i].arg; in vhpet_init()
737 arg->vhpet = vhpet; in vhpet_init()
738 arg->timer_num = i; in vhpet_init()
750 callout_drain(&vhpet->timer[i].callout); in vhpet_cleanup()
752 mtx_destroy(&vhpet->mtx); in vhpet_cleanup()
760 cap->capabilities = vhpet_capabilities(); in vhpet_getcap()
771 SNAPSHOT_VAR_OR_LEAVE(vhpet->freq_sbt, meta, ret, done); in vhpet_snapshot()
772 SNAPSHOT_VAR_OR_LEAVE(vhpet->config, meta, ret, done); in vhpet_snapshot()
773 SNAPSHOT_VAR_OR_LEAVE(vhpet->isr, meta, ret, done); in vhpet_snapshot()
777 * vhpet->countbase, but rather computed relative to the current system in vhpet_snapshot()
780 if (meta->op == VM_SNAPSHOT_SAVE) in vhpet_snapshot()
783 if (meta->op == VM_SNAPSHOT_RESTORE) in vhpet_snapshot()
784 vhpet->countbase = countbase; in vhpet_snapshot()
786 for (i = 0; i < nitems(vhpet->timer); i++) { in vhpet_snapshot()
787 SNAPSHOT_VAR_OR_LEAVE(vhpet->timer[i].cap_config, in vhpet_snapshot()
789 SNAPSHOT_VAR_OR_LEAVE(vhpet->timer[i].msireg, meta, ret, done); in vhpet_snapshot()
790 SNAPSHOT_VAR_OR_LEAVE(vhpet->timer[i].compval, meta, ret, done); in vhpet_snapshot()
791 SNAPSHOT_VAR_OR_LEAVE(vhpet->timer[i].comprate, meta, ret, done); in vhpet_snapshot()
792 SNAPSHOT_VAR_OR_LEAVE(vhpet->timer[i].callout_sbt, in vhpet_snapshot()