svn commit: r303490 - head/sys/x86/xen

Roger Pau Monné royger at FreeBSD.org
Fri Jul 29 16:34:56 UTC 2016


Author: royger
Date: Fri Jul 29 16:34:54 2016
New Revision: 303490
URL: https://svnweb.freebsd.org/changeset/base/303490

Log:
  xen-intr: fix removal of event channels during resume
  
  Event channel handlers cannot be removed during resume because there might
  be an interrupt thread running on a CPU currently blocked in the
  cpususpend_handler, which prevents the call to intr_remove_handler from
  finishing and completely freezes the system during resume. r291022 tried to
  fix this by allowing recursion in intr_remove_handler, but that's clearly
  not enough.
  
  Instead don't remove the handlers at the interrupt resume phase, and let
  each driver remove the handler by itself during resume. In order to do this,
  change the opaque event channel handler cookie to use the global interrupt
  vector instead of the event channel port. The event channel port cannot be
  used because after resume all event channels are reset, and the port numbers
  can change.
  
  Sponsored by:		Citrix Systems R&D
  MFC after:		5 days

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

Modified: head/sys/x86/xen/xen_intr.c
==============================================================================
--- head/sys/x86/xen/xen_intr.c	Fri Jul 29 16:34:16 2016	(r303489)
+++ head/sys/x86/xen/xen_intr.c	Fri Jul 29 16:34:54 2016	(r303490)
@@ -130,8 +130,6 @@ struct xenisrc {
 	u_int		xi_masked:1;
 };
 
-#define ARRAY_SIZE(a)	(sizeof(a) / sizeof(a[0]))
-
 static void	xen_intr_suspend(struct pic *);
 static void	xen_intr_resume(struct pic *, bool suspend_cancelled);
 static void	xen_intr_enable_source(struct intsrc *isrc);
@@ -422,7 +420,7 @@ xen_intr_bind_isrc(struct xenisrc **isrc
 	mtx_unlock(&xen_intr_isrc_lock);
 
 	/* Assign the opaque handler (the event channel port) */
-	*port_handlep = &isrc->xi_port;
+	*port_handlep = &isrc->xi_vector;
 
 #ifdef SMP
 	if (type == EVTCHN_TYPE_PORT) {
@@ -468,16 +466,17 @@ xen_intr_bind_isrc(struct xenisrc **isrc
 static struct xenisrc *
 xen_intr_isrc(xen_intr_handle_t handle)
 {
-	evtchn_port_t port;
+	int vector;
 
 	if (handle == NULL)
 		return (NULL);
 
-	port = *(evtchn_port_t *)handle;
-	if (!is_valid_evtchn(port) || port >= NR_EVENT_CHANNELS)
-		return (NULL);
+	vector = *(int *)handle;
+	KASSERT(vector >= FIRST_EVTCHN_INT &&
+	    vector < (FIRST_EVTCHN_INT + xen_intr_auto_vector_count),
+	    ("Xen interrupt vector is out of range"));
 
-	return (xen_intr_port_to_isrc[port]);
+	return ((struct xenisrc *)intr_lookup_source(vector));
 }
 
 /**
@@ -780,10 +779,6 @@ xen_intr_resume(struct pic *unused, bool
 				xen_rebind_virq(isrc);
 				break;
 			default:
-				intr_remove_handler(isrc->xi_cookie);
-				isrc->xi_cpu = 0;
-				isrc->xi_type = EVTCHN_TYPE_UNBOUND;
-				isrc->xi_cookie = NULL;
 				break;
 			}
 		}


More information about the svn-src-head mailing list