patch-2.1.124 linux/arch/sparc64/mm/fault.c

Next file: linux/arch/sparc64/mm/init.c
Previous file: linux/arch/sparc64/mm/asyncd.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/mm/fault.c linux/arch/sparc64/mm/fault.c
@@ -1,4 +1,4 @@
-/* $Id: fault.c,v 1.21 1998/03/25 10:43:20 jj Exp $
+/* $Id: fault.c,v 1.24 1998/09/22 03:27:33 davem Exp $
  * arch/sparc64/mm/fault.c: Page fault handlers for the 64-bit Sparc.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -100,49 +100,38 @@
 	       (unsigned long) tsk->mm->context);
 	printk(KERN_ALERT "tsk->mm->pgd = %016lx\n",
 	       (unsigned long) tsk->mm->pgd);
+	lock_kernel();
 	die_if_kernel("Oops", regs);
-}
-
-asmlinkage int lookup_fault(unsigned long pc, unsigned long ret_pc, 
-			    unsigned long address)
-{
-	unsigned long g2;
-	int i;
-	unsigned insn;
-	struct pt_regs regs;
-	
-	i = search_exception_table (ret_pc, &g2);
-	switch (i) {
-	/* load & store will be handled by fixup */
-	case 3: return 3;
-	/* store will be handled by fixup, load will bump out */
-	/* for _to_ macros */
-	case 1: insn = *(unsigned *)pc; if ((insn >> 21) & 1) return 1; break;
-	/* load will be handled by fixup, store will bump out */
-	/* for _from_ macros */
-	case 2: insn = *(unsigned *)pc; 
-		if (!((insn >> 21) & 1) || ((insn>>19)&0x3f) == 15) return 2; 
-		break; 
-	default: break;
-	}
-	memset (&regs, 0, sizeof (regs));
-	regs.tpc = pc;
-	regs.tnpc = pc + 4;
-	/* FIXME: Should set up regs->tstate? */
-	unhandled_fault (address, current, &regs);
-	/* Not reached */
-	return 0;
+	unlock_kernel();
 }
 
 /* #define DEBUG_EXCEPTIONS */
+/* #define DEBUG_LOCKUPS */
 
 asmlinkage void do_sparc64_fault(struct pt_regs *regs, unsigned long address, int write)
 {
 	struct mm_struct *mm = current->mm;
 	struct vm_area_struct *vma;
+#ifdef DEBUG_LOCKUPS
+	static unsigned long lastaddr, lastpc;
+	static int lastwrite, lockcnt;
+#endif
 
-	lock_kernel();
 	down(&mm->mmap_sem);
+#ifdef DEBUG_LOCKUPS
+	if (regs->tpc == lastpc && address == lastaddr && write == lastwrite) {
+		lockcnt++;
+		if (lockcnt == 100000) {
+			printk("do_sparc64_fault: possible fault loop for %016lx %s\n", address, write ? "write" : "read");
+			show_regs(regs);
+		}
+	} else {
+		lastpc = regs->tpc;
+		lastaddr = address;
+		lastwrite = write;
+		lockcnt = 0;
+	}
+#endif
 	vma = find_vma(mm, address);
 	if(!vma)
 		goto bad_area;
@@ -167,7 +156,7 @@
 	}
 	handle_mm_fault(current, vma, address, write);
 	up(&mm->mmap_sem);
-	goto out;
+	return;
 	/*
 	 * Something tried to access memory that isn't in our memory map..
 	 * Fix it, but check if it's kernel or user first..
@@ -204,16 +193,14 @@
 				regs->tpc = fixup;
 				regs->tnpc = regs->tpc + 4;
 				regs->u_regs[UREG_G2] = g2;
-				goto out;
+				return;
 			}
 		} else {
 			current->tss.sig_address = address;
 			current->tss.sig_desc = SUBSIG_NOMAPPING;
 			force_sig(SIGSEGV, current);
-			goto out;
+			return;
 		}
 		unhandled_fault (address, current, regs);
 	}
-out:
-	unlock_kernel();
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov