xref: /original-bsd/sys/hp300/hp300/trap.c (revision 3705696b)
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.1 (Berkeley) 06/16/93
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, 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_md.md_flags & MDP_HPUX) {
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_md.md_flags & MDP_HPUX)
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_md.md_flags & MDP_HPUX)
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_md.md_flags & MDP_HPUX) {
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_md.md_flags & MDP_HPUX) {
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 #ifdef HPUXCOMPAT
465 		if (ISHPMMADDR(va)) {
466 			vm_offset_t bva;
467 
468 			rv = pmap_mapmulti(map->pmap, va);
469 			if (rv != KERN_SUCCESS) {
470 				bva = HPMMBASEADDR(va);
471 				rv = vm_fault(map, bva, ftype, FALSE);
472 				if (rv == KERN_SUCCESS)
473 					(void) pmap_mapmulti(map->pmap, va);
474 			}
475 		} else
476 #endif
477 		rv = vm_fault(map, va, ftype, FALSE);
478 #ifdef DEBUG
479 		if (rv && MDB_ISPID(p->p_pid))
480 			printf("vm_fault(%x, %x, %x, 0) -> %x\n",
481 			       map, va, ftype, rv);
482 #endif
483 		/*
484 		 * If this was a stack access we keep track of the maximum
485 		 * accessed stack size.  Also, if vm_fault gets a protection
486 		 * failure it is due to accessing the stack region outside
487 		 * the current limit and we need to reflect that as an access
488 		 * error.
489 		 */
490 		if ((caddr_t)va >= vm->vm_maxsaddr && map != kernel_map) {
491 			if (rv == KERN_SUCCESS) {
492 				unsigned nss;
493 
494 				nss = clrnd(btoc(USRSTACK-(unsigned)va));
495 				if (nss > vm->vm_ssize)
496 					vm->vm_ssize = nss;
497 			} else if (rv == KERN_PROTECTION_FAILURE)
498 				rv = KERN_INVALID_ADDRESS;
499 		}
500 		if (rv == KERN_SUCCESS) {
501 			if (type == T_MMUFLT) {
502 #ifdef HP380
503 				if (mmutype == MMU_68040)
504 					(void) writeback(&frame, 1);
505 #endif
506 				return;
507 			}
508 			goto out;
509 		}
510 		if (type == T_MMUFLT) {
511 			if (p->p_addr->u_pcb.pcb_onfault)
512 				goto copyfault;
513 			printf("vm_fault(%x, %x, %x, 0) -> %x\n",
514 			       map, va, ftype, rv);
515 			printf("  type %x, code [mmu,,ssw]: %x\n",
516 			       type, code);
517 			goto dopanic;
518 		}
519 		ucode = v;
520 		i = (rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV;
521 		break;
522 	    }
523 	}
524 	trapsignal(p, i, ucode);
525 	if ((type & T_USER) == 0)
526 		return;
527 out:
528 	userret(p, &frame, sticks, v, 1);
529 }
530 
531 #ifdef HP380
532 #ifdef DEBUG
533 struct writebackstats {
534 	int calls;
535 	int cpushes;
536 	int move16s;
537 	int wb1s, wb2s, wb3s;
538 	int wbsize[4];
539 } wbstats;
540 
541 char *f7sz[] = { "longword", "byte", "word", "line" };
542 char *f7tt[] = { "normal", "MOVE16", "AFC", "ACK" };
543 char *f7tm[] = { "d-push", "u-data", "u-code", "M-data",
544 		 "M-code", "k-data", "k-code", "RES" };
545 char wberrstr[] =
546     "WARNING: pid %d(%s) writeback [%s] failed, pc=%x fa=%x wba=%x wbd=%x\n";
547 #endif
548 
549 writeback(fp, docachepush)
550 	struct frame *fp;
551 	int docachepush;
552 {
553 	register struct fmt7 *f = &fp->f_fmt7;
554 	register struct proc *p = curproc;
555 	int err = 0;
556 	u_int fa;
557 	caddr_t oonfault = p->p_addr->u_pcb.pcb_onfault;
558 
559 #ifdef DEBUG
560 	if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) {
561 		printf(" pid=%d, fa=%x,", p->p_pid, f->f_fa);
562 		dumpssw(f->f_ssw);
563 	}
564 	wbstats.calls++;
565 #endif
566 	/*
567 	 * Deal with special cases first.
568 	 */
569 	if ((f->f_ssw & SSW4_TMMASK) == SSW4_TMDCP) {
570 		/*
571 		 * Dcache push fault.
572 		 * Line-align the address and write out the push data to
573 		 * the indicated physical address.
574 		 */
575 #ifdef DEBUG
576 		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) {
577 			printf(" pushing %s to PA %x, data %x",
578 			       f7sz[(f->f_ssw & SSW4_SZMASK) >> 5],
579 			       f->f_fa, f->f_pd0);
580 			if ((f->f_ssw & SSW4_SZMASK) == SSW4_SZLN)
581 				printf("/%x/%x/%x",
582 				       f->f_pd1, f->f_pd2, f->f_pd3);
583 			printf("\n");
584 		}
585 		if (f->f_wb1s & SSW4_WBSV)
586 			panic("writeback: cache push with WB1S valid");
587 		wbstats.cpushes++;
588 #endif
589 		/*
590 		 * XXX there are security problems if we attempt to do a
591 		 * cache push after a signal handler has been called.
592 		 */
593 		if (docachepush) {
594 			pmap_enter(kernel_pmap, (vm_offset_t)vmmap,
595 				   trunc_page(f->f_fa), VM_PROT_WRITE, TRUE);
596 			fa = (u_int)&vmmap[(f->f_fa & PGOFSET) & ~0xF];
597 			bcopy((caddr_t)&f->f_pd0, (caddr_t)fa, 16);
598 			DCFL(pmap_extract(kernel_pmap, (vm_offset_t)fa));
599 			pmap_remove(kernel_pmap, (vm_offset_t)vmmap,
600 				    (vm_offset_t)&vmmap[NBPG]);
601 		} else
602 			printf("WARNING: pid %d(%s) uid %d: CPUSH not done\n",
603 			       p->p_pid, p->p_comm, p->p_ucred->cr_uid);
604 	} else if ((f->f_ssw & (SSW4_RW|SSW4_TTMASK)) == SSW4_TTM16) {
605 		/*
606 		 * MOVE16 fault.
607 		 * Line-align the address and write out the push data to
608 		 * the indicated virtual address.
609 		 */
610 #ifdef DEBUG
611 		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
612 			printf(" MOVE16 to VA %x(%x), data %x/%x/%x/%x\n",
613 			       f->f_fa, f->f_fa & ~0xF, f->f_pd0, f->f_pd1,
614 			       f->f_pd2, f->f_pd3);
615 		if (f->f_wb1s & SSW4_WBSV)
616 			panic("writeback: MOVE16 with WB1S valid");
617 		wbstats.move16s++;
618 #endif
619 		if (KDFAULT(f->f_wb1s))
620 			bcopy((caddr_t)&f->f_pd0, (caddr_t)(f->f_fa & ~0xF), 16);
621 		else
622 			err = suline((caddr_t)(f->f_fa & ~0xF), (caddr_t)&f->f_pd0);
623 		if (err) {
624 			fa = f->f_fa & ~0xF;
625 #ifdef DEBUG
626 			if (mmudebug & MDB_WBFAILED)
627 				printf(wberrstr, p->p_pid, p->p_comm,
628 				       "MOVE16", fp->f_pc, f->f_fa,
629 				       f->f_fa & ~0xF, f->f_pd0);
630 #endif
631 		}
632 	} else if (f->f_wb1s & SSW4_WBSV) {
633 		/*
634 		 * Writeback #1.
635 		 * Position the "memory-aligned" data and write it out.
636 		 */
637 		register u_int wb1d = f->f_wb1d;
638 		register int off;
639 
640 #ifdef DEBUG
641 		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
642 			dumpwb(1, f->f_wb1s, f->f_wb1a, f->f_wb1d);
643 		wbstats.wb1s++;
644 		wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++;
645 #endif
646 		off = (f->f_wb1a & 3) * 8;
647 		switch (f->f_wb1s & SSW4_SZMASK) {
648 		case SSW4_SZLW:
649 			if (off)
650 				wb1d = (wb1d >> (32 - off)) | (wb1d << off);
651 			if (KDFAULT(f->f_wb1s))
652 				*(long *)f->f_wb1a = wb1d;
653 			else
654 				err = suword((caddr_t)f->f_wb1a, wb1d);
655 			break;
656 		case SSW4_SZB:
657 			off = 24 - off;
658 			if (off)
659 				wb1d >>= off;
660 			if (KDFAULT(f->f_wb1s))
661 				*(char *)f->f_wb1a = wb1d;
662 			else
663 				err = subyte((caddr_t)f->f_wb1a, wb1d);
664 			break;
665 		case SSW4_SZW:
666 			off = (off + 16) % 32;
667 			if (off)
668 				wb1d = (wb1d >> (32 - off)) | (wb1d << off);
669 			if (KDFAULT(f->f_wb1s))
670 				*(short *)f->f_wb1a = wb1d;
671 			else
672 				err = susword((caddr_t)f->f_wb1a, wb1d);
673 			break;
674 		}
675 		if (err) {
676 			fa = f->f_wb1a;
677 #ifdef DEBUG
678 			if (mmudebug & MDB_WBFAILED)
679 				printf(wberrstr, p->p_pid, p->p_comm,
680 				       "#1", fp->f_pc, f->f_fa,
681 				       f->f_wb1a, f->f_wb1d);
682 #endif
683 		}
684 	}
685 	/*
686 	 * Deal with the "normal" writebacks.
687 	 *
688 	 * XXX writeback2 is known to reflect a LINE size writeback after
689 	 * a MOVE16 was already dealt with above.  Ignore it.
690 	 */
691 	if (err == 0 && (f->f_wb2s & SSW4_WBSV) &&
692 	    (f->f_wb2s & SSW4_SZMASK) != SSW4_SZLN) {
693 #ifdef DEBUG
694 		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
695 			dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d);
696 		wbstats.wb2s++;
697 		wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++;
698 #endif
699 		switch (f->f_wb2s & SSW4_SZMASK) {
700 		case SSW4_SZLW:
701 			if (KDFAULT(f->f_wb2s))
702 				*(long *)f->f_wb2a = f->f_wb2d;
703 			else
704 				err = suword((caddr_t)f->f_wb2a, f->f_wb2d);
705 			break;
706 		case SSW4_SZB:
707 			if (KDFAULT(f->f_wb2s))
708 				*(char *)f->f_wb2a = f->f_wb2d;
709 			else
710 				err = subyte((caddr_t)f->f_wb2a, f->f_wb2d);
711 			break;
712 		case SSW4_SZW:
713 			if (KDFAULT(f->f_wb2s))
714 				*(short *)f->f_wb2a = f->f_wb2d;
715 			else
716 				err = susword((caddr_t)f->f_wb2a, f->f_wb2d);
717 			break;
718 		}
719 		if (err) {
720 			fa = f->f_wb2a;
721 #ifdef DEBUG
722 			if (mmudebug & MDB_WBFAILED) {
723 				printf(wberrstr, p->p_pid, p->p_comm,
724 				       "#2", fp->f_pc, f->f_fa,
725 				       f->f_wb2a, f->f_wb2d);
726 				dumpssw(f->f_ssw);
727 				dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d);
728 			}
729 #endif
730 		}
731 	}
732 	if (err == 0 && (f->f_wb3s & SSW4_WBSV)) {
733 #ifdef DEBUG
734 		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
735 			dumpwb(3, f->f_wb3s, f->f_wb3a, f->f_wb3d);
736 		wbstats.wb3s++;
737 		wbstats.wbsize[(f->f_wb3s&SSW4_SZMASK)>>5]++;
738 #endif
739 		switch (f->f_wb3s & SSW4_SZMASK) {
740 		case SSW4_SZLW:
741 			if (KDFAULT(f->f_wb3s))
742 				*(long *)f->f_wb3a = f->f_wb3d;
743 			else
744 				err = suword((caddr_t)f->f_wb3a, f->f_wb3d);
745 			break;
746 		case SSW4_SZB:
747 			if (KDFAULT(f->f_wb3s))
748 				*(char *)f->f_wb3a = f->f_wb3d;
749 			else
750 				err = subyte((caddr_t)f->f_wb3a, f->f_wb3d);
751 			break;
752 		case SSW4_SZW:
753 			if (KDFAULT(f->f_wb3s))
754 				*(short *)f->f_wb3a = f->f_wb3d;
755 			else
756 				err = susword((caddr_t)f->f_wb3a, f->f_wb3d);
757 			break;
758 #ifdef DEBUG
759 		case SSW4_SZLN:
760 			panic("writeback: wb3s indicates LINE write");
761 #endif
762 		}
763 		if (err) {
764 			fa = f->f_wb3a;
765 #ifdef DEBUG
766 			if (mmudebug & MDB_WBFAILED)
767 				printf(wberrstr, p->p_pid, p->p_comm,
768 				       "#3", fp->f_pc, f->f_fa,
769 				       f->f_wb3a, f->f_wb3d);
770 #endif
771 		}
772 	}
773 	p->p_addr->u_pcb.pcb_onfault = oonfault;
774 	/*
775 	 * Determine the cause of the failure if any translating to
776 	 * a signal.  If the corresponding VA is valid and RO it is
777 	 * a protection fault (SIGBUS) otherwise consider it an
778 	 * illegal reference (SIGSEGV).
779 	 */
780 	if (err) {
781 		if (vm_map_check_protection(&p->p_vmspace->vm_map,
782 					    trunc_page(fa), round_page(fa),
783 					    VM_PROT_READ) &&
784 		    !vm_map_check_protection(&p->p_vmspace->vm_map,
785 					     trunc_page(fa), round_page(fa),
786 					     VM_PROT_WRITE))
787 			err = SIGBUS;
788 		else
789 			err = SIGSEGV;
790 	}
791 	return(err);
792 }
793 
794 #ifdef DEBUG
795 dumpssw(ssw)
796 	register u_short ssw;
797 {
798 	printf(" SSW: %x: ", ssw);
799 	if (ssw & SSW4_CP)
800 		printf("CP,");
801 	if (ssw & SSW4_CU)
802 		printf("CU,");
803 	if (ssw & SSW4_CT)
804 		printf("CT,");
805 	if (ssw & SSW4_CM)
806 		printf("CM,");
807 	if (ssw & SSW4_MA)
808 		printf("MA,");
809 	if (ssw & SSW4_ATC)
810 		printf("ATC,");
811 	if (ssw & SSW4_LK)
812 		printf("LK,");
813 	if (ssw & SSW4_RW)
814 		printf("RW,");
815 	printf(" SZ=%s, TT=%s, TM=%s\n",
816 	       f7sz[(ssw & SSW4_SZMASK) >> 5],
817 	       f7tt[(ssw & SSW4_TTMASK) >> 3],
818 	       f7tm[ssw & SSW4_TMMASK]);
819 }
820 
821 dumpwb(num, s, a, d)
822 	int num;
823 	u_short s;
824 	u_int a, d;
825 {
826 	register struct proc *p = curproc;
827 	vm_offset_t pa;
828 
829 	printf(" writeback #%d: VA %x, data %x, SZ=%s, TT=%s, TM=%s\n",
830 	       num, a, d, f7sz[(s & SSW4_SZMASK) >> 5],
831 	       f7tt[(s & SSW4_TTMASK) >> 3], f7tm[s & SSW4_TMMASK]);
832 	printf("               PA ");
833 	pa = pmap_extract(&p->p_vmspace->vm_pmap, (vm_offset_t)a);
834 	if (pa == 0)
835 		printf("<invalid address>");
836 	else
837 		printf("%x, current value %x", pa, fuword((caddr_t)a));
838 	printf("\n");
839 }
840 #endif
841 #endif
842 
843 /*
844  * Proces a system call.
845  */
846 syscall(code, frame)
847 	u_int code;
848 	struct frame frame;
849 {
850 	register caddr_t params;
851 	register struct sysent *callp;
852 	register struct proc *p;
853 	int error, opc, numsys, s;
854 	u_int argsize;
855 	struct args {
856 		int i[8];
857 	} args;
858 	int rval[2];
859 	u_quad_t sticks;
860 #ifdef HPUXCOMPAT
861 	extern struct sysent hpuxsysent[];
862 	extern int hpuxnsysent, notimp();
863 #endif
864 
865 	cnt.v_syscall++;
866 	if (!USERMODE(frame.f_sr))
867 		panic("syscall");
868 	p = curproc;
869 	sticks = p->p_sticks;
870 	p->p_md.md_regs = frame.f_regs;
871 	opc = frame.f_pc - 2;
872 #ifdef HPUXCOMPAT
873 	if (p->p_md.md_flags & MDP_HPUX)
874 		callp = hpuxsysent, numsys = hpuxnsysent;
875 	else
876 #endif
877 		callp = sysent, numsys = nsysent;
878 	params = (caddr_t)frame.f_regs[SP] + sizeof(int);
879 	switch (code) {
880 
881 	case SYS_syscall:
882 		/*
883 		 * Code is first argument, followed by actual args.
884 		 */
885 		code = fuword(params);
886 		params += sizeof(int);
887 		/*
888 		 * XXX sigreturn requires special stack manipulation
889 		 * that is only done if entered via the sigreturn
890 		 * trap.  Cannot allow it here so make sure we fail.
891 		 */
892 		if (code == SYS_sigreturn)
893 			code = numsys;
894 		break;
895 
896 	case SYS___syscall:
897 		/*
898 		 * Like syscall, but code is a quad, so as to maintain
899 		 * quad alignment for the rest of the arguments.
900 		 */
901 #ifdef HPUXCOMPAT
902 		if (p->p_md.md_flags & MDP_HPUX)
903 			break;
904 #endif
905 		code = fuword(params + _QUAD_LOWWORD * sizeof(int));
906 		params += sizeof(quad_t);
907 		break;
908 
909 	default:
910 		/* nothing to do by default */
911 		break;
912 	}
913 	if (code < numsys)
914 		callp += code;
915 	else
916 		callp += SYS_syscall;	/* => nosys */
917 	argsize = callp->sy_narg * sizeof(int);
918 	if (argsize && (error = copyin(params, (caddr_t)&args, argsize))) {
919 #ifdef KTRACE
920 		if (KTRPOINT(p, KTR_SYSCALL))
921 			ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i);
922 #endif
923 		goto bad;
924 	}
925 #ifdef KTRACE
926 	if (KTRPOINT(p, KTR_SYSCALL))
927 		ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i);
928 #endif
929 	rval[0] = 0;
930 	rval[1] = frame.f_regs[D1];
931 #ifdef HPUXCOMPAT
932 	/* debug kludge */
933 	if (callp->sy_call == notimp)
934 		error = notimp(p, args.i, rval, code, callp->sy_narg);
935 	else
936 #endif
937 		error = (*callp->sy_call)(p, &args, rval);
938 	switch (error) {
939 
940 	case 0:
941 		/*
942 		 * Reinitialize proc pointer `p' as it may be different
943 		 * if this is a child returning from fork syscall.
944 		 */
945 		p = curproc;
946 		frame.f_regs[D0] = rval[0];
947 		frame.f_regs[D1] = rval[1];
948 		frame.f_sr &= ~PSL_C;
949 		break;
950 
951 	case ERESTART:
952 		frame.f_pc = opc;
953 		break;
954 
955 	case EJUSTRETURN:
956 		break;		/* nothing to do */
957 
958 	default:
959 	bad:
960 #ifdef HPUXCOMPAT
961 		if (p->p_md.md_flags & MDP_HPUX)
962 			error = bsdtohpuxerrno(error);
963 #endif
964 		frame.f_regs[D0] = error;
965 		frame.f_sr |= PSL_C;
966 		break;
967 	}
968 
969 	userret(p, &frame, sticks, (u_int)0, 0);
970 #ifdef KTRACE
971 	if (KTRPOINT(p, KTR_SYSRET))
972 		ktrsysret(p->p_tracep, code, error, rval[0]);
973 #endif
974 }
975