From 35228f775a9a119723aa6c44f1c23a80ce04e899 Mon Sep 17 00:00:00 2001 From: bjh21 Date: Tue, 21 Aug 2001 22:47:17 +0000 Subject: [PATCH] Two related changes: Make splhigh disable IRQs at the CPU rather than at the IOC. This has the potential to be faster, and more importantly ensures that splhigh() blocks FIQ downgrades. Have a variable which indicates that a FIQ downgrade is required, and ensure that the IOC "force IRQ" bit is turned on in this case. This ensures that FIQ downgrades don't get lost if something happens to be fiddling with the interrupt mask at the wrong moment. --- sys/arch/arm26/arm26/fiq_util.S | 11 +++++-- sys/arch/arm26/arm26/irq.c | 52 ++++++++++++++++++++++++--------- sys/arch/arm26/arm26/start.c | 23 ++------------- sys/arch/arm26/include/intr.h | 4 +-- 4 files changed, 51 insertions(+), 39 deletions(-) diff --git a/sys/arch/arm26/arm26/fiq_util.S b/sys/arch/arm26/arm26/fiq_util.S index 7d17e2e58f2e..a4da27aed0a6 100644 --- a/sys/arch/arm26/arm26/fiq_util.S +++ b/sys/arch/arm26/arm26/fiq_util.S @@ -1,4 +1,4 @@ -/* $NetBSD: fiq_util.S,v 1.1 2001/08/20 23:08:10 bjh21 Exp $ */ +/* $NetBSD: fiq_util.S,v 1.2 2001/08/21 22:47:17 bjh21 Exp $ */ /*- * Copyright (c) 2001 Ben Harris @@ -29,7 +29,7 @@ #include -RCSID("$NetBSD: fiq_util.S,v 1.1 2001/08/20 23:08:10 bjh21 Exp $") +RCSID("$NetBSD: fiq_util.S,v 1.2 2001/08/21 22:47:17 bjh21 Exp $") #include #include @@ -45,6 +45,11 @@ ENTRY(fiq_downgrade) strb r13, [r12, #(IOC_IRQMSKA << 2)] mov r13, #0 strb r13, [r12, #(IOC_FIQMSK << 2)] + ldr r12, Lfiq_want_downgrade + mov r13, #1 + str r13, [r12] subs pc, r14, #4 Lioc_base: - .word 0x03200000 \ No newline at end of file + .word 0x03200000 +Lfiq_want_downgrade: + .word _C_LABEL(fiq_want_downgrade) \ No newline at end of file diff --git a/sys/arch/arm26/arm26/irq.c b/sys/arch/arm26/arm26/irq.c index 041f6a558442..568280ec3bf7 100644 --- a/sys/arch/arm26/arm26/irq.c +++ b/sys/arch/arm26/arm26/irq.c @@ -1,4 +1,4 @@ -/* $NetBSD: irq.c,v 1.19 2001/08/20 23:08:10 bjh21 Exp $ */ +/* $NetBSD: irq.c,v 1.20 2001/08/21 22:47:18 bjh21 Exp $ */ /*- * Copyright (c) 2000, 2001 Ben Harris @@ -33,7 +33,7 @@ #include -__RCSID("$NetBSD: irq.c,v 1.19 2001/08/20 23:08:10 bjh21 Exp $"); +__RCSID("$NetBSD: irq.c,v 1.20 2001/08/21 22:47:18 bjh21 Exp $"); #include #include /* for cold */ @@ -76,6 +76,10 @@ extern char *irqnames[]; int current_intr_depth = 0; +#if NFIQ > 0 +int fiq_want_downgrade; +#endif + /* * Interrupt masks are held in 32-bit integers. At present, the * bottom eight bits are interrupt register A on the IOC, and the next @@ -133,13 +137,8 @@ irq_handler(struct irqframe *irqf) status |= unixbp_irq_status_full() << IRQ_UNIXBP_BASE; #endif - /* Get interrupt-disabling back to the IOC */ -#if NFIQ > 0 - s = hardsplx(IPL_HIGH); /* In case it's a FIQ downgrade. */ -#else + /* We're already in splhigh, but make sure the kernel knows that. */ s = splhigh(); -#endif - int_on(); #if 0 printf("*"); @@ -149,8 +148,9 @@ irq_handler(struct irqframe *irqf) stray = 1; #if NFIQ > 0 /* Check for downgraded FIQs. */ - if (status & (1 << IOC_IRQ_1)) { - fiq_downgrade_handler(); + if (fiq_want_downgrade) { + fiq_want_downgrade = 0; + (fiq_downgrade_handler)(); goto handled; } #endif @@ -183,16 +183,17 @@ irq_handler(struct irqframe *irqf) stray = 0; } - if (__predict_false(stray)) + if (__predict_false(stray)) { log(LOG_WARNING, "Stray IRQ, status = 0x%x, spl = %d, " "mask = 0x%x\n", status, s, irqmask[s]); + Debugger(); + } handled: #if 0 printf(" handled\n"); #endif dosoftints(s); /* May lower spl to s + 1, but no lower. */ - int_off(); hardsplx(s); current_intr_depth--; } @@ -308,20 +309,43 @@ __inline int hardsplx(int s) { int was; + u_int32_t mask; + KASSERT(s < IPL_HIGH); int_off(); was = current_spl; + mask = irqmask[s]; +#if NFIQ > 0 + if (fiq_want_downgrade) + mask |= IOC_IRQ_1; +#endif /* Don't try this till we've found the IOC */ if (the_ioc != NULL) - ioc_irq_setmask(irqmask[s]); + ioc_irq_setmask(mask); #if NUNIXBP > 0 - unixbp_irq_setmask(irqmask[s] >> IRQ_UNIXBP_BASE); + unixbp_irq_setmask(mask >> IRQ_UNIXBP_BASE); #endif current_spl = s; int_on(); return was; } +int +splhigh(void) +{ + int was; + + int_off(); + was = current_spl; + current_spl = IPL_HIGH; +#ifdef DEBUG + /* Make sure that anything that turns off the I flag gets spotted. */ + if (the_ioc != NULL) + ioc_irq_setmask(0xffff); +#endif + return was; +} + int raisespl(int s) { diff --git a/sys/arch/arm26/arm26/start.c b/sys/arch/arm26/arm26/start.c index 0ced3794f876..96db78dafbe8 100644 --- a/sys/arch/arm26/arm26/start.c +++ b/sys/arch/arm26/arm26/start.c @@ -1,4 +1,4 @@ -/* $NetBSD: start.c,v 1.10 2001/05/13 13:48:11 bjh21 Exp $ */ +/* $NetBSD: start.c,v 1.11 2001/08/21 22:47:18 bjh21 Exp $ */ /*- * Copyright (c) 1998, 2000 Ben Harris * All rights reserved. @@ -32,7 +32,7 @@ #include -__KERNEL_RCSID(0, "$NetBSD: start.c,v 1.10 2001/05/13 13:48:11 bjh21 Exp $"); +__KERNEL_RCSID(0, "$NetBSD: start.c,v 1.11 2001/08/21 22:47:18 bjh21 Exp $"); #include #include @@ -196,24 +196,7 @@ start(initbootconfig) /* Set up the undefined instruction handlers. */ undefined_init(); - /* - * This is a nasty bit. Because the kernel uses a 26-bit APCS - * variant, the CPU interrupt disable flags get munged on - * every function return. Thus, we need to enable interrupts - * at the CPU now since this is the last function we control - * that won't return. In order to be able to do this, we need - * to ensure we won't get any interrupts before we're ready - * for them. For now, I'll assume we've got an IOC doing all - * this at the usual location, but it should be done more - * elegantly. - */ - -#if NIOC > 0 - *(volatile u_char *)(0x03200000 + (IOC_IRQMSKA << 2)) = 0; - *(volatile u_char *)(0x03200000 + (IOC_IRQMSKB << 2)) = 0; - *(volatile u_char *)(0x03200000 + (IOC_FIQMSK << 2)) = 0; -#endif - int_on(); + splhigh(); /* * Locate process 0's user structure, in the bottom of its kernel diff --git a/sys/arch/arm26/include/intr.h b/sys/arch/arm26/include/intr.h index 47276a9d9e74..a926ea875659 100644 --- a/sys/arch/arm26/include/intr.h +++ b/sys/arch/arm26/include/intr.h @@ -1,4 +1,4 @@ -/* $NetBSD: intr.h,v 1.9 2001/05/13 13:47:23 bjh21 Exp $ */ +/* $NetBSD: intr.h,v 1.10 2001/08/21 22:47:18 bjh21 Exp $ */ /*- * Copyright (c) 1998, 2000 Ben Harris * All rights reserved. @@ -74,7 +74,6 @@ #define splserial() raisespl(IPL_SERIAL) #define splclock() raisespl(IPL_CLOCK) #define splstatclock() raisespl(IPL_STATCLOCK) -#define splhigh() raisespl(IPL_HIGH) #define splsched() splhigh() #define spllock() splhigh() @@ -85,6 +84,7 @@ extern int current_spl_level; /* XXX tautological name */ +extern int splhigh(void); extern int raisespl(int); extern void lowerspl(int); extern int hardsplx(int);