Lines Matching defs:vhpet

27  * $FreeBSD: releng/10.2/sys/amd64/vmm/io/vhpet.c 284900 2015-06-28 03:22:26Z neel $
31 __FBSDID("$FreeBSD: releng/10.2/sys/amd64/vmm/io/vhpet.c 284900 2015-06-28 03:22:26Z neel $");
48 #include "vhpet.h"
52 static MALLOC_DEFINE(M_VHPET, "vhpet", "bhyve virtual hpet");
69 struct vhpet *vhpet;
73 struct vhpet {
97 static void vhpet_start_timer(struct vhpet *vhpet, int n, uint32_t counter,
117 vhpet_counter_enabled(struct vhpet *vhpet)
120 return ((vhpet->config & HPET_CNF_ENABLE) ? true : false);
124 vhpet_timer_msi_enabled(struct vhpet *vhpet, int n)
128 if ((vhpet->timer[n].cap_config & msi_enable) == msi_enable)
135 vhpet_timer_ioapic_pin(struct vhpet *vhpet, int n)
141 if (vhpet_timer_msi_enabled(vhpet, n))
144 return ((vhpet->timer[n].cap_config & HPET_TCNF_INT_ROUTE) >> 9);
148 vhpet_counter(struct vhpet *vhpet, sbintime_t *nowptr)
153 val = vhpet->countbase;
154 if (vhpet_counter_enabled(vhpet)) {
156 delta = now - vhpet->countbase_sbt;
158 "%#lx to %#lx", vhpet->countbase_sbt, now));
159 val += delta / vhpet->freq_sbt;
174 vhpet_timer_clear_isr(struct vhpet *vhpet, int n)
178 if (vhpet->isr & (1 << n)) {
179 pin = vhpet_timer_ioapic_pin(vhpet, n);
180 KASSERT(pin != 0, ("vhpet timer %d irq incorrectly routed", n));
181 vioapic_deassert_irq(vhpet->vm, pin);
182 vhpet->isr &= ~(1 << n);
187 vhpet_periodic_timer(struct vhpet *vhpet, int n)
190 return ((vhpet->timer[n].cap_config & HPET_TCNF_TYPE) != 0);
194 vhpet_timer_interrupt_enabled(struct vhpet *vhpet, int n)
197 return ((vhpet->timer[n].cap_config & HPET_TCNF_INT_ENB) != 0);
201 vhpet_timer_edge_trig(struct vhpet *vhpet, int n)
204 KASSERT(!vhpet_timer_msi_enabled(vhpet, n), ("vhpet_timer_edge_trig: "
207 if ((vhpet->timer[n].cap_config & HPET_TCNF_INT_TYPE) == 0)
214 vhpet_timer_interrupt(struct vhpet *vhpet, int n)
219 if (!vhpet_timer_interrupt_enabled(vhpet, n))
225 if ((vhpet->isr & (1 << n)) != 0) {
226 VM_CTR1(vhpet->vm, "hpet t%d intr is already asserted", n);
230 if (vhpet_timer_msi_enabled(vhpet, n)) {
231 lapic_intr_msi(vhpet->vm, vhpet->timer[n].msireg >> 32,
232 vhpet->timer[n].msireg & 0xffffffff);
236 pin = vhpet_timer_ioapic_pin(vhpet, n);
238 VM_CTR1(vhpet->vm, "hpet t%d intr is not routed to ioapic", n);
242 if (vhpet_timer_edge_trig(vhpet, n)) {
243 vioapic_pulse_irq(vhpet->vm, pin);
245 vhpet->isr |= 1 << n;
246 vioapic_assert_irq(vhpet->vm, pin);
251 vhpet_adjust_compval(struct vhpet *vhpet, int n, uint32_t counter)
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;
273 vhpet->timer[n].compval = compnext;
282 struct vhpet *vhpet;
287 vhpet = arg->vhpet;
289 callout = &vhpet->timer[n].callout;
291 VM_CTR1(vhpet->vm, "hpet t%d fired", n);
293 VHPET_LOCK(vhpet);
303 if (!vhpet_counter_enabled(vhpet))
304 panic("vhpet(%p) callout with counter disabled", vhpet);
306 counter = vhpet_counter(vhpet, &now);
307 vhpet_start_timer(vhpet, n, counter, now);
308 vhpet_timer_interrupt(vhpet, n);
310 VHPET_UNLOCK(vhpet);
315 vhpet_stop_timer(struct vhpet *vhpet, int n, sbintime_t now)
318 VM_CTR1(vhpet->vm, "hpet t%d stopped", n);
319 callout_stop(&vhpet->timer[n].callout);
328 if (vhpet->timer[n].callout_sbt < now) {
329 VM_CTR1(vhpet->vm, "hpet t%d interrupt triggered after "
331 vhpet_timer_interrupt(vhpet, n);
336 vhpet_start_timer(struct vhpet *vhpet, int n, uint32_t counter, sbintime_t now)
340 if (vhpet->timer[n].comprate != 0)
341 vhpet_adjust_compval(vhpet, n, counter);
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);
359 vhpet_start_counting(struct vhpet *vhpet)
363 vhpet->countbase_sbt = sbinuptime();
369 vhpet_start_timer(vhpet, i, vhpet->countbase,
370 vhpet->countbase_sbt);
375 vhpet_stop_counting(struct vhpet *vhpet, uint32_t counter, sbintime_t now)
379 vhpet->countbase = counter;
381 vhpet_stop_timer(vhpet, i, now);
393 vhpet_timer_update_config(struct vhpet *vhpet, int n, uint64_t data,
401 if (vhpet_timer_msi_enabled(vhpet, n) ||
402 vhpet_timer_edge_trig(vhpet, n)) {
403 if (vhpet->isr & (1 << n))
404 panic("vhpet timer %d isr should not be asserted", n);
406 old_pin = vhpet_timer_ioapic_pin(vhpet, 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;
426 new_pin = vhpet_timer_ioapic_pin(vhpet, n);
428 VM_CTR3(vhpet->vm, "hpet t%d configured invalid irq %d, "
431 vhpet->timer[n].cap_config &= ~HPET_TCNF_INT_ROUTE;
434 if (!vhpet_periodic_timer(vhpet, n))
435 vhpet->timer[n].comprate = 0;
446 if (vhpet->isr & (1 << n)) {
449 if (!vhpet_timer_interrupt_enabled(vhpet, n))
451 else if (vhpet_timer_msi_enabled(vhpet, n))
453 else if (vhpet_timer_edge_trig(vhpet, n))
455 else if (vhpet_timer_ioapic_pin(vhpet, n) != old_pin)
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);
473 struct vhpet *vhpet;
479 vhpet = vm_hpet(vm);
482 VHPET_LOCK(vhpet);
499 VM_CTR2(vhpet->vm, "hpet invalid mmio write: "
506 VM_CTR2(vhpet->vm, "hpet invalid mmio write: "
518 nowptr = vhpet_counter_enabled(vhpet) ? &now : NULL;
519 counter = vhpet_counter(vhpet, nowptr);
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) {
530 if (vhpet_counter_enabled(vhpet)) {
531 vhpet_start_counting(vhpet);
532 VM_CTR0(vhpet->vm, "hpet enabled");
534 vhpet_stop_counting(vhpet, counter, now);
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);
546 vhpet_timer_clear_isr(vhpet, i);
554 val64 = vhpet_counter(vhpet, NULL);
556 vhpet->countbase = val64;
557 if (vhpet_counter_enabled(vhpet))
558 vhpet_start_counting(vhpet);
565 vhpet_timer_update_config(vhpet, i, data, mask);
571 old_compval = vhpet->timer[i].compval;
572 old_comprate = vhpet->timer[i].comprate;
573 if (vhpet_periodic_timer(vhpet, i)) {
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) {
599 if (vhpet_counter_enabled(vhpet)) {
600 counter = vhpet_counter(vhpet, &now);
601 vhpet_start_timer(vhpet, i, counter,
610 update_register(&vhpet->timer[i].msireg, data, mask);
615 VHPET_UNLOCK(vhpet);
624 struct vhpet *vhpet;
627 vhpet = vm_hpet(vm);
630 VHPET_LOCK(vhpet);
634 VM_CTR2(vhpet->vm, "hpet invalid mmio read: "
642 VM_CTR2(vhpet->vm, "hpet invalid mmio read: "
654 data = vhpet->config;
659 data = vhpet->isr;
664 data = vhpet_counter(vhpet, NULL);
671 data = vhpet->timer[i].cap_config;
677 data = vhpet->timer[i].compval;
683 data = vhpet->timer[i].msireg;
691 VHPET_UNLOCK(vhpet);
701 struct vhpet *
705 struct vhpet *vhpet;
710 vhpet = malloc(sizeof(struct vhpet), M_VHPET, M_WAITOK | M_ZERO);
711 vhpet->vm = vm;
712 mtx_init(&vhpet->mtx, "vhpet lock", NULL, MTX_DEF);
715 vhpet->freq_sbt = bttosbt(bt);
727 vhpet->timer[i].cap_config = allowed_irqs << 32;
728 vhpet->timer[i].cap_config |= HPET_TCAP_PER_INT;
729 vhpet->timer[i].cap_config |= HPET_TCAP_FSB_INT_DEL;
731 vhpet->timer[i].compval = 0xffffffff;
732 callout_init(&vhpet->timer[i].callout, 1);
734 arg = &vhpet->timer[i].arg;
735 arg->vhpet = vhpet;
739 return (vhpet);
743 vhpet_cleanup(struct vhpet *vhpet)
748 callout_drain(&vhpet->timer[i].callout);
750 free(vhpet, M_VHPET);