Hi,

Accessing non present "IO ports" on 8xx generates MCE's. The exception is easily
triggered during insertion/removal/suspension of PCMCIA cards. 

The following (against ancient v2.4) adds exception table entries for I/O
instructions on 8xx (copied from the original Paul's PowerMac code), and
changes MachineCheckException() slightly to cover 8xx specific's (on 8xx
the MCE can be generated while executing the IO access instruction itself,
which is not the case on PowerMac's, as the comment on traps.c details).

A few things I'm wondering:

1) why does the current PowerMac version covers only inb() and not outb() ?  
I had to add outb() exception table entries for 8xx.

2) Is the same wanted for other embedded PPC's? 

3) How to make the misc.S exception entries and additional instructions 
selectable only on the platform who need it? #ifdef does not sound 
a good idea. 

Nevermind the "#ifdef CONFIG_ALL_PPC" crap - that needs to be done
properly.


Index: arch/ppc/kernel/misc.S
===================================================================
RCS file: /mnt/test1/tslinux_mv21/linux-216/arch/ppc/kernel/misc.S,v
retrieving revision 1.2
diff -u -r1.2 misc.S
--- arch/ppc/kernel/misc.S      22 Oct 2003 19:34:30 -0000      1.2
+++ arch/ppc/kernel/misc.S      1 Jun 2005 17:59:30 -0000
@@ -736,8 +736,23 @@
        subi    r4,r4,1
        blelr-
 00:    lbz     r5,0(r3)
-       eieio
-       stbu    r5,1(r4)
+01:    eieio
+02:    stbu    r5,1(r4)
+03:    twi 0, r5, 0
+04:    isync
+05:    nop
+06:    .section .fixup,"ax"
+07:            b 9f
+       .text
+08:    .section __ex_table, "a"
+               .align 2
+               .long 00b, 07b
+               .long 01b, 07b
+               .long 02b, 07b
+               .long 03b, 07b
+               .long 04b, 07b
+               .long 05b, 07b
+       .text
        bdnz    00b
        blr
 
@@ -747,10 +762,27 @@
        subi    r4,r4,1
        blelr-
 00:    lbzu    r5,1(r4)
-       stb     r5,0(r3)
-       eieio
+01:    stb     r5,0(r3)
+02:    eieio
+03:    twi 0, r5, 0
+04:    isync
+05:    nop
+06:    .section .fixup,"ax"
+07:            b 9f
+       .text
+08:    .section __ex_table, "a"
+               .align 2
+               .long 00b, 07b
+               .long 01b, 07b
+               .long 02b, 07b
+               .long 03b, 07b
+               .long 04b, 07b
+               .long 05b, 07b
+       .text
+
        bdnz    00b
-       blr     
+9:     blr     
+
 
 _GLOBAL(_insw)
        cmpwi   0,r5,0
@@ -758,10 +790,25 @@
        subi    r4,r4,2
        blelr-
 00:    lhbrx   r5,0,r3
-       eieio
-       sthu    r5,2(r4)
+01:    eieio
+02:    sthu    r5,2(r4)
+03:    twi 0, r5, 0
+04:    isync
+05:    nop
+06:    .section .fixup,"ax"
+07:            b 9f
+       .text
+08:    .section __ex_table, "a"
+               .align 2
+               .long 00b, 07b
+               .long 01b, 07b
+               .long 02b, 07b
+               .long 03b, 07b
+               .long 04b, 07b
+               .long 05b, 07b
+       .text
        bdnz    00b
-       blr
+9:     blr
 
 _GLOBAL(_outsw)
        cmpwi   0,r5,0
@@ -769,10 +816,25 @@
        subi    r4,r4,2
        blelr-
 00:    lhzu    r5,2(r4)
-       eieio
-       sthbrx  r5,0,r3 
+01:    eieio
+02:    sthbrx  r5,0,r3 
+03:    twi 0, r5, 0
+04:    isync
+05:    nop
+06:    .section .fixup,"ax"
+07:            b 9f    
+       .text
+08:    .section __ex_table, "a"
+               .align 2
+               .long 00b, 07b
+               .long 01b, 07b
+               .long 02b, 07b
+               .long 03b, 07b
+               .long 04b, 07b
+               .long 05b, 07b
+       .text
        bdnz    00b
-       blr     
+9:     blr     
 
 _GLOBAL(_insl)
        cmpwi   0,r5,0
@@ -780,10 +842,25 @@
        subi    r4,r4,4
        blelr-
 00:    lwbrx   r5,0,r3
-       eieio
-       stwu    r5,4(r4)
+01:    eieio
+02:    stwu    r5,4(r4)
+03:    twi 0, r5, 0
+04:    isync
+05:    nop
+06:    .section .fixup,"ax"
+07:            b 9f
+       .text
+08:    .section __ex_table, "a"
+               .align 2
+               .long 00b, 07b
+               .long 01b, 07b
+               .long 02b, 07b
+               .long 03b, 07b
+               .long 04b, 07b
+               .long 05b, 07b
+       .text
        bdnz    00b
-       blr
+9:     blr
 
 _GLOBAL(_outsl)
        cmpwi   0,r5,0
@@ -791,10 +868,26 @@
        subi    r4,r4,4
        blelr-
 00:    lwzu    r5,4(r4)
-       stwbrx  r5,0,r3
-       eieio
+01:    stwbrx  r5,0,r3
+02:    eieio
+02:    stwu    r5,4(r4)
+03:    twi 0, r5, 0
+04:    isync
+05:    nop
+06:    .section .fixup,"ax"
+07:            b 9f
+       .text
+08:    .section __ex_table, "a"
+               .align 2
+               .long 00b, 07b
+               .long 01b, 07b
+               .long 02b, 07b
+               .long 03b, 07b
+               .long 04b, 07b
+               .long 05b, 07b
+       .text
        bdnz    00b
-       blr     
+9:     blr     
 
 _GLOBAL(ide_insw)
 _GLOBAL(_insw_ns)
@@ -803,10 +896,25 @@
        subi    r4,r4,2
        blelr-
 00:    lhz     r5,0(r3)
-       eieio
-       sthu    r5,2(r4)
+01:    eieio
+02:    sthu    r5,2(r4)
+03:    twi 0, r5, 0
+04:    isync
+05:    nop
+06:    .section .fixup,"ax"
+07:            blr
+       .previous
+08:    .section __ex_table, "a"
+               .align 2
+               .long 00b, 07b
+               .long 01b, 07b
+               .long 02b, 07b
+               .long 03b, 07b
+               .long 04b, 07b
+               .long 05b, 07b
+       .previous
        bdnz    00b
-       blr
+9:     blr
 
 _GLOBAL(ide_outsw)
 _GLOBAL(_outsw_ns)
@@ -815,10 +923,25 @@
        subi    r4,r4,2
        blelr-
 00:    lhzu    r5,2(r4)
-       sth     r5,0(r3)
-       eieio
+01:    sth     r5,0(r3)
+02:    eieio
+03:    twi 0, r5, 0
+04:    isync
+05:    nop
+06:    .section .fixup,"ax"
+07:            b 9f
+       .text
+08:    .section __ex_table, "a"
+               .align 2
+               .long 00b, 07b
+               .long 01b, 07b
+               .long 02b, 07b
+               .long 03b, 07b
+               .long 04b, 07b
+               .long 05b, 07b
+       .text
        bdnz    00b
-       blr     
+9:     blr     
 
 _GLOBAL(_insl_ns)
        cmpwi   0,r5,0
@@ -826,10 +949,10 @@
        subi    r4,r4,4
        blelr-
 00:    lwz     r5,0(r3)
-       eieio
-       stwu    r5,4(r4)
+01:    eieio
+02:    stwu    r5,4(r4)
        bdnz    00b
-       blr
+9:     blr
 
 _GLOBAL(_outsl_ns)
        cmpwi   0,r5,0
@@ -837,10 +960,10 @@
        subi    r4,r4,4
        blelr-
 00:    lwzu    r5,4(r4)
-       stw     r5,0(r3)
-       eieio
+01:    stw     r5,0(r3)
+02:    eieio
        bdnz    00b
-       blr     
+9:     blr     
 
 /*
  * Extended precision shifts.
Index: arch/ppc/kernel/traps.c
===================================================================
RCS file: /mnt/test1/tslinux_mv21/linux-216/arch/ppc/kernel/traps.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 traps.c
--- arch/ppc/kernel/traps.c     19 Jun 2002 18:15:32 -0000      1.1.1.1
+++ arch/ppc/kernel/traps.c     1 Jun 2005 19:09:15 -0000
@@ -130,9 +130,7 @@
 void
 MachineCheckException(struct pt_regs *regs)
 {
-#ifdef CONFIG_ALL_PPC
        unsigned long fixup;
-#endif /* CONFIG_ALL_PPC */
        unsigned long msr = regs->msr;
 
        if (user_mode(regs)) {
@@ -150,7 +148,7 @@
                return;
        }
 
-#ifdef CONFIG_ALL_PPC
+//#ifdef CONFIG_ALL_PPC
        /*
         * I/O accesses can cause machine checks on powermacs.
         * Check if the NIP corresponds to the address of a sync
@@ -176,20 +174,25 @@
                        nip -= 2;
                else if (*nip == 0x4c00012c)    /* isync */
                        --nip;
-               if (*nip == 0x7c0004ac || (*nip >> 26) == 3) {
+               /* eieio from I/O string functions */
+               else if ((*nip) == 0x7c0006ac || *(nip+1) == 0x7c0006ac)
+                       nip += 2;
+
+               if (*nip == 0x7c0004ac || (*(nip+1) >> 26) == 3 ||
+                               (*nip >> 26) == 3) {
                        /* sync or twi */
                        unsigned int rb;
 
                        --nip;
                        rb = (*nip >> 11) & 0x1f;
-                       printk(KERN_DEBUG "%s bad port %lx at %p\n",
+                       printk(KERN_ERR "%s bad port %lx at %p\n",
                               (*nip & 0x100)? "OUT to": "IN from",
                               regs->gpr[rb] - _IO_BASE, nip);
                        regs->nip = fixup;
                        return;
                }
        }
-#endif /* CONFIG_ALL_PPC */
+//#endif /* CONFIG_ALL_PPC */
        printk("Machine check in kernel mode.\n");
        printk("Caused by (from SRR1=%lx): ", msr);
        switch (msr & 0x601F0000) {
Index: include/asm-ppc/io.h
===================================================================
RCS file: /mnt/test1/tslinux_mv21/linux-216/include/asm-ppc/io.h,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 io.h
--- include/asm-ppc/io.h        19 Jun 2002 18:16:26 -0000      1.1.1.1
+++ include/asm-ppc/io.h        30 May 2005 21:12:38 -0000
@@ -82,7 +82,7 @@
 #define insl(port, buf, nl)    _insl_ns((u32 *)((port)+_IO_BASE), (buf), (nl))
 #define outsl(port, buf, nl)   _outsl_ns((u32 *)((port)+_IO_BASE), (buf), (nl))
 
-#ifdef CONFIG_ALL_PPC
+#ifdef CONFIG_8xx
 /*
  * On powermacs, we will get a machine check exception if we
  * try to read data from a non-existent I/O port.  Because the
@@ -105,7 +105,7 @@
 {                                                      \
        unsigned int x;                                 \
        __asm__ __volatile__(                           \
-                       op "    %0,0,%1\n"              \
+               "0:"    op "    %0,0,%1\n"              \
                "1:     twi     0,%0,0\n"               \
                "2:     isync\n"                        \
                "3:     nop\n"                          \
@@ -116,6 +116,7 @@
                ".previous\n"                           \
                ".section __ex_table,\"a\"\n"           \
                "       .align  2\n"                    \
+               "       .long   0b,5b\n"                        \
                "       .long   1b,5b\n"                \
                "       .long   2b,5b\n"                \
                "       .long   3b,5b\n"                \
@@ -129,12 +130,20 @@
 extern __inline__ void name(unsigned int val, unsigned int port) \
 {                                                      \
        __asm__ __volatile__(                           \
-               op " %0,0,%1\n"                         \
-               "1:     sync\n"                         \
-               "2:\n"                                  \
+               "0:" op " %0,0,%1\n"                    \
+               "1:  twi 0, %0, 0\n"                    \
+               "2:   isync\n"                          \
+               "3:   nop\n"                            \
+               "4:\n"                                  \
+               ".section .fixup,\"ax\"\n"              \
+               "5:     b       4b\n"                   \
+               ".previous\n"                           \
                ".section __ex_table,\"a\"\n"           \
                "       .align  2\n"                    \
-               "       .long   1b,2b\n"                \
+               "       .long   0b,5b\n"                \
+               "       .long   1b,5b\n"                \
+               "       .long   2b,5b\n"                \
+               "       .long   3b,5b\n"                \
                ".previous"                             \
                : : "r" (val), "r" (port + _IO_BASE));  \
 }

Reply via email to