incorpaorated floppy code from Brad Pepers, needs work doesn't work on my
machine. more clenaup in trap.c
This commit is contained in:
parent
10466baa67
commit
602ef3f30f
|
@ -38,7 +38,7 @@
|
|||
* from: Utah $Hdr: autoconf.c 1.31 91/01/21$
|
||||
*
|
||||
* @(#)autoconf.c 7.5 (Berkeley) 5/7/91
|
||||
* $Id: autoconf.c,v 1.12 1994/03/28 06:15:55 chopps Exp $
|
||||
* $Id: autoconf.c,v 1.13 1994/04/05 18:08:56 chopps Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -586,6 +586,9 @@ same_hw_device(hw, ad)
|
|||
case D_PPORT:
|
||||
found = dr_type(ad->amiga_driver, "par");
|
||||
break;
|
||||
case D_FLOP:
|
||||
found = dr_type(ad->amiga_driver, "fp");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -701,6 +704,15 @@ find_devs()
|
|||
hw->hw_serno = 0;
|
||||
hw++;
|
||||
|
||||
hw->hw_pa = 0;
|
||||
hw->hw_size = 0;
|
||||
hw->hw_kva = CUSTOMbase;
|
||||
hw->hw_manufacturer = MANUF_BUILTIN;
|
||||
hw->hw_product = PROD_BUILTIN_FLOP;
|
||||
hw->hw_type = B_BUILTIN | D_FLOP;
|
||||
hw->hw_serno = 0;
|
||||
hw++;
|
||||
|
||||
hw->hw_pa = 0;
|
||||
hw->hw_size = 0;
|
||||
hw->hw_kva = (caddr_t) CUSTOMbase;
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
* on the Hardware Reference Manual. It is NOT based on the Amiga's
|
||||
* hardware/custom.h.
|
||||
*
|
||||
* $Id: custom.h,v 1.5 1994/02/11 06:59:34 chopps Exp $
|
||||
* $Id: custom.h,v 1.6 1994/04/05 18:09:00 chopps Exp $
|
||||
*/
|
||||
|
||||
#ifndef _amiga_custom_
|
||||
|
@ -286,6 +286,23 @@ extern volatile struct Custom *CUSTOMbase;
|
|||
#define INTF_DSKBLK (1<<INTB_DSKBLK)
|
||||
#define INTF_TBE (1<<INTB_TBE)
|
||||
|
||||
/* Bit definitions for adkcon, adkconr */
|
||||
#define ADKB_SETCLR 15
|
||||
#define ADKB_PRECOMP1 14
|
||||
#define ADKB_PRECOMP0 13
|
||||
#define ADKB_MFMPREC 12
|
||||
#define ADKB_UARTBRK 11
|
||||
#define ADKB_WORDSYNC 10
|
||||
#define ADKB_MSBSYNC 9
|
||||
#define ADKB_FAST 8
|
||||
|
||||
#define ADKF_SETCLR (1<<ADKB_SETCLR)
|
||||
#define ADKF_PRECOMP1 (1<<ADKB_PRECOMP1)
|
||||
#define ADKF_PRECOMP0 (1<<ADKB_PRECOMP0)
|
||||
#define ADKF_MFMPREC (1<<ADKB_MFMPREC)
|
||||
#define ADKF_UARTBRK (1<<ADKB_UARTBRK)
|
||||
#define ADKF_WORDSYNC (1<<ADKB_WORDSYNC)
|
||||
#define ADKF_MSBSYNC (1<<ADKB_MSBSYNC)
|
||||
#define ADKF_FAST (1<<ADKB_FAST)
|
||||
|
||||
#endif /* _machine_custom_ */
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
* from: Utah $Hdr: machdep.c 1.63 91/04/24$
|
||||
*
|
||||
* @(#)machdep.c 7.16 (Berkeley) 6/3/91
|
||||
* $Id: machdep.c,v 1.14 1994/03/30 17:24:08 chopps Exp $
|
||||
* $Id: machdep.c,v 1.15 1994/04/05 18:09:02 chopps Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
|
@ -1392,15 +1392,17 @@ intrhand(sr)
|
|||
{
|
||||
ser_outintr ();
|
||||
}
|
||||
|
||||
if (ireq & INTF_DSKBLK)
|
||||
{
|
||||
fpintr(0);
|
||||
custom.intreq = INTF_DSKBLK;
|
||||
}
|
||||
if (ireq & INTF_SOFTINT)
|
||||
{
|
||||
/* first call installed callbacks, then clear the softint-bit */
|
||||
call_sicallbacks ();
|
||||
custom.intreq = INTF_SOFTINT;
|
||||
}
|
||||
|
||||
custom.intreq = INTF_DSKBLK;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
* from: Utah $Hdr: trap.c 1.32 91/04/06$
|
||||
*
|
||||
* @(#)trap.c 7.15 (Berkeley) 8/2/91
|
||||
* $Id: trap.c,v 1.12 1994/04/04 11:10:55 chopps Exp $
|
||||
* $Id: trap.c,v 1.13 1994/04/05 18:09:04 chopps Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
|
@ -119,7 +119,7 @@ static void
|
|||
userret(p, pc, oticks)
|
||||
struct proc *p;
|
||||
int pc;
|
||||
struct timeval oticks;
|
||||
struct timeval *oticks;
|
||||
{
|
||||
int sig, s;
|
||||
|
||||
|
@ -149,8 +149,8 @@ userret(p, pc, oticks)
|
|||
int ticks;
|
||||
struct timeval *tv = &p->p_stime;
|
||||
|
||||
ticks = ((tv->tv_sec - oticks.tv_sec) * 1000 +
|
||||
(tv->tv_usec - oticks.tv_usec) / 1000) / (tick / 1000);
|
||||
ticks = ((tv->tv_sec - oticks->tv_sec) * 1000 +
|
||||
(tv->tv_usec - oticks->tv_usec) / 1000) / (tick / 1000);
|
||||
if (ticks) {
|
||||
#ifdef PROFTIMER
|
||||
extern int profscale;
|
||||
|
@ -163,6 +163,239 @@ userret(p, pc, oticks)
|
|||
curpri = p->p_pri;
|
||||
}
|
||||
|
||||
void
|
||||
panictrap(type, code, v, fp)
|
||||
int type;
|
||||
u_int code, v;
|
||||
struct frame *fp;
|
||||
{
|
||||
static int panicing = 0;
|
||||
if (panicing++ == 0) {
|
||||
printf("trap type %d, code = %x, v = %x\n", type, code, v);
|
||||
regdump(fp->f_regs, 128);
|
||||
}
|
||||
type &= ~T_USER;
|
||||
DCIS(); /* XXX? push cache */
|
||||
if ((u_int)type < trap_types)
|
||||
panic(trap_type[type]);
|
||||
panic("trap");
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
/*
|
||||
* return to fault handler
|
||||
*/
|
||||
void
|
||||
trapcpfault(p, fp)
|
||||
struct proc *p;
|
||||
struct frame *fp;
|
||||
{
|
||||
/*
|
||||
* We have arranged to catch this fault in one of the
|
||||
* copy to/from user space routines, set PC to return to
|
||||
* indicated location and set flag informing buserror code
|
||||
* that it may need to clean up stack frame.
|
||||
*/
|
||||
fp->f_stackadj = exframesize[fp->f_format];
|
||||
fp->f_format = fp->f_vector = 0;
|
||||
fp->f_pc = (int) p->p_addr->u_pcb.pcb_onfault;
|
||||
}
|
||||
|
||||
void
|
||||
trapmmufault(type, code, v, fp, p, sticks)
|
||||
int type;
|
||||
u_int code, v;
|
||||
struct frame *fp;
|
||||
struct proc *p;
|
||||
struct timeval *sticks;
|
||||
{
|
||||
extern vm_map_t kernel_map;
|
||||
struct vmspace *vm;
|
||||
vm_prot_t ftype;
|
||||
vm_offset_t va;
|
||||
vm_map_t map;
|
||||
u_int nss;
|
||||
int rv;
|
||||
|
||||
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 data fault
|
||||
* The last can occur during an exec() copyin where the
|
||||
* argument space is lazy-allocated.
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
/*
|
||||
* Print out some data about the fault
|
||||
*/
|
||||
if (mmudebug && cpu040) {
|
||||
printf ("68040 access error: pc %x, code %x,"
|
||||
" ea %x, fa %x\n", fp->f_pc, code, fp->f_fmt7.f_ea, v);
|
||||
if (curpcb)
|
||||
printf (" curpcb %x ->pcb_ustp %x / %x\n",
|
||||
curpcb, curpcb->pcb_ustp,
|
||||
curpcb->pcb_ustp << PG_SHIFT);
|
||||
}
|
||||
#endif
|
||||
if (type == T_MMUFLT &&
|
||||
(p->p_addr->u_pcb.pcb_onfault == 0 ||
|
||||
(cpu040 && (code & SSW_TMMASK) == FC_SUPERD) ||
|
||||
(!cpu040 && (code & (SSW_DF|FC_SUPERD)) == (SSW_DF|FC_SUPERD))))
|
||||
map = kernel_map;
|
||||
else
|
||||
map = &vm->vm_map;
|
||||
if ((cpu040 && (code & SSW_RW040) == 0) ||
|
||||
(!cpu040 && (code & (SSW_DF|SSW_RW)) ==
|
||||
SSW_DF)) /* what about RMW? */
|
||||
ftype = VM_PROT_READ | VM_PROT_WRITE;
|
||||
else
|
||||
ftype = VM_PROT_READ;
|
||||
va = trunc_page((vm_offset_t)v);
|
||||
#ifdef DEBUG
|
||||
if (map == kernel_map && va == 0) {
|
||||
printf("trap: bad kernel access at %x\n", v);
|
||||
panictrap(type, code, v, fp);
|
||||
}
|
||||
#endif
|
||||
#ifndef no_386bsd_code
|
||||
/*
|
||||
* XXX: rude hack to make stack limits "work"
|
||||
*/
|
||||
nss = 0;
|
||||
if ((caddr_t)va >= vm->vm_maxsaddr && map != kernel_map) {
|
||||
nss = clrnd(btoc(USRSTACK - (unsigned)va));
|
||||
if (nss > btoc(p->p_rlimit[RLIMIT_STACK].rlim_cur)) {
|
||||
rv = KERN_FAILURE;
|
||||
goto nogo;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
if (mmudebug)
|
||||
printf("vm_fault(%x,%x,%d,0)\n", map, va, ftype);
|
||||
#endif
|
||||
|
||||
rv = vm_fault(map, va, ftype, FALSE);
|
||||
|
||||
#ifdef DEBUG
|
||||
if (mmudebug)
|
||||
printf("vmfault %s %x returned %d\n",
|
||||
map == kernel_map ? "kernel" : "user", va, rv);
|
||||
#endif
|
||||
|
||||
if (cpu040) {
|
||||
if(rv != KERN_SUCCESS) {
|
||||
goto nogo;
|
||||
}
|
||||
|
||||
/*
|
||||
* The 68040 doesn't re-run instructions that cause
|
||||
* write page faults (unless due to a move16 isntruction).
|
||||
* So once the page is repaired, we have to write the
|
||||
* value of WB2D out to memory ourselves. Because
|
||||
* the writeback could possibly span two pages in
|
||||
* memory, so we need to check both "ends" of the
|
||||
* address to see if they are in the same page or not.
|
||||
* If not, then we need to make sure the second page
|
||||
* is valid, and bring it into memory if it's not.
|
||||
*
|
||||
* This whole process needs to be repeated for WB3 as well.
|
||||
* <sigh>
|
||||
*/
|
||||
|
||||
/* Check WB1 */
|
||||
if (fp->f_fmt7.f_wb1s & WBS_VALID) {
|
||||
printf ("trap: wb1 was valid, not handled yet\n");
|
||||
panictrap(type, code, v, fp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check WB2
|
||||
* skip if it's for a move16 instruction
|
||||
*/
|
||||
if(fp->f_fmt7.f_wb2s & WBS_VALID &&
|
||||
((fp->f_fmt7.f_wb2s & WBS_TTMASK)==WBS_TT_MOVE16) == 0) {
|
||||
if (_write_back(2, fp->f_fmt7.f_wb2s,
|
||||
fp->f_fmt7.f_wb2d, fp->f_fmt7.f_wb2a, map)
|
||||
!= KERN_SUCCESS)
|
||||
goto nogo;
|
||||
if ((fp->f_fmt7.f_wb2s & WBS_TMMASK)
|
||||
!= (code & SSW_TMMASK))
|
||||
panictrap(type, code, v, fp);
|
||||
}
|
||||
|
||||
/* Check WB3 */
|
||||
if(fp->f_fmt7.f_wb3s & WBS_VALID) {
|
||||
vm_map_t wb3_map;
|
||||
|
||||
if ((fp->f_fmt7.f_wb3s & WBS_TMMASK) == WBS_TM_SDATA)
|
||||
wb3_map = kernel_map;
|
||||
else
|
||||
wb3_map = &vm->vm_map;
|
||||
if (_write_back(3, fp->f_fmt7.f_wb3s,
|
||||
fp->f_fmt7.f_wb3d, fp->f_fmt7.f_wb3a, wb3_map)
|
||||
!= KERN_SUCCESS)
|
||||
goto nogo;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef no_386bsd_code
|
||||
/*
|
||||
* If this was a stack access we keep track of the maximum
|
||||
* accessed stack size. Also, if vm_fault gets a protection
|
||||
* failure it is due to accessing the stack region outside
|
||||
* the current limit and we need to reflect that as an access
|
||||
* error.
|
||||
*/
|
||||
if ((caddr_t)va >= vm->vm_maxsaddr && map != kernel_map) {
|
||||
if (rv == KERN_SUCCESS) {
|
||||
nss = clrnd(btoc(USRSTACK-(unsigned)va));
|
||||
if (nss > vm->vm_ssize)
|
||||
vm->vm_ssize = nss;
|
||||
} else if (rv == KERN_PROTECTION_FAILURE)
|
||||
rv = KERN_INVALID_ADDRESS;
|
||||
}
|
||||
|
||||
if (rv == KERN_SUCCESS) {
|
||||
if (type == T_MMUFLT)
|
||||
return;
|
||||
userret(p, fp->f_pc, sticks);
|
||||
reutrn;
|
||||
}
|
||||
#else /* use hacky 386bsd_code */
|
||||
if (rv == KERN_SUCCESS) {
|
||||
/*
|
||||
* XXX: continuation of rude stack hack
|
||||
*/
|
||||
if (nss > vm->vm_ssize)
|
||||
vm->vm_ssize = nss;
|
||||
if (type == T_MMUFLT)
|
||||
return;
|
||||
userret(p, fp->f_pc, sticks);
|
||||
return;
|
||||
}
|
||||
nogo:
|
||||
#endif
|
||||
if (type == T_MMUFLT) {
|
||||
if (p->p_addr->u_pcb.pcb_onfault) {
|
||||
trapcpfault(p, fp);
|
||||
return;
|
||||
}
|
||||
printf("vm_fault(%x, %x, %x, 0) -> %x\n",
|
||||
map, va, ftype, rv);
|
||||
printf(" type %x, code [mmu,,ssw]: %x\n",
|
||||
type, code);
|
||||
panictrap(type, code, v, fp);
|
||||
}
|
||||
trapsignal(p, (rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV, v);
|
||||
if ((type & T_USER) == 0)
|
||||
return;
|
||||
userret(p, fp->f_pc, sticks);
|
||||
}
|
||||
/*
|
||||
* Trap is called from locore to handle most types of processor traps,
|
||||
* including events such as simulated software interrupts/AST's.
|
||||
|
@ -171,20 +404,19 @@ userret(p, pc, oticks)
|
|||
/*ARGSUSED*/
|
||||
trap(type, code, v, frame)
|
||||
int type;
|
||||
unsigned code;
|
||||
register unsigned v;
|
||||
u_int code, v;
|
||||
struct frame frame;
|
||||
{
|
||||
register int i;
|
||||
unsigned ucode = 0;
|
||||
register struct proc *p = curproc;
|
||||
struct timeval syst;
|
||||
unsigned ncode;
|
||||
static int panicing = 0;
|
||||
int s;
|
||||
struct proc *p;
|
||||
u_int ncode, ucode;
|
||||
int i, s;
|
||||
|
||||
p = curproc;
|
||||
ucode = 0;
|
||||
cnt.v_trap++;
|
||||
syst = p->p_stime;
|
||||
|
||||
if (USERMODE(frame.f_sr)) {
|
||||
type |= T_USER;
|
||||
p->p_regs = frame.f_regs;
|
||||
|
@ -198,51 +430,84 @@ trap(type, code, v, frame)
|
|||
#endif
|
||||
|
||||
switch (type) {
|
||||
|
||||
default:
|
||||
dopanic:
|
||||
if (! panicing++)
|
||||
{
|
||||
printf("trap type %d, code = %x, v = %x\n", type, code, v);
|
||||
regdump(frame.f_regs, 128);
|
||||
}
|
||||
type &= ~T_USER;
|
||||
DCIS(); /* push cache */
|
||||
if ((unsigned)type < trap_types)
|
||||
panic(trap_type[type]);
|
||||
panic("trap");
|
||||
|
||||
case T_BUSERR: /* kernel bus error */
|
||||
panictrap(type, code, v, &frame);
|
||||
/*
|
||||
* Kernel Bus error
|
||||
*/
|
||||
case T_BUSERR:
|
||||
if (!p->p_addr->u_pcb.pcb_onfault)
|
||||
goto dopanic;
|
||||
/*
|
||||
* If we have arranged to catch this fault in any of the
|
||||
* copy to/from user space routines, set PC to return to
|
||||
* indicated location and set flag informing buserror code
|
||||
* that it may need to clean up stack frame.
|
||||
*/
|
||||
copyfault:
|
||||
frame.f_stackadj = exframesize[frame.f_format];
|
||||
frame.f_format = frame.f_vector = 0;
|
||||
frame.f_pc = (int) p->p_addr->u_pcb.pcb_onfault;
|
||||
panictrap(type, code, v, &frame);
|
||||
trapcpfault(p, &frame);
|
||||
return;
|
||||
|
||||
case T_BUSERR|T_USER: /* bus error */
|
||||
case T_ADDRERR|T_USER: /* address error */
|
||||
/*
|
||||
* User Bus/Addr error.
|
||||
*/
|
||||
case T_BUSERR|T_USER:
|
||||
case T_ADDRERR|T_USER:
|
||||
i = SIGBUS;
|
||||
break;
|
||||
|
||||
#ifdef FPCOPROC
|
||||
case T_COPERR: /* kernel coprocessor violation */
|
||||
#endif
|
||||
case T_FMTERR: /* kernel format error */
|
||||
/*
|
||||
* The user has most likely trashed the RTE or FP state info
|
||||
* in the stack frame of a signal handler.
|
||||
* User illegal/privleged inst fault
|
||||
*/
|
||||
case T_ILLINST|T_USER:
|
||||
case T_PRIVINST|T_USER:
|
||||
ucode = frame.f_format; /* XXX was ILL_PRIVIN_FAULT */
|
||||
i = SIGILL;
|
||||
break;
|
||||
/*
|
||||
* divde by zero, CHK/TRAPV inst
|
||||
*/
|
||||
case T_ZERODIV|T_USER:
|
||||
case T_CHKINST|T_USER:
|
||||
case T_TRAPVINST|T_USER:
|
||||
ucode = frame.f_format;
|
||||
i = SIGFPE;
|
||||
break;
|
||||
#ifdef FPCOPROC
|
||||
/*
|
||||
* User coprocessor violation
|
||||
*/
|
||||
case T_COPERR|T_USER:
|
||||
ucode = 0;
|
||||
i = SIGFPE; /* XXX What is a proper response here? */
|
||||
break;
|
||||
/*
|
||||
* 6888x exceptions
|
||||
*/
|
||||
case T_FPERR|T_USER:
|
||||
/*
|
||||
* We pass along the 68881 status register which locore
|
||||
* stashed in code for us. Note that there is a
|
||||
* possibility that the bit pattern of this register
|
||||
* will conflict with one of the FPE_* codes defined
|
||||
* in signal.h. Fortunately for us, the only such
|
||||
* codes we use are all in the range 1-7 and the low
|
||||
* 3 bits of the status register are defined as 0 so
|
||||
* there is no clash.
|
||||
*/
|
||||
ucode = code;
|
||||
i = SIGFPE;
|
||||
break;
|
||||
/*
|
||||
* Kernel coprocessor violation
|
||||
*/
|
||||
case T_COPERR:
|
||||
/*FALLTHROUGH*/
|
||||
#endif
|
||||
/*
|
||||
* Kernel format error
|
||||
*/
|
||||
case T_FMTERR:
|
||||
/*
|
||||
* The user has most likely trashed the RTE or FP state info
|
||||
* in the stack frame of a signal handler.
|
||||
*/
|
||||
type |= T_USER;
|
||||
#ifdef DEBUG
|
||||
printf("pid %d: kernel %s exception\n", p->p_pid,
|
||||
type==T_COPERR ? "coprocessor" : "format");
|
||||
type==T_COPERR ? "coprocessor" : "format");
|
||||
#endif
|
||||
p->p_sigacts->ps_sigact[SIGILL] = SIG_DFL;
|
||||
i = sigmask(SIGILL);
|
||||
p->p_sigignore &= ~i;
|
||||
|
@ -251,84 +516,48 @@ copyfault:
|
|||
i = SIGILL;
|
||||
ucode = frame.f_format; /* XXX was ILL_RESAD_FAULT */
|
||||
break;
|
||||
|
||||
#ifdef FPCOPROC
|
||||
case T_COPERR|T_USER: /* user coprocessor violation */
|
||||
/* What is a proper response here? */
|
||||
ucode = 0;
|
||||
i = SIGFPE;
|
||||
break;
|
||||
|
||||
case T_FPERR|T_USER: /* 68881 exceptions */
|
||||
/*
|
||||
* We pass along the 68881 status register which locore stashed
|
||||
* in code for us. Note that there is a possibility that the
|
||||
* bit pattern of this register will conflict with one of the
|
||||
* FPE_* codes defined in signal.h. Fortunately for us, the
|
||||
* only such codes we use are all in the range 1-7 and the low
|
||||
* 3 bits of the status register are defined as 0 so there is
|
||||
* no clash.
|
||||
*/
|
||||
ucode = code;
|
||||
i = SIGFPE;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case T_ILLINST|T_USER: /* illegal instruction fault */
|
||||
case T_PRIVINST|T_USER: /* privileged instruction fault */
|
||||
ucode = frame.f_format; /* XXX was ILL_PRIVIN_FAULT */
|
||||
i = SIGILL;
|
||||
break;
|
||||
|
||||
case T_ZERODIV|T_USER: /* Divide by zero */
|
||||
ucode = frame.f_format; /* XXX was FPE_INTDIV_TRAP */
|
||||
i = SIGFPE;
|
||||
break;
|
||||
|
||||
case T_CHKINST|T_USER: /* CHK instruction trap */
|
||||
ucode = frame.f_format; /* XXX was FPE_SUBRNG_TRAP */
|
||||
i = SIGFPE;
|
||||
break;
|
||||
|
||||
case T_TRAPVINST|T_USER: /* TRAPV instruction trap */
|
||||
ucode = frame.f_format; /* XXX was FPE_INTOVF_TRAP */
|
||||
i = SIGFPE;
|
||||
break;
|
||||
|
||||
/*
|
||||
* XXX: Trace traps are a nightmare.
|
||||
* Trace traps.
|
||||
*
|
||||
* HP-UX uses trap #1 for breakpoints,
|
||||
* HPBSD uses trap #2,
|
||||
* SUN 3.x uses trap #15,
|
||||
* KGDB uses trap #15 (for kernel breakpoints; handled elsewhere).
|
||||
* M68k NetBSD uses trap #2,
|
||||
* SUN 3.x uses trap #15,
|
||||
* KGDB uses trap #15 (for kernel breakpoints; handled elsewhere).
|
||||
*
|
||||
* HPBSD and HP-UX traps both get mapped by locore.s into T_TRACE.
|
||||
* Amiga traps get mapped by locore.s into T_TRACE.
|
||||
* SUN 3.x traps get passed through as T_TRAP15 and are not really
|
||||
* supported yet.
|
||||
*/
|
||||
case T_TRACE: /* kernel trace trap */
|
||||
case T_TRAP15: /* SUN trace trap */
|
||||
case T_TRACE:
|
||||
case T_TRAP15:
|
||||
frame.f_sr &= ~PSL_T;
|
||||
i = SIGTRAP;
|
||||
break;
|
||||
|
||||
case T_TRACE|T_USER: /* user trace trap */
|
||||
case T_TRAP15|T_USER: /* SUN user trace trap */
|
||||
case T_TRACE|T_USER:
|
||||
case T_TRAP15|T_USER:
|
||||
#ifdef COMPAT_SUNOS
|
||||
/* SunOS seems to use Trap #2 for some obscure fpu operations.
|
||||
So far, just ignore it, but DONT trap on it.. */
|
||||
if (p->p_emul == EMUL_SUNOS)
|
||||
goto out;
|
||||
/*
|
||||
* XXX This comment/code is not consistent XXX
|
||||
* SunOS seems to use Trap #2 for some obscure
|
||||
* fpu operations. So far, just ignore it, but
|
||||
* DONT trap on it..
|
||||
*/
|
||||
if (p->p_emul == EMUL_SUNOS) {
|
||||
userret(p, frame.f_pc, &syst);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
frame.f_sr &= ~PSL_T;
|
||||
i = SIGTRAP;
|
||||
break;
|
||||
|
||||
case T_ASTFLT: /* system async trap, cannot happen */
|
||||
goto dopanic;
|
||||
|
||||
case T_ASTFLT|T_USER: /* user async trap */
|
||||
/*
|
||||
* Kernel AST (should not happen)
|
||||
*/
|
||||
case T_ASTFLT:
|
||||
panictrap(type, code, v, &frame);
|
||||
/*
|
||||
* User AST
|
||||
*/
|
||||
case T_ASTFLT|T_USER:
|
||||
astpending = 0;
|
||||
/*
|
||||
* We check for software interrupts first. This is because
|
||||
|
@ -339,9 +568,11 @@ copyfault:
|
|||
* IPL while processing the SIR.
|
||||
*/
|
||||
spl1();
|
||||
/* fall into... */
|
||||
|
||||
case T_SSIR: /* software interrupt */
|
||||
/*FALLTHROUGH*/
|
||||
/*
|
||||
* Software interrupt
|
||||
*/
|
||||
case T_SSIR:
|
||||
case T_SSIR|T_USER:
|
||||
if (ssir & SIR_NET) {
|
||||
siroff(SIR_NET);
|
||||
|
@ -367,204 +598,26 @@ copyfault:
|
|||
p->p_flag &= ~SOWEUPC;
|
||||
}
|
||||
#endif
|
||||
goto out;
|
||||
|
||||
case T_MMUFLT: /* kernel mode page fault */
|
||||
/* fall into ... */
|
||||
|
||||
userret(p, frame.f_pc, &syst);
|
||||
return;
|
||||
/*
|
||||
* Kernel/User page fault
|
||||
*/
|
||||
case T_MMUFLT:
|
||||
case T_MMUFLT|T_USER: /* page fault */
|
||||
{
|
||||
register vm_offset_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;
|
||||
|
||||
|
||||
/*
|
||||
* 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 data fault
|
||||
* The last can occur during an exec() copyin where the
|
||||
* argument space is lazy-allocated.
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
/*
|
||||
* Print out some data about the fault
|
||||
*/
|
||||
if (mmudebug && cpu040) {
|
||||
printf ("68040 access error: pc %x, code %x, ea %x, fa %x\n",
|
||||
frame.f_pc, code, frame.f_fmt7.f_ea, v);
|
||||
if (curpcb)
|
||||
printf (" curpcb %x ->pcb_ustp %x / %x\n", curpcb,
|
||||
curpcb->pcb_ustp, curpcb->pcb_ustp << PG_SHIFT);
|
||||
}
|
||||
#endif
|
||||
if (type == T_MMUFLT &&
|
||||
(!p->p_addr->u_pcb.pcb_onfault ||
|
||||
(cpu040 && (code & SSW_TMMASK) == FC_SUPERD) ||
|
||||
(!cpu040 && (code & (SSW_DF|FC_SUPERD)) ==
|
||||
(SSW_DF|FC_SUPERD))))
|
||||
map = kernel_map;
|
||||
else
|
||||
map = &vm->vm_map;
|
||||
if ((cpu040 && (code & SSW_RW040) == 0) ||
|
||||
(!cpu040 && (code & (SSW_DF|SSW_RW)) ==
|
||||
SSW_DF)) /* what about RMW? */
|
||||
ftype = VM_PROT_READ | VM_PROT_WRITE;
|
||||
else
|
||||
ftype = VM_PROT_READ;
|
||||
va = trunc_page((vm_offset_t)v);
|
||||
#ifdef DEBUG
|
||||
if (map == kernel_map && va == 0) {
|
||||
printf("trap: bad kernel access at %x\n", v);
|
||||
goto dopanic;
|
||||
}
|
||||
#endif
|
||||
#ifndef no_386bsd_code
|
||||
/*
|
||||
* XXX: rude hack to make stack limits "work"
|
||||
*/
|
||||
nss = 0;
|
||||
if ((caddr_t)va >= vm->vm_maxsaddr && map != kernel_map) {
|
||||
nss = clrnd(btoc(USRSTACK - (unsigned)va));
|
||||
if (nss > btoc(p->p_rlimit[RLIMIT_STACK].rlim_cur)) {
|
||||
/*pg("trap rlimit %d, maxsaddr %x va %x ", nss, vm->vm_maxsaddr, va);*/
|
||||
rv = KERN_FAILURE;
|
||||
goto nogo;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
if (mmudebug)
|
||||
printf("vm_fault(%x,%x,%d,0)\n", map, va, ftype);
|
||||
#endif
|
||||
rv = vm_fault(map, va, ftype, FALSE);
|
||||
#ifdef DEBUG
|
||||
if (mmudebug)
|
||||
printf("vmfault %s %x returned %d\n", map == kernel_map ? "kernel" : "user", va, rv);
|
||||
#endif
|
||||
|
||||
if (cpu040) {
|
||||
if(rv != KERN_SUCCESS) {
|
||||
goto nogo;
|
||||
}
|
||||
|
||||
|
||||
/* Okay folks, here's the deal. The 68040 doesn't re-run instructions
|
||||
that cause write page faults (unless due to a move16 isntruction).
|
||||
So once the page is repaired, we have to write the value of WB2D
|
||||
out to memory ourselves. Because the writeback could possibly span
|
||||
two pages in memory, so we need to check both "ends" of the address
|
||||
to see if they are in the same page or not. If not, then we need
|
||||
to make sure the second page is valid, and bring it into memory if
|
||||
it's not.
|
||||
|
||||
This whole process needs to be repeated for WB3 as well. <sigh> */
|
||||
|
||||
/* WB1 Valid? */
|
||||
if (frame.f_fmt7.f_wb1s & WBS_VALID)
|
||||
{
|
||||
/* Panic for now */
|
||||
printf ("trap: wb1 was valid, but I'm not ready to do it\n");
|
||||
goto dopanic;
|
||||
}
|
||||
|
||||
/* WB2 Valid? */
|
||||
if(frame.f_fmt7.f_wb2s & WBS_VALID &&
|
||||
/* We can skip WB2 if it's for a move16 instruction */
|
||||
!((frame.f_fmt7.f_wb2s & WBS_TTMASK) == WBS_TT_MOVE16))
|
||||
{
|
||||
if (_write_back (2, frame.f_fmt7.f_wb2s, frame.f_fmt7.f_wb2d,
|
||||
frame.f_fmt7.f_wb2a, map) != KERN_SUCCESS)
|
||||
goto nogo;
|
||||
if ((frame.f_fmt7.f_wb2s & WBS_TMMASK) != (code & SSW_TMMASK))
|
||||
goto dopanic;
|
||||
}
|
||||
|
||||
/* WB3 Valid? */
|
||||
if(frame.f_fmt7.f_wb3s & WBS_VALID)
|
||||
{
|
||||
vm_map_t wb3_map;
|
||||
|
||||
if ((frame.f_fmt7.f_wb3s & WBS_TMMASK) == WBS_TM_SDATA)
|
||||
wb3_map = kernel_map;
|
||||
else
|
||||
wb3_map = &vm->vm_map;
|
||||
if (_write_back (3, frame.f_fmt7.f_wb3s, frame.f_fmt7.f_wb3d,
|
||||
frame.f_fmt7.f_wb3a, wb3_map) != KERN_SUCCESS)
|
||||
goto nogo;
|
||||
#ifdef DEBUG
|
||||
if (mmudebug & 2)
|
||||
goto dopanic;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef no_386bsd_code
|
||||
/*
|
||||
* If this was a stack access we keep track of the maximum
|
||||
* accessed stack size. Also, if vm_fault gets a protection
|
||||
* failure it is due to accessing the stack region outside
|
||||
* the current limit and we need to reflect that as an access
|
||||
* error.
|
||||
*/
|
||||
if ((caddr_t)va >= vm->vm_maxsaddr && map != kernel_map) {
|
||||
if (rv == KERN_SUCCESS) {
|
||||
nss = clrnd(btoc(USRSTACK-(unsigned)va));
|
||||
if (nss > vm->vm_ssize)
|
||||
vm->vm_ssize = nss;
|
||||
} else if (rv == KERN_PROTECTION_FAILURE)
|
||||
rv = KERN_INVALID_ADDRESS;
|
||||
}
|
||||
|
||||
if (rv == KERN_SUCCESS) {
|
||||
if (type == T_MMUFLT)
|
||||
return;
|
||||
goto out;
|
||||
}
|
||||
#else /* use hacky 386bsd_code */
|
||||
if (rv == KERN_SUCCESS) {
|
||||
/*
|
||||
* XXX: continuation of rude stack hack
|
||||
*/
|
||||
if (nss > vm->vm_ssize)
|
||||
vm->vm_ssize = nss;
|
||||
if (type == T_MMUFLT)
|
||||
return;
|
||||
goto out;
|
||||
}
|
||||
nogo:
|
||||
#endif
|
||||
if (type == T_MMUFLT) {
|
||||
if (p->p_addr->u_pcb.pcb_onfault)
|
||||
goto copyfault;
|
||||
printf("vm_fault(%x, %x, %x, 0) -> %x\n",
|
||||
map, va, ftype, rv);
|
||||
printf(" type %x, code [mmu,,ssw]: %x\n",
|
||||
type, code);
|
||||
goto dopanic;
|
||||
}
|
||||
ucode = v;
|
||||
i = (rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV;
|
||||
break;
|
||||
}
|
||||
trapmmufault(type, code, v, &frame, p, &syst);
|
||||
return;
|
||||
}
|
||||
if (i != SIGTRAP)
|
||||
printf("trapsignal(%d, %d, %d, %x, %x)\n", p->p_pid, i, ucode, v, frame.f_regs[PC]);
|
||||
|
||||
#ifdef DEBUG
|
||||
if (mmudebug & 2) /* Panic if bit 1 of mmudebug set */
|
||||
goto dopanic;
|
||||
if (i != SIGTRAP)
|
||||
printf("trapsignal(%d, %d, %d, %x, %x)\n", p->p_pid, i,
|
||||
ucode, v, frame.f_regs[PC]);
|
||||
#endif
|
||||
trapsignal(p, i, ucode);
|
||||
if ((type & T_USER) == 0)
|
||||
return;
|
||||
out:
|
||||
userret(p, frame.f_pc, syst);
|
||||
userret(p, frame.f_pc, &syst);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -696,7 +749,7 @@ syscall(code, frame)
|
|||
p->p_md.md_flags &= ~MDP_STACKADJ;
|
||||
}
|
||||
#endif
|
||||
userret(p, frame.f_pc, syst);
|
||||
userret(p, frame.f_pc, &syst);
|
||||
#ifdef KTRACE
|
||||
if (KTRPOINT(p, KTR_SYSRET))
|
||||
ktrsysret(p->p_tracep, code, error, rval[0]);
|
||||
|
|
Loading…
Reference in New Issue