Date: Tue, 7 Jan 2014 00:38:23 +0000 (UTC) From: Neel Natu <neel@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r260383 - in head/sys/amd64/vmm: . intel io Message-ID: <201401070038.s070cNmC025758@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: neel Date: Tue Jan 7 00:38:22 2014 New Revision: 260383 URL: http://svnweb.freebsd.org/changeset/base/260383 Log: Allow vlapic_set_intr_ready() to return a value that indicates whether or not the vcpu should be kicked to process a pending interrupt. This will be useful in the implementation of the Posted Interrupt APICv feature. Change the return value of 'vlapic_pending_intr()' to indicate whether or not an interrupt is available to be delivered to the vcpu depending on the value of the PPR. Add KTR tracepoints to debug guest IPI delivery. Modified: head/sys/amd64/vmm/intel/vmx.c head/sys/amd64/vmm/io/vlapic.c head/sys/amd64/vmm/io/vlapic.h head/sys/amd64/vmm/vmm.c head/sys/amd64/vmm/vmm_lapic.c Modified: head/sys/amd64/vmm/intel/vmx.c ============================================================================== --- head/sys/amd64/vmm/intel/vmx.c Mon Jan 6 23:51:26 2014 (r260382) +++ head/sys/amd64/vmm/intel/vmx.c Tue Jan 7 00:38:22 2014 (r260383) @@ -989,8 +989,7 @@ vmx_inject_interrupts(struct vmx *vmx, i return; /* Ask the local apic for a vector to inject */ - vector = vlapic_pending_intr(vlapic); - if (vector < 0) + if (!vlapic_pending_intr(vlapic, &vector)) return; if (vector < 32 || vector > 255) Modified: head/sys/amd64/vmm/io/vlapic.c ============================================================================== --- head/sys/amd64/vmm/io/vlapic.c Mon Jan 6 23:51:26 2014 (r260382) +++ head/sys/amd64/vmm/io/vlapic.c Tue Jan 7 00:38:22 2014 (r260383) @@ -289,27 +289,29 @@ vlapic_esr_write_handler(struct vlapic * vlapic->esr_pending = 0; } -void +int vlapic_set_intr_ready(struct vlapic *vlapic, int vector, bool level) { - struct LAPIC *lapic = vlapic->apic_page; - uint32_t *irrptr, *tmrptr, mask; - int idx; + struct LAPIC *lapic; + uint32_t *irrptr, *tmrptr, mask; + int idx; - if (vector < 0 || vector >= 256) - panic("vlapic_set_intr_ready: invalid vector %d\n", vector); + KASSERT(vector >= 0 && vector < 256, ("invalid vector %d", vector)); + lapic = vlapic->apic_page; if (!(lapic->svr & APIC_SVR_ENABLE)) { VLAPIC_CTR1(vlapic, "vlapic is software disabled, ignoring " "interrupt %d", vector); - return; + return (0); } if (vector < 16) { vlapic_set_error(vlapic, APIC_ESR_RECEIVE_ILLEGAL_VECTOR); - return; + VLAPIC_CTR1(vlapic, "vlapic ignoring interrupt to vector %d", + vector); + return (1); } - + idx = (vector / 32) * 4; mask = 1 << (vector % 32); @@ -328,6 +330,7 @@ vlapic_set_intr_ready(struct vlapic *vla atomic_clear_int(&tmrptr[idx], mask); VLAPIC_CTR_IRR(vlapic, "vlapic_set_intr_ready"); + return (1); } static __inline uint32_t * @@ -473,8 +476,8 @@ vlapic_fire_lvt(struct vlapic *vlapic, u vlapic_set_error(vlapic, APIC_ESR_SEND_ILLEGAL_VECTOR); return (0); } - vlapic_set_intr_ready(vlapic, vec, false); - vcpu_notify_event(vlapic->vm, vlapic->vcpuid, true); + if (vlapic_set_intr_ready(vlapic, vec, false)) + vcpu_notify_event(vlapic->vm, vlapic->vcpuid, true); break; case APIC_LVT_DM_NMI: vm_inject_nmi(vlapic->vm, vlapic->vcpuid); @@ -935,9 +938,12 @@ vlapic_icrlo_write_handler(struct vlapic if (mode == APIC_DELMODE_FIXED && vec < 16) { vlapic_set_error(vlapic, APIC_ESR_SEND_ILLEGAL_VECTOR); + VLAPIC_CTR1(vlapic, "Ignoring invalid IPI %d", vec); return (0); } - + + VLAPIC_CTR2(vlapic, "icrlo 0x%016lx triggered ipi %d", icrval, vec); + if (mode == APIC_DELMODE_FIXED || mode == APIC_DELMODE_NMI) { switch (icrval & APIC_DEST_MASK) { case APIC_DEST_DESTFLD: @@ -967,8 +973,13 @@ vlapic_icrlo_write_handler(struct vlapic lapic_intr_edge(vlapic->vm, i, vec); vmm_stat_array_incr(vlapic->vm, vlapic->vcpuid, IPIS_SENT, i, 1); - } else + VLAPIC_CTR2(vlapic, "vlapic sending ipi %d " + "to vcpuid %d", vec, i); + } else { vm_inject_nmi(vlapic->vm, i); + VLAPIC_CTR1(vlapic, "vlapic sending ipi nmi " + "to vcpuid %d", i); + } } return (0); /* handled completely in the kernel */ @@ -1023,7 +1034,7 @@ vlapic_icrlo_write_handler(struct vlapic } int -vlapic_pending_intr(struct vlapic *vlapic) +vlapic_pending_intr(struct vlapic *vlapic, int *vecptr) { struct LAPIC *lapic = vlapic->apic_page; int idx, i, bitpos, vector; @@ -1043,12 +1054,14 @@ vlapic_pending_intr(struct vlapic *vlapi vector = i * 32 + (bitpos - 1); if (PRIO(vector) > PRIO(lapic->ppr)) { VLAPIC_CTR1(vlapic, "pending intr %d", vector); - return (vector); + if (vecptr != NULL) + *vecptr = vector; + return (1); } else break; } } - return (-1); + return (0); } void Modified: head/sys/amd64/vmm/io/vlapic.h ============================================================================== --- head/sys/amd64/vmm/io/vlapic.h Mon Jan 6 23:51:26 2014 (r260382) +++ head/sys/amd64/vmm/io/vlapic.h Tue Jan 7 00:38:22 2014 (r260383) @@ -38,16 +38,16 @@ int vlapic_read(struct vlapic *vlapic, u bool *retu); /* - * Returns a vector between 32 and 255 if an interrupt is pending in the - * IRR that can be delivered based on the current state of ISR and TPR. + * Returns 0 if there is no eligible vector that can be delivered to the + * guest at this time and non-zero otherwise. + * + * If an eligible vector number is found and 'vecptr' is not NULL then it will + * be stored in the location pointed to by 'vecptr'. * * Note that the vector does not automatically transition to the ISR as a * result of calling this function. - * - * Returns -1 if there is no eligible vector that can be delivered to the - * guest at this time. */ -int vlapic_pending_intr(struct vlapic *vlapic); +int vlapic_pending_intr(struct vlapic *vlapic, int *vecptr); /* * Transition 'vector' from IRR to ISR. This function is called with the @@ -57,7 +57,18 @@ int vlapic_pending_intr(struct vlapic *v */ void vlapic_intr_accepted(struct vlapic *vlapic, int vector); -void vlapic_set_intr_ready(struct vlapic *vlapic, int vector, bool level); +/* + * Returns 1 if the vcpu needs to be notified of the interrupt and 0 otherwise. + */ +int vlapic_set_intr_ready(struct vlapic *vlapic, int vector, bool level); + +/* + * Post an interrupt to the vcpu running on 'hostcpu'. This will use a + * hardware assist if available (e.g. Posted Interrupt) or fall back to + * sending an IPI to interrupt the 'hostcpu'. + */ +void vlapic_post_intr(struct vlapic *vlapic, int hostcpu); + void vlapic_set_error(struct vlapic *vlapic, uint32_t mask); void vlapic_fire_cmci(struct vlapic *vlapic); int vlapic_trigger_lvt(struct vlapic *vlapic, int vector); @@ -69,7 +80,6 @@ bool vlapic_enabled(struct vlapic *vlapi void vlapic_deliver_intr(struct vm *vm, bool level, uint32_t dest, bool phys, int delmode, int vec); -void vlapic_post_intr(struct vlapic *vlapic, int hostcpu); /* APIC write handlers */ void vlapic_id_write_handler(struct vlapic *vlapic); Modified: head/sys/amd64/vmm/vmm.c ============================================================================== --- head/sys/amd64/vmm/vmm.c Mon Jan 6 23:51:26 2014 (r260382) +++ head/sys/amd64/vmm/vmm.c Tue Jan 7 00:38:22 2014 (r260383) @@ -910,7 +910,7 @@ vm_handle_hlt(struct vm *vm, int vcpuid, * returned from VMRUN() and before we grabbed the vcpu lock. */ if (!vm_nmi_pending(vm, vcpuid) && - (intr_disabled || vlapic_pending_intr(vcpu->vlapic) < 0)) { + (intr_disabled || !vlapic_pending_intr(vcpu->vlapic, NULL))) { t = ticks; vcpu_require_state_locked(vcpu, VCPU_SLEEPING); if (vlapic_enabled(vcpu->vlapic)) { Modified: head/sys/amd64/vmm/vmm_lapic.c ============================================================================== --- head/sys/amd64/vmm/vmm_lapic.c Mon Jan 6 23:51:26 2014 (r260382) +++ head/sys/amd64/vmm/vmm_lapic.c Tue Jan 7 00:38:22 2014 (r260383) @@ -62,8 +62,8 @@ lapic_set_intr(struct vm *vm, int cpu, i return (EINVAL); vlapic = vm_lapic(vm, cpu); - vlapic_set_intr_ready(vlapic, vector, level); - vcpu_notify_event(vm, cpu, true); + if (vlapic_set_intr_ready(vlapic, vector, level)) + vcpu_notify_event(vm, cpu, true); return (0); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201401070038.s070cNmC025758>