xref: /original-bsd/sys/luna68k/luna68k/trap.c (revision 3705696b)
1 /*
2  * Copyright (c) 1988 University of Utah.
3  * Copyright (c) 1992 OMRON Corporation.
4  * Copyright (c) 1982, 1986, 1990, 1993
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * the Systems Programming Group of the University of Utah Computer
9  * Science Department.
10  *
11  * %sccs.include.redist.c%
12  *
13  * from: Utah $Hdr: trap.c 1.35 91/12/26$
14  * from: hp300/hp300/trap.c	7.26 (Berkeley) 12/27/92
15  *
16  *	@(#)trap.c	8.1 (Berkeley) 06/16/93
17  */
18 
19 #include <sys/param.h>
20 #include <sys/systm.h>
21 #include <sys/proc.h>
22 #include <sys/acct.h>
23 #include <sys/kernel.h>
24 #include <sys/signalvar.h>
25 #include <sys/resourcevar.h>
26 #include <sys/syscall.h>
27 #include <sys/syslog.h>
28 #include <sys/user.h>
29 #ifdef KTRACE
30 #include <sys/ktrace.h>
31 #endif
32 
33 #include <machine/psl.h>
34 #include <machine/trap.h>
35 #include <machine/cpu.h>
36 #include <machine/reg.h>
37 #include <machine/mtpr.h>
38 
39 #include <vm/vm.h>
40 #include <vm/pmap.h>
41 
42 struct	sysent	sysent[];
43 int	nsysent;
44 
45 char	*trap_type[] = {
46 	"Bus error",
47 	"Address error",
48 	"Illegal instruction",
49 	"Zero divide",
50 	"CHK instruction",
51 	"TRAPV instruction",
52 	"Privilege violation",
53 	"Trace trap",
54 	"MMU fault",
55 	"SSIR trap",
56 	"Format error",
57 	"68881 exception",
58 	"Coprocessor violation",
59 	"Async system trap"
60 };
61 #define	TRAP_TYPES	(sizeof trap_type / sizeof trap_type[0])
62 
63 /*
64  * Size of various exception stack frames (minus the standard 8 bytes)
65  */
66 short	exframesize[] = {
67 	FMT0SIZE,	/* type 0 - normal (68020/030/040) */
68 	FMT1SIZE,	/* type 1 - throwaway (68020/030/040) */
69 	FMT2SIZE,	/* type 2 - normal 6-word (68020/030/040) */
70 	FMT3SIZE,	/* type 3 - FP post-instruction (68040) */
71 	-1, -1, -1,	/* type 4-6 - undefined */
72 	FMT7SIZE,	/* type 7 - access error (68040) */
73 	58,		/* type 8 - bus fault (68010) */
74 	FMT9SIZE,	/* type 9 - coprocessor mid-instruction (68020/030) */
75 	FMTASIZE,	/* type A - short bus fault (68020/030) */
76 	FMTBSIZE,	/* type B - long bus fault (68020/030) */
77 	-1, -1, -1, -1	/* type C-F - undefined */
78 };
79 
80 #ifdef LUNA2
81 #define KDFAULT(c)	(mmutype == MMU_68040 ? \
82 			    ((c) & SSW4_TMMASK) == SSW4_TMKD : \
83 			    ((c) & (SSW_DF|FC_SUPERD)) == (SSW_DF|FC_SUPERD))
84 #define WRFAULT(c) 	(mmutype == MMU_68040 ? \
85 			    ((c) & SSW4_RW) == 0 : \
86 			    ((c) & (SSW_DF|SSW_RW)) == SSW_DF)
87 #else
88 #define KDFAULT(c)	(((c) & (SSW_DF|SSW_FCMASK)) == (SSW_DF|FC_SUPERD))
89 #define WRFAULT(c)	(((c) & (SSW_DF|SSW_RW)) == SSW_DF)
90 #endif
91 
92 #ifdef DEBUG
93 int mmudebug = 0;
94 int mmupid = -1;
95 #define MDB_FOLLOW	1
96 #define MDB_WBFOLLOW	2
97 #define MDB_WBFAILED	4
98 #define MDB_ISPID(p)	(p) == mmupid
99 #endif
100 
101 /*
102  * trap and syscall both need the following work done before returning
103  * to user mode.
104  */
105 static inline void
106 userret(p, fp, oticks, faultaddr, fromtrap)
107 	register struct proc *p;
108 	register struct frame *fp;
109 	u_quad_t oticks;
110 	u_int faultaddr;
111 	int fromtrap;
112 {
113 	int sig, s;
114 #ifdef LUNA2
115 	int beenhere = 0;
116 
117 again:
118 #endif
119 	/* take pending signals */
120 	while ((sig = CURSIG(p)) != 0)
121 		psig(sig);
122 	p->p_pri = p->p_usrpri;
123 	if (want_resched) {
124 		/*
125 		 * Since we are curproc, clock will normally just change
126 		 * our priority without moving us from one queue to another
127 		 * (since the running process is not on a queue.)
128 		 * If that happened after we setrq ourselves but before we
129 		 * swtch()'ed, we might not be on the queue indicated by
130 		 * our priority.
131 		 */
132 		s = splstatclock();
133 		setrq(p);
134 		p->p_stats->p_ru.ru_nivcsw++;
135 		swtch();
136 		splx(s);
137 		while ((sig = CURSIG(p)) != 0)
138 			psig(sig);
139 	}
140 
141 	/*
142 	 * If profiling, charge system time to the trapped pc.
143 	 */
144 	if (p->p_flag & SPROFIL) {
145 		extern int psratio;
146 
147 		addupc_task(p, fp->f_pc,
148 			    (int)(p->p_sticks - oticks) * psratio);
149 	}
150 #ifdef LUNA2
151 	/*
152 	 * Deal with user mode writebacks (from trap, or from sigreturn).
153 	 * If any writeback fails, go back and attempt signal delivery.
154 	 * unless we have already been here and attempted the writeback
155 	 * (e.g. bad address with user ignoring SIGSEGV).  In that case
156 	 * we just return to the user without sucessfully completing
157 	 * the writebacks.  Maybe we should just drop the sucker?
158 	 */
159 	if (mmutype == MMU_68040 && fp->f_format == FMT7) {
160 		if (beenhere) {
161 #ifdef DEBUG
162 			if (mmudebug & MDB_WBFAILED)
163 				printf(fromtrap ?
164 		"pid %d(%s): writeback aborted, pc=%x, fa=%x\n" :
165 		"pid %d(%s): writeback aborted in sigreturn, pc=%x\n",
166 				    p->p_pid, p->p_comm, fp->f_pc, faultaddr);
167 #endif
168 		} else if (sig = writeback(fp, fromtrap)) {
169 			beenhere = 1;
170 			oticks = p->p_sticks;
171 			trapsignal(p, sig, faultaddr);
172 			goto again;
173 		}
174 	}
175 #endif
176 	curpri = p->p_pri;
177 }
178 
179 /*
180  * Trap is called from locore to handle most types of processor traps,
181  * including events such as simulated software interrupts/AST's.
182  * System calls are broken out for efficiency.
183  */
184 /*ARGSUSED*/
185 trap(type, code, v, frame)
186 	int type;
187 	unsigned code;
188 	register unsigned v;
189 	struct frame frame;
190 {
191 	register int i;
192 	unsigned ucode;
193 	register struct proc *p;
194 	u_quad_t sticks;
195 	unsigned ncode;
196 	extern char fswintr[];
197 
198 	cnt.v_trap++;
199 	p = curproc;
200 	ucode = 0;
201 	if (USERMODE(frame.f_sr)) {
202 		type |= T_USER;
203 		sticks = p->p_sticks;
204 		p->p_md.md_regs = frame.f_regs;
205 	}
206 	switch (type) {
207 
208 	default:
209 dopanic:
210 		printf("trap type %d, code = %x, v = %x\n", type, code, v);
211 		regdump(&frame, 128);
212 		type &= ~T_USER;
213 		if ((unsigned)type < TRAP_TYPES)
214 			panic(trap_type[type]);
215 		panic("trap");
216 
217 	case T_BUSERR:		/* kernel bus error */
218 		if (!p->p_addr->u_pcb.pcb_onfault)
219 			goto dopanic;
220 		/*
221 		 * If we have arranged to catch this fault in any of the
222 		 * copy to/from user space routines, set PC to return to
223 		 * indicated location and set flag informing buserror code
224 		 * that it may need to clean up stack frame.
225 		 */
226 copyfault:
227 		frame.f_stackadj = exframesize[frame.f_format];
228 		frame.f_format = frame.f_vector = 0;
229 		frame.f_pc = (int) p->p_addr->u_pcb.pcb_onfault;
230 		return;
231 
232 	case T_BUSERR|T_USER:	/* bus error */
233 	case T_ADDRERR|T_USER:	/* address error */
234 		ucode = v;
235 		i = SIGBUS;
236 		break;
237 
238 #ifdef FPCOPROC
239 	case T_COPERR:		/* kernel coprocessor violation */
240 #endif
241 	case T_FMTERR|T_USER:	/* do all RTE errors come in as T_USER? */
242 	case T_FMTERR:		/* ...just in case... */
243 	/*
244 	 * The user has most likely trashed the RTE or FP state info
245 	 * in the stack frame of a signal handler.
246 	 */
247 		type |= T_USER;
248 		printf("pid %d: kernel %s exception\n", p->p_pid,
249 		       type==T_COPERR ? "coprocessor" : "format");
250 		p->p_sigacts->ps_sigact[SIGILL] = SIG_DFL;
251 		i = sigmask(SIGILL);
252 		p->p_sigignore &= ~i;
253 		p->p_sigcatch &= ~i;
254 		p->p_sigmask &= ~i;
255 		i = SIGILL;
256 		ucode = frame.f_format;	/* XXX was ILL_RESAD_FAULT */
257 		break;
258 
259 #ifdef FPCOPROC
260 	case T_COPERR|T_USER:	/* user coprocessor violation */
261 	/* What is a proper response here? */
262 		ucode = 0;
263 		i = SIGFPE;
264 		break;
265 
266 	case T_FPERR|T_USER:	/* 68881 exceptions */
267 	/*
268 	 * We pass along the 68881 status register which locore stashed
269 	 * in code for us.  Note that there is a possibility that the
270 	 * bit pattern of this register will conflict with one of the
271 	 * FPE_* codes defined in signal.h.  Fortunately for us, the
272 	 * only such codes we use are all in the range 1-7 and the low
273 	 * 3 bits of the status register are defined as 0 so there is
274 	 * no clash.
275 	 */
276 		ucode = code;
277 		i = SIGFPE;
278 		break;
279 #endif
280 
281 #ifdef LUNA2
282 	case T_FPEMULI|T_USER:	/* unimplemented FP instuction */
283 	case T_FPEMULD|T_USER:	/* unimplemented FP data type */
284 		/* XXX need to FSAVE */
285 		printf("pid %d(%s): unimplemented FP %s at %x (EA %x)\n",
286 		       p->p_pid, p->p_comm,
287 		       frame.f_format == 2 ? "instruction" : "data type",
288 		       frame.f_pc, frame.f_fmt2.f_iaddr);
289 		/* XXX need to FRESTORE */
290 		i = SIGFPE;
291 		break;
292 #endif
293 
294 	case T_ILLINST|T_USER:	/* illegal instruction fault */
295 	case T_PRIVINST|T_USER:	/* privileged instruction fault */
296 		ucode = frame.f_format;	/* XXX was ILL_PRIVIN_FAULT */
297 		i = SIGILL;
298 		break;
299 
300 	case T_ZERODIV|T_USER:	/* Divide by zero */
301 		ucode = frame.f_format;	/* XXX was FPE_INTDIV_TRAP */
302 		i = SIGFPE;
303 		break;
304 
305 	case T_CHKINST|T_USER:	/* CHK instruction trap */
306 		ucode = frame.f_format;	/* XXX was FPE_SUBRNG_TRAP */
307 		i = SIGFPE;
308 		break;
309 
310 	case T_TRAPVINST|T_USER:	/* TRAPV instruction trap */
311 		ucode = frame.f_format;	/* XXX was FPE_INTOVF_TRAP */
312 		i = SIGFPE;
313 		break;
314 
315 	/*
316 	 * XXX: Trace traps are a nightmare.
317 	 *
318 	 *	HP-UX uses trap #1 for breakpoints,
319 	 *	HPBSD uses trap #2,
320 	 *	SUN 3.x uses trap #15,
321 	 *	KGDB uses trap #15 (for kernel breakpoints; handled elsewhere).
322 	 *
323 	 * HPBSD and HP-UX traps both get mapped by locore.s into T_TRACE.
324 	 * SUN 3.x traps get passed through as T_TRAP15 and are not really
325 	 * supported yet.
326 	 */
327 	case T_TRACE:		/* kernel trace trap */
328 	case T_TRAP15:		/* SUN trace trap */
329 		frame.f_sr &= ~PSL_T;
330 		i = SIGTRAP;
331 		break;
332 
333 	case T_TRACE|T_USER:	/* user trace trap */
334 	case T_TRAP15|T_USER:	/* SUN user trace trap */
335 		frame.f_sr &= ~PSL_T;
336 		i = SIGTRAP;
337 		break;
338 
339 	case T_ASTFLT:		/* system async trap, cannot happen */
340 		goto dopanic;
341 
342 	case T_ASTFLT|T_USER:	/* user async trap */
343 		astpending = 0;
344 		/*
345 		 * We check for software interrupts first.  This is because
346 		 * they are at a higher level than ASTs, and on a VAX would
347 		 * interrupt the AST.  We assume that if we are processing
348 		 * an AST that we must be at IPL0 so we don't bother to
349 		 * check.  Note that we ensure that we are at least at SIR
350 		 * IPL while processing the SIR.
351 		 */
352 		spl1();
353 		/* fall into... */
354 
355 	case T_SSIR:		/* software interrupt */
356 	case T_SSIR|T_USER:
357 		if (ssir & SIR_NET) {
358 			siroff(SIR_NET);
359 			cnt.v_soft++;
360 			netintr();
361 		}
362 		if (ssir & SIR_CLOCK) {
363 			siroff(SIR_CLOCK);
364 			cnt.v_soft++;
365 			softclock();
366 		}
367 		/*
368 		 * If this was not an AST trap, we are all done.
369 		 */
370 		if (type != (T_ASTFLT|T_USER)) {
371 			cnt.v_trap--;
372 			return;
373 		}
374 		spl0();
375 		if (p->p_flag & SOWEUPC) {
376 			p->p_flag &= ~SOWEUPC;
377 			ADDUPROF(p);
378 		}
379 		goto out;
380 
381 	case T_MMUFLT:		/* kernel mode page fault */
382 		/*
383 		 * If we were doing profiling ticks or other user mode
384 		 * stuff from interrupt code, Just Say No.
385 		 */
386 		if (p->p_addr->u_pcb.pcb_onfault == fswintr)
387 			goto copyfault;
388 		/* fall into ... */
389 
390 	case T_MMUFLT|T_USER:	/* page fault */
391 	    {
392 		register vm_offset_t va;
393 		register struct vmspace *vm = p->p_vmspace;
394 		register vm_map_t map;
395 		int rv;
396 		vm_prot_t ftype;
397 		extern vm_map_t kernel_map;
398 
399 #ifdef DEBUG
400 		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
401 		printf("trap: T_MMUFLT pid=%d, code=%x, v=%x, pc=%x, sr=%x\n",
402 		       p->p_pid, code, v, frame.f_pc, frame.f_sr);
403 #endif
404 		/*
405 		 * It is only a kernel address space fault iff:
406 		 * 	1. (type & T_USER) == 0  and
407 		 * 	2. pcb_onfault not set or
408 		 *	3. pcb_onfault set but supervisor space data fault
409 		 * The last can occur during an exec() copyin where the
410 		 * argument space is lazy-allocated.
411 		 */
412 		if (type == T_MMUFLT &&
413 		    (!p->p_addr->u_pcb.pcb_onfault || KDFAULT(code)))
414 			map = kernel_map;
415 		else
416 			map = &vm->vm_map;
417 		if (WRFAULT(code))
418 			ftype = VM_PROT_READ | VM_PROT_WRITE;
419 		else
420 			ftype = VM_PROT_READ;
421 		va = trunc_page((vm_offset_t)v);
422 #ifdef DEBUG
423 		if (map == kernel_map && va == 0) {
424 			printf("trap: bad kernel access at %x\n", v);
425 			goto dopanic;
426 		}
427 #endif
428 		rv = vm_fault(map, va, ftype, FALSE);
429 #ifdef DEBUG
430 		if (rv && MDB_ISPID(p->p_pid))
431 			printf("vm_fault(%x, %x, %x, 0) -> %x\n",
432 			       map, va, ftype, rv);
433 #endif
434 		/*
435 		 * If this was a stack access we keep track of the maximum
436 		 * accessed stack size.  Also, if vm_fault gets a protection
437 		 * failure it is due to accessing the stack region outside
438 		 * the current limit and we need to reflect that as an access
439 		 * error.
440 		 */
441 		if ((caddr_t)va >= vm->vm_maxsaddr && map != kernel_map) {
442 			if (rv == KERN_SUCCESS) {
443 				unsigned nss;
444 
445 				nss = clrnd(btoc(USRSTACK-(unsigned)va));
446 				if (nss > vm->vm_ssize)
447 					vm->vm_ssize = nss;
448 			} else if (rv == KERN_PROTECTION_FAILURE)
449 				rv = KERN_INVALID_ADDRESS;
450 		}
451 		if (rv == KERN_SUCCESS) {
452 			if (type == T_MMUFLT) {
453 #ifdef LUNA2
454 				if (mmutype == MMU_68040)
455 					(void) writeback(&frame, 1);
456 #endif
457 				return;
458 			}
459 			goto out;
460 		}
461 		if (type == T_MMUFLT) {
462 			if (p->p_addr->u_pcb.pcb_onfault)
463 				goto copyfault;
464 			printf("vm_fault(%x, %x, %x, 0) -> %x\n",
465 			       map, va, ftype, rv);
466 			printf("  type %x, code [mmu,,ssw]: %x\n",
467 			       type, code);
468 			goto dopanic;
469 		}
470 		ucode = v;
471 		i = (rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV;
472 		break;
473 	    }
474 	}
475 	trapsignal(p, i, ucode);
476 	if ((type & T_USER) == 0)
477 		return;
478 out:
479 	userret(p, &frame, sticks, v, 1);
480 }
481 
482 #ifdef LUNA2
483 #ifdef DEBUG
484 struct writebackstats {
485 	int calls;
486 	int cpushes;
487 	int move16s;
488 	int wb1s, wb2s, wb3s;
489 	int wbsize[4];
490 } wbstats;
491 
492 char *f7sz[] = { "longword", "byte", "word", "line" };
493 char *f7tt[] = { "normal", "MOVE16", "AFC", "ACK" };
494 char *f7tm[] = { "d-push", "u-data", "u-code", "M-data",
495 		 "M-code", "k-data", "k-code", "RES" };
496 char wberrstr[] =
497     "WARNING: pid %d(%s) writeback [%s] failed, pc=%x fa=%x wba=%x wbd=%x\n";
498 #endif
499 
500 writeback(fp, docachepush)
501 	struct frame *fp;
502 	int docachepush;
503 {
504 	register struct fmt7 *f = &fp->f_fmt7;
505 	register struct proc *p = curproc;
506 	int err = 0;
507 	u_int fa;
508 	caddr_t oonfault = p->p_addr->u_pcb.pcb_onfault;
509 
510 #ifdef DEBUG
511 	if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) {
512 		printf(" pid=%d, fa=%x,", p->p_pid, f->f_fa);
513 		dumpssw(f->f_ssw);
514 	}
515 	wbstats.calls++;
516 #endif
517 	/*
518 	 * Deal with special cases first.
519 	 */
520 	if ((f->f_ssw & SSW4_TMMASK) == SSW4_TMDCP) {
521 		/*
522 		 * Dcache push fault.
523 		 * Line-align the address and write out the push data to
524 		 * the indicated physical address.
525 		 */
526 #ifdef DEBUG
527 		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) {
528 			printf(" pushing %s to PA %x, data %x",
529 			       f7sz[(f->f_ssw & SSW4_SZMASK) >> 5],
530 			       f->f_fa, f->f_pd0);
531 			if ((f->f_ssw & SSW4_SZMASK) == SSW4_SZLN)
532 				printf("/%x/%x/%x",
533 				       f->f_pd1, f->f_pd2, f->f_pd3);
534 			printf("\n");
535 		}
536 		if (f->f_wb1s & SSW4_WBSV)
537 			panic("writeback: cache push with WB1S valid");
538 		wbstats.cpushes++;
539 #endif
540 		/*
541 		 * XXX there are security problems if we attempt to do a
542 		 * cache push after a signal handler has been called.
543 		 */
544 		if (docachepush) {
545 			pmap_enter(kernel_pmap, (vm_offset_t)vmmap,
546 				   trunc_page(f->f_fa), VM_PROT_WRITE, TRUE);
547 			fa = (u_int)&vmmap[(f->f_fa & PGOFSET) & ~0xF];
548 			bcopy((caddr_t)&f->f_pd0, (caddr_t)fa, 16);
549 			DCFL(pmap_extract(kernel_pmap, (vm_offset_t)fa));
550 			pmap_remove(kernel_pmap, (vm_offset_t)vmmap,
551 				    (vm_offset_t)&vmmap[NBPG]);
552 		} else
553 			printf("WARNING: pid %d(%s) uid %d: CPUSH not done\n",
554 			       p->p_pid, p->p_comm, p->p_ucred->cr_uid);
555 	} else if ((f->f_ssw & (SSW4_RW|SSW4_TTMASK)) == SSW4_TTM16) {
556 		/*
557 		 * MOVE16 fault.
558 		 * Line-align the address and write out the push data to
559 		 * the indicated virtual address.
560 		 */
561 #ifdef DEBUG
562 		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
563 			printf(" MOVE16 to VA %x(%x), data %x/%x/%x/%x\n",
564 			       f->f_fa, f->f_fa & ~0xF, f->f_pd0, f->f_pd1,
565 			       f->f_pd2, f->f_pd3);
566 		if (f->f_wb1s & SSW4_WBSV)
567 			panic("writeback: MOVE16 with WB1S valid");
568 		wbstats.move16s++;
569 #endif
570 		if (KDFAULT(f->f_wb1s))
571 			bcopy((caddr_t)&f->f_pd0, (caddr_t)(f->f_fa & ~0xF), 16);
572 		else
573 			err = suline((caddr_t)(f->f_fa & ~0xF), (caddr_t)&f->f_pd0);
574 		if (err) {
575 			fa = f->f_fa & ~0xF;
576 #ifdef DEBUG
577 			if (mmudebug & MDB_WBFAILED)
578 				printf(wberrstr, p->p_pid, p->p_comm,
579 				       "MOVE16", fp->f_pc, f->f_fa,
580 				       f->f_fa & ~0xF, f->f_pd0);
581 #endif
582 		}
583 	} else if (f->f_wb1s & SSW4_WBSV) {
584 		/*
585 		 * Writeback #1.
586 		 * Position the "memory-aligned" data and write it out.
587 		 */
588 		register u_int wb1d = f->f_wb1d;
589 		register int off;
590 
591 #ifdef DEBUG
592 		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
593 			dumpwb(1, f->f_wb1s, f->f_wb1a, f->f_wb1d);
594 		wbstats.wb1s++;
595 		wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++;
596 #endif
597 		off = (f->f_wb1a & 3) * 8;
598 		switch (f->f_wb1s & SSW4_SZMASK) {
599 		case SSW4_SZLW:
600 			if (off)
601 				wb1d = (wb1d >> (32 - off)) | (wb1d << off);
602 			if (KDFAULT(f->f_wb1s))
603 				*(long *)f->f_wb1a = wb1d;
604 			else
605 				err = suword((caddr_t)f->f_wb1a, wb1d);
606 			break;
607 		case SSW4_SZB:
608 			off = 24 - off;
609 			if (off)
610 				wb1d >>= off;
611 			if (KDFAULT(f->f_wb1s))
612 				*(char *)f->f_wb1a = wb1d;
613 			else
614 				err = subyte((caddr_t)f->f_wb1a, wb1d);
615 			break;
616 		case SSW4_SZW:
617 			off = (off + 16) % 32;
618 			if (off)
619 				wb1d = (wb1d >> (32 - off)) | (wb1d << off);
620 			if (KDFAULT(f->f_wb1s))
621 				*(short *)f->f_wb1a = wb1d;
622 			else
623 				err = susword((caddr_t)f->f_wb1a, wb1d);
624 			break;
625 		}
626 		if (err) {
627 			fa = f->f_wb1a;
628 #ifdef DEBUG
629 			if (mmudebug & MDB_WBFAILED)
630 				printf(wberrstr, p->p_pid, p->p_comm,
631 				       "#1", fp->f_pc, f->f_fa,
632 				       f->f_wb1a, f->f_wb1d);
633 #endif
634 		}
635 	}
636 	/*
637 	 * Deal with the "normal" writebacks.
638 	 *
639 	 * XXX writeback2 is known to reflect a LINE size writeback after
640 	 * a MOVE16 was already dealt with above.  Ignore it.
641 	 */
642 	if (err == 0 && (f->f_wb2s & SSW4_WBSV) &&
643 	    (f->f_wb2s & SSW4_SZMASK) != SSW4_SZLN) {
644 #ifdef DEBUG
645 		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
646 			dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d);
647 		wbstats.wb2s++;
648 		wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++;
649 #endif
650 		switch (f->f_wb2s & SSW4_SZMASK) {
651 		case SSW4_SZLW:
652 			if (KDFAULT(f->f_wb2s))
653 				*(long *)f->f_wb2a = f->f_wb2d;
654 			else
655 				err = suword((caddr_t)f->f_wb2a, f->f_wb2d);
656 			break;
657 		case SSW4_SZB:
658 			if (KDFAULT(f->f_wb2s))
659 				*(char *)f->f_wb2a = f->f_wb2d;
660 			else
661 				err = subyte((caddr_t)f->f_wb2a, f->f_wb2d);
662 			break;
663 		case SSW4_SZW:
664 			if (KDFAULT(f->f_wb2s))
665 				*(short *)f->f_wb2a = f->f_wb2d;
666 			else
667 				err = susword((caddr_t)f->f_wb2a, f->f_wb2d);
668 			break;
669 		}
670 		if (err) {
671 			fa = f->f_wb2a;
672 #ifdef DEBUG
673 			if (mmudebug & MDB_WBFAILED) {
674 				printf(wberrstr, p->p_pid, p->p_comm,
675 				       "#2", fp->f_pc, f->f_fa,
676 				       f->f_wb2a, f->f_wb2d);
677 				dumpssw(f->f_ssw);
678 				dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d);
679 			}
680 #endif
681 		}
682 	}
683 	if (err == 0 && (f->f_wb3s & SSW4_WBSV)) {
684 #ifdef DEBUG
685 		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
686 			dumpwb(3, f->f_wb3s, f->f_wb3a, f->f_wb3d);
687 		wbstats.wb3s++;
688 		wbstats.wbsize[(f->f_wb3s&SSW4_SZMASK)>>5]++;
689 #endif
690 		switch (f->f_wb3s & SSW4_SZMASK) {
691 		case SSW4_SZLW:
692 			if (KDFAULT(f->f_wb3s))
693 				*(long *)f->f_wb3a = f->f_wb3d;
694 			else
695 				err = suword((caddr_t)f->f_wb3a, f->f_wb3d);
696 			break;
697 		case SSW4_SZB:
698 			if (KDFAULT(f->f_wb3s))
699 				*(char *)f->f_wb3a = f->f_wb3d;
700 			else
701 				err = subyte((caddr_t)f->f_wb3a, f->f_wb3d);
702 			break;
703 		case SSW4_SZW:
704 			if (KDFAULT(f->f_wb3s))
705 				*(short *)f->f_wb3a = f->f_wb3d;
706 			else
707 				err = susword((caddr_t)f->f_wb3a, f->f_wb3d);
708 			break;
709 #ifdef DEBUG
710 		case SSW4_SZLN:
711 			panic("writeback: wb3s indicates LINE write");
712 #endif
713 		}
714 		if (err) {
715 			fa = f->f_wb3a;
716 #ifdef DEBUG
717 			if (mmudebug & MDB_WBFAILED)
718 				printf(wberrstr, p->p_pid, p->p_comm,
719 				       "#3", fp->f_pc, f->f_fa,
720 				       f->f_wb3a, f->f_wb3d);
721 #endif
722 		}
723 	}
724 	p->p_addr->u_pcb.pcb_onfault = oonfault;
725 	/*
726 	 * Determine the cause of the failure if any translating to
727 	 * a signal.  If the corresponding VA is valid and RO it is
728 	 * a protection fault (SIGBUS) otherwise consider it an
729 	 * illegal reference (SIGSEGV).
730 	 */
731 	if (err) {
732 		if (vm_map_check_protection(&p->p_vmspace->vm_map,
733 					    trunc_page(fa), round_page(fa),
734 					    VM_PROT_READ) &&
735 		    !vm_map_check_protection(&p->p_vmspace->vm_map,
736 					     trunc_page(fa), round_page(fa),
737 					     VM_PROT_WRITE))
738 			err = SIGBUS;
739 		else
740 			err = SIGSEGV;
741 	}
742 	return(err);
743 }
744 
745 #ifdef DEBUG
746 dumpssw(ssw)
747 	register u_short ssw;
748 {
749 	printf(" SSW: %x: ", ssw);
750 	if (ssw & SSW4_CP)
751 		printf("CP,");
752 	if (ssw & SSW4_CU)
753 		printf("CU,");
754 	if (ssw & SSW4_CT)
755 		printf("CT,");
756 	if (ssw & SSW4_CM)
757 		printf("CM,");
758 	if (ssw & SSW4_MA)
759 		printf("MA,");
760 	if (ssw & SSW4_ATC)
761 		printf("ATC,");
762 	if (ssw & SSW4_LK)
763 		printf("LK,");
764 	if (ssw & SSW4_RW)
765 		printf("RW,");
766 	printf(" SZ=%s, TT=%s, TM=%s\n",
767 	       f7sz[(ssw & SSW4_SZMASK) >> 5],
768 	       f7tt[(ssw & SSW4_TTMASK) >> 3],
769 	       f7tm[ssw & SSW4_TMMASK]);
770 }
771 
772 dumpwb(num, s, a, d)
773 	int num;
774 	u_short s;
775 	u_int a, d;
776 {
777 	register struct proc *p = curproc;
778 	vm_offset_t pa;
779 
780 	printf(" writeback #%d: VA %x, data %x, SZ=%s, TT=%s, TM=%s\n",
781 	       num, a, d, f7sz[(s & SSW4_SZMASK) >> 5],
782 	       f7tt[(s & SSW4_TTMASK) >> 3], f7tm[s & SSW4_TMMASK]);
783 	printf("               PA ");
784 	pa = pmap_extract(&p->p_vmspace->vm_pmap, (vm_offset_t)a);
785 	if (pa == 0)
786 		printf("<invalid address>");
787 	else
788 		printf("%x, current value %x", pa, fuword((caddr_t)a));
789 	printf("\n");
790 }
791 #endif
792 #endif
793 
794 /*
795  * Proces a system call.
796  */
797 syscall(code, frame)
798 	u_int code;
799 	struct frame frame;
800 {
801 	register caddr_t params;
802 	register struct sysent *callp;
803 	register struct proc *p;
804 	int error, opc, numsys, s;
805 	u_int argsize;
806 	struct args {
807 		int i[8];
808 	} args;
809 	int rval[2];
810 	u_quad_t sticks;
811 
812 	cnt.v_syscall++;
813 	if (!USERMODE(frame.f_sr))
814 		panic("syscall");
815 	p = curproc;
816 	sticks = p->p_sticks;
817 	p->p_md.md_regs = frame.f_regs;
818 	opc = frame.f_pc - 2;
819 	callp = sysent, numsys = nsysent;
820 	params = (caddr_t)frame.f_regs[SP] + sizeof(int);
821 	switch (code) {
822 
823 	case SYS_syscall:
824 		/*
825 		 * Code is first argument, followed by actual args.
826 		 */
827 		code = fuword(params);
828 		params += sizeof(int);
829 		/*
830 		 * XXX sigreturn requires special stack manipulation
831 		 * that is only done if entered via the sigreturn
832 		 * trap.  Cannot allow it here so make sure we fail.
833 		 */
834 		if (code == SYS_sigreturn)
835 			code = numsys;
836 		break;
837 
838 	case SYS___syscall:
839 		/*
840 		 * Like syscall, but code is a quad, so as to maintain
841 		 * quad alignment for the rest of the arguments.
842 		 */
843 		code = fuword(params + _QUAD_LOWWORD * sizeof(int));
844 		params += sizeof(quad_t);
845 		break;
846 
847 	default:
848 		/* nothing to do by default */
849 		break;
850 	}
851 	if (code < numsys)
852 		callp += code;
853 	else
854 		callp += SYS_syscall;	/* => nosys */
855 	argsize = callp->sy_narg * sizeof(int);
856 	if (argsize && (error = copyin(params, (caddr_t)&args, argsize))) {
857 #ifdef KTRACE
858 		if (KTRPOINT(p, KTR_SYSCALL))
859 			ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i);
860 #endif
861 		goto bad;
862 	}
863 #ifdef KTRACE
864 	if (KTRPOINT(p, KTR_SYSCALL))
865 		ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i);
866 #endif
867 	rval[0] = 0;
868 	rval[1] = frame.f_regs[D1];
869 	error = (*callp->sy_call)(p, &args, rval);
870 	switch (error) {
871 
872 	case 0:
873 		/*
874 		 * Reinitialize proc pointer `p' as it may be different
875 		 * if this is a child returning from fork syscall.
876 		 */
877 		p = curproc;
878 		frame.f_regs[D0] = rval[0];
879 		frame.f_regs[D1] = rval[1];
880 		frame.f_sr &= ~PSL_C;
881 		break;
882 
883 	case ERESTART:
884 		frame.f_pc = opc;
885 		break;
886 
887 	case EJUSTRETURN:
888 		break;		/* nothing to do */
889 
890 	default:
891 	bad:
892 		frame.f_regs[D0] = error;
893 		frame.f_sr |= PSL_C;
894 		break;
895 	}
896 
897 	userret(p, &frame, sticks, (u_int)0, 0);
898 #ifdef KTRACE
899 	if (KTRPOINT(p, KTR_SYSRET))
900 		ktrsysret(p->p_tracep, code, error, rval[0]);
901 #endif
902 }
903