* Inject event to virtual cpu. */
| 1605 | * Inject event to virtual cpu. |
| 1606 | */ |
| 1607 | static void |
| 1608 | svm_inj_interrupts(struct svm_softc *sc, int vcpu, struct vlapic *vlapic) |
| 1609 | { |
| 1610 | struct vmcb_ctrl *ctrl; |
| 1611 | struct vmcb_state *state; |
| 1612 | struct svm_vcpu *vcpustate; |
| 1613 | uint8_t v_tpr; |
| 1614 | int vector, need_intr_window; |
| 1615 | int extint_pending; |
| 1616 | |
| 1617 | state = svm_get_vmcb_state(sc, vcpu); |
| 1618 | ctrl = svm_get_vmcb_ctrl(sc, vcpu); |
| 1619 | vcpustate = svm_get_vcpu(sc, vcpu); |
| 1620 | |
| 1621 | need_intr_window = 0; |
| 1622 | |
| 1623 | if (vcpustate->nextrip != state->rip) { |
| 1624 | ctrl->intr_shadow = 0; |
| 1625 | VCPU_CTR2(sc->vm, vcpu, "Guest interrupt blocking " |
| 1626 | "cleared due to rip change: %#lx/%#lx", |
| 1627 | vcpustate->nextrip, state->rip); |
| 1628 | } |
| 1629 | |
| 1630 | /* |
| 1631 | * Inject pending events or exceptions for this vcpu. |
| 1632 | * |
| 1633 | * An event might be pending because the previous #VMEXIT happened |
| 1634 | * during event delivery (i.e. ctrl->exitintinfo). |
| 1635 | * |
| 1636 | * An event might also be pending because an exception was injected |
| 1637 | * by the hypervisor (e.g. #PF during instruction emulation). |
| 1638 | */ |
| 1639 | svm_inj_intinfo(sc, vcpu); |
| 1640 | |
| 1641 | /* NMI event has priority over interrupts. */ |
| 1642 | if (vm_nmi_pending(sc->vm, vcpu)) { |
| 1643 | if (nmi_blocked(sc, vcpu)) { |
| 1644 | /* |
| 1645 | * Can't inject another NMI if the guest has not |
| 1646 | * yet executed an "iret" after the last NMI. |
| 1647 | */ |
| 1648 | VCPU_CTR0(sc->vm, vcpu, "Cannot inject NMI due " |
| 1649 | "to NMI-blocking"); |
| 1650 | } else if (ctrl->intr_shadow) { |
| 1651 | /* |
| 1652 | * Can't inject an NMI if the vcpu is in an intr_shadow. |
| 1653 | */ |
| 1654 | VCPU_CTR0(sc->vm, vcpu, "Cannot inject NMI due to " |
| 1655 | "interrupt shadow"); |
| 1656 | need_intr_window = 1; |
| 1657 | goto done; |
| 1658 | } else if (ctrl->eventinj & VMCB_EVENTINJ_VALID) { |
| 1659 | /* |
| 1660 | * If there is already an exception/interrupt pending |
| 1661 | * then defer the NMI until after that. |
| 1662 | */ |
| 1663 | VCPU_CTR1(sc->vm, vcpu, "Cannot inject NMI due to " |
| 1664 | "eventinj %#lx", ctrl->eventinj); |
no test coverage detected