X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fs390%2Fmm%2Ffault.c;h=9cf3b392ebf55bf761cf4f48010e29954e582cd5;hb=f9296eb00ed30209424102d3c920e69617eea853;hp=8b2dda88330799fd4eecca2e9b0f763458c36b36;hpb=a91482bdcc2e0f6035702e46f1b99043a0893346;p=linux-2.6.git diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index 8b2dda883..9cf3b392e 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c @@ -159,8 +159,7 @@ static void force_sigsegv(struct pt_regs *regs, unsigned long error_code, * 11 Page translation -> Not present (nullification) * 3b Region third trans. -> Not present (nullification) */ -extern inline void -do_exception(struct pt_regs *regs, unsigned long error_code, int is_protection) +extern inline void do_exception(struct pt_regs *regs, unsigned long error_code) { struct task_struct *tsk; struct mm_struct *mm; @@ -178,7 +177,7 @@ do_exception(struct pt_regs *regs, unsigned long error_code, int is_protection) * as a special case because the translation exception code * field is not guaranteed to contain valid data in this case. */ - if (is_protection && !(S390_lowcore.trans_exc_code & 4)) { + if (error_code == 4 && !(S390_lowcore.trans_exc_code & 4)) { /* Low-address protection hit in kernel mode means NULL pointer write access in kernel mode. */ @@ -233,7 +232,7 @@ do_exception(struct pt_regs *regs, unsigned long error_code, int is_protection) */ good_area: si_code = SEGV_ACCERR; - if (!is_protection) { + if (error_code != 4) { /* page not present, check vm flags */ if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE))) goto bad_area; @@ -248,7 +247,7 @@ survive: * make sure we exit gracefully rather than endlessly redo * the fault. */ - switch (handle_mm_fault(mm, vma, address, is_protection)) { + switch (handle_mm_fault(mm, vma, address, error_code == 4)) { case VM_FAULT_MINOR: tsk->min_flt++; break; @@ -264,11 +263,6 @@ survive: } up_read(&mm->mmap_sem); - /* - * The instruction that caused the program check will - * be repeated. Don't signal single step via SIGTRAP. - */ - clear_tsk_thread_flag(current, TIF_SINGLE_STEP); return; /* @@ -343,15 +337,28 @@ do_sigbus: void do_protection_exception(struct pt_regs *regs, unsigned long error_code) { regs->psw.addr -= (error_code >> 16); - do_exception(regs, 4, 1); + do_exception(regs, 4); } -void do_dat_exception(struct pt_regs *regs, unsigned long error_code) +void do_segment_exception(struct pt_regs *regs, unsigned long error_code) { - do_exception(regs, error_code & 0xff, 0); + do_exception(regs, 0x10); } -#ifndef CONFIG_ARCH_S390X +void do_page_exception(struct pt_regs *regs, unsigned long error_code) +{ + do_exception(regs, 0x11); +} + +#ifdef CONFIG_ARCH_S390X + +void +do_region_exception(struct pt_regs *regs, unsigned long error_code) +{ + do_exception(regs, 0x3b); +} + +#else /* CONFIG_ARCH_S390X */ typedef struct _pseudo_wait_t { struct _pseudo_wait_t *next; @@ -449,11 +456,6 @@ do_pseudo_page_fault(struct pt_regs *regs, unsigned long error_code) wait_struct.next = pseudo_lock_queue; pseudo_lock_queue = &wait_struct; spin_unlock(&pseudo_wait_spinlock); - /* - * The instruction that caused the program check will - * be repeated. Don't signal single step via SIGTRAP. - */ - clear_tsk_thread_flag(current, TIF_SINGLE_STEP); /* go to sleep */ wait_event(wait_struct.queue, wait_struct.resolved); }