Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F142791723
D30936.id96851.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
10 KB
Referenced Files
None
Subscribers
None
D30936.id96851.diff
View Options
Index: sys/x86/include/xen/arch-intr.h
===================================================================
--- sys/x86/include/xen/arch-intr.h
+++ sys/x86/include/xen/arch-intr.h
@@ -40,6 +40,4 @@
typedef struct xen_arch_isrc xen_arch_isrc_t;
-extern struct pic xen_intr_pic;
-
#endif /* _MACHINE_X86_XEN_ARCH_INTR_H_ */
Index: sys/x86/xen/xen_arch_intr.c
===================================================================
--- sys/x86/xen/xen_arch_intr.c
+++ sys/x86/xen/xen_arch_intr.c
@@ -48,6 +48,28 @@
#include <xen/xen_intr.h>
#include <xen/arch-intr.h>
+/*
+ * 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;
+
+
+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;
+}
+
/********************************* EVTCHN PIC ********************************/
static void
@@ -175,7 +197,7 @@
/**
* 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,
@@ -195,9 +217,128 @@
xen_arch_intr_init(void)
{
+ mtx_init(&xen_intr_x86_lock, "xen-x86-table-lock", NULL, MTX_DEF);
+
intr_register_pic(&xen_intr_pic);
}
+/**
+ * Search for an already allocated but currently unused Xen interrupt
+ * source object.
+ *
+ * \param type Restrict the search to interrupt sources of the given
+ * type.
+ *
+ * \return A pointer to a free Xen interrupt source object or NULL.
+ */
+static struct xenisrc *
+xen_intr_find_unused_isrc(enum evtchn_type type)
+{
+ int isrc_idx;
+
+ mtx_assert(&xen_intr_x86_lock, MA_OWNED);
+
+ for (isrc_idx = 0; isrc_idx < xen_intr_auto_vector_count; isrc_idx ++) {
+ struct xenisrc *isrc;
+ u_int vector;
+
+ vector = first_evtchn_irq + isrc_idx;
+ isrc = (struct xenisrc *)intr_lookup_source(vector);
+ if (isrc != NULL
+ && isrc->xi_type == EVTCHN_TYPE_UNBOUND) {
+ KASSERT(!xen_arch_intr_has_handlers(isrc),
+ ("Free evtchn still has handlers"));
+ isrc->xi_type = type;
+ return (isrc);
+ }
+ }
+ return (NULL);
+}
+
+/**
+ * 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(struct malloc_type *mtype, const char *name __unused,
+ enum evtchn_type type, evtchn_port_t port)
+{
+ static int warned;
+ struct xenisrc *isrc;
+ unsigned int vector;
+
+ mtx_lock(&xen_intr_x86_lock);
+ isrc = xen_intr_find_unused_isrc(type);
+
+ if (isrc != NULL) {
+ mtx_unlock(&xen_intr_x86_lock);
+ goto out;
+ }
+
+ 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), mtype, M_WAITOK | M_ZERO);
+ isrc->xi_arch.xai_intsrc.is_pic = &xen_intr_pic;
+ isrc->xi_arch.xai_vector = vector;
+ isrc->xi_type = type;
+ if (intr_register_source(&isrc->xi_arch.xai_intsrc) != 0) {
+ free(isrc, mtype);
+ return (NULL);
+ }
+
+out:
+ /* xen_intr_assign_cpu() requires this to be set */
+ isrc->xi_port = port;
+
+#ifdef SMP
+ if (type == EVTCHN_TYPE_PORT) {
+ /*
+ * By default all interrupts are assigned to vCPU#0
+ * unless specified otherwise, so shuffle them to balance
+ * the interrupt load.
+ */
+ xen_intr_assign_cpu(isrc, intr_next_cpu(0));
+ }
+#endif
+
+ return (isrc);
+}
+
+void
+xen_arch_intr_release(struct malloc_type *mtype __unused, struct xenisrc *isrc)
+{
+ isrc->xi_cpu = 0;
+ isrc->xi_port = ~0;
+ isrc->xi_cookie = NULL;
+ /*
+ * Fun with locking here. xen_intr_x86_lock is actually controlling
+ * *allocation*. This means the isrc isn't under control of the lock
+ * until ->xi_type == EVTCHN_TYPE_UNBOUND. The consequence is
+ * atomic_store_rel() is appropriate since we merely need the other
+ * stores to complete before this one. This one simply needs to
+ * complete atomically.
+ */
+ atomic_store_rel_32(&isrc->xi_type, EVTCHN_TYPE_UNBOUND);
+}
+
bool
xen_arch_intr_has_handlers(struct xenisrc *isrc)
{
Index: sys/xen/arch-intr.h
===================================================================
--- sys/xen/arch-intr.h
+++ sys/xen/arch-intr.h
@@ -62,6 +62,9 @@
/******************* Functions implemented by each architecture **************/
void xen_arch_intr_init(void);
+struct xenisrc *xen_arch_intr_alloc(struct malloc_type *mtype, const char *name,
+ enum evtchn_type type, evtchn_port_t port);
+void xen_arch_intr_release(struct malloc_type *mtype, struct xenisrc *isrc);
bool xen_arch_intr_has_handlers(struct xenisrc *isrc);
bool xen_arch_intr_execute_handlers(struct xenisrc *isrc,
struct trapframe *frame);
Index: sys/xen/xen_intr.c
===================================================================
--- sys/xen/xen_intr.c
+++ sys/xen/xen_intr.c
@@ -50,7 +50,6 @@
#include <vm/vm.h>
#include <vm/pmap.h>
-#include <machine/intr_machdep.h>
#include <machine/smp.h>
#include <machine/stdarg.h>
@@ -71,15 +70,6 @@
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.
*/
@@ -127,7 +117,6 @@
* MUST be true for all values of i which are valid indicies of the array.
*/
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];
/*------------------------- Private Functions --------------------------------*/
@@ -226,105 +215,6 @@
intrcnt_add(buf, &pcpu->evtchn_intrcnt);
}
-/**
- * Search for an already allocated but currently unused Xen interrupt
- * source object.
- *
- * \param type Restrict the search to interrupt sources of the given
- * type.
- *
- * \return A pointer to a free Xen interrupt source object or NULL.
- */
-static struct xenisrc *
-xen_intr_find_unused_isrc(enum evtchn_type type)
-{
- int isrc_idx;
-
- mtx_assert(&xen_intr_x86_lock, MA_OWNED);
-
- for (isrc_idx = 0; isrc_idx < xen_intr_auto_vector_count; isrc_idx ++) {
- struct xenisrc *isrc;
- u_int vector;
-
- vector = first_evtchn_irq + isrc_idx;
- isrc = (struct xenisrc *)intr_lookup_source(vector);
- if (isrc != NULL
- && isrc->xi_type == EVTCHN_TYPE_UNBOUND) {
- KASSERT(!xen_arch_intr_has_handlers(isrc),
- ("Free evtchn still has handlers"));
- isrc->xi_type = type;
- return (isrc);
- }
- }
- return (NULL);
-}
-
-/**
- * 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(enum evtchn_type type, evtchn_port_t port)
-{
- static int warned;
- struct xenisrc *isrc;
- unsigned int vector;
-
- mtx_lock(&xen_intr_x86_lock);
- isrc = xen_intr_find_unused_isrc(type);
-
- if (isrc != NULL) {
- mtx_unlock(&xen_intr_x86_lock);
- goto out;
- }
-
- 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.xai_intsrc.is_pic = &xen_intr_pic;
- isrc->xi_arch.xai_vector = vector;
- isrc->xi_type = type;
- if (intr_register_source(&isrc->xi_arch.xai_intsrc) != 0) {
- free(isrc, M_XENINTR);
- return (NULL);
- }
-
-out:
- /* xen_intr_assign_cpu() requires this to be set */
- isrc->xi_port = port;
-
-#ifdef SMP
- if (type == EVTCHN_TYPE_PORT) {
- /*
- * By default all interrupts are assigned to vCPU#0
- * unless specified otherwise, so shuffle them to balance
- * the interrupt load.
- */
- xen_intr_assign_cpu(isrc, intr_next_cpu(0));
- }
-#endif
-
- return (isrc);
-}
-
/**
* Attempt to free an active Xen interrupt source object.
*
@@ -358,18 +248,8 @@
/* not reachable from xen_intr_port_to_isrc[], therefore unlock */
mtx_unlock(&xen_intr_isrc_lock);
- isrc->xi_cpu = 0;
- isrc->xi_port = ~0;
- isrc->xi_cookie = NULL;
- /*
- * Fun with locking here. xen_intr_x86_lock is actually controlling
- * *allocation*. This means the isrc isn't under control of the lock
- * until ->xi_type == EVTCHN_TYPE_UNBOUND. The consequence is
- * atomic_store_rel() is appropriate since we merely need the other
- * stores to complete before this one. This one simply needs to
- * complete atomically.
- */
- atomic_store_rel_32(&isrc->xi_type, EVTCHN_TYPE_UNBOUND);
+ xen_arch_intr_release(M_XENINTR, isrc);
+
return (0);
}
@@ -409,7 +289,7 @@
return (EINVAL);
}
- isrc = xen_intr_alloc_isrc(type, local_port);
+ isrc = xen_arch_intr_alloc(M_XENINTR, intr_owner, type, local_port);
if (isrc == NULL)
return (ENOSPC);
mtx_lock(&xen_intr_isrc_lock);
@@ -592,8 +472,6 @@
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.
@@ -633,16 +511,6 @@
}
SYSINIT(xen_intrcnt_init, SI_SUB_INTR, SI_ORDER_MIDDLE, xen_intrcnt_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 ---------------------------*/
/**
* Prepare this PIC for system suspension.
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Jan 24, 4:50 PM (3 h, 19 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
27899244
Default Alt Text
D30936.id96851.diff (10 KB)
Attached To
Mode
D30936: xen/intr: move interrupt allocation/release to architecture
Attached
Detach File
Event Timeline
Log In to Comment