patch-2.0.21-2.1.0 linux/arch/m68k/kernel/traps.c

Next file: linux/arch/m68k/lib/Makefile
Previous file: linux/arch/m68k/kernel/time.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file lx2.0/v2.0.21/linux/arch/m68k/kernel/traps.c linux/arch/m68k/kernel/traps.c
@@ -28,10 +28,10 @@
 #include <linux/string.h>
 #include <linux/linkage.h>
 
+#include <asm/setup.h>
 #include <asm/system.h>
 #include <asm/segment.h>
 #include <asm/traps.h>
-#include <asm/bootinfo.h>
 #include <asm/pgtable.h>
 #include <asm/machdep.h>
 
@@ -77,8 +77,7 @@
                 vectors[VEC_INT7] = nmihandler;
         }
 
-#ifdef CONFIG_FPSP_040
-	if (m68k_is040or060 == 4) {
+	if (CPU_IS_040) {
 		/* set up FPSP entry points */
 		asmlinkage void dz_vec(void) asm ("dz");
 		asmlinkage void inex_vec(void) asm ("inex");
@@ -101,38 +100,34 @@
 		vectors[VEC_LINE11] = fline_vec;
 		vectors[VEC_FPUNSUP] = unsupp_vec;
 	}
-#endif
-#ifdef CONFIG_IFPSP_060
-	if (m68k_is040or060 == 6) {
-	  /* set up IFPSP entry points */
- 	  asmlinkage void snan_vec(void) asm ("_060_fpsp_snan");
- 	  asmlinkage void operr_vec(void) asm ("_060_fpsp_operr");
- 	  asmlinkage void ovfl_vec(void) asm ("_060_fpsp_ovfl");
- 	  asmlinkage void unfl_vec(void) asm ("_060_fpsp_unfl");
- 	  asmlinkage void dz_vec(void) asm ("_060_fpsp_dz");
- 	  asmlinkage void inex_vec(void) asm ("_060_fpsp_inex");
- 	  asmlinkage void fline_vec(void) asm ("_060_fpsp_fline");
- 	  asmlinkage void unsupp_vec(void) asm ("_060_fpsp_unsupp");
- 	  asmlinkage void effadd_vec(void) asm ("_060_fpsp_effadd");
-  
- 	  asmlinkage void unimp_vec(void) asm ("_060_isp_unimp");
-  
- 	  vectors[VEC_FPNAN] = snan_vec;
- 	  vectors[VEC_FPOE] = operr_vec;
- 	  vectors[VEC_FPOVER] = ovfl_vec;
- 	  vectors[VEC_FPUNDER] = unfl_vec;
- 	  vectors[VEC_FPDIVZ] = dz_vec;
- 	  vectors[VEC_FPIR] = inex_vec;
- 	  vectors[VEC_LINE11] = fline_vec;
- 	  vectors[VEC_FPUNSUP] = unsupp_vec;
- 	  vectors[VEC_UNIMPEA] = effadd_vec;
-  
- 	  /* set up ISP entry points */
-  
- 	  vectors[VEC_UNIMPII] = unimp_vec;
-  
-  	}
-#endif
+	if (CPU_IS_060) {
+		/* set up IFPSP entry points */
+		asmlinkage void snan_vec(void) asm ("_060_fpsp_snan");
+		asmlinkage void operr_vec(void) asm ("_060_fpsp_operr");
+		asmlinkage void ovfl_vec(void) asm ("_060_fpsp_ovfl");
+		asmlinkage void unfl_vec(void) asm ("_060_fpsp_unfl");
+		asmlinkage void dz_vec(void) asm ("_060_fpsp_dz");
+		asmlinkage void inex_vec(void) asm ("_060_fpsp_inex");
+		asmlinkage void fline_vec(void) asm ("_060_fpsp_fline");
+		asmlinkage void unsupp_vec(void) asm ("_060_fpsp_unsupp");
+		asmlinkage void effadd_vec(void) asm ("_060_fpsp_effadd");
+
+		asmlinkage void unimp_vec(void) asm ("_060_isp_unimp");
+
+		vectors[VEC_FPNAN] = snan_vec;
+		vectors[VEC_FPOE] = operr_vec;
+		vectors[VEC_FPOVER] = ovfl_vec;
+		vectors[VEC_FPUNDER] = unfl_vec;
+		vectors[VEC_FPDIVZ] = dz_vec;
+		vectors[VEC_FPIR] = inex_vec;
+		vectors[VEC_LINE11] = fline_vec;
+		vectors[VEC_FPUNSUP] = unsupp_vec;
+		vectors[VEC_UNIMPEA] = effadd_vec;
+
+		/* set up ISP entry points */
+
+		vectors[VEC_UNIMPII] = unimp_vec;
+	}
 }
 
 void set_evector(int vecnum, void (*handler)(void))
@@ -176,10 +171,11 @@
 
 extern void die_if_kernel(char *,struct pt_regs *,int);
 asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
-			      unsigned long error_code);
+                             unsigned long error_code);
 
 asmlinkage void trap_c(struct frame *fp);
 
+#if defined (CONFIG_M68060)
 static inline void access_error060 (struct frame *fp)
 {
 	unsigned long fslw = fp->un.fmt4.pc; /* is really FSLW for access error */
@@ -208,7 +204,7 @@
 		printk("errorcode = %d\n", errorcode );
 #endif
 		if (fslw & MMU060_MA)
-		  addr = PAGE_ALIGN(addr);
+			addr = PAGE_ALIGN(addr);
 		do_page_fault( (struct pt_regs *)fp, addr, errorcode );
 	}
 	else {
@@ -216,7 +212,9 @@
 		trap_c( fp );
 	}
 }
+#endif /* CONFIG_M68060 */
 
+#if defined (CONFIG_M68040)
 static unsigned long probe040 (int iswrite, int fc, unsigned long addr)
 {
 	unsigned long mmusr;
@@ -224,8 +222,8 @@
 
 	set_fs (fc);
 
-  	if (iswrite)
-  		/* write */
+	if (iswrite)
+		/* write */
 		asm volatile ("movel %1,%/a0\n\t"
 			      ".word 0xf548\n\t"	/* ptestw (a0) */
 			      ".long 0x4e7a8805\n\t"	/* movec mmusr,a0 */
@@ -242,7 +240,6 @@
 			      : "g" (addr)
 			      : "a0");
 
-
 	set_fs (fs);
 
 	return mmusr;
@@ -351,14 +348,19 @@
 				 fp->un.fmt7.wb3a, fp->un.fmt7.wb3d,
 				 fp);
 }
+#endif /* CONFIG_M68040 */
 
+#if defined(CONFIG_M68020_OR_M68030)
 static inline void bus_error030 (struct frame *fp)
 {
 	volatile unsigned short temp;
 	unsigned short mmusr;
-	unsigned long addr, desc, errorcode;
+	unsigned long addr, errorcode;
 	unsigned short ssw = fp->un.fmtb.ssw;
 	int user_space_fault = 1;
+#if DEBUG
+	unsigned long desc;
+#endif
 
 #if DEBUG
 	printk ("pid = %x  ", current->pid);
@@ -414,14 +416,20 @@
 	  {
 	    addr = fp->un.fmtb.daddr;
 
+	    mmusr = MMU_I;
 	    if (user_space_fault) {
+#if DEBUG
 		    asm volatile ("ptestr #1,%2@,#7,%0\n\t"
 				  "pmove %/psr,%1@"
 				  : "=a&" (desc)
 				  : "a" (&temp), "a" (addr));
+#else
+		    asm volatile ("ptestr #1,%1@,#7\n\t"
+				  "pmove %/psr,%0@"
+				  : : "a" (&temp), "a" (addr));
+#endif
 		    mmusr = temp;
-	    } else
-		    mmusr = MMU_I;
+	    }
       
 #if DEBUG
 	    printk ("mmusr is %#x for addr %#lx in task %p\n",
@@ -431,16 +439,10 @@
 #endif
 
 	    errorcode = (mmusr & MMU_I) ? 0 : 1;
-	      /* if (!(ssw & RW)) updated to 1.2.13pl6 */
- 	    if (!(ssw & RW) || ssw & RM)
+	    if (!(ssw & RW) || ssw & RM)
 		    errorcode |= 2;
 
-	    if (mmusr & MMU_I)
-		    do_page_fault ((struct pt_regs *)fp, addr, errorcode);
-
-	    /* else if ((mmusr & MMU_WP) && !(ssw & RW)) */
-
- 	    else if ((mmusr & MMU_WP) && (!(ssw & RW) || ssw & RM))
+	    if (mmusr & (MMU_I | MMU_WP))
 		    do_page_fault ((struct pt_regs *)fp, addr, errorcode);
 	    else if (mmusr & (MMU_B|MMU_L|MMU_S)) {
 		    printk ("invalid %s access at %#lx from pc %#lx\n",
@@ -450,7 +452,7 @@
 		    force_sig(SIGSEGV, current);
 		    return;
 	    } else {
-#ifdef DEBUG
+#if 0
 		    static volatile long tlong;
 #endif
 
@@ -484,12 +486,13 @@
 
 	    /* setup an ATC entry for the access about to be retried */
 	    if (!(ssw & RW))
-		    asm volatile ("ploadw #1,%0@" : /* no outputs */
-				  : "a" (addr));
+		    asm volatile ("ploadw %1,%0@" : /* no outputs */
+				  : "a" (addr), "d" (ssw));
 	    else
-		    asm volatile ("ploadr #1,%0@" : /* no outputs */
-				  : "a" (addr));
+		    asm volatile ("ploadr %1,%0@" : /* no outputs */
+				  : "a" (addr), "d" (ssw));
 
+#if 0
 	    /* If this was a data fault due to an invalid page and a
 	       prefetch is pending on the same page, simulate it (but
 	       only if the page is now valid).  Otherwise we'll get an
@@ -525,38 +528,41 @@
 		      }
 		  }
 	      }
+#endif
 	  }
 
 	/* Now handle the instruction fault. */
 
+	if (!(ssw & (FC|FB)))
+		return;
+
 	/* get the fault address */
-	if ((fp->ptregs.format) == 0xA )
-		if (ssw & FC)
-			addr = fp->ptregs.pc + 2;
-		else if (ssw & FB)
-			addr = fp->ptregs.pc + 4;
-		else
-			return;
+	if (fp->ptregs.format == 10)
+		addr = fp->ptregs.pc + 4;
 	else
-		if (ssw & FC)
-			addr = fp->un.fmtb.baddr - 2;
-		else if (ssw & FB)
-			addr = fp->un.fmtb.baddr;
-		else
-			return;
+		addr = fp->un.fmtb.baddr;
+	if (ssw & FC)
+		addr -= 2;
 
 	if ((ssw & DF) && ((addr ^ fp->un.fmtb.daddr) & PAGE_MASK) == 0)
-		/* Insn fault on same page as data fault */
-		return;
+		/* Insn fault on same page as data fault.  But we
+		   should still create the ATC entry.  */
+		goto create_atc_entry;
 
+	mmusr = MMU_I;
 	if (user_space_fault) {
+#if DEBUG
 		asm volatile ("ptestr #1,%2@,#7,%0\n\t"
 			      "pmove %/psr,%1@"
 			      : "=a&" (desc)
 			      : "a" (&temp), "a" (addr));
+#else
+		asm volatile ("ptestr #1,%1@,#7\n\t"
+			      "pmove %/psr,%0@"
+			      : : "a" (&temp), "a" (addr));
+#endif
 		mmusr = temp;
-	} else
-		mmusr = MMU_I;
+	}
       
 #ifdef DEBUG
 	printk ("mmusr is %#x for addr %#lx in task %p\n",
@@ -565,10 +571,8 @@
 		mm_ptov(desc), *(unsigned long *)mm_ptov(desc));
 #endif
 
-	errorcode = (mmusr & MMU_I) ? 0 : 1;
-
 	if (mmusr & MMU_I)
-		do_page_fault ((struct pt_regs *)fp, addr, errorcode);
+		do_page_fault ((struct pt_regs *)fp, addr, 0);
 	else if (mmusr & (MMU_B|MMU_L|MMU_S)) {
 		printk ("invalid insn access at %#lx from pc %#lx\n",
 			addr, fp->ptregs.pc);
@@ -579,6 +583,8 @@
 		force_sig(SIGSEGV, current);
 		return;
 	} else {
+#if 0 /* stale ATC entry??  Ignore it */
+
 #ifdef DEBUG
 		static volatile long tlong;
 #endif
@@ -605,18 +611,22 @@
 		}
 
 #endif
+
 #if DEBUG
 		printk("Unknown SIGSEGV - 3\n");
 #endif
 		die_if_kernel("Oops",&fp->ptregs,mmusr);
 		force_sig(SIGSEGV, current);
 		return;
+#endif
 	}
 
+create_atc_entry:
 	/* setup an ATC entry for the access about to be retried */
-	asm volatile ("ploadr #1,%0@" : /* no outputs */
+	asm volatile ("ploadr #2,%0@" : /* no outputs */
 		      : "a" (addr));
 }
+#endif /* CONFIG_M68020_OR_M68030 */
 
 asmlinkage void buserr_c(struct frame *fp)
 {
@@ -629,16 +639,22 @@
 #endif
 
 	switch (fp->ptregs.format) {
+#if defined (CONFIG_M68060)
 	case 4:				/* 68060 access error */
 	  access_error060 (fp);
 	  break;
+#endif
+#if defined (CONFIG_M68040)
 	case 0x7:			/* 68040 access error */
 	  access_error040 (fp);
 	  break;
+#endif
+#if defined (CONFIG_M68020_OR_M68030)
 	case 0xa:
 	case 0xb:
 	  bus_error030 (fp);
 	  break;
+#endif
 	default:
 	  die_if_kernel("bad frame format",&fp->ptregs,0);
 #if DEBUG
@@ -673,7 +689,7 @@
 	    addr += sizeof(fp->un.fmt3);
 	    break;
 	case 0x4:
-	    printk((m68k_is040or060 == 6 ? "fault addr=%08lx fslw=%08lx\n"
+	    printk((CPU_IS_060 ? "fault addr=%08lx fslw=%08lx\n"
 		    : "eff addr=%08lx pc=%08lx\n"),
 		   fp->un.fmt4.effaddr, fp->un.fmt4.pc);
 	    addr += sizeof(fp->un.fmt4);
@@ -767,8 +783,7 @@
 		printk ("*** Exception %d ***   FORMAT=%X\n",
 			(fp->ptregs.vector) >> 2, 
 			fp->ptregs.format);
-	if (((fp->ptregs.vector) >> 2) == VEC_ADDRERR
-	    && !m68k_is040or060) {
+	if (fp->ptregs.vector >> 2 == VEC_ADDRERR && CPU_IS_020_OR_030) {
 		unsigned short ssw = fp->un.fmtb.ssw;
 
 		printk ("SSW=%#06x  ", ssw);
@@ -871,7 +886,7 @@
 		break;
 	}
 
-	force_sig (sig, current);
+	send_sig (sig, current, 1);
 }
 
 asmlinkage void set_esp0 (unsigned long ssp)

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