Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F147392314
D40161.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
5 KB
Referenced Files
None
Subscribers
None
D40161.diff
View Options
diff --git a/sys/kern/subr_intr.c b/sys/kern/subr_intr.c
--- a/sys/kern/subr_intr.c
+++ b/sys/kern/subr_intr.c
@@ -94,13 +94,16 @@
MALLOC_DEFINE(M_INTRNG, "intr", "intr interrupt handling");
/* Main interrupt handler called from assembler -> 'hidden' for C code. */
+void intr_irq_handler_type(struct trapframe *tf, uint32_t type);
void intr_irq_handler(struct trapframe *tf);
/* Root interrupt controller stuff. */
device_t intr_irq_root_dev;
+static intr_irq_type_filter_t *irq_root_type_filter;
static intr_irq_filter_t *irq_root_filter;
static void *irq_root_arg;
static u_int irq_root_ipicount;
+static uint32_t irq_root_typemask;
struct intr_pic_child {
SLIST_ENTRY(intr_pic_child) pc_next;
@@ -337,12 +340,23 @@
* from the assembler, where CPU interrupt is served.
*/
void
-intr_irq_handler(struct trapframe *tf)
+intr_irq_handler_type(struct trapframe *tf, uint32_t type)
{
struct trapframe * oldframe;
struct thread * td;
- KASSERT(irq_root_filter != NULL, ("%s: no filter", __func__));
+ KASSERT(irq_root_type_filter != NULL, ("%s: no filter", __func__));
+ KASSERT((irq_root_typemask & type) != 0,
+ ("%s: unknown irq type (%x)", __func__, type));
+
+ /*
+ * We could allow this possibility, but it doesn't make sense at the
+ * moment so we should defend against it early on. Root filter
+ * implementations should be more carefully considered if we start to
+ * allow multiple types firing at once for some reason.
+ */
+ KASSERT((type & ~(1 << (ffs(type) - 1))) == 0,
+ ("%s: multiple irq types specified (%x)", __func__, type));
kasan_mark(tf, sizeof(*tf), sizeof(*tf), 0);
@@ -351,7 +365,7 @@
td = curthread;
oldframe = td->td_intr_frame;
td->td_intr_frame = tf;
- irq_root_filter(irq_root_arg);
+ irq_root_type_filter(irq_root_arg, type);
td->td_intr_frame = oldframe;
critical_exit();
#ifdef HWPMC_HOOKS
@@ -361,6 +375,12 @@
#endif
}
+void
+intr_irq_handler(struct trapframe *tf)
+{
+ intr_irq_handler_type(tf, INTR_TYPE_IRQ);
+}
+
int
intr_child_irq_handler(struct intr_pic *parent, uintptr_t irq)
{
@@ -883,8 +903,9 @@
* an interrupts property and thus no explicit interrupt parent."
*/
int
-intr_pic_claim_root(device_t dev, intptr_t xref, intr_irq_filter_t *filter,
- void *arg, u_int ipicount)
+intr_pic_claim_root_type(device_t dev, intptr_t xref,
+ intr_irq_type_filter_t *filter, void *arg, u_int ipicount,
+ uint32_t typemask)
{
struct intr_pic *pic;
@@ -903,6 +924,11 @@
return (EINVAL);
}
+ if (typemask == 0) {
+ device_printf(dev, "typemask must be specified\n");
+ return (EINVAL);
+ }
+
/*
* Only one interrupt controllers could be on the root for now.
* Note that we further suppose that there is not threaded interrupt
@@ -914,14 +940,44 @@
}
intr_irq_root_dev = dev;
- irq_root_filter = filter;
+ irq_root_type_filter = filter;
irq_root_arg = arg;
irq_root_ipicount = ipicount;
+ irq_root_typemask = typemask;
debugf("irq root set to %s\n", device_get_nameunit(dev));
return (0);
}
+/*
+ * Shim from a typed filter to an untyped filter. It's expected that if an
+ * interrupt controller used intr_pic_claim_root(), they'll go through this shim
+ * that specifically only handles the basic irq type. This maintains KBI to
+ * avoid needing to touch existing drivers, they can still use a driver_intr_t
+ * compatible filter as long as they don't care about types (i.e., all existing
+ * drivers).
+ */
+static int
+intr_pic_root_type_filter(void *arg, uint32_t type __diagused)
+{
+
+ MPASS(type == INTR_TYPE_IRQ);
+ return (irq_root_filter(arg));
+}
+
+int
+intr_pic_claim_root(device_t dev, intptr_t xref, intr_irq_filter_t *filter,
+ void *arg, u_int ipicount)
+{
+ int error;
+
+ error = intr_pic_claim_root_type(dev, xref, intr_pic_root_type_filter,
+ arg, ipicount, INTR_TYPE_IRQ);
+ if (error == 0)
+ irq_root_filter = filter;
+ return (error);
+}
+
/*
* Add a handler to manage a sub range of a parents interrupts.
*/
diff --git a/sys/sys/intr.h b/sys/sys/intr.h
--- a/sys/sys/intr.h
+++ b/sys/sys/intr.h
@@ -63,14 +63,31 @@
#ifdef notyet
#define INTR_SOLO INTR_MD1
+typedef int intr_irq_type_filter_t(void *arg, uint32_t type, struct trapframe *tf);
typedef int intr_irq_filter_t(void *arg, struct trapframe *tf);
#else
+typedef int intr_irq_type_filter_t(void *arg, uint32_t type);
typedef int intr_irq_filter_t(void *arg);
#endif
typedef int intr_child_irq_filter_t(void *arg, uintptr_t irq);
#define INTR_ISRC_NAMELEN (MAXCOMLEN + 1)
+/*
+ * For INTR types, the top two bits are reserved for INTRNG usage. Only one of
+ * the two bits is used at this time. The rest of the space is divided in two,
+ * the lower half for machdep reservations and the upper half for platform
+ * reservations.
+ */
+#define INTR_TYPE_MD_FIRST 0x00000001
+#define INTR_TYPE_MD_LAST 0x00004000
+#define INTR_TYPE_PLATFORM_FIRST 0x00008000
+#define INTR_TYPE_PLATFORM_LAST 0x20000000
+#define INTR_TYPE_INTRNG_FIRST 0x40000000
+
+/* INTRNG's slice */
+#define INTR_TYPE_IRQ (INTR_TYPE_INTRNG_FIRST << 0)
+
#define INTR_ISRCF_IPI 0x01 /* IPI interrupt */
#define INTR_ISRCF_PPI 0x02 /* PPI interrupt */
#define INTR_ISRCF_BOUND 0x04 /* bound to a CPU */
@@ -110,6 +127,8 @@
struct intr_pic *intr_pic_register(device_t, intptr_t);
int intr_pic_deregister(device_t, intptr_t);
+int intr_pic_claim_root_type(device_t, intptr_t, intr_irq_type_filter_t *, void *,
+ u_int, uint32_t);
int intr_pic_claim_root(device_t, intptr_t, intr_irq_filter_t *, void *, u_int);
int intr_pic_add_handler(device_t, struct intr_pic *,
intr_child_irq_filter_t *, void *, uintptr_t, uintptr_t);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Mar 11, 2:40 PM (10 h, 12 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29541823
Default Alt Text
D40161.diff (5 KB)
Attached To
Mode
D40161: arm64/intrng: add support for FIQs
Attached
Detach File
Event Timeline
Log In to Comment