* [parisc-linux] [RFC] Revamp exception handling in the kernel
@ 2004-09-11 16:53 Randolph Chung
2004-09-11 22:49 ` John David Anglin
` (2 more replies)
0 siblings, 3 replies; 16+ messages in thread
From: Randolph Chung @ 2004-09-11 16:53 UTC (permalink / raw)
To: PARISC list
Currently, palinux handles exceptions differently from other
architectures in the kernel. On most other architectures, an exception
to a read/store that has an associated exception table entry in the
kernel is handled by code in a fixup section, which is responsible for
setting the proper return values, etc.
On pa, we currently have an interesting scheme that associates a "skip"
value with each exception entry. The bottom two bits of the skip value
indicates whether r8,r9 should be set to -EFAULT,0 during a fault, and
the top bits indicate a relative adjustment that should be applied to
the iaoq to handle the fault.
The patch below, based on my discussions with jejb, changes this
behaviour so that it more closely matches what happens on other
architectures (but with a twist...): the exception table entries now
contain an *absolute* address to branch to for the fixup [1]. The
fixups are placed in a separate fixup section (this simplifies a bit of
code in unaligned.c too). The fixup code loads up whatever values are
required by the caller, and typically branches back to the original
code at a correct location to continue.
This frees up the bottom two bits for other purposes -- currently there
is no way to pass the faulting address and instruction back to an
exception table handler. The proposal is to reuse the bottom 2 bits to
indicate whether the faulting address/insn should be passed back to the
handler in r8/r9. (this will be used by the optimized pa copy routines,
for example)
One downside of this approach is that the extra fixup sections take up
more space, so the end kernel is bigger. In my test on 64-bit, the
kernel size increases by ~2%.
The patch below has been tested against 2.6.8.1-pa11 on 64-bit-SMP, and
compile tested on 32-bit-UP. I don't have a 32-bit machine to test on
atm, so test reports are most welcome [2]. I've applied the manual stubs
trick that jejb mentioned earlier, but only for 64-bit, since the 32-bit
linker is able to generate those stubs automatically when needed.
Comments?
randolph
[1] The change to using absolute jumps is because gas doesn't want to
let us take the difference of labels in two different sections (viz.
.text vs .fixup). jejb and I are not able to come up with a case where
using relative jumps is required.
[2] Since this changes the *exception* path, simply booting a kernel or
building things will not exercise the new code. You need to do something
that will trigger a load/store fault on userspace in the kernel. If I
were Carlos I would have attached a nice testsuite to this patch, but
alas I've only done some manual testing on a few cases.... there's a
debug printk in this patch which will print something like:
"applying fixup for 0x10281ae4, fixup at 0x103ca614"
if you see that, then you are exercising the new code.
Index: arch/parisc/kernel/syscall.S
===================================================================
RCS file: /var/cvs/linux-2.6/arch/parisc/kernel/syscall.S,v
retrieving revision 1.14
diff -u -p -r1.14 syscall.S
--- arch/parisc/kernel/syscall.S 10 Sep 2004 14:52:01 -0000 1.14
+++ arch/parisc/kernel/syscall.S 11 Sep 2004 16:25:50 -0000
@@ -29,6 +29,19 @@
#else
.level 1.1
#endif
+
+#ifndef __LP64__
+ .macro fixup_branch,lbl
+ b \lbl
+ .endm
+#else
+ .macro fixup_branch,lbl
+ ldil L%\lbl, %r1
+ ldo R%\lbl(%r1), %r1
+ bv,n %r0(%r1)
+ .endm
+#endif
+
.text
.import syscall_exit,code
@@ -575,10 +588,8 @@ cas_action:
/* Return to userspace, set no error */
b lws_exit
copy %r0, %r21
- nop /* Add some visual space in objdump */
- nop
- nop
- nop
+
+ .section .fixup,"ax"
3:
/* Error occured on load or store */
#ifdef CONFIG_SMP
@@ -588,12 +599,13 @@ cas_action:
stw %r0, 4(%sr2,%r20)
# endif
#endif
- b lws_exit
+ fixup_branch lws_exit
ldo -EFAULT(%r0),%r21 /* set errno */
nop
nop
nop
nop
+ .previous
/* Two exception table entries, one for the load,
the other for the store. Either return -EFAULT */
@@ -601,10 +613,10 @@ cas_action:
#ifdef __LP64__
/* Pad the address calculation */
.word 0,(2b - linux_gateway_page)
- .dword (3b - 2b)
+ .dword 3b
#else
.word 2b - linux_gateway_page
- .word (3b - 2b)
+ .word 3b
#endif
.previous
@@ -612,10 +624,10 @@ cas_action:
#ifdef __LP64__
/* Pad the address calculation */
.word 0,(1b - linux_gateway_page)
- .dword (3b - 1b)
+ .dword 3b
#else
.word 1b - linux_gateway_page
- .word (3b - 1b)
+ .word 3b
#endif
.previous
Index: arch/parisc/kernel/unaligned.c
===================================================================
RCS file: /var/cvs/linux-2.6/arch/parisc/kernel/unaligned.c,v
retrieving revision 1.8
diff -u -p -r1.8 unaligned.c
--- arch/parisc/kernel/unaligned.c 21 Aug 2004 06:19:33 -0000 1.8
+++ arch/parisc/kernel/unaligned.c 11 Sep 2004 16:25:50 -0000
@@ -23,6 +23,7 @@
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <asm/uaccess.h>
/* #define DEBUG_UNALIGNED 1 */
@@ -134,15 +135,19 @@ static int emulate_ldh(struct pt_regs *r
"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)
@@ -175,15 +180,19 @@ static int emulate_ldw(struct pt_regs *r
" 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)
@@ -222,15 +231,19 @@ static int emulate_ldd(struct pt_regs *r
" 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)
@@ -250,17 +263,20 @@ static int emulate_ldd(struct pt_regs *r
" 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"
#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"
+" .dword 1b,5b\n"
+" .dword 2b,5b\n"
+" .dword 3b,5b\n"
+#else
+" .word 1b,5b\n"
+" .word 2b,5b\n"
+" .word 3b,5b\n"
#endif
" .previous\n"
: "=r" (valh), "=r" (vall), "=r" (ret)
@@ -296,15 +312,19 @@ static int emulate_sth(struct pt_regs *r
" 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)
@@ -346,15 +366,19 @@ static int emulate_stw(struct pt_regs *r
" 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)
@@ -399,19 +423,23 @@ static int emulate_std(struct pt_regs *r
" 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"
-#else
-" .word 1b,(5b-1b)\n"
-" .word 2b,(5b-2b)\n"
-" .word 3b,(5b-3b)\n"
-" .word 4b,(5b-4b)\n"
+" .dword 1b,6b\n"
+" .dword 2b,6b\n"
+" .dword 3b,6b\n"
+" .dword 4b,6b\n"
+#else
+" .word 1b,6b\n"
+" .word 2b,6b\n"
+" .word 3b,6b\n"
+" .word 4b,6b\n"
#endif
" .previous\n"
: "=r" (ret)
@@ -438,21 +466,25 @@ static int emulate_std(struct pt_regs *r
"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"
-#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"
+" .dword 1b,7b\n"
+" .dword 2b,7b\n"
+" .dword 3b,7b\n"
+" .dword 4b,7b\n"
+" .dword 5b,7b\n"
+#else
+" .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)
Index: arch/parisc/lib/lusercopy.S
===================================================================
RCS file: /var/cvs/linux-2.6/arch/parisc/lib/lusercopy.S,v
retrieving revision 1.3
diff -u -p -r1.3 lusercopy.S
--- arch/parisc/lib/lusercopy.S 17 Jan 2004 06:39:24 -0000 1.3
+++ arch/parisc/lib/lusercopy.S 11 Sep 2004 16:25:50 -0000
@@ -53,6 +53,18 @@
mtsp %r1,%sr1
.endm
+#ifndef __LP64__
+ .macro fixup_branch lbl
+ b \lbl
+ .endm
+#else
+ .macro fixup_branch lbl
+ ldil L%\lbl, %r1
+ ldo R%\lbl(%r1), %r1
+ bv,n %r0(%r1)
+ .endm
+#endif
+
/*
* unsigned long
* lcopy_to_user(void *to, const void *from, unsigned long n)
@@ -77,14 +89,16 @@ $lctu_done:
copy %r24,%r28
.exit
-2: b $lctu_done
+ .section .fixup,"ax"
+2: fixup_branch $lctu_done
ldo 1(%r24),%r24
+ .previous
- .section __ex_table,"a"
+ .section __ex_table,"aw"
#ifdef __LP64__
- .dword 1b,(2b-1b)
+ .dword 1b,2b
#else
- .word 1b,(2b-1b)
+ .word 1b,2b
#endif
.previous
@@ -118,18 +132,20 @@ $lcfu_done:
copy %r24,%r28
.exit
+ .section .fixup,"ax"
2: copy %r24,%r23
$lcfu_zero_loop:
addib,<> -1,%r23,$lcfu_zero_loop
stbs,ma %r0,1(%r26)
- b $lcfu_done
+ fixup_branch $lcfu_done
nop
+ .previous
- .section __ex_table,"a"
+ .section __ex_table,"aw"
#ifdef __LP64__
- .dword 1b,(2b-1b)
+ .dword 1b,2b
#else
- .word 1b,(2b-1b)
+ .word 1b,2b
#endif
.previous
@@ -159,14 +175,16 @@ $lciu_done:
copy %r24,%r28
.exit
-2: b $lciu_done
+ .section .fixup,"ax"
+2: fixup_branch $lciu_done
ldo 1(%r24),%r24
+ .previous
- .section __ex_table,"a"
+ .section __ex_table,"aw"
#ifdef __LP64__
- .dword 1b,(2b-1b)
+ .dword 1b,2b
#else
- .word 1b,(2b-1b)
+ .word 1b,2b
#endif
.previous
@@ -201,16 +219,18 @@ $lsfu_exit:
nop
.exit
-3: b $lsfu_exit
+ .section .fixup,"ax"
+3: fixup_branch $lsfu_exit
ldi -EFAULT,%r28
+ .previous
- .section __ex_table,"a"
+ .section __ex_table,"aw"
#ifdef __LP64__
- .dword 1b,(3b-1b)
- .dword 2b,(3b-2b)
+ .dword 1b,3b
+ .dword 2b,3b
#else
- .word 1b,(3b-1b)
- .word 2b,(3b-2b)
+ .word 1b,3b
+ .word 2b,3b
#endif
.previous
@@ -239,14 +259,16 @@ $lclu_done:
copy %r25,%r28
.exit
-2: b $lclu_done
+ .section .fixup,"ax"
+2: fixup_branch $lclu_done
ldo 1(%r25),%r25
+ .previous
- .section __ex_table,"a"
+ .section __ex_table,"aw"
#ifdef __LP64__
- .dword 1b,(2b-1b)
+ .dword 1b,2b
#else
- .word 1b,(2b-1b)
+ .word 1b,2b
#endif
.previous
@@ -282,16 +304,18 @@ $lslen_nzero:
b $lslen_done
ldo 1(%r26),%r26 /* special case for N == 0 */
-3: b $lslen_done
+ .section .fixup,"ax"
+3: fixup_branch $lslen_done
copy %r24,%r26 /* reset r26 so 0 is returned on fault */
+ .previous
- .section __ex_table,"a"
+ .section __ex_table,"aw"
#ifdef __LP64__
- .dword 1b,(3b-1b)
- .dword 2b,(3b-2b)
+ .dword 1b,3b
+ .dword 2b,3b
#else
- .word 1b,(3b-1b)
- .word 2b,(3b-2b)
+ .word 1b,3b
+ .word 2b,3b
#endif
.previous
Index: arch/parisc/mm/fault.c
===================================================================
RCS file: /var/cvs/linux-2.6/arch/parisc/mm/fault.c,v
retrieving revision 1.1
diff -u -p -r1.1 fault.c
--- arch/parisc/mm/fault.c 29 Jul 2003 17:00:42 -0000 1.1
+++ arch/parisc/mm/fault.c 11 Sep 2004 16:25:50 -0000
@@ -235,12 +235,14 @@ no_context:
if (fix) {
- if (fix->skip & 1)
- regs->gr[8] = -EFAULT;
- if (fix->skip & 2)
- regs->gr[9] = 0;
+printk("applying fixup for 0x%lx, fixup at 0x%lx\n", regs->iaoq[0], fix->fixup & ~3);
- regs->iaoq[0] += ((fix->skip) & ~3);
+ if (fix->fixup & 1)
+ regs->gr[8] = regs->iir;
+ if (fix->fixup & 2)
+ regs->gr[9] = regs->ior;
+
+ regs->iaoq[0] = ((fix->fixup) & ~3);
/*
* NOTE: In some cases the faulting instruction
Index: include/asm-parisc/uaccess.h
===================================================================
RCS file: /var/cvs/linux-2.6/include/asm-parisc/uaccess.h,v
retrieving revision 1.13
diff -u -p -r1.13 uaccess.h
--- include/asm-parisc/uaccess.h 4 Feb 2004 18:24:55 -0000 1.13
+++ include/asm-parisc/uaccess.h 11 Sep 2004 16:26:04 -0000
@@ -54,16 +54,15 @@ extern int __put_user_bad(void);
/*
* The exception table contains two values: the first is an address
* for an instruction that is allowed to fault, and the second is
- * the number of bytes to skip if a fault occurs. We also support in
- * two bit flags: 0x2 tells the exception handler to clear register
- * r9 and 0x1 tells the exception handler to put -EFAULT in r8.
- * This allows us to handle the simple cases for put_user and
- * get_user without having to have .fixup sections.
+ * the address to the fixup routine. We also support two bit flags:
+ * 0x2 tells the exception handler to store the faulting address in
+ * r9 and 0x1 tells the exception handler to store the faulting
+ * insn in r8.
*/
struct exception_table_entry {
unsigned long insn; /* address of insn that is allowed to fault. */
- long skip; /* pcoq skip | r9 clear flag | r8 -EFAULT flag */
+ long fixup; /* fixup | r9 ior flag | r8 iir flag */
};
#define __get_user(x,ptr) \
@@ -94,43 +93,70 @@ struct exception_table_entry {
__gu_err; \
})
+#ifndef __LP64__
+#define FIXUP_BRANCH(lbl) \
+ "\tb " #lbl "\n"
+#else
+#define FIXUP_BRANCH(lbl) \
+ "\tldil L%%" #lbl ", %%r1\n" \
+ "\tldo R%%" #lbl "(%%r1), %%r1\n" \
+ "\tbv,n %%r0(%%r1)\n"
+#endif
+
+/* -14 is -EFAULT below */
#ifdef __LP64__
#define __get_kernel_asm(ldx,ptr) \
__asm__("\n1:\t" ldx "\t0(%2),%0\n" \
"2:\n" \
- "\t.section __ex_table,\"aw\"\n" \
- "\t.dword\t1b\n" \
- "\t.dword\t(2b-1b)+3\n" \
- "\t.previous" \
+ "\t.section .fixup,\"ax\"\n" \
+ "3:\tldi -14, %1\n" \
+ "\tcopy %%r0, %0\n" \
+ FIXUP_BRANCH(2b) \
+ "\t.previous" \
+ "\t.section __ex_table,\"aw\"\n" \
+ "\t.dword\t1b,3b\n" \
+ "\t.previous" \
: "=r"(__gu_val), "=r"(__gu_err) \
: "r"(ptr), "1"(__gu_err));
#define __get_user_asm(ldx,ptr) \
__asm__("\n1:\t" ldx "\t0(%%sr3,%2),%0\n" \
"2:\n" \
- "\t.section __ex_table,\"aw\"\n" \
- "\t.dword\t1b\n" \
- "\t.dword\t(2b-1b)+3\n" \
- "\t.previous" \
+ "\t.section .fixup,\"ax\"\n" \
+ "3:\tldi -14, %1\n" \
+ "\tcopy %%r0, %0\n" \
+ FIXUP_BRANCH(2b) \
+ "\t.previous" \
+ "\t.section __ex_table,\"aw\"\n" \
+ "\t.dword\t1b,3b\n" \
+ "\t.previous" \
: "=r"(__gu_val), "=r"(__gu_err) \
: "r"(ptr), "1"(__gu_err));
#else
#define __get_kernel_asm(ldx,ptr) \
__asm__("\n1:\t" ldx "\t0(%2),%0\n" \
"2:\n" \
- "\t.section __ex_table,\"aw\"\n" \
- "\t.word\t1b\n" \
- "\t.word\t(2b-1b)+3\n" \
- "\t.previous" \
+ "\t.section .fixup,\"ax\"\n" \
+ "3:\tldi -14, %1\n" \
+ "\tcopy %%r0, %0\n" \
+ FIXUP_BRANCH(2b) \
+ "\t.previous" \
+ "\t.section __ex_table,\"aw\"\n" \
+ "\t.word\t1b,3b\n" \
+ "\t.previous" \
: "=r"(__gu_val), "=r"(__gu_err) \
: "r"(ptr), "1"(__gu_err));
#define __get_user_asm(ldx,ptr) \
__asm__("\n1:\t" ldx "\t0(%%sr3,%2),%0\n" \
"2:\n" \
- "\t.section __ex_table,\"aw\"\n" \
- "\t.word\t1b\n" \
- "\t.word\t(2b-1b)+3\n" \
+ "\t.section .fixup,\"ax\"\n" \
+ "3:\tldi -14, %1\n" \
+ "\tcopy %%r0, %0\n" \
+ FIXUP_BRANCH(2b) \
+ "\t.previous" \
+ "\t.section __ex_table,\"aw\"\n" \
+ "\t.word\t1b,3b\n" \
"\t.previous" \
: "=r"(__gu_val), "=r"(__gu_err) \
: "r"(ptr), "1"(__gu_err));
@@ -168,15 +194,19 @@ struct exception_table_entry {
* gcc knows about, so there are no aliasing issues.
*/
+/* -14 is -EFAULT below */
#ifdef __LP64__
#define __put_kernel_asm(stx,x,ptr) \
__asm__ __volatile__ ( \
"\n1:\t" stx "\t%2,0(%1)\n" \
"2:\n" \
- "\t.section __ex_table,\"aw\"\n" \
- "\t.dword\t1b\n" \
- "\t.dword\t(2b-1b)+1\n" \
- "\t.previous" \
+ "\t.section .fixup,\"ax\"\n" \
+ "3:\tldi -14, %0\n" \
+ FIXUP_BRANCH(2b) \
+ "\t.previous" \
+ "\t.section __ex_table,\"aw\"\n" \
+ "\t.dword\t1b,3b\n" \
+ "\t.previous" \
: "=r"(__pu_err) \
: "r"(ptr), "r"(x), "0"(__pu_err))
@@ -184,9 +214,12 @@ struct exception_table_entry {
__asm__ __volatile__ ( \
"\n1:\t" stx "\t%2,0(%%sr3,%1)\n" \
"2:\n" \
- "\t.section __ex_table,\"aw\"\n" \
- "\t.dword\t1b\n" \
- "\t.dword\t(2b-1b)+1\n" \
+ "\t.section .fixup,\"ax\"\n" \
+ "3:\tldi -14, %0\n" \
+ FIXUP_BRANCH(2b) \
+ "\t.previous" \
+ "\t.section __ex_table,\"aw\"\n" \
+ "\t.dword\t1b,3b\n" \
"\t.previous" \
: "=r"(__pu_err) \
: "r"(ptr), "r"(x), "0"(__pu_err))
@@ -195,9 +228,12 @@ struct exception_table_entry {
__asm__ __volatile__ ( \
"\n1:\t" stx "\t%2,0(%1)\n" \
"2:\n" \
- "\t.section __ex_table,\"aw\"\n" \
- "\t.word\t1b\n" \
- "\t.word\t(2b-1b)+1\n" \
+ "\t.section .fixup,\"ax\"\n" \
+ "3:\tldi -14, %0\n" \
+ FIXUP_BRANCH(2b) \
+ "\t.previous" \
+ "\t.section __ex_table,\"aw\"\n" \
+ "\t.word\t1b,3b\n" \
"\t.previous" \
: "=r"(__pu_err) \
: "r"(ptr), "r"(x), "0"(__pu_err))
@@ -206,9 +242,12 @@ struct exception_table_entry {
__asm__ __volatile__ ( \
"\n1:\t" stx "\t%2,0(%%sr3,%1)\n" \
"2:\n" \
- "\t.section __ex_table,\"aw\"\n" \
- "\t.word\t1b\n" \
- "\t.word\t(2b-1b)+1\n" \
+ "\t.section .fixup,\"ax\"\n" \
+ "3:\tldi -14, %0\n" \
+ FIXUP_BRANCH(2b) \
+ "\t.previous" \
+ "\t.section __ex_table,\"aw\"\n" \
+ "\t.word\t1b,3b\n" \
"\t.previous" \
: "=r"(__pu_err) \
: "r"(ptr), "r"(x), "0"(__pu_err))
@@ -221,11 +260,14 @@ static inline void __put_kernel_asm64(u6
"\n1:\tstw %1,0(%0)\n"
"\n2:\tstw %2,4(%0)\n"
"3:\n"
+ "\t.section .fixup,\"ax\"\n"
+/* "4:\tldi -14, %0\n" */
+ "4:"
+ FIXUP_BRANCH(3b)
+ "\t.previous"
"\t.section __ex_table,\"aw\"\n"
- "\t.word\t1b\n"
- "\t.word\t(3b-1b)+1\n"
- "\t.word\t2b\n"
- "\t.word\t(3b-2b)+1\n"
+ "\t.word\t1b,4b\n"
+ "\t.word\t2b,4b\n"
"\t.previous"
: : "r"(ptr), "r"(hi), "r"(lo));
@@ -239,11 +281,14 @@ static inline void __put_user_asm64(u64
"\n1:\tstw %1,0(%%sr3,%0)\n"
"\n2:\tstw %2,4(%%sr3,%0)\n"
"3:\n"
+ "\t.section .fixup,\"ax\"\n"
+/* "4:\tldi -14, %0\n" */
+ "4:"
+ FIXUP_BRANCH(3b)
+ "\t.previous"
"\t.section __ex_table,\"aw\"\n"
- "\t.word\t1b\n"
- "\t.word\t(3b-1b)+1\n"
- "\t.word\t2b\n"
- "\t.word\t(3b-2b)+1\n"
+ "\t.word\t1b,4b\n"
+ "\t.word\t2b,4b\n"
"\t.previous"
: : "r"(ptr), "r"(hi), "r"(lo));
--
Randolph Chung
Debian GNU/Linux Developer, hppa/ia64 ports
http://www.tausq.org/
_______________________________________________
parisc-linux mailing list
parisc-linux@lists.parisc-linux.org
http://lists.parisc-linux.org/mailman/listinfo/parisc-linux
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [parisc-linux] [RFC] Revamp exception handling in the kernel
2004-09-11 16:53 [parisc-linux] [RFC] Revamp exception handling in the kernel Randolph Chung
@ 2004-09-11 22:49 ` John David Anglin
2004-09-12 13:10 ` Carlos O'Donell
2004-09-12 13:47 ` Carlos O'Donell
2004-09-13 23:37 ` Randolph Chung
2 siblings, 1 reply; 16+ messages in thread
From: John David Anglin @ 2004-09-11 22:49 UTC (permalink / raw)
To: randolph; +Cc: parisc-linux
> [1] The change to using absolute jumps is because gas doesn't want to
> let us take the difference of labels in two different sections (viz.
> .text vs .fixup). jejb and I are not able to come up with a case where
> using relative jumps is required.
Right. However, there is a way to do 32/64 bit pc-relative offsets.
The table entries need to look like "L$1+(.+8-L$0)-$PIC_pcrel$0".
GAS needs to be reasonably new to support this.
Dave
--
J. David Anglin dave.anglin@nrc-cnrc.gc.ca
National Research Council of Canada (613) 990-0752 (FAX: 952-6602)
_______________________________________________
parisc-linux mailing list
parisc-linux@lists.parisc-linux.org
http://lists.parisc-linux.org/mailman/listinfo/parisc-linux
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [parisc-linux] [RFC] Revamp exception handling in the kernel
2004-09-11 22:49 ` John David Anglin
@ 2004-09-12 13:10 ` Carlos O'Donell
0 siblings, 0 replies; 16+ messages in thread
From: Carlos O'Donell @ 2004-09-12 13:10 UTC (permalink / raw)
To: John David Anglin; +Cc: parisc-linux
On Sat, Sep 11, 2004 at 06:49:45PM -0400, John David Anglin wrote:
> > [1] The change to using absolute jumps is because gas doesn't want to
> > let us take the difference of labels in two different sections (viz.
> > .text vs .fixup). jejb and I are not able to come up with a case where
> > using relative jumps is required.
>
> Right. However, there is a way to do 32/64 bit pc-relative offsets.
> The table entries need to look like "L$1+(.+8-L$0)-$PIC_pcrel$0".
> GAS needs to be reasonably new to support this.
Interesting.
I thought I needed relative fixups, then I realized I was wrong.
I use exception fixups for LWS on the gateway page, but I can
just fudge the exception entries differently. No big problem
since I have to do a fixed relocation on them anyway.
c.
_______________________________________________
parisc-linux mailing list
parisc-linux@lists.parisc-linux.org
http://lists.parisc-linux.org/mailman/listinfo/parisc-linux
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [parisc-linux] [RFC] Revamp exception handling in the kernel
2004-09-11 16:53 [parisc-linux] [RFC] Revamp exception handling in the kernel Randolph Chung
2004-09-11 22:49 ` John David Anglin
@ 2004-09-12 13:47 ` Carlos O'Donell
2004-09-12 13:58 ` James Bottomley
2004-09-12 16:15 ` Randolph Chung
2004-09-13 23:37 ` Randolph Chung
2 siblings, 2 replies; 16+ messages in thread
From: Carlos O'Donell @ 2004-09-12 13:47 UTC (permalink / raw)
To: Randolph Chung, James Bottomley; +Cc: PARISC list
> The patch below, based on my discussions with jejb, changes this
> behaviour so that it more closely matches what happens on other
> architectures (but with a twist...): the exception table entries now
> contain an *absolute* address to branch to for the fixup [1]. The
> fixups are placed in a separate fixup section (this simplifies a bit of
> code in unaligned.c too). The fixup code loads up whatever values are
> required by the caller, and typically branches back to the original
> code at a correct location to continue.
I'm looking through the module loading code and worrying about how
absolute fixups works when a module needs a fixup?
> This frees up the bottom two bits for other purposes -- currently there
> is no way to pass the faulting address and instruction back to an
> exception table handler. The proposal is to reuse the bottom 2 bits to
> indicate whether the faulting address/insn should be passed back to the
> handler in r8/r9. (this will be used by the optimized pa copy routines,
> for example)
I think this is a brilliant proposal. I found the use of r8/r9 a bit
washy and rather useless in the current implementation.
> One downside of this approach is that the extra fixup sections take up
> more space, so the end kernel is bigger. In my test on 64-bit, the
> kernel size increases by ~2%.
What is that converted to bytes?
> The patch below has been tested against 2.6.8.1-pa11 on 64-bit-SMP, and
> compile tested on 32-bit-UP. I don't have a 32-bit machine to test on
> atm, so test reports are most welcome [2]. I've applied the manual stubs
> trick that jejb mentioned earlier, but only for 64-bit, since the 32-bit
> linker is able to generate those stubs automatically when needed.
>
> Comments?
How are we handling module fixups with absolute fixup addresses?
Is there ever a case where you want only the faulting instruction and
not the faulting address aswell? This might be a case for saving a flag,
if you are going to write to r9 you might aswell write two words,
anyway? The code has already locked r8/r9 into variables and gcc won't
do a better job for you.
0x2 = 1 then Write r8/r9 values (slow path)
0x2 = 0 then do nothing (fast path)
Then 0x1 is free to be used for something magical.
c.
_______________________________________________
parisc-linux mailing list
parisc-linux@lists.parisc-linux.org
http://lists.parisc-linux.org/mailman/listinfo/parisc-linux
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [parisc-linux] [RFC] Revamp exception handling in the kernel
2004-09-12 13:47 ` Carlos O'Donell
@ 2004-09-12 13:58 ` James Bottomley
2004-09-12 14:29 ` Carlos O'Donell
2004-09-12 16:15 ` Randolph Chung
1 sibling, 1 reply; 16+ messages in thread
From: James Bottomley @ 2004-09-12 13:58 UTC (permalink / raw)
To: Carlos O'Donell; +Cc: PARISC list
On Sun, 2004-09-12 at 09:47, Carlos O'Donell wrote:
> I'm looking through the module loading code and worrying about how
> absolute fixups works when a module needs a fixup?
It should work identically to non-module code ... what specifically is
worrying you?
> How are we handling module fixups with absolute fixup addresses?
The same way we do in the regular kernel ... jump to the absolute
address.
James
_______________________________________________
parisc-linux mailing list
parisc-linux@lists.parisc-linux.org
http://lists.parisc-linux.org/mailman/listinfo/parisc-linux
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [parisc-linux] [RFC] Revamp exception handling in the kernel
2004-09-12 13:58 ` James Bottomley
@ 2004-09-12 14:29 ` Carlos O'Donell
2004-09-12 15:03 ` James Bottomley
0 siblings, 1 reply; 16+ messages in thread
From: Carlos O'Donell @ 2004-09-12 14:29 UTC (permalink / raw)
To: James Bottomley; +Cc: PARISC list
> > I'm looking through the module loading code and worrying about how
> > absolute fixups works when a module needs a fixup?
>
> It should work identically to non-module code ... what specifically is
> worrying you?
Are relocations generated against the exception table entries?
> The same way we do in the regular kernel ... jump to the absolute
> address.
If relocations are generated against extable entries then all should be
okay. The address will be fixed by the loader and everything is fine.
That was my only worry, Randolph didn't seem to address testing a failed
copy_from_user through a module extable.
My other question about freeing a flag still stands though.
c.
_______________________________________________
parisc-linux mailing list
parisc-linux@lists.parisc-linux.org
http://lists.parisc-linux.org/mailman/listinfo/parisc-linux
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [parisc-linux] [RFC] Revamp exception handling in the kernel
2004-09-12 14:29 ` Carlos O'Donell
@ 2004-09-12 15:03 ` James Bottomley
0 siblings, 0 replies; 16+ messages in thread
From: James Bottomley @ 2004-09-12 15:03 UTC (permalink / raw)
To: Carlos O'Donell; +Cc: PARISC list
On Sun, 2004-09-12 at 10:29, Carlos O'Donell wrote:
> Are relocations generated against the exception table entries?
Yes. A module is just a normal .o file with a few extra sections. It
contains all the relocations a .o file usually contains.
> > The same way we do in the regular kernel ... jump to the absolute
> > address.
>
> If relocations are generated against extable entries then all should be
> okay. The address will be fixed by the loader and everything is fine.
>
> That was my only worry, Randolph didn't seem to address testing a failed
> copy_from_user through a module extable.
>
> My other question about freeing a flag still stands though.
I'll let Randolph answer that ... I find thinks like this are sticky;
once you touch them you can never get them off your hands...
James
_______________________________________________
parisc-linux mailing list
parisc-linux@lists.parisc-linux.org
http://lists.parisc-linux.org/mailman/listinfo/parisc-linux
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [parisc-linux] [RFC] Revamp exception handling in the kernel
2004-09-12 13:47 ` Carlos O'Donell
2004-09-12 13:58 ` James Bottomley
@ 2004-09-12 16:15 ` Randolph Chung
2004-09-12 17:54 ` Carlos O'Donell
1 sibling, 1 reply; 16+ messages in thread
From: Randolph Chung @ 2004-09-12 16:15 UTC (permalink / raw)
To: Carlos O'Donell; +Cc: James Bottomley, PARISC list
> > One downside of this approach is that the extra fixup sections take up
> > more space, so the end kernel is bigger. In my test on 64-bit, the
> > kernel size increases by ~2%.
>
> What is that converted to bytes?
about 100k for 64-bit. should be significantly less for 32-bit.
> Is there ever a case where you want only the faulting instruction and
> not the faulting address aswell? This might be a case for saving a flag,
> if you are going to write to r9 you might aswell write two words,
> anyway? The code has already locked r8/r9 into variables and gcc won't
> do a better job for you.
actually a nice effect of this patch is that you don't need to lock down
r8 and r9 anymore for the get_user/put_user cases. Potentially any
register can be used to store the error and result values.
i need to do some experiments to verify this, but after thinking
about it more last night, it seems to me that we don't even need to put
the isr/ior into registers in the fault handler. the fixup code could
potentially just look at current->thread.regs.isr/ior directly.
> 0x2 = 1 then Write r8/r9 values (slow path)
> 0x2 = 0 then do nothing (fast path)
>
> Then 0x1 is free to be used for something magical.
sure, that works too.
randolph
--
Randolph Chung
Debian GNU/Linux Developer, hppa/ia64 ports
http://www.tausq.org/
_______________________________________________
parisc-linux mailing list
parisc-linux@lists.parisc-linux.org
http://lists.parisc-linux.org/mailman/listinfo/parisc-linux
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [parisc-linux] [RFC] Revamp exception handling in the kernel
2004-09-12 16:15 ` Randolph Chung
@ 2004-09-12 17:54 ` Carlos O'Donell
2004-09-12 18:48 ` Randolph Chung
0 siblings, 1 reply; 16+ messages in thread
From: Carlos O'Donell @ 2004-09-12 17:54 UTC (permalink / raw)
To: Randolph Chung; +Cc: James Bottomley, PARISC list
> > What is that converted to bytes?
>
> about 100k for 64-bit. should be significantly less for 32-bit.
That's quite a bit, but it does make the infrastructure more flexible.
I don't think anyone is going to be building embedded PA systems, but
lets not bloat.
> > Is there ever a case where you want only the faulting instruction and
> > not the faulting address aswell? This might be a case for saving a flag,
> > if you are going to write to r9 you might aswell write two words,
> > anyway? The code has already locked r8/r9 into variables and gcc won't
> > do a better job for you.
>
> actually a nice effect of this patch is that you don't need to lock down
> r8 and r9 anymore for the get_user/put_user cases. Potentially any
> register can be used to store the error and result values.
I don't see how the fixup code knows which registers to use?
> i need to do some experiments to verify this, but after thinking
> about it more last night, it seems to me that we don't even need to put
> the isr/ior into registers in the fault handler. the fixup code could
> potentially just look at current->thread.regs.isr/ior directly.
Yes, that's very true, just fillin those values during the fixup phase.
Then you don't need to use r8/r9 and the flags just become "Yes I care,
please deposit the value" or "No I don't care."
> > 0x2 = 1 then Write r8/r9 values (slow path)
> > 0x2 = 0 then do nothing (fast path)
> >
> > Then 0x1 is free to be used for something magical.
>
> sure, that works too.
I'm not sure what we would use the flag for, but it's nice to have it
there. Perhaps we may in the future wish to have absolute and relative
fixups based on the flag? This would reduce the kernel size bloat and
produce faster code again. Technically only the pa_memcpy code is the
only one that would have to enable "absolute" fixups?
c.
_______________________________________________
parisc-linux mailing list
parisc-linux@lists.parisc-linux.org
http://lists.parisc-linux.org/mailman/listinfo/parisc-linux
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [parisc-linux] [RFC] Revamp exception handling in the kernel
2004-09-12 17:54 ` Carlos O'Donell
@ 2004-09-12 18:48 ` Randolph Chung
2004-09-12 19:19 ` Carlos O'Donell
0 siblings, 1 reply; 16+ messages in thread
From: Randolph Chung @ 2004-09-12 18:48 UTC (permalink / raw)
To: Carlos O'Donell; +Cc: James Bottomley, PARISC list
> That's quite a bit, but it does make the infrastructure more flexible.
> I don't think anyone is going to be building embedded PA systems, but
> lets not bloat.
yes, that's why i brought it up :)
> > actually a nice effect of this patch is that you don't need to lock down
> > r8 and r9 anymore for the get_user/put_user cases. Potentially any
> > register can be used to store the error and result values.
>
> I don't see how the fixup code knows which registers to use?
Consider:
#define __get_user_asm(ldx,ptr) \
__asm__("\n1:\t" ldx "\t0(%%sr3,%2),%0\n" \
"2:\n" \
"\t.section .fixup,\"ax\"\n" \
"3:\tldi -14, %1\n" \
"\tcopy %%r0, %0\n" \
FIXUP_BRANCH(2b) \
"\t.previous" \
"\t.section __ex_table,\"aw\"\n" \
"\t.word\t1b,3b\n" \
"\t.previous" \
: "=r"(__gu_val), "=r"(__gu_err) \
: "r"(ptr), "1"(__gu_err));
By the time the fixup is called, we are back into user context. the
ldi/copy will write into whatever registers store __gu_val, __gu_err,
and then branch back to "2:", so essentially this code is
self-contained. There is no real requirements that __gu_val/__gu_err be
in any special registers.
In the original code, we have to write to r8/r9 inside interruption
context, and have the values survive back to user context.
> > i need to do some experiments to verify this, but after thinking
> > about it more last night, it seems to me that we don't even need to put
> > the isr/ior into registers in the fault handler. the fixup code could
> > potentially just look at current->thread.regs.isr/ior directly.
>
> Yes, that's very true, just fillin those values during the fixup phase.
> Then you don't need to use r8/r9 and the flags just become "Yes I care,
> please deposit the value" or "No I don't care."
nono, you don't fill them up in the fixup phase.
when you have a fault, we already store the ior/isr into the pt_regs
structure. so as long as we are not clobbering those in the interruption
exit path, it will still be accessible in the fixup code.
> I'm not sure what we would use the flag for, but it's nice to have it
> there. Perhaps we may in the future wish to have absolute and relative
> fixups based on the flag? This would reduce the kernel size bloat and
> produce faster code again. Technically only the pa_memcpy code is the
> only one that would have to enable "absolute" fixups?
why do you think absolute fixups take more space? in fact, absolute
fixup is what might allow us to save space.
the bit that is taking up more space is that the logic that stores
-EFAULT/0 is now duplicated for each get_user/put_user call. For 64-bit
kernels, that's 5 insns per call. In the original implementation, this
logic is centralized in the fault handling code.
possibly, we can create a centralized fixup routine in
arch/parisc/lib/fixup.S that looks like:
.section .fixup, "ax"
fixup_load_skip_1:
ldi -14, %r8
copy %r0, %r9
mfctl %cr30, %r1
LDREG 0(%r1), %r1
LDREG TASK_PT_IOR(%r1), %r1
ldo 4(%r1), %r1
bv,n %r0(%r1)
and __get_user_asm() will become
#define __get_user_asm(ldx,ptr) \
__asm__("\n1:\t" ldx "\t0(%%sr3,%2),%0\n" \
"2:\n" \
"\t.section __ex_table,\"aw\"\n" \
"\t.word\t1b,fixup_load_skip_1\n" \
"\t.previous" \
: "=r"(__gu_val), "=r"(__gu_err) \
: "r"(ptr), "1"(__gu_err));
similarly we will have fixup_store_skip_1, and for 32-bit we also need
fixup_load_skip_2 and fixup_store_skip_2 for the 64-bit
get_user/put_user calls.
this reintroduces the requirement that __gu_val and __gu_err be in fixed
registers, but the fixup regions don't need to be duplicated, so the
kernel size should become smaller again.
thoughts?
randolph
--
Randolph Chung
Debian GNU/Linux Developer, hppa/ia64 ports
http://www.tausq.org/
_______________________________________________
parisc-linux mailing list
parisc-linux@lists.parisc-linux.org
http://lists.parisc-linux.org/mailman/listinfo/parisc-linux
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [parisc-linux] [RFC] Revamp exception handling in the kernel
2004-09-12 18:48 ` Randolph Chung
@ 2004-09-12 19:19 ` Carlos O'Donell
0 siblings, 0 replies; 16+ messages in thread
From: Carlos O'Donell @ 2004-09-12 19:19 UTC (permalink / raw)
To: Randolph Chung; +Cc: James Bottomley, PARISC list
Randolph,
> when you have a fault, we already store the ior/isr into the pt_regs
> structure. so as long as we are not clobbering those in the interruption
> exit path, it will still be accessible in the fixup code.
I worry that the fixup code may trigger another interruption and clobber
those values before it can read them? Any interruption will resave
ior/isr. Perhaps storing them into r8/r9 is still best.
> possibly, we can create a centralized fixup routine in
> arch/parisc/lib/fixup.S that looks like:
>
> .section .fixup, "ax"
> fixup_load_skip_1:
> ldi -14, %r8
> copy %r0, %r9
> mfctl %cr30, %r1
> LDREG 0(%r1), %r1
> LDREG TASK_PT_IOR(%r1), %r1
> ldo 4(%r1), %r1
> bv,n %r0(%r1)
>
> and __get_user_asm() will become
>
> #define __get_user_asm(ldx,ptr) \
> __asm__("\n1:\t" ldx "\t0(%%sr3,%2),%0\n" \
> "2:\n" \
> "\t.section __ex_table,\"aw\"\n" \
> "\t.word\t1b,fixup_load_skip_1\n" \
> "\t.previous" \
> : "=r"(__gu_val), "=r"(__gu_err) \
> : "r"(ptr), "1"(__gu_err));
>
> similarly we will have fixup_store_skip_1, and for 32-bit we also need
> fixup_load_skip_2 and fixup_store_skip_2 for the 64-bit
> get_user/put_user calls.
That would be a brilliant space saver. I take it back, I hand't thought
about interrupting to a generic fixup function for all the
__get_user_asm uses.
> this reintroduces the requirement that __gu_val and __gu_err be in fixed
> registers, but the fixup regions don't need to be duplicated, so the
> kernel size should become smaller again.
Implementation?
a. Single generic fixup for all the asm macros (reduce kernel size).
- Fixes previous quibble that absolute addresses made
the kernel bigger because asm macros had more insns.
b. Absoulte fixup addresses (allows fixup to be anywhere).
c. Use only one flag in the fixup address to indicate wether
r8/r9 should be written to with ior/iir or not.
Leaving a spare flag for future uses.
Pro:
o Kernel size is smaller.
- Bonus!
o fixup can be located almost anywhere (absolute address).
- Bonus!
o Custom code can examine r8/r9 to determine more accurately the
faulting situation.
- Bonus!
Con:
o Generic slow path is a couple more insns slower ;)
- Regression, no worries.
o Generic fixup always locks r8/r9 into gu_err and gu_val
- Same as always.
c.
_______________________________________________
parisc-linux mailing list
parisc-linux@lists.parisc-linux.org
http://lists.parisc-linux.org/mailman/listinfo/parisc-linux
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [parisc-linux] [RFC] Revamp exception handling in the kernel
2004-09-11 16:53 [parisc-linux] [RFC] Revamp exception handling in the kernel Randolph Chung
2004-09-11 22:49 ` John David Anglin
2004-09-12 13:47 ` Carlos O'Donell
@ 2004-09-13 23:37 ` Randolph Chung
2004-09-14 2:37 ` Randolph Chung
2 siblings, 1 reply; 16+ messages in thread
From: Randolph Chung @ 2004-09-13 23:37 UTC (permalink / raw)
To: PARISC list
Version 2 of the patch. Changes from the previous version:
- Uses centralized exception handling for get_user/put_user
- Uses per-cpu variables to store the fault ip, fault space and fault
address (not controlled by a flag)
- 64-bit get_user/put_user for 32-bit kernels is a bit broken in the old
code. this contains a fix for that as well.
Tested against 2.6.8.1-pa11 for 64-UP and 64-SMP
jejb asked me why we don't do the fixup in C code. It seems to me that
in order to do that, we will need to mark all the caller-saved registers
as clobbered by get_user/put_user. That may cause a large amount of
register spills across those calls, even for non-faulting cases.
But the alternative (as implemented below) is some rather nasty-looking
asm code in the fixup handler. A third alternative might be for the
fixup handler to create a stack frame and save/restore caller-saved
registers across a call to a C-code handler. seems like a lot of
work....
Thoughts?
randolph
Index: arch/parisc/kernel/asm-offsets.c
===================================================================
RCS file: /var/cvs/linux-2.6/arch/parisc/kernel/asm-offsets.c,v
retrieving revision 1.9
diff -u -p -r1.9 asm-offsets.c
--- arch/parisc/kernel/asm-offsets.c 8 May 2004 14:12:45 -0000 1.9
+++ arch/parisc/kernel/asm-offsets.c 13 Sep 2004 23:31:46 -0000
@@ -38,6 +38,7 @@
#include <asm/processor.h>
#include <asm/hardirq.h>
#include <asm/pdc.h>
+#include <asm/uaccess.h>
#define DEFINE(sym, val) \
asm volatile("\n->" #sym " %0 " #val : : "i" (val))
@@ -291,5 +292,8 @@ int main(void)
DEFINE(ASM_PT_INITIAL, PT_INITIAL);
DEFINE(ASM_PAGE_SIZE, PAGE_SIZE);
BLANK();
+ DEFINE(EXCDATA_IP, offsetof(struct exception_data, fault_ip));
+ DEFINE(EXCDATA_SPACE, offsetof(struct exception_data, fault_space));
+ DEFINE(EXCDATA_ADDR, offsetof(struct exception_data, fault_addr));
return 0;
}
Index: arch/parisc/kernel/syscall.S
===================================================================
RCS file: /var/cvs/linux-2.6/arch/parisc/kernel/syscall.S,v
retrieving revision 1.14
diff -u -p -r1.14 syscall.S
--- arch/parisc/kernel/syscall.S 10 Sep 2004 14:52:01 -0000 1.14
+++ arch/parisc/kernel/syscall.S 13 Sep 2004 23:31:46 -0000
@@ -29,6 +29,19 @@
#else
.level 1.1
#endif
+
+#ifndef __LP64__
+ .macro fixup_branch,lbl
+ b \lbl
+ .endm
+#else
+ .macro fixup_branch,lbl
+ ldil L%\lbl, %r1
+ ldo R%\lbl(%r1), %r1
+ bv,n %r0(%r1)
+ .endm
+#endif
+
.text
.import syscall_exit,code
@@ -575,10 +588,8 @@ cas_action:
/* Return to userspace, set no error */
b lws_exit
copy %r0, %r21
- nop /* Add some visual space in objdump */
- nop
- nop
- nop
+
+ .section .fixup,"ax"
3:
/* Error occured on load or store */
#ifdef CONFIG_SMP
@@ -588,12 +599,13 @@ cas_action:
stw %r0, 4(%sr2,%r20)
# endif
#endif
- b lws_exit
+ fixup_branch lws_exit
ldo -EFAULT(%r0),%r21 /* set errno */
nop
nop
nop
nop
+ .previous
/* Two exception table entries, one for the load,
the other for the store. Either return -EFAULT */
@@ -601,10 +613,10 @@ cas_action:
#ifdef __LP64__
/* Pad the address calculation */
.word 0,(2b - linux_gateway_page)
- .dword (3b - 2b)
+ .dword 3b
#else
.word 2b - linux_gateway_page
- .word (3b - 2b)
+ .word 3b
#endif
.previous
@@ -612,10 +624,10 @@ cas_action:
#ifdef __LP64__
/* Pad the address calculation */
.word 0,(1b - linux_gateway_page)
- .dword (3b - 1b)
+ .dword 3b
#else
.word 1b - linux_gateway_page
- .word (3b - 1b)
+ .word 3b
#endif
.previous
Index: arch/parisc/kernel/unaligned.c
===================================================================
RCS file: /var/cvs/linux-2.6/arch/parisc/kernel/unaligned.c,v
retrieving revision 1.8
diff -u -p -r1.8 unaligned.c
--- arch/parisc/kernel/unaligned.c 21 Aug 2004 06:19:33 -0000 1.8
+++ arch/parisc/kernel/unaligned.c 13 Sep 2004 23:31:46 -0000
@@ -23,6 +23,7 @@
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <asm/uaccess.h>
/* #define DEBUG_UNALIGNED 1 */
@@ -34,8 +35,14 @@
#ifdef __LP64__
#define RFMT "%016lx"
+#define FIXUP_BRANCH(lbl) \
+ "\tb " #lbl "\n"
#else
#define RFMT "%08lx"
+#define FIXUP_BRANCH(lbl) \
+ "\tldil L%%" #lbl ", %%r1\n" \
+ "\tldo R%%" #lbl "(%%r1), %%r1\n" \
+ "\tbv,n %%r0(%%r1)\n"
#endif
/* 1111 1100 0000 0000 0001 0011 1100 0000 */
@@ -134,15 +141,19 @@ static int emulate_ldh(struct pt_regs *r
"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)
@@ -175,15 +186,19 @@ static int emulate_ldw(struct pt_regs *r
" 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)
@@ -222,15 +237,19 @@ static int emulate_ldd(struct pt_regs *r
" 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)
@@ -250,17 +269,20 @@ static int emulate_ldd(struct pt_regs *r
" 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"
#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"
+" .dword 1b,5b\n"
+" .dword 2b,5b\n"
+" .dword 3b,5b\n"
+#else
+" .word 1b,5b\n"
+" .word 2b,5b\n"
+" .word 3b,5b\n"
#endif
" .previous\n"
: "=r" (valh), "=r" (vall), "=r" (ret)
@@ -296,15 +318,19 @@ static int emulate_sth(struct pt_regs *r
" 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)
@@ -346,15 +372,19 @@ static int emulate_stw(struct pt_regs *r
" 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)
@@ -399,19 +429,23 @@ static int emulate_std(struct pt_regs *r
" 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"
-#else
-" .word 1b,(5b-1b)\n"
-" .word 2b,(5b-2b)\n"
-" .word 3b,(5b-3b)\n"
-" .word 4b,(5b-4b)\n"
+" .dword 1b,6b\n"
+" .dword 2b,6b\n"
+" .dword 3b,6b\n"
+" .dword 4b,6b\n"
+#else
+" .word 1b,6b\n"
+" .word 2b,6b\n"
+" .word 3b,6b\n"
+" .word 4b,6b\n"
#endif
" .previous\n"
: "=r" (ret)
@@ -438,21 +472,25 @@ static int emulate_std(struct pt_regs *r
"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"
-#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"
+" .dword 1b,7b\n"
+" .dword 2b,7b\n"
+" .dword 3b,7b\n"
+" .dword 4b,7b\n"
+" .dword 5b,7b\n"
+#else
+" .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)
Index: arch/parisc/lib/Makefile
===================================================================
RCS file: /var/cvs/linux-2.6/arch/parisc/lib/Makefile,v
retrieving revision 1.2
diff -u -p -r1.2 Makefile
--- arch/parisc/lib/Makefile 1 Jul 2004 18:30:36 -0000 1.2
+++ arch/parisc/lib/Makefile 13 Sep 2004 23:31:46 -0000
@@ -2,6 +2,6 @@
# Makefile for parisc-specific library files
#
-lib-y := lusercopy.o bitops.o checksum.o io.o memset.o
+lib-y := lusercopy.o bitops.o checksum.o io.o memset.o fixup.o
lib-$(CONFIG_SMP) += debuglocks.o
Index: arch/parisc/lib/fixup.S
===================================================================
RCS file: arch/parisc/lib/fixup.S
diff -N arch/parisc/lib/fixup.S
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ arch/parisc/lib/fixup.S 13 Sep 2004 23:31:46 -0000
@@ -0,0 +1,84 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Copyright (C) 2004 Randolph Chung <tausq@debian.org>
+ *
+ * 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/config.h>
+#include <asm/offsets.h>
+#include <asm/assembly.h>
+#include <asm/errno.h>
+
+#ifdef CONFIG_SMP
+ .macro get_fault_ip t1 t2
+ addil LT'__per_cpu_offset,\t1
+ LDREG RT'__per_cpu_offset(\t1),\t1
+ /* t2 = smp_processor_id() */
+ mfctl 30,\t2
+ ldw TI_CPU(\t2),\t2
+#ifdef __LP64__
+ extrd,u \t2,63,32,\t2
+#endif
+ /* t2 = &__per_cpu_offset[smp_processor_id()]; */
+ LDREG,s \t2(\t1),\t2
+ addil LT'per_cpu__exception_data,\t1
+ LDREG RT'per_cpu__exception_data(\t1),\t1
+ /* t1 = &__get_cpu_var(exception_data) */
+ add,l \t1,\t2,\t1
+ /* t1 = t1->fault_ip */
+ LDREG EXCDATA_IP(\t1), \t1
+ .endm
+#else
+ .macro get_fault_ip t1 t2
+ /* t1 = &__get_cpu_var(exception_data) */
+ addil LT'per_cpu__exception_data,\t1
+ LDREG RT'per_cpu__exception_data(\t1),\t2
+ /* t1 = t1->fault_ip */
+ LDREG EXCDATA_IP(\t2), \t1
+ .endm
+#endif
+
+ .text
+
+ .export fixup_get_user_skip_1
+fixup_get_user_skip_1:
+ get_fault_ip %r1,%r8
+ ldo 4(%r1), %r1
+ ldi -EFAULT, %r8
+ bv %r0(%r1)
+ copy %r0, %r9
+
+ .export fixup_get_user_skip_2
+fixup_get_user_skip_2:
+ get_fault_ip %r1,%r8
+ ldo 8(%r1), %r1
+ ldi -EFAULT, %r8
+ bv %r0(%r1)
+ copy %r0, %r9
+
+ .export fixup_put_user_skip_1
+fixup_put_user_skip_1:
+ get_fault_ip %r1,%r8
+ ldo 4(%r1), %r1
+ bv %r0(%r1)
+ ldi -EFAULT, %r8
+
+ .export fixup_put_user_skip_2
+fixup_put_user_skip_2:
+ get_fault_ip %r1,%r8
+ ldo 8(%r1), %r1
+ bv %r0(%r1)
+ ldi -EFAULT, %r8
Index: arch/parisc/lib/lusercopy.S
===================================================================
RCS file: /var/cvs/linux-2.6/arch/parisc/lib/lusercopy.S,v
retrieving revision 1.3
diff -u -p -r1.3 lusercopy.S
--- arch/parisc/lib/lusercopy.S 17 Jan 2004 06:39:24 -0000 1.3
+++ arch/parisc/lib/lusercopy.S 13 Sep 2004 23:31:46 -0000
@@ -53,6 +53,18 @@
mtsp %r1,%sr1
.endm
+#ifndef __LP64__
+ .macro fixup_branch lbl
+ b \lbl
+ .endm
+#else
+ .macro fixup_branch lbl
+ ldil L%\lbl, %r1
+ ldo R%\lbl(%r1), %r1
+ bv,n %r0(%r1)
+ .endm
+#endif
+
/*
* unsigned long
* lcopy_to_user(void *to, const void *from, unsigned long n)
@@ -77,14 +89,16 @@ $lctu_done:
copy %r24,%r28
.exit
-2: b $lctu_done
+ .section .fixup,"ax"
+2: fixup_branch $lctu_done
ldo 1(%r24),%r24
+ .previous
- .section __ex_table,"a"
+ .section __ex_table,"aw"
#ifdef __LP64__
- .dword 1b,(2b-1b)
+ .dword 1b,2b
#else
- .word 1b,(2b-1b)
+ .word 1b,2b
#endif
.previous
@@ -118,18 +132,20 @@ $lcfu_done:
copy %r24,%r28
.exit
+ .section .fixup,"ax"
2: copy %r24,%r23
$lcfu_zero_loop:
addib,<> -1,%r23,$lcfu_zero_loop
stbs,ma %r0,1(%r26)
- b $lcfu_done
+ fixup_branch $lcfu_done
nop
+ .previous
- .section __ex_table,"a"
+ .section __ex_table,"aw"
#ifdef __LP64__
- .dword 1b,(2b-1b)
+ .dword 1b,2b
#else
- .word 1b,(2b-1b)
+ .word 1b,2b
#endif
.previous
@@ -159,14 +175,16 @@ $lciu_done:
copy %r24,%r28
.exit
-2: b $lciu_done
+ .section .fixup,"ax"
+2: fixup_branch $lciu_done
ldo 1(%r24),%r24
+ .previous
- .section __ex_table,"a"
+ .section __ex_table,"aw"
#ifdef __LP64__
- .dword 1b,(2b-1b)
+ .dword 1b,2b
#else
- .word 1b,(2b-1b)
+ .word 1b,2b
#endif
.previous
@@ -201,16 +219,18 @@ $lsfu_exit:
nop
.exit
-3: b $lsfu_exit
+ .section .fixup,"ax"
+3: fixup_branch $lsfu_exit
ldi -EFAULT,%r28
+ .previous
- .section __ex_table,"a"
+ .section __ex_table,"aw"
#ifdef __LP64__
- .dword 1b,(3b-1b)
- .dword 2b,(3b-2b)
+ .dword 1b,3b
+ .dword 2b,3b
#else
- .word 1b,(3b-1b)
- .word 2b,(3b-2b)
+ .word 1b,3b
+ .word 2b,3b
#endif
.previous
@@ -239,14 +259,16 @@ $lclu_done:
copy %r25,%r28
.exit
-2: b $lclu_done
+ .section .fixup,"ax"
+2: fixup_branch $lclu_done
ldo 1(%r25),%r25
+ .previous
- .section __ex_table,"a"
+ .section __ex_table,"aw"
#ifdef __LP64__
- .dword 1b,(2b-1b)
+ .dword 1b,2b
#else
- .word 1b,(2b-1b)
+ .word 1b,2b
#endif
.previous
@@ -282,16 +304,18 @@ $lslen_nzero:
b $lslen_done
ldo 1(%r26),%r26 /* special case for N == 0 */
-3: b $lslen_done
+ .section .fixup,"ax"
+3: fixup_branch $lslen_done
copy %r24,%r26 /* reset r26 so 0 is returned on fault */
+ .previous
- .section __ex_table,"a"
+ .section __ex_table,"aw"
#ifdef __LP64__
- .dword 1b,(3b-1b)
- .dword 2b,(3b-2b)
+ .dword 1b,3b
+ .dword 2b,3b
#else
- .word 1b,(3b-1b)
- .word 2b,(3b-2b)
+ .word 1b,3b
+ .word 2b,3b
#endif
.previous
Index: arch/parisc/mm/fault.c
===================================================================
RCS file: /var/cvs/linux-2.6/arch/parisc/mm/fault.c,v
retrieving revision 1.1
diff -u -p -r1.1 fault.c
--- arch/parisc/mm/fault.c 29 Jul 2003 17:00:42 -0000 1.1
+++ arch/parisc/mm/fault.c 13 Sep 2004 23:31:46 -0000
@@ -36,6 +36,9 @@
#define BITSSET 0x1c0 /* for identifying LDCW */
+
+DEFINE_PER_CPU(struct exception_data, exception_data);
+
/*
* parisc_acctyp(unsigned int inst) --
* Given a PA-RISC memory access instruction, determine if the
@@ -234,13 +237,16 @@ no_context:
fix = search_exception_tables(regs->iaoq[0]);
if (fix) {
+ struct exception_data *d;
+
+printk("applying fixup for 0x%lx, fixup at 0x%lx\n", regs->iaoq[0], fix->fixup & ~3);
- if (fix->skip & 1)
- regs->gr[8] = -EFAULT;
- if (fix->skip & 2)
- regs->gr[9] = 0;
+ d = &__get_cpu_var(exception_data);
+ d->fault_ip = regs->iaoq[0];
+ d->fault_space = regs->isr;
+ d->fault_addr = regs->ior;
- regs->iaoq[0] += ((fix->skip) & ~3);
+ regs->iaoq[0] = ((fix->fixup) & ~3);
/*
* NOTE: In some cases the faulting instruction
Index: include/asm-parisc/uaccess.h
===================================================================
RCS file: /var/cvs/linux-2.6/include/asm-parisc/uaccess.h,v
retrieving revision 1.13
diff -u -p -r1.13 uaccess.h
--- include/asm-parisc/uaccess.h 4 Feb 2004 18:24:55 -0000 1.13
+++ include/asm-parisc/uaccess.h 13 Sep 2004 23:31:47 -0000
@@ -54,16 +54,21 @@ extern int __put_user_bad(void);
/*
* The exception table contains two values: the first is an address
* for an instruction that is allowed to fault, and the second is
- * the number of bytes to skip if a fault occurs. We also support in
- * two bit flags: 0x2 tells the exception handler to clear register
- * r9 and 0x1 tells the exception handler to put -EFAULT in r8.
- * This allows us to handle the simple cases for put_user and
- * get_user without having to have .fixup sections.
+ * the address to the fixup routine. We also support two bit flags:
+ * 0x2 tells the exception handler to store the faulting address in
+ * r9 and 0x1 tells the exception handler to store the faulting
+ * insn in r8.
*/
struct exception_table_entry {
unsigned long insn; /* address of insn that is allowed to fault. */
- long skip; /* pcoq skip | r9 clear flag | r8 -EFAULT flag */
+ long fixup; /* fixup | r9 ior flag | r8 iir flag */
+};
+
+struct exception_data {
+ unsigned long fault_ip;
+ unsigned long fault_space;
+ unsigned long fault_addr;
};
#define __get_user(x,ptr) \
@@ -97,40 +102,32 @@ struct exception_table_entry {
#ifdef __LP64__
#define __get_kernel_asm(ldx,ptr) \
__asm__("\n1:\t" ldx "\t0(%2),%0\n" \
- "2:\n" \
- "\t.section __ex_table,\"aw\"\n" \
- "\t.dword\t1b\n" \
- "\t.dword\t(2b-1b)+3\n" \
- "\t.previous" \
+ "\t.section __ex_table,\"aw\"\n" \
+ "\t.dword\t1b,fixup_get_user_skip_1\n" \
+ "\t.previous" \
: "=r"(__gu_val), "=r"(__gu_err) \
: "r"(ptr), "1"(__gu_err));
#define __get_user_asm(ldx,ptr) \
__asm__("\n1:\t" ldx "\t0(%%sr3,%2),%0\n" \
- "2:\n" \
- "\t.section __ex_table,\"aw\"\n" \
- "\t.dword\t1b\n" \
- "\t.dword\t(2b-1b)+3\n" \
- "\t.previous" \
+ "\t.section __ex_table,\"aw\"\n" \
+ "\t.dword\t1b,fixup_get_user_skip_1\n" \
+ "\t.previous" \
: "=r"(__gu_val), "=r"(__gu_err) \
: "r"(ptr), "1"(__gu_err));
#else
#define __get_kernel_asm(ldx,ptr) \
__asm__("\n1:\t" ldx "\t0(%2),%0\n" \
- "2:\n" \
- "\t.section __ex_table,\"aw\"\n" \
- "\t.word\t1b\n" \
- "\t.word\t(2b-1b)+3\n" \
- "\t.previous" \
+ "\t.section __ex_table,\"aw\"\n" \
+ "\t.word\t1b,fixup_get_user_skip_1\n" \
+ "\t.previous" \
: "=r"(__gu_val), "=r"(__gu_err) \
: "r"(ptr), "1"(__gu_err));
#define __get_user_asm(ldx,ptr) \
__asm__("\n1:\t" ldx "\t0(%%sr3,%2),%0\n" \
- "2:\n" \
- "\t.section __ex_table,\"aw\"\n" \
- "\t.word\t1b\n" \
- "\t.word\t(2b-1b)+3\n" \
+ "\t.section __ex_table,\"aw\"\n" \
+ "\t.word\t1b,fixup_get_user_skip_1\n" \
"\t.previous" \
: "=r"(__gu_val), "=r"(__gu_err) \
: "r"(ptr), "1"(__gu_err));
@@ -138,7 +135,7 @@ struct exception_table_entry {
#define __put_user(x,ptr) \
({ \
- register long __pu_err __asm__ ("r8") = 0; \
+ register long __pu_err __asm__ ("r8") = 0; \
\
if (segment_eq(get_fs(),KERNEL_DS)) { \
switch (sizeof(*(ptr))) { \
@@ -172,21 +169,17 @@ struct exception_table_entry {
#define __put_kernel_asm(stx,x,ptr) \
__asm__ __volatile__ ( \
"\n1:\t" stx "\t%2,0(%1)\n" \
- "2:\n" \
- "\t.section __ex_table,\"aw\"\n" \
- "\t.dword\t1b\n" \
- "\t.dword\t(2b-1b)+1\n" \
- "\t.previous" \
+ "\t.section __ex_table,\"aw\"\n" \
+ "\t.dword\t1b,fixup_put_user_skip_1\n" \
+ "\t.previous" \
: "=r"(__pu_err) \
: "r"(ptr), "r"(x), "0"(__pu_err))
#define __put_user_asm(stx,x,ptr) \
__asm__ __volatile__ ( \
"\n1:\t" stx "\t%2,0(%%sr3,%1)\n" \
- "2:\n" \
- "\t.section __ex_table,\"aw\"\n" \
- "\t.dword\t1b\n" \
- "\t.dword\t(2b-1b)+1\n" \
+ "\t.section __ex_table,\"aw\"\n" \
+ "\t.dword\t1b,fixup_put_user_skip_1\n" \
"\t.previous" \
: "=r"(__pu_err) \
: "r"(ptr), "r"(x), "0"(__pu_err))
@@ -194,10 +187,8 @@ struct exception_table_entry {
#define __put_kernel_asm(stx,x,ptr) \
__asm__ __volatile__ ( \
"\n1:\t" stx "\t%2,0(%1)\n" \
- "2:\n" \
- "\t.section __ex_table,\"aw\"\n" \
- "\t.word\t1b\n" \
- "\t.word\t(2b-1b)+1\n" \
+ "\t.section __ex_table,\"aw\"\n" \
+ "\t.word\t1b,fixup_put_user_skip_1\n" \
"\t.previous" \
: "=r"(__pu_err) \
: "r"(ptr), "r"(x), "0"(__pu_err))
@@ -205,49 +196,41 @@ struct exception_table_entry {
#define __put_user_asm(stx,x,ptr) \
__asm__ __volatile__ ( \
"\n1:\t" stx "\t%2,0(%%sr3,%1)\n" \
- "2:\n" \
- "\t.section __ex_table,\"aw\"\n" \
- "\t.word\t1b\n" \
- "\t.word\t(2b-1b)+1\n" \
+ "\t.section __ex_table,\"aw\"\n" \
+ "\t.word\t1b,fixup_put_user_skip_1\n" \
"\t.previous" \
: "=r"(__pu_err) \
: "r"(ptr), "r"(x), "0"(__pu_err))
-static inline void __put_kernel_asm64(u64 x, void *ptr)
-{
- u32 hi = x>>32;
- u32 lo = x&0xffffffff;
- __asm__ __volatile__ (
- "\n1:\tstw %1,0(%0)\n"
- "\n2:\tstw %2,4(%0)\n"
- "3:\n"
- "\t.section __ex_table,\"aw\"\n"
- "\t.word\t1b\n"
- "\t.word\t(3b-1b)+1\n"
- "\t.word\t2b\n"
- "\t.word\t(3b-2b)+1\n"
- "\t.previous"
- : : "r"(ptr), "r"(hi), "r"(lo));
-
-}
-
-static inline void __put_user_asm64(u64 x, void *ptr)
-{
- u32 hi = x>>32;
- u32 lo = x&0xffffffff;
- __asm__ __volatile__ (
- "\n1:\tstw %1,0(%%sr3,%0)\n"
- "\n2:\tstw %2,4(%%sr3,%0)\n"
- "3:\n"
- "\t.section __ex_table,\"aw\"\n"
- "\t.word\t1b\n"
- "\t.word\t(3b-1b)+1\n"
- "\t.word\t2b\n"
- "\t.word\t(3b-2b)+1\n"
- "\t.previous"
- : : "r"(ptr), "r"(hi), "r"(lo));
+#define __put_kernel_asm64(_x,ptr) do { \
+ u64 x = (u64)_x; \
+ u32 hi = x>>32; \
+ u32 lo = x&0xffffffff; \
+ __asm__ __volatile__ ( \
+ "\n1:\tstw %2,0(%1)\n" \
+ "\n2:\tstw %3,4(%1)\n" \
+ "\t.section __ex_table,\"aw\"\n" \
+ "\t.word\t1b,fixup_put_user_skip_2\n" \
+ "\t.word\t2b,fixup_put_user_skip_1\n" \
+ "\t.previous" \
+ : "=r"(__pu_err) \
+ : "r"(ptr), "r"(hi), "r"(lo), "0"(__pu_err)); \
+} while (0)
-}
+#define __put_user_asm64(_x,ptr) do { \
+ u64 x = (u64)_x; \
+ u32 hi = x>>32; \
+ u32 lo = x&0xffffffff; \
+ __asm__ __volatile__ ( \
+ "\n1:\tstw %2,0(%%sr3,%1)\n" \
+ "\n2:\tstw %3,4(%%sr3,%1)\n" \
+ "\t.section __ex_table,\"aw\"\n" \
+ "\t.word\t1b,fixup_get_user_skip_2\n" \
+ "\t.word\t2b,fixup_get_user_skip_1\n" \
+ "\t.previous" \
+ : "=r"(__pu_err) \
+ : "r"(ptr), "r"(hi), "r"(lo), "0"(__pu_err)); \
+} while (0)
#endif /* !__LP64__ */
_______________________________________________
parisc-linux mailing list
parisc-linux@lists.parisc-linux.org
http://lists.parisc-linux.org/mailman/listinfo/parisc-linux
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [parisc-linux] [RFC] Revamp exception handling in the kernel
2004-09-13 23:37 ` Randolph Chung
@ 2004-09-14 2:37 ` Randolph Chung
2004-09-14 18:52 ` Joel Soete
0 siblings, 1 reply; 16+ messages in thread
From: Randolph Chung @ 2004-09-14 2:37 UTC (permalink / raw)
To: PARISC list
Version 2a of the patch. Changes from the previous version:
- Fixed the comment in uaccess.h, added some more comments to fixup.S
- Added missing r1 clobbers
- addil/ldd should be relative to r27, not r1
i found out this is a somewhat effective way of testing this patch:
- run "make vmlinux" (or make -j4 vmlinux) in one window
- run "while true; do ./wtest; sleep 30; done" in another window
wtest is compiled from:
-------------------8< cut here 8<--------------------
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
int main(int argc, char **argv)
{
char *buf = (char *)1;
int ret;
ret = write(fileno(stdout), buf, 10);
printf("write returned ret = %d, errno = %d\n", ret, errno);
return 0;
}
-------------------8< cut here 8<--------------------
patch:
Index: arch/parisc/kernel/asm-offsets.c
===================================================================
RCS file: /var/cvs/linux-2.6/arch/parisc/kernel/asm-offsets.c,v
retrieving revision 1.9
diff -u -p -r1.9 asm-offsets.c
--- arch/parisc/kernel/asm-offsets.c 8 May 2004 14:12:45 -0000 1.9
+++ arch/parisc/kernel/asm-offsets.c 14 Sep 2004 02:34:06 -0000
@@ -38,6 +38,7 @@
#include <asm/processor.h>
#include <asm/hardirq.h>
#include <asm/pdc.h>
+#include <asm/uaccess.h>
#define DEFINE(sym, val) \
asm volatile("\n->" #sym " %0 " #val : : "i" (val))
@@ -291,5 +292,8 @@ int main(void)
DEFINE(ASM_PT_INITIAL, PT_INITIAL);
DEFINE(ASM_PAGE_SIZE, PAGE_SIZE);
BLANK();
+ DEFINE(EXCDATA_IP, offsetof(struct exception_data, fault_ip));
+ DEFINE(EXCDATA_SPACE, offsetof(struct exception_data, fault_space));
+ DEFINE(EXCDATA_ADDR, offsetof(struct exception_data, fault_addr));
return 0;
}
Index: arch/parisc/kernel/syscall.S
===================================================================
RCS file: /var/cvs/linux-2.6/arch/parisc/kernel/syscall.S,v
retrieving revision 1.14
diff -u -p -r1.14 syscall.S
--- arch/parisc/kernel/syscall.S 10 Sep 2004 14:52:01 -0000 1.14
+++ arch/parisc/kernel/syscall.S 14 Sep 2004 02:34:06 -0000
@@ -29,6 +29,19 @@
#else
.level 1.1
#endif
+
+#ifndef __LP64__
+ .macro fixup_branch,lbl
+ b \lbl
+ .endm
+#else
+ .macro fixup_branch,lbl
+ ldil L%\lbl, %r1
+ ldo R%\lbl(%r1), %r1
+ bv,n %r0(%r1)
+ .endm
+#endif
+
.text
.import syscall_exit,code
@@ -575,10 +588,8 @@ cas_action:
/* Return to userspace, set no error */
b lws_exit
copy %r0, %r21
- nop /* Add some visual space in objdump */
- nop
- nop
- nop
+
+ .section .fixup,"ax"
3:
/* Error occured on load or store */
#ifdef CONFIG_SMP
@@ -588,12 +599,13 @@ cas_action:
stw %r0, 4(%sr2,%r20)
# endif
#endif
- b lws_exit
+ fixup_branch lws_exit
ldo -EFAULT(%r0),%r21 /* set errno */
nop
nop
nop
nop
+ .previous
/* Two exception table entries, one for the load,
the other for the store. Either return -EFAULT */
@@ -601,10 +613,10 @@ cas_action:
#ifdef __LP64__
/* Pad the address calculation */
.word 0,(2b - linux_gateway_page)
- .dword (3b - 2b)
+ .dword 3b
#else
.word 2b - linux_gateway_page
- .word (3b - 2b)
+ .word 3b
#endif
.previous
@@ -612,10 +624,10 @@ cas_action:
#ifdef __LP64__
/* Pad the address calculation */
.word 0,(1b - linux_gateway_page)
- .dword (3b - 1b)
+ .dword 3b
#else
.word 1b - linux_gateway_page
- .word (3b - 1b)
+ .word 3b
#endif
.previous
Index: arch/parisc/kernel/unaligned.c
===================================================================
RCS file: /var/cvs/linux-2.6/arch/parisc/kernel/unaligned.c,v
retrieving revision 1.8
diff -u -p -r1.8 unaligned.c
--- arch/parisc/kernel/unaligned.c 21 Aug 2004 06:19:33 -0000 1.8
+++ arch/parisc/kernel/unaligned.c 14 Sep 2004 02:34:06 -0000
@@ -23,6 +23,7 @@
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <asm/uaccess.h>
/* #define DEBUG_UNALIGNED 1 */
@@ -34,8 +35,14 @@
#ifdef __LP64__
#define RFMT "%016lx"
+#define FIXUP_BRANCH(lbl) \
+ "\tb " #lbl "\n"
#else
#define RFMT "%08lx"
+#define FIXUP_BRANCH(lbl) \
+ "\tldil L%%" #lbl ", %%r1\n" \
+ "\tldo R%%" #lbl "(%%r1), %%r1\n" \
+ "\tbv,n %%r0(%%r1)\n"
#endif
/* 1111 1100 0000 0000 0001 0011 1100 0000 */
@@ -134,15 +141,19 @@ static int emulate_ldh(struct pt_regs *r
"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)
@@ -175,15 +186,19 @@ static int emulate_ldw(struct pt_regs *r
" 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)
@@ -222,15 +237,19 @@ static int emulate_ldd(struct pt_regs *r
" 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)
@@ -250,17 +269,20 @@ static int emulate_ldd(struct pt_regs *r
" 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"
#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"
+" .dword 1b,5b\n"
+" .dword 2b,5b\n"
+" .dword 3b,5b\n"
+#else
+" .word 1b,5b\n"
+" .word 2b,5b\n"
+" .word 3b,5b\n"
#endif
" .previous\n"
: "=r" (valh), "=r" (vall), "=r" (ret)
@@ -296,15 +318,19 @@ static int emulate_sth(struct pt_regs *r
" 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)
@@ -346,15 +372,19 @@ static int emulate_stw(struct pt_regs *r
" 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)
@@ -399,19 +429,23 @@ static int emulate_std(struct pt_regs *r
" 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"
-#else
-" .word 1b,(5b-1b)\n"
-" .word 2b,(5b-2b)\n"
-" .word 3b,(5b-3b)\n"
-" .word 4b,(5b-4b)\n"
+" .dword 1b,6b\n"
+" .dword 2b,6b\n"
+" .dword 3b,6b\n"
+" .dword 4b,6b\n"
+#else
+" .word 1b,6b\n"
+" .word 2b,6b\n"
+" .word 3b,6b\n"
+" .word 4b,6b\n"
#endif
" .previous\n"
: "=r" (ret)
@@ -438,21 +472,25 @@ static int emulate_std(struct pt_regs *r
"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"
-#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"
+" .dword 1b,7b\n"
+" .dword 2b,7b\n"
+" .dword 3b,7b\n"
+" .dword 4b,7b\n"
+" .dword 5b,7b\n"
+#else
+" .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)
Index: arch/parisc/lib/Makefile
===================================================================
RCS file: /var/cvs/linux-2.6/arch/parisc/lib/Makefile,v
retrieving revision 1.2
diff -u -p -r1.2 Makefile
--- arch/parisc/lib/Makefile 1 Jul 2004 18:30:36 -0000 1.2
+++ arch/parisc/lib/Makefile 14 Sep 2004 02:34:06 -0000
@@ -2,6 +2,6 @@
# Makefile for parisc-specific library files
#
-lib-y := lusercopy.o bitops.o checksum.o io.o memset.o
+lib-y := lusercopy.o bitops.o checksum.o io.o memset.o fixup.o
lib-$(CONFIG_SMP) += debuglocks.o
Index: arch/parisc/lib/fixup.S
===================================================================
RCS file: arch/parisc/lib/fixup.S
diff -N arch/parisc/lib/fixup.S
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ arch/parisc/lib/fixup.S 14 Sep 2004 02:34:06 -0000
@@ -0,0 +1,89 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Copyright (C) 2004 Randolph Chung <tausq@debian.org>
+ *
+ * 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Fixup routines for kernel exception handling.
+ */
+#include <linux/config.h>
+#include <asm/offsets.h>
+#include <asm/assembly.h>
+#include <asm/errno.h>
+
+#ifdef CONFIG_SMP
+ .macro get_fault_ip t1 t2
+ addil LT%__per_cpu_offset,%r27
+ LDREG RT%__per_cpu_offset(%r1),\t1
+ /* t2 = smp_processor_id() */
+ mfctl 30,\t2
+ ldw TI_CPU(\t2),\t2
+#ifdef __LP64__
+ extrd,u \t2,63,32,\t2
+#endif
+ /* t2 = &__per_cpu_offset[smp_processor_id()]; */
+ LDREG,s \t2(\t1),\t2
+ addil LT%per_cpu__exception_data,%r27
+ LDREG RT%per_cpu__exception_data(%r1),\t1
+ /* t1 = &__get_cpu_var(exception_data) */
+ add,l \t1,\t2,\t1
+ /* t1 = t1->fault_ip */
+ LDREG EXCDATA_IP(\t1), \t1
+ .endm
+#else
+ .macro get_fault_ip t1 t2
+ /* t1 = &__get_cpu_var(exception_data) */
+ addil LT%per_cpu__exception_data,%r27
+ LDREG RT%per_cpu__exception_data(%r1),\t2
+ /* t1 = t2->fault_ip */
+ LDREG EXCDATA_IP(\t2), \t1
+ .endm
+#endif
+
+ .text
+ .section .fixup, "ax"
+
+ /* get_user() fixups, store -EFAULT in r8, and 0 in r9 */
+ .export fixup_get_user_skip_1
+fixup_get_user_skip_1:
+ get_fault_ip %r1,%r8
+ ldo 4(%r1), %r1
+ ldi -EFAULT, %r8
+ bv %r0(%r1)
+ copy %r0, %r9
+
+ .export fixup_get_user_skip_2
+fixup_get_user_skip_2:
+ get_fault_ip %r1,%r8
+ ldo 8(%r1), %r1
+ ldi -EFAULT, %r8
+ bv %r0(%r1)
+ copy %r0, %r9
+
+ /* put_user() fixups, store -EFAULT in r8 */
+ .export fixup_put_user_skip_1
+fixup_put_user_skip_1:
+ get_fault_ip %r1,%r8
+ ldo 4(%r1), %r1
+ bv %r0(%r1)
+ ldi -EFAULT, %r8
+
+ .export fixup_put_user_skip_2
+fixup_put_user_skip_2:
+ get_fault_ip %r1,%r8
+ ldo 8(%r1), %r1
+ bv %r0(%r1)
+ ldi -EFAULT, %r8
Index: arch/parisc/lib/lusercopy.S
===================================================================
RCS file: /var/cvs/linux-2.6/arch/parisc/lib/lusercopy.S,v
retrieving revision 1.3
diff -u -p -r1.3 lusercopy.S
--- arch/parisc/lib/lusercopy.S 17 Jan 2004 06:39:24 -0000 1.3
+++ arch/parisc/lib/lusercopy.S 14 Sep 2004 02:34:06 -0000
@@ -53,6 +53,18 @@
mtsp %r1,%sr1
.endm
+#ifndef __LP64__
+ .macro fixup_branch lbl
+ b \lbl
+ .endm
+#else
+ .macro fixup_branch lbl
+ ldil L%\lbl, %r1
+ ldo R%\lbl(%r1), %r1
+ bv,n %r0(%r1)
+ .endm
+#endif
+
/*
* unsigned long
* lcopy_to_user(void *to, const void *from, unsigned long n)
@@ -77,14 +89,16 @@ $lctu_done:
copy %r24,%r28
.exit
-2: b $lctu_done
+ .section .fixup,"ax"
+2: fixup_branch $lctu_done
ldo 1(%r24),%r24
+ .previous
- .section __ex_table,"a"
+ .section __ex_table,"aw"
#ifdef __LP64__
- .dword 1b,(2b-1b)
+ .dword 1b,2b
#else
- .word 1b,(2b-1b)
+ .word 1b,2b
#endif
.previous
@@ -118,18 +132,20 @@ $lcfu_done:
copy %r24,%r28
.exit
+ .section .fixup,"ax"
2: copy %r24,%r23
$lcfu_zero_loop:
addib,<> -1,%r23,$lcfu_zero_loop
stbs,ma %r0,1(%r26)
- b $lcfu_done
+ fixup_branch $lcfu_done
nop
+ .previous
- .section __ex_table,"a"
+ .section __ex_table,"aw"
#ifdef __LP64__
- .dword 1b,(2b-1b)
+ .dword 1b,2b
#else
- .word 1b,(2b-1b)
+ .word 1b,2b
#endif
.previous
@@ -159,14 +175,16 @@ $lciu_done:
copy %r24,%r28
.exit
-2: b $lciu_done
+ .section .fixup,"ax"
+2: fixup_branch $lciu_done
ldo 1(%r24),%r24
+ .previous
- .section __ex_table,"a"
+ .section __ex_table,"aw"
#ifdef __LP64__
- .dword 1b,(2b-1b)
+ .dword 1b,2b
#else
- .word 1b,(2b-1b)
+ .word 1b,2b
#endif
.previous
@@ -201,16 +219,18 @@ $lsfu_exit:
nop
.exit
-3: b $lsfu_exit
+ .section .fixup,"ax"
+3: fixup_branch $lsfu_exit
ldi -EFAULT,%r28
+ .previous
- .section __ex_table,"a"
+ .section __ex_table,"aw"
#ifdef __LP64__
- .dword 1b,(3b-1b)
- .dword 2b,(3b-2b)
+ .dword 1b,3b
+ .dword 2b,3b
#else
- .word 1b,(3b-1b)
- .word 2b,(3b-2b)
+ .word 1b,3b
+ .word 2b,3b
#endif
.previous
@@ -239,14 +259,16 @@ $lclu_done:
copy %r25,%r28
.exit
-2: b $lclu_done
+ .section .fixup,"ax"
+2: fixup_branch $lclu_done
ldo 1(%r25),%r25
+ .previous
- .section __ex_table,"a"
+ .section __ex_table,"aw"
#ifdef __LP64__
- .dword 1b,(2b-1b)
+ .dword 1b,2b
#else
- .word 1b,(2b-1b)
+ .word 1b,2b
#endif
.previous
@@ -282,16 +304,18 @@ $lslen_nzero:
b $lslen_done
ldo 1(%r26),%r26 /* special case for N == 0 */
-3: b $lslen_done
+ .section .fixup,"ax"
+3: fixup_branch $lslen_done
copy %r24,%r26 /* reset r26 so 0 is returned on fault */
+ .previous
- .section __ex_table,"a"
+ .section __ex_table,"aw"
#ifdef __LP64__
- .dword 1b,(3b-1b)
- .dword 2b,(3b-2b)
+ .dword 1b,3b
+ .dword 2b,3b
#else
- .word 1b,(3b-1b)
- .word 2b,(3b-2b)
+ .word 1b,3b
+ .word 2b,3b
#endif
.previous
Index: arch/parisc/mm/fault.c
===================================================================
RCS file: /var/cvs/linux-2.6/arch/parisc/mm/fault.c,v
retrieving revision 1.1
diff -u -p -r1.1 fault.c
--- arch/parisc/mm/fault.c 29 Jul 2003 17:00:42 -0000 1.1
+++ arch/parisc/mm/fault.c 14 Sep 2004 02:34:06 -0000
@@ -36,6 +36,9 @@
#define BITSSET 0x1c0 /* for identifying LDCW */
+
+DEFINE_PER_CPU(struct exception_data, exception_data);
+
/*
* parisc_acctyp(unsigned int inst) --
* Given a PA-RISC memory access instruction, determine if the
@@ -234,13 +237,16 @@ no_context:
fix = search_exception_tables(regs->iaoq[0]);
if (fix) {
+ struct exception_data *d;
+
+printk("applying fixup for 0x%lx, fixup at 0x%lx\n", regs->iaoq[0], fix->fixup & ~3);
- if (fix->skip & 1)
- regs->gr[8] = -EFAULT;
- if (fix->skip & 2)
- regs->gr[9] = 0;
+ d = &__get_cpu_var(exception_data);
+ d->fault_ip = regs->iaoq[0];
+ d->fault_space = regs->isr;
+ d->fault_addr = regs->ior;
- regs->iaoq[0] += ((fix->skip) & ~3);
+ regs->iaoq[0] = ((fix->fixup) & ~3);
/*
* NOTE: In some cases the faulting instruction
Index: include/asm-parisc/uaccess.h
===================================================================
RCS file: /var/cvs/linux-2.6/include/asm-parisc/uaccess.h,v
retrieving revision 1.13
diff -u -p -r1.13 uaccess.h
--- include/asm-parisc/uaccess.h 4 Feb 2004 18:24:55 -0000 1.13
+++ include/asm-parisc/uaccess.h 14 Sep 2004 02:34:28 -0000
@@ -54,16 +54,22 @@ extern int __put_user_bad(void);
/*
* The exception table contains two values: the first is an address
* for an instruction that is allowed to fault, and the second is
- * the number of bytes to skip if a fault occurs. We also support in
- * two bit flags: 0x2 tells the exception handler to clear register
- * r9 and 0x1 tells the exception handler to put -EFAULT in r8.
- * This allows us to handle the simple cases for put_user and
- * get_user without having to have .fixup sections.
+ * the address to the fixup routine.
*/
struct exception_table_entry {
unsigned long insn; /* address of insn that is allowed to fault. */
- long skip; /* pcoq skip | r9 clear flag | r8 -EFAULT flag */
+ long fixup; /* fixup routine */
+};
+
+/*
+ * The page fault handler stores, in a per-cpu area, the following information
+ * if a fixup routine is available.
+ */
+struct exception_data {
+ unsigned long fault_ip;
+ unsigned long fault_space;
+ unsigned long fault_addr;
};
#define __get_user(x,ptr) \
@@ -97,48 +103,44 @@ struct exception_table_entry {
#ifdef __LP64__
#define __get_kernel_asm(ldx,ptr) \
__asm__("\n1:\t" ldx "\t0(%2),%0\n" \
- "2:\n" \
- "\t.section __ex_table,\"aw\"\n" \
- "\t.dword\t1b\n" \
- "\t.dword\t(2b-1b)+3\n" \
- "\t.previous" \
+ "\t.section __ex_table,\"aw\"\n" \
+ "\t.dword\t1b,fixup_get_user_skip_1\n" \
+ "\t.previous" \
: "=r"(__gu_val), "=r"(__gu_err) \
- : "r"(ptr), "1"(__gu_err));
+ : "r"(ptr), "1"(__gu_err) \
+ : "r1");
#define __get_user_asm(ldx,ptr) \
__asm__("\n1:\t" ldx "\t0(%%sr3,%2),%0\n" \
- "2:\n" \
- "\t.section __ex_table,\"aw\"\n" \
- "\t.dword\t1b\n" \
- "\t.dword\t(2b-1b)+3\n" \
- "\t.previous" \
+ "\t.section __ex_table,\"aw\"\n" \
+ "\t.dword\t1b,fixup_get_user_skip_1\n" \
+ "\t.previous" \
: "=r"(__gu_val), "=r"(__gu_err) \
- : "r"(ptr), "1"(__gu_err));
+ : "r"(ptr), "1"(__gu_err) \
+ : "r1");
#else
#define __get_kernel_asm(ldx,ptr) \
__asm__("\n1:\t" ldx "\t0(%2),%0\n" \
- "2:\n" \
- "\t.section __ex_table,\"aw\"\n" \
- "\t.word\t1b\n" \
- "\t.word\t(2b-1b)+3\n" \
- "\t.previous" \
+ "\t.section __ex_table,\"aw\"\n" \
+ "\t.word\t1b,fixup_get_user_skip_1\n" \
+ "\t.previous" \
: "=r"(__gu_val), "=r"(__gu_err) \
- : "r"(ptr), "1"(__gu_err));
+ : "r"(ptr), "1"(__gu_err) \
+ : "r1");
#define __get_user_asm(ldx,ptr) \
__asm__("\n1:\t" ldx "\t0(%%sr3,%2),%0\n" \
- "2:\n" \
- "\t.section __ex_table,\"aw\"\n" \
- "\t.word\t1b\n" \
- "\t.word\t(2b-1b)+3\n" \
+ "\t.section __ex_table,\"aw\"\n" \
+ "\t.word\t1b,fixup_get_user_skip_1\n" \
"\t.previous" \
: "=r"(__gu_val), "=r"(__gu_err) \
- : "r"(ptr), "1"(__gu_err));
+ : "r"(ptr), "1"(__gu_err) \
+ : "r1");
#endif /* !__LP64__ */
#define __put_user(x,ptr) \
({ \
- register long __pu_err __asm__ ("r8") = 0; \
+ register long __pu_err __asm__ ("r8") = 0; \
\
if (segment_eq(get_fs(),KERNEL_DS)) { \
switch (sizeof(*(ptr))) { \
@@ -172,82 +174,73 @@ struct exception_table_entry {
#define __put_kernel_asm(stx,x,ptr) \
__asm__ __volatile__ ( \
"\n1:\t" stx "\t%2,0(%1)\n" \
- "2:\n" \
- "\t.section __ex_table,\"aw\"\n" \
- "\t.dword\t1b\n" \
- "\t.dword\t(2b-1b)+1\n" \
- "\t.previous" \
+ "\t.section __ex_table,\"aw\"\n" \
+ "\t.dword\t1b,fixup_put_user_skip_1\n" \
+ "\t.previous" \
: "=r"(__pu_err) \
: "r"(ptr), "r"(x), "0"(__pu_err))
#define __put_user_asm(stx,x,ptr) \
__asm__ __volatile__ ( \
"\n1:\t" stx "\t%2,0(%%sr3,%1)\n" \
- "2:\n" \
- "\t.section __ex_table,\"aw\"\n" \
- "\t.dword\t1b\n" \
- "\t.dword\t(2b-1b)+1\n" \
+ "\t.section __ex_table,\"aw\"\n" \
+ "\t.dword\t1b,fixup_put_user_skip_1\n" \
"\t.previous" \
: "=r"(__pu_err) \
- : "r"(ptr), "r"(x), "0"(__pu_err))
+ : "r"(ptr), "r"(x), "0"(__pu_err) \
+ : "r1")
#else
#define __put_kernel_asm(stx,x,ptr) \
__asm__ __volatile__ ( \
"\n1:\t" stx "\t%2,0(%1)\n" \
- "2:\n" \
- "\t.section __ex_table,\"aw\"\n" \
- "\t.word\t1b\n" \
- "\t.word\t(2b-1b)+1\n" \
+ "\t.section __ex_table,\"aw\"\n" \
+ "\t.word\t1b,fixup_put_user_skip_1\n" \
"\t.previous" \
: "=r"(__pu_err) \
- : "r"(ptr), "r"(x), "0"(__pu_err))
+ : "r"(ptr), "r"(x), "0"(__pu_err) \
+ : "r1")
#define __put_user_asm(stx,x,ptr) \
__asm__ __volatile__ ( \
"\n1:\t" stx "\t%2,0(%%sr3,%1)\n" \
- "2:\n" \
- "\t.section __ex_table,\"aw\"\n" \
- "\t.word\t1b\n" \
- "\t.word\t(2b-1b)+1\n" \
+ "\t.section __ex_table,\"aw\"\n" \
+ "\t.word\t1b,fixup_put_user_skip_1\n" \
"\t.previous" \
: "=r"(__pu_err) \
- : "r"(ptr), "r"(x), "0"(__pu_err))
+ : "r"(ptr), "r"(x), "0"(__pu_err) \
+ : "r1")
-static inline void __put_kernel_asm64(u64 x, void *ptr)
-{
- u32 hi = x>>32;
- u32 lo = x&0xffffffff;
- __asm__ __volatile__ (
- "\n1:\tstw %1,0(%0)\n"
- "\n2:\tstw %2,4(%0)\n"
- "3:\n"
- "\t.section __ex_table,\"aw\"\n"
- "\t.word\t1b\n"
- "\t.word\t(3b-1b)+1\n"
- "\t.word\t2b\n"
- "\t.word\t(3b-2b)+1\n"
- "\t.previous"
- : : "r"(ptr), "r"(hi), "r"(lo));
-
-}
-
-static inline void __put_user_asm64(u64 x, void *ptr)
-{
- u32 hi = x>>32;
- u32 lo = x&0xffffffff;
- __asm__ __volatile__ (
- "\n1:\tstw %1,0(%%sr3,%0)\n"
- "\n2:\tstw %2,4(%%sr3,%0)\n"
- "3:\n"
- "\t.section __ex_table,\"aw\"\n"
- "\t.word\t1b\n"
- "\t.word\t(3b-1b)+1\n"
- "\t.word\t2b\n"
- "\t.word\t(3b-2b)+1\n"
- "\t.previous"
- : : "r"(ptr), "r"(hi), "r"(lo));
-
-}
+#define __put_kernel_asm64(_x,ptr) do { \
+ u64 x = (u64)_x; \
+ u32 hi = x>>32; \
+ u32 lo = x&0xffffffff; \
+ __asm__ __volatile__ ( \
+ "\n1:\tstw %2,0(%1)\n" \
+ "\n2:\tstw %3,4(%1)\n" \
+ "\t.section __ex_table,\"aw\"\n" \
+ "\t.word\t1b,fixup_put_user_skip_2\n" \
+ "\t.word\t2b,fixup_put_user_skip_1\n" \
+ "\t.previous" \
+ : "=r"(__pu_err) \
+ : "r"(ptr), "r"(hi), "r"(lo), "0"(__pu_err) \
+ : "r1"); \
+} while (0)
+
+#define __put_user_asm64(_x,ptr) do { \
+ u64 x = (u64)_x; \
+ u32 hi = x>>32; \
+ u32 lo = x&0xffffffff; \
+ __asm__ __volatile__ ( \
+ "\n1:\tstw %2,0(%%sr3,%1)\n" \
+ "\n2:\tstw %3,4(%%sr3,%1)\n" \
+ "\t.section __ex_table,\"aw\"\n" \
+ "\t.word\t1b,fixup_get_user_skip_2\n" \
+ "\t.word\t2b,fixup_get_user_skip_1\n" \
+ "\t.previous" \
+ : "=r"(__pu_err) \
+ : "r"(ptr), "r"(hi), "r"(lo), "0"(__pu_err) \
+ : "r1"); \
+} while (0)
#endif /* !__LP64__ */
randolph
--
Randolph Chung
Debian GNU/Linux Developer, hppa/ia64 ports
http://www.tausq.org/
_______________________________________________
parisc-linux mailing list
parisc-linux@lists.parisc-linux.org
http://lists.parisc-linux.org/mailman/listinfo/parisc-linux
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [parisc-linux] [RFC] Revamp exception handling in the kernel
2004-09-14 2:37 ` Randolph Chung
@ 2004-09-14 18:52 ` Joel Soete
0 siblings, 0 replies; 16+ messages in thread
From: Joel Soete @ 2004-09-14 18:52 UTC (permalink / raw)
To: Randolph Chung; +Cc: PARISC list
Randolph Chung wrote:
> Version 2a of the patch. Changes from the previous version:
>
> - Fixed the comment in uaccess.h, added some more comments to fixup.S
> - Added missing r1 clobbers
> - addil/ldd should be relative to r27, not r1
>
> i found out this is a somewhat effective way of testing this patch:
>
> - run "make vmlinux" (or make -j4 vmlinux) in one window
> - run "while true; do ./wtest; sleep 30; done" in another window
>
> wtest is compiled from:
> -------------------8< cut here 8<--------------------
> #include <stdio.h>
> #include <unistd.h>
> #include <errno.h>
>
> int main(int argc, char **argv)
> {
> char *buf = (char *)1;
> int ret;
>
> ret = write(fileno(stdout), buf, 10);
> printf("write returned ret = %d, errno = %d\n", ret, errno);
>
> return 0;
> }
>
> -------------------8< cut here 8<--------------------
>
[...]
mmm, just running wtest and:
applying fixup for 0x10100350, fixup at 0x1038e1d8
Backtrace:
[<1024fee0>] opost_block+0x58/0x1f8
[<10252d84>] write_chan+0x204/0x2a8
[<1024c02c>] tty_write+0x260/0x32c
[<1017d6b0>] vfs_write+0x100/0x148
[<1017d7fc>] sys_write+0x5c/0xa8
[<10110178>] syscall_exit+0x0/0x14
Kernel Fault: Code=26 regs=2a9fc3c0 (Addr=00000001)
YZrvWESTHLNXBCVMcbcbcbcbOGFRQPDI
PSW: 00000000000001101111111100001111 Not tainted
r00-03 00000000 00000aa0 1024fee0 0000000a
r04-07 2cb89000 00000001 2cb89000 2cc95320
r08-11 00000000 00000001 00000000 2cb89948
r12-15 00000001 00000000 000aa000 000eae68
r16-19 000eaf08 000eab48 00000000 00000000
r20-23 30000001 00000fff 00000001 00000000
r24-27 0000000a 00000001 2a9fc312 103ef010
r28-31 00000fff 00000000 2a9fc3c0 102540d8
sr0-3 00000000 00000aa0 00000000 00000aa0
sr4-7 00000000 00000000 00000000 00000000
IASQ: 00000000 00000000 IAOQ: 10100320 10100324
IIR: 0f221021 ISR: 00000000 IOR: 00000001
CPU: 0 CR30: 2a9fc000 CR31: 10454000
ORIG_R28: 00000000
IAOQ[0]: $lctu_loop+0x0/0xc
IAOQ[1]: $lctu_loop+0x4/0xc
RP(r2): opost_block+0x58/0x1f8
Kernel panic - not syncing: Kernel Fault
Is panic awaited?
TIA,
Joel
_______________________________________________
parisc-linux mailing list
parisc-linux@lists.parisc-linux.org
http://lists.parisc-linux.org/mailman/listinfo/parisc-linux
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [parisc-linux] [RFC] Revamp exception handling in the kernel
[not found] <20040914160613.GA28659@tausq.org>
@ 2004-09-14 22:36 ` Carlos O'Donell
[not found] ` <41487C05.3010606@tiscali.be>
0 siblings, 1 reply; 16+ messages in thread
From: Carlos O'Donell @ 2004-09-14 22:36 UTC (permalink / raw)
To: Randolph Chung; +Cc: parisc-linux
On Tue, Sep 14, 2004 at 09:06:13AM -0700, Randolph Chung wrote:
> then..... i don't particular like this change (inline to macro). was
> hoping that it will fix some compile warnings, but it introduces other
> ones :(
This works for me on 32-bit (c3k, latest cvs head) + patches.
Passes my multi-kill-kernel and test-lws tests, along with a kernel
build. It includes my changes for LWS.
I say it's good to checkin.
c.
Index: arch/parisc/kernel/asm-offsets.c
===================================================================
RCS file: /var/cvs/linux-2.6/arch/parisc/kernel/asm-offsets.c,v
retrieving revision 1.10
diff -u -p -r1.10 asm-offsets.c
--- arch/parisc/kernel/asm-offsets.c 13 Sep 2004 15:22:24 -0000 1.10
+++ arch/parisc/kernel/asm-offsets.c 14 Sep 2004 22:30:09 -0000
@@ -38,6 +38,7 @@
#include <asm/ptrace.h>
#include <asm/processor.h>
#include <asm/pdc.h>
+#include <asm/uaccess.h>
#define DEFINE(sym, val) \
asm volatile("\n->" #sym " %0 " #val : : "i" (val))
@@ -291,5 +292,8 @@ int main(void)
DEFINE(ASM_PT_INITIAL, PT_INITIAL);
DEFINE(ASM_PAGE_SIZE, PAGE_SIZE);
BLANK();
+ DEFINE(EXCDATA_IP, offsetof(struct exception_data, fault_ip));
+ DEFINE(EXCDATA_SPACE, offsetof(struct exception_data, fault_space));
+ DEFINE(EXCDATA_ADDR, offsetof(struct exception_data, fault_addr));
return 0;
}
Index: arch/parisc/kernel/syscall.S
===================================================================
RCS file: /var/cvs/linux-2.6/arch/parisc/kernel/syscall.S,v
retrieving revision 1.14
diff -u -p -r1.14 syscall.S
--- arch/parisc/kernel/syscall.S 10 Sep 2004 14:52:01 -0000 1.14
+++ arch/parisc/kernel/syscall.S 14 Sep 2004 22:30:09 -0000
@@ -29,6 +29,19 @@
#else
.level 1.1
#endif
+
+#ifndef __LP64__
+ .macro fixup_branch,lbl
+ b \lbl
+ .endm
+#else
+ .macro fixup_branch,lbl
+ ldil L%\lbl, %r1
+ ldo R%\lbl(%r1), %r1
+ bv,n %r0(%r1)
+ .endm
+#endif
+
.text
.import syscall_exit,code
@@ -575,10 +588,7 @@ cas_action:
/* Return to userspace, set no error */
b lws_exit
copy %r0, %r21
- nop /* Add some visual space in objdump */
- nop
- nop
- nop
+
3:
/* Error occured on load or store */
#ifdef CONFIG_SMP
@@ -596,15 +606,16 @@ cas_action:
nop
/* Two exception table entries, one for the load,
- the other for the store. Either return -EFAULT */
+ the other for the store. Either return -EFAULT.
+ Each of the entries must be relocated. */
.section __ex_table,"aw"
#ifdef __LP64__
/* Pad the address calculation */
.word 0,(2b - linux_gateway_page)
- .dword (3b - 2b)
+ .word 0,(3b - linux_gateway_page)
#else
- .word 2b - linux_gateway_page
- .word (3b - 2b)
+ .word (2b - linux_gateway_page)
+ .word (3b - linux_gateway_page)
#endif
.previous
@@ -612,10 +623,10 @@ cas_action:
#ifdef __LP64__
/* Pad the address calculation */
.word 0,(1b - linux_gateway_page)
- .dword (3b - 1b)
+ .word 0,(3b - linux_gateway_page)
#else
- .word 1b - linux_gateway_page
- .word (3b - 1b)
+ .word (1b - linux_gateway_page)
+ .word (3b - linux_gateway_page)
#endif
.previous
Index: arch/parisc/kernel/unaligned.c
===================================================================
RCS file: /var/cvs/linux-2.6/arch/parisc/kernel/unaligned.c,v
retrieving revision 1.8
diff -u -p -r1.8 unaligned.c
--- arch/parisc/kernel/unaligned.c 21 Aug 2004 06:19:33 -0000 1.8
+++ arch/parisc/kernel/unaligned.c 14 Sep 2004 22:30:09 -0000
@@ -23,6 +23,7 @@
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <asm/uaccess.h>
/* #define DEBUG_UNALIGNED 1 */
@@ -34,8 +35,14 @@
#ifdef __LP64__
#define RFMT "%016lx"
+#define FIXUP_BRANCH(lbl) \
+ "\tb " #lbl "\n"
#else
#define RFMT "%08lx"
+#define FIXUP_BRANCH(lbl) \
+ "\tldil L%%" #lbl ", %%r1\n" \
+ "\tldo R%%" #lbl "(%%r1), %%r1\n" \
+ "\tbv,n %%r0(%%r1)\n"
#endif
/* 1111 1100 0000 0000 0001 0011 1100 0000 */
@@ -134,15 +141,19 @@ static int emulate_ldh(struct pt_regs *r
"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)
@@ -175,15 +186,19 @@ static int emulate_ldw(struct pt_regs *r
" 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)
@@ -222,15 +237,19 @@ static int emulate_ldd(struct pt_regs *r
" 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)
@@ -250,17 +269,20 @@ static int emulate_ldd(struct pt_regs *r
" 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"
#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"
+" .dword 1b,5b\n"
+" .dword 2b,5b\n"
+" .dword 3b,5b\n"
+#else
+" .word 1b,5b\n"
+" .word 2b,5b\n"
+" .word 3b,5b\n"
#endif
" .previous\n"
: "=r" (valh), "=r" (vall), "=r" (ret)
@@ -296,15 +318,19 @@ static int emulate_sth(struct pt_regs *r
" 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)
@@ -346,15 +372,19 @@ static int emulate_stw(struct pt_regs *r
" 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)
@@ -399,19 +429,23 @@ static int emulate_std(struct pt_regs *r
" 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"
-#else
-" .word 1b,(5b-1b)\n"
-" .word 2b,(5b-2b)\n"
-" .word 3b,(5b-3b)\n"
-" .word 4b,(5b-4b)\n"
+" .dword 1b,6b\n"
+" .dword 2b,6b\n"
+" .dword 3b,6b\n"
+" .dword 4b,6b\n"
+#else
+" .word 1b,6b\n"
+" .word 2b,6b\n"
+" .word 3b,6b\n"
+" .word 4b,6b\n"
#endif
" .previous\n"
: "=r" (ret)
@@ -438,21 +472,25 @@ static int emulate_std(struct pt_regs *r
"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"
-#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"
+" .dword 1b,7b\n"
+" .dword 2b,7b\n"
+" .dword 3b,7b\n"
+" .dword 4b,7b\n"
+" .dword 5b,7b\n"
+#else
+" .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)
Index: arch/parisc/lib/Makefile
===================================================================
RCS file: /var/cvs/linux-2.6/arch/parisc/lib/Makefile,v
retrieving revision 1.2
diff -u -p -r1.2 Makefile
--- arch/parisc/lib/Makefile 1 Jul 2004 18:30:36 -0000 1.2
+++ arch/parisc/lib/Makefile 14 Sep 2004 22:30:09 -0000
@@ -2,6 +2,6 @@
# Makefile for parisc-specific library files
#
-lib-y := lusercopy.o bitops.o checksum.o io.o memset.o
+lib-y := lusercopy.o bitops.o checksum.o io.o memset.o fixup.o
lib-$(CONFIG_SMP) += debuglocks.o
Index: arch/parisc/lib/lusercopy.S
===================================================================
RCS file: /var/cvs/linux-2.6/arch/parisc/lib/lusercopy.S,v
retrieving revision 1.3
diff -u -p -r1.3 lusercopy.S
--- arch/parisc/lib/lusercopy.S 17 Jan 2004 06:39:24 -0000 1.3
+++ arch/parisc/lib/lusercopy.S 14 Sep 2004 22:30:09 -0000
@@ -53,6 +53,18 @@
mtsp %r1,%sr1
.endm
+#ifndef __LP64__
+ .macro fixup_branch lbl
+ b \lbl
+ .endm
+#else
+ .macro fixup_branch lbl
+ ldil L%\lbl, %r1
+ ldo R%\lbl(%r1), %r1
+ bv,n %r0(%r1)
+ .endm
+#endif
+
/*
* unsigned long
* lcopy_to_user(void *to, const void *from, unsigned long n)
@@ -77,14 +89,16 @@ $lctu_done:
copy %r24,%r28
.exit
-2: b $lctu_done
+ .section .fixup,"ax"
+2: fixup_branch $lctu_done
ldo 1(%r24),%r24
+ .previous
- .section __ex_table,"a"
+ .section __ex_table,"aw"
#ifdef __LP64__
- .dword 1b,(2b-1b)
+ .dword 1b,2b
#else
- .word 1b,(2b-1b)
+ .word 1b,2b
#endif
.previous
@@ -118,18 +132,20 @@ $lcfu_done:
copy %r24,%r28
.exit
+ .section .fixup,"ax"
2: copy %r24,%r23
$lcfu_zero_loop:
addib,<> -1,%r23,$lcfu_zero_loop
stbs,ma %r0,1(%r26)
- b $lcfu_done
+ fixup_branch $lcfu_done
nop
+ .previous
- .section __ex_table,"a"
+ .section __ex_table,"aw"
#ifdef __LP64__
- .dword 1b,(2b-1b)
+ .dword 1b,2b
#else
- .word 1b,(2b-1b)
+ .word 1b,2b
#endif
.previous
@@ -159,14 +175,16 @@ $lciu_done:
copy %r24,%r28
.exit
-2: b $lciu_done
+ .section .fixup,"ax"
+2: fixup_branch $lciu_done
ldo 1(%r24),%r24
+ .previous
- .section __ex_table,"a"
+ .section __ex_table,"aw"
#ifdef __LP64__
- .dword 1b,(2b-1b)
+ .dword 1b,2b
#else
- .word 1b,(2b-1b)
+ .word 1b,2b
#endif
.previous
@@ -201,16 +219,18 @@ $lsfu_exit:
nop
.exit
-3: b $lsfu_exit
+ .section .fixup,"ax"
+3: fixup_branch $lsfu_exit
ldi -EFAULT,%r28
+ .previous
- .section __ex_table,"a"
+ .section __ex_table,"aw"
#ifdef __LP64__
- .dword 1b,(3b-1b)
- .dword 2b,(3b-2b)
+ .dword 1b,3b
+ .dword 2b,3b
#else
- .word 1b,(3b-1b)
- .word 2b,(3b-2b)
+ .word 1b,3b
+ .word 2b,3b
#endif
.previous
@@ -239,14 +259,16 @@ $lclu_done:
copy %r25,%r28
.exit
-2: b $lclu_done
+ .section .fixup,"ax"
+2: fixup_branch $lclu_done
ldo 1(%r25),%r25
+ .previous
- .section __ex_table,"a"
+ .section __ex_table,"aw"
#ifdef __LP64__
- .dword 1b,(2b-1b)
+ .dword 1b,2b
#else
- .word 1b,(2b-1b)
+ .word 1b,2b
#endif
.previous
@@ -282,16 +304,18 @@ $lslen_nzero:
b $lslen_done
ldo 1(%r26),%r26 /* special case for N == 0 */
-3: b $lslen_done
+ .section .fixup,"ax"
+3: fixup_branch $lslen_done
copy %r24,%r26 /* reset r26 so 0 is returned on fault */
+ .previous
- .section __ex_table,"a"
+ .section __ex_table,"aw"
#ifdef __LP64__
- .dword 1b,(3b-1b)
- .dword 2b,(3b-2b)
+ .dword 1b,3b
+ .dword 2b,3b
#else
- .word 1b,(3b-1b)
- .word 2b,(3b-2b)
+ .word 1b,3b
+ .word 2b,3b
#endif
.previous
Index: arch/parisc/mm/fault.c
===================================================================
RCS file: /var/cvs/linux-2.6/arch/parisc/mm/fault.c,v
retrieving revision 1.1
diff -u -p -r1.1 fault.c
--- arch/parisc/mm/fault.c 29 Jul 2003 17:00:42 -0000 1.1
+++ arch/parisc/mm/fault.c 14 Sep 2004 22:30:09 -0000
@@ -36,6 +36,9 @@
#define BITSSET 0x1c0 /* for identifying LDCW */
+
+DEFINE_PER_CPU(struct exception_data, exception_data);
+
/*
* parisc_acctyp(unsigned int inst) --
* Given a PA-RISC memory access instruction, determine if the
@@ -234,13 +237,16 @@ no_context:
fix = search_exception_tables(regs->iaoq[0]);
if (fix) {
+ struct exception_data *d;
+
+printk("applying fixup for 0x%lx, fixup at 0x%lx\n", regs->iaoq[0], fix->fixup & ~3);
- if (fix->skip & 1)
- regs->gr[8] = -EFAULT;
- if (fix->skip & 2)
- regs->gr[9] = 0;
+ d = &__get_cpu_var(exception_data);
+ d->fault_ip = regs->iaoq[0];
+ d->fault_space = regs->isr;
+ d->fault_addr = regs->ior;
- regs->iaoq[0] += ((fix->skip) & ~3);
+ regs->iaoq[0] = ((fix->fixup) & ~3);
/*
* NOTE: In some cases the faulting instruction
Index: include/asm-parisc/uaccess.h
===================================================================
RCS file: /var/cvs/linux-2.6/include/asm-parisc/uaccess.h,v
retrieving revision 1.15
diff -u -p -r1.15 uaccess.h
--- include/asm-parisc/uaccess.h 13 Sep 2004 16:43:28 -0000 1.15
+++ include/asm-parisc/uaccess.h 14 Sep 2004 22:30:19 -0000
@@ -55,16 +55,22 @@ extern int __put_user_bad(void);
/*
* The exception table contains two values: the first is an address
* for an instruction that is allowed to fault, and the second is
- * the number of bytes to skip if a fault occurs. We also support in
- * two bit flags: 0x2 tells the exception handler to clear register
- * r9 and 0x1 tells the exception handler to put -EFAULT in r8.
- * This allows us to handle the simple cases for put_user and
- * get_user without having to have .fixup sections.
+ * the address to the fixup routine.
*/
struct exception_table_entry {
unsigned long insn; /* address of insn that is allowed to fault. */
- long skip; /* pcoq skip | r9 clear flag | r8 -EFAULT flag */
+ long fixup; /* fixup routine */
+};
+
+/*
+ * The page fault handler stores, in a per-cpu area, the following information
+ * if a fixup routine is available.
+ */
+struct exception_data {
+ unsigned long fault_ip;
+ unsigned long fault_space;
+ unsigned long fault_addr;
};
#define __get_user(x,ptr) \
@@ -98,48 +104,44 @@ struct exception_table_entry {
#ifdef __LP64__
#define __get_kernel_asm(ldx,ptr) \
__asm__("\n1:\t" ldx "\t0(%2),%0\n" \
- "2:\n" \
- "\t.section __ex_table,\"aw\"\n" \
- "\t.dword\t1b\n" \
- "\t.dword\t(2b-1b)+3\n" \
- "\t.previous" \
+ "\t.section __ex_table,\"aw\"\n" \
+ "\t.dword\t1b,fixup_get_user_skip_1\n" \
+ "\t.previous" \
: "=r"(__gu_val), "=r"(__gu_err) \
- : "r"(ptr), "1"(__gu_err));
+ : "r"(ptr), "1"(__gu_err) \
+ : "r1");
#define __get_user_asm(ldx,ptr) \
__asm__("\n1:\t" ldx "\t0(%%sr3,%2),%0\n" \
- "2:\n" \
- "\t.section __ex_table,\"aw\"\n" \
- "\t.dword\t1b\n" \
- "\t.dword\t(2b-1b)+3\n" \
- "\t.previous" \
+ "\t.section __ex_table,\"aw\"\n" \
+ "\t.dword\t1b,fixup_get_user_skip_1\n" \
+ "\t.previous" \
: "=r"(__gu_val), "=r"(__gu_err) \
- : "r"(ptr), "1"(__gu_err));
+ : "r"(ptr), "1"(__gu_err) \
+ : "r1");
#else
#define __get_kernel_asm(ldx,ptr) \
__asm__("\n1:\t" ldx "\t0(%2),%0\n" \
- "2:\n" \
- "\t.section __ex_table,\"aw\"\n" \
- "\t.word\t1b\n" \
- "\t.word\t(2b-1b)+3\n" \
- "\t.previous" \
+ "\t.section __ex_table,\"aw\"\n" \
+ "\t.word\t1b,fixup_get_user_skip_1\n" \
+ "\t.previous" \
: "=r"(__gu_val), "=r"(__gu_err) \
- : "r"(ptr), "1"(__gu_err));
+ : "r"(ptr), "1"(__gu_err) \
+ : "r1");
#define __get_user_asm(ldx,ptr) \
__asm__("\n1:\t" ldx "\t0(%%sr3,%2),%0\n" \
- "2:\n" \
- "\t.section __ex_table,\"aw\"\n" \
- "\t.word\t1b\n" \
- "\t.word\t(2b-1b)+3\n" \
+ "\t.section __ex_table,\"aw\"\n" \
+ "\t.word\t1b,fixup_get_user_skip_1\n" \
"\t.previous" \
: "=r"(__gu_val), "=r"(__gu_err) \
- : "r"(ptr), "1"(__gu_err));
+ : "r"(ptr), "1"(__gu_err) \
+ : "r1");
#endif /* !__LP64__ */
#define __put_user(x,ptr) \
({ \
- register long __pu_err __asm__ ("r8") = 0; \
+ register long __pu_err __asm__ ("r8") = 0; \
\
if (segment_eq(get_fs(),KERNEL_DS)) { \
switch (sizeof(*(ptr))) { \
@@ -173,82 +175,73 @@ struct exception_table_entry {
#define __put_kernel_asm(stx,x,ptr) \
__asm__ __volatile__ ( \
"\n1:\t" stx "\t%2,0(%1)\n" \
- "2:\n" \
- "\t.section __ex_table,\"aw\"\n" \
- "\t.dword\t1b\n" \
- "\t.dword\t(2b-1b)+1\n" \
- "\t.previous" \
+ "\t.section __ex_table,\"aw\"\n" \
+ "\t.dword\t1b,fixup_put_user_skip_1\n" \
+ "\t.previous" \
: "=r"(__pu_err) \
: "r"(ptr), "r"(x), "0"(__pu_err))
#define __put_user_asm(stx,x,ptr) \
__asm__ __volatile__ ( \
"\n1:\t" stx "\t%2,0(%%sr3,%1)\n" \
- "2:\n" \
- "\t.section __ex_table,\"aw\"\n" \
- "\t.dword\t1b\n" \
- "\t.dword\t(2b-1b)+1\n" \
+ "\t.section __ex_table,\"aw\"\n" \
+ "\t.dword\t1b,fixup_put_user_skip_1\n" \
"\t.previous" \
: "=r"(__pu_err) \
- : "r"(ptr), "r"(x), "0"(__pu_err))
+ : "r"(ptr), "r"(x), "0"(__pu_err) \
+ : "r1")
#else
#define __put_kernel_asm(stx,x,ptr) \
__asm__ __volatile__ ( \
"\n1:\t" stx "\t%2,0(%1)\n" \
- "2:\n" \
- "\t.section __ex_table,\"aw\"\n" \
- "\t.word\t1b\n" \
- "\t.word\t(2b-1b)+1\n" \
+ "\t.section __ex_table,\"aw\"\n" \
+ "\t.word\t1b,fixup_put_user_skip_1\n" \
"\t.previous" \
: "=r"(__pu_err) \
- : "r"(ptr), "r"(x), "0"(__pu_err))
+ : "r"(ptr), "r"(x), "0"(__pu_err) \
+ : "r1")
#define __put_user_asm(stx,x,ptr) \
__asm__ __volatile__ ( \
"\n1:\t" stx "\t%2,0(%%sr3,%1)\n" \
- "2:\n" \
- "\t.section __ex_table,\"aw\"\n" \
- "\t.word\t1b\n" \
- "\t.word\t(2b-1b)+1\n" \
+ "\t.section __ex_table,\"aw\"\n" \
+ "\t.word\t1b,fixup_put_user_skip_1\n" \
"\t.previous" \
: "=r"(__pu_err) \
- : "r"(ptr), "r"(x), "0"(__pu_err))
+ : "r"(ptr), "r"(x), "0"(__pu_err) \
+ : "r1")
-static inline void __put_kernel_asm64(u64 x, void *ptr)
-{
- u32 hi = x>>32;
- u32 lo = x&0xffffffff;
- __asm__ __volatile__ (
- "\n1:\tstw %1,0(%0)\n"
- "\n2:\tstw %2,4(%0)\n"
- "3:\n"
- "\t.section __ex_table,\"aw\"\n"
- "\t.word\t1b\n"
- "\t.word\t(3b-1b)+1\n"
- "\t.word\t2b\n"
- "\t.word\t(3b-2b)+1\n"
- "\t.previous"
- : : "r"(ptr), "r"(hi), "r"(lo));
-
-}
-
-static inline void __put_user_asm64(u64 x, void *ptr)
-{
- u32 hi = x>>32;
- u32 lo = x&0xffffffff;
- __asm__ __volatile__ (
- "\n1:\tstw %1,0(%%sr3,%0)\n"
- "\n2:\tstw %2,4(%%sr3,%0)\n"
- "3:\n"
- "\t.section __ex_table,\"aw\"\n"
- "\t.word\t1b\n"
- "\t.word\t(3b-1b)+1\n"
- "\t.word\t2b\n"
- "\t.word\t(3b-2b)+1\n"
- "\t.previous"
- : : "r"(ptr), "r"(hi), "r"(lo));
-
-}
+#define __put_kernel_asm64(__val,ptr) do { \
+ u64 __val64 = (u64)(__val); \
+ u32 hi = (__val64) >> 32; \
+ u32 lo = (__val64) & 0xffffffff; \
+ __asm__ __volatile__ ( \
+ "\n1:\tstw %2,0(%1)\n" \
+ "\n2:\tstw %3,4(%1)\n" \
+ "\t.section __ex_table,\"aw\"\n" \
+ "\t.word\t1b,fixup_put_user_skip_2\n" \
+ "\t.word\t2b,fixup_put_user_skip_1\n" \
+ "\t.previous" \
+ : "=r"(__pu_err) \
+ : "r"(ptr), "r"(hi), "r"(lo), "0"(__pu_err) \
+ : "r1"); \
+} while (0)
+
+#define __put_user_asm64(__val,ptr) do { \
+ u64 __val64 = (u64)__val; \
+ u32 hi = (__val64) >> 32; \
+ u32 lo = (__val64) & 0xffffffff; \
+ __asm__ __volatile__ ( \
+ "\n1:\tstw %2,0(%%sr3,%1)\n" \
+ "\n2:\tstw %3,4(%%sr3,%1)\n" \
+ "\t.section __ex_table,\"aw\"\n" \
+ "\t.word\t1b,fixup_get_user_skip_2\n" \
+ "\t.word\t2b,fixup_get_user_skip_1\n" \
+ "\t.previous" \
+ : "=r"(__pu_err) \
+ : "r"(ptr), "r"(hi), "r"(lo), "0"(__pu_err) \
+ : "r1"); \
+} while (0)
#endif /* !__LP64__ */
_______________________________________________
parisc-linux mailing list
parisc-linux@lists.parisc-linux.org
http://lists.parisc-linux.org/mailman/listinfo/parisc-linux
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [parisc-linux] [RFC] Revamp exception handling in the kernel
[not found] ` <41487D4C.2020004@tiscali.be>
@ 2004-09-16 14:31 ` Carlos O'Donell
0 siblings, 0 replies; 16+ messages in thread
From: Carlos O'Donell @ 2004-09-16 14:31 UTC (permalink / raw)
To: Joel Soete; +Cc: parisc-linux
On Wed, Sep 15, 2004 at 05:35:08PM +0000, Joel Soete wrote:
> Out of Memory: Killed process 1760 (test-lws).
> Out of Memory: Killed process 1762 (test-lws).
Yeah, you can't let this happen. The test is a bit rough on your box,
I've always turnes OOM off and minimized the number of *other* running
processes. The test (I think) has a tunable for memory to try capture
before running the CAS. That particular part of the test is trying to
see if CAS'ing on swapped pages is atomic or non-atomic by signaling the
process during a write to a swapped page.
c.
_______________________________________________
parisc-linux mailing list
parisc-linux@lists.parisc-linux.org
http://lists.parisc-linux.org/mailman/listinfo/parisc-linux
^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2004-09-16 14:31 UTC | newest]
Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-09-11 16:53 [parisc-linux] [RFC] Revamp exception handling in the kernel Randolph Chung
2004-09-11 22:49 ` John David Anglin
2004-09-12 13:10 ` Carlos O'Donell
2004-09-12 13:47 ` Carlos O'Donell
2004-09-12 13:58 ` James Bottomley
2004-09-12 14:29 ` Carlos O'Donell
2004-09-12 15:03 ` James Bottomley
2004-09-12 16:15 ` Randolph Chung
2004-09-12 17:54 ` Carlos O'Donell
2004-09-12 18:48 ` Randolph Chung
2004-09-12 19:19 ` Carlos O'Donell
2004-09-13 23:37 ` Randolph Chung
2004-09-14 2:37 ` Randolph Chung
2004-09-14 18:52 ` Joel Soete
[not found] <20040914160613.GA28659@tausq.org>
2004-09-14 22:36 ` Carlos O'Donell
[not found] ` <41487C05.3010606@tiscali.be>
[not found] ` <41487D4C.2020004@tiscali.be>
2004-09-16 14:31 ` Carlos O'Donell
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.