From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from smtp-out.tiscali.be (spoolo1.tiscali.be [62.235.13.210]) by dsl2.external.hp.com (Postfix) with ESMTP id 3CF84483E for ; Sun, 19 Oct 2003 07:44:08 -0600 (MDT) Message-ID: <3F92950F.5050003@tiscali.be> Date: Sun, 19 Oct 2003 13:43:43 +0000 From: Joel Soete MIME-Version: 1.0 To: Randolph Chung Cc: parisc-linux@lists.parisc-linux.org Subject: Re: [parisc-linux] [patch] handle pagefaults on unaligned access References: <20031019063825.GE24406@tausq.org> In-Reply-To: <20031019063825.GE24406@tausq.org> Content-Type: text/plain; charset=us-ascii; format=flowed Sender: parisc-linux-admin@lists.parisc-linux.org Errors-To: parisc-linux-admin@lists.parisc-linux.org List-Help: List-Post: List-Subscribe: , List-Id: parisc-linux developers list List-Unsubscribe: , List-Archive: Hi Randolph, I don't yet fully tested (just compile 2.6) but imho need this change: ===== --- unaligned.c.RC.orig 2003-10-19 15:02:22.000000000 +0200 +++ unaligned.c 2003-10-19 15:03:00.000000000 +0200 @@ -474,7 +474,7 @@ " .word 5b,(6b-5b)\n" #endif " .previous\n" - : "r" (ret) + : "=r" (ret) : "r" (valh), "r" (vall), "r" (regs->ior), "r" (regs->isr) : "r19", "r20", "r21", "r1" ); } ===== hth, Joel Randolph Chung wrote: > while testing out gcj today, i was able to crash the machine > consistently with both 2.4 and 2.6 kernel. turns out our unaligned > handler doesn't handle page faults properly. in the case for gcj, there > was a ldh on the edge of the page, the first byte is on a resident page, > the 2nd byte is on a faulting page. > > this patch seems to fix it (at least the case i was seeing). any > comments before i commit it? > > thanks > randolph > > Index: arch/parisc/kernel/unaligned.c > =================================================================== > RCS file: /var/cvs/linux-2.4/arch/parisc/kernel/unaligned.c,v > retrieving revision 1.21 > diff -u -p -r1.21 unaligned.c > --- arch/parisc/kernel/unaligned.c 23 Sep 2003 20:15:33 -0000 1.21 > +++ arch/parisc/kernel/unaligned.c 19 Oct 2003 06:29:00 -0000 > @@ -128,6 +128,9 @@ > #define IM5_3(i) IM((i),5) > #define IM14(i) IM((i),14) > > +#define ERR_NOTHANDLED -1 > +#define ERR_PAGEFAULT -2 > + > int unaligned_enabled = 1; > > void die_if_kernel (char *str, struct pt_regs *regs, long err); > @@ -136,16 +139,28 @@ static int emulate_ldh(struct pt_regs *r > { > unsigned long saddr = regs->ior; > unsigned long val = 0; > + int ret; > > DPRINTF("load " RFMT ":" RFMT " to r%d for 2 bytes\n", > regs->isr, regs->ior, toreg); > > __asm__ __volatile__ ( > -" mtsp %3, %%sr1\n" > -" ldbs 0(%%sr1,%2), %%r20\n" > -" ldbs 1(%%sr1,%2), %0\n" > - "depw %%r20, 23, 24, %0\n" > - : "=r" (val) > +" mtsp %4, %%sr1\n" > +"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" > +#ifdef __LP64__ > +" .dword 1b,(3b-1b)\n" > +" .dword 2b,(3b-2b)\n" > +#else > +" .word 1b,(3b-1b)\n" > +" .word 2b,(3b-2b)\n" > +#endif > +" .previous\n" > + : "=r" (val), "=r" (ret) > : "0" (val), "r" (saddr), "r" (regs->isr) > : "r20" ); > > @@ -154,26 +169,39 @@ static int emulate_ldh(struct pt_regs *r > if (toreg) > regs->gr[toreg] = val; > > - return 0; > + return ret; > } > + > static int emulate_ldw(struct pt_regs *regs, int toreg, int flop) > { > unsigned long saddr = regs->ior; > unsigned long val = 0; > + int ret; > > DPRINTF("load " RFMT ":" RFMT " to r%d for 4 bytes\n", > regs->isr, regs->ior, toreg); > > __asm__ __volatile__ ( > -" zdep %2,28,2,%%r19\n" /* r19=(ofs&3)*8 */ > -" mtsp %3, %%sr1\n" > -" depw %%r0,31,2,%2\n" > -" ldw 0(%%sr1,%2),%0\n" > -" ldw 4(%%sr1,%2),%%r20\n" > +" zdep %3,28,2,%%r19\n" /* r19=(ofs&3)*8 */ > +" mtsp %4, %%sr1\n" > +" depw %%r0,31,2,%3\n" > +"1: ldw 0(%%sr1,%3),%0\n" > +"2: ldw 4(%%sr1,%3),%%r20\n" > " subi 32,%%r19,%%r19\n" > " mtctl %%r19,11\n" > " vshd %0,%%r20,%0\n" > - : "=r" (val) > +" cmpclr,= %%r0, %%r0, %1\n" > +"3: ldo -2(%%r0), %1\n" > +" .section __ex_table,\"a\"\n" > +#ifdef __LP64__ > +" .dword 1b,(3b-1b)\n" > +" .dword 2b,(3b-2b)\n" > +#else > +" .word 1b,(3b-1b)\n" > +" .word 2b,(3b-2b)\n" > +#endif > +" .previous\n" > + : "=r" (val), "=r" (ret) > : "0" (val), "r" (saddr), "r" (regs->isr) > : "r19", "r20" ); > > @@ -184,12 +212,13 @@ static int emulate_ldw(struct pt_regs *r > else if (toreg) > regs->gr[toreg] = val; > > - return 0; > + return ret; > } > static int emulate_ldd(struct pt_regs *regs, int toreg, int flop) > { > unsigned long saddr = regs->ior; > __u64 val = 0; > + int ret; > > DPRINTF("load " RFMT ":" RFMT " to r%d for 8 bytes\n", > regs->isr, regs->ior, toreg); > @@ -200,51 +229,77 @@ static int emulate_ldd(struct pt_regs *r > return -1; > #endif > __asm__ __volatile__ ( > -" depd,z %2,60,3,%%r19\n" /* r19=(ofs&7)*8 */ > -" mtsp %3, %%sr1\n" > -" depd %%r0,63,3,%2\n" > -" ldd 0(%%sr1,%2),%0\n" > -" ldd 8(%%sr1,%2),%%r20\n" > +" depd,z %3,60,3,%%r19\n" /* r19=(ofs&7)*8 */ > +" mtsp %4, %%sr1\n" > +" depd %%r0,63,3,%3\n" > +"1: ldd 0(%%sr1,%3),%0\n" > +"2: ldd 8(%%sr1,%3),%%r20\n" > " subi 64,%%r19,%%r19\n" > " mtsar %%r19\n" > " shrpd %0,%%r20,%%sar,%0\n" > - : "=r" (val) > +" cmpclr,= %%r0, %%r0, %1\n" > +"3: ldo -2(%%r0), %1\n" > +" .section __ex_table,\"a\"\n" > +#ifdef __LP64__ > +" .dword 1b,(3b-1b)\n" > +" .dword 2b,(3b-2b)\n" > +#else > +" .word 1b,(3b-1b)\n" > +" .word 2b,(3b-2b)\n" > +#endif > +" .previous\n" > + : "=r" (val), "=r" (ret) > : "0" (val), "r" (saddr), "r" (regs->isr) > : "r19", "r20" ); > #else > { > unsigned long valh=0,vall=0; > __asm__ __volatile__ ( > -" zdep %4,29,2,%%r19\n" /* r19=(ofs&3)*8 */ > -" mtsp %5, %%sr1\n" > -" dep %%r0,31,2,%4\n" > -" ldw 0(%%sr1,%5),%0\n" > -" ldw 4(%%sr1,%5),%1\n" > -" ldw 8(%%sr1,%5),%%r20\n" > +" zdep %5,29,2,%%r19\n" /* r19=(ofs&3)*8 */ > +" mtsp %6, %%sr1\n" > +" dep %%r0,31,2,%5\n" > +"1: ldw 0(%%sr1,%6),%0\n" > +"2: ldw 4(%%sr1,%6),%1\n" > +"3: ldw 8(%%sr1,%6),%%r20\n" > " subi 32,%%r19,%%r19\n" > " mtsar %%r19\n" > " vshd %0,%1,%0\n" > " vshd %1,%%r20,%1\n" > - : "=r" (valh), "=r" (vall) > +" cmpclr,= %%r0, %%r0, %2\n" > +"4: ldo -2(%%r0), %2\n" > +" .section __ex_table,\"a\"\n" > +#ifdef __LP64__ > +" .dword 1b,(4b-1b)\n" > +" .dword 2b,(4b-2b)\n" > +" .dword 3b,(4b-3b)\n" > +#else > +" .word 1b,(4b-1b)\n" > +" .word 2b,(4b-2b)\n" > +" .word 3b,(4b-3b)\n" > +#endif > +" .previous\n" > + : "=r" (valh), "=r" (vall), "=r" (ret) > : "0" (valh), "1" (vall), "r" (saddr), "r" (regs->isr) > : "r19", "r20" ); > val=((__u64)valh<<32)|(__u64)vall; > } > #endif > > - DPRINTF("val = 0x" RFMT "\n", val); > + DPRINTF("val = 0xllx\n", val); > > if (flop) > regs->fr[toreg] = val; > else if (toreg) > regs->gr[toreg] = val; > > - return 0; > + return ret; > } > > static int emulate_sth(struct pt_regs *regs, int frreg) > { > unsigned long val = regs->gr[frreg]; > + int ret; > + > if (!frreg) > val = 0; > > @@ -252,19 +307,32 @@ static int emulate_sth(struct pt_regs *r > val, regs->isr, regs->ior); > > __asm__ __volatile__ ( > -" mtsp %2, %%sr1\n" > -" extrw,u %0, 23, 8, %%r19\n" > -" stb %0, 1(%%sr1, %1)\n" > -" stb %%r19, 0(%%sr1, %1)\n" > - : > +" mtsp %3, %%sr1\n" > +" 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" > +#ifdef __LP64__ > +" .dword 1b,(3b-1b)\n" > +" .dword 2b,(3b-2b)\n" > +#else > +" .word 1b,(3b-1b)\n" > +" .word 2b,(3b-2b)\n" > +#endif > +" .previous\n" > + : "=r" (ret) > : "r" (val), "r" (regs->ior), "r" (regs->isr) > : "r19" ); > > - return 0; > + return ret; > } > + > static int emulate_stw(struct pt_regs *regs, int frreg, int flop) > { > unsigned long val; > + int ret; > > if (flop) > val = ((__u32*)(regs->fr))[frreg]; > @@ -278,22 +346,33 @@ static int emulate_stw(struct pt_regs *r > > > __asm__ __volatile__ ( > -" mtsp %2, %%sr1\n" > -" zdep %1, 28, 2, %%r19\n" > -" dep %%r0, 31, 2, %1\n" > +" mtsp %3, %%sr1\n" > +" zdep %2, 28, 2, %%r19\n" > +" dep %%r0, 31, 2, %2\n" > " mtsar %%r19\n" > " depwi,z -2, %%sar, 32, %%r19\n" > -" ldw 0(%%sr1,%1),%%r20\n" > -" ldw 4(%%sr1,%1),%%r21\n" > -" vshd %%r0, %0, %%r22\n" > -" vshd %0, %%r0, %%r1\n" > +"1: ldw 0(%%sr1,%2),%%r20\n" > +"2: ldw 4(%%sr1,%2),%%r21\n" > +" vshd %%r0, %1, %%r22\n" > +" vshd %1, %%r0, %%r1\n" > " and %%r20, %%r19, %%r20\n" > " andcm %%r21, %%r19, %%r21\n" > " or %%r22, %%r20, %%r20\n" > " or %%r1, %%r21, %%r21\n" > -" stw %%r20,0(%%sr1,%1)\n" > -" stw %%r21,4(%%sr1,%1)\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" > +#ifdef __LP64__ > +" .dword 1b,(3b-1b)\n" > +" .dword 2b,(3b-2b)\n" > +#else > +" .word 1b,(3b-1b)\n" > +" .word 2b,(3b-2b)\n" > +#endif > +" .previous\n" > + : "=r" (ret) > : "r" (val), "r" (regs->ior), "r" (regs->isr) > : "r19", "r20", "r21", "r22", "r1" ); > > @@ -302,6 +381,7 @@ static int emulate_stw(struct pt_regs *r > static int emulate_std(struct pt_regs *regs, int frreg, int flop) > { > __u64 val; > + int ret; > > if (flop) > val = regs->fr[frreg]; > @@ -310,7 +390,7 @@ static int emulate_std(struct pt_regs *r > else > val = 0; > > - DPRINTF("store r%d (0x" %016llx ") to " RFMT ":" RFMT " for 8 bytes\n", frreg, > + DPRINTF("store r%d (0x%016llx) to " RFMT ":" RFMT " for 8 bytes\n", frreg, > val, regs->isr, regs->ior); > > #ifdef CONFIG_PA20 > @@ -319,52 +399,84 @@ static int emulate_std(struct pt_regs *r > return -1; > #endif > __asm__ __volatile__ ( > -" mtsp %2, %%sr1\n" > -" depd,z %1, 60, 3, %%r19\n" > -" depd %%r0, 63, 3, %1\n" > +" mtsp %3, %%sr1\n" > +" depd,z %2, 60, 3, %%r19\n" > +" depd %%r0, 63, 3, %2\n" > " mtsar %%r19\n" > " depdi,z -2, %%sar, 64, %%r19\n" > -" ldd 0(%%sr1,%1),%%r20\n" > -" ldd 8(%%sr1,%1),%%r21\n" > -" shrpd %%r0, %0, %%sar, %%r22\n" > -" shrpd %0, %%r0, %%sar, %%r1\n" > +"1: ldd 0(%%sr1,%2),%%r20\n" > +"2: ldd 8(%%sr1,%2),%%r21\n" > +" shrpd %%r0, %1, %%sar, %%r22\n" > +" shrpd %1, %%r0, %%sar, %%r1\n" > " and %%r20, %%r19, %%r20\n" > " andcm %%r21, %%r19, %%r21\n" > " or %%r22, %%r20, %%r20\n" > " or %%r1, %%r21, %%r21\n" > -" std %%r20,0(%%sr1,%1)\n" > -" std %%r21,8(%%sr1,%1)\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" > +#ifdef __LP64__ > +" .dword 1b,(5b-1b)\n" > +" .dword 2b,(5b-2b)\n" > +" .dword 3b,(5b-3b)\n" > +" .dword 4b,(5b-4b)\n" > +#else > +" .word 1b,(5b-1b)\n" > +" .word 2b,(5b-2b)\n" > +" .word 3b,(5b-3b)\n" > +" .word 4b,(5b-4b)\n" > +#endif > +" .previous\n" > + : "=r" (ret) > : "r" (val), "r" (regs->ior), "r" (regs->isr) > : "r19", "r20", "r21", "r22", "r1" ); > #else > { > unsigned long valh=(val>>32),vall=(val&0xffffffffl); > __asm__ __volatile__ ( > -" mtsp %3, %%sr1\n" > -" zdep %1, 29, 2, %%r19\n" > -" dep %%r0, 31, 2, %1\n" > +" mtsp %4, %%sr1\n" > +" zdep %2, 29, 2, %%r19\n" > +" dep %%r0, 31, 2, %2\n" > " mtsar %%r19\n" > " zvdepi -2, 32, %%r19\n" > -" ldw 0(%%sr1,%2),%%r20\n" > -" ldw 8(%%sr1,%2),%%r21\n" > -" vshd %0, %1, %%r1\n" > -" vshd %%r0, %0, %0\n" > -" vshd %1, %%r0, %1\n" > +"1: ldw 0(%%sr1,%3),%%r20\n" > +"2: ldw 8(%%sr1,%3),%%r21\n" > +" vshd %1, %2, %%r1\n" > +" vshd %%r0, %1, %1\n" > +" vshd %2, %%r0, %2\n" > " and %%r20, %%r19, %%r20\n" > " andcm %%r21, %%r19, %%r21\n" > -" or %0, %%r20, %0\n" > -" or %1, %%r21, %1\n" > -" stw %0,0(%%sr1,%2)\n" > -" stw %%r1,4(%%sr1,%2)\n" > -" stw %1,8(%%sr1,%2)\n" > - : > +" or %1, %%r20, %1\n" > +" or %2, %%r21, %2\n" > +"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" > +#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" > +#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" > +#endif > +" .previous\n" > + : "r" (ret) > : "r" (valh), "r" (vall), "r" (regs->ior), "r" (regs->isr) > : "r19", "r20", "r21", "r1" ); > } > #endif > > - return 0; > + return ret; > } > > void handle_unaligned(struct pt_regs *regs) > @@ -373,7 +485,7 @@ void handle_unaligned(struct pt_regs *re > static unsigned long last_time = 0; > unsigned long newbase = R1(regs->iir)?regs->gr[R1(regs->iir)]:0; > int modify = 0; > - int ret = -1; > + int ret = ERR_NOTHANDLED; > struct siginfo si; > register int flop=0; /* true if this is a flop */ > > @@ -567,7 +679,7 @@ void handle_unaligned(struct pt_regs *re > case OPCODE_LDCW_I: > case OPCODE_LDCD_S: > case OPCODE_LDCW_S: > - ret = -1; /* "undefined", but lets kill them. */ > + ret = ERR_NOTHANDLED; /* "undefined", but lets kill them. */ > break; > } > #ifdef CONFIG_PA20 > @@ -632,7 +744,7 @@ void handle_unaligned(struct pt_regs *re > regs->gr[R1(regs->iir)] = newbase; > > > - if (ret < 0) > + if (ret == ERR_NOTHANDLED) > printk(KERN_CRIT "Not-handled unaligned insn 0x%08lx\n", regs->iir); > > DPRINTF("ret = %d\n", ret); > @@ -641,13 +753,25 @@ void handle_unaligned(struct pt_regs *re > { > printk(KERN_CRIT "Unaligned handler failed, ret = %d\n", ret); > die_if_kernel("Unaligned data reference", regs, 28); > + > + if (ret == ERR_PAGEFAULT) > + { > + si.si_signo = SIGSEGV; > + si.si_errno = 0; > + si.si_code = SEGV_MAPERR; > + si.si_addr = (void *)regs->ior; > + force_sig_info(SIGSEGV, &si, current); > + } > + else > + { > force_sigbus: > - /* couldn't handle it ... */ > - si.si_signo = SIGBUS; > - si.si_errno = 0; > - si.si_code = BUS_ADRALN; > - si.si_addr = (void *)regs->ior; > - force_sig_info(SIGBUS, &si, current); > + /* couldn't handle it ... */ > + si.si_signo = SIGBUS; > + si.si_errno = 0; > + si.si_code = BUS_ADRALN; > + si.si_addr = (void *)regs->ior; > + force_sig_info(SIGBUS, &si, current); > + } > > return; > }