svn commit: r269819 - in projects/arm64/sys: arm/arm arm64/arm64 arm64/include
Andrew Turner
andrew at FreeBSD.org
Mon Aug 11 16:57:48 UTC 2014
Author: andrew
Date: Mon Aug 11 16:57:47 2014
New Revision: 269819
URL: http://svnweb.freebsd.org/changeset/base/269819
Log:
Get interrupts working through the GICv2 driver.
Modified:
projects/arm64/sys/arm/arm/gic.c
projects/arm64/sys/arm64/arm64/exception.S
projects/arm64/sys/arm64/arm64/intr_machdep.c
projects/arm64/sys/arm64/arm64/pic_if.m
projects/arm64/sys/arm64/include/intr.h
Modified: projects/arm64/sys/arm/arm/gic.c
==============================================================================
--- projects/arm64/sys/arm/arm/gic.c Mon Aug 11 16:57:42 2014 (r269818)
+++ projects/arm64/sys/arm/arm/gic.c Mon Aug 11 16:57:47 2014 (r269819)
@@ -135,10 +135,10 @@ static struct arm_gic_softc *arm_gic_sc
static int gic_config_irq(int irq, enum intr_trigger trig,
enum intr_polarity pol);
-static void gic_pre_filter(device_t, u_int);
-static void gic_post_filter(device_t, u_int);
-void gic_mask_irq(device_t, u_int);
-void gic_unmask_irq(device_t, u_int);
+static pic_dispatch_t gic_dispatch;
+static pic_eoi_t gic_eoi;
+static pic_mask_t gic_mask_irq;
+static pic_unmask_t gic_unmask_irq;
static int
arm_gic_probe(device_t dev)
@@ -269,8 +269,8 @@ static device_method_t arm_gic_methods[]
DEVMETHOD(device_attach, arm_gic_attach),
/* pic_if */
- DEVMETHOD(pic_pre_filter, gic_pre_filter),
- DEVMETHOD(pic_post_filter, gic_post_filter),
+ DEVMETHOD(pic_dispatch, gic_dispatch),
+ DEVMETHOD(pic_eoi, gic_eoi),
DEVMETHOD(pic_mask, gic_mask_irq),
DEVMETHOD(pic_unmask, gic_unmask_irq),
@@ -289,13 +289,37 @@ EARLY_DRIVER_MODULE(gic, simplebus, arm_
BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE);
DRIVER_MODULE(gic, ofwbus, arm_gic_driver, arm_gic_devclass, 0, 0);
-static void
-gic_pre_filter(device_t dev, u_int irq)
+static void gic_dispatch(device_t dev, struct trapframe *frame)
{
+ uint32_t active_irq;
+ int first = 1;
+
+ while (1) {
+ active_irq = gic_c_read_4(GICC_IAR);
+
+ /*
+ * Immediatly EOIR the SGIs, because doing so requires the other
+ * bits (ie CPU number), not just the IRQ number, and we do not
+ * have this information later.
+ */
+
+ if ((active_irq & 0x3ff) <= GIC_LAST_IPI)
+ gic_c_write_4(GICC_EOIR, active_irq);
+ active_irq &= 0x3FF;
+
+ if (active_irq == 0x3FF) {
+ if (first)
+ printf("Spurious interrupt detected\n");
+ return;
+ }
+
+ cpu_dispatch_intr(active_irq, frame);
+ first = 0;
+ }
}
static void
-gic_post_filter(device_t dev, u_int irq)
+gic_eoi(device_t dev, u_int irq)
{
/* TODO: Get working on arm64 */
#if 0
Modified: projects/arm64/sys/arm64/arm64/exception.S
==============================================================================
--- projects/arm64/sys/arm64/arm64/exception.S Mon Aug 11 16:57:42 2014 (r269818)
+++ projects/arm64/sys/arm64/arm64/exception.S Mon Aug 11 16:57:47 2014 (r269819)
@@ -103,6 +103,13 @@ handle_el1h_sync:
restore_registers
eret
+handle_el1h_irq:
+ save_registers
+ mov x0, sp
+ bl cpu_intr
+ restore_registers
+ eret
+
.macro vempty
.align 7
EMIT('Z');
@@ -114,6 +121,11 @@ handle_el1h_sync:
b handle_el1h_sync
.endm
+.macro el1h_irq
+ .align 7
+ b handle_el1h_irq
+.endm
+
.macro el1h_error
.align 7
EMIT('C');
@@ -129,7 +141,7 @@ exception_vectors:
vempty /* Error EL1t */
el1h_sync /* Synchronous EL1h */
- vempty /* IRQ EL1h */
+ el1h_irq /* IRQ EL1h */
vempty /* FIQ EL1h */
el1h_error /* Error EL1h */
Modified: projects/arm64/sys/arm64/arm64/intr_machdep.c
==============================================================================
--- projects/arm64/sys/arm64/arm64/intr_machdep.c Mon Aug 11 16:57:42 2014 (r269818)
+++ projects/arm64/sys/arm64/arm64/intr_machdep.c Mon Aug 11 16:57:47 2014 (r269819)
@@ -87,61 +87,26 @@ arm_unmask_irq(u_int irq)
PIC_UNMASK(root_pic, irq);
}
-#if 0
static void
-mips_mask_soft_irq(void *source)
-{
- uintptr_t irq = (uintptr_t)source;
-
- mips_wr_status(mips_rd_status() & ~((1 << irq) << 8));
-}
-
-static void
-mips_unmask_soft_irq(void *source)
-{
- uintptr_t irq = (uintptr_t)source;
-
- mips_wr_status(mips_rd_status() | ((1 << irq) << 8));
-}
-
-/*
- * Perform initialization of interrupts prior to setting
- * handlings
- */
-void
-cpu_init_interrupts()
+intr_pre_ithread(void *arg)
{
- int i;
- char name[MAXCOMLEN + 1];
-
- /*
- * Initialize all available vectors so spare IRQ
- * would show up in systat output
- */
- for (i = 0; i < NSOFT_IRQS; i++) {
- snprintf(name, MAXCOMLEN + 1, "sint%d:", i);
- mips_intr_counters[i] = mips_intrcnt_create(name);
- }
+ u_int irq = (uintptr_t)arg;
- for (i = 0; i < NHARD_IRQS; i++) {
- snprintf(name, MAXCOMLEN + 1, "int%d:", i);
- mips_intr_counters[NSOFT_IRQS + i] = mips_intrcnt_create(name);
- }
+ PIC_PRE_ITHREAD(root_pic, irq);
}
-#endif
static void
-intr_pre_ithread(void *arg)
+intr_post_ithread(void *arg)
{
- int irq = (uintptr_t)arg;
+ u_int irq = (uintptr_t)arg;
- PIC_PRE_FILTER(root_pic, irq);
+ PIC_POST_ITHREAD(root_pic, irq);
}
static void
-intr_post_ithread(void *arg)
+intr_post_filter(void *arg)
{
- int irq = (uintptr_t)arg;
+ u_int irq = (uintptr_t)arg;
PIC_POST_FILTER(root_pic, irq);
}
@@ -172,7 +137,7 @@ cpu_establish_intr(const char *name, dri
if (event == NULL) {
error = intr_event_create(&event, (void *)(uintptr_t)irq, 0,
irq, intr_pre_ithread, intr_post_ithread,
- NULL, NULL, "int%d", irq);
+ intr_post_filter, NULL, "int%d", irq);
if (error)
return;
intr_events[irq] = event;
@@ -188,65 +153,24 @@ cpu_establish_intr(const char *name, dri
#endif
}
-#if 0
void
-cpu_intr(struct trapframe *tf)
+cpu_dispatch_intr(u_int irq, struct trapframe *tf)
{
struct intr_event *event;
- register_t cause, status;
- int hard, i, intr;
- critical_enter();
-
- cause = mips_rd_cause();
- status = mips_rd_status();
- intr = (cause & MIPS_INT_MASK) >> 8;
- /*
- * Do not handle masked interrupts. They were masked by
- * pre_ithread function (mips_mask_XXX_intr) and will be
- * unmasked once ithread is through with handler
- */
- intr &= (status & MIPS_INT_MASK) >> 8;
- while ((i = fls(intr)) != 0) {
- intr &= ~(1 << (i - 1));
- switch (i) {
- case 1: case 2:
- /* Software interrupt. */
- i--; /* Get a 0-offset interrupt. */
- hard = 0;
- event = softintr_events[i];
- mips_intrcnt_inc(mips_intr_counters[i]);
- break;
- default:
- /* Hardware interrupt. */
- i -= 2; /* Trim software interrupt bits. */
- i--; /* Get a 0-offset interrupt. */
- hard = 1;
- event = hardintr_events[i];
- mips_intrcnt_inc(mips_intr_counters[NSOFT_IRQS + i]);
- break;
- }
-
- if (!event || TAILQ_EMPTY(&event->ie_handlers)) {
- printf("stray %s interrupt %d\n",
- hard ? "hard" : "soft", i);
- continue;
- }
-
- if (intr_event_handle(event, tf) != 0) {
- printf("stray %s interrupt %d\n",
- hard ? "hard" : "soft", i);
- }
+ event = intr_events[irq];
+ if (intr_event_handle(event, tf) != 0) {
+ /* Stray irq */
+ printf("Stray IRQ %u\n", irq);
+ arm_mask_irq(irq);
}
+}
- KASSERT(i == 0, ("all interrupts handled"));
-
+void
+cpu_intr(struct trapframe *tf)
+{
+ critical_enter();
+ PIC_DISPATCH(root_pic, tf);
critical_exit();
-
-#ifdef HWPMC_HOOKS
- if (pmc_hook && (PCPU_GET(curthread)->td_pflags & TDP_CALLCHAIN))
- pmc_hook(PCPU_GET(curthread), PMC_FN_USER_CALLCHAIN, tf);
-#endif
}
-#endif
Modified: projects/arm64/sys/arm64/arm64/pic_if.m
==============================================================================
--- projects/arm64/sys/arm64/arm64/pic_if.m Mon Aug 11 16:57:42 2014 (r269818)
+++ projects/arm64/sys/arm64/arm64/pic_if.m Mon Aug 11 16:57:47 2014 (r269819)
@@ -43,14 +43,19 @@ CODE {
*pol = INTR_POLARITY_CONFORM;
}
- static void pic_pre_filter(device_t dev, u_int irq)
+ static void pic_pre_ithread(device_t dev, u_int irq)
{
PIC_MASK(dev, irq);
+ PIC_EOI(dev, irq);
}
- static void pic_post_filter(device_t dev, u_int irq)
+ static void pic_post_ithread(device_t dev, u_int irq)
{
PIC_UNMASK(dev, irq);
+ }
+
+ static void pic_post_filter(device_t dev, u_int irq)
+ {
PIC_EOI(dev, irq);
}
};
@@ -87,10 +92,15 @@ METHOD void enable {
u_int vector;
};
-METHOD void pre_filter {
+METHOD void pre_ithread {
+ device_t dev;
+ u_int irq;
+} DEFAULT pic_pre_ithread;
+
+METHOD void post_ithread {
device_t dev;
u_int irq;
-} DEFAULT pic_pre_filter;
+} DEFAULT pic_post_ithread;
METHOD void post_filter {
device_t dev;
Modified: projects/arm64/sys/arm64/include/intr.h
==============================================================================
--- projects/arm64/sys/arm64/include/intr.h Mon Aug 11 16:57:42 2014 (r269818)
+++ projects/arm64/sys/arm64/include/intr.h Mon Aug 11 16:57:47 2014 (r269819)
@@ -32,6 +32,8 @@
void cpu_set_pic(device_t, u_int);
void cpu_establish_intr(const char *, driver_filter_t *, void (*)(void*),
void *, int, int, void **);
+void cpu_dispatch_intr(u_int, struct trapframe *);
+void cpu_intr(struct trapframe *);
void arm_mask_irq(u_int);
void arm_unmask_irq(u_int);
More information about the svn-src-projects
mailing list