Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 14 Apr 2023 14:01:05 GMT
From:      =?utf-8?Q?Roger=20Pau=20Monn=C3=A9?= <royger@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: 6699c22c1cb0 - main - xen/intr: move interrupt allocation/release to architecture
Message-ID:  <202304141401.33EE15Jp084930@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by royger:

URL: https://cgit.FreeBSD.org/src/commit/?id=6699c22c1cb0f8a355ecb9d030c6990e48f8d7db

commit 6699c22c1cb0f8a355ecb9d030c6990e48f8d7db
Author:     Elliott Mitchell <ehem+freebsd@m5p.com>
AuthorDate: 2021-05-14 04:36:02 +0000
Commit:     Roger Pau Monné <royger@FreeBSD.org>
CommitDate: 2023-04-14 13:58:56 +0000

    xen/intr: move interrupt allocation/release to architecture
    
    Simply moving the interrupt allocation and release functions into files
    which belong to the architecture.  Since x86 interrupt handling is quite
    distinct from other architectures, this is a crucial necessary step.
    
    Identifying the border between x86 and architecture-independent is
    actually quite tricky.  Similarly, getting the prototypes for the
    border right is also quite tricky.
    
    Inspired by the work of Julien Grall <julien@xen.org>,
    2015-10-20 09:14:56, but heavily adjusted.
    
    Reviewed by: royger
    Differential Revision: https://reviews.freebsd.org/D30936
---
 sys/dev/xen/bus/intr-internal.h |   3 ++
 sys/x86/include/xen/arch-intr.h |  13 ++++-
 sys/x86/xen/xen_arch_intr.c     | 115 +++++++++++++++++++++++++++++++++++++++-
 sys/x86/xen/xen_intr.c          | 111 ++------------------------------------
 4 files changed, 131 insertions(+), 111 deletions(-)

diff --git a/sys/dev/xen/bus/intr-internal.h b/sys/dev/xen/bus/intr-internal.h
index 2c707edf095e..28024d53e106 100644
--- a/sys/dev/xen/bus/intr-internal.h
+++ b/sys/dev/xen/bus/intr-internal.h
@@ -77,6 +77,9 @@ extern int	xen_intr_assign_cpu(struct xenisrc *isrc, u_int to_cpu);
  * <machine/xen/arch-intr.h>.  The architecture may implement these as inline.
  */
 void	xen_arch_intr_init(void);
+struct xenisrc *xen_arch_intr_alloc(void);
+void	xen_arch_intr_release(struct xenisrc *isrc);
+u_int	xen_arch_intr_next_cpu(struct xenisrc *isrc);
 u_long	xen_arch_intr_execute_handlers(struct xenisrc *isrc,
 	    struct trapframe *frame);
 int	xen_arch_intr_add_handler(const char *name,
diff --git a/sys/x86/include/xen/arch-intr.h b/sys/x86/include/xen/arch-intr.h
index 06e70ba462a2..eae3994108cc 100644
--- a/sys/x86/include/xen/arch-intr.h
+++ b/sys/x86/include/xen/arch-intr.h
@@ -30,20 +30,29 @@
 #define	_MACHINE__XEN_ARCH_INTR_H_
 
 #include <x86/intr_machdep.h>
+#include <x86/apicvar.h>
 
 typedef struct {
 	struct intsrc		intsrc;		/* @TOP -> *xen_arch_isrc */
 	u_int			vector;		/* Global isrc vector number */
 } xen_arch_isrc_t;
 
-extern struct pic xen_intr_pic;
-
 #include <dev/xen/bus/intr-internal.h>
 
 /******************************* ARCH wrappers *******************************/
 
 extern void xen_arch_intr_init(void);
 
+extern struct xenisrc *xen_arch_intr_alloc(void);
+extern void     xen_arch_intr_release(struct xenisrc *isrc);
+
+static inline u_int
+xen_arch_intr_next_cpu(struct xenisrc *isrc)
+{
+
+	return (apic_cpuid(intr_next_cpu(0)));
+}
+
 static inline u_long
 xen_arch_intr_execute_handlers(struct xenisrc *isrc, struct trapframe *frame)
 {
diff --git a/sys/x86/xen/xen_arch_intr.c b/sys/x86/xen/xen_arch_intr.c
index 94ada3dee4e9..8b136885f190 100644
--- a/sys/x86/xen/xen_arch_intr.c
+++ b/sys/x86/xen/xen_arch_intr.c
@@ -111,6 +111,41 @@ xen_arch_intr_handle_upcall(struct trapframe *trap_frame)
 
 /******************************** EVTCHN PIC *********************************/
 
+static MALLOC_DEFINE(M_XENINTR, "xen_intr", "Xen Interrupt Services");
+
+/*
+ * Lock for x86-related structures.  Notably modifying
+ * xen_intr_auto_vector_count, and allocating interrupts require this lock be
+ * held.
+ */
+static struct mtx	xen_intr_x86_lock;
+
+static u_int		first_evtchn_irq;
+
+static u_int		xen_intr_auto_vector_count;
+
+/*
+ * list of released isrcs
+ * This is meant to overlay struct xenisrc, with only the xen_arch_isrc_t
+ * portion being preserved, everything else can be wiped.
+ */
+struct avail_list {
+	xen_arch_isrc_t preserve;
+	SLIST_ENTRY(avail_list) free;
+};
+static SLIST_HEAD(free, avail_list) avail_list =
+    SLIST_HEAD_INITIALIZER(avail_list);
+
+void
+xen_intr_alloc_irqs(void)
+{
+
+	if (num_io_irqs > UINT_MAX - NR_EVENT_CHANNELS)
+		panic("IRQ allocation overflow (num_msi_irqs too high?)");
+	first_evtchn_irq = num_io_irqs;
+	num_io_irqs += NR_EVENT_CHANNELS;
+}
+
 static void
 xen_intr_pic_enable_source(struct intsrc *isrc)
 {
@@ -244,7 +279,7 @@ xen_intr_pic_assign_cpu(struct intsrc *isrc, u_int apic_id)
 /**
  * PIC interface for all event channel port types except physical IRQs.
  */
-struct pic xen_intr_pic = {
+static struct pic xen_intr_pic = {
 	.pic_enable_source  = xen_intr_pic_enable_source,
 	.pic_disable_source = xen_intr_pic_disable_source,
 	.pic_eoi_source     = xen_intr_pic_eoi_source,
@@ -265,8 +300,86 @@ xen_arch_intr_init(void)
 {
 	int error;
 
+	mtx_init(&xen_intr_x86_lock, "xen-x86-table-lock", NULL, MTX_DEF);
+
 	error = intr_register_pic(&xen_intr_pic);
 	if (error != 0)
 		panic("%s(): failed registering Xen/x86 PIC, error=%d\n",
 		    __func__, error);
 }
+
+/**
+ * Allocate a Xen interrupt source object.
+ *
+ * \param type  The type of interrupt source to create.
+ *
+ * \return  A pointer to a newly allocated Xen interrupt source
+ *          object or NULL.
+ */
+struct xenisrc *
+xen_arch_intr_alloc(void)
+{
+	static int warned;
+	struct xenisrc *isrc;
+	unsigned int vector;
+	int error;
+
+	mtx_lock(&xen_intr_x86_lock);
+	isrc = (struct xenisrc *)SLIST_FIRST(&avail_list);
+	if (isrc != NULL) {
+		SLIST_REMOVE_HEAD(&avail_list, free);
+		mtx_unlock(&xen_intr_x86_lock);
+
+		KASSERT(isrc->xi_arch.intsrc.is_pic == &xen_intr_pic,
+		    ("interrupt not owned by Xen code?"));
+
+		KASSERT(isrc->xi_arch.intsrc.is_handlers == 0,
+		    ("Free evtchn still has handlers"));
+
+		return (isrc);
+	}
+
+	if (xen_intr_auto_vector_count >= NR_EVENT_CHANNELS) {
+		if (!warned) {
+			warned = 1;
+			printf("%s: Xen interrupts exhausted.\n", __func__);
+		}
+		mtx_unlock(&xen_intr_x86_lock);
+		return (NULL);
+	}
+
+	vector = first_evtchn_irq + xen_intr_auto_vector_count;
+	xen_intr_auto_vector_count++;
+
+	KASSERT((intr_lookup_source(vector) == NULL),
+	    ("Trying to use an already allocated vector"));
+
+	mtx_unlock(&xen_intr_x86_lock);
+	isrc = malloc(sizeof(*isrc), M_XENINTR, M_WAITOK | M_ZERO);
+	isrc->xi_arch.intsrc.is_pic = &xen_intr_pic;
+	isrc->xi_arch.vector = vector;
+	error = intr_register_source(&isrc->xi_arch.intsrc);
+	if (error != 0)
+		panic("%s(): failed registering interrupt %u, error=%d\n",
+		    __func__, vector, error);
+
+	return (isrc);
+}
+
+void
+xen_arch_intr_release(struct xenisrc *isrc)
+{
+
+	KASSERT(isrc->xi_arch.intsrc.is_handlers == 0,
+	    ("Release called, but xenisrc still in use"));
+
+	_Static_assert(sizeof(struct xenisrc) >= sizeof(struct avail_list),
+	    "unused structure MUST be no larger than in-use structure");
+	_Static_assert(offsetof(struct xenisrc, xi_arch) ==
+	    offsetof(struct avail_list, preserve),
+	    "unused structure does not properly overlay in-use structure");
+
+	mtx_lock(&xen_intr_x86_lock);
+	SLIST_INSERT_HEAD(&avail_list, (struct avail_list *)isrc, free);
+	mtx_unlock(&xen_intr_x86_lock);
+}
diff --git a/sys/x86/xen/xen_intr.c b/sys/x86/xen/xen_intr.c
index ebce27816539..c9de4675d091 100644
--- a/sys/x86/xen/xen_intr.c
+++ b/sys/x86/xen/xen_intr.c
@@ -38,7 +38,6 @@ __FBSDID("$FreeBSD$");
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/bus.h>
-#include <sys/malloc.h>
 #include <sys/kernel.h>
 #include <sys/limits.h>
 #include <sys/lock.h>
@@ -68,17 +67,6 @@ __FBSDID("$FreeBSD$");
 #include <ddb/ddb.h>
 #endif
 
-static MALLOC_DEFINE(M_XENINTR, "xen_intr", "Xen Interrupt Services");
-
-/*
- * Lock for x86-related structures.  Notably modifying
- * xen_intr_auto_vector_count, and allocating interrupts require this lock be
- * held.
- */
-static struct mtx	xen_intr_x86_lock;
-
-static u_int first_evtchn_irq;
-
 /**
  * Per-cpu event channel processing state.
  */
@@ -128,21 +116,8 @@ DPCPU_DECLARE(struct vcpu_info *, vcpu_info);
  * Acquire/release operations for isrc->xi_refcount require this lock be held.
  */
 static struct mtx	 xen_intr_isrc_lock;
-static u_int		 xen_intr_auto_vector_count;
 static struct xenisrc	*xen_intr_port_to_isrc[NR_EVENT_CHANNELS];
 
-/*
- * list of released isrcs
- * This is meant to overlay struct xenisrc, with only the xen_arch_isrc_t
- * portion being preserved, everything else can be wiped.
- */
-struct avail_list {
-	xen_arch_isrc_t preserve;
-	SLIST_ENTRY(avail_list) free;
-};
-static SLIST_HEAD(free, avail_list) avail_list =
-    SLIST_HEAD_INITIALIZER(avail_list);
-
 /*------------------------- Private Functions --------------------------------*/
 
 /**
@@ -220,64 +195,6 @@ evtchn_cpu_unmask_port(u_int cpu, evtchn_port_t port)
 	xen_set_bit(port, pcpu->evtchn_enabled);
 }
 
-/**
- * Allocate a Xen interrupt source object.
- *
- * \param type  The type of interrupt source to create.
- *
- * \return  A pointer to a newly allocated Xen interrupt source
- *          object or NULL.
- */
-static struct xenisrc *
-xen_intr_alloc_isrc(void)
-{
-	static int warned;
-	struct xenisrc *isrc;
-	unsigned int vector;
-	int error;
-
-	mtx_lock(&xen_intr_x86_lock);
-	isrc = (struct xenisrc *)SLIST_FIRST(&avail_list);
-	if (isrc != NULL) {
-		SLIST_REMOVE_HEAD(&avail_list, free);
-		mtx_unlock(&xen_intr_x86_lock);
-
-		KASSERT(isrc->xi_arch.intsrc.is_pic == &xen_intr_pic,
-		    ("interrupt not owned by Xen code?"));
-
-		KASSERT(isrc->xi_arch.intsrc.is_handlers == 0,
-		    ("Free evtchn still has handlers"));
-
-		return (isrc);
-	}
-
-	if (xen_intr_auto_vector_count >= NR_EVENT_CHANNELS) {
-		if (!warned) {
-			warned = 1;
-			printf("%s: Xen interrupts exhausted.\n", __func__);
-		}
-		mtx_unlock(&xen_intr_x86_lock);
-		return (NULL);
-	}
-
-	vector = first_evtchn_irq + xen_intr_auto_vector_count;
-	xen_intr_auto_vector_count++;
-
-	KASSERT((intr_lookup_source(vector) == NULL),
-	    ("Trying to use an already allocated vector"));
-
-	mtx_unlock(&xen_intr_x86_lock);
-	isrc = malloc(sizeof(*isrc), M_XENINTR, M_WAITOK | M_ZERO);
-	isrc->xi_arch.intsrc.is_pic = &xen_intr_pic;
-	isrc->xi_arch.vector = vector;
-	error = intr_register_source(&isrc->xi_arch.intsrc);
-	if (error != 0)
-		panic("%s(): failed registering interrupt %u, error=%d\n",
-		    __func__, vector, error);
-
-	return (isrc);
-}
-
 /**
  * Attempt to free an active Xen interrupt source object.
  *
@@ -289,8 +206,6 @@ static int
 xen_intr_release_isrc(struct xenisrc *isrc)
 {
 
-	KASSERT(isrc->xi_arch.intsrc.is_handlers == 0,
-	    ("Release called, but xenisrc still in use"));
 	mtx_lock(&xen_intr_isrc_lock);
 	if (is_valid_evtchn(isrc->xi_port)) {
 		evtchn_mask_port(isrc->xi_port);
@@ -312,15 +227,7 @@ xen_intr_release_isrc(struct xenisrc *isrc)
 	/* not reachable from xen_intr_port_to_isrc[], unlock */
 	mtx_unlock(&xen_intr_isrc_lock);
 
-	_Static_assert(sizeof(struct xenisrc) >= sizeof(struct avail_list),
-	    "unused structure MUST be no larger than in-use structure");
-	_Static_assert(offsetof(struct xenisrc, xi_arch) ==
-	    offsetof(struct avail_list, preserve),
-	    "unused structure does not properly overlay in-use structure");
-
-	mtx_lock(&xen_intr_x86_lock);
-	SLIST_INSERT_HEAD(&avail_list, (struct avail_list *)isrc, free);
-	mtx_unlock(&xen_intr_x86_lock);
+	xen_arch_intr_release(isrc);
 	return (0);
 }
 
@@ -361,7 +268,7 @@ xen_intr_bind_isrc(struct xenisrc **isrcp, evtchn_port_t local_port,
 	}
 	*port_handlep = NULL;
 
-	isrc = xen_intr_alloc_isrc();
+	isrc = xen_arch_intr_alloc();
 	if (isrc == NULL)
 		return (ENOSPC);
 
@@ -382,7 +289,7 @@ xen_intr_bind_isrc(struct xenisrc **isrcp, evtchn_port_t local_port,
 		 * unless specified otherwise, so shuffle them to balance
 		 * the interrupt load.
 		 */
-		xen_intr_assign_cpu(isrc, apic_cpuid(intr_next_cpu(0)));
+		xen_intr_assign_cpu(isrc, xen_arch_intr_next_cpu(isrc));
 	}
 #endif
 
@@ -561,8 +468,6 @@ xen_intr_init(void *dummy __unused)
 
 	mtx_init(&xen_intr_isrc_lock, "xen-irq-lock", NULL, MTX_DEF);
 
-	mtx_init(&xen_intr_x86_lock, "xen-x86-table-lock", NULL, MTX_DEF);
-
 	/*
 	 * Set the per-cpu mask of CPU#0 to enable all, since by default all
 	 * event channels are bound to CPU#0.
@@ -585,16 +490,6 @@ xen_intr_init(void *dummy __unused)
 }
 SYSINIT(xen_intr_init, SI_SUB_INTR, SI_ORDER_SECOND, xen_intr_init, NULL);
 
-void
-xen_intr_alloc_irqs(void)
-{
-
-	if (num_io_irqs > UINT_MAX - NR_EVENT_CHANNELS)
-		panic("IRQ allocation overflow (num_msi_irqs too high?)");
-	first_evtchn_irq = num_io_irqs;
-	num_io_irqs += NR_EVENT_CHANNELS;
-}
-
 /*--------------------------- Common PIC Functions ---------------------------*/
 
 static void



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