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);
 }
 
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "[email protected]"

Reply via email to