svn commit: r269626 - in projects/arm64/sys: arm/arm arm64/arm64 arm64/include conf
Andrew Turner
andrew at FreeBSD.org
Wed Aug 6 14:20:03 UTC 2014
Author: andrew
Date: Wed Aug 6 14:20:01 2014
New Revision: 269626
URL: http://svnweb.freebsd.org/changeset/base/269626
Log:
First cut at interrupt handling
Added:
projects/arm64/sys/arm64/arm64/intr_machdep.c
projects/arm64/sys/arm64/arm64/pic_if.m
projects/arm64/sys/arm64/include/intr.h
- copied, changed from r269625, projects/arm64/sys/arm64/include/cpufunc.h
Modified:
projects/arm64/sys/arm/arm/gic.c
projects/arm64/sys/arm64/arm64/autoconf.c
projects/arm64/sys/arm64/arm64/nexus.c
projects/arm64/sys/arm64/include/cpufunc.h
projects/arm64/sys/conf/files.arm64
Modified: projects/arm64/sys/arm/arm/gic.c
==============================================================================
--- projects/arm64/sys/arm/arm/gic.c Wed Aug 6 14:19:57 2014 (r269625)
+++ projects/arm64/sys/arm/arm/gic.c Wed Aug 6 14:20:01 2014 (r269626)
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2011 The FreeBSD Foundation
+ * Copyright (c) 2014 Andrew Turner
* All rights reserved.
*
* Developed by Damjan Marion <damjan.marion at gmail.com>
@@ -47,9 +48,7 @@ __FBSDID("$FreeBSD$");
#include <sys/lock.h>
#include <sys/mutex.h>
#include <machine/bus.h>
-#if 0
#include <machine/intr.h>
-#endif
#include <machine/smp.h>
#include <dev/fdt/fdt_common.h>
@@ -57,6 +56,9 @@ __FBSDID("$FreeBSD$");
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
+
+#include "pic_if.h"
+
/* We are using GICv2 register naming */
/* Distributor Registers */
@@ -131,7 +133,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_post_filter(void *);
+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 int
arm_gic_probe(device_t dev)
@@ -217,11 +222,7 @@ arm_gic_attach(device_t dev)
sc->nirqs = gic_d_read_4(GICD_TYPER);
sc->nirqs = 32 * ((sc->nirqs & 0x1f) + 1);
-#if 0
- /* Set up function pointers */
- arm_post_filter = gic_post_filter;
- arm_config_irq = gic_config_irq;
-#endif
+ cpu_set_pic(dev, sc->nirqs);
icciidr = gic_c_read_4(GICC_IIDR);
device_printf(dev,"pn 0x%x, arch 0x%x, rev 0x%x, implementer 0x%x sc->nirqs %u\n",
@@ -263,6 +264,13 @@ arm_gic_attach(device_t dev)
static device_method_t arm_gic_methods[] = {
DEVMETHOD(device_probe, arm_gic_probe),
DEVMETHOD(device_attach, arm_gic_attach),
+
+ /* pic_if */
+ DEVMETHOD(pic_pre_filter, gic_pre_filter),
+ DEVMETHOD(pic_post_filter, gic_post_filter),
+ DEVMETHOD(pic_mask, gic_mask_irq),
+ DEVMETHOD(pic_unmask, gic_unmask_irq),
+
{ 0, 0 }
};
@@ -278,10 +286,13 @@ DRIVER_MODULE(gic, simplebus, arm_gic_dr
DRIVER_MODULE(gic, ofwbus, arm_gic_driver, arm_gic_devclass, 0, 0);
static void
-gic_post_filter(void *arg)
+gic_pre_filter(device_t dev, u_int irq)
{
- uintptr_t irq = (uintptr_t) arg;
+}
+static void
+gic_post_filter(device_t dev, u_int irq)
+{
gic_c_write_4(GICC_EOIR, irq);
}
@@ -311,22 +322,22 @@ arm_get_next_irq(int last_irq)
return active_irq;
}
+#endif
void
-arm_mask_irq(uintptr_t nb)
+gic_mask_irq(device_t dev, u_int irq)
{
- gic_d_write_4(GICD_ICENABLER(nb >> 5), (1UL << (nb & 0x1F)));
- gic_c_write_4(GICC_EOIR, nb);
+ gic_d_write_4(GICD_ICENABLER(irq >> 5), (1UL << (irq & 0x1F)));
+ gic_c_write_4(GICC_EOIR, irq);
}
void
-arm_unmask_irq(uintptr_t nb)
+gic_unmask_irq(device_t dev, u_int irq)
{
- gic_d_write_4(GICD_ISENABLER(nb >> 5), (1UL << (nb & 0x1F)));
+ gic_d_write_4(GICD_ISENABLER(irq >> 5), (1UL << (irq & 0x1F)));
}
-#endif
static int
gic_config_irq(int irq, enum intr_trigger trig,
Modified: projects/arm64/sys/arm64/arm64/autoconf.c
==============================================================================
--- projects/arm64/sys/arm64/arm64/autoconf.c Wed Aug 6 14:19:57 2014 (r269625)
+++ projects/arm64/sys/arm64/arm64/autoconf.c Wed Aug 6 14:20:01 2014 (r269626)
@@ -99,6 +99,7 @@ configure(void *dummy)
static void
configure_final(void *dummy)
{
+ intr_enable();
cninit_finish();
if (bootverbose)
Added: projects/arm64/sys/arm64/arm64/intr_machdep.c
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ projects/arm64/sys/arm64/arm64/intr_machdep.c Wed Aug 6 14:20:01 2014 (r269626)
@@ -0,0 +1,252 @@
+/*-
+ * Copyright (c) 2006 Oleksandr Tymoshenko
+ * Copyright (c) 2002-2004 Juli Mallett <jmallett at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification, immediately at the beginning of the file.
+ * 2. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * From: projects/arm64/sys/mips/mips/intr_machdep.c r233318
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: projects/arm64/sys/mips/mips/intr_machdep.c 233318 2012-03-22 17:47:52Z gonzo $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/cpuset.h>
+#include <sys/interrupt.h>
+
+#include <machine/intr.h>
+
+#include "pic_if.h"
+
+#define NIRQS 1024
+
+static struct intr_event *intr_events[NIRQS];
+static device_t root_pic;
+static u_int num_irq;
+
+#if 0
+static struct intr_event *softintr_events[NSOFT_IRQS];
+static mips_intrcnt_t mips_intr_counters[NSOFT_IRQS + NHARD_IRQS];
+
+static int intrcnt_index;
+
+mips_intrcnt_t
+mips_intrcnt_create(const char* name)
+{
+ mips_intrcnt_t counter = &intrcnt[intrcnt_index++];
+
+ mips_intrcnt_setname(counter, name);
+ return counter;
+}
+
+void
+mips_intrcnt_setname(mips_intrcnt_t counter, const char *name)
+{
+ int idx = counter - intrcnt;
+
+ KASSERT(counter != NULL, ("mips_intrcnt_setname: NULL counter"));
+
+ snprintf(intrnames + (MAXCOMLEN + 1) * idx,
+ MAXCOMLEN + 1, "%-*s", MAXCOMLEN, name);
+}
+#endif
+
+void
+arm_mask_irq(u_int irq)
+{
+
+ PIC_MASK(root_pic, irq);
+}
+
+void
+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()
+{
+ 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);
+ }
+
+ for (i = 0; i < NHARD_IRQS; i++) {
+ snprintf(name, MAXCOMLEN + 1, "int%d:", i);
+ mips_intr_counters[NSOFT_IRQS + i] = mips_intrcnt_create(name);
+ }
+}
+#endif
+
+static void
+intr_pre_ithread(void *arg)
+{
+ int irq = (uintptr_t)arg;
+
+ PIC_PRE_FILTER(root_pic, irq);
+}
+
+static void
+intr_post_ithread(void *arg)
+{
+ int irq = (uintptr_t)arg;
+
+ PIC_POST_FILTER(root_pic, irq);
+}
+
+void
+cpu_set_pic(device_t pic, u_int nirq)
+{
+
+ KASSERT(root_pic == NULL, ("Unable to set the pic twice"));
+ KASSERT(nirq <= NIRQS, ("PIC is trying to handle too many IRQs"));
+
+ num_irq = nirq;
+ root_pic = pic;
+}
+
+void
+cpu_establish_intr(const char *name, driver_filter_t *filt,
+ void (*handler)(void*), void *arg, int irq, int flags, void **cookiep)
+{
+ struct intr_event *event;
+ int error;
+
+ if (irq < 0 || irq >= num_irq)
+ panic("%s called for unknown intr %d", __func__, irq);
+
+ /* TODO: Add locking for the intr_events array */
+ event = intr_events[irq];
+ 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);
+ if (error)
+ return;
+ intr_events[irq] = event;
+ PIC_UNMASK(root_pic, irq);
+ }
+
+ intr_event_add_handler(event, name, filt, handler, arg,
+ intr_priority(flags), flags, cookiep);
+
+#if 0
+ mips_intrcnt_setname(mips_intr_counters[NSOFT_IRQS + irq],
+ event->ie_fullname);
+#endif
+}
+
+#if 0
+void
+cpu_intr(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);
+ }
+ }
+
+ KASSERT(i == 0, ("all interrupts handled"));
+
+ 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/nexus.c
==============================================================================
--- projects/arm64/sys/arm64/arm64/nexus.c Wed Aug 6 14:19:57 2014 (r269625)
+++ projects/arm64/sys/arm64/arm64/nexus.c Wed Aug 6 14:20:01 2014 (r269626)
@@ -58,7 +58,7 @@ __FBSDID("$FreeBSD$");
#include <vm/pmap.h>
#include <machine/resource.h>
-//#include <machine/intr.h>
+#include <machine/intr.h>
#include "opt_platform.h"
@@ -249,20 +249,16 @@ static int
nexus_setup_intr(device_t dev, device_t child, struct resource *res, int flags,
driver_filter_t *filt, driver_intr_t *intr, void *arg, void **cookiep)
{
-#if 0
int irq;
if ((rman_get_flags(res) & RF_SHAREABLE) == 0)
flags |= INTR_EXCL;
for (irq = rman_get_start(res); irq <= rman_get_end(res); irq++) {
- arm_setup_irqhandler(device_get_nameunit(child),
- filt, intr, arg, irq, flags, cookiep);
- arm_unmask_irq(irq);
+ cpu_establish_intr(device_get_nameunit(child), filt, intr,
+ arg, irq, flags, cookiep);
}
return (0);
-#endif
- panic("nexus_setup_intr");
}
static int
Added: projects/arm64/sys/arm64/arm64/pic_if.m
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ projects/arm64/sys/arm64/arm64/pic_if.m Wed Aug 6 14:20:01 2014 (r269626)
@@ -0,0 +1,119 @@
+#-
+# Copyright (c) 1998 Doug Rabson
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# from: src/sys/kern/bus_if.m,v 1.21 2002/04/21 11:16:10 markm Exp
+# $FreeBSD: projects/arm64/sys/powerpc/powerpc/pic_if.m 257059 2013-10-24 15:37:32Z nwhitehorn $
+#
+
+#include <sys/bus.h>
+#include <sys/cpuset.h>
+#include <machine/frame.h>
+
+INTERFACE pic;
+
+CODE {
+ static pic_translate_code_t pic_translate_code_default;
+
+ static void pic_translate_code_default(device_t dev, u_int irq,
+ int code, enum intr_trigger *trig, enum intr_polarity *pol)
+ {
+ *trig = INTR_TRIGGER_CONFORM;
+ *pol = INTR_POLARITY_CONFORM;
+ }
+
+ static void pic_pre_filter(device_t dev, u_int irq)
+ {
+ PIC_MASK(dev, irq);
+ }
+
+ static void pic_post_filter(device_t dev, u_int irq)
+ {
+ PIC_UNMASK(dev, irq);
+ PIC_EOI(dev, irq);
+ }
+};
+
+METHOD void bind {
+ device_t dev;
+ u_int irq;
+ cpuset_t cpumask;
+};
+
+METHOD void translate_code {
+ device_t dev;
+ u_int irq;
+ int code;
+ enum intr_trigger *trig;
+ enum intr_polarity *pol;
+} DEFAULT pic_translate_code_default;
+
+METHOD void config {
+ device_t dev;
+ u_int irq;
+ enum intr_trigger trig;
+ enum intr_polarity pol;
+};
+
+METHOD void dispatch {
+ device_t dev;
+ struct trapframe *tf;
+};
+
+METHOD void enable {
+ device_t dev;
+ u_int irq;
+ u_int vector;
+};
+
+METHOD void pre_filter {
+ device_t dev;
+ u_int irq;
+} DEFAULT pic_pre_filter;
+
+METHOD void post_filter {
+ device_t dev;
+ u_int irq;
+} DEFAULT pic_post_filter;
+
+METHOD void eoi {
+ device_t dev;
+ u_int irq;
+};
+
+METHOD void ipi {
+ device_t dev;
+ u_int cpu;
+};
+
+METHOD void mask {
+ device_t dev;
+ u_int irq;
+};
+
+METHOD void unmask {
+ device_t dev;
+ u_int irq;
+};
+
Modified: projects/arm64/sys/arm64/include/cpufunc.h
==============================================================================
--- projects/arm64/sys/arm64/include/cpufunc.h Wed Aug 6 14:19:57 2014 (r269625)
+++ projects/arm64/sys/arm64/include/cpufunc.h Wed Aug 6 14:20:01 2014 (r269626)
@@ -57,7 +57,13 @@ intr_restore(register_t s)
{
__asm __volatile("msr daif, %x0" : : "r" (s));
+}
+
+static __inline void
+intr_enable(void)
+{
+ __asm __volatile("msr daifclr, #2");
}
#endif /* _KERNEL */
Copied and modified: projects/arm64/sys/arm64/include/intr.h (from r269625, projects/arm64/sys/arm64/include/cpufunc.h)
==============================================================================
--- projects/arm64/sys/arm64/include/cpufunc.h Wed Aug 6 14:19:57 2014 (r269625, copy source)
+++ projects/arm64/sys/arm64/include/intr.h Wed Aug 6 14:20:01 2014 (r269626)
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2014 Andrew Turner
+ * Copyright (c) 2014 Andrew Turner <andrew at FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -26,39 +26,13 @@
* $FreeBSD$
*/
-#ifndef _MACHINE_CPUFUNC_H_
-#define _MACHINE_CPUFUNC_H_
+#ifndef _MACHINE_INTR_H_
+#define _MACHINE_INTR_H_
-#ifdef _KERNEL
+void cpu_set_pic(device_t, u_int);
+void cpu_establish_intr(const char *, driver_filter_t *, void (*)(void*),
+ void *, int, int, void **);
+void arm_mask_irq(u_int);
+void arm_unmask_irq(u_int);
-static __inline void
-breakpoint(void)
-{
-
- __asm("brk #0");
-}
-
-static __inline register_t
-intr_disable(void)
-{
- /* DAIF is a 32-bit register */
- uint32_t ret;
-
- __asm __volatile(
- "mrs %x0, daif \n"
- "msr daifset, #2 \n"
- : "=&r" (ret));
-
- return (ret);
-}
-
-static __inline void
-intr_restore(register_t s)
-{
-
- __asm __volatile("msr daif, %x0" : : "r" (s));
-
-}
-
-#endif /* _KERNEL */
-#endif /* _MACHINE_CPUFUNC_H_ */
+#endif /* _MACHINE_INTR_H */
Modified: projects/arm64/sys/conf/files.arm64
==============================================================================
--- projects/arm64/sys/conf/files.arm64 Wed Aug 6 14:19:57 2014 (r269625)
+++ projects/arm64/sys/conf/files.arm64 Wed Aug 6 14:20:01 2014 (r269626)
@@ -13,11 +13,13 @@ arm64/arm64/dump_machdep.c standard
arm64/arm64/elf_machdep.c standard
arm64/arm64/exception.S standard
arm64/arm64/identcpu.c standard
+arm64/arm64/intr_machdep.c standard
arm64/arm64/in_cksum.c optional inet | inet6
arm64/arm64/locore.S standard no-obj
arm64/arm64/machdep.c standard
arm64/arm64/mem.c standard
arm64/arm64/nexus.c standard
+arm64/arm64/pic_if.m standard
arm64/arm64/pmap.c standard
arm64/arm64/stack_machdep.c standard
arm64/arm64/support.c standard
More information about the svn-src-projects
mailing list