svn commit: r260383 - in head/sys/amd64/vmm: . intel io

Neel Natu neel at FreeBSD.org
Tue Jan 7 00:38:24 UTC 2014


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);
 }
 


More information about the svn-src-all mailing list