patch-2.2.16 linux/arch/s390/mm/fault.c

Next file: linux/arch/s390/mm/init.c
Previous file: linux/arch/s390/lib/strncpy.S
Back to the patch index
Back to the overall index

diff -urN v2.2.15/linux/arch/s390/mm/fault.c linux/arch/s390/mm/fault.c
@@ -65,12 +65,12 @@
 
         address = S390_lowcore.trans_exc_code&0x7ffff000;
 
-        if (atomic_read(&S390_lowcore.local_irq_count))
-                die("page fault from irq handler",regs,error_code);
-
         tsk = current;
         mm = tsk->mm;
 
+        if (atomic_read(&S390_lowcore.local_irq_count))
+                die("page fault from irq handler",regs,error_code);
+
         down(&mm->mmap_sem);
 
         vma = find_vma(mm, address);
@@ -116,7 +116,20 @@
                        printk("code should be 4, 10 or 11 (%lX) \n",error_code&0xFF);  
                        goto bad_area;
         }
-        handle_mm_fault(tsk, vma, address, write);
+
+	/*
+	 * If for any reason at all we couldn't handle the fault,
+	 * make sure we exit gracefully rather than endlessly redo
+	 * the fault.
+	 */
+survive:
+	{
+	  int fault = handle_mm_fault(tsk, vma, address, write);
+	  if (!fault)
+		  goto do_sigbus;
+	  if (fault < 0)
+		  goto out_of_memory;
+	}
 
         up(&mm->mmap_sem);
         return;
@@ -141,8 +154,8 @@
                 return;
 	}
 
+ no_context:
         /* Are we prepared to handle this kernel fault?  */
-
         if ((fixup = search_exception_table(regs->psw.addr)) != 0) {
                 regs->psw.addr = fixup;
                 return;
@@ -163,41 +176,43 @@
  * need to define, which information is useful here
  */
 
-        lock_kernel();
         die("Oops", regs, error_code);
         do_exit(SIGKILL);
-        unlock_kernel();
-}
+
 
 /*
+ * We ran out of memory, or some other thing happened to us that made
+ * us unable to handle the page fault gracefully.
+ */
+out_of_memory:
+	if (tsk->pid == 1)
                 {
-		  char c;
-                  int i,j;
-		  char *addr;
-		  addr = ((char*) psw_addr)-0x20;
-		  for (i=0;i<16;i++) {
-		    if (i == 2)
-		      printk("\n");
-		    printk ("%08X:    ",(unsigned long) addr);
-		    for (j=0;j<4;j++) {
-		      printk("%08X ",*(unsigned long*)addr);
-		      addr += 4;
-		    }
-		    addr -=0x10;
-		    printk(" | ");
-		    for (j=0;j<16;j++) {
-		      printk("%c",(c=*addr++) < 0x20 ? '.' : c );
+		tsk->policy |= SCHED_YIELD;
+		schedule();
+		goto survive;
 		    }
-
-		    printk("\n");
-		  }
-                  printk("\n");
+	up(&mm->mmap_sem);
+	if (psw_mask & PSW_PROBLEM_STATE)
+	{
+		printk("VM: killing process %s\n", tsk->comm);
+		do_exit(SIGKILL);
                 }
+	goto no_context;
 
-*/
-
-
-
-
+do_sigbus:
+	up(&mm->mmap_sem);
 
+	/*
+	 * Send a sigbus, regardless of whether we were in kernel
+	 * or user mode.
+	 */
+        tsk->tss.prot_addr = address;
+        tsk->tss.error_code = error_code;
+        tsk->tss.trap_no = 14;
+	force_sig(SIGBUS, tsk);
+
+	/* Kernel mode? Handle exceptions or die */
+	if (!(psw_mask & PSW_PROBLEM_STATE))
+		goto no_context;
+}
 

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)