X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fparisc%2Fkernel%2Funaligned.c;h=bd2230d6a2a69645352eb4b1c8c71b7a4115b5a5;hb=refs%2Fheads%2Fvserver;hp=530235c0b17e3fd8ab37c4f549dce927e2374536;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/arch/parisc/kernel/unaligned.c b/arch/parisc/kernel/unaligned.c index 530235c0b..bd2230d6a 100644 --- a/arch/parisc/kernel/unaligned.c +++ b/arch/parisc/kernel/unaligned.c @@ -20,9 +20,9 @@ * */ -#include #include #include +#include /* #define DEBUG_UNALIGNED 1 */ @@ -38,6 +38,13 @@ #define RFMT "%08lx" #endif +#define FIXUP_BRANCH(lbl) \ + "\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 OPCODE2(a,b) ((a)<<26|(b)<<1) @@ -116,7 +123,7 @@ #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); @@ -134,20 +141,24 @@ static int emulate_ldh(struct pt_regs *regs, int toreg) "1: ldbs 0(%%sr1,%3), %%r20\n" "2: ldbs 1(%%sr1,%3), %0\n" " depw %%r20, 23, 24, %0\n" -" cmpclr,= %%r0, %%r0, %1\n" -"3: ldo -2(%%r0), %1\n" -" .section __ex_table,\"a\"\n" +" copy %%r0, %1\n" +"3: \n" +" .section .fixup,\"ax\"\n" +"4: ldi -2, %1\n" + FIXUP_BRANCH(3b) +" .previous\n" +" .section __ex_table,\"aw\"\n" #ifdef __LP64__ -" .dword 1b,(3b-1b)\n" -" .dword 2b,(3b-2b)\n" +" .dword 1b,4b\n" +" .dword 2b,4b\n" #else -" .word 1b,(3b-1b)\n" -" .word 2b,(3b-2b)\n" +" .word 1b,4b\n" +" .word 2b,4b\n" #endif " .previous\n" : "=r" (val), "=r" (ret) : "0" (val), "r" (saddr), "r" (regs->isr) - : "r20" ); + : "r20", FIXUP_BRANCH_CLOBBER ); DPRINTF("val = 0x" RFMT "\n", val); @@ -175,20 +186,24 @@ static int emulate_ldw(struct pt_regs *regs, int toreg, int flop) " subi 32,%%r19,%%r19\n" " mtctl %%r19,11\n" " vshd %0,%%r20,%0\n" -" cmpclr,= %%r0, %%r0, %1\n" -"3: ldo -2(%%r0), %1\n" -" .section __ex_table,\"a\"\n" +" copy %%r0, %1\n" +"3: \n" +" .section .fixup,\"ax\"\n" +"4: ldi -2, %1\n" + FIXUP_BRANCH(3b) +" .previous\n" +" .section __ex_table,\"aw\"\n" #ifdef __LP64__ -" .dword 1b,(3b-1b)\n" -" .dword 2b,(3b-2b)\n" +" .dword 1b,4b\n" +" .dword 2b,4b\n" #else -" .word 1b,(3b-1b)\n" -" .word 2b,(3b-2b)\n" +" .word 1b,4b\n" +" .word 2b,4b\n" #endif " .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); @@ -222,20 +237,24 @@ static int emulate_ldd(struct pt_regs *regs, int toreg, int flop) " subi 64,%%r19,%%r19\n" " mtsar %%r19\n" " shrpd %0,%%r20,%%sar,%0\n" -" cmpclr,= %%r0, %%r0, %1\n" -"3: ldo -2(%%r0), %1\n" -" .section __ex_table,\"a\"\n" +" copy %%r0, %1\n" +"3: \n" +" .section .fixup,\"ax\"\n" +"4: ldi -2, %1\n" + FIXUP_BRANCH(3b) +" .previous\n" +" .section __ex_table,\"aw\"\n" #ifdef __LP64__ -" .dword 1b,(3b-1b)\n" -" .dword 2b,(3b-2b)\n" +" .dword 1b,4b\n" +" .dword 2b,4b\n" #else -" .word 1b,(3b-1b)\n" -" .word 2b,(3b-2b)\n" +" .word 1b,4b\n" +" .word 2b,4b\n" #endif " .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; @@ -250,22 +269,26 @@ static int emulate_ldd(struct pt_regs *regs, int toreg, int flop) " mtsar %%r19\n" " vshd %0,%1,%0\n" " vshd %1,%%r20,%1\n" -" cmpclr,= %%r0, %%r0, %2\n" -"4: ldo -2(%%r0), %2\n" -" .section __ex_table,\"a\"\n" +" copy %%r0, %2\n" +"4: \n" +" .section .fixup,\"ax\"\n" +"5: ldi -2, %2\n" + FIXUP_BRANCH(4b) +" .previous\n" +" .section __ex_table,\"aw\"\n" #ifdef __LP64__ -" .dword 1b,(4b-1b)\n" -" .dword 2b,(4b-2b)\n" -" .dword 3b,(4b-3b)\n" +" .dword 1b,5b\n" +" .dword 2b,5b\n" +" .dword 3b,5b\n" #else -" .word 1b,(4b-1b)\n" -" .word 2b,(4b-2b)\n" -" .word 3b,(4b-3b)\n" +" .word 1b,5b\n" +" .word 2b,5b\n" +" .word 3b,5b\n" #endif " .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 @@ -296,20 +319,24 @@ static int emulate_sth(struct pt_regs *regs, int frreg) " extrw,u %1, 23, 8, %%r19\n" "1: stb %1, 1(%%sr1, %2)\n" "2: stb %%r19, 0(%%sr1, %2)\n" -" cmpclr,= %%r0, %%r0, %0\n" -"3: ldo -2(%%r0), %0\n" -" .section __ex_table,\"a\"\n" +" copy %%r0, %0\n" +"3: \n" +" .section .fixup,\"ax\"\n" +"4: ldi -2, %0\n" + FIXUP_BRANCH(3b) +" .previous\n" +" .section __ex_table,\"aw\"\n" #ifdef __LP64__ -" .dword 1b,(3b-1b)\n" -" .dword 2b,(3b-2b)\n" +" .dword 1b,4b\n" +" .dword 2b,4b\n" #else -" .word 1b,(3b-1b)\n" -" .word 2b,(3b-2b)\n" +" .word 1b,4b\n" +" .word 2b,4b\n" #endif " .previous\n" : "=r" (ret) : "r" (val), "r" (regs->ior), "r" (regs->isr) - : "r19" ); + : "r19", FIXUP_BRANCH_CLOBBER ); return ret; } @@ -346,20 +373,24 @@ static int emulate_stw(struct pt_regs *regs, int frreg, int flop) " or %%r1, %%r21, %%r21\n" " stw %%r20,0(%%sr1,%2)\n" " stw %%r21,4(%%sr1,%2)\n" -" cmpclr,= %%r0, %%r0, %0\n" -"3: ldo -2(%%r0), %0\n" -" .section __ex_table,\"a\"\n" +" copy %%r0, %0\n" +"3: \n" +" .section .fixup,\"ax\"\n" +"4: ldi -2, %0\n" + FIXUP_BRANCH(3b) +" .previous\n" +" .section __ex_table,\"aw\"\n" #ifdef __LP64__ -" .dword 1b,(3b-1b)\n" -" .dword 2b,(3b-2b)\n" +" .dword 1b,4b\n" +" .dword 2b,4b\n" #else -" .word 1b,(3b-1b)\n" -" .word 2b,(3b-2b)\n" +" .word 1b,4b\n" +" .word 2b,4b\n" #endif " .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; } @@ -399,24 +430,28 @@ static int emulate_std(struct pt_regs *regs, int frreg, int flop) " or %%r1, %%r21, %%r21\n" "3: std %%r20,0(%%sr1,%2)\n" "4: std %%r21,8(%%sr1,%2)\n" -" cmpclr,= %%r0, %%r0, %0\n" -"5: ldo -2(%%r0), %0\n" -" .section __ex_table,\"a\"\n" +" copy %%r0, %0\n" +"5: \n" +" .section .fixup,\"ax\"\n" +"6: ldi -2, %0\n" + FIXUP_BRANCH(5b) +" .previous\n" +" .section __ex_table,\"aw\"\n" #ifdef __LP64__ -" .dword 1b,(5b-1b)\n" -" .dword 2b,(5b-2b)\n" -" .dword 3b,(5b-3b)\n" -" .dword 4b,(5b-4b)\n" +" .dword 1b,6b\n" +" .dword 2b,6b\n" +" .dword 3b,6b\n" +" .dword 4b,6b\n" #else -" .word 1b,(5b-1b)\n" -" .word 2b,(5b-2b)\n" -" .word 3b,(5b-3b)\n" -" .word 4b,(5b-4b)\n" +" .word 1b,6b\n" +" .word 2b,6b\n" +" .word 3b,6b\n" +" .word 4b,6b\n" #endif " .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); @@ -438,26 +473,30 @@ static int emulate_std(struct pt_regs *regs, int frreg, int flop) "3: stw %1,0(%%sr1,%1)\n" "4: stw %%r1,4(%%sr1,%3)\n" "5: stw %2,8(%%sr1,%3)\n" -" cmpclr,= %%r0, %%r0, %0\n" -"6: ldo -2(%%r0), %0\n" -" .section __ex_table,\"a\"\n" +" copy %%r0, %0\n" +"6: \n" +" .section .fixup,\"ax\"\n" +"7: ldi -2, %0\n" + FIXUP_BRANCH(6b) +" .previous\n" +" .section __ex_table,\"aw\"\n" #ifdef __LP64__ -" .dword 1b,(6b-1b)\n" -" .dword 2b,(6b-2b)\n" -" .dword 3b,(6b-3b)\n" -" .dword 4b,(6b-4b)\n" -" .dword 5b,(6b-5b)\n" +" .dword 1b,7b\n" +" .dword 2b,7b\n" +" .dword 3b,7b\n" +" .dword 4b,7b\n" +" .dword 5b,7b\n" #else -" .word 1b,(6b-1b)\n" -" .word 2b,(6b-2b)\n" -" .word 3b,(6b-3b)\n" -" .word 4b,(6b-4b)\n" -" .word 5b,(6b-5b)\n" +" .word 1b,7b\n" +" .word 2b,7b\n" +" .word 3b,7b\n" +" .word 4b,7b\n" +" .word 5b,7b\n" #endif " .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 @@ -475,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]); @@ -557,16 +599,6 @@ void handle_unaligned(struct pt_regs *regs) break; } - if (regs->isr != regs->sr[7]) - { - printk(KERN_CRIT "isr verification failed (isr: " RFMT ", sr7: " RFMT "\n", - regs->isr, regs->sr[7]); - - /* don't kill him though, since he has appropriate access to the page, or we - * would never have gotten here. - */ - } - /* TODO: make this cleaner... */ switch (regs->iir & OPCODE1_MASK) { @@ -717,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 @@ -727,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); }