fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / arch / parisc / kernel / unaligned.c
index 3eda1da..bd2230d 100644 (file)
@@ -20,7 +20,6 @@
  *
  */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <asm/uaccess.h>
@@ -43,6 +42,8 @@
        "\tldil L%%" #lbl ", %%r1\n"                    \
        "\tldo R%%" #lbl "(%%r1), %%r1\n"               \
        "\tbv,n %%r0(%%r1)\n"
+/* If you use FIXUP_BRANCH, then you must list this clobber */
+#define FIXUP_BRANCH_CLOBBER "r1"
 
 /* 1111 1100 0000 0000 0001 0011 1100 0000 */
 #define OPCODE1(a,b,c) ((a)<<26|(b)<<12|(c)<<6) 
 #define ERR_NOTHANDLED -1
 #define ERR_PAGEFAULT  -2
 
-int unaligned_enabled = 1;
+int unaligned_enabled __read_mostly = 1;
 
 void die_if_kernel (char *str, struct pt_regs *regs, long err);
 
@@ -157,7 +158,7 @@ static int emulate_ldh(struct pt_regs *regs, int toreg)
 "      .previous\n"
        : "=r" (val), "=r" (ret)
        : "0" (val), "r" (saddr), "r" (regs->isr)
-       : "r20" );
+       : "r20", FIXUP_BRANCH_CLOBBER );
 
        DPRINTF("val = 0x" RFMT "\n", val);
 
@@ -202,7 +203,7 @@ static int emulate_ldw(struct pt_regs *regs, int toreg, int flop)
 "      .previous\n"
        : "=r" (val), "=r" (ret)
        : "0" (val), "r" (saddr), "r" (regs->isr)
-       : "r19", "r20" );
+       : "r19", "r20", FIXUP_BRANCH_CLOBBER );
 
        DPRINTF("val = 0x" RFMT "\n", val);
 
@@ -253,7 +254,7 @@ static int emulate_ldd(struct pt_regs *regs, int toreg, int flop)
 "      .previous\n"
        : "=r" (val), "=r" (ret)
        : "0" (val), "r" (saddr), "r" (regs->isr)
-       : "r19", "r20" );
+       : "r19", "r20", FIXUP_BRANCH_CLOBBER );
 #else
     {
        unsigned long valh=0,vall=0;
@@ -287,7 +288,7 @@ static int emulate_ldd(struct pt_regs *regs, int toreg, int flop)
 "      .previous\n"
        : "=r" (valh), "=r" (vall), "=r" (ret)
        : "0" (valh), "1" (vall), "r" (saddr), "r" (regs->isr)
-       : "r19", "r20" );
+       : "r19", "r20", FIXUP_BRANCH_CLOBBER );
        val=((__u64)valh<<32)|(__u64)vall;
     }
 #endif
@@ -335,7 +336,7 @@ static int emulate_sth(struct pt_regs *regs, int frreg)
 "      .previous\n"
        : "=r" (ret)
        : "r" (val), "r" (regs->ior), "r" (regs->isr)
-       : "r19" );
+       : "r19", FIXUP_BRANCH_CLOBBER );
 
        return ret;
 }
@@ -389,7 +390,7 @@ static int emulate_stw(struct pt_regs *regs, int frreg, int flop)
 "      .previous\n"
        : "=r" (ret)
        : "r" (val), "r" (regs->ior), "r" (regs->isr)
-       : "r19", "r20", "r21", "r22", "r1" );
+       : "r19", "r20", "r21", "r22", "r1", FIXUP_BRANCH_CLOBBER );
 
        return 0;
 }
@@ -450,7 +451,7 @@ static int emulate_std(struct pt_regs *regs, int frreg, int flop)
 "      .previous\n"
        : "=r" (ret)
        : "r" (val), "r" (regs->ior), "r" (regs->isr)
-       : "r19", "r20", "r21", "r22", "r1" );
+       : "r19", "r20", "r21", "r22", "r1", FIXUP_BRANCH_CLOBBER );
 #else
     {
        unsigned long valh=(val>>32),vall=(val&0xffffffffl);
@@ -495,7 +496,7 @@ static int emulate_std(struct pt_regs *regs, int frreg, int flop)
 "      .previous\n"
        : "=r" (ret)
        : "r" (valh), "r" (vall), "r" (regs->ior), "r" (regs->isr)
-       : "r19", "r20", "r21", "r1" );
+       : "r19", "r20", "r21", "r1", FIXUP_BRANCH_CLOBBER );
     }
 #endif
 
@@ -513,15 +514,18 @@ void handle_unaligned(struct pt_regs *regs)
        register int flop=0;    /* true if this is a flop */
 
        /* log a message with pacing */
-       if (user_mode(regs))
-       {
-               if (unaligned_count > 5 && jiffies - last_time > 5*HZ)
-               {
+       if (user_mode(regs)) {
+               if (current->thread.flags & PARISC_UAC_SIGBUS) {
+                       goto force_sigbus;
+               }
+
+               if (unaligned_count > 5 && jiffies - last_time > 5*HZ) {
                        unaligned_count = 0;
                        last_time = jiffies;
                }
-               if (++unaligned_count < 5)
-               {
+
+               if (!(current->thread.flags & PARISC_UAC_NOPRINT) 
+                   && ++unaligned_count < 5) {
                        char buf[256];
                        sprintf(buf, "%s(%d): unaligned access to 0x" RFMT " at ip=0x" RFMT "\n",
                                current->comm, current->pid, regs->ior, regs->iaoq[0]);
@@ -530,6 +534,7 @@ void handle_unaligned(struct pt_regs *regs)
                        show_regs(regs);
 #endif         
                }
+
                if (!unaligned_enabled)
                        goto force_sigbus;
        }
@@ -744,7 +749,7 @@ void handle_unaligned(struct pt_regs *regs)
                        si.si_signo = SIGSEGV;
                        si.si_errno = 0;
                        si.si_code = SEGV_MAPERR;
-                       si.si_addr = (void *)regs->ior;
+                       si.si_addr = (void __user *)regs->ior;
                        force_sig_info(SIGSEGV, &si, current);
                }
                else
@@ -754,7 +759,7 @@ force_sigbus:
                        si.si_signo = SIGBUS;
                        si.si_errno = 0;
                        si.si_code = BUS_ADRALN;
-                       si.si_addr = (void *)regs->ior;
+                       si.si_addr = (void __user *)regs->ior;
                        force_sig_info(SIGBUS, &si, current);
                }