4m memory fault traps: simplify fault address logic, since per-CPU
fault-status reading stubs pre-cook the arguments. illegal instruction trap: catch iflush instructions that cause this trap on some CPU/MMU combinations.
This commit is contained in:
parent
01e424f233
commit
92d853e309
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: trap.c,v 1.50 1996/12/01 23:21:07 pk Exp $ */
|
||||
/* $NetBSD: trap.c,v 1.51 1997/03/11 01:20:25 pk Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1996
|
||||
|
@ -84,6 +84,7 @@
|
|||
|
||||
#include <sparc/fpu/fpu_extern.h>
|
||||
#include <sparc/sparc/memreg.h>
|
||||
#include <sparc/sparc/cpuvar.h>
|
||||
|
||||
#define offsetof(s, f) ((int)&((s *)0)->f)
|
||||
|
||||
|
@ -190,6 +191,8 @@ static int fixalign __P((struct proc *, struct trapframe *));
|
|||
void mem_access_fault __P((unsigned, int, u_int, int, int, struct trapframe *));
|
||||
void mem_access_fault4m __P((unsigned, u_int, u_int, u_int, u_int, struct trapframe *));
|
||||
void syscall __P((register_t, struct trapframe *, register_t));
|
||||
int trap_instr __P((int, struct trapframe *));
|
||||
static int decode_address __P((int, struct trapframe *));
|
||||
|
||||
/*
|
||||
* Define the code needed before returning to user mode, for
|
||||
|
@ -241,6 +244,68 @@ userret(p, pc, oticks)
|
|||
curpriority = p->p_priority;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode a trapped instruction to see if we should do
|
||||
* something about it.
|
||||
*/
|
||||
int
|
||||
trap_instr(pc, tf)
|
||||
register int pc;
|
||||
register struct trapframe *tf;
|
||||
{
|
||||
union instr instr;
|
||||
|
||||
if (copyin((caddr_t)pc, &instr, sizeof(instr)) != 0)
|
||||
return(0);
|
||||
|
||||
if (instr.i_any.i_op == 2 &&
|
||||
instr.i_op3.i_op3 == IOP3_FLUSH) {
|
||||
int addr = decode_address(instr.i_int, tf);
|
||||
cpuinfo.cache_flush((caddr_t)addr, 4); /*XXX*/
|
||||
return(1);
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get source address from an `op3' instruction.
|
||||
*/
|
||||
static int
|
||||
decode_address(instruction, tf)
|
||||
int instruction;
|
||||
struct trapframe *tf;
|
||||
{
|
||||
union instr instr;
|
||||
int addr, i, rs[2], offset;
|
||||
|
||||
instr.i_int = instruction;
|
||||
rs[0] = instr.i_op3.i_rs1;
|
||||
i = instr.i_simm13.i_i;
|
||||
if (i) {
|
||||
rs[1] = 0;
|
||||
offset = instr.i_simm13.i_simm13;
|
||||
} else {
|
||||
rs[1] = instr.i_op3.i_low14 & 0x1f;
|
||||
offset = 0;
|
||||
}
|
||||
for (addr = 0, i = 0; i < 2; i++) {
|
||||
int r = rs[i];
|
||||
if (r < 16) {
|
||||
addr += r == 0 ? 0 : tf->tf_global[r];
|
||||
} else {
|
||||
struct rwindow rwindow;
|
||||
write_user_windows();
|
||||
/* Copy frame from user stack */
|
||||
if (copyin((caddr_t)tf->tf_out[6],
|
||||
&rwindow, sizeof(rwindow)) != 0)
|
||||
return (-1);
|
||||
addr += rwindow.rw_local[r];
|
||||
}
|
||||
}
|
||||
return (addr + offset);
|
||||
}
|
||||
|
||||
/*
|
||||
* If someone stole the FPU while we were away, do not enable it
|
||||
* on return. This is not done in userret() above as it must follow
|
||||
|
@ -309,7 +374,12 @@ trap(type, psr, pc, tf)
|
|||
ADVANCE;
|
||||
return;
|
||||
}
|
||||
goto dopanic;
|
||||
dopanic:
|
||||
printf("trap type 0x%x: pc=%x npc=%x psr=%s\n",
|
||||
type, pc, tf->tf_npc, bitmask_snprintf(psr,
|
||||
PSR_BITS, bits, sizeof(bits)));
|
||||
panic(type < N_TRAP_TYPES ? trap_type[type] : T);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
if ((p = curproc) == NULL)
|
||||
p = &proc0;
|
||||
|
@ -321,12 +391,15 @@ trap(type, psr, pc, tf)
|
|||
|
||||
default:
|
||||
if (type < 0x80) {
|
||||
dopanic:
|
||||
#ifdef SUSTAIN_BOGUS_TRAPS
|
||||
if (0)
|
||||
#endif
|
||||
goto dopanic;
|
||||
printf("trap type 0x%x: pc=%x npc=%x psr=%s\n",
|
||||
type, pc, tf->tf_npc, bitmask_snprintf(psr,
|
||||
PSR_BITS, bits, sizeof(bits)));
|
||||
panic(type < N_TRAP_TYPES ? trap_type[type] : T);
|
||||
/* NOTREACHED */
|
||||
trapsignal(p, SIGILL, type);
|
||||
break;
|
||||
}
|
||||
#if defined(COMPAT_SVR4)
|
||||
badtrap:
|
||||
|
@ -355,6 +428,10 @@ badtrap:
|
|||
break; /* the work is all in userret() */
|
||||
|
||||
case T_ILLINST:
|
||||
if (trap_instr(pc, tf)) {
|
||||
ADVANCE;
|
||||
break;
|
||||
}
|
||||
trapsignal(p, SIGILL, 0); /* XXX code?? */
|
||||
break;
|
||||
|
||||
|
@ -789,9 +866,6 @@ mem_access_fault4m(type, sfsr, sfva, afsr, afva, tf)
|
|||
int onfault;
|
||||
u_quad_t sticks;
|
||||
char bits[64];
|
||||
#if DEBUG
|
||||
static int lastdouble;
|
||||
#endif
|
||||
|
||||
cnt.v_trap++;
|
||||
if ((p = curproc) == NULL) /* safety check */
|
||||
|
@ -818,7 +892,7 @@ static int lastdouble;
|
|||
memerr4m(type, sfsr, sfva, afsr, afva, tf);
|
||||
/*
|
||||
* If we get here, exit the trap handler and wait for the
|
||||
* trap to reoccur
|
||||
* trap to re-occur.
|
||||
*/
|
||||
goto out;
|
||||
}
|
||||
|
@ -848,26 +922,12 @@ static int lastdouble;
|
|||
goto out; /* No fault. Why were we called? */
|
||||
|
||||
/*
|
||||
* This next section is a mess since some chips use sfva, and others
|
||||
* don't on text faults. We want to use sfva where possible, since
|
||||
* we _could_ be dealing with an ASI 0x8,0x9 data access to text space,
|
||||
* which would trap as a text fault, at least on a HyperSPARC. Ugh.
|
||||
* XXX: Find out about MicroSPARCs.
|
||||
* NOTE: the per-CPU fault status register readers (in locore)
|
||||
* may already have decided to pass `pc' in `sfva', so we avoid
|
||||
* testing CPU types here.
|
||||
* Q: test SFSR_FAV in the locore stubs too?
|
||||
*/
|
||||
|
||||
if (type == T_TEXTFAULT && mmumod == SUN4M_MMU_SS &&
|
||||
(cpumod & 0xf0) == (SUN4M_SS) && (sfsr & SFSR_FAV)) {
|
||||
sfva = pc; /* can't trust fav on supersparc/text fault */
|
||||
} else if (type == T_TEXTFAULT && mmumod != SUN4M_MMU_HS) {
|
||||
sfva = pc;
|
||||
} else if (!(sfsr & SFSR_FAV)) {
|
||||
#ifdef DEBUG
|
||||
if (type != T_TEXTFAULT)
|
||||
printf("mem_access_fault: got fault without valid SFVA\n");
|
||||
if (mmumod == SUN4M_MMU_HS)
|
||||
printf("mem_access_fault: got fault without valid SFVA on "
|
||||
"HyperSPARC!\n");
|
||||
#endif
|
||||
if ((sfsr & SFSR_FAV) == 0) {
|
||||
if (type == T_TEXTFAULT)
|
||||
sfva = pc;
|
||||
else
|
||||
|
@ -876,7 +936,7 @@ static int lastdouble;
|
|||
|
||||
if ((sfsr & SFSR_FT) == SFSR_FT_TRANSERR) {
|
||||
/* Translation errors are always fatal, as they indicate
|
||||
* a corrupt translation (page) table heirarchy.
|
||||
* a corrupt translation (page) table hierarchy.
|
||||
*/
|
||||
if (tfaultaddr == sfva) /* Prevent infinite loops w/a static */
|
||||
goto fault;
|
||||
|
@ -889,41 +949,17 @@ static int lastdouble;
|
|||
|
||||
va = trunc_page(sfva);
|
||||
|
||||
#ifdef DEBUG
|
||||
if (lastdouble) {
|
||||
printf("stacked tfault @ %x (pc %x); sfsr %x", sfva, pc, sfsr);
|
||||
lastdouble = 0;
|
||||
if (curproc == NULL)
|
||||
printf("NULL proc\n");
|
||||
else
|
||||
printf("pid %d(%s); sigmask %x, sigcatch %x\n",
|
||||
curproc->p_pid, curproc->p_comm,
|
||||
curproc->p_sigmask, curproc->p_sigcatch);
|
||||
}
|
||||
#endif
|
||||
if (((sfsr & SFSR_AT_TEXT) || type == T_TEXTFAULT) &&
|
||||
!(sfsr & SFSR_AT_STORE) && (sfsr & SFSR_OW)) {
|
||||
if (psr & PSR_PS) /* never allow in kernel */
|
||||
goto kfault;
|
||||
#if 0
|
||||
/*
|
||||
* Double text fault. The evil "case 5" from the HS manual...
|
||||
* Attempt to handle early fault. Ignores ASI 8,9 issue...may
|
||||
* do a useless VM read.
|
||||
* XXX: Is this really necessary?
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
if (dfdebug) {
|
||||
lastdouble = 1;
|
||||
printf("mem_access_fault: double text fault @ %x (pc %x); sfsr %x",
|
||||
sfva, pc, sfsr);
|
||||
if (curproc == NULL)
|
||||
printf("NULL proc\n");
|
||||
else
|
||||
printf(" pid %d(%s); sigmask %x, sigcatch %x\n",
|
||||
curproc->p_pid, curproc->p_comm,
|
||||
curproc->p_sigmask, curproc->p_sigcatch);
|
||||
}
|
||||
#endif
|
||||
if (mmumod == SUN4M_MMU_HS) { /* On HS, we have va for both */
|
||||
if (vm_fault(kernel_map, trunc_page(pc),
|
||||
VM_PROT_READ, 0) != KERN_SUCCESS)
|
||||
|
@ -933,6 +969,7 @@ static int lastdouble;
|
|||
#endif
|
||||
;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Now munch on protections... */
|
||||
|
@ -980,7 +1017,7 @@ static int lastdouble;
|
|||
rv = mmu_pagein4m(&vm->vm_pmap, va,
|
||||
sfsr & SFSR_AT_STORE ? VM_PROT_WRITE : VM_PROT_READ);
|
||||
if (rv < 0)
|
||||
printf(" sfsr=%x(FT=%x,AT=%x,LVL=%x), sfva=%x, pc=%x, psr=%x\n",
|
||||
uprintf(" sfsr=%x(FT=%x,AT=%x,LVL=%x), sfva=%x, pc=%x, psr=%x\n",
|
||||
sfsr, (sfsr >> 2) & 7, (sfsr >> 5) & 7, (sfsr >> 8) & 3,
|
||||
sfva, pc, psr);
|
||||
if (rv > 0)
|
||||
|
|
Loading…
Reference in New Issue