File: [cvs.NetBSD.org] / src / sys / arch / sh3 / sh3 / Attic / trap.c (download)
Revision 1.14, Wed Jun 7 11:34:17 2000 UTC (20 years, 7 months ago) by tsubai
Branch: MAIN
CVS Tags: netbsd-1-5-base, netbsd-1-5-ALPHA2 Branch point for: netbsd-1-5
Changes since 1.13: +8 -8
lines
child_return() should take void *arg.
|
/* $NetBSD: trap.c,v 1.14 2000/06/07 11:34:17 tsubai Exp $ */
/*-
* Copyright (c) 1995 Charles M. Hannum. All rights reserved.
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* the University of Utah, and William Jolitz.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)trap.c 7.4 (Berkeley) 5/13/91
*/
#define RECURSE_TLB_HANDLER
/*
* SH3 Trap and System call handling
*
* T.Horiuchi 1998.06.8
*/
#include "opt_ddb.h"
#include "opt_syscall_debug.h"
#include "opt_ktrace.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/proc.h>
#include <sys/user.h>
#include <sys/acct.h>
#include <sys/kernel.h>
#include <sys/signal.h>
#ifdef KTRACE
#include <sys/ktrace.h>
#endif
#include <sys/syscall.h>
#include <vm/vm.h>
#include <sh3/trapreg.h>
#include <machine/cpu.h>
#include <machine/cpufunc.h>
#include <machine/psl.h>
#include <machine/reg.h>
#include <machine/trap.h>
#ifdef DDB
#include <machine/db_machdep.h>
#endif
#ifdef KGDB
#include <sys/kgdb.h>
#endif
extern int cpu_debug_mode;
static __inline void userret __P((struct proc *, int, u_quad_t));
void trap __P((int, int, int, int, struct trapframe));
int trapwrite __P((unsigned));
void syscall __P((struct trapframe *));
void
tlb_handler __P((
int p1, int p2, int p3, int p4, /* These four param is dummy */
struct trapframe frame));
/*
* Define the code needed before returning to user mode, for
* trap and syscall.
*/
static __inline void
userret(p, pc, oticks)
register struct proc *p;
int pc;
u_quad_t oticks;
{
int sig;
/* take pending signals */
while ((sig = CURSIG(p)) != 0)
postsig(sig);
p->p_priority = p->p_usrpri;
if (want_resched) {
/*
* We are being preempted.
*/
preempt(NULL);
while ((sig = CURSIG(p)) != 0)
postsig(sig);
}
/*
* If profiling, charge recent system time to the trapped pc.
*/
if (p->p_flag & P_PROFIL) {
extern int psratio;
addupc_task(p, pc, (int)(p->p_sticks - oticks) * psratio);
}
curcpu()->ci_schedstate.spc_curpriority = p->p_priority;
}
char *trap_type[] = {
"power-on", /* 0x000 T_POWERON */
"manual reset", /* 0x020 T_RESET */
"TLB miss/invalid (load)", /* 0x040 T_TLBMISSR */
"TLB miss/invalid (store)", /* 0x060 T_TLBMISSW */
"initial page write", /* 0x080 T_INITPAGEWR */
"TLB protection violation (load)", /* 0x0a0 T_TLBPRIVR */
"TLB protection violation (store)", /* 0x0c0 T_TLBPRIVW */
"address error (load)", /* 0x0e0 T_ADDRESSERRR */
"address error (store)", /* 0x100 T_ADDRESSERRW */
"unknown trap (0x120)", /* 0x120 */
"unknown trap (0x140)", /* 0x140 */
"unconditional trap (TRAPA)", /* 0x160 T_TRAP */
"reserved instruction code exception", /* 0x180 T_INVALIDISN */
"illegal slot instruction exception", /* 0x1a0 T_INVALIDSLOT */
"nonmaskable interrupt", /* 0x1c0 T_NMI */
"user break point trap", /* 0x1e0 T_USERBREAK */
};
int trap_types = sizeof trap_type / sizeof trap_type[0];
#define DEBUG 1
#ifdef DEBUG
int trapdebug = 1;
#endif
/*
* trap(frame):
* Exception, fault, and trap interface to BSD kernel. This
* common code is called from assembly language IDT gate entry
* routines that prepare a suitable stack frame, and restore this
* frame after the exception has been processed. Note that the
* effect is as if the arguments were passed call by reference.
*/
/*ARGSUSED*/
void
trap(p1, p2, p3, p4, frame)
int p1, p2, p3, p4; /* dummy param */
struct trapframe frame;
{
register struct proc *p = curproc;
int type = frame.tf_trapno;
u_quad_t sticks;
struct pcb *pcb = NULL;
int resume;
vaddr_t va;
if (p == NULL)
goto we_re_toast;
uvmexp.traps++;
#ifdef TRAPDEBUG
if (trapdebug) {
printf("trap %x spc %x ssr %x \n",
frame.tf_trapno, frame.tf_spc, frame.tf_ssr);
printf("curproc %p\n", curproc);
}
#endif
#if 1
if (!KERNELMODE(frame.tf_r15)) {
#else
if (!KERNELMODE(frame.tf_spc, frame.tf_ssr)) {
#endif
type |= T_USER;
sticks = p->p_sticks;
p->p_md.md_regs = &frame;
}
else
sticks = 0;
switch (type) {
default:
we_re_toast:
if (frame.tf_trapno >> 5 < trap_types)
printf("fatal %s", trap_type[frame.tf_trapno >> 5]);
else
printf("unknown trap %x", frame.tf_trapno);
printf(" in %s mode\n", (type & T_USER) ? "user" : "supervisor");
printf("trap type %x spc %x ssr %x \n",
type, frame.tf_spc, frame.tf_ssr);
panic("trap");
/*NOTREACHED*/
case T_TRAP|T_USER:
if (SHREG_TRA == (0x000000c3 << 2)) {
trapsignal(p, SIGTRAP, type &~ T_USER);
break;
} else {
syscall(&frame);
return;
}
case T_INITPAGEWR:
case T_INITPAGEWR|T_USER:
va = (vaddr_t)SHREG_TEA;
pmap_emulate_reference(p, va, type & T_USER, 1);
return;
case T_TRAP:
goto we_re_toast;
case T_ADDRESSERRR:
case T_ADDRESSERRW:
case T_INVALIDSLOT:
/* Check for copyin/copyout fault. */
pcb = &p->p_addr->u_pcb;
if (pcb->pcb_onfault != 0) {
#ifdef TODO
copyfault:
#endif
printf("copyin/copyout fault\n");
frame.tf_spc = (int)pcb->pcb_onfault;
return;
}
/*
* Check for failure during return to user mode.
*
* We do this by looking at the instruction we faulted on. The
* specific instructions we recognize only happen when
* returning from a trap, syscall, or interrupt.
*
* XXX
* The heuristic used here will currently fail for the case of
* one of the 2 pop instructions faulting when returning from a
* a fast interrupt. This should not be possible. It can be
* fixed by rearranging the trap frame so that the stack format
* at this point is the same as on exit from a `slow'
* interrupt.
*/
switch (*(u_char *)frame.tf_spc) {
#ifdef TODO
case 0xcf: /* iret */
vframe = (void *)((int)&frame.tf_esp - 44);
resume = (int)resume_iret;
break;
#endif
default:
goto we_re_toast;
}
frame.tf_spc = resume;
return;
case T_ADDRESSERRR|T_USER: /* protection fault */
case T_ADDRESSERRW|T_USER:
case T_INVALIDSLOT|T_USER:
printf("trap type %x spc %x ssr %x \n",
type, frame.tf_spc, frame.tf_ssr);
trapsignal(p, SIGBUS, type &~ T_USER);
goto out;
case T_INVALIDISN|T_USER: /* invalid instruction fault */
trapsignal(p, SIGILL, type &~ T_USER);
goto out;
case T_ASTFLT :
printf("AST fault\n");
return;
case T_ASTFLT|T_USER: /* Allow process switch */
/* printf("ASTU fault\n"); */
uvmexp.softs++;
if (p->p_flag & P_OWEUPC) {
p->p_flag &= ~P_OWEUPC;
ADDUPROF(p);
}
goto out;
#ifdef TODO
case T_PAGEFLT: /* allow page faults in kernel mode */
if (p == 0)
goto we_re_toast;
pcb = &p->p_addr->u_pcb;
/*
* fusubail is used by [fs]uswintr() to prevent page faulting
* from inside the profiling interrupt.
*/
if (pcb->pcb_onfault == fusubail)
goto copyfault;
#if 0
/* XXX - check only applies to 386's and 486's with WP off */
if (frame.tf_err & PGEX_P)
goto we_re_toast;
#endif
/* FALLTHROUGH */
case T_PAGEFLT|T_USER: { /* page fault */
register vaddrt_t va;
register struct vmspace *vm = p->p_vmspace;
register vm_map_t map;
int rv;
vm_prot_t ftype;
extern vm_map_t kernel_map;
unsigned nss, v;
va = trunc_page((vaddr_t)rcr2());
/*
* It is only a kernel address space fault iff:
* 1. (type & T_USER) == 0 and
* 2. pcb_onfault not set or
* 3. pcb_onfault set but supervisor space fault
* The last can occur during an exec() copyin where the
* argument space is lazy-allocated.
*/
if (type == T_PAGEFLT && va >= KERNBASE)
map = kernel_map;
else
map = &vm->vm_map;
if (frame.tf_err & PGEX_W)
ftype = VM_PROT_READ | VM_PROT_WRITE;
else
ftype = VM_PROT_READ;
#ifdef DIAGNOSTIC
if (map == kernel_map && va == 0) {
printf("trap: bad kernel access at %lx\n", va);
goto we_re_toast;
}
#endif
nss = 0;
if ((caddr_t)va >= vm->vm_maxsaddr
&& (caddr_t)va < (caddr_t)VM_MAXUSER_ADDRESS
&& map != kernel_map) {
nss = btoc(USRSTACK-(unsigned)va);
if (nss > btoc(p->p_rlimit[RLIMIT_STACK].rlim_cur)) {
rv = KERN_FAILURE;
goto nogo;
}
}
/* Fault the original page in. */
rv = uvm_fault(map, va, 0, ftype);
if (rv == KERN_SUCCESS) {
if (nss > vm->vm_ssize)
vm->vm_ssize = nss;
if (type == T_PAGEFLT)
return;
goto out;
}
nogo:
if (type == T_PAGEFLT) {
if (pcb->pcb_onfault != 0)
goto copyfault;
printf("uvm_fault(%p, 0x%lx, 0, %d) -> %x\n",
map, va, ftype, rv);
goto we_re_toast;
}
if (rv == KERN_RESOURCE_SHORTAGE) {
printf("UVM: pid %d (%s), uid %d killed: out of swap\n",
p->p_pid, p->p_comm,
p->p_cred && p->p_ucred ?
p->p_ucred->cr_uid : -1);
trapsignal(p, SIGKILL, T_PAGEFLT);
} else
trapsignal(p, SIGSEGV, T_PAGEFLT);
break;
}
#endif /* TODO */
case T_USERBREAK|T_USER: /* bpt instruction fault */
trapsignal(p, SIGTRAP, type &~ T_USER);
break;
}
if ((type & T_USER) == 0)
return;
out:
userret(p, frame.tf_spc, sticks);
}
/*
* syscall(frame):
* System call request from POSIX system call gate interface to kernel.
* Like trap(), argument is call by reference.
*/
/*ARGSUSED*/
void
syscall(frame)
struct trapframe *frame;
{
register caddr_t params;
register struct sysent *callp;
register struct proc *p;
int error, opc, nsys;
size_t argsize;
register_t code, args[8], rval[2], ocode;
u_quad_t sticks;
uvmexp.syscalls++;
#if 1
if (KERNELMODE(frame->tf_r15))
#else
if (!USERMODE(frame->tf_spc, frame->tf_ssr))
#endif
panic("syscall");
p = curproc;
sticks = p->p_sticks;
p->p_md.md_regs = frame;
opc = frame->tf_spc;
ocode = code = frame->tf_r0;
nsys = p->p_emul->e_nsysent;
callp = p->p_emul->e_sysent;
params = (caddr_t)frame->tf_r15;
switch (code) {
case SYS_syscall:
/*
* Code is first argument, followed by actual args.
*/
code = frame->tf_r4; /* fuword(params); */
/* params += sizeof(int); */
break;
case SYS___syscall:
/*
* Like syscall, but code is a quad, so as to maintain
* quad alignment for the rest of the arguments.
*/
if (callp != sysent)
break;
code = frame->tf_r5; /* fuword(params + _QUAD_LOWWORD * sizeof(int)); */
/* params += sizeof(quad_t); */
break;
default:
break;
}
if (code < 0 || code >= nsys)
callp += p->p_emul->e_nosys; /* illegal */
else
callp += code;
argsize = callp->sy_argsize;
if (ocode == SYS_syscall) {
if (argsize) {
args[0] = frame->tf_r5;
args[1] = frame->tf_r6;
args[2] = frame->tf_r7;
if (argsize > 3 * sizeof(int)) {
argsize -= 3 * sizeof(int);
error = copyin(params, (caddr_t)&args[3],
argsize);
} else
error = 0;
} else
error = 0;
}
else if (ocode == SYS___syscall) {
if (argsize) {
args[0] = frame->tf_r6;
args[1] = frame->tf_r7;
if (argsize > 2 * sizeof(int)) {
argsize -= 2 * sizeof(int);
error = copyin(params, (caddr_t)&args[2],
argsize);
} else
error = 0;
} else
error = 0;
} else {
if (argsize) {
args[0] = frame->tf_r4;
args[1] = frame->tf_r5;
args[2] = frame->tf_r6;
args[3] = frame->tf_r7;
if (argsize > 4 * sizeof(int)) {
argsize -= 4 * sizeof(int);
error = copyin(params, (caddr_t)&args[4],
argsize);
} else
error = 0;
} else
error = 0;
}
//#ifdef TRAP_DEBUG
#ifdef SYSCALL_DEBUG
if (cpu_debug_mode)
scdebug_call(p, code, args);
#endif
//#endif
#ifdef KTRACE
if (KTRPOINT(p, KTR_SYSCALL))
ktrsyscall(p, code, argsize, args);
#endif
if (error)
goto bad;
rval[0] = 0;
rval[1] = frame->tf_r1;
error = (*callp->sy_call)(p, args, rval);
switch (error) {
case 0:
/*
* Reinitialize proc pointer `p' as it may be different
* if this is a child returning from fork syscall.
*/
p = curproc;
frame->tf_r0 = rval[0];
frame->tf_r1 = rval[1];
frame->tf_ssr |= PSL_TBIT; /* T bit */
break;
case ERESTART:
/* 2 = TRAPA instruction size */
frame->tf_spc = opc - 2;
break;
case EJUSTRETURN:
/* nothing to do */
break;
default:
bad:
if (p->p_emul->e_errno)
error = p->p_emul->e_errno[error];
frame->tf_r0 = error;
frame->tf_ssr &= ~PSL_TBIT; /* T bit */
break;
}
//#ifdef TRAP_DEBUG
#ifdef SYSCALL_DEBUG
if (cpu_debug_mode)
scdebug_ret(p, code, error, rval);
#endif
//#endif
userret(p, frame->tf_spc, sticks);
#ifdef KTRACE
if (KTRPOINT(p, KTR_SYSRET))
ktrsysret(p, code, error, rval[0]);
#endif
}
void
child_return(arg)
void *arg;
{
struct proc *p = arg;
struct trapframe *tf = p->p_md.md_regs;
tf->tf_r0 = 0;
tf->tf_ssr |= PSL_TBIT; /* This indicates no error. */
userret(p, tf->tf_spc, 0);
#ifdef KTRACE
if (KTRPOINT(p, KTR_SYSRET))
ktrsysret(p, SYS_fork, 0, 0);
#endif
}
/*
* Set TLB entry
* This is called from tlb_miss exception handler.
*/
void
tlb_handler(p1, p2, p3, p4, frame)
int p1, p2, p3, p4; /* These four params are dummy */
struct trapframe frame;
{
vaddr_t va;
int pde_index;
unsigned long *pde;
unsigned long pte;
unsigned long *pd_top;
int pte_index;
struct proc *p;
struct vmspace *vm;
vm_map_t map;
int rv = 0;
u_quad_t sticks = 0;
int type = 0;
vm_prot_t ftype;
extern vm_map_t kernel_map;
unsigned int nss;
vaddr_t va_save;
unsigned long pteh_save;
int exptype;
#ifdef RECURSE_TLB_HANDLER
int reentrant = 0;
#endif
uvmexp.traps++;
va = (vaddr_t)SHREG_TEA;
va = trunc_page(va);
pde_index = pdei(va);
#ifdef SH4
pd_top = (u_long *)(SH3_P1SEG_TO_P2SEG(SHREG_TTB));
pde = (u_long *)((u_long)SH3_P1SEG_TO_P2SEG(pd_top[pde_index]));
#else
pd_top = (u_long *)SHREG_TTB;
pde = (u_long *)pd_top[pde_index];
#endif
exptype = SHREG_EXPEVT;
#if 0 /* def SH4 */
if (((u_long)pde & PG_V) != 0 &&
(incpuswitch || exptype != T_TLBPRIVW)) {
#else
if (((u_long)pde & PG_V) != 0 && exptype != T_TLBPRIVW) {
#endif
(u_long)pde &= ~PGOFSET;
pte_index = ptei(va);
#ifdef SH4
pte = SH3_P1SEG_TO_P2SEG(pde[pte_index]);
#else
pte = pde[pte_index];
#endif
if ((pte & PG_V) != 0) {
#ifdef DEBUG_TLB
if (trapdebug)
printf("tlb_handler:va(0x%lx),pte(0x%lx)\n",
va, pte);
#endif
#ifdef SH4_PCMCIA
#define PTEL_VALIDBITS 0x1ffff17e
#else
#define PTEL_VALIDBITS 0x1ffffd7e
#endif
#ifdef SH4
if (pte & PG_PCMCIA) {
int pcmtype;
unsigned long ptea = 0;
pcmtype = pte & PG_PCMCIA;
/* printf("pcmtype = %lx,pte=%lx\n",
pcmtype,pte); */
if (pcmtype == PG_PCMCIA_IO) {
ptea = 0x03;
} else if (pcmtype == PG_PCMCIA_MEM) {
ptea = 0x05;
/* ptea = 0x03; */
} else if (pcmtype == PG_PCMCIA_ATT) {
ptea = 0x07;
}
SHREG_PTEL = (pte & PTEL_VALIDBITS)
& ~PG_N;
SHREG_PTEA = ptea;
} else {
if ( /*1 ||*/ (va >= SH3_P1SEG_BASE)) {
SHREG_PTEL = (pte & PTEL_VALIDBITS)
| PG_WT;
} else {
SHREG_PTEL = pte & PTEL_VALIDBITS;
}
SHREG_PTEA = 0;
}
#else
SHREG_PTEL = pte & PTEL_VALIDBITS;
#endif
return;
}
}
#ifdef TRAP_DEBUG
if (trapdebug)
printf("tlb_handler#:va(0x%lx),curproc(%p)\n", va, curproc);
#endif
pteh_save = SHREG_PTEH;
va_save = va;
p = curproc;
if (p == NULL) {
rv = KERN_FAILURE;
goto nogo;
} else {
#if 1
if (!KERNELMODE(frame.tf_r15)) {
#else
if (!KERNELMODE(frame.tf_spc, frame.tf_ssr)) {
#endif
type = T_USER;
sticks = p->p_sticks;
p->p_md.md_regs = &frame;
}
else
sticks = 0;
}
vm = p->p_vmspace;
/*
* It is only a kernel address space fault iff:
* 1. (type & T_USER) == 0 and
* 2. pcb_onfault not set or
* 3. pcb_onfault set but supervisor space fault
* The last can occur during an exec() copyin where the
* argument space is lazy-allocated.
*/
if (va >= KERNBASE)
map = kernel_map;
else
map = &vm->vm_map;
/* exptype = SHREG_EXPEVT; */
if (exptype == T_TLBMISSW || exptype == T_TLBPRIVW)
ftype = VM_PROT_READ | VM_PROT_WRITE;
else
ftype = VM_PROT_READ;
nss = 0;
#ifdef SH4
if (vm != NULL && (caddr_t)va >= vm->vm_maxsaddr
&& (caddr_t)va < (caddr_t)VM_MAXUSER_ADDRESS
&& map != kernel_map) {
nss = btoc(USRSTACK-(unsigned)va);
if (nss > btoc(p->p_rlimit[RLIMIT_STACK].rlim_cur)) {
rv = KERN_FAILURE;
goto nogo;
}
}
#else
if ((caddr_t)va >= vm->vm_maxsaddr
&& (caddr_t)va < (caddr_t)VM_MAXUSER_ADDRESS
&& map != kernel_map) {
nss = btoc(USRSTACK-(unsigned)va);
if (nss > btoc(p->p_rlimit[RLIMIT_STACK].rlim_cur)) {
rv = KERN_FAILURE;
goto nogo;
}
}
#endif
#ifdef RECURSE_TLB_HANDLER
if (((PSL_BL | PSL_IMASK) & frame.tf_ssr) == 0)
reentrant = 1;
#endif
/* Fault the original page in. */
#ifdef RECURSE_TLB_HANDLER
if (reentrant)
enable_ext_intr();
#endif
rv = uvm_fault(map, va, 0, ftype);
#ifdef RECURSE_TLB_HANDLER
if (reentrant)
disable_ext_intr();
#endif
if (rv == KERN_SUCCESS) {
#ifdef SH4
if (vm != NULL && nss > vm->vm_ssize)
vm->vm_ssize = nss;
#else
if (nss > vm->vm_ssize)
vm->vm_ssize = nss;
#endif
va = va_save;
SHREG_PTEH = pteh_save;
pde_index = pdei(va);
pd_top = (u_long *)SHREG_TTB;
#ifdef SH4
pde = (u_long *)
((u_long)SH3_P1SEG_TO_P2SEG(pd_top[pde_index]));
#else
pde = (u_long *)pd_top[pde_index];
#endif
if (((u_long)pde & PG_V) != 0) {
(u_long)pde &= ~PGOFSET;
pte_index = ptei(va);
pte = pde[pte_index];
if ((pte & PG_V) != 0) {
#ifdef TRAP_DEBUG
if (trapdebug)
printf("tlb_handler#:va(0x%lx),pte(0x%lx)\n", va, pte);
#endif
#ifdef SH4
if (pte & PG_PCMCIA) {
int pcmtype;
unsigned long ptea = 0;
pcmtype = pte & PG_PCMCIA;
/* printf("pcmtype = %lx,pte=%lx\n",
pcmtype,pte); */
if (pcmtype == PG_PCMCIA_IO) {
ptea = 0x03;
} else if (pcmtype == PG_PCMCIA_MEM) {
ptea = 0x05;
/*ptea = 0x03; */
} else if (pcmtype == PG_PCMCIA_ATT) {
ptea = 0x07;
}
SHREG_PTEL = (pte & PTEL_VALIDBITS)
& ~PG_N;
SHREG_PTEA = ptea;
} else {
if ( /*1 ||*/ (va >= SH3_P1SEG_BASE)) {
SHREG_PTEL =
(pte & PTEL_VALIDBITS)
| PG_WT;
} else {
SHREG_PTEL =
(pte & PTEL_VALIDBITS);
}
SHREG_PTEA = 0;
}
#else
SHREG_PTEL = pte & PTEL_VALIDBITS;
#endif
return;
}
}
}
nogo:
if (p != NULL) {
struct pcb *pcb = &p->p_addr->u_pcb;
if (pcb->pcb_onfault != 0) {
frame.tf_spc = (int)pcb->pcb_onfault;
return;
}
}
#ifdef DEBUG
if (trapdebug) {
printf("tlb_handler#NOGO:va(0x%lx),spc=%x\n",
va, frame.tf_spc);
}
#endif
if (rv == KERN_RESOURCE_SHORTAGE) {
printf("UVM: pid %d (%s), uid %d killed: out of swap\n",
p->p_pid, p->p_comm,
p->p_cred && p->p_ucred ?
p->p_ucred->cr_uid : -1);
trapsignal(p, SIGKILL, T_TLBINVALIDR);
} else
trapsignal(p, SIGSEGV, T_TLBINVALIDR);
if ((type & T_USER) == 0)
return;
if (p != NULL)
userret(p, frame.tf_spc, sticks);
}