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