Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 11 Aug 2014 16:57:47 +0000 (UTC)
From:      Andrew Turner <andrew@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r269819 - in projects/arm64/sys: arm/arm arm64/arm64 arm64/include
Message-ID:  <53e8f60c.23fc.37502c6a@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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);
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?53e8f60c.23fc.37502c6a>