VServer 1.9.2 (patch-2.6.8.1-vs1.9.2.diff)
[linux-2.6.git] / arch / s390 / mm / fault.c
index 9cf3b39..8b2dda8 100644 (file)
@@ -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);
         }