diff options
Diffstat (limited to 'arch/s390/mm/fault.c')
-rw-r--r-- | arch/s390/mm/fault.c | 33 |
1 files changed, 22 insertions, 11 deletions
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index 04ad4001a289..2fb9e63b8fc4 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c | |||
@@ -49,15 +49,19 @@ | |||
49 | #define VM_FAULT_BADCONTEXT 0x010000 | 49 | #define VM_FAULT_BADCONTEXT 0x010000 |
50 | #define VM_FAULT_BADMAP 0x020000 | 50 | #define VM_FAULT_BADMAP 0x020000 |
51 | #define VM_FAULT_BADACCESS 0x040000 | 51 | #define VM_FAULT_BADACCESS 0x040000 |
52 | #define VM_FAULT_SIGNAL 0x080000 | 52 | #define VM_FAULT_SIGNAL 0x080000 |
53 | 53 | ||
54 | static unsigned long store_indication; | 54 | static unsigned long store_indication __read_mostly; |
55 | 55 | ||
56 | void fault_init(void) | 56 | #ifdef CONFIG_64BIT |
57 | static int __init fault_init(void) | ||
57 | { | 58 | { |
58 | if (test_facility(2) && test_facility(75)) | 59 | if (test_facility(75)) |
59 | store_indication = 0xc00; | 60 | store_indication = 0xc00; |
61 | return 0; | ||
60 | } | 62 | } |
63 | early_initcall(fault_init); | ||
64 | #endif | ||
61 | 65 | ||
62 | static inline int notify_page_fault(struct pt_regs *regs) | 66 | static inline int notify_page_fault(struct pt_regs *regs) |
63 | { | 67 | { |
@@ -273,10 +277,16 @@ static inline int do_exception(struct pt_regs *regs, int access) | |||
273 | unsigned int flags; | 277 | unsigned int flags; |
274 | int fault; | 278 | int fault; |
275 | 279 | ||
280 | tsk = current; | ||
281 | /* | ||
282 | * The instruction that caused the program check has | ||
283 | * been nullified. Don't signal single step via SIGTRAP. | ||
284 | */ | ||
285 | clear_tsk_thread_flag(tsk, TIF_PER_TRAP); | ||
286 | |||
276 | if (notify_page_fault(regs)) | 287 | if (notify_page_fault(regs)) |
277 | return 0; | 288 | return 0; |
278 | 289 | ||
279 | tsk = current; | ||
280 | mm = tsk->mm; | 290 | mm = tsk->mm; |
281 | trans_exc_code = regs->int_parm_long; | 291 | trans_exc_code = regs->int_parm_long; |
282 | 292 | ||
@@ -372,11 +382,6 @@ retry: | |||
372 | goto retry; | 382 | goto retry; |
373 | } | 383 | } |
374 | } | 384 | } |
375 | /* | ||
376 | * The instruction that caused the program check will | ||
377 | * be repeated. Don't signal single step via SIGTRAP. | ||
378 | */ | ||
379 | clear_tsk_thread_flag(tsk, TIF_PER_TRAP); | ||
380 | fault = 0; | 385 | fault = 0; |
381 | out_up: | 386 | out_up: |
382 | up_read(&mm->mmap_sem); | 387 | up_read(&mm->mmap_sem); |
@@ -423,6 +428,12 @@ void __kprobes do_asce_exception(struct pt_regs *regs) | |||
423 | struct vm_area_struct *vma; | 428 | struct vm_area_struct *vma; |
424 | unsigned long trans_exc_code; | 429 | unsigned long trans_exc_code; |
425 | 430 | ||
431 | /* | ||
432 | * The instruction that caused the program check has | ||
433 | * been nullified. Don't signal single step via SIGTRAP. | ||
434 | */ | ||
435 | clear_tsk_thread_flag(current, TIF_PER_TRAP); | ||
436 | |||
426 | trans_exc_code = regs->int_parm_long; | 437 | trans_exc_code = regs->int_parm_long; |
427 | if (unlikely(!user_space_fault(trans_exc_code) || in_atomic() || !mm)) | 438 | if (unlikely(!user_space_fault(trans_exc_code) || in_atomic() || !mm)) |
428 | goto no_context; | 439 | goto no_context; |
@@ -558,7 +569,7 @@ static void pfault_interrupt(struct ext_code ext_code, | |||
558 | subcode = ext_code.subcode; | 569 | subcode = ext_code.subcode; |
559 | if ((subcode & 0xff00) != __SUBCODE_MASK) | 570 | if ((subcode & 0xff00) != __SUBCODE_MASK) |
560 | return; | 571 | return; |
561 | kstat_cpu(smp_processor_id()).irqs[EXTINT_PFL]++; | 572 | inc_irq_stat(IRQEXT_PFL); |
562 | /* Get the token (= pid of the affected task). */ | 573 | /* Get the token (= pid of the affected task). */ |
563 | pid = sizeof(void *) == 4 ? param32 : param64; | 574 | pid = sizeof(void *) == 4 ? param32 : param64; |
564 | rcu_read_lock(); | 575 | rcu_read_lock(); |