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
This commit is contained in:
parent
ef72f3110d
commit
2ef4dfd9d9
|
@ -77,6 +77,7 @@ struct exception_table_entry {
|
||||||
*/
|
*/
|
||||||
struct exception_data {
|
struct exception_data {
|
||||||
unsigned long fault_ip;
|
unsigned long fault_ip;
|
||||||
|
unsigned long fault_gp;
|
||||||
unsigned long fault_space;
|
unsigned long fault_space;
|
||||||
unsigned long fault_addr;
|
unsigned long fault_addr;
|
||||||
};
|
};
|
||||||
|
|
|
@ -299,6 +299,7 @@ int main(void)
|
||||||
#endif
|
#endif
|
||||||
BLANK();
|
BLANK();
|
||||||
DEFINE(EXCDATA_IP, offsetof(struct exception_data, fault_ip));
|
DEFINE(EXCDATA_IP, offsetof(struct exception_data, fault_ip));
|
||||||
|
DEFINE(EXCDATA_GP, offsetof(struct exception_data, fault_gp));
|
||||||
DEFINE(EXCDATA_SPACE, offsetof(struct exception_data, fault_space));
|
DEFINE(EXCDATA_SPACE, offsetof(struct exception_data, fault_space));
|
||||||
DEFINE(EXCDATA_ADDR, offsetof(struct exception_data, fault_addr));
|
DEFINE(EXCDATA_ADDR, offsetof(struct exception_data, fault_addr));
|
||||||
BLANK();
|
BLANK();
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
.macro get_fault_ip t1 t2
|
.macro get_fault_ip t1 t2
|
||||||
|
loadgp
|
||||||
addil LT%__per_cpu_offset,%r27
|
addil LT%__per_cpu_offset,%r27
|
||||||
LDREG RT%__per_cpu_offset(%r1),\t1
|
LDREG RT%__per_cpu_offset(%r1),\t1
|
||||||
/* t2 = smp_processor_id() */
|
/* t2 = smp_processor_id() */
|
||||||
|
@ -40,14 +41,19 @@
|
||||||
LDREG RT%exception_data(%r1),\t1
|
LDREG RT%exception_data(%r1),\t1
|
||||||
/* t1 = this_cpu_ptr(&exception_data) */
|
/* t1 = this_cpu_ptr(&exception_data) */
|
||||||
add,l \t1,\t2,\t1
|
add,l \t1,\t2,\t1
|
||||||
|
/* %r27 = t1->fault_gp - restore gp */
|
||||||
|
LDREG EXCDATA_GP(\t1), %r27
|
||||||
/* t1 = t1->fault_ip */
|
/* t1 = t1->fault_ip */
|
||||||
LDREG EXCDATA_IP(\t1), \t1
|
LDREG EXCDATA_IP(\t1), \t1
|
||||||
.endm
|
.endm
|
||||||
#else
|
#else
|
||||||
.macro get_fault_ip t1 t2
|
.macro get_fault_ip t1 t2
|
||||||
|
loadgp
|
||||||
/* t1 = this_cpu_ptr(&exception_data) */
|
/* t1 = this_cpu_ptr(&exception_data) */
|
||||||
addil LT%exception_data,%r27
|
addil LT%exception_data,%r27
|
||||||
LDREG RT%exception_data(%r1),\t2
|
LDREG RT%exception_data(%r1),\t2
|
||||||
|
/* %r27 = t2->fault_gp - restore gp */
|
||||||
|
LDREG EXCDATA_GP(\t2), %r27
|
||||||
/* t1 = t2->fault_ip */
|
/* t1 = t2->fault_ip */
|
||||||
LDREG EXCDATA_IP(\t2), \t1
|
LDREG EXCDATA_IP(\t2), \t1
|
||||||
.endm
|
.endm
|
||||||
|
|
|
@ -145,6 +145,7 @@ int fixup_exception(struct pt_regs *regs)
|
||||||
struct exception_data *d;
|
struct exception_data *d;
|
||||||
d = this_cpu_ptr(&exception_data);
|
d = this_cpu_ptr(&exception_data);
|
||||||
d->fault_ip = regs->iaoq[0];
|
d->fault_ip = regs->iaoq[0];
|
||||||
|
d->fault_gp = regs->gr[27];
|
||||||
d->fault_space = regs->isr;
|
d->fault_space = regs->isr;
|
||||||
d->fault_addr = regs->ior;
|
d->fault_addr = regs->ior;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue