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