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