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.
Unified · Split
| @@ -77,6 +77,7 @@ struct exception_table_entry { · 76 unmodified lines | |||
| 77 | */ | 77 | */ |
| 78 | struct exception_data { | 78 | struct 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 | }; |
| @@ -299,6 +299,7 @@ int main(void) · 298 unmodified lines | |||
| 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(); |
| @@ -26,6 +26,7 @@ · 25 unmodified lines | |||
| 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 @@ · 8 unmodified lines | |||
| 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 |
| @@ -145,6 +145,7 @@ int fixup_exception(struct pt_regs *regs) · 144 unmodified lines | |||
| 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 | ||