svn commit: r308127 - in head/sys: x86/xen xen

Roger Pau Monné royger at FreeBSD.org
Mon Oct 31 13:00:54 UTC 2016


Author: royger
Date: Mon Oct 31 13:00:53 2016
New Revision: 308127
URL: https://svnweb.freebsd.org/changeset/base/308127

Log:
  xen/intr: add reference counts to event channels
  
  Add a reference count to xenisrc. This is required for implementation of
  unmap-notifications in the grant table userspace device (gntdev). We need to
  hold a reference to the event channel port, in case the user deallocates the
  port before we send the notification.
  
  Submitted by:		jaggi
  Reviewed by:		royger
  Differential review:	https://reviews.freebsd.org/D7429

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

Modified: head/sys/x86/xen/xen_intr.c
==============================================================================
--- head/sys/x86/xen/xen_intr.c	Mon Oct 31 11:31:11 2016	(r308126)
+++ head/sys/x86/xen/xen_intr.c	Mon Oct 31 13:00:53 2016	(r308127)
@@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/interrupt.h>
 #include <sys/pcpu.h>
 #include <sys/smp.h>
+#include <sys/refcount.h>
 
 #include <vm/vm.h>
 #include <vm/pmap.h>
@@ -128,6 +129,7 @@ struct xenisrc {
 	u_int		xi_activehi:1;
 	u_int		xi_edgetrigger:1;
 	u_int		xi_masked:1;
+	volatile u_int	xi_refcount;
 };
 
 static void	xen_intr_suspend(struct pic *);
@@ -343,10 +345,8 @@ xen_intr_release_isrc(struct xenisrc *is
 {
 
 	mtx_lock(&xen_intr_isrc_lock);
-	if (isrc->xi_intsrc.is_handlers != 0) {
-		mtx_unlock(&xen_intr_isrc_lock);
-		return (EBUSY);
-	}
+	KASSERT(isrc->xi_intsrc.is_handlers == 0,
+	    ("Release called, but xenisrc still in use"));
 	evtchn_mask_port(isrc->xi_port);
 	evtchn_clear_port(isrc->xi_port);
 
@@ -417,6 +417,7 @@ xen_intr_bind_isrc(struct xenisrc **isrc
 	}
 	isrc->xi_port = local_port;
 	xen_intr_port_to_isrc[local_port] = isrc;
+	refcount_init(&isrc->xi_refcount, 1);
 	mtx_unlock(&xen_intr_isrc_lock);
 
 	/* Assign the opaque handler (the event channel port) */
@@ -1508,6 +1509,13 @@ xen_intr_unbind(xen_intr_handle_t *port_
 	if (isrc == NULL)
 		return;
 
+	mtx_lock(&xen_intr_isrc_lock);
+	if (refcount_release(&isrc->xi_refcount) == 0) {
+		mtx_unlock(&xen_intr_isrc_lock);
+		return;
+	}
+	mtx_unlock(&xen_intr_isrc_lock);
+
 	if (isrc->xi_cookie != NULL)
 		intr_remove_handler(isrc->xi_cookie);
 	xen_intr_release_isrc(isrc);
@@ -1563,6 +1571,31 @@ xen_intr_add_handler(device_t dev, drive
 	return (error);
 }
 
+int
+xen_intr_get_evtchn_from_port(evtchn_port_t port, xen_intr_handle_t *handlep)
+{
+
+	if (!is_valid_evtchn(port) || port >= NR_EVENT_CHANNELS)
+		return (EINVAL);
+
+	if (handlep == NULL) {
+		return (EINVAL);
+	}
+
+	mtx_lock(&xen_intr_isrc_lock);
+	if (xen_intr_port_to_isrc[port] == NULL) {
+		mtx_unlock(&xen_intr_isrc_lock);
+		return (EINVAL);
+	}
+	refcount_acquire(&xen_intr_port_to_isrc[port]->xi_refcount);
+	mtx_unlock(&xen_intr_isrc_lock);
+
+	/* Assign the opaque handler (the event channel port) */
+	*handlep = &xen_intr_port_to_isrc[port]->xi_vector;
+
+	return (0);
+}
+
 #ifdef DDB
 static const char *
 xen_intr_print_type(enum evtchn_type type)

Modified: head/sys/xen/xen_intr.h
==============================================================================
--- head/sys/xen/xen_intr.h	Mon Oct 31 11:31:11 2016	(r308126)
+++ head/sys/xen/xen_intr.h	Mon Oct 31 13:00:53 2016	(r308127)
@@ -263,4 +263,16 @@ int xen_intr_add_handler(device_t dev, d
 	driver_intr_t handler, void *arg, enum intr_type flags,
 	xen_intr_handle_t handle);
 
+/**
+ * Get a reference to an event channel port
+ *
+ * \param port	    Event channel port to which we get a reference.
+ * \param handlep   Pointer to an opaque handle used to manage this
+ *                  registration.
+ *
+ * \returns  0 on success, otherwise an errno.
+ */
+int xen_intr_get_evtchn_from_port(evtchn_port_t port,
+	xen_intr_handle_t *handlep);
+
 #endif /* _XEN_INTR_H_ */


More information about the svn-src-head mailing list