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

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

diff -urN linux-2.4.18/arch/sparc64/mm/fault.c linux-2.4.19/arch/sparc64/mm/fault.c
@@ -1,4 +1,4 @@
-/* $Id: fault.c,v 1.58 2001/09/01 00:11:16 kanoj Exp $
+/* $Id: fault.c,v 1.58.2.2 2002/03/12 12:25:15 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)
@@ -55,13 +55,21 @@
  */
 void set_brkpt(unsigned long addr, unsigned char mask, int flags, int mode)
 {
-	unsigned long lsubits = LSU_CONTROL_IC|LSU_CONTROL_DC|LSU_CONTROL_IM|LSU_CONTROL_DM;
+	unsigned long lsubits;
+
+	__asm__ __volatile__("ldxa [%%g0] %1, %0"
+			     : "=r" (lsubits)
+			     : "i" (ASI_LSU_CONTROL));
+	lsubits &= ~(LSU_CONTROL_PM | LSU_CONTROL_VM |
+		     LSU_CONTROL_PR | LSU_CONTROL_VR |
+		     LSU_CONTROL_PW | LSU_CONTROL_VW);
 
 	__asm__ __volatile__("stxa	%0, [%1] %2\n\t"
 			     "membar	#Sync"
 			     : /* no outputs */
 			     : "r" (addr), "r" (mode ? VIRT_WATCHPOINT : PHYS_WATCHPOINT),
 			       "i" (ASI_DMMU));
+
 	lsubits |= ((unsigned long)mask << (mode ? 25 : 33));
 	if (flags & VM_READ)
 		lsubits |= (mode ? LSU_CONTROL_VR : LSU_CONTROL_PR);
@@ -340,6 +348,20 @@
 		goto good_area;
 	if (!(vma->vm_flags & VM_GROWSDOWN))
 		goto bad_area;
+	if (!(fault_code & FAULT_CODE_WRITE)) {
+		/* Non-faulting loads shouldn't expand stack. */
+		insn = get_fault_insn(regs, insn);
+		if ((insn & 0xc0800000) == 0xc0800000) {
+			unsigned char asi;
+
+			if (insn & 0x2000)
+				asi = (regs->tstate >> 24);
+			else
+				asi = (insn >> 5);
+			if ((asi & 0xf2) == 0x82)
+				goto bad_area;
+		}
+	}
 	if (expand_stack(vma, address))
 		goto bad_area;
 	/*

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