diff options
Diffstat (limited to 'arch/s390/mm/fault.c')
-rw-r--r-- | arch/s390/mm/fault.c | 46 |
1 files changed, 2 insertions, 44 deletions
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index fc6679210d83..d95265b2719f 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c | |||
@@ -115,13 +115,8 @@ static inline int user_space_fault(unsigned long trans_exc_code) | |||
115 | if (trans_exc_code == 2) | 115 | if (trans_exc_code == 2) |
116 | /* Access via secondary space, set_fs setting decides */ | 116 | /* Access via secondary space, set_fs setting decides */ |
117 | return current->thread.mm_segment.ar4; | 117 | return current->thread.mm_segment.ar4; |
118 | if (s390_user_mode == HOME_SPACE_MODE) | ||
119 | /* User space if the access has been done via home space. */ | ||
120 | return trans_exc_code == 3; | ||
121 | /* | 118 | /* |
122 | * If the user space is not the home space the kernel runs in home | 119 | * Access via primary space or access register is from user space |
123 | * space. Access via secondary space has already been covered, | ||
124 | * access via primary space or access register is from user space | ||
125 | * and access via home space is from the kernel. | 120 | * and access via home space is from the kernel. |
126 | */ | 121 | */ |
127 | return trans_exc_code != 3; | 122 | return trans_exc_code != 3; |
@@ -428,50 +423,13 @@ void __kprobes do_dat_exception(struct pt_regs *regs) | |||
428 | do_fault_error(regs, fault); | 423 | do_fault_error(regs, fault); |
429 | } | 424 | } |
430 | 425 | ||
431 | #ifdef CONFIG_64BIT | ||
432 | void __kprobes do_asce_exception(struct pt_regs *regs) | ||
433 | { | ||
434 | struct mm_struct *mm = current->mm; | ||
435 | struct vm_area_struct *vma; | ||
436 | unsigned long trans_exc_code; | ||
437 | |||
438 | /* | ||
439 | * The instruction that caused the program check has | ||
440 | * been nullified. Don't signal single step via SIGTRAP. | ||
441 | */ | ||
442 | clear_tsk_thread_flag(current, TIF_PER_TRAP); | ||
443 | |||
444 | trans_exc_code = regs->int_parm_long; | ||
445 | if (unlikely(!user_space_fault(trans_exc_code) || in_atomic() || !mm)) | ||
446 | goto no_context; | ||
447 | |||
448 | down_read(&mm->mmap_sem); | ||
449 | vma = find_vma(mm, trans_exc_code & __FAIL_ADDR_MASK); | ||
450 | up_read(&mm->mmap_sem); | ||
451 | |||
452 | if (vma) { | ||
453 | update_mm(mm, current); | ||
454 | return; | ||
455 | } | ||
456 | |||
457 | /* User mode accesses just cause a SIGSEGV */ | ||
458 | if (user_mode(regs)) { | ||
459 | do_sigsegv(regs, SEGV_MAPERR); | ||
460 | return; | ||
461 | } | ||
462 | |||
463 | no_context: | ||
464 | do_no_context(regs); | ||
465 | } | ||
466 | #endif | ||
467 | |||
468 | int __handle_fault(unsigned long uaddr, unsigned long pgm_int_code, int write) | 426 | int __handle_fault(unsigned long uaddr, unsigned long pgm_int_code, int write) |
469 | { | 427 | { |
470 | struct pt_regs regs; | 428 | struct pt_regs regs; |
471 | int access, fault; | 429 | int access, fault; |
472 | 430 | ||
473 | /* Emulate a uaccess fault from kernel mode. */ | 431 | /* Emulate a uaccess fault from kernel mode. */ |
474 | regs.psw.mask = psw_kernel_bits | PSW_MASK_DAT | PSW_MASK_MCHECK; | 432 | regs.psw.mask = PSW_KERNEL_BITS | PSW_MASK_DAT | PSW_MASK_MCHECK; |
475 | if (!irqs_disabled()) | 433 | if (!irqs_disabled()) |
476 | regs.psw.mask |= PSW_MASK_IO | PSW_MASK_EXT; | 434 | regs.psw.mask |= PSW_MASK_IO | PSW_MASK_EXT; |
477 | regs.psw.addr = (unsigned long) __builtin_return_address(0); | 435 | regs.psw.addr = (unsigned long) __builtin_return_address(0); |