From: Randolph Chung <randolph@tausq.org>
To: PARISC list <parisc-linux@lists.parisc-linux.org>
Subject: Re: [parisc-linux] [RFC] Revamp exception handling in the kernel
Date: Mon, 13 Sep 2004 16:37:42 -0700 [thread overview]
Message-ID: <20040913233742.GW28659@tausq.org> (raw)
In-Reply-To: <20040911165325.GO28659@tausq.org>
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
next prev parent reply other threads:[~2004-09-13 23:37 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
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 [this message]
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
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20040913233742.GW28659@tausq.org \
--to=randolph@tausq.org \
--cc=parisc-linux@lists.parisc-linux.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.