Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 16 Feb 2015 16:30:42 +0000 (UTC)
From:      Roger Pau Monné <royger@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r278854 - head/sys/x86/xen
Message-ID:  <201502161630.t1GGUg43013575@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: royger
Date: Mon Feb 16 16:30:42 2015
New Revision: 278854
URL: https://svnweb.freebsd.org/changeset/base/278854

Log:
  xen/intr: improve PIRQ handling
  
  Improve and cleanup the Xen PIRQ event channel code:
  
   - Remove the xi_shared field as it is unused.
   - Clean the "pending" bit in the EOI handler, this is more similar to how
     native interrupts are handled.
   - Don't mask edge triggered PIRQs, edge trigger interrupts cannot be
     masked.
   - Panic if PHYSDEVOP_eoi fails.
   - Remove the usage of the PHYSDEVOP_alloc_irq_vector hypercall because
     it's just a no-op in the Xen versions that are supported by FreeBSD Dom0.
  
  Sponsored by: Citrix Systems R&D

Modified:
  head/sys/x86/xen/xen_intr.c

Modified: head/sys/x86/xen/xen_intr.c
==============================================================================
--- head/sys/x86/xen/xen_intr.c	Mon Feb 16 15:47:55 2015	(r278853)
+++ head/sys/x86/xen/xen_intr.c	Mon Feb 16 16:30:42 2015	(r278854)
@@ -126,7 +126,6 @@ struct xenisrc {
 	int		xi_virq;
 	void		*xi_cookie;
 	u_int		xi_close:1;	/* close on unbind? */
-	u_int		xi_shared:1;	/* Shared with other domains. */
 	u_int		xi_activehi:1;
 	u_int		xi_edgetrigger:1;
 };
@@ -579,11 +578,12 @@ xen_intr_handle_upcall(struct trapframe 
 
 			/* process port */
 			port = (l1i * LONG_BIT) + l2i;
-			synch_clear_bit(port, &s->evtchn_pending[0]);
 
 			isrc = xen_intr_port_to_isrc[port];
-			if (__predict_false(isrc == NULL))
+			if (__predict_false(isrc == NULL)) {
+				synch_clear_bit(port, &s->evtchn_pending[0]);
 				continue;
+			}
 
 			/* Make sure we are firing on the right vCPU */
 			KASSERT((isrc->xi_cpu == PCPU_GET(cpuid)),
@@ -932,6 +932,9 @@ out:
 static void
 xen_intr_disable_source(struct intsrc *isrc, int eoi)
 {
+
+	if (eoi == PIC_EOI)
+		xen_intr_eoi_source(isrc);
 }
 
 /*
@@ -950,8 +953,13 @@ xen_intr_enable_source(struct intsrc *is
  * \param isrc  The interrupt source to EOI.
  */
 static void
-xen_intr_eoi_source(struct intsrc *isrc)
+xen_intr_eoi_source(struct intsrc *base_isrc)
 {
+	struct xenisrc *isrc;
+
+	isrc = (struct xenisrc *)base_isrc;
+	synch_clear_bit(isrc->xi_port,
+	    &HYPERVISOR_shared_info->evtchn_pending[0]);
 }
 
 /*
@@ -981,8 +989,9 @@ xen_intr_pirq_disable_source(struct ints
 	struct xenisrc *isrc;
 
 	isrc = (struct xenisrc *)base_isrc;
-	evtchn_mask_port(isrc->xi_port);
 
+	if (isrc->xi_edgetrigger == 0)
+		evtchn_mask_port(isrc->xi_port);
 	if (eoi == PIC_EOI)
 		xen_intr_pirq_eoi_source(base_isrc);
 }
@@ -998,7 +1007,9 @@ xen_intr_pirq_enable_source(struct intsr
 	struct xenisrc *isrc;
 
 	isrc = (struct xenisrc *)base_isrc;
-	evtchn_unmask_port(isrc->xi_port);
+
+	if (isrc->xi_edgetrigger == 0)
+		evtchn_unmask_port(isrc->xi_port);
 }
 
 /*
@@ -1010,13 +1021,19 @@ static void
 xen_intr_pirq_eoi_source(struct intsrc *base_isrc)
 {
 	struct xenisrc *isrc;
+	int error;
 
-	/* XXX Use shared page of flags for this. */
 	isrc = (struct xenisrc *)base_isrc;
+
+	synch_clear_bit(isrc->xi_port,
+	    &HYPERVISOR_shared_info->evtchn_pending[0]);
 	if (test_bit(isrc->xi_pirq, xen_intr_pirq_eoi_map)) {
 		struct physdev_eoi eoi = { .irq = isrc->xi_pirq };
 
-		(void)HYPERVISOR_physdev_op(PHYSDEVOP_eoi, &eoi);
+		error = HYPERVISOR_physdev_op(PHYSDEVOP_eoi, &eoi);
+		if (error != 0)
+			panic("Unable to EOI PIRQ#%d: %d\n",
+			    isrc->xi_pirq, error);
 	}
 }
 
@@ -1361,7 +1378,6 @@ int
 xen_register_pirq(int vector, enum intr_trigger trig, enum intr_polarity pol)
 {
 	struct physdev_map_pirq map_pirq;
-	struct physdev_irq alloc_pirq;
 	struct xenisrc *isrc;
 	int error;
 
@@ -1382,14 +1398,6 @@ xen_register_pirq(int vector, enum intr_
 		return (error);
 	}
 
-	alloc_pirq.irq = vector;
-	alloc_pirq.vector = 0;
-	error = HYPERVISOR_physdev_op(PHYSDEVOP_alloc_irq_vector, &alloc_pirq);
-	if (error) {
-		printf("xen: unable to alloc PIRQ for IRQ#%d\n", vector);
-		return (error);
-	}
-
 	mtx_lock(&xen_intr_isrc_lock);
 	isrc = xen_intr_alloc_isrc(EVTCHN_TYPE_PIRQ, vector);
 	mtx_unlock(&xen_intr_isrc_lock);
@@ -1432,6 +1440,8 @@ xen_register_msi(device_t dev, int vecto
 		KASSERT(isrc != NULL,
 		    ("xen: unable to allocate isrc for interrupt"));
 		isrc->xi_pirq = msi_irq.pirq + i;
+		/* MSI interrupts are always edge triggered */
+		isrc->xi_edgetrigger = 1;
 	}
 	mtx_unlock(&xen_intr_isrc_lock);
 
@@ -1573,10 +1583,9 @@ xen_intr_dump_port(struct xenisrc *isrc)
 	    isrc->xi_port, xen_intr_print_type(isrc->xi_type));
 	if (isrc->xi_type == EVTCHN_TYPE_PIRQ) {
 		db_printf("\tPirq: %d ActiveHi: %d EdgeTrigger: %d "
-		    "NeedsEOI: %d Shared: %d\n",
+		    "NeedsEOI: %d\n",
 		    isrc->xi_pirq, isrc->xi_activehi, isrc->xi_edgetrigger,
-		    !!test_bit(isrc->xi_pirq, xen_intr_pirq_eoi_map),
-		    isrc->xi_shared);
+		    !!test_bit(isrc->xi_pirq, xen_intr_pirq_eoi_map));
 	}
 	if (isrc->xi_type == EVTCHN_TYPE_VIRQ)
 		db_printf("\tVirq: %d\n", isrc->xi_virq);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201502161630.t1GGUg43013575>