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