xref: /netbsd/sys/arch/amiga/amiga/trap.c (revision 5f04920c)
1*5f04920cSrin /*	$NetBSD: trap.c,v 1.139 2020/08/10 10:51:21 rin Exp $	*/
2aad01611Sagc 
3aad01611Sagc /*
48ac3875aSrmind  * Copyright (c) 1988 University of Utah.
5aad01611Sagc  * Copyright (c) 1982, 1986, 1990 The Regents of the University of California.
6aad01611Sagc  * All rights reserved.
7aad01611Sagc  *
8aad01611Sagc  * This code is derived from software contributed to Berkeley by
9aad01611Sagc  * the Systems Programming Group of the University of Utah Computer
10aad01611Sagc  * Science Department.
11aad01611Sagc  *
12aad01611Sagc  * Redistribution and use in source and binary forms, with or without
13aad01611Sagc  * modification, are permitted provided that the following conditions
14aad01611Sagc  * are met:
15aad01611Sagc  * 1. Redistributions of source code must retain the above copyright
16aad01611Sagc  *    notice, this list of conditions and the following disclaimer.
17aad01611Sagc  * 2. Redistributions in binary form must reproduce the above copyright
18aad01611Sagc  *    notice, this list of conditions and the following disclaimer in the
19aad01611Sagc  *    documentation and/or other materials provided with the distribution.
20aad01611Sagc  * 3. Neither the name of the University nor the names of its contributors
21aad01611Sagc  *    may be used to endorse or promote products derived from this software
22aad01611Sagc  *    without specific prior written permission.
23aad01611Sagc  *
24aad01611Sagc  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25aad01611Sagc  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26aad01611Sagc  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27aad01611Sagc  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28aad01611Sagc  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29aad01611Sagc  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30aad01611Sagc  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31aad01611Sagc  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32aad01611Sagc  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33aad01611Sagc  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34aad01611Sagc  * SUCH DAMAGE.
35aad01611Sagc  *
36aad01611Sagc  * from: Utah $Hdr: trap.c 1.32 91/04/06$
37aad01611Sagc  *
38aad01611Sagc  *	@(#)trap.c	7.15 (Berkeley) 8/2/91
39aad01611Sagc  */
40ec77f0b3Scgd 
41466e784eSjonathan #include "opt_ddb.h"
42c05dadc1Sitohy #include "opt_execfmt.h"
438aee7782Sthorpej #include "opt_compat_sunos.h"
44d505b189Smartin #include "opt_fpu_emulate.h"
45bd01b4a3Smrg #include "opt_m68k_arch.h"
46971b8956Sthorpej 
471ea4df81Saymeric #include <sys/cdefs.h>
48*5f04920cSrin __KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.139 2020/08/10 10:51:21 rin Exp $");
491ea4df81Saymeric 
50b700b86fSchopps #include <sys/param.h>
51b700b86fSchopps #include <sys/systm.h>
52b700b86fSchopps #include <sys/proc.h>
53b700b86fSchopps #include <sys/acct.h>
54b700b86fSchopps #include <sys/kernel.h>
55b700b86fSchopps #include <sys/signalvar.h>
56b700b86fSchopps #include <sys/resourcevar.h>
57b700b86fSchopps #include <sys/syslog.h>
5863451f69Schopps #include <sys/syscall.h>
59ef56cc40Scl #include <sys/userret.h>
60d73ce018Syamt #include <sys/kauth.h>
619af91bf2Schopps 
62dc9188e3Smhitch #include <uvm/uvm_extern.h>
63dc9188e3Smhitch 
64b700b86fSchopps #include <machine/psl.h>
65b700b86fSchopps #include <machine/trap.h>
66b700b86fSchopps #include <machine/cpu.h>
67da876597Srmind #include <machine/pcb.h>
68b700b86fSchopps #include <machine/pte.h>
6933e84123Smw 
70006b6172Sis #include <m68k/fpe/fpu_emulate.h>
7133014f7bSis #include <m68k/cacheops.h>
72006b6172Sis 
73df9af289Schopps #ifdef COMPAT_SUNOS
74df9af289Schopps #include <compat/sunos/sunos_syscall.h>
75df9af289Schopps extern struct emul emul_sunos;
76df9af289Schopps #endif
77df9af289Schopps 
789caa601eSchopps /*
799caa601eSchopps  * XXX Hack until I can figure out what to do about this code's removal
809caa601eSchopps  * from m68k/include/frame.h
819caa601eSchopps  */
829caa601eSchopps 
839caa601eSchopps /* 68040 fault frame */
849caa601eSchopps #define SSW_CP		0x8000		/* Continuation - Floating-Point Post*/
859caa601eSchopps #define SSW_CU		0x4000		/* Continuation - Unimpl. FP */
869caa601eSchopps #define SSW_CT		0x2000		/* Continuation - Trace */
879caa601eSchopps #define SSW_CM		0x1000		/* Continuation - MOVEM */
889caa601eSchopps #define SSW_MA		0x0800		/* Misaligned access */
899caa601eSchopps #define SSW_ATC		0x0400		/* ATC fault */
909caa601eSchopps #define SSW_LK		0x0200		/* Locked transfer */
919caa601eSchopps #define SSW_RW040	0x0100		/* Read/Write */
929caa601eSchopps #define SSW_SZMASK	0x0060		/* Transfer size */
939caa601eSchopps #define SSW_TTMASK	0x0018		/* Transfer type */
949caa601eSchopps #define SSW_TMMASK	0x0007		/* Transfer modifier */
959caa601eSchopps 
969caa601eSchopps #define WBS_TMMASK	0x0007
979caa601eSchopps #define WBS_TTMASK	0x0018
989caa601eSchopps #define WBS_SZMASK	0x0060
999caa601eSchopps #define WBS_VALID	0x0080
1009caa601eSchopps 
1019caa601eSchopps #define WBS_SIZE_BYTE	0x0020
1029caa601eSchopps #define WBS_SIZE_WORD	0x0040
1039caa601eSchopps #define WBS_SIZE_LONG	0x0000
1049caa601eSchopps #define WBS_SIZE_LINE	0x0060
1059caa601eSchopps 
1069caa601eSchopps #define WBS_TT_NORMAL	0x0000
1079caa601eSchopps #define WBS_TT_MOVE16	0x0008
1089caa601eSchopps #define WBS_TT_ALTFC	0x0010
1099caa601eSchopps #define WBS_TT_ACK	0x0018
1109caa601eSchopps 
1119caa601eSchopps #define WBS_TM_PUSH	0x0000
1129caa601eSchopps #define WBS_TM_UDATA	0x0001
1139caa601eSchopps #define WBS_TM_UCODE	0x0002
1149caa601eSchopps #define WBS_TM_MMUTD	0x0003
1159caa601eSchopps #define WBS_TM_MMUTC	0x0004
1169caa601eSchopps #define WBS_TM_SDATA	0x0005
1179caa601eSchopps #define WBS_TM_SCODE	0x0006
1189caa601eSchopps #define WBS_TM_RESV	0x0007
1199caa601eSchopps 
1209caa601eSchopps #define	MMUSR_PA_MASK	0xfffff000
1219caa601eSchopps #define MMUSR_B		0x00000800
1229caa601eSchopps #define MMUSR_G		0x00000400
1239caa601eSchopps #define MMUSR_U1	0x00000200
1249caa601eSchopps #define MMUSR_U0	0x00000100
1259caa601eSchopps #define MMUSR_S		0x00000080
1269caa601eSchopps #define MMUSR_CM	0x00000060
1279caa601eSchopps #define MMUSR_M		0x00000010
1289caa601eSchopps #define MMUSR_0		0x00000008
1299caa601eSchopps #define MMUSR_W		0x00000004
1309caa601eSchopps #define MMUSR_T		0x00000002
1319caa601eSchopps #define MMUSR_R		0x00000001
132f6ab1073Sis 
133f6ab1073Sis #define FSLW_STRING	"\020\1SEE\3BPE\4TTR\5WE\6RE\7TWE\010WP\011SP" \
134f6ab1073Sis 			"\012PF\013IL\014PTB\015PTA\016SBE\017PBE"
1359caa601eSchopps /*
1369caa601eSchopps  * XXX End hack
1379caa601eSchopps  */
138f49dd3efSscottr 
139f49dd3efSscottr int	astpending;
140f49dd3efSscottr 
141dc6e239cSjandberg const char *trap_type[] = {
14233e84123Smw 	"Bus error",
14333e84123Smw 	"Address error",
14433e84123Smw 	"Illegal instruction",
14533e84123Smw 	"Zero divide",
14633e84123Smw 	"CHK instruction",
14733e84123Smw 	"TRAPV instruction",
14833e84123Smw 	"Privilege violation",
14933e84123Smw 	"Trace trap",
15033e84123Smw 	"MMU fault",
15133e84123Smw 	"SSIR trap",
15233e84123Smw 	"Format error",
15333e84123Smw 	"68881 exception",
15433e84123Smw 	"Coprocessor violation",
15533e84123Smw 	"Async system trap"
15633e84123Smw };
15706149f6fSmw int	trap_types = sizeof trap_type / sizeof trap_type[0];
15833e84123Smw 
15933e84123Smw /*
16033e84123Smw  * Size of various exception stack frames (minus the standard 8 bytes)
16133e84123Smw  */
16233e84123Smw short	exframesize[] = {
163f6ab1073Sis 	FMT0SIZE,	/* type 0 - normal (68020/030/040/060) */
16433e84123Smw 	FMT1SIZE,	/* type 1 - throwaway (68020/030/040) */
165f6ab1073Sis 	FMT2SIZE,	/* type 2 - normal 6-word (68020/030/040/060) */
166f6ab1073Sis 	FMT3SIZE,	/* type 3 - FP post-instruction (68040/060) */
167f6ab1073Sis 	FMT4SIZE,	/* type 4 - access error/fp disabled (68060) */
168f6ab1073Sis 	-1, -1,		/* type 5-6 - undefined */
16906149f6fSmw 	FMT7SIZE,	/* type 7 - access error (68040) */
17033e84123Smw 	58,		/* type 8 - bus fault (68010) */
17133e84123Smw 	FMT9SIZE,	/* type 9 - coprocessor mid-instruction (68020/030) */
17233e84123Smw 	FMTASIZE,	/* type A - short bus fault (68020/030) */
17333e84123Smw 	FMTBSIZE,	/* type B - long bus fault (68020/030) */
17433e84123Smw 	-1, -1, -1, -1	/* type C-F - undefined */
17533e84123Smw };
17633e84123Smw 
17733e84123Smw #ifdef DEBUG
17833e84123Smw int mmudebug = 0;
17933e84123Smw #endif
18033e84123Smw 
18106149f6fSmw extern struct pcb *curpcb;
18208fd7bc9Saymeric int _write_back(u_int, u_int, u_int, u_int, struct vm_map *);
18323bc2503Sthorpej static void userret(struct lwp *, int, u_quad_t);
18408fd7bc9Saymeric void panictrap(int, u_int, u_int, struct frame *);
18504aa4da3Schs void trapcpfault(struct lwp *, struct frame *, int);
18623bc2503Sthorpej void trapmmufault(int, u_int, u_int, struct frame *, struct lwp *,
18708fd7bc9Saymeric 			u_quad_t);
188d2eac2f6Smhitch void trap(struct frame *, int, u_int, u_int);
189db6f1b13Sveego #ifdef DDB
190db6f1b13Sveego #include <m68k/db_machdep.h>
19108fd7bc9Saymeric int kdb_trap(int, db_regs_t *);
192db6f1b13Sveego #endif
19308fd7bc9Saymeric void _wb_fault(void);
194db6f1b13Sveego 
19506149f6fSmw 
19663451f69Schopps static void
userret(struct lwp * l,int pc,u_quad_t oticks)197454af1c0Sdsl userret(struct lwp *l, int pc, u_quad_t oticks)
19863451f69Schopps {
19923bc2503Sthorpej 	struct proc *p = l->l_proc;
20063451f69Schopps 
201ef56cc40Scl 	/* Invoke MI userret code */
202ef56cc40Scl 	mi_userret(l);
20323bc2503Sthorpej 
2046ceb2246Schopps 	/*
2056ceb2246Schopps 	 * If profiling, charge recent system time.
2066ceb2246Schopps 	 */
207b07ec3fcSad 	if (p->p_stflag & PST_PROFIL) {
2086ceb2246Schopps 		extern int psratio;
20963451f69Schopps 
210b07ec3fcSad 		addupc_task(l, pc, (int)(p->p_sticks - oticks) * psratio);
21163451f69Schopps 	}
21263451f69Schopps }
21363451f69Schopps 
2144350a7f2Sscw /*
2154350a7f2Sscw  * Used by the common m68k syscall() and child_return() functions.
2164350a7f2Sscw  * XXX: Temporary until all m68k ports share common trap()/userret() code.
2174350a7f2Sscw  */
21823bc2503Sthorpej void machine_userret(struct lwp *, struct frame *, u_quad_t);
2194350a7f2Sscw 
2204350a7f2Sscw void
machine_userret(struct lwp * l,struct frame * f,u_quad_t t)221454af1c0Sdsl machine_userret(struct lwp *l, struct frame *f, u_quad_t t)
2224350a7f2Sscw {
2234350a7f2Sscw 
22423bc2503Sthorpej 	userret(l, f->f_pc, t);
2254350a7f2Sscw }
2264350a7f2Sscw 
227602ef3f3Schopps void
panictrap(int type,u_int code,u_int v,struct frame * fp)22882357f6dSdsl panictrap(int type, u_int code, u_int v, struct frame *fp)
229602ef3f3Schopps {
23012490842Swiz 	static int panicking = 0;
23112490842Swiz 	if (panicking++ == 0) {
232ca36ac9eSchristos 		printf("trap type %d, code = %x, v = %x\n", type, code, v);
2331cd753c6Sthorpej 		regdump((struct trapframe *)fp, 128);
234602ef3f3Schopps 	}
235602ef3f3Schopps 	type &= ~T_USER;
236319c5313Schopps #ifdef DEBUG
237602ef3f3Schopps 	DCIS(); 		/* XXX? push cache */
238319c5313Schopps #endif
239602ef3f3Schopps 	if ((u_int)type < trap_types)
240602ef3f3Schopps 		panic(trap_type[type]);
241602ef3f3Schopps 	panic("trap");
242602ef3f3Schopps 	/*NOTREACHED*/
243602ef3f3Schopps }
244602ef3f3Schopps 
245602ef3f3Schopps /*
246602ef3f3Schopps  * return to fault handler
247602ef3f3Schopps  */
248602ef3f3Schopps void
trapcpfault(struct lwp * l,struct frame * fp,int error)24904aa4da3Schs trapcpfault(struct lwp *l, struct frame *fp, int error)
250602ef3f3Schopps {
2513dc24f5aSrmind 	struct pcb *pcb = lwp_getpcb(l);
2523dc24f5aSrmind 
253602ef3f3Schopps 	/*
254602ef3f3Schopps 	 * We have arranged to catch this fault in one of the
255602ef3f3Schopps 	 * copy to/from user space routines, set PC to return to
256602ef3f3Schopps 	 * indicated location and set flag informing buserror code
257602ef3f3Schopps 	 * that it may need to clean up stack frame.
258602ef3f3Schopps 	 */
259602ef3f3Schopps 	fp->f_stackadj = exframesize[fp->f_format];
260602ef3f3Schopps 	fp->f_format = fp->f_vector = 0;
2613dc24f5aSrmind 	fp->f_pc = (int)pcb->pcb_onfault;
26204aa4da3Schs 	fp->f_regs[D0] = error;
263602ef3f3Schopps }
264602ef3f3Schopps 
265f6ab1073Sis int donomore = 0;
266f6ab1073Sis 
267602ef3f3Schopps void
trapmmufault(int type,u_int code,u_int v,struct frame * fp,struct lwp * l,u_quad_t sticks)26882357f6dSdsl trapmmufault(int type, u_int code, u_int v, struct frame *fp, struct lwp *l, u_quad_t sticks)
269602ef3f3Schopps {
270e138ae4fSis #if defined(DEBUG) && defined(M68060)
271f6ab1073Sis 	static u_int oldcode=0, oldv=0;
272f6ab1073Sis 	static struct proc *oldp=0;
273e138ae4fSis #endif
274821ec03eSchs 	extern struct vm_map *kernel_map;
27523bc2503Sthorpej 	struct proc *p = l->l_proc;
276db6f1b13Sveego 	struct vmspace *vm = NULL;
27704aa4da3Schs 	struct vm_map *map;
2783dc24f5aSrmind 	struct pcb *pcb;
27904aa4da3Schs 	void *onfault;
280602ef3f3Schopps 	vm_prot_t ftype;
281744246faSis 	vaddr_t va;
28241692372Scl 	ksiginfo_t ksi;
283602ef3f3Schopps 	int rv;
284602ef3f3Schopps 
28504aa4da3Schs 	pcb = lwp_getpcb(l);
28604aa4da3Schs 	onfault = pcb->pcb_onfault;
28704aa4da3Schs 
28868723a99Sthorpej 	KSI_INIT_TRAP(&ksi);
28941692372Scl 	ksi.ksi_trap = type & ~T_USER;
29041692372Scl 
291602ef3f3Schopps 	/*
292602ef3f3Schopps 	 * It is only a kernel address space fault iff:
293602ef3f3Schopps 	 * 	1. (type & T_USER) == 0  and
294602ef3f3Schopps 	 * 	2. pcb_onfault not set or
295602ef3f3Schopps 	 *	3. pcb_onfault set but supervisor space data fault
296602ef3f3Schopps 	 * The last can occur during an exec() copyin where the
297602ef3f3Schopps 	 * argument space is lazy-allocated.
298602ef3f3Schopps 	 */
299602ef3f3Schopps #ifdef DEBUG
300602ef3f3Schopps 	/*
301602ef3f3Schopps 	 * Print out some data about the fault
302602ef3f3Schopps 	 */
3030cd79344Sjtc #ifdef DEBUG_PAGE0
3048818afa4Sthorpej 	if (v < PAGE_SIZE)				/* XXX PAGE0 */
3055dcc668eSchopps 		mmudebug |= 0x100;			/* XXX PAGE0 */
3060cd79344Sjtc #endif
30722087826Schopps 	if (mmudebug && mmutype == MMU_68040) {
308f6ab1073Sis #ifdef M68060
309f6ab1073Sis 		if (machineid & AMIGA_68060) {
31035c9c776Sthorpej 			if (--donomore == 0 || mmudebug & 1) {
31135c9c776Sthorpej 				char bits[64];
3129a5d3f28Schristos 				snprintb(bits, sizeof(bits), FSLW_STRING, code);
31335c9c776Sthorpej 				printf ("68060 access error: pc %x, code %s,"
3149a5d3f28Schristos 				     " ea %x\n", fp->f_pc, bits, v);
31535c9c776Sthorpej 			}
316f6ab1073Sis 			if (p == oldp && v == oldv && code == oldcode)
317f6ab1073Sis 				panic("Identical fault backtoback!");
318f6ab1073Sis 			if (donomore == 0)
319f6ab1073Sis 				panic("Tired of faulting.");
320f6ab1073Sis 			oldp = p;
321f6ab1073Sis 			oldv = v;
322f6ab1073Sis 			oldcode = code;
323f6ab1073Sis 		} else
324f6ab1073Sis #endif
325ca36ac9eSchristos 		printf("68040 access error: pc %x, code %x,"
326602ef3f3Schopps 		    " ea %x, fa %x\n", fp->f_pc, code, fp->f_fmt7.f_ea, v);
327602ef3f3Schopps 		if (curpcb)
328db6e62f6Sis 			printf(" curpcb %p\n", curpcb);
329f6ab1073Sis 
330f6ab1073Sis 
3315dcc668eSchopps #ifdef DDB						/* XXX PAGE0 */
3328818afa4Sthorpej 		if (v < PAGE_SIZE)			/* XXX PAGE0 */
3335dcc668eSchopps 			Debugger();			/* XXX PAGE0 */
3345dcc668eSchopps #endif							/* XXX PAGE0 */
335602ef3f3Schopps 	}
3360cd79344Sjtc #ifdef DEBUG_PAGE0
3374e276bb0Schopps 	mmudebug &= ~0x100;				/* XXX PAGE0 */
338602ef3f3Schopps #endif
3390cd79344Sjtc #endif
340319c5313Schopps 
341319c5313Schopps 	if (p)
342319c5313Schopps 		vm = p->p_vmspace;
343319c5313Schopps 
34404aa4da3Schs 	if (type == T_MMUFLT && (l == &lwp0 || onfault == 0 || (
345f6ab1073Sis #ifdef M68060
346f6ab1073Sis 	     machineid & AMIGA_68060 ? code & FSLW_TM_SV :
347f6ab1073Sis #endif
348f6ab1073Sis 	     mmutype == MMU_68040 ? (code & SSW_TMMASK) == FC_SUPERD :
349f6ab1073Sis 	     (code & (SSW_DF|FC_SUPERD)) == (SSW_DF|FC_SUPERD))))
350602ef3f3Schopps 		map = kernel_map;
351154d3024Srmind 	else
352602ef3f3Schopps 		map = &vm->vm_map;
353f6ab1073Sis 
3549caa601eSchopps 	if (
355f6ab1073Sis #ifdef M68060
356f6ab1073Sis 	    machineid & AMIGA_68060 ? code & FSLW_RW_W :
357f6ab1073Sis #endif
3589b0f085dSmhitch 	    mmutype == MMU_68040 ? (code & (SSW_LK|SSW_RW040)) != SSW_RW040 :
3599b0f085dSmhitch 	    ((code & SSW_DF) != 0 &&
3609b0f085dSmhitch 	    ((code & SSW_RW) == 0 || (code & SSW_RM) != 0)))
361b744097aSchs 		ftype = VM_PROT_WRITE;
362602ef3f3Schopps 	else
363602ef3f3Schopps 		ftype = VM_PROT_READ;
364744246faSis 	va = trunc_page((vaddr_t)v);
365602ef3f3Schopps #ifdef DEBUG
366602ef3f3Schopps 	if (map == kernel_map && va == 0) {
367ca36ac9eSchristos 		printf("trap: bad kernel access at %x pc %x\n", v, fp->f_pc);
368602ef3f3Schopps 		panictrap(type, code, v, fp);
369602ef3f3Schopps 	}
370602ef3f3Schopps 
371602ef3f3Schopps 	if (mmudebug)
37247fbb9d8Sdrochner 		printf("vm_fault(%p,%lx,%d)\n", map, va, ftype);
373602ef3f3Schopps #endif
374602ef3f3Schopps 
37504aa4da3Schs 	pcb->pcb_onfault = NULL;
37647fbb9d8Sdrochner 	rv = uvm_fault(map, va, ftype);
37704aa4da3Schs 	pcb->pcb_onfault = onfault;
378602ef3f3Schopps 
379602ef3f3Schopps #ifdef DEBUG
380602ef3f3Schopps 	if (mmudebug)
381ca36ac9eSchristos 		printf("vmfault %s %lx returned %d\n",
382602ef3f3Schopps 		    map == kernel_map ? "kernel" : "user", va, rv);
383602ef3f3Schopps #endif
3849ea6b6e3Schs 
385f6ab1073Sis #ifdef M68060
386f6ab1073Sis 	if ((machineid & AMIGA_68060) == 0 && mmutype == MMU_68040) {
387f6ab1073Sis #else
38822087826Schopps 	if (mmutype == MMU_68040) {
389f6ab1073Sis #endif
390ac3bc537Schs 		if (rv != 0) {
391602ef3f3Schopps 			goto nogo;
392602ef3f3Schopps 		}
393602ef3f3Schopps 
394602ef3f3Schopps 		/*
395602ef3f3Schopps 		 * The 68040 doesn't re-run instructions that cause
396602ef3f3Schopps 		 * write page faults (unless due to a move16 isntruction).
397602ef3f3Schopps 		 * So once the page is repaired, we have to write the
398602ef3f3Schopps 		 * value of WB2D out to memory ourselves.  Because
399602ef3f3Schopps 		 * the writeback could possibly span two pages in
400602ef3f3Schopps 		 * memory, so we need to check both "ends" of the
401602ef3f3Schopps 		 * address to see if they are in the same page or not.
402602ef3f3Schopps 		 * If not, then we need to make sure the second page
403602ef3f3Schopps 		 * is valid, and bring it into memory if it's not.
404602ef3f3Schopps 		 *
405602ef3f3Schopps 		 * This whole process needs to be repeated for WB3 as well.
406602ef3f3Schopps 		 * <sigh>
407602ef3f3Schopps 		 */
408602ef3f3Schopps 
409602ef3f3Schopps 		/* Check WB1 */
410602ef3f3Schopps 		if (fp->f_fmt7.f_wb1s & WBS_VALID) {
411ca36ac9eSchristos 			printf ("trap: wb1 was valid, not handled yet\n");
412602ef3f3Schopps 			panictrap(type, code, v, fp);
413602ef3f3Schopps 		}
414602ef3f3Schopps 
415602ef3f3Schopps 		/*
416602ef3f3Schopps 		 * Check WB2
417602ef3f3Schopps 		 * skip if it's for a move16 instruction
418602ef3f3Schopps 		 */
419602ef3f3Schopps 		if(fp->f_fmt7.f_wb2s & WBS_VALID &&
420602ef3f3Schopps 		   ((fp->f_fmt7.f_wb2s & WBS_TTMASK)==WBS_TT_MOVE16) == 0) {
421602ef3f3Schopps 			if (_write_back(2, fp->f_fmt7.f_wb2s,
422ac3bc537Schs 			    fp->f_fmt7.f_wb2d, fp->f_fmt7.f_wb2a, map) != 0)
423602ef3f3Schopps 				goto nogo;
424602ef3f3Schopps 			if ((fp->f_fmt7.f_wb2s & WBS_TMMASK)
425602ef3f3Schopps 			    != (code & SSW_TMMASK))
426602ef3f3Schopps 				panictrap(type, code, v, fp);
427602ef3f3Schopps 		}
428602ef3f3Schopps 
429602ef3f3Schopps 		/* Check WB3 */
430602ef3f3Schopps 		if(fp->f_fmt7.f_wb3s & WBS_VALID) {
431821ec03eSchs 			struct vm_map *wb3_map;
432602ef3f3Schopps 
433602ef3f3Schopps 			if ((fp->f_fmt7.f_wb3s & WBS_TMMASK) == WBS_TM_SDATA)
434602ef3f3Schopps 				wb3_map = kernel_map;
435602ef3f3Schopps 			else
436602ef3f3Schopps 				wb3_map = &vm->vm_map;
437602ef3f3Schopps 			if (_write_back(3, fp->f_fmt7.f_wb3s,
438ac3bc537Schs 			    fp->f_fmt7.f_wb3d, fp->f_fmt7.f_wb3a, wb3_map) != 0)
439602ef3f3Schopps 				goto nogo;
440602ef3f3Schopps 		}
441602ef3f3Schopps 	}
442602ef3f3Schopps 
443602ef3f3Schopps 	/*
444602ef3f3Schopps 	 * If this was a stack access we keep track of the maximum
445602ef3f3Schopps 	 * accessed stack size.  Also, if vm_fault gets a protection
446602ef3f3Schopps 	 * failure it is due to accessing the stack region outside
447602ef3f3Schopps 	 * the current limit and we need to reflect that as an access
448602ef3f3Schopps 	 * error.
449602ef3f3Schopps 	 */
450ac3bc537Schs 	if (rv == 0) {
45153524e44Schristos 		if (map != kernel_map && (void *)va >= vm->vm_maxsaddr)
45264969161Sjdolecek 			uvm_grow(p, va);
453602ef3f3Schopps 
454602ef3f3Schopps 		if (type == T_MMUFLT)
455602ef3f3Schopps 			return;
45623bc2503Sthorpej 		userret(l, fp->f_pc, sticks);
457602ef3f3Schopps 		return;
458602ef3f3Schopps 	}
459602ef3f3Schopps nogo:
460602ef3f3Schopps 	if (type == T_MMUFLT) {
46104aa4da3Schs 		if (onfault) {
46204aa4da3Schs 			trapcpfault(l, fp, rv);
463602ef3f3Schopps 			return;
464602ef3f3Schopps 		}
46547fbb9d8Sdrochner 		printf("uvm_fault(%p, 0x%lx, 0x%x) -> 0x%x\n",
466dc9188e3Smhitch 		    map, va, ftype, rv);
467ca36ac9eSchristos 		printf("  type %x, code [mmu,,ssw]: %x\n",
468602ef3f3Schopps 		       type, code);
469602ef3f3Schopps 		panictrap(type, code, v, fp);
470602ef3f3Schopps 	}
47141692372Scl 	ksi.ksi_addr = (void *)v;
4720eb69247Smlelstv 	switch (rv) {
4730eb69247Smlelstv 	case ENOMEM:
474ab7269f6Schs 		printf("UVM: pid %d (%s), uid %d killed: out of swap\n",
475ab7269f6Schs 		    p->p_pid, p->p_comm,
476f474dcebSad 		    l->l_cred ? kauth_cred_geteuid(l->l_cred) : -1);
47741692372Scl 		ksi.ksi_signo = SIGKILL;
4780eb69247Smlelstv 		break;
4790eb69247Smlelstv 	case EINVAL:
4800eb69247Smlelstv 		ksi.ksi_signo = SIGBUS;
4810eb69247Smlelstv 		ksi.ksi_code = BUS_ADRERR;
4820eb69247Smlelstv 		break;
4830eb69247Smlelstv 	case EACCES:
48441692372Scl 		ksi.ksi_signo = SIGSEGV;
4850eb69247Smlelstv 		ksi.ksi_code = SEGV_ACCERR;
4860eb69247Smlelstv 		break;
4870eb69247Smlelstv 	default:
4880eb69247Smlelstv 		ksi.ksi_signo = SIGSEGV;
4890eb69247Smlelstv 		ksi.ksi_code = SEGV_MAPERR;
4900eb69247Smlelstv 		break;
491ab7269f6Schs 	}
49241692372Scl 	trapsignal(l, &ksi);
493602ef3f3Schopps 	if ((type & T_USER) == 0)
494602ef3f3Schopps 		return;
49523bc2503Sthorpej 	userret(l, fp->f_pc, sticks);
496602ef3f3Schopps }
49733e84123Smw /*
49833e84123Smw  * Trap is called from locore to handle most types of processor traps,
49933e84123Smw  * including events such as simulated software interrupts/AST's.
50033e84123Smw  * System calls are broken out for efficiency.
50133e84123Smw  */
50233e84123Smw /*ARGSUSED*/
503db6f1b13Sveego void
50482357f6dSdsl trap(struct frame *fp, int type, u_int code, u_int v)
50533e84123Smw {
50623bc2503Sthorpej 	struct lwp *l;
507602ef3f3Schopps 	struct proc *p;
5083dc24f5aSrmind 	struct pcb *pcb;
50941692372Scl 	ksiginfo_t ksi;
510db6f1b13Sveego 	u_quad_t sticks = 0;
51133e84123Smw 
51223bc2503Sthorpej 	l = curlwp;
51304aa4da3Schs 	p = l->l_proc;
51404aa4da3Schs 	pcb = lwp_getpcb(l);
51504aa4da3Schs 
516ccde4787Smatt 	curcpu()->ci_data.cpu_ntrap++;
517602ef3f3Schopps 
51868723a99Sthorpej 	KSI_INIT_TRAP(&ksi);
51941692372Scl 	ksi.ksi_trap = type & ~T_USER;
52041692372Scl 
521d2eac2f6Smhitch 	if (USERMODE(fp->f_sr)) {
52233e84123Smw 		type |= T_USER;
5236ceb2246Schopps 		sticks = p->p_sticks;
524d2eac2f6Smhitch 		l->l_md.md_regs = fp->f_regs;
5252b79369cSad 		LWP_CACHE_CREDS(l, p);
52633e84123Smw 	}
52706149f6fSmw 
52806149f6fSmw #ifdef DDB
52906149f6fSmw 	if (type == T_TRACE || type == T_BREAKPOINT) {
530d2eac2f6Smhitch 		if (kdb_trap(type, (db_regs_t *)fp))
53106149f6fSmw 			return;
53206149f6fSmw 	}
53306149f6fSmw #endif
534e138ae4fSis #ifdef DEBUG
535f6ab1073Sis 	if (mmudebug & 2)
536d3662916Schristos 	printf("%s: t %x c %x v %x adj %x sr %x pc %x fmt %x vc %x\n",
537d3662916Schristos 	    __func__, type, code, v, fp->f_stackadj, fp->f_sr,
538d2eac2f6Smhitch 	    fp->f_pc, fp->f_format, fp->f_vector);
539e138ae4fSis #endif
54033e84123Smw 	switch (type) {
54133e84123Smw 	default:
542d2eac2f6Smhitch 		panictrap(type, code, v, fp);
54333e84123Smw 	/*
544602ef3f3Schopps 	 * Kernel Bus error
54533e84123Smw 	 */
546602ef3f3Schopps 	case T_BUSERR:
54704aa4da3Schs 		if (!pcb->pcb_onfault)
548d2eac2f6Smhitch 			panictrap(type, code, v, fp);
54904aa4da3Schs 		trapcpfault(l, fp, EFAULT);
55033e84123Smw 		return;
551602ef3f3Schopps 	/*
552602ef3f3Schopps 	 * User Bus/Addr error.
553602ef3f3Schopps 	 */
554602ef3f3Schopps 	case T_BUSERR|T_USER:
555602ef3f3Schopps 	case T_ADDRERR|T_USER:
55641692372Scl 		ksi.ksi_addr = (void *)v;
55741692372Scl 		ksi.ksi_signo = SIGBUS;
55841692372Scl 		ksi.ksi_code = (type == (T_BUSERR|T_USER)) ?
55941692372Scl 			BUS_OBJERR : BUS_ADRERR;
56033e84123Smw 		break;
561602ef3f3Schopps 	/*
562602ef3f3Schopps 	 * User illegal/privleged inst fault
563602ef3f3Schopps 	 */
564602ef3f3Schopps 	case T_ILLINST|T_USER:
565602ef3f3Schopps 	case T_PRIVINST|T_USER:
566d2eac2f6Smhitch 		ksi.ksi_addr = (void *)(int)fp->f_format;
56741692372Scl 				/* XXX was ILL_PRIVIN_FAULT */
56841692372Scl 		ksi.ksi_signo = SIGILL;
56941692372Scl 		ksi.ksi_code = (type == (T_PRIVINST|T_USER)) ?
57041692372Scl 			ILL_PRVOPC : ILL_ILLOPC;
571602ef3f3Schopps 		break;
572602ef3f3Schopps 	/*
573602ef3f3Schopps 	 * divde by zero, CHK/TRAPV inst
574602ef3f3Schopps 	 */
575602ef3f3Schopps 	case T_ZERODIV|T_USER:
576*5f04920cSrin 		ksi.ksi_code = FPE_INTDIV;
577602ef3f3Schopps 	case T_CHKINST|T_USER:
578602ef3f3Schopps 	case T_TRAPVINST|T_USER:
579d2eac2f6Smhitch 		ksi.ksi_addr = (void *)(int)fp->f_format;
58041692372Scl 		ksi.ksi_signo = SIGFPE;
581602ef3f3Schopps 		break;
582006b6172Sis 
583006b6172Sis 	case T_FPEMULI|T_USER:
584006b6172Sis 	case T_FPEMULD|T_USER:
585006b6172Sis #ifdef FPU_EMULATE
5863dc24f5aSrmind 		if (fpu_emulate(fp, &pcb->pcb_fpregs, &ksi) == 0)
587d2eac2f6Smhitch 			; /* XXX - Deal with tracing? (fp->f_sr & PSL_T) */
588006b6172Sis #else
589006b6172Sis 		printf("pid %d killed: no floating point support\n", p->p_pid);
59041692372Scl 		ksi.ksi_signo = SIGILL;
59141692372Scl 		ksi.ksi_code = ILL_ILLOPC;
592006b6172Sis #endif
593006b6172Sis 		break;
594006b6172Sis 
59533e84123Smw #ifdef FPCOPROC
596602ef3f3Schopps 	/*
597602ef3f3Schopps 	 * User coprocessor violation
598602ef3f3Schopps 	 */
599602ef3f3Schopps 	case T_COPERR|T_USER:
60041692372Scl 	/* XXX What is a proper response here? */
60141692372Scl 		ksi.ksi_signo = SIGFPE;
60241692372Scl 		ksi.ksi_code = FPE_FLTINV;
603602ef3f3Schopps 		break;
604602ef3f3Schopps 	/*
605602ef3f3Schopps 	 * 6888x exceptions
606602ef3f3Schopps 	 */
607602ef3f3Schopps 	case T_FPERR|T_USER:
608602ef3f3Schopps 		/*
609602ef3f3Schopps 		 * We pass along the 68881 status register which locore
610f055e182Smartin 		 * stashed in code for us.
611602ef3f3Schopps 		 */
61241692372Scl 		ksi.ksi_signo = SIGFPE;
613f055e182Smartin 		ksi.ksi_code = fpsr2siginfocode(code);
614602ef3f3Schopps 		break;
615602ef3f3Schopps 	/*
616602ef3f3Schopps 	 * Kernel coprocessor violation
617602ef3f3Schopps 	 */
618602ef3f3Schopps 	case T_COPERR:
619602ef3f3Schopps 		/*FALLTHROUGH*/
62033e84123Smw #endif
621602ef3f3Schopps 	/*
622602ef3f3Schopps 	 * Kernel format error
623602ef3f3Schopps 	 */
624602ef3f3Schopps 	case T_FMTERR:
62533e84123Smw 		/*
62633e84123Smw 		 * The user has most likely trashed the RTE or FP state info
62733e84123Smw 		 * in the stack frame of a signal handler.
62833e84123Smw 		 */
62933e84123Smw 		type |= T_USER;
630602ef3f3Schopps #ifdef DEBUG
631ca36ac9eSchristos 		printf("pid %d: kernel %s exception\n", p->p_pid,
63233e84123Smw 		    type==T_COPERR ? "coprocessor" : "format");
633602ef3f3Schopps #endif
634284c2b9aSad 		mutex_enter(p->p_lock);
635de31133fSjdolecek 		SIGACTION(p, SIGILL).sa_handler = SIG_DFL;
636de31133fSjdolecek 		sigdelset(&p->p_sigctx.ps_sigignore, SIGILL);
637de31133fSjdolecek 		sigdelset(&p->p_sigctx.ps_sigcatch, SIGILL);
638b07ec3fcSad 		sigdelset(&l->l_sigmask, SIGILL);
639284c2b9aSad 		mutex_exit(p->p_lock);
640b07ec3fcSad 
64141692372Scl 		ksi.ksi_signo = SIGILL;
642d2eac2f6Smhitch 		ksi.ksi_addr = (void *)(int)fp->f_format;
64341692372Scl 				/* XXX was ILL_RESAD_FAULT */
64441692372Scl 		ksi.ksi_code = (type == T_COPERR) ?
64541692372Scl 			ILL_COPROC : ILL_ILLOPC;
64633e84123Smw 		break;
64733e84123Smw 	/*
648602ef3f3Schopps 	 * Trace traps.
64933e84123Smw 	 *
650602ef3f3Schopps 	 * M68k NetBSD uses trap #2,
65133e84123Smw 	 * SUN 3.x uses trap #15,
65233e84123Smw 	 * KGDB uses trap #15 (for kernel breakpoints; handled elsewhere).
65333e84123Smw 	 *
654602ef3f3Schopps 	 * Amiga traps get mapped by locore.s into T_TRACE.
65533e84123Smw 	 * SUN 3.x traps get passed through as T_TRAP15 and are not really
65633e84123Smw 	 * supported yet.
65733e84123Smw 	 */
658602ef3f3Schopps 	case T_TRACE:
659602ef3f3Schopps 	case T_TRAP15:
660d2eac2f6Smhitch 		fp->f_sr &= ~PSL_T;
66141692372Scl 		ksi.ksi_signo = SIGTRAP;
66233e84123Smw 		break;
663602ef3f3Schopps 	case T_TRACE|T_USER:
664602ef3f3Schopps 	case T_TRAP15|T_USER:
6652be73160Smw #ifdef COMPAT_SUNOS
666602ef3f3Schopps 		/*
66796914606Skleink 		 * SunOS uses Trap #2 for a "CPU cache flush".
66896914606Skleink 		 * Just flush the on-chip caches and return.
669602ef3f3Schopps 		 */
670de42a28aSchristos 		if (p->p_emul == &emul_sunos) {
67196914606Skleink 			ICIA();
67296914606Skleink 			DCIU();
673602ef3f3Schopps 			return;
674602ef3f3Schopps 		}
6752be73160Smw #endif
676d2eac2f6Smhitch 		fp->f_sr &= ~PSL_T;
677*5f04920cSrin 		ksi.ksi_addr = (void *)fp->f_pc;
67841692372Scl 		ksi.ksi_signo = SIGTRAP;
679*5f04920cSrin 		if (type == (T_TRAP15|T_USER))
680*5f04920cSrin 			ksi.ksi_code = TRAP_BRKPT;
681*5f04920cSrin 		else
682*5f04920cSrin 			ksi.ksi_code = TRAP_TRACE;
68333e84123Smw 		break;
684602ef3f3Schopps 	/*
685602ef3f3Schopps 	 * Kernel AST (should not happen)
686602ef3f3Schopps 	 */
687602ef3f3Schopps 	case T_ASTFLT:
688d2eac2f6Smhitch 		panictrap(type, code, v, fp);
689602ef3f3Schopps 	/*
690602ef3f3Schopps 	 * User AST
691602ef3f3Schopps 	 */
692602ef3f3Schopps 	case T_ASTFLT|T_USER:
69333e84123Smw 		astpending = 0;
69433e84123Smw 		spl0();
695b07ec3fcSad 		if (l->l_pflag & LP_OWEUPC) {
696b07ec3fcSad 			l->l_pflag &= ~LP_OWEUPC;
697b07ec3fcSad 			ADDUPROF(l);
69833e84123Smw 		}
699d2eac2f6Smhitch 		userret(l, fp->f_pc, sticks);
700602ef3f3Schopps 		return;
701602ef3f3Schopps 	/*
702602ef3f3Schopps 	 * Kernel/User page fault
703602ef3f3Schopps 	 */
704602ef3f3Schopps 	case T_MMUFLT:
70533e84123Smw 	case T_MMUFLT|T_USER:	/* page fault */
706d2eac2f6Smhitch 		trapmmufault(type, code, v, fp, l, sticks);
70733e84123Smw 		return;
70833e84123Smw 	}
709602ef3f3Schopps 
710602ef3f3Schopps #ifdef DEBUG
71141692372Scl 	if (ksi.ksi_signo != SIGTRAP)
71241692372Scl 		printf("trapsignal(%d, %d, %d, %x, %x)\n", p->p_pid,
713d2eac2f6Smhitch 		    ksi.ksi_signo, ksi.ksi_code, v, fp->f_pc);
71406149f6fSmw #endif
71541692372Scl 	if (ksi.ksi_signo)
71641692372Scl 		trapsignal(l, &ksi);
71733e84123Smw 	if ((type & T_USER) == 0)
71833e84123Smw 		return;
719d2eac2f6Smhitch 	userret(l, fp->f_pc, sticks);
72033e84123Smw }
72133e84123Smw 
72233e84123Smw /*
72306149f6fSmw  * Process a pending write back
72406149f6fSmw  */
725db6f1b13Sveego int
72682357f6dSdsl _write_back (u_int wb, u_int wb_sts, u_int wb_data, u_int wb_addr, struct vm_map *wb_map)
72782357f6dSdsl 	/* wb:	 writeback type: 1, 2, or 3 */
72882357f6dSdsl 	/* wb_sts:	 writeback status information */
72982357f6dSdsl 	/* wb_data:	 data to writeback */
73082357f6dSdsl 	/* wb_addr:	 address to writeback to */
73106149f6fSmw {
73206149f6fSmw 	u_int wb_extra_page = 0;
73306149f6fSmw 	u_int wb_rc, mmusr;
73404aa4da3Schs 	void *onfault;
73506149f6fSmw 
73606149f6fSmw #ifdef DEBUG
73706149f6fSmw 	if (mmudebug)
738ca36ac9eSchristos 		printf("wb%d valid: %x %x %x\n",wb,wb_sts,wb_addr,wb_data);
73906149f6fSmw #endif
74006149f6fSmw 
74106149f6fSmw 	/* See if we're going to span two pages (for word or long transfers) */
74206149f6fSmw 
74306149f6fSmw 	if((wb_sts & WBS_SZMASK) == WBS_SIZE_WORD)
744744246faSis 		if(trunc_page((vaddr_t)wb_addr) !=
745744246faSis 		    trunc_page((vaddr_t)wb_addr+1))
74606149f6fSmw 			wb_extra_page = 1;
74706149f6fSmw 
74806149f6fSmw 	if((wb_sts & WBS_SZMASK) == WBS_SIZE_LONG)
749744246faSis 		if(trunc_page((vaddr_t)wb_addr) !=
750744246faSis 		    trunc_page((vaddr_t)wb_addr+3))
75106149f6fSmw 			wb_extra_page = 3;
75206149f6fSmw 
75306149f6fSmw 	/*
75406149f6fSmw 	 * if it's writeback 3, we need to check the first page
75506149f6fSmw 	 */
75606149f6fSmw 	if (wb == 3) {
75706149f6fSmw 		mmusr = probeva(wb_addr, wb_sts & WBS_TMMASK);
75806149f6fSmw #ifdef DEBUG
75906149f6fSmw 	if (mmudebug)
760ca36ac9eSchristos 		printf("wb3: probeva(%x,%x) = %x\n",
76163451f69Schopps 		    wb_addr + wb_extra_page, wb_sts & WBS_TMMASK, mmusr);
76206149f6fSmw #endif
76306149f6fSmw 
764d6f84d66Schopps 		if((mmusr & (MMUSR_R | MMUSR_W)) != MMUSR_R) {
76506149f6fSmw #ifdef DEBUG
76606149f6fSmw 			if (mmudebug)
767ca36ac9eSchristos 				printf("wb3: need to bring in first page\n");
76806149f6fSmw #endif
76904aa4da3Schs 			onfault = curpcb->pcb_onfault;
77004aa4da3Schs 			curpcb->pcb_onfault = NULL;
771dc9188e3Smhitch 			wb_rc = uvm_fault(wb_map,
772dc9188e3Smhitch 			    trunc_page((vm_offset_t)wb_addr),
77347fbb9d8Sdrochner 			    VM_PROT_READ | VM_PROT_WRITE);
77404aa4da3Schs 			curpcb->pcb_onfault = onfault;
77506149f6fSmw 
776ac3bc537Schs 			if (wb_rc != 0)
77706149f6fSmw 				return (wb_rc);
77806149f6fSmw #ifdef DEBUG
77906149f6fSmw 			if (mmudebug)
780ca36ac9eSchristos 				printf("wb3: first page brought in.\n");
78106149f6fSmw #endif
78206149f6fSmw 		}
78306149f6fSmw 	}
78406149f6fSmw 
78506149f6fSmw 	/*
78606149f6fSmw 	 * now check to see if a second page is required
78706149f6fSmw 	 */
78806149f6fSmw 	if(wb_extra_page) {
78906149f6fSmw 
79006149f6fSmw 		mmusr = probeva(wb_addr+wb_extra_page, wb_sts & WBS_TMMASK);
79106149f6fSmw #ifdef DEBUG
79206149f6fSmw 		if (mmudebug)
793ca36ac9eSchristos 			printf("wb%d: probeva %x %x = %x\n",
79463451f69Schopps 			    wb, wb_addr + wb_extra_page,
79563451f69Schopps 			    wb_sts & WBS_TMMASK,mmusr);
79606149f6fSmw #endif
79706149f6fSmw 
798d6f84d66Schopps 		if((mmusr & (MMUSR_R | MMUSR_W)) != MMUSR_R) {
79906149f6fSmw #ifdef DEBUG
80006149f6fSmw 			if (mmudebug)
801ca36ac9eSchristos 				printf("wb%d: page boundary crossed."
80263451f69Schopps 				    "  Bringing in extra page.\n",wb);
80306149f6fSmw #endif
80406149f6fSmw 
80504aa4da3Schs 			onfault = curpcb->pcb_onfault;
80604aa4da3Schs 			curpcb->pcb_onfault = NULL;
807dc9188e3Smhitch 			wb_rc = uvm_fault(wb_map,
808dc9188e3Smhitch 			    trunc_page((vm_offset_t)wb_addr + wb_extra_page),
80947fbb9d8Sdrochner 			    VM_PROT_READ | VM_PROT_WRITE);
81004aa4da3Schs 			curpcb->pcb_onfault = onfault;
81106149f6fSmw 
812ac3bc537Schs 			if (wb_rc != 0)
81306149f6fSmw 				return (wb_rc);
81406149f6fSmw 		}
81506149f6fSmw #ifdef DEBUG
81606149f6fSmw 		if (mmudebug)
817ca36ac9eSchristos 			printf("wb%d: extra page brought in okay.\n", wb);
81806149f6fSmw #endif
81906149f6fSmw 	}
82006149f6fSmw 
82106149f6fSmw 	/* Actually do the write now */
82206149f6fSmw 
82306149f6fSmw 	if ((wb_sts & WBS_TMMASK) == FC_USERD &&
82406149f6fSmw 	    !curpcb->pcb_onfault) {
82553524e44Schristos 	    	curpcb->pcb_onfault = (void *) _wb_fault;
82606149f6fSmw 	}
82706149f6fSmw 
82806149f6fSmw 	switch(wb_sts & WBS_SZMASK) {
82906149f6fSmw 
83006149f6fSmw 	case WBS_SIZE_BYTE :
8312d65de24Sperry 		__asm volatile ("movec %0,%%dfc ; movesb %1,%2@":: "d" (wb_sts & WBS_TMMASK),
83206149f6fSmw 								 "d" (wb_data),
83306149f6fSmw 								 "a" (wb_addr));
83406149f6fSmw 		break;
83506149f6fSmw 
83606149f6fSmw 	case WBS_SIZE_WORD :
8372d65de24Sperry 		__asm volatile ("movec %0,%%dfc ; movesw %1,%2@":: "d" (wb_sts & WBS_TMMASK),
83806149f6fSmw 								 "d" (wb_data),
83906149f6fSmw 								 "a" (wb_addr));
84006149f6fSmw 		break;
84106149f6fSmw 
84206149f6fSmw 	case WBS_SIZE_LONG :
8432d65de24Sperry 		__asm volatile ("movec %0,%%dfc ; movesl %1,%2@":: "d" (wb_sts & WBS_TMMASK),
84406149f6fSmw 								 "d" (wb_data),
84506149f6fSmw 								 "a" (wb_addr));
84606149f6fSmw 		break;
84706149f6fSmw 
84806149f6fSmw 	}
84953524e44Schristos 	if (curpcb->pcb_onfault == (void *) _wb_fault)
85006149f6fSmw 		curpcb->pcb_onfault = NULL;
85106149f6fSmw 	if ((wb_sts & WBS_TMMASK) != FC_USERD)
8522d65de24Sperry 		__asm volatile ("movec %0,%%dfc\n" : : "d" (FC_USERD));
853ac3bc537Schs 	return 0;
85406149f6fSmw }
85506149f6fSmw 
85606149f6fSmw /*
85706149f6fSmw  * fault handler for write back
85806149f6fSmw  */
859db6f1b13Sveego void
860df7f595eScegger _wb_fault(void)
86106149f6fSmw {
86206149f6fSmw #ifdef DEBUG
863ca36ac9eSchristos 	printf ("trap: writeback fault\n");
86406149f6fSmw #endif
86506149f6fSmw 	return;
86606149f6fSmw }
867