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