X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;ds=sidebyside;f=arch%2Fs390%2Fmm%2Ffault.c;h=8b2dda88330799fd4eecca2e9b0f763458c36b36;hb=9bf4aaab3e101692164d49b7ca357651eb691cb6;hp=9cf3b392ebf55bf761cf4f48010e29954e582cd5;hpb=db216c3d5e4c040e557a50f8f5d35d5c415e8c1c;p=linux-2.6.git diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index 9cf3b392e..8b2dda883 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c @@ -159,7 +159,8 @@ 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) +extern inline void +do_exception(struct pt_regs *regs, unsigned long error_code, int is_protection) { struct task_struct *tsk; struct mm_struct *mm; @@ -177,7 +178,7 @@ extern inline void do_exception(struct pt_regs *regs, unsigned long error_code) * as a special case because the translation exception code * field is not guaranteed to contain valid data in this case. */ - if (error_code == 4 && !(S390_lowcore.trans_exc_code & 4)) { + if (is_protection && !(S390_lowcore.trans_exc_code & 4)) { /* Low-address protection hit in kernel mode means NULL pointer write access in kernel mode. */ @@ -232,7 +233,7 @@ extern inline void do_exception(struct pt_regs *regs, unsigned long error_code) */ good_area: si_code = SEGV_ACCERR; - if (error_code != 4) { + if (!is_protection) { /* page not present, check vm flags */ if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE))) goto bad_area; @@ -247,7 +248,7 @@ survive: * make sure we exit gracefully rather than endlessly redo * the fault. */ - switch (handle_mm_fault(mm, vma, address, error_code == 4)) { + switch (handle_mm_fault(mm, vma, address, is_protection)) { case VM_FAULT_MINOR: tsk->min_flt++; break; @@ -263,6 +264,11 @@ 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; /* @@ -337,28 +343,15 @@ do_sigbus: void do_protection_exception(struct pt_regs *regs, unsigned long error_code) { regs->psw.addr -= (error_code >> 16); - do_exception(regs, 4); + do_exception(regs, 4, 1); } -void do_segment_exception(struct pt_regs *regs, unsigned long error_code) +void do_dat_exception(struct pt_regs *regs, unsigned long error_code) { - do_exception(regs, 0x10); + do_exception(regs, error_code & 0xff, 0); } -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 */ +#ifndef CONFIG_ARCH_S390X typedef struct _pseudo_wait_t { struct _pseudo_wait_t *next; @@ -456,6 +449,11 @@ 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); }