linux-mips
[Top] [All Lists]

[patch] linux: DBE/IBE handling rewrite

To: Ladislav Michl <ladis@psi.cz>, Ralf Baechle <ralf@uni-koblenz.de>
Subject: [patch] linux: DBE/IBE handling rewrite
From: "Maciej W. Rozycki" <macro@ds2.pg.gda.pl>
Date: Wed, 26 Jun 2002 13:51:08 +0200 (MET DST)
Cc: linux-mips@oss.sgi.com
In-reply-to: <Pine.GSO.3.96.1020625131229.29623A-100000@delta.ds2.pg.gda.pl>
Organization: Technical University of Gdansk
Reply-to: "Maciej W. Rozycki" <macro@ds2.pg.gda.pl>
Sender: owner-linux-mips@oss.sgi.com
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 */


<Prev in Thread] Current Thread [Next in Thread>