On Tue, 25 Jun 2002, Maciej W. Rozycki wrote: > This way, the fixup search is invoked first and a system-specific handler > can judge whether to let the fixup be invoked or a serious failure > happened and the system should act appropriately. The handler can do > whatever actions are needed (e.g. clear error status data in system > registers, report ECC syndromes, etc.) for the system for both cases. OK, here is the code. I wrote it a bit differently from what I considered yesterday, as fixup doesn't seem useful for a system-specific handler. With the following code only a boolean flag is passed informing whether a fixup is available and the handler can decide how to treat an error, based on the state passed as arguments and possibly additional one obtained from system-specific resources. Both MIPS and MIPS64 are handled in the same way. For MIPS64 it means a removal of duplicated similar code as well. I adjusted some SGI-specific code appropriately, but platform maintainers will have to check if bus_error_init() stubs are OK for them. Ralf, OK to apply? Maciej -- + Maciej W. Rozycki, Technical University of Gdansk, Poland + +--------------------------------------------------------------+ + e-mail: macro@ds2.pg.gda.pl, PGP key available + patch-mips-2.4.18-20020625-be-5 diff -up --recursive --new-file linux-mips-2.4.18-20020625.macro/arch/mips/cobalt/setup.c linux-mips-2.4.18-20020625/arch/mips/cobalt/setup.c --- linux-mips-2.4.18-20020625.macro/arch/mips/cobalt/setup.c 2002-01-07 03:33:54.000000000 +0000 +++ linux-mips-2.4.18-20020625/arch/mips/cobalt/setup.c 2002-06-26 11:21:15.000000000 +0000 @@ -25,6 +25,7 @@ #include <asm/pci.h> #include <asm/processor.h> #include <asm/reboot.h> +#include <asm/traps.h> extern void cobalt_machine_restart(char *command); extern void cobalt_machine_halt(void); @@ -71,6 +72,10 @@ static void __init cobalt_timer_setup(st *((volatile unsigned long *) GALILEO_CPU_MASK) = (unsigned long) 0x00000100; } + +void __init bus_error_init(void) { /* nothing */ } + + int cobalt_serial_present; int cobalt_serial_type; int cobalt_is_raq; diff -up --recursive --new-file linux-mips-2.4.18-20020625.macro/arch/mips/ddb5074/setup.c linux-mips-2.4.18-20020625/arch/mips/ddb5074/setup.c --- linux-mips-2.4.18-20020625.macro/arch/mips/ddb5074/setup.c 2001-11-26 05:25:59.000000000 +0000 +++ linux-mips-2.4.18-20020625/arch/mips/ddb5074/setup.c 2002-06-26 11:21:24.000000000 +0000 @@ -25,6 +25,7 @@ #include <asm/gdb-stub.h> #include <asm/nile4.h> #include <asm/ddb5074.h> +#include <asm/traps.h> #ifdef CONFIG_REMOTE_DEBUG @@ -91,6 +92,10 @@ static void __init ddb_time_init(struct IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4); } + +void __init bus_error_init(void) { /* nothing */ } + + void __init ddb_setup(void) { extern int panic_timeout; diff -up --recursive --new-file linux-mips-2.4.18-20020625.macro/arch/mips/ddb5xxx/ddb5476/setup.c linux-mips-2.4.18-20020625/arch/mips/ddb5xxx/ddb5476/setup.c --- linux-mips-2.4.18-20020625.macro/arch/mips/ddb5xxx/ddb5476/setup.c 2002-02-04 05:27:22.000000000 +0000 +++ linux-mips-2.4.18-20020625/arch/mips/ddb5xxx/ddb5476/setup.c 2002-06-26 11:21:56.000000000 +0000 @@ -25,6 +25,7 @@ #include <asm/gdb-stub.h> #include <asm/time.h> #include <asm/debug.h> +#include <asm/traps.h> #include <asm/ddb5xxx/ddb5xxx.h> @@ -138,6 +139,10 @@ static struct { { "Nile 4", DDB_BASE, DDB_BASE + DDB_SIZE - 1, IORESOURCE_BUSY} }; + +void __init bus_error_init(void) { /* nothing */ } + + static void ddb5476_board_init(void); extern void ddb5476_irq_setup(void); extern void (*irq_setup)(void); diff -up --recursive --new-file linux-mips-2.4.18-20020625.macro/arch/mips/ddb5xxx/ddb5477/setup.c linux-mips-2.4.18-20020625/arch/mips/ddb5xxx/ddb5477/setup.c --- linux-mips-2.4.18-20020625.macro/arch/mips/ddb5xxx/ddb5477/setup.c 2001-12-27 05:27:16.000000000 +0000 +++ linux-mips-2.4.18-20020625/arch/mips/ddb5xxx/ddb5477/setup.c 2002-06-26 11:22:25.000000000 +0000 @@ -32,6 +32,7 @@ #include <asm/reboot.h> #include <asm/gdb-stub.h> #include <asm/debug.h> +#include <asm/traps.h> #include <asm/ddb5xxx/ddb5xxx.h> @@ -117,6 +118,10 @@ static void __init ddb_timer_setup(struc #endif } + +void __init bus_error_init(void) { /* nothing */ } + + static void ddb5477_board_init(void); extern void ddb5477_irq_setup(void); diff -up --recursive --new-file linux-mips-2.4.18-20020625.macro/arch/mips/dec/setup.c linux-mips-2.4.18-20020625/arch/mips/dec/setup.c --- linux-mips-2.4.18-20020625.macro/arch/mips/dec/setup.c 2002-05-30 02:57:37.000000000 +0000 +++ linux-mips-2.4.18-20020625/arch/mips/dec/setup.c 2002-06-25 18:05:05.000000000 +0000 @@ -24,6 +24,7 @@ #include <asm/irq_cpu.h> #include <asm/mipsregs.h> #include <asm/reboot.h> +#include <asm/traps.h> #include <asm/dec/interrupts.h> #include <asm/dec/kn01.h> @@ -113,6 +114,16 @@ static void __init dec_time_init(struct setup_irq(dec_interrupt[DEC_IRQ_RTC], irq); } + +/* + * Bus error (DBE/IBE exceptions and memory interrupts) handling + * setup. Nothing for now. + */ +void __init bus_error_init(void) +{ +} + + void __init decstation_setup(void) { board_time_init = dec_time_init; diff -up --recursive --new-file linux-mips-2.4.18-20020625.macro/arch/mips/galileo-boards/ev64120/setup.c linux-mips-2.4.18-20020625/arch/mips/galileo-boards/ev64120/setup.c --- linux-mips-2.4.18-20020625.macro/arch/mips/galileo-boards/ev64120/setup.c 2001-12-13 05:27:47.000000000 +0000 +++ linux-mips-2.4.18-20020625/arch/mips/galileo-boards/ev64120/setup.c 2002-06-26 11:25:04.000000000 +0000 @@ -51,6 +51,7 @@ #include <asm/ptrace.h> #include <asm/reboot.h> #include <asm/mc146818rtc.h> +#include <asm/traps.h> #include <linux/version.h> #include <linux/bootmem.h> @@ -105,6 +106,10 @@ struct rtc_ops galileo_rtc_ops = { &galileo_rtc_bcd_mode }; + +void __init bus_error_init(void) { /* nothing */ } + + /******************************************************************** *ev64120_setup - * diff -up --recursive --new-file linux-mips-2.4.18-20020625.macro/arch/mips/gt64120/momenco_ocelot/setup.c linux-mips-2.4.18-20020625/arch/mips/gt64120/momenco_ocelot/setup.c --- linux-mips-2.4.18-20020625.macro/arch/mips/gt64120/momenco_ocelot/setup.c 2002-02-07 05:27:13.000000000 +0000 +++ linux-mips-2.4.18-20020625/arch/mips/gt64120/momenco_ocelot/setup.c 2002-06-26 11:26:58.000000000 +0000 @@ -59,6 +59,7 @@ #include <asm/ptrace.h> #include <asm/reboot.h> #include <asm/mc146818rtc.h> +#include <asm/traps.h> #include <linux/version.h> #include <linux/bootmem.h> #include <linux/blk.h> @@ -83,6 +84,10 @@ static char reset_reason; static void __init setup_l3cache(unsigned long size); + +void __init bus_error_init(void) { /* nothing */ } + + void __init momenco_ocelot_setup(void) { void (*l3func)(unsigned long)=KSEG1ADDR(&setup_l3cache); diff -up --recursive --new-file linux-mips-2.4.18-20020625.macro/arch/mips/ite-boards/generic/it8172_setup.c linux-mips-2.4.18-20020625/arch/mips/ite-boards/generic/it8172_setup.c --- linux-mips-2.4.18-20020625.macro/arch/mips/ite-boards/generic/it8172_setup.c 2001-11-27 05:26:05.000000000 +0000 +++ linux-mips-2.4.18-20020625/arch/mips/ite-boards/generic/it8172_setup.c 2002-06-26 11:32:13.000000000 +0000 @@ -40,6 +40,7 @@ #include <asm/irq.h> #include <asm/mipsregs.h> #include <asm/reboot.h> +#include <asm/traps.h> #include <asm/it8172/it8172.h> #include <asm/it8712.h> #ifdef CONFIG_PC_KEYB @@ -114,6 +115,9 @@ struct { #endif +void __init bus_error_init(void) { /* nothing */ } + + void __init it8172_init_ram_resource(unsigned long memsize) { it8172_resources.ram.end = memsize; diff -up --recursive --new-file linux-mips-2.4.18-20020625.macro/arch/mips/jazz/setup.c linux-mips-2.4.18-20020625/arch/mips/jazz/setup.c --- linux-mips-2.4.18-20020625.macro/arch/mips/jazz/setup.c 2001-12-12 05:27:26.000000000 +0000 +++ linux-mips-2.4.18-20020625/arch/mips/jazz/setup.c 2002-06-26 11:32:42.000000000 +0000 @@ -28,6 +28,7 @@ #include <asm/reboot.h> #include <asm/io.h> #include <asm/pgtable.h> +#include <asm/traps.h> /* * Initial irq handlers. @@ -80,6 +81,10 @@ static void __init jazz_irq_setup(void) i8259_setup_irq(2, &irq2); } + +void __init bus_error_init(void) { /* nothing */ } + + void __init jazz_setup(void) { /* Map 0xe0000000 -> 0x0:800005C0, 0xe0010000 -> 0x1:30000580 */ diff -up --recursive --new-file linux-mips-2.4.18-20020625.macro/arch/mips/jmr3927/rbhma3100/setup.c linux-mips-2.4.18-20020625/arch/mips/jmr3927/rbhma3100/setup.c --- linux-mips-2.4.18-20020625.macro/arch/mips/jmr3927/rbhma3100/setup.c 2002-02-23 05:28:27.000000000 +0000 +++ linux-mips-2.4.18-20020625/arch/mips/jmr3927/rbhma3100/setup.c 2002-06-26 11:36:26.000000000 +0000 @@ -55,6 +55,7 @@ #include <asm/gdb-stub.h> #include <asm/jmr3927/jmr3927.h> #include <asm/mipsregs.h> +#include <asm/traps.h> /* Tick Timer divider */ #define JMR3927_TIMER_CCD 0 /* 1/2 */ @@ -182,6 +183,10 @@ unsigned long jmr3927_do_gettimeoffset(v return res; } + +void __init bus_error_init(void) { /* nothing */ } + + #if defined(CONFIG_BLK_DEV_INITRD) extern unsigned long __rd_start, __rd_end, initrd_start, initrd_end; #endif diff -up --recursive --new-file linux-mips-2.4.18-20020625.macro/arch/mips/kernel/entry.S linux-mips-2.4.18-20020625/arch/mips/kernel/entry.S --- linux-mips-2.4.18-20020625.macro/arch/mips/kernel/entry.S 2002-04-16 02:57:34.000000000 +0000 +++ linux-mips-2.4.18-20020625/arch/mips/kernel/entry.S 2002-06-25 16:39:19.000000000 +0000 @@ -236,8 +236,8 @@ EXPORT(exception_count_##exception); BUILD_HANDLER(adel,ade,ade,silent) /* #4 */ BUILD_HANDLER(ades,ade,ade,silent) /* #5 */ - BUILD_HANDLER(ibe,ibe,cli,silent) /* #6 */ - BUILD_HANDLER(dbe,dbe,cli,silent) /* #7 */ + BUILD_HANDLER(ibe,be,cli,silent) /* #6 */ + BUILD_HANDLER(dbe,be,cli,silent) /* #7 */ BUILD_HANDLER(bp,bp,sti,silent) /* #9 */ BUILD_HANDLER(ri,ri,sti,silent) /* #10 */ BUILD_HANDLER(cpu,cpu,sti,silent) /* #11 */ diff -up --recursive --new-file linux-mips-2.4.18-20020625.macro/arch/mips/kernel/traps.c linux-mips-2.4.18-20020625/arch/mips/kernel/traps.c --- linux-mips-2.4.18-20020625.macro/arch/mips/kernel/traps.c 2002-05-28 10:13:03.000000000 +0000 +++ linux-mips-2.4.18-20020625/arch/mips/kernel/traps.c 2002-06-25 19:38:02.000000000 +0000 @@ -10,6 +10,7 @@ * * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com * Copyright (C) 2000, 01 MIPS Technologies, Inc. + * Copyright (C) 2002 Maciej W. Rozycki */ #include <linux/config.h> #include <linux/init.h> @@ -32,6 +33,7 @@ #include <asm/siginfo.h> #include <asm/watch.h> #include <asm/system.h> +#include <asm/traps.h> #include <asm/uaccess.h> #include <asm/mmu_context.h> @@ -66,8 +68,7 @@ extern int fpu_emulator_cop1Handler(stru char watch_available = 0; -void (*ibe_board_handler)(struct pt_regs *regs); -void (*dbe_board_handler)(struct pt_regs *regs); +int (*be_board_handler)(struct pt_regs *regs, int is_fixup); int kstack_depth_to_print = 24; @@ -417,20 +418,35 @@ search_dbe_table(unsigned long addr) #endif } -static void default_be_board_handler(struct pt_regs *regs) +asmlinkage void do_be(struct pt_regs *regs) { unsigned long new_epc; - unsigned long fixup; + unsigned long fixup = 0; int data = regs->cp0_cause & 4; + int action = MIPS_BE_FATAL; - if (data && !user_mode(regs)) { + if (data && !user_mode(regs)) fixup = search_dbe_table(regs->cp0_epc); + + if (fixup) + action = MIPS_BE_FIXUP; + + if (be_board_handler) + action = be_board_handler(regs, fixup != 0); + + switch (action) { + case MIPS_BE_DISCARD: + return; + case MIPS_BE_FIXUP: if (fixup) { new_epc = fixup_exception(dpf_reg, fixup, regs->cp0_epc); regs->cp0_epc = new_epc; return; } + break; + default: + break; } /* @@ -443,16 +459,6 @@ static void default_be_board_handler(str force_sig(SIGBUS, current); } -asmlinkage void do_ibe(struct pt_regs *regs) -{ - ibe_board_handler(regs); -} - -asmlinkage void do_dbe(struct pt_regs *regs) -{ - dbe_board_handler(regs); -} - asmlinkage void do_ov(struct pt_regs *regs) { if (compute_return_epc(regs)) @@ -950,6 +956,13 @@ void __init trap_init(void) */ parity_protection_init(); + /* + * The Data Bus Errors / Instruction Bus Errors are signaled + * by external hardware. Therefore these two exceptions + * may have board specific handlers. + */ + bus_error_init(); + set_except_vector(1, handle_mod); set_except_vector(2, handle_tlbl); set_except_vector(3, handle_tlbs); @@ -958,13 +971,11 @@ void __init trap_init(void) /* * The Data Bus Error/ Instruction Bus Errors are signaled - * by external hardware. Therefore these two expection have - * board specific handlers. + * by external hardware. Therefore these two exceptions + * may have board specific handlers. */ set_except_vector(6, handle_ibe); set_except_vector(7, handle_dbe); - ibe_board_handler = default_be_board_handler; - dbe_board_handler = default_be_board_handler; set_except_vector(8, handle_sys); set_except_vector(9, handle_bp); diff -up --recursive --new-file linux-mips-2.4.18-20020625.macro/arch/mips/mips-boards/atlas/atlas_setup.c linux-mips-2.4.18-20020625/arch/mips/mips-boards/atlas/atlas_setup.c --- linux-mips-2.4.18-20020625.macro/arch/mips/mips-boards/atlas/atlas_setup.c 2002-01-25 05:26:36.000000000 +0000 +++ linux-mips-2.4.18-20020625/arch/mips/mips-boards/atlas/atlas_setup.c 2002-06-26 11:36:59.000000000 +0000 @@ -31,6 +31,7 @@ #include <asm/mips-boards/atlasint.h> #include <asm/gt64120.h> #include <asm/time.h> +#include <asm/traps.h> #if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_PROM_CONSOLE) extern void console_setup(char *, int *); diff -up --recursive --new-file linux-mips-2.4.18-20020625.macro/arch/mips/mips-boards/malta/malta_setup.c linux-mips-2.4.18-20020625/arch/mips/mips-boards/malta/malta_setup.c --- linux-mips-2.4.18-20020625.macro/arch/mips/mips-boards/malta/malta_setup.c 2002-05-09 02:57:10.000000000 +0000 +++ linux-mips-2.4.18-20020625/arch/mips/mips-boards/malta/malta_setup.c 2002-06-26 11:37:27.000000000 +0000 @@ -37,6 +37,7 @@ #endif #include <asm/dma.h> #include <asm/time.h> +#include <asm/traps.h> #ifdef CONFIG_PC_KEYB #include <asm/keyboard.h> #endif diff -up --recursive --new-file linux-mips-2.4.18-20020625.macro/arch/mips/philips/nino/setup.c linux-mips-2.4.18-20020625/arch/mips/philips/nino/setup.c --- linux-mips-2.4.18-20020625.macro/arch/mips/philips/nino/setup.c 2002-05-30 02:57:50.000000000 +0000 +++ linux-mips-2.4.18-20020625/arch/mips/philips/nino/setup.c 2002-06-26 11:38:05.000000000 +0000 @@ -19,6 +19,7 @@ #include <asm/irq.h> #include <asm/reboot.h> #include <asm/time.h> +#include <asm/traps.h> #include <asm/tx3912.h> static void nino_machine_restart(char *command) @@ -81,6 +82,10 @@ static __init void nino_timer_setup(stru setup_irq(0, irq); } + +void __init bus_error_init(void) { /* nothing */ } + + void __init nino_setup(void) { extern void nino_irq_setup(void); diff -up --recursive --new-file linux-mips-2.4.18-20020625.macro/arch/mips/sgi-ip22/ip22-setup.c linux-mips-2.4.18-20020625/arch/mips/sgi-ip22/ip22-setup.c --- linux-mips-2.4.18-20020625.macro/arch/mips/sgi-ip22/ip22-setup.c 2002-05-13 02:57:38.000000000 +0000 +++ linux-mips-2.4.18-20020625/arch/mips/sgi-ip22/ip22-setup.c 2002-06-26 11:41:03.000000000 +0000 @@ -28,6 +28,7 @@ #include <asm/sgi/sgint23.h> #include <asm/time.h> #include <asm/gdb-stub.h> +#include <asm/traps.h> #ifdef CONFIG_REMOTE_DEBUG extern void rs_kgdb_hook(int); diff -up --recursive --new-file linux-mips-2.4.18-20020625.macro/arch/mips/sni/setup.c linux-mips-2.4.18-20020625/arch/mips/sni/setup.c --- linux-mips-2.4.18-20020625.macro/arch/mips/sni/setup.c 2001-11-26 05:26:01.000000000 +0000 +++ linux-mips-2.4.18-20020625/arch/mips/sni/setup.c 2002-06-26 11:39:42.000000000 +0000 @@ -31,6 +31,7 @@ #include <asm/reboot.h> #include <asm/sni.h> #include <asm/time.h> +#include <asm/traps.h> extern void sni_machine_restart(char *command); extern void sni_machine_halt(void); @@ -49,6 +50,10 @@ static void __init sni_rm200_pci_time_in setup_irq(0, irq); } + +void __init bus_error_init(void) { /* nothing */ } + + extern unsigned char sni_map_isa_cache; /* diff -up --recursive --new-file linux-mips-2.4.18-20020625.macro/arch/mips64/kernel/r4k_genex.S linux-mips-2.4.18-20020625/arch/mips64/kernel/r4k_genex.S --- linux-mips-2.4.18-20020625.macro/arch/mips64/kernel/r4k_genex.S 2002-02-23 05:28:29.000000000 +0000 +++ linux-mips-2.4.18-20020625/arch/mips64/kernel/r4k_genex.S 2002-06-25 16:48:31.000000000 +0000 @@ -20,8 +20,8 @@ BUILD_HANDLER adel ade ade silent /* #4 */ BUILD_HANDLER ades ade ade silent /* #5 */ - BUILD_HANDLER ibe ibe cli silent /* #6 */ - BUILD_HANDLER dbe dbe cli silent /* #7 */ + BUILD_HANDLER ibe be cli silent /* #6 */ + BUILD_HANDLER dbe be cli silent /* #7 */ BUILD_HANDLER bp bp sti silent /* #9 */ BUILD_HANDLER ri ri sti silent /* #10 */ BUILD_HANDLER cpu cpu sti silent /* #11 */ diff -up --recursive --new-file linux-mips-2.4.18-20020625.macro/arch/mips64/kernel/traps.c linux-mips-2.4.18-20020625/arch/mips64/kernel/traps.c --- linux-mips-2.4.18-20020625.macro/arch/mips64/kernel/traps.c 2002-06-20 02:57:37.000000000 +0000 +++ linux-mips-2.4.18-20020625/arch/mips64/kernel/traps.c 2002-06-25 19:43:46.000000000 +0000 @@ -7,6 +7,7 @@ * Copyright (C) 1995, 1996 Paul M. Antoine * Copyright (C) 1998 Ulf Carlsson * Copyright (C) 1999 Silicon Graphics, Inc. + * Copyright (C) 2002 Maciej W. Rozycki */ #include <linux/config.h> #include <linux/init.h> @@ -23,10 +24,10 @@ #include <asm/module.h> #include <asm/pgtable.h> #include <asm/io.h> -#include <asm/paccess.h> #include <asm/ptrace.h> #include <asm/watch.h> #include <asm/system.h> +#include <asm/traps.h> #include <asm/uaccess.h> #include <asm/mmu_context.h> #include <asm/cachectl.h> @@ -55,6 +56,8 @@ void fpu_emulator_init_fpu(void); char watch_available = 0; char dedicated_iv_available = 0; +int (*be_board_handler)(struct pt_regs *regs, int is_fixup); + int kstack_depth_to_print = 24; /* @@ -272,7 +275,8 @@ search_one_table(const struct exception_ extern spinlock_t modlist_lock; -unsigned long search_dbe_table(unsigned long addr) +static inline unsigned long +search_dbe_table(unsigned long addr) { unsigned long ret = 0; @@ -308,26 +312,45 @@ unsigned long search_dbe_table(unsigned #endif } -/* Default data and instruction bus error handlers. */ -void do_ibe(struct pt_regs *regs) +asmlinkage void do_be(struct pt_regs *regs) { - die("Got ibe\n", regs); -} + unsigned long new_epc; + unsigned long fixup = 0; + int data = regs->cp0_cause & 4; + int action = MIPS_BE_FATAL; -void do_dbe(struct pt_regs *regs) -{ - unsigned long fixup; + if (data && !user_mode(regs)) + fixup = search_dbe_table(regs->cp0_epc); + + if (fixup) + action = MIPS_BE_FIXUP; - fixup = search_dbe_table(regs->cp0_epc); - if (fixup) { - long new_epc; + if (be_board_handler) + action = be_board_handler(regs, fixup != 0); - new_epc = fixup_exception(dpf_reg, fixup, regs->cp0_epc); - regs->cp0_epc = new_epc; + switch (action) { + case MIPS_BE_DISCARD: return; + case MIPS_BE_FIXUP: + if (fixup) { + new_epc = fixup_exception(dpf_reg, fixup, + regs->cp0_epc); + regs->cp0_epc = new_epc; + return; + } + break; + default: + break; } - die("Got dbe\n", regs); + /* + * Assume it would be too dangerous to continue ... + */ + printk(KERN_ALERT "%s bus error, epc == %08lx, ra == %08lx\n", + data ? "Data" : "Instruction", + regs->cp0_epc, regs->regs[31]); + die_if_kernel("Oops", regs); + force_sig(SIGBUS, current); } void do_ov(struct pt_regs *regs) @@ -634,7 +657,6 @@ void __init trap_init(void) extern char except_vec2_generic, except_vec2_sb1; extern char except_vec3_generic, except_vec3_r4000; extern char except_vec4; - extern void bus_error_init(void); unsigned long i; int dummy; @@ -666,6 +688,13 @@ void __init trap_init(void) set_except_vector(24, handle_mcheck); /* + * The Data Bus Errors / Instruction Bus Errors are signaled + * by external hardware. Therefore these two exceptions + * may have board specific handlers. + */ + bus_error_init(); + + /* * Handling the following exceptions depends mostly of the cpu type */ switch(mips_cpu.cputype) { @@ -713,18 +742,6 @@ void __init trap_init(void) set_except_vector(6, handle_ibe); set_except_vector(7, handle_dbe); - /* - * If nothing uses the DBE protection mechanism this is - * necessary to get the kernel to link. - */ - get_dbe(dummy, (int *)KSEG0); - - /* - * DBE / IBE handlers may be overridden by system specific - * handlers. - */ - bus_error_init(); - set_except_vector(8, handle_sys); set_except_vector(9, handle_bp); set_except_vector(10, handle_ri); diff -up --recursive --new-file linux-mips-2.4.18-20020625.macro/arch/mips64/sgi-ip27/Makefile linux-mips-2.4.18-20020625/arch/mips64/sgi-ip27/Makefile --- linux-mips-2.4.18-20020625.macro/arch/mips64/sgi-ip27/Makefile 2002-01-25 05:27:27.000000000 +0000 +++ linux-mips-2.4.18-20020625/arch/mips64/sgi-ip27/Makefile 2002-06-25 18:07:47.000000000 +0000 @@ -11,9 +11,8 @@ O_TARGET = ip27.o export-objs = ip27-rtc.o -obj-y := ip27-berr.o ip27-console.o ip27-dbe-glue.o ip27-irq.o ip27-init.o \ - ip27-irq-glue.o ip27-klconfig.o ip27-klnuma.o ip27-memory.o \ - ip27-nmi.o ip27-pci.o ip27-pci-dma.o ip27-reset.o ip27-setup.o \ - ip27-timer.o +obj-y := ip27-berr.o ip27-console.o ip27-irq.o ip27-init.o ip27-irq-glue.o \ + ip27-klconfig.o ip27-klnuma.o ip27-memory.o ip27-nmi.o ip27-pci.o \ + ip27-pci-dma.o ip27-reset.o ip27-setup.o ip27-timer.o include $(TOPDIR)/Rules.make diff -up --recursive --new-file linux-mips-2.4.18-20020625.macro/arch/mips64/sgi-ip27/ip27-berr.c linux-mips-2.4.18-20020625/arch/mips64/sgi-ip27/ip27-berr.c --- linux-mips-2.4.18-20020625.macro/arch/mips64/sgi-ip27/ip27-berr.c 2002-01-25 05:27:27.000000000 +0000 +++ linux-mips-2.4.18-20020625/arch/mips64/sgi-ip27/ip27-berr.c 2002-06-25 19:45:12.000000000 +0000 @@ -5,6 +5,7 @@ * * Copyright (C) 1994, 1995, 1996, 1999, 2000 by Ralf Baechle * Copyright (C) 1999, 2000 by Silicon Graphics + * Copyright (C) 2002 Maciej W. Rozycki */ #include <linux/init.h> #include <linux/kernel.h> @@ -14,24 +15,12 @@ #include <asm/sn/addrs.h> #include <asm/sn/arch.h> #include <asm/sn/sn0/hub.h> +#include <asm/traps.h> #include <asm/uaccess.h> -#include <asm/paccess.h> extern void dump_tlb_addr(unsigned long addr); extern void dump_tlb_all(void); -extern asmlinkage void handle_ip27_ibe(void); -extern asmlinkage void handle_ip27_dbe(void); - -void do_ip27_ibe(struct pt_regs *regs) -{ - printk("Got ibe at 0x%lx\n", regs->cp0_epc); - show_regs(regs); - dump_tlb_addr(regs->cp0_epc); - force_sig(SIGBUS, current); - while(1); -} - static void dump_hub_information(unsigned long errst0, unsigned long errst1) { static char *err_type[2][8] = { @@ -65,21 +54,17 @@ static void dump_hub_information(unsigne ? : "invalid"); } -void do_ip27_dbe(struct pt_regs *regs) +int be_ip27_handler(struct pt_regs *regs, int is_fixup) { - unsigned long fixup, errst0, errst1; + unsigned long errst0, errst1; + int data = regs->cp0_cause & 4; int cpu = LOCAL_HUB_L(PI_CPU_NUM); - fixup = search_dbe_table(regs->cp0_epc); - if (fixup) { - long new_epc; - - new_epc = fixup_exception(dpf_reg, fixup, regs->cp0_epc); - regs->cp0_epc = new_epc; - return; - } + if (is_fixup) + return MIPS_BE_FIXUP; - printk("Slice %c got dbe at 0x%lx\n", 'A' + cpu, regs->cp0_epc); + printk("Slice %c got %cbe at 0x%lx\n", 'A' + cpu, data ? 'd' : 'i', + regs->cp0_epc); printk("Hub information:\n"); printk("ERR_INT_PEND = 0x%06lx\n", LOCAL_HUB_L(PI_ERR_INT_PEND)); errst0 = LOCAL_HUB_L(cpu ? PI_ERR_STATUS0_B : PI_ERR_STATUS0_A); @@ -97,8 +82,7 @@ void __init bus_error_init(void) int cpu = LOCAL_HUB_L(PI_CPU_NUM); int cpuoff = cpu << 8; - set_except_vector(6, handle_ip27_ibe); - set_except_vector(7, handle_ip27_dbe); + be_board_handler = be_ip27_handler; LOCAL_HUB_S(PI_ERR_INT_PEND, cpu ? PI_ERR_CLEAR_ALL_B : PI_ERR_CLEAR_ALL_A); diff -up --recursive --new-file linux-mips-2.4.18-20020625.macro/arch/mips64/sgi-ip27/ip27-dbe-glue.S linux-mips-2.4.18-20020625/arch/mips64/sgi-ip27/ip27-dbe-glue.S --- linux-mips-2.4.18-20020625.macro/arch/mips64/sgi-ip27/ip27-dbe-glue.S 2002-01-24 23:14:27.000000000 +0000 +++ linux-mips-2.4.18-20020625/arch/mips64/sgi-ip27/ip27-dbe-glue.S 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 1994 - 1999 by Ralf Baechle - * Copyright (C) 1999 Silicon Graphics - * - * Low level exception handling - */ -#define __ASSEMBLY__ -#include <linux/init.h> -#include <asm/asm.h> -#include <asm/regdef.h> -#include <asm/fpregdef.h> -#include <asm/mipsregs.h> -#include <asm/exception.h> - - BUILD_HANDLER ip27_ibe ip27_ibe cli silent /* #6 */ - BUILD_HANDLER ip27_dbe ip27_dbe cli silent /* #7 */ diff -up --recursive --new-file linux-mips-2.4.18-20020625.macro/arch/mips64/sgi-ip32/Makefile linux-mips-2.4.18-20020625/arch/mips64/sgi-ip32/Makefile --- linux-mips-2.4.18-20020625.macro/arch/mips64/sgi-ip32/Makefile 2002-01-25 05:27:27.000000000 +0000 +++ linux-mips-2.4.18-20020625/arch/mips64/sgi-ip32/Makefile 2002-06-25 17:52:20.000000000 +0000 @@ -17,8 +17,8 @@ O_TARGET := ip32-kern.a all: ip32-kern.a ip32-irq-glue.o -obj-y += ip32-rtc.o ip32-setup.o ip32-irq.o ip32-irq-glue.o ip32-timer.o \ - crime.o ip32-reset.o +obj-y += ip32-berr.o ip32-rtc.o ip32-setup.o ip32-irq.o ip32-irq-glue.o \ + ip32-timer.o crime.o ip32-reset.o obj-$(CONFIG_PCI) += ip32-pci.o diff -up --recursive --new-file linux-mips-2.4.18-20020625.macro/arch/mips64/sgi-ip32/ip32-berr.c linux-mips-2.4.18-20020625/arch/mips64/sgi-ip32/ip32-berr.c --- linux-mips-2.4.18-20020625.macro/arch/mips64/sgi-ip32/ip32-berr.c 2001-08-24 18:10:59.000000000 +0000 +++ linux-mips-2.4.18-20020625/arch/mips64/sgi-ip32/ip32-berr.c 2002-06-25 19:46:03.000000000 +0000 @@ -5,78 +5,24 @@ * * Copyright (C) 1994, 1995, 1996, 1999, 2000 by Ralf Baechle * Copyright (C) 1999, 2000 by Silicon Graphics + * Copyright (C) 2002 Maciej W. Rozycki */ #include <linux/init.h> #include <linux/kernel.h> +#include <asm/traps.h> #include <asm/uaccess.h> -#include <asm/paccess.h> #include <asm/addrspace.h> #include <asm/ptrace.h> -/* XXX I have no idea what this does --kmw */ - -extern asmlinkage void handle_ibe(void); -extern asmlinkage void handle_dbe(void); - -extern const struct exception_table_entry __start___dbe_table[]; -extern const struct exception_table_entry __stop___dbe_table[]; - -static inline unsigned long -search_one_table(const struct exception_table_entry *first, - const struct exception_table_entry *last, - unsigned long value) +int +be_ip32_handler(struct pt_regs *regs, int is_fixup) { - while (first <= last) { - const struct exception_table_entry *mid; - long diff; + int data = regs->cp0_cause & 4; - mid = (last - first) / 2 + first; - diff = mid->insn - value; - if (diff == 0) - return mid->nextinsn; - else if (diff < 0) - first = mid+1; - else - last = mid-1; - } - return 0; -} - -static inline unsigned long -search_dbe_table(unsigned long addr) -{ - unsigned long ret; + if (is_fixup) + return MIPS_BE_FIXUP; - /* There is only the kernel to search. */ - ret = search_one_table(__start___dbe_table, __stop___dbe_table-1, addr); - if (ret) return ret; - - return 0; -} - -void do_ibe(struct pt_regs *regs) -{ - printk("Got ibe at 0x%lx\n", regs->cp0_epc); - show_regs(regs); - dump_tlb_addr(regs->cp0_epc); - force_sig(SIGBUS, current); - while(1); -} - -void do_dbe(struct pt_regs *regs) -{ - unsigned long fixup; - - fixup = search_dbe_table(regs->cp0_epc); - if (fixup) { - long new_epc; - - new_epc = fixup_exception(dpf_reg, fixup, regs->cp0_epc); - regs->cp0_epc = new_epc; - return; - } - - printk("Got dbe at 0x%lx\n", regs->cp0_epc); + printk("Got %cbe at 0x%lx\n", data ? 'd' : 'i', regs->cp0_epc); show_regs(regs); dump_tlb_all(); while(1); @@ -86,12 +32,5 @@ void do_dbe(struct pt_regs *regs) void __init bus_error_init(void) { - int dummy; - - set_except_vector(6, handle_ibe); - set_except_vector(7, handle_dbe); - - /* At this time nothing uses the DBE protection mechanism on the - O2, so this here is needed to make the kernel link. */ - get_dbe(dummy, (int *)KSEG0); + be_board_handler = be_ip27_handler; } diff -up --recursive --new-file linux-mips-2.4.18-20020625.macro/arch/mips64/sgi-ip32/ip32-setup.c linux-mips-2.4.18-20020625/arch/mips64/sgi-ip32/ip32-setup.c --- linux-mips-2.4.18-20020625.macro/arch/mips64/sgi-ip32/ip32-setup.c 2002-05-30 02:57:51.000000000 +0000 +++ linux-mips-2.4.18-20020625/arch/mips64/sgi-ip32/ip32-setup.c 2002-06-25 17:52:58.000000000 +0000 @@ -60,10 +60,6 @@ static inline void str2eaddr(unsigned ch extern void ip32_time_init(void); -void __init bus_error_init(void) -{ -} - void __init ip32_setup(void) { #ifdef CONFIG_SERIAL_CONSOLE diff -up --recursive --new-file linux-mips-2.4.18-20020625.macro/include/asm-mips/traps.h linux-mips-2.4.18-20020625/include/asm-mips/traps.h --- linux-mips-2.4.18-20020625.macro/include/asm-mips/traps.h 1970-01-01 00:00:00.000000000 +0000 +++ linux-mips-2.4.18-20020625/include/asm-mips/traps.h 2002-06-25 19:30:41.000000000 +0000 @@ -0,0 +1,27 @@ +/* + * include/asm-mips/traps.h + * + * Trap handling definitions. + * + * Copyright (C) 2002 Maciej W. Rozycki + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#ifndef __ASM_MIPS_TRAPS_H +#define __ASM_MIPS_TRAPS_H + +/* + * Possible status responses for a be_board_handler backend. + */ +#define MIPS_BE_DISCARD 0 /* return with no action */ +#define MIPS_BE_FIXUP 1 /* return to the fixup code */ +#define MIPS_BE_FATAL 2 /* treat as an unrecoverable error */ + +extern int (*be_board_handler)(struct pt_regs *regs, int is_fixup); + +extern void bus_error_init(void); + +#endif /* __ASM_MIPS_TRAPS_H */ diff -up --recursive --new-file linux-mips-2.4.18-20020625.macro/include/asm-mips64/traps.h linux-mips-2.4.18-20020625/include/asm-mips64/traps.h --- linux-mips-2.4.18-20020625.macro/include/asm-mips64/traps.h 1970-01-01 00:00:00.000000000 +0000 +++ linux-mips-2.4.18-20020625/include/asm-mips64/traps.h 2002-06-25 19:31:45.000000000 +0000 @@ -0,0 +1,27 @@ +/* + * include/asm-mips64/traps.h + * + * Trap handling definitions. + * + * Copyright (C) 2002 Maciej W. Rozycki + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#ifndef __ASM_MIPS64_TRAPS_H +#define __ASM_MIPS64_TRAPS_H + +/* + * Possible status responses for a be_board_handler backend. + */ +#define MIPS_BE_DISCARD 0 /* return with no action */ +#define MIPS_BE_FIXUP 1 /* return to the fixup code */ +#define MIPS_BE_FATAL 2 /* treat as an unrecoverable error */ + +extern int (*be_board_handler)(struct pt_regs *regs, int is_fixup); + +extern void bus_error_init(void); + +#endif /* __ASM_MIPS64_TRAPS_H */