aboutsummaryrefslogtreecommitdiffstats
path: root/arch/parisc
diff options
context:
space:
mode:
authorHelge Deller <deller@gmx.de>2016-04-08 12:32:52 -0400
committerHelge Deller <deller@gmx.de>2016-04-08 16:14:14 -0400
commit2ef4dfd9d9f288943e249b78365a69e3ea3ec072 (patch)
treeb2add375348d201853d93329c144159cf45b96ae /arch/parisc
parentef72f3110d8b19f4c098a0bff7ed7d11945e70c6 (diff)
parisc: Unbreak handling exceptions from kernel modules
Handling exceptions from modules never worked on parisc. It was just masked by the fact that exceptions from modules don't happen during normal use. When a module triggers an exception in get_user() we need to load the main kernel dp value before accessing the exception_data structure, and afterwards restore the original dp value of the module on exit. Noticed-by: Mikulas Patocka <mpatocka@redhat.com> Signed-off-by: Helge Deller <deller@gmx.de> Cc: stable@vger.kernel.org
Diffstat (limited to 'arch/parisc')
-rw-r--r--arch/parisc/include/asm/uaccess.h1
-rw-r--r--arch/parisc/kernel/asm-offsets.c1
-rw-r--r--arch/parisc/lib/fixup.S6
-rw-r--r--arch/parisc/mm/fault.c1
4 files changed, 9 insertions, 0 deletions
diff --git a/arch/parisc/include/asm/uaccess.h b/arch/parisc/include/asm/uaccess.h
index d4dd6e58682c..6f893d29f1b2 100644
--- a/arch/parisc/include/asm/uaccess.h
+++ b/arch/parisc/include/asm/uaccess.h
@@ -77,6 +77,7 @@ struct exception_table_entry {
77 */ 77 */
78struct exception_data { 78struct exception_data {
79 unsigned long fault_ip; 79 unsigned long fault_ip;
80 unsigned long fault_gp;
80 unsigned long fault_space; 81 unsigned long fault_space;
81 unsigned long fault_addr; 82 unsigned long fault_addr;
82}; 83};
diff --git a/arch/parisc/kernel/asm-offsets.c b/arch/parisc/kernel/asm-offsets.c
index d2f62570a7b1..78d30d2ea2d8 100644
--- a/arch/parisc/kernel/asm-offsets.c
+++ b/arch/parisc/kernel/asm-offsets.c
@@ -299,6 +299,7 @@ int main(void)
299#endif 299#endif
300 BLANK(); 300 BLANK();
301 DEFINE(EXCDATA_IP, offsetof(struct exception_data, fault_ip)); 301 DEFINE(EXCDATA_IP, offsetof(struct exception_data, fault_ip));
302 DEFINE(EXCDATA_GP, offsetof(struct exception_data, fault_gp));
302 DEFINE(EXCDATA_SPACE, offsetof(struct exception_data, fault_space)); 303 DEFINE(EXCDATA_SPACE, offsetof(struct exception_data, fault_space));
303 DEFINE(EXCDATA_ADDR, offsetof(struct exception_data, fault_addr)); 304 DEFINE(EXCDATA_ADDR, offsetof(struct exception_data, fault_addr));
304 BLANK(); 305 BLANK();
diff --git a/arch/parisc/lib/fixup.S b/arch/parisc/lib/fixup.S
index 536ef66bb94b..1052b747e011 100644
--- a/arch/parisc/lib/fixup.S
+++ b/arch/parisc/lib/fixup.S
@@ -26,6 +26,7 @@
26 26
27#ifdef CONFIG_SMP 27#ifdef CONFIG_SMP
28 .macro get_fault_ip t1 t2 28 .macro get_fault_ip t1 t2
29 loadgp
29 addil LT%__per_cpu_offset,%r27 30 addil LT%__per_cpu_offset,%r27
30 LDREG RT%__per_cpu_offset(%r1),\t1 31 LDREG RT%__per_cpu_offset(%r1),\t1
31 /* t2 = smp_processor_id() */ 32 /* t2 = smp_processor_id() */
@@ -40,14 +41,19 @@
40 LDREG RT%exception_data(%r1),\t1 41 LDREG RT%exception_data(%r1),\t1
41 /* t1 = this_cpu_ptr(&exception_data) */ 42 /* t1 = this_cpu_ptr(&exception_data) */
42 add,l \t1,\t2,\t1 43 add,l \t1,\t2,\t1
44 /* %r27 = t1->fault_gp - restore gp */
45 LDREG EXCDATA_GP(\t1), %r27
43 /* t1 = t1->fault_ip */ 46 /* t1 = t1->fault_ip */
44 LDREG EXCDATA_IP(\t1), \t1 47 LDREG EXCDATA_IP(\t1), \t1
45 .endm 48 .endm
46#else 49#else
47 .macro get_fault_ip t1 t2 50 .macro get_fault_ip t1 t2
51 loadgp
48 /* t1 = this_cpu_ptr(&exception_data) */ 52 /* t1 = this_cpu_ptr(&exception_data) */
49 addil LT%exception_data,%r27 53 addil LT%exception_data,%r27
50 LDREG RT%exception_data(%r1),\t2 54 LDREG RT%exception_data(%r1),\t2
55 /* %r27 = t2->fault_gp - restore gp */
56 LDREG EXCDATA_GP(\t2), %r27
51 /* t1 = t2->fault_ip */ 57 /* t1 = t2->fault_ip */
52 LDREG EXCDATA_IP(\t2), \t1 58 LDREG EXCDATA_IP(\t2), \t1
53 .endm 59 .endm
diff --git a/arch/parisc/mm/fault.c b/arch/parisc/mm/fault.c
index 26fac9c671c9..16dbe81c97c9 100644
--- a/arch/parisc/mm/fault.c
+++ b/arch/parisc/mm/fault.c
@@ -145,6 +145,7 @@ int fixup_exception(struct pt_regs *regs)
145 struct exception_data *d; 145 struct exception_data *d;
146 d = this_cpu_ptr(&exception_data); 146 d = this_cpu_ptr(&exception_data);
147 d->fault_ip = regs->iaoq[0]; 147 d->fault_ip = regs->iaoq[0];
148 d->fault_gp = regs->gr[27];
148 d->fault_space = regs->isr; 149 d->fault_space = regs->isr;
149 d->fault_addr = regs->ior; 150 d->fault_addr = regs->ior;
150 151