Fix newsmips interrupt handling for new mips interrupt/spl framework:

- make news3400_badaddr() work even if interrupts are disabled
   (in the old world bus error interrupt is enabled even during splhigh())
 - make ipl_sr_map values model dependent

Now GENERIC kernel boots to single user properly on R3000 NWS-3470D,
though sh(1) still gets floating point exceptions during /etc/rc scripts.
news5000 is untested (yet).
This commit is contained in:
tsutsui 2011-03-09 13:21:36 +00:00
parent 73fa5bcac3
commit 4fada584a6
4 changed files with 74 additions and 39 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: autoconf.c,v 1.34 2011/02/20 07:56:31 matt Exp $ */
/* $NetBSD: autoconf.c,v 1.35 2011/03/09 13:21:36 tsutsui Exp $ */
/*
* Copyright (c) 1988 University of Utah.
@ -49,7 +49,7 @@
#define __INTR_PRIVATE
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: autoconf.c,v 1.34 2011/02/20 07:56:31 matt Exp $");
__KERNEL_RCSID(0, "$NetBSD: autoconf.c,v 1.35 2011/03/09 13:21:36 tsutsui Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -94,19 +94,14 @@ cpu_configure(void)
/*
* Kick off autoconfiguration
*/
spl0(); /* enable all interrupts */
splhigh(); /* ...then disable device interrupts */
if (systype == NEWS3400) {
*(char *)INTEN0 = INTEN0_BERR; /* only buserr occurs */
*(char *)INTEN1 = 0;
}
(*disable_intr)();
(void)splhigh();
if (config_rootfound("mainbus", NULL) == NULL)
panic("no mainbus found");
/* Enable hardware interrupt registers. */
enable_intr();
(*enable_intr)();
/* Configuration is finished, turn on interrupts. */
spl0(); /* enable all source forcing SOFT_INTs cleared */

View File

@ -1,4 +1,4 @@
/* $NetBSD: machdep.c,v 1.112 2011/02/20 07:56:31 matt Exp $ */
/* $NetBSD: machdep.c,v 1.113 2011/03/09 13:21:36 tsutsui Exp $ */
/*
* Copyright (c) 1988 University of Utah.
@ -39,7 +39,7 @@
#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.112 2011/02/20 07:56:31 matt Exp $");
__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.113 2011/03/09 13:21:36 tsutsui Exp $");
/* from: Utah Hdr: machdep.c 1.63 91/04/24 */
@ -138,27 +138,6 @@ void to_monitor(int) __attribute__((__noreturn__));
extern void stacktrace(void); /*XXX*/
#endif
/*
* This is a mask of bits to clear in the SR when we go to a
* given interrupt priority level.
*/
const struct ipl_sr_map newsmips_ipl_sr_map = {
.sr_bits = {
[IPL_NONE] = 0,
[IPL_SOFTCLOCK] = MIPS_SOFT_INT_MASK_0,
[IPL_SOFTNET] = MIPS_SOFT_INT_MASK,
[IPL_VM] = MIPS_SOFT_INT_MASK
| MIPS_INT_MASK_0
| MIPS_INT_MASK_1,
[IPL_SCHED] = MIPS_SOFT_INT_MASK
| MIPS_INT_MASK_0
| MIPS_INT_MASK_1
| MIPS_INT_MASK_2,
[IPL_DDB] = MIPS_INT_MASK,
[IPL_HIGH] = MIPS_INT_MASK,
},
};
extern u_long bootdev;
extern char edata[], end[];
@ -284,7 +263,6 @@ mach_init(int x_boothowto, int x_bootdev, int x_bootname, int x_maxmem)
* Initialize locore-function vector.
* Clear out the I and D caches.
*/
ipl_sr_map = newsmips_ipl_sr_map;
mips_vector_init(NULL, false);
/*

View File

@ -1,4 +1,4 @@
/* $NetBSD: news3400.c,v 1.20 2011/02/20 07:56:31 matt Exp $ */
/* $NetBSD: news3400.c,v 1.21 2011/03/09 13:21:36 tsutsui Exp $ */
/*-
* Copyright (C) 1999 Tsubai Masanari. All rights reserved.
@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: news3400.c,v 1.20 2011/02/20 07:56:31 matt Exp $");
__KERNEL_RCSID(0, "$NetBSD: news3400.c,v 1.21 2011/03/09 13:21:36 tsutsui Exp $");
#define __INTR_PRIVATE
#include <sys/param.h>
@ -58,6 +58,27 @@ static volatile int badaddr_flag;
#define INT_MASK_FPU MIPS_INT_MASK_3
/*
* This is a mask of bits to clear in the SR when we go to a
* given interrupt priority level.
*/
static const struct ipl_sr_map news3400_ipl_sr_map = {
.sr_bits = {
[IPL_NONE] = 0,
[IPL_SOFTCLOCK] = MIPS_SOFT_INT_MASK_0,
[IPL_SOFTNET] = MIPS_SOFT_INT_MASK,
[IPL_VM] = MIPS_SOFT_INT_MASK
| MIPS_INT_MASK_0
| MIPS_INT_MASK_1,
[IPL_SCHED] = MIPS_SOFT_INT_MASK
| MIPS_INT_MASK_0
| MIPS_INT_MASK_1
| MIPS_INT_MASK_2,
[IPL_DDB] = MIPS_INT_MASK,
[IPL_HIGH] = MIPS_INT_MASK,
},
};
/*
* Handle news3400 interrupts.
*/
@ -179,10 +200,16 @@ news3400_level1_intr(void)
int
news3400_badaddr(void *addr, u_int size)
{
uint32_t cause;
volatile u_int x;
volatile uint8_t *intclr0 = (void *)INTCLR0;
badaddr_flag = 0;
/* clear bus error interrupt */
*intclr0 = INTCLR0_BERR;
/* bus error will cause INT4 */
switch (size) {
case 1:
x = *(volatile uint8_t *)addr;
@ -195,6 +222,15 @@ news3400_badaddr(void *addr, u_int size)
break;
}
/* also check CPU INT4 here for bus errors during splhigh() */
if (badaddr_flag == 0) {
cause = mips_cp0_cause_read();
if ((cause & MIPS_INT_MASK_4) != 0) {
badaddr_flag = 1;
*intclr0 = INTCLR0_BERR;
}
}
return badaddr_flag;
}
@ -233,7 +269,8 @@ news3400_disable_intr(void)
volatile uint8_t *inten0 = (void *)INTEN0;
volatile uint8_t *inten1 = (void *)INTEN1;
*inten0 = 0;
/* always enable bus error check so that news3400_badaddr() works */
*inten0 = INTEN0_BERR;
*inten1 = 0;
}
@ -264,6 +301,8 @@ void
news3400_init(void)
{
ipl_sr_map = news3400_ipl_sr_map;
enable_intr = news3400_enable_intr;
disable_intr = news3400_disable_intr;
enable_timer = news3400_enable_timer;

View File

@ -1,4 +1,4 @@
/* $NetBSD: news5000.c,v 1.18 2011/02/20 07:56:32 matt Exp $ */
/* $NetBSD: news5000.c,v 1.19 2011/03/09 13:21:36 tsutsui Exp $ */
/*-
* Copyright (C) 1999 SHIMIZU Ryo. All rights reserved.
@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: news5000.c,v 1.18 2011/02/20 07:56:32 matt Exp $");
__KERNEL_RCSID(0, "$NetBSD: news5000.c,v 1.19 2011/03/09 13:21:36 tsutsui Exp $");
#define __INTR_PRIVATE
#include <sys/param.h>
@ -52,6 +52,27 @@ static void news5000_readidrom(uint8_t *);
static void news5000_tc_init(void);
static uint32_t news5000_getfreerun(struct timecounter *);
/*
* This is a mask of bits to clear in the SR when we go to a
* given interrupt priority level.
*/
static const struct ipl_sr_map news5000_ipl_sr_map = {
.sr_bits = {
[IPL_NONE] = 0,
[IPL_SOFTCLOCK] = MIPS_SOFT_INT_MASK_0,
[IPL_SOFTNET] = MIPS_SOFT_INT_MASK,
[IPL_VM] = MIPS_SOFT_INT_MASK
| MIPS_INT_MASK_0
| MIPS_INT_MASK_1,
[IPL_SCHED] = MIPS_SOFT_INT_MASK
| MIPS_INT_MASK_0
| MIPS_INT_MASK_1
| MIPS_INT_MASK_2,
[IPL_DDB] = MIPS_INT_MASK,
[IPL_HIGH] = MIPS_INT_MASK,
},
};
/*
* Handle news5000 interrupts.
*/
@ -259,6 +280,8 @@ void
news5000_init(void)
{
ipl_sr_map = news5000_ipl_sr_map;
enable_intr = news5000_enable_intr;
disable_intr = news5000_disable_intr;
enable_timer = news5000_enable_timer;