Lines Matching +full:msi +full:- +full:base +full:- +full:vec

1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
62 #define x2apic(vlapic) (((vlapic)->msr_apicbase & APICBASE_X2APIC) ? 1 : 0)
65 * The 'vlapic->timer_mtx' is used to provide mutual exclusion between the
67 * - timer_freq_bt, timer_period_bt, timer_fire_bt
68 * - timer LVT register
70 #define VLAPIC_TIMER_LOCK(vlapic) mtx_lock_spin(&((vlapic)->timer_mtx))
71 #define VLAPIC_TIMER_UNLOCK(vlapic) mtx_unlock_spin(&((vlapic)->timer_mtx))
72 #define VLAPIC_TIMER_LOCKED(vlapic) mtx_owned(&((vlapic)->timer_mtx))
76 * - arbitrary but chosen to be in the ballpark of contemporary hardware.
77 * - power-of-two to avoid loss of precision when converted to a bintime.
90 return (vlapic->vcpuid);
92 return (vlapic->vcpuid << 24);
112 lapic = vlapic->apic_page;
114 VM_CTR1(vlapic->vm, "ignoring write to DFR in x2apic mode: %#x",
115 lapic->dfr);
116 lapic->dfr = 0;
120 lapic->dfr &= APIC_DFR_MODEL_MASK;
121 lapic->dfr |= APIC_DFR_RESERVED;
123 if ((lapic->dfr & APIC_DFR_MODEL_MASK) == APIC_DFR_MODEL_FLAT)
125 else if ((lapic->dfr & APIC_DFR_MODEL_MASK) == APIC_DFR_MODEL_CLUSTER)
128 VLAPIC_CTR1(vlapic, "DFR in Unknown Model %#x", lapic->dfr);
136 lapic = vlapic->apic_page;
138 /* LDR is read-only in x2apic mode */
141 lapic->ldr);
142 lapic->ldr = x2apic_ldr(vlapic);
144 lapic->ldr &= ~APIC_LDR_RESERVED;
145 VLAPIC_CTR1(vlapic, "vlapic LDR set to %#x", lapic->ldr);
158 lapic = vlapic->apic_page;
159 lapic->id = vlapic_get_id(vlapic);
205 lapic = vlapic->apic_page;
208 if (callout_active(&vlapic->callout)) {
214 if (bintime_cmp(&vlapic->timer_fire_bt, &bt_now, >)) {
215 bt_rem = vlapic->timer_fire_bt;
217 ccr += bt_rem.sec * BT2FREQ(&vlapic->timer_freq_bt);
218 ccr += bt_rem.frac / vlapic->timer_freq_bt.frac;
221 KASSERT(ccr <= lapic->icr_timer, ("vlapic_get_ccr: invalid ccr %#x, "
222 "icr_timer is %#x", ccr, lapic->icr_timer));
224 ccr, lapic->icr_timer);
235 lapic = vlapic->apic_page;
238 divisor = vlapic_timer_divisor(lapic->dcr_timer);
240 lapic->dcr_timer, divisor);
248 FREQ2BT(VLAPIC_BUS_FREQ / divisor, &vlapic->timer_freq_bt);
249 vlapic->timer_period_bt = vlapic->timer_freq_bt;
250 bintime_mul(&vlapic->timer_period_bt, lapic->icr_timer);
260 lapic = vlapic->apic_page;
261 lapic->esr = vlapic->esr_pending;
262 vlapic->esr_pending = 0;
274 lapic = vlapic->apic_page;
275 if (!(lapic->svr & APIC_SVR_ENABLE)) {
289 if (vlapic->ops.set_intr_ready)
290 return ((*vlapic->ops.set_intr_ready)(vlapic, vector, level));
295 irrptr = &lapic->irr0;
299 * Verify that the trigger-mode of the interrupt matches with
302 tmrptr = &lapic->tmr0;
305 "interrupt is %s-triggered", idx / 4, tmrptr[idx],
316 struct LAPIC *lapic = vlapic->apic_page;
321 return (&lapic->lvt_cmci);
323 i = (offset - APIC_OFFSET_TIMER_LVT) >> 2;
324 return ((&lapic->lvt_timer) + i);
358 index = -1;
374 val = atomic_load_acq_32(&vlapic->lvt_last[idx]);
385 lapic = vlapic->apic_page;
390 if (!(lapic->svr & APIC_SVR_ENABLE))
409 atomic_store_rel_32(&vlapic->lvt_last[idx], val);
415 struct LAPIC *lapic = vlapic->apic_page;
417 lapic->lvt_cmci |= APIC_LVT_M;
420 lapic->lvt_timer |= APIC_LVT_M;
423 lapic->lvt_thermal |= APIC_LVT_M;
426 lapic->lvt_pcint |= APIC_LVT_M;
429 lapic->lvt_lint0 |= APIC_LVT_M;
432 lapic->lvt_lint1 |= APIC_LVT_M;
435 lapic->lvt_error |= APIC_LVT_M;
442 uint32_t mode, reg, vec;
444 reg = atomic_load_acq_32(&vlapic->lvt_last[lvt]);
448 vec = reg & APIC_LVT_VECTOR;
453 if (vec < 16) {
458 if (vlapic_set_intr_ready(vlapic, vec, false))
459 vcpu_notify_event(vlapic->vcpu, true);
462 vm_inject_nmi(vlapic->vcpu);
465 vm_inject_extint(vlapic->vcpu);
481 isrptr = &vlapic->apic_page->isr0;
485 for (i = 0; i <= vlapic->isrvec_stk_top; i++)
486 printf("isrvec_stk[%d] = %d\n", i, vlapic->isrvec_stk[i]);
505 isrvec = vlapic->isrvec_stk[vlapic->isrvec_stk_top];
506 tpr = vlapic->apic_page->tpr;
513 if (vlapic->isrvec_stk_top == 0 && isrvec != 0)
520 lastprio = -1;
521 for (i = 1; i <= vlapic->isrvec_stk_top; i++) {
522 curprio = PRIO(vlapic->isrvec_stk[i]);
535 isrptr = &vlapic->apic_page->isr0;
539 if (i > vlapic->isrvec_stk_top ||
540 vlapic->isrvec_stk[i] != vector) {
555 vlapic->apic_page->ppr = ppr;
565 static VMM_STAT(VLAPIC_GRATUITOUS_EOI, "EOI without any in-service interrupt");
570 struct LAPIC *lapic = vlapic->apic_page;
574 isrptr = &lapic->isr0;
575 tmrptr = &lapic->tmr0;
577 for (i = 7; i >= 0; i--) {
580 if (bitpos-- != 0) {
581 if (vlapic->isrvec_stk_top <= 0) {
583 vlapic->isrvec_stk_top);
589 vlapic->isrvec_stk_top--;
592 vioapic_process_eoi(vlapic->vm, vector);
598 vmm_stat_incr(vlapic->vcpu, VLAPIC_GRATUITOUS_EOI, 1);
624 vlapic->esr_pending |= mask;
634 vmm_stat_incr(vlapic->vcpu, VLAPIC_INTR_ERROR, 1);
648 vmm_stat_incr(vlapic->vcpu, VLAPIC_INTR_TIMER, 1);
660 vmm_stat_incr(vlapic->vcpu, VLAPIC_INTR_CMC, 1);
679 vm_inject_extint(vlapic->vcpu);
682 vm_inject_nmi(vlapic->vcpu);
699 vmm_stat_array_incr(vlapic->vcpu, LVTS_TRIGGERRED,
712 callout_reset_sbt_curcpu(&vlapic->callout, t, 0,
726 if (callout_pending(&vlapic->callout)) /* callout was reset */
729 if (!callout_active(&vlapic->callout)) /* callout was stopped */
732 callout_deactivate(&vlapic->callout);
738 KASSERT(bintime_cmp(&btnow, &vlapic->timer_fire_bt, >=),
740 btnow.sec, btnow.frac, vlapic->timer_fire_bt.sec,
741 vlapic->timer_fire_bt.frac));
748 bintime_sub(&bt, &vlapic->timer_fire_bt);
750 rem_sbt = bttosbt(vlapic->timer_period_bt);
751 if (bintime_cmp(&bt, &vlapic->timer_period_bt, <)) {
756 rem_sbt -= bttosbt(bt);
760 * just reset our time base instead of trying to catch
763 vlapic->timer_fire_bt = btnow;
765 "usecs, period is %lu usecs - resetting time base",
767 bttosbt(vlapic->timer_period_bt) / SBT_1US);
770 bintime_add(&vlapic->timer_fire_bt, &vlapic->timer_period_bt);
786 lapic = vlapic->apic_page;
787 icr_timer = lapic->icr_timer;
789 vlapic->timer_period_bt = vlapic->timer_freq_bt;
790 bintime_mul(&vlapic->timer_period_bt, icr_timer);
793 binuptime(&vlapic->timer_fire_bt);
794 bintime_add(&vlapic->timer_fire_bt, &vlapic->timer_period_bt);
796 sbt = bttosbt(vlapic->timer_period_bt);
799 callout_stop(&vlapic->callout);
808 * 'x2apic_dest' specifies whether 'dest' is interpreted as x2APIC (32-bit)
809 * or xAPIC (8-bit) destination field.
841 * In the "Flat Model" the MDA is interpreted as an 8-bit wide
866 dfr = vlapic->apic_page->dfr;
867 ldr = vlapic->apic_page->ldr;
888 * model for this vcpu - skip it.
891 "model %x - cannot deliver interrupt", dfr);
910 struct LAPIC *lapic = vlapic->apic_page;
912 if (lapic->tpr != val) {
914 lapic->tpr, val);
915 lapic->tpr = val;
923 struct LAPIC *lapic = vlapic->apic_page;
925 return (lapic->tpr);
934 vm_inject_gp(vlapic->vcpu);
1038 uint32_t dest, vec, mode, shorthand;
1043 lapic = vlapic->apic_page;
1044 lapic->icr_lo &= ~APIC_DELSTAT_PEND;
1045 icrval = ((uint64_t)lapic->icr_hi << 32) | lapic->icr_lo;
1051 vec = icrval & APIC_VECTOR_MASK;
1056 VLAPIC_CTR2(vlapic, "icrlo 0x%016lx triggered ipi %d", icrval, vec);
1060 vlapic_calcdest(vlapic->vm, &dmask, dest, phys, false, x2apic(vlapic));
1063 CPU_SETOF(vlapic->vcpuid, &dmask);
1066 dmask = vm_active_cpus(vlapic->vm);
1069 dmask = vm_active_cpus(vlapic->vm);
1070 CPU_CLR(vlapic->vcpuid, &dmask);
1092 if (vec < 16) {
1095 VLAPIC_CTR1(vlapic, "Ignoring invalid IPI %d", vec);
1100 vcpu = vm_vcpu(vlapic->vm, i);
1101 lapic_intr_edge(vcpu, vec);
1102 vmm_stat_incr(vlapic->vcpu, VLAPIC_IPI_SEND, 1);
1105 "vlapic sending ipi %d to vcpuid %d", vec, i);
1111 vcpu = vm_vcpu(vlapic->vm, i);
1120 if (!vlapic->ipi_exit) {
1124 i = vm_apicid2vcpuid(vlapic->vm, dest);
1125 if (i >= vm_get_maxcpus(vlapic->vm) ||
1126 i == vlapic->vcpuid)
1141 vmexit = vm_exitinfo(vlapic->vcpu);
1142 vmexit->exitcode = VM_EXITCODE_IPI;
1143 vmexit->u.ipi.mode = mode;
1144 vmexit->u.ipi.vector = vec;
1145 *vm_exitinfo_cpuset(vlapic->vcpu) = ipimask;
1166 uint8_t vec = vme->u.ipi.vector;
1169 switch (vme->u.ipi.mode) {
1181 if (!vlapic->ipi_exit)
1188 * Ignore SIPIs in any state other than wait-for-SIPI
1201 if (!vlapic->ipi_exit) {
1202 vme->exitcode = VM_EXITCODE_SPINUP_AP;
1203 vme->u.spinup_ap.vcpu = CPU_FFS(dmask) - 1;
1204 vme->u.spinup_ap.rip = vec << PAGE_SHIFT;
1218 int vec;
1222 vec = val & 0xff;
1223 lapic_intr_edge(vlapic->vcpu, vec);
1224 vmm_stat_incr(vlapic->vcpu, VLAPIC_IPI_SEND, 1);
1225 vmm_stat_incr(vlapic->vcpu, VLAPIC_IPI_RECV, 1);
1226 VLAPIC_CTR1(vlapic, "vlapic self-ipi %d", vec);
1232 struct LAPIC *lapic = vlapic->apic_page;
1238 if (vlapic->ops.pending_intr)
1239 return ((*vlapic->ops.pending_intr)(vlapic, vecptr));
1241 irrptr = &lapic->irr0;
1243 for (i = 7; i >= 0; i--) {
1248 vector = i * 32 + (bitpos - 1);
1249 if (PRIO(vector) > PRIO(lapic->ppr)) {
1264 struct LAPIC *lapic = vlapic->apic_page;
1268 if (vlapic->ops.intr_accepted)
1269 return ((*vlapic->ops.intr_accepted)(vlapic, vector));
1277 irrptr = &lapic->irr0;
1281 isrptr = &lapic->isr0;
1288 vlapic->isrvec_stk_top++;
1290 stk_top = vlapic->isrvec_stk_top;
1294 vlapic->isrvec_stk[stk_top] = vector;
1303 lapic = vlapic->apic_page;
1305 new = lapic->svr;
1306 old = vlapic->svr_last;
1307 vlapic->svr_last = new;
1316 VLAPIC_CTR0(vlapic, "vlapic is software-disabled");
1318 callout_stop(&vlapic->callout);
1326 VLAPIC_CTR0(vlapic, "vlapic is software-enabled");
1337 struct LAPIC *lapic = vlapic->apic_page;
1368 *data = lapic->id;
1371 *data = lapic->version;
1377 *data = lapic->apr;
1380 *data = lapic->ppr;
1383 *data = lapic->eoi;
1386 *data = lapic->ldr;
1389 *data = lapic->dfr;
1392 *data = lapic->svr;
1395 i = (offset - APIC_OFFSET_ISR0) >> 2;
1396 reg = &lapic->isr0;
1400 i = (offset - APIC_OFFSET_TMR0) >> 2;
1401 reg = &lapic->tmr0;
1405 i = (offset - APIC_OFFSET_IRR0) >> 2;
1406 reg = &lapic->irr0;
1410 *data = lapic->esr;
1413 *data = lapic->icr_lo;
1415 *data |= (uint64_t)lapic->icr_hi << 32;
1418 *data = lapic->icr_hi;
1430 *data = lapic->icr_timer;
1436 *data = lapic->dcr_timer;
1458 struct LAPIC *lapic = vlapic->apic_page;
1491 lapic->id = data;
1501 lapic->ldr = data;
1505 lapic->dfr = data;
1509 lapic->svr = data;
1513 lapic->icr_lo = data;
1515 lapic->icr_hi = data >> 32;
1519 lapic->icr_hi = data;
1528 lapic->icr_timer = data;
1533 lapic->dcr_timer = data;
1567 lapic = vlapic->apic_page;
1570 lapic->id = vlapic_get_id(vlapic);
1571 lapic->version = VLAPIC_VERSION;
1572 lapic->version |= (VLAPIC_MAXLVT_INDEX << MAXLVTSHIFT);
1573 lapic->dfr = 0xffffffff;
1574 lapic->svr = APIC_SVR_VECTOR;
1578 lapic->dcr_timer = 0;
1581 vlapic->svr_last = lapic->svr;
1587 KASSERT(vlapic->vm != NULL, ("vlapic_init: vm is not initialized"));
1588 KASSERT(vlapic->vcpuid >= 0 &&
1589 vlapic->vcpuid < vm_get_maxcpus(vlapic->vm),
1591 KASSERT(vlapic->apic_page != NULL, ("vlapic_init: apic_page is not "
1601 mtx_init(&vlapic->timer_mtx, "vlapic timer mtx", NULL, MTX_SPIN);
1602 callout_init(&vlapic->callout, 1);
1604 vlapic->msr_apicbase = DEFAULT_APIC_BASE | APICBASE_ENABLED;
1606 if (vlapic->vcpuid == 0)
1607 vlapic->msr_apicbase |= APICBASE_BSP;
1609 vlapic->ipi_exit = false;
1618 callout_drain(&vlapic->callout);
1619 mtx_destroy(&vlapic->timer_mtx);
1626 return (vlapic->msr_apicbase);
1633 if (vlapic->msr_apicbase != new) {
1635 "not supported", vlapic->msr_apicbase, new);
1636 return (-1);
1651 vlapic->msr_apicbase &= ~APICBASE_X2APIC;
1653 vlapic->msr_apicbase |= APICBASE_X2APIC;
1656 * Reset the local APIC registers whose values are mode-dependent.
1661 lapic = vlapic->apic_page;
1662 lapic->id = vlapic_get_id(vlapic);
1664 lapic->ldr = x2apic_ldr(vlapic);
1665 lapic->dfr = 0;
1667 lapic->ldr = 0;
1668 lapic->dfr = 0xffffffff;
1672 if (vlapic->ops.enable_x2apic_mode)
1673 (*vlapic->ops.enable_x2apic_mode)(vlapic);
1679 int delmode, int vec)
1696 * all interrupts originating from the ioapic or MSI specify the
1706 lapic_set_intr(vcpu, vec, level);
1723 if (vlapic->ops.post_intr)
1724 (*vlapic->ops.post_intr)(vlapic, hostcpu);
1732 struct LAPIC *lapic = vlapic->apic_page;
1734 if ((vlapic->msr_apicbase & APICBASE_ENABLED) != 0 &&
1735 (lapic->svr & APIC_SVR_ENABLE) != 0)
1748 lapic = vlapic->apic_page;
1749 tmrptr = &lapic->tmr0;
1757 if (vlapic->ops.set_tmr != NULL)
1758 (*vlapic->ops.set_tmr)(vlapic, vector, level);
1766 VLAPIC_CTR0(vlapic, "vlapic resetting all vectors to edge-triggered");
1785 VLAPIC_CTR1(vlapic, "Ignoring level trigger-mode for "
1786 "delivery-mode %d", delmode);
1791 vlapic_calcdest(vlapic->vm, &dmask, dest, phys, lowprio, false);
1793 if (!CPU_ISSET(vlapic->vcpuid, &dmask))
1796 VLAPIC_CTR1(vlapic, "vector %d set to level-triggered", vector);
1812 bt = vlapic->timer_freq_bt;
1816 binuptime(&vlapic->timer_fire_bt);
1817 bintime_add(&vlapic->timer_fire_bt, &bt);
1824 binuptime(&vlapic->timer_fire_bt);
1825 bintime_add(&vlapic->timer_fire_bt,
1826 &vlapic->timer_period_bt);
1827 sbt = bttosbt(vlapic->timer_period_bt);
1829 callout_stop(&vlapic->callout);
1859 lapic = vlapic->apic_page;
1862 SNAPSHOT_VAR_OR_LEAVE(vlapic->esr_pending, meta, ret, done);
1864 SNAPSHOT_VAR_OR_LEAVE(vlapic->timer_freq_bt.sec,
1866 SNAPSHOT_VAR_OR_LEAVE(vlapic->timer_freq_bt.frac,
1873 if (meta->op == VM_SNAPSHOT_RESTORE) {
1874 vlapic->timer_period_bt = vlapic->timer_freq_bt;
1875 bintime_mul(&vlapic->timer_period_bt, lapic->icr_timer);
1878 SNAPSHOT_BUF_OR_LEAVE(vlapic->isrvec_stk,
1879 sizeof(vlapic->isrvec_stk),
1881 SNAPSHOT_VAR_OR_LEAVE(vlapic->isrvec_stk_top, meta, ret, done);
1883 SNAPSHOT_BUF_OR_LEAVE(vlapic->lvt_last,
1884 sizeof(vlapic->lvt_last),
1887 if (meta->op == VM_SNAPSHOT_SAVE)
1892 if (meta->op == VM_SNAPSHOT_RESTORE &&
1893 vlapic_enabled(vlapic) && lapic->icr_timer != 0) {