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
- Lines: 385
- Date:
Wed Sep 25 10:47:40 1996
- Orig file:
lx2.0/v2.0.21/linux/arch/m68k/kernel/traps.c
- Orig date:
Mon May 20 07:54:26 1996
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