xref: /original-bsd/sys/pmax/pmax/trap.c (revision 00a25f5a)
1 /*
2  * Copyright (c) 1988 University of Utah.
3  * Copyright (c) 1992, 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 and Ralph Campbell.
9  *
10  * %sccs.include.redist.c%
11  *
12  * from: Utah $Hdr: trap.c 1.32 91/04/06$
13  *
14  *	@(#)trap.c	8.7 (Berkeley) 06/02/95
15  */
16 
17 #include <sys/param.h>
18 #include <sys/systm.h>
19 #include <sys/proc.h>
20 #include <sys/kernel.h>
21 #include <sys/signalvar.h>
22 #include <sys/syscall.h>
23 #include <sys/user.h>
24 #include <sys/buf.h>
25 #ifdef KTRACE
26 #include <sys/ktrace.h>
27 #endif
28 #include <net/netisr.h>
29 
30 #include <machine/trap.h>
31 #include <machine/psl.h>
32 #include <machine/reg.h>
33 #include <machine/cpu.h>
34 #include <machine/pte.h>
35 #include <machine/mips_opcode.h>
36 
37 #include <vm/vm.h>
38 #include <vm/vm_kern.h>
39 #include <vm/vm_page.h>
40 
41 #include <pmax/pmax/clockreg.h>
42 #include <pmax/pmax/kn01.h>
43 #include <pmax/pmax/kn02.h>
44 #include <pmax/pmax/kmin.h>
45 #include <pmax/pmax/maxine.h>
46 #include <pmax/pmax/kn03.h>
47 #include <pmax/pmax/asic.h>
48 #include <pmax/pmax/turbochannel.h>
49 
50 #include <pmax/stand/dec_prom.h>
51 
52 #include <asc.h>
53 #include <sii.h>
54 #include <le.h>
55 #include <dc.h>
56 
57 struct	proc *machFPCurProcPtr;		/* pointer to last proc to use FP */
58 
59 extern void MachKernGenException();
60 extern void MachUserGenException();
61 extern void MachKernIntr();
62 extern void MachUserIntr();
63 extern void MachTLBModException();
64 extern void MachTLBMissException();
65 extern unsigned MachEmulateBranch();
66 
67 void (*machExceptionTable[])() = {
68 /*
69  * The kernel exception handlers.
70  */
71 	MachKernIntr,			/* external interrupt */
72 	MachKernGenException,		/* TLB modification */
73 	MachTLBMissException,		/* TLB miss (load or instr. fetch) */
74 	MachTLBMissException,		/* TLB miss (store) */
75 	MachKernGenException,		/* address error (load or I-fetch) */
76 	MachKernGenException,		/* address error (store) */
77 	MachKernGenException,		/* bus error (I-fetch) */
78 	MachKernGenException,		/* bus error (load or store) */
79 	MachKernGenException,		/* system call */
80 	MachKernGenException,		/* breakpoint */
81 	MachKernGenException,		/* reserved instruction */
82 	MachKernGenException,		/* coprocessor unusable */
83 	MachKernGenException,		/* arithmetic overflow */
84 	MachKernGenException,		/* reserved */
85 	MachKernGenException,		/* reserved */
86 	MachKernGenException,		/* reserved */
87 /*
88  * The user exception handlers.
89  */
90 	MachUserIntr,
91 	MachUserGenException,
92 	MachUserGenException,
93 	MachUserGenException,
94 	MachUserGenException,
95 	MachUserGenException,
96 	MachUserGenException,
97 	MachUserGenException,
98 	MachUserGenException,
99 	MachUserGenException,
100 	MachUserGenException,
101 	MachUserGenException,
102 	MachUserGenException,
103 	MachUserGenException,
104 	MachUserGenException,
105 	MachUserGenException,
106 };
107 
108 char	*trap_type[] = {
109 	"external interrupt",
110 	"TLB modification",
111 	"TLB miss (load or instr. fetch)",
112 	"TLB miss (store)",
113 	"address error (load or I-fetch)",
114 	"address error (store)",
115 	"bus error (I-fetch)",
116 	"bus error (load or store)",
117 	"system call",
118 	"breakpoint",
119 	"reserved instruction",
120 	"coprocessor unusable",
121 	"arithmetic overflow",
122 	"reserved 13",
123 	"reserved 14",
124 	"reserved 15",
125 };
126 
127 #ifdef DEBUG
128 #define TRAPSIZE	10
129 struct trapdebug {		/* trap history buffer for debugging */
130 	u_int	status;
131 	u_int	cause;
132 	u_int	vadr;
133 	u_int	pc;
134 	u_int	ra;
135 	u_int	code;
136 } trapdebug[TRAPSIZE], *trp = trapdebug;
137 
138 u_int	intr_level;		/* number of nested interrupts */
139 #endif
140 
141 static void pmax_errintr();
142 static void kn02_errintr(), kn02ba_errintr();
143 #ifdef DS5000_240
144 static void kn03_errintr();
145 #endif
146 static unsigned kn02ba_recover_erradr();
147 extern tc_option_t tc_slot_info[TC_MAX_LOGICAL_SLOTS];
148 extern u_long kmin_tc3_imask, xine_tc3_imask;
149 extern const struct callback *callv;
150 #ifdef DS5000_240
151 extern u_long kn03_tc3_imask;
152 #endif
153 int (*pmax_hardware_intr)() = (int (*)())0;
154 extern volatile struct chiptime *Mach_clock_addr;
155 extern long intrcnt[];
156 
157 /*
158  * Handle an exception.
159  * Called from MachKernGenException() or MachUserGenException()
160  * when a processor trap occurs.
161  * In the case of a kernel trap, we return the pc where to resume if
162  * ((struct pcb *)UADDR)->pcb_onfault is set, otherwise, return old pc.
163  */
164 unsigned
165 trap(statusReg, causeReg, vadr, pc, args)
166 	unsigned statusReg;	/* status register at time of the exception */
167 	unsigned causeReg;	/* cause register at time of exception */
168 	unsigned vadr;		/* address (if any) the fault occured on */
169 	unsigned pc;		/* program counter where to continue */
170 {
171 	register int type, i;
172 	unsigned ucode = 0;
173 	register struct proc *p = curproc;
174 	u_quad_t sticks;
175 	vm_prot_t ftype;
176 	extern unsigned onfault_table[];
177 
178 #ifdef DEBUG
179 	trp->status = statusReg;
180 	trp->cause = causeReg;
181 	trp->vadr = vadr;
182 	trp->pc = pc;
183 	trp->ra = !USERMODE(statusReg) ? ((int *)&args)[19] :
184 		p->p_md.md_regs[RA];
185 	trp->code = 0;
186 	if (++trp == &trapdebug[TRAPSIZE])
187 		trp = trapdebug;
188 #endif
189 
190 	cnt.v_trap++;
191 	type = (causeReg & MACH_CR_EXC_CODE) >> MACH_CR_EXC_CODE_SHIFT;
192 	if (USERMODE(statusReg)) {
193 		type |= T_USER;
194 		sticks = p->p_sticks;
195 	}
196 
197 	/*
198 	 * Enable hardware interrupts if they were on before.
199 	 * We only respond to software interrupts when returning to user mode.
200 	 */
201 	if (statusReg & MACH_SR_INT_ENA_PREV)
202 		splx((statusReg & MACH_HARD_INT_MASK) | MACH_SR_INT_ENA_CUR);
203 
204 	switch (type) {
205 	case T_TLB_MOD:
206 		/* check for kernel address */
207 		if ((int)vadr < 0) {
208 			register pt_entry_t *pte;
209 			register unsigned entry;
210 			register vm_offset_t pa;
211 
212 			pte = kvtopte(vadr);
213 			entry = pte->pt_entry;
214 #ifdef DIAGNOSTIC
215 			if (!(entry & PG_V) || (entry & PG_M))
216 				panic("trap: ktlbmod: invalid pte");
217 #endif
218 			if (entry & PG_RO) {
219 				/* write to read only page in the kernel */
220 				ftype = VM_PROT_WRITE;
221 				goto kernel_fault;
222 			}
223 			entry |= PG_M;
224 			pte->pt_entry = entry;
225 			vadr &= ~PGOFSET;
226 			MachTLBUpdate(vadr, entry);
227 			pa = entry & PG_FRAME;
228 #ifdef ATTR
229 			pmap_attributes[atop(pa)] |= PMAP_ATTR_MOD;
230 #else
231 			if (!IS_VM_PHYSADDR(pa))
232 				panic("trap: ktlbmod: unmanaged page");
233 			PHYS_TO_VM_PAGE(pa)->flags &= ~PG_CLEAN;
234 #endif
235 			return (pc);
236 		}
237 		/* FALLTHROUGH */
238 
239 	case T_TLB_MOD+T_USER:
240 	    {
241 		register pt_entry_t *pte;
242 		register unsigned entry;
243 		register vm_offset_t pa;
244 		pmap_t pmap = &p->p_vmspace->vm_pmap;
245 
246 		if (!(pte = pmap_segmap(pmap, vadr)))
247 			panic("trap: utlbmod: invalid segmap");
248 		pte += (vadr >> PGSHIFT) & (NPTEPG - 1);
249 		entry = pte->pt_entry;
250 #ifdef DIAGNOSTIC
251 		if (!(entry & PG_V) || (entry & PG_M))
252 			panic("trap: utlbmod: invalid pte");
253 #endif
254 		if (entry & PG_RO) {
255 			/* write to read only page */
256 			ftype = VM_PROT_WRITE;
257 			goto dofault;
258 		}
259 		entry |= PG_M;
260 		pte->pt_entry = entry;
261 		vadr = (vadr & ~PGOFSET) |
262 			(pmap->pm_tlbpid << VMMACH_TLB_PID_SHIFT);
263 		MachTLBUpdate(vadr, entry);
264 		pa = entry & PG_FRAME;
265 #ifdef ATTR
266 		pmap_attributes[atop(pa)] |= PMAP_ATTR_MOD;
267 #else
268 		if (!IS_VM_PHYSADDR(pa))
269 			panic("trap: utlbmod: unmanaged page");
270 		PHYS_TO_VM_PAGE(pa)->flags &= ~PG_CLEAN;
271 #endif
272 		if (!USERMODE(statusReg))
273 			return (pc);
274 		goto out;
275 	    }
276 
277 	case T_TLB_LD_MISS:
278 	case T_TLB_ST_MISS:
279 		ftype = (type == T_TLB_ST_MISS) ? VM_PROT_WRITE : VM_PROT_READ;
280 		/* check for kernel address */
281 		if ((int)vadr < 0) {
282 			register vm_offset_t va;
283 			int rv;
284 
285 		kernel_fault:
286 			va = trunc_page((vm_offset_t)vadr);
287 			rv = vm_fault(kernel_map, va, ftype, FALSE);
288 			if (rv == KERN_SUCCESS)
289 				return (pc);
290 			if (i = ((struct pcb *)UADDR)->pcb_onfault) {
291 				((struct pcb *)UADDR)->pcb_onfault = 0;
292 				return (onfault_table[i]);
293 			}
294 			goto err;
295 		}
296 		/*
297 		 * It is an error for the kernel to access user space except
298 		 * through the copyin/copyout routines.
299 		 */
300 		if ((i = ((struct pcb *)UADDR)->pcb_onfault) == 0)
301 			goto err;
302 		/* check for fuswintr() or suswintr() getting a page fault */
303 		if (i == 4)
304 			return (onfault_table[i]);
305 		goto dofault;
306 
307 	case T_TLB_LD_MISS+T_USER:
308 		ftype = VM_PROT_READ;
309 		goto dofault;
310 
311 	case T_TLB_ST_MISS+T_USER:
312 		ftype = VM_PROT_WRITE;
313 	dofault:
314 	    {
315 		register vm_offset_t va;
316 		register struct vmspace *vm;
317 		register vm_map_t map;
318 		int rv;
319 
320 		vm = p->p_vmspace;
321 		map = &vm->vm_map;
322 		va = trunc_page((vm_offset_t)vadr);
323 		rv = vm_fault(map, va, ftype, FALSE);
324 		/*
325 		 * If this was a stack access we keep track of the maximum
326 		 * accessed stack size.  Also, if vm_fault gets a protection
327 		 * failure it is due to accessing the stack region outside
328 		 * the current limit and we need to reflect that as an access
329 		 * error.
330 		 */
331 		if ((caddr_t)va >= vm->vm_maxsaddr) {
332 			if (rv == KERN_SUCCESS) {
333 				unsigned nss;
334 
335 				nss = clrnd(btoc(USRSTACK-(unsigned)va));
336 				if (nss > vm->vm_ssize)
337 					vm->vm_ssize = nss;
338 			} else if (rv == KERN_PROTECTION_FAILURE)
339 				rv = KERN_INVALID_ADDRESS;
340 		}
341 		if (rv == KERN_SUCCESS) {
342 			if (!USERMODE(statusReg))
343 				return (pc);
344 			goto out;
345 		}
346 		if (!USERMODE(statusReg)) {
347 			if (i = ((struct pcb *)UADDR)->pcb_onfault) {
348 				((struct pcb *)UADDR)->pcb_onfault = 0;
349 				return (onfault_table[i]);
350 			}
351 			goto err;
352 		}
353 		ucode = vadr;
354 		i = (rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV;
355 		break;
356 	    }
357 
358 	case T_ADDR_ERR_LD+T_USER:	/* misaligned or kseg access */
359 	case T_ADDR_ERR_ST+T_USER:	/* misaligned or kseg access */
360 	case T_BUS_ERR_IFETCH+T_USER:	/* BERR asserted to cpu */
361 	case T_BUS_ERR_LD_ST+T_USER:	/* BERR asserted to cpu */
362 		i = SIGSEGV;
363 		break;
364 
365 	case T_SYSCALL+T_USER:
366 	    {
367 		register int *locr0 = p->p_md.md_regs;
368 		register struct sysent *callp;
369 		unsigned int code;
370 		int numsys;
371 		struct args {
372 			int i[8];
373 		} args;
374 		int rval[2];
375 		struct sysent *systab;
376 		extern int nsysent;
377 #ifdef ULTRIXCOMPAT
378 		extern struct sysent ultrixsysent[];
379 		extern int ultrixnsysent;
380 #endif
381 
382 		cnt.v_syscall++;
383 		/* compute next PC after syscall instruction */
384 		if ((int)causeReg < 0)
385 			locr0[PC] = MachEmulateBranch(locr0, pc, 0, 0);
386 		else
387 			locr0[PC] += 4;
388 		systab = sysent;
389 		numsys = nsysent;
390 #ifdef ULTRIXCOMPAT
391 		if (p->p_md.md_flags & MDP_ULTRIX) {
392 			systab = ultrixsysent;
393 			numsys = ultrixnsysent;
394 		}
395 #endif
396 		code = locr0[V0];
397 		switch (code) {
398 		case SYS_syscall:
399 			/*
400 			 * Code is first argument, followed by actual args.
401 			 */
402 			code = locr0[A0];
403 			if (code >= numsys)
404 				callp = &systab[SYS_syscall]; /* (illegal) */
405 			else
406 				callp = &systab[code];
407 			i = callp->sy_argsize;
408 			args.i[0] = locr0[A1];
409 			args.i[1] = locr0[A2];
410 			args.i[2] = locr0[A3];
411 			if (i > 3 * sizeof(register_t)) {
412 				i = copyin((caddr_t)(locr0[SP] +
413 						4 * sizeof(register_t)),
414 					(caddr_t)&args.i[3],
415 					(u_int)(i - 3 * sizeof(register_t)));
416 				if (i) {
417 					locr0[V0] = i;
418 					locr0[A3] = 1;
419 #ifdef KTRACE
420 					if (KTRPOINT(p, KTR_SYSCALL))
421 						ktrsyscall(p->p_tracep, code,
422 							callp->sy_argsize,
423 							args.i);
424 #endif
425 					goto done;
426 				}
427 			}
428 			break;
429 
430 		case SYS___syscall:
431 			/*
432 			 * Like syscall, but code is a quad, so as to maintain
433 			 * quad alignment for the rest of the arguments.
434 			 */
435 			code = locr0[A0 + _QUAD_LOWWORD];
436 			if (code >= numsys)
437 				callp = &systab[SYS_syscall]; /* (illegal) */
438 			else
439 				callp = &systab[code];
440 			i = callp->sy_argsize;
441 			args.i[0] = locr0[A2];
442 			args.i[1] = locr0[A3];
443 			if (i > 2 * sizeof(register_t)) {
444 				i = copyin((caddr_t)(locr0[SP] +
445 						4 * sizeof(register_t)),
446 					(caddr_t)&args.i[2],
447 					(u_int)(i - 2 * sizeof(register_t)));
448 				if (i) {
449 					locr0[V0] = i;
450 					locr0[A3] = 1;
451 #ifdef KTRACE
452 					if (KTRPOINT(p, KTR_SYSCALL))
453 						ktrsyscall(p->p_tracep, code,
454 							callp->sy_argsize,
455 							args.i);
456 #endif
457 					goto done;
458 				}
459 			}
460 			break;
461 
462 		default:
463 			if (code >= numsys)
464 				callp = &systab[SYS_syscall]; /* (illegal) */
465 			else
466 				callp = &systab[code];
467 			i = callp->sy_argsize;
468 			args.i[0] = locr0[A0];
469 			args.i[1] = locr0[A1];
470 			args.i[2] = locr0[A2];
471 			args.i[3] = locr0[A3];
472 			if (i > 4 * sizeof(register_t)) {
473 				i = copyin((caddr_t)(locr0[SP] +
474 						4 * sizeof(register_t)),
475 					(caddr_t)&args.i[4],
476 					(u_int)(i - 4 * sizeof(register_t)));
477 				if (i) {
478 					locr0[V0] = i;
479 					locr0[A3] = 1;
480 #ifdef KTRACE
481 					if (KTRPOINT(p, KTR_SYSCALL))
482 						ktrsyscall(p->p_tracep, code,
483 							callp->sy_argsize,
484 							args.i);
485 #endif
486 					goto done;
487 				}
488 			}
489 		}
490 #ifdef KTRACE
491 		if (KTRPOINT(p, KTR_SYSCALL))
492 			ktrsyscall(p->p_tracep, code, callp->sy_argsize, args.i);
493 #endif
494 		rval[0] = 0;
495 		rval[1] = locr0[V1];
496 #ifdef DEBUG
497 		if (trp == trapdebug)
498 			trapdebug[TRAPSIZE - 1].code = code;
499 		else
500 			trp[-1].code = code;
501 #endif
502 		i = (*callp->sy_call)(p, &args, rval);
503 		/*
504 		 * Reinitialize proc pointer `p' as it may be different
505 		 * if this is a child returning from fork syscall.
506 		 */
507 		p = curproc;
508 		locr0 = p->p_md.md_regs;
509 #ifdef DEBUG
510 		{ int s;
511 		s = splhigh();
512 		trp->status = statusReg;
513 		trp->cause = causeReg;
514 		trp->vadr = locr0[SP];
515 		trp->pc = locr0[PC];
516 		trp->ra = locr0[RA];
517 		trp->code = -code;
518 		if (++trp == &trapdebug[TRAPSIZE])
519 			trp = trapdebug;
520 		splx(s);
521 		}
522 #endif
523 		switch (i) {
524 		case 0:
525 			locr0[V0] = rval[0];
526 			locr0[V1] = rval[1];
527 			locr0[A3] = 0;
528 			break;
529 
530 		case ERESTART:
531 			locr0[PC] = pc;
532 			break;
533 
534 		case EJUSTRETURN:
535 			break;	/* nothing to do */
536 
537 		default:
538 			locr0[V0] = i;
539 			locr0[A3] = 1;
540 		}
541 	done:
542 #ifdef KTRACE
543 		if (KTRPOINT(p, KTR_SYSRET))
544 			ktrsysret(p->p_tracep, code, i, rval[0]);
545 #endif
546 		goto out;
547 	    }
548 
549 	case T_BREAK+T_USER:
550 	    {
551 		register unsigned va, instr;
552 
553 		/* compute address of break instruction */
554 		va = pc;
555 		if ((int)causeReg < 0)
556 			va += 4;
557 
558 		/* read break instruction */
559 		instr = fuiword((caddr_t)va);
560 #if 0
561 		printf("trap: %s (%d) breakpoint %x at %x: (adr %x ins %x)\n",
562 			p->p_comm, p->p_pid, instr, pc,
563 			p->p_md.md_ss_addr, p->p_md.md_ss_instr); /* XXX */
564 #endif
565 #ifdef KADB
566 		if (instr == MACH_BREAK_BRKPT || instr == MACH_BREAK_SSTEP)
567 			goto err;
568 #endif
569 		if (p->p_md.md_ss_addr != va || instr != MACH_BREAK_SSTEP) {
570 			i = SIGTRAP;
571 			break;
572 		}
573 
574 		/* restore original instruction and clear BP  */
575 		i = suiword((caddr_t)va, p->p_md.md_ss_instr);
576 		if (i < 0) {
577 			vm_offset_t sa, ea;
578 			int rv;
579 
580 			sa = trunc_page((vm_offset_t)va);
581 			ea = round_page((vm_offset_t)va+sizeof(int)-1);
582 			rv = vm_map_protect(&p->p_vmspace->vm_map, sa, ea,
583 				VM_PROT_DEFAULT, FALSE);
584 			if (rv == KERN_SUCCESS) {
585 				i = suiword((caddr_t)va, p->p_md.md_ss_instr);
586 				(void) vm_map_protect(&p->p_vmspace->vm_map,
587 					sa, ea, VM_PROT_READ|VM_PROT_EXECUTE,
588 					FALSE);
589 			}
590 		}
591 		if (i < 0)
592 			printf("Warning: can't restore instruction at %x: %x\n",
593 				p->p_md.md_ss_addr, p->p_md.md_ss_instr);
594 		p->p_md.md_ss_addr = 0;
595 		i = SIGTRAP;
596 		break;
597 	    }
598 
599 	case T_RES_INST+T_USER:
600 		i = SIGILL;
601 		break;
602 
603 	case T_COP_UNUSABLE+T_USER:
604 		if ((causeReg & MACH_CR_COP_ERR) != 0x10000000) {
605 			i = SIGILL;	/* only FPU instructions allowed */
606 			break;
607 		}
608 		MachSwitchFPState(machFPCurProcPtr, p->p_md.md_regs);
609 		machFPCurProcPtr = p;
610 		p->p_md.md_regs[PS] |= MACH_SR_COP_1_BIT;
611 		p->p_md.md_flags |= MDP_FPUSED;
612 		goto out;
613 
614 	case T_OVFLOW+T_USER:
615 		i = SIGFPE;
616 		break;
617 
618 	case T_ADDR_ERR_LD:	/* misaligned access */
619 	case T_ADDR_ERR_ST:	/* misaligned access */
620 	case T_BUS_ERR_LD_ST:	/* BERR asserted to cpu */
621 		if (i = ((struct pcb *)UADDR)->pcb_onfault) {
622 			((struct pcb *)UADDR)->pcb_onfault = 0;
623 			return (onfault_table[i]);
624 		}
625 		/* FALLTHROUGH */
626 
627 	default:
628 	err:
629 #ifdef KADB
630 	    {
631 		extern struct pcb kdbpcb;
632 
633 		if (USERMODE(statusReg))
634 			kdbpcb = p->p_addr->u_pcb;
635 		else {
636 			kdbpcb.pcb_regs[ZERO] = 0;
637 			kdbpcb.pcb_regs[AST] = ((int *)&args)[2];
638 			kdbpcb.pcb_regs[V0] = ((int *)&args)[3];
639 			kdbpcb.pcb_regs[V1] = ((int *)&args)[4];
640 			kdbpcb.pcb_regs[A0] = ((int *)&args)[5];
641 			kdbpcb.pcb_regs[A1] = ((int *)&args)[6];
642 			kdbpcb.pcb_regs[A2] = ((int *)&args)[7];
643 			kdbpcb.pcb_regs[A3] = ((int *)&args)[8];
644 			kdbpcb.pcb_regs[T0] = ((int *)&args)[9];
645 			kdbpcb.pcb_regs[T1] = ((int *)&args)[10];
646 			kdbpcb.pcb_regs[T2] = ((int *)&args)[11];
647 			kdbpcb.pcb_regs[T3] = ((int *)&args)[12];
648 			kdbpcb.pcb_regs[T4] = ((int *)&args)[13];
649 			kdbpcb.pcb_regs[T5] = ((int *)&args)[14];
650 			kdbpcb.pcb_regs[T6] = ((int *)&args)[15];
651 			kdbpcb.pcb_regs[T7] = ((int *)&args)[16];
652 			kdbpcb.pcb_regs[T8] = ((int *)&args)[17];
653 			kdbpcb.pcb_regs[T9] = ((int *)&args)[18];
654 			kdbpcb.pcb_regs[RA] = ((int *)&args)[19];
655 			kdbpcb.pcb_regs[MULLO] = ((int *)&args)[21];
656 			kdbpcb.pcb_regs[MULHI] = ((int *)&args)[22];
657 			kdbpcb.pcb_regs[PC] = pc;
658 			kdbpcb.pcb_regs[SR] = statusReg;
659 			bzero((caddr_t)&kdbpcb.pcb_regs[F0], 33 * sizeof(int));
660 		}
661 		if (kdb(causeReg, vadr, p, !USERMODE(statusReg)))
662 			return (kdbpcb.pcb_regs[PC]);
663 	    }
664 #else
665 #ifdef DEBUG
666 		trapDump("trap");
667 #endif
668 #endif
669 		panic("trap");
670 	}
671 	trapsignal(p, i, ucode);
672 out:
673 	/*
674 	 * Note: we should only get here if returning to user mode.
675 	 */
676 	/* take pending signals */
677 	while ((i = CURSIG(p)) != 0)
678 		postsig(i);
679 	p->p_priority = p->p_usrpri;
680 	astpending = 0;
681 	if (want_resched) {
682 		int s;
683 
684 		/*
685 		 * Since we are curproc, clock will normally just change
686 		 * our priority without moving us from one queue to another
687 		 * (since the running process is not on a queue.)
688 		 * If that happened after we put ourselves on the run queue
689 		 * but before we switched, we might not be on the queue
690 		 * indicated by our priority.
691 		 */
692 		s = splstatclock();
693 		setrunqueue(p);
694 		p->p_stats->p_ru.ru_nivcsw++;
695 		mi_switch();
696 		splx(s);
697 		while ((i = CURSIG(p)) != 0)
698 			postsig(i);
699 	}
700 
701 	/*
702 	 * If profiling, charge system time to the trapped pc.
703 	 */
704 	if (p->p_flag & P_PROFIL) {
705 		extern int psratio;
706 
707 		addupc_task(p, pc, (int)(p->p_sticks - sticks) * psratio);
708 	}
709 
710 	curpriority = p->p_priority;
711 	return (pc);
712 }
713 
714 /*
715  * Handle an interrupt.
716  * Called from MachKernIntr() or MachUserIntr()
717  * Note: curproc might be NULL.
718  */
719 interrupt(statusReg, causeReg, pc)
720 	unsigned statusReg;	/* status register at time of the exception */
721 	unsigned causeReg;	/* cause register at time of exception */
722 	unsigned pc;		/* program counter where to continue */
723 {
724 	register unsigned mask;
725 	struct clockframe cf;
726 
727 #ifdef DEBUG
728 	trp->status = statusReg;
729 	trp->cause = causeReg;
730 	trp->vadr = 0;
731 	trp->pc = pc;
732 	trp->ra = 0;
733 	trp->code = 0;
734 	if (++trp == &trapdebug[TRAPSIZE])
735 		trp = trapdebug;
736 
737 	intr_level++;
738 #endif
739 
740 	cnt.v_intr++;
741 	mask = causeReg & statusReg;	/* pending interrupts & enable mask */
742 	if (pmax_hardware_intr)
743 		splx((*pmax_hardware_intr)(mask, pc, statusReg, causeReg));
744 	if (mask & MACH_INT_MASK_5) {
745 		intrcnt[7]++;
746 		if (!USERMODE(statusReg)) {
747 #ifdef DEBUG
748 			trapDump("fpintr");
749 #else
750 			printf("FPU interrupt: PC %x CR %x SR %x\n",
751 				pc, causeReg, statusReg);
752 #endif
753 		} else
754 			MachFPInterrupt(statusReg, causeReg, pc);
755 	}
756 	if (mask & MACH_SOFT_INT_MASK_0) {
757 		clearsoftclock();
758 		cnt.v_soft++;
759 		intrcnt[0]++;
760 		softclock();
761 	}
762 	/* process network interrupt if we trapped or will very soon */
763 	if ((mask & MACH_SOFT_INT_MASK_1) ||
764 	    netisr && (statusReg & MACH_SOFT_INT_MASK_1)) {
765 		clearsoftnet();
766 		cnt.v_soft++;
767 		intrcnt[1]++;
768 #ifdef INET
769 		if (netisr & (1 << NETISR_ARP)) {
770 			netisr &= ~(1 << NETISR_ARP);
771 			arpintr();
772 		}
773 		if (netisr & (1 << NETISR_IP)) {
774 			netisr &= ~(1 << NETISR_IP);
775 			ipintr();
776 		}
777 #endif
778 #ifdef NS
779 		if (netisr & (1 << NETISR_NS)) {
780 			netisr &= ~(1 << NETISR_NS);
781 			nsintr();
782 		}
783 #endif
784 #ifdef ISO
785 		if (netisr & (1 << NETISR_ISO)) {
786 			netisr &= ~(1 << NETISR_ISO);
787 			clnlintr();
788 		}
789 #endif
790 	}
791 #ifdef DEBUG
792 	intr_level--;
793 #endif
794 }
795 
796 /*
797  * Handle pmax (DECstation 2100/3100) interrupts.
798  */
799 pmax_intr(mask, pc, statusReg, causeReg)
800 	unsigned mask;
801 	unsigned pc;
802 	unsigned statusReg;
803 	unsigned causeReg;
804 {
805 	register volatile struct chiptime *c = Mach_clock_addr;
806 	struct clockframe cf;
807 	int temp;
808 
809 	/* handle clock interrupts ASAP */
810 	if (mask & MACH_INT_MASK_3) {
811 		intrcnt[6]++;
812 		temp = c->regc;	/* XXX clear interrupt bits */
813 		cf.pc = pc;
814 		cf.sr = statusReg;
815 		hardclock(&cf);
816 		/* keep clock interrupts enabled */
817 		causeReg &= ~MACH_INT_MASK_3;
818 	}
819 	/* Re-enable clock interrupts */
820 	splx(MACH_INT_MASK_3 | MACH_SR_INT_ENA_CUR);
821 #if NSII > 0
822 	if (mask & MACH_INT_MASK_0) {
823 		intrcnt[2]++;
824 		siiintr(0);
825 	}
826 #endif
827 #if NLE > 0
828 	if (mask & MACH_INT_MASK_1) {
829 		intrcnt[3]++;
830 		leintr(0);
831 	}
832 #endif
833 #if NDC > 0
834 	if (mask & MACH_INT_MASK_2) {
835 		intrcnt[4]++;
836 		dcintr(0);
837 	}
838 #endif
839 	if (mask & MACH_INT_MASK_4) {
840 		intrcnt[5]++;
841 		pmax_errintr();
842 	}
843 	return ((statusReg & ~causeReg & MACH_HARD_INT_MASK) |
844 		MACH_SR_INT_ENA_CUR);
845 }
846 
847 /*
848  * Handle hardware interrupts for the KN02. (DECstation 5000/200)
849  * Returns spl value.
850  */
851 kn02_intr(mask, pc, statusReg, causeReg)
852 	unsigned mask;
853 	unsigned pc;
854 	unsigned statusReg;
855 	unsigned causeReg;
856 {
857 	register unsigned i, m;
858 	register volatile struct chiptime *c = Mach_clock_addr;
859 	register unsigned csr;
860 	int temp;
861 	struct clockframe cf;
862 	static int warned = 0;
863 
864 	/* handle clock interrupts ASAP */
865 	if (mask & MACH_INT_MASK_1) {
866 		csr = *(unsigned *)MACH_PHYS_TO_UNCACHED(KN02_SYS_CSR);
867 		if ((csr & KN02_CSR_PSWARN) && !warned) {
868 			warned = 1;
869 			printf("WARNING: power supply is overheating!\n");
870 		} else if (warned && !(csr & KN02_CSR_PSWARN)) {
871 			warned = 0;
872 			printf("WARNING: power supply is OK again\n");
873 		}
874 		intrcnt[6]++;
875 
876 		temp = c->regc;	/* XXX clear interrupt bits */
877 		cf.pc = pc;
878 		cf.sr = statusReg;
879 		hardclock(&cf);
880 
881 		/* keep clock interrupts enabled */
882 		causeReg &= ~MACH_INT_MASK_1;
883 	}
884 	/* Re-enable clock interrupts */
885 	splx(MACH_INT_MASK_1 | MACH_SR_INT_ENA_CUR);
886 	if (mask & MACH_INT_MASK_0) {
887 		static int map[8] = { 8, 8, 8, 8, 8, 4, 3, 2 };
888 
889 		csr = *(unsigned *)MACH_PHYS_TO_UNCACHED(KN02_SYS_CSR);
890 		m = csr & (csr >> KN02_CSR_IOINTEN_SHIFT) & KN02_CSR_IOINT;
891 #if 0
892 		*(unsigned *)MACHPHYS_TO_UNCACHED(KN02_SYS_CSR) =
893 			(csr & ~(KN02_CSR_WRESERVED | 0xFF)) |
894 			(m << KN02_CSR_IOINTEN_SHIFT);
895 #endif
896 		for (i = 0; m; i++, m >>= 1) {
897 			if (!(m & 1))
898 				continue;
899 			intrcnt[map[i]]++;
900 			if (tc_slot_info[i].intr)
901 				(*tc_slot_info[i].intr)(tc_slot_info[i].unit);
902 			else
903 				printf("spurious interrupt %d\n", i);
904 		}
905 #if 0
906 		*(unsigned *)MACH_PHYS_TO_UNCACHED(KN02_SYS_CSR) =
907 			csr & ~(KN02_CSR_WRESERVED | 0xFF);
908 #endif
909 	}
910 	if (mask & MACH_INT_MASK_3) {
911 		intrcnt[5]++;
912 		kn02_errintr();
913 	}
914 	return ((statusReg & ~causeReg & MACH_HARD_INT_MASK) |
915 		MACH_SR_INT_ENA_CUR);
916 }
917 
918 /*
919  * 3min hardware interrupts. (DECstation 5000/1xx)
920  */
921 kmin_intr(mask, pc, statusReg, causeReg)
922 	unsigned mask;
923 	unsigned pc;
924 	unsigned statusReg;
925 	unsigned causeReg;
926 {
927 	register u_int intr;
928 	register volatile struct chiptime *c = Mach_clock_addr;
929 	volatile u_int *imaskp =
930 		(volatile u_int *)MACH_PHYS_TO_UNCACHED(KMIN_REG_IMSK);
931 	volatile u_int *intrp =
932 		(volatile u_int *)MACH_PHYS_TO_UNCACHED(KMIN_REG_INTR);
933 	unsigned int old_mask;
934 	struct clockframe cf;
935 	int temp;
936 	static int user_warned = 0;
937 
938 	old_mask = *imaskp & kmin_tc3_imask;
939 	*imaskp = old_mask;
940 
941 	if (mask & MACH_INT_MASK_4)
942 		(*callv->halt)((int *)0, 0);
943 	if (mask & MACH_INT_MASK_3) {
944 		intr = *intrp;
945 		/* masked interrupts are still observable */
946 		intr &= old_mask;
947 
948 		if (intr & KMIN_INTR_SCSI_PTR_LOAD) {
949 			*intrp &= ~KMIN_INTR_SCSI_PTR_LOAD;
950 #ifdef notdef
951 			asc_dma_intr();
952 #endif
953 		}
954 
955 		if (intr & (KMIN_INTR_SCSI_OVRUN | KMIN_INTR_SCSI_READ_E))
956 			*intrp &= ~(KMIN_INTR_SCSI_OVRUN | KMIN_INTR_SCSI_READ_E);
957 
958 		if (intr & KMIN_INTR_LANCE_READ_E)
959 			*intrp &= ~KMIN_INTR_LANCE_READ_E;
960 
961 		if (intr & KMIN_INTR_TIMEOUT)
962 			kn02ba_errintr();
963 
964 		if (intr & KMIN_INTR_CLOCK) {
965 			temp = c->regc;	/* XXX clear interrupt bits */
966 			cf.pc = pc;
967 			cf.sr = statusReg;
968 			hardclock(&cf);
969 		}
970 
971 		if ((intr & KMIN_INTR_SCC_0) &&
972 			tc_slot_info[KMIN_SCC0_SLOT].intr)
973 			(*(tc_slot_info[KMIN_SCC0_SLOT].intr))
974 			(tc_slot_info[KMIN_SCC0_SLOT].unit);
975 
976 		if ((intr & KMIN_INTR_SCC_1) &&
977 			tc_slot_info[KMIN_SCC1_SLOT].intr)
978 			(*(tc_slot_info[KMIN_SCC1_SLOT].intr))
979 			(tc_slot_info[KMIN_SCC1_SLOT].unit);
980 
981 		if ((intr & KMIN_INTR_SCSI) &&
982 			tc_slot_info[KMIN_SCSI_SLOT].intr)
983 			(*(tc_slot_info[KMIN_SCSI_SLOT].intr))
984 			(tc_slot_info[KMIN_SCSI_SLOT].unit);
985 
986 		if ((intr & KMIN_INTR_LANCE) &&
987 			tc_slot_info[KMIN_LANCE_SLOT].intr)
988 			(*(tc_slot_info[KMIN_LANCE_SLOT].intr))
989 			(tc_slot_info[KMIN_LANCE_SLOT].unit);
990 
991 		if (user_warned && ((intr & KMIN_INTR_PSWARN) == 0)) {
992 			printf("%s\n", "Power supply ok now.");
993 			user_warned = 0;
994 		}
995 		if ((intr & KMIN_INTR_PSWARN) && (user_warned < 3)) {
996 			user_warned++;
997 			printf("%s\n", "Power supply overheating");
998 		}
999 	}
1000 	if ((mask & MACH_INT_MASK_0) && tc_slot_info[0].intr)
1001 		(*tc_slot_info[0].intr)(tc_slot_info[0].unit);
1002 	if ((mask & MACH_INT_MASK_1) && tc_slot_info[1].intr)
1003 		(*tc_slot_info[1].intr)(tc_slot_info[1].unit);
1004 	if ((mask & MACH_INT_MASK_2) && tc_slot_info[2].intr)
1005 		(*tc_slot_info[2].intr)(tc_slot_info[2].unit);
1006 	return ((statusReg & ~causeReg & MACH_HARD_INT_MASK) |
1007 		MACH_SR_INT_ENA_CUR);
1008 }
1009 
1010 /*
1011  * Maxine hardware interrupts. (Personal DECstation 5000/xx)
1012  */
1013 xine_intr(mask, pc, statusReg, causeReg)
1014 	unsigned mask;
1015 	unsigned pc;
1016 	unsigned statusReg;
1017 	unsigned causeReg;
1018 {
1019 	register u_int intr;
1020 	register volatile struct chiptime *c = Mach_clock_addr;
1021 	volatile u_int *imaskp = (volatile u_int *)
1022 		MACH_PHYS_TO_UNCACHED(XINE_REG_IMSK);
1023 	volatile u_int *intrp = (volatile u_int *)
1024 		MACH_PHYS_TO_UNCACHED(XINE_REG_INTR);
1025 	u_int old_mask;
1026 	struct clockframe cf;
1027 	int temp;
1028 
1029 	old_mask = *imaskp & xine_tc3_imask;
1030 	*imaskp = old_mask;
1031 
1032 	if (mask & MACH_INT_MASK_4)
1033 		(*callv->halt)((int *)0, 0);
1034 
1035 	/* handle clock interrupts ASAP */
1036 	if (mask & MACH_INT_MASK_1) {
1037 		temp = c->regc;	/* XXX clear interrupt bits */
1038 		cf.pc = pc;
1039 		cf.sr = statusReg;
1040 		hardclock(&cf);
1041 		causeReg &= ~MACH_INT_MASK_1;
1042 		/* reenable clock interrupts */
1043 		splx(MACH_INT_MASK_1 | MACH_SR_INT_ENA_CUR);
1044 	}
1045 	if (mask & MACH_INT_MASK_3) {
1046 		intr = *intrp;
1047 		/* masked interrupts are still observable */
1048 		intr &= old_mask;
1049 
1050 		if (intr & XINE_INTR_SCSI_PTR_LOAD) {
1051 			*intrp &= ~XINE_INTR_SCSI_PTR_LOAD;
1052 #ifdef notdef
1053 			asc_dma_intr();
1054 #endif
1055 		}
1056 
1057 		if (intr & (XINE_INTR_SCSI_OVRUN | XINE_INTR_SCSI_READ_E))
1058 			*intrp &= ~(XINE_INTR_SCSI_OVRUN | XINE_INTR_SCSI_READ_E);
1059 
1060 		if (intr & XINE_INTR_LANCE_READ_E)
1061 			*intrp &= ~XINE_INTR_LANCE_READ_E;
1062 
1063 		if ((intr & XINE_INTR_SCC_0) &&
1064 			tc_slot_info[XINE_SCC0_SLOT].intr)
1065 			(*(tc_slot_info[XINE_SCC0_SLOT].intr))
1066 			(tc_slot_info[XINE_SCC0_SLOT].unit);
1067 
1068 		if ((intr & XINE_INTR_DTOP_RX) &&
1069 			tc_slot_info[XINE_DTOP_SLOT].intr)
1070 			(*(tc_slot_info[XINE_DTOP_SLOT].intr))
1071 			(tc_slot_info[XINE_DTOP_SLOT].unit);
1072 
1073 		if ((intr & XINE_INTR_FLOPPY) &&
1074 			tc_slot_info[XINE_FLOPPY_SLOT].intr)
1075 			(*(tc_slot_info[XINE_FLOPPY_SLOT].intr))
1076 			(tc_slot_info[XINE_FLOPPY_SLOT].unit);
1077 
1078 		if ((intr & XINE_INTR_TC_0) &&
1079 			tc_slot_info[0].intr)
1080 			(*(tc_slot_info[0].intr))
1081 			(tc_slot_info[0].unit);
1082 
1083 		if ((intr & XINE_INTR_TC_1) &&
1084 			tc_slot_info[1].intr)
1085 			(*(tc_slot_info[1].intr))
1086 			(tc_slot_info[1].unit);
1087 
1088 		if ((intr & XINE_INTR_ISDN) &&
1089 			tc_slot_info[XINE_ISDN_SLOT].intr)
1090 			(*(tc_slot_info[XINE_ISDN_SLOT].intr))
1091 			(tc_slot_info[XINE_ISDN_SLOT].unit);
1092 
1093 		if ((intr & XINE_INTR_SCSI) &&
1094 			tc_slot_info[XINE_SCSI_SLOT].intr)
1095 			(*(tc_slot_info[XINE_SCSI_SLOT].intr))
1096 			(tc_slot_info[XINE_SCSI_SLOT].unit);
1097 
1098 		if ((intr & XINE_INTR_LANCE) &&
1099 			tc_slot_info[XINE_LANCE_SLOT].intr)
1100 			(*(tc_slot_info[XINE_LANCE_SLOT].intr))
1101 			(tc_slot_info[XINE_LANCE_SLOT].unit);
1102 
1103 	}
1104 	if (mask & MACH_INT_MASK_2)
1105 		kn02ba_errintr();
1106 	return ((statusReg & ~causeReg & MACH_HARD_INT_MASK) |
1107 		MACH_SR_INT_ENA_CUR);
1108 }
1109 
1110 #ifdef DS5000_240
1111 /*
1112  * 3Max+ hardware interrupts. (DECstation 5000/240) UNTESTED!!
1113  */
1114 kn03_intr(mask, pc, statusReg, causeReg)
1115 	unsigned mask;
1116 	unsigned pc;
1117 	unsigned statusReg;
1118 	unsigned causeReg;
1119 {
1120 	register u_int intr;
1121 	register volatile struct chiptime *c = Mach_clock_addr;
1122 	volatile u_int *imaskp = (volatile u_int *)
1123 		MACH_PHYS_TO_UNCACHED(KN03_REG_IMSK);
1124 	volatile u_int *intrp = (volatile u_int *)
1125 		MACH_PHYS_TO_UNCACHED(KN03_REG_INTR);
1126 	u_int old_mask;
1127 	struct clockframe cf;
1128 	int temp;
1129 	static int user_warned = 0;
1130 
1131 	old_mask = *imaskp & kn03_tc3_imask;
1132 	*imaskp = old_mask;
1133 
1134 	if (mask & MACH_INT_MASK_4)
1135 		(*callv->halt)((int *)0, 0);
1136 
1137 	/* handle clock interrupts ASAP */
1138 	if (mask & MACH_INT_MASK_1) {
1139 		temp = c->regc;	/* XXX clear interrupt bits */
1140 		cf.pc = pc;
1141 		cf.sr = statusReg;
1142 		hardclock(&cf);
1143 		causeReg &= ~MACH_INT_MASK_1;
1144 		/* reenable clock interrupts */
1145 		splx(MACH_INT_MASK_1 | MACH_SR_INT_ENA_CUR);
1146 	}
1147 	if (mask & MACH_INT_MASK_0) {
1148 		intr = *intrp;
1149 		/* masked interrupts are still observable */
1150 		intr &= old_mask;
1151 
1152 		if (intr & KN03_INTR_SCSI_PTR_LOAD) {
1153 			*intrp &= ~KN03_INTR_SCSI_PTR_LOAD;
1154 #ifdef notdef
1155 			asc_dma_intr();
1156 #endif
1157 		}
1158 
1159 		if (intr & (KN03_INTR_SCSI_OVRUN | KN03_INTR_SCSI_READ_E))
1160 			*intrp &= ~(KN03_INTR_SCSI_OVRUN | KN03_INTR_SCSI_READ_E);
1161 
1162 		if (intr & KN03_INTR_LANCE_READ_E)
1163 			*intrp &= ~KN03_INTR_LANCE_READ_E;
1164 
1165 		if ((intr & KN03_INTR_SCC_0) &&
1166 			tc_slot_info[KN03_SCC0_SLOT].intr)
1167 			(*(tc_slot_info[KN03_SCC0_SLOT].intr))
1168 			(tc_slot_info[KN03_SCC0_SLOT].unit);
1169 
1170 		if ((intr & KN03_INTR_SCC_1) &&
1171 			tc_slot_info[KN03_SCC1_SLOT].intr)
1172 			(*(tc_slot_info[KN03_SCC1_SLOT].intr))
1173 			(tc_slot_info[KN03_SCC1_SLOT].unit);
1174 
1175 		if ((intr & KN03_INTR_TC_0) &&
1176 			tc_slot_info[0].intr)
1177 			(*(tc_slot_info[0].intr))
1178 			(tc_slot_info[0].unit);
1179 
1180 		if ((intr & KN03_INTR_TC_1) &&
1181 			tc_slot_info[1].intr)
1182 			(*(tc_slot_info[1].intr))
1183 			(tc_slot_info[1].unit);
1184 
1185 		if ((intr & KN03_INTR_TC_2) &&
1186 			tc_slot_info[2].intr)
1187 			(*(tc_slot_info[2].intr))
1188 			(tc_slot_info[2].unit);
1189 
1190 		if ((intr & KN03_INTR_SCSI) &&
1191 			tc_slot_info[KN03_SCSI_SLOT].intr)
1192 			(*(tc_slot_info[KN03_SCSI_SLOT].intr))
1193 			(tc_slot_info[KN03_SCSI_SLOT].unit);
1194 
1195 		if ((intr & KN03_INTR_LANCE) &&
1196 			tc_slot_info[KN03_LANCE_SLOT].intr)
1197 			(*(tc_slot_info[KN03_LANCE_SLOT].intr))
1198 			(tc_slot_info[KN03_LANCE_SLOT].unit);
1199 
1200 		if (user_warned && ((intr & KN03_INTR_PSWARN) == 0)) {
1201 			printf("%s\n", "Power supply ok now.");
1202 			user_warned = 0;
1203 		}
1204 		if ((intr & KN03_INTR_PSWARN) && (user_warned < 3)) {
1205 			user_warned++;
1206 			printf("%s\n", "Power supply overheating");
1207 		}
1208 	}
1209 	if (mask & MACH_INT_MASK_3)
1210 		kn03_errintr();
1211 	return ((statusReg & ~causeReg & MACH_HARD_INT_MASK) |
1212 		MACH_SR_INT_ENA_CUR);
1213 }
1214 #endif /* DS5000_240 */
1215 
1216 /*
1217  * This is called from MachUserIntr() if astpending is set.
1218  * This is very similar to the tail of trap().
1219  */
1220 softintr(statusReg, pc)
1221 	unsigned statusReg;	/* status register at time of the exception */
1222 	unsigned pc;		/* program counter where to continue */
1223 {
1224 	register struct proc *p = curproc;
1225 	int sig;
1226 
1227 	cnt.v_soft++;
1228 	/* take pending signals */
1229 	while ((sig = CURSIG(p)) != 0)
1230 		postsig(sig);
1231 	p->p_priority = p->p_usrpri;
1232 	astpending = 0;
1233 	if (p->p_flag & P_OWEUPC) {
1234 		p->p_flag &= ~P_OWEUPC;
1235 		ADDUPROF(p);
1236 	}
1237 	if (want_resched) {
1238 		int s;
1239 
1240 		/*
1241 		 * Since we are curproc, clock will normally just change
1242 		 * our priority without moving us from one queue to another
1243 		 * (since the running process is not on a queue.)
1244 		 * If that happened after we put ourselves on the run queue
1245 		 * but before we switched, we might not be on the queue
1246 		 * indicated by our priority.
1247 		 */
1248 		s = splstatclock();
1249 		setrunqueue(p);
1250 		p->p_stats->p_ru.ru_nivcsw++;
1251 		mi_switch();
1252 		splx(s);
1253 		while ((sig = CURSIG(p)) != 0)
1254 			postsig(sig);
1255 	}
1256 	curpriority = p->p_priority;
1257 }
1258 
1259 #ifdef DEBUG
1260 trapDump(msg)
1261 	char *msg;
1262 {
1263 	register int i;
1264 	int s;
1265 
1266 	s = splhigh();
1267 	printf("trapDump(%s)\n", msg);
1268 	for (i = 0; i < TRAPSIZE; i++) {
1269 		if (trp == trapdebug)
1270 			trp = &trapdebug[TRAPSIZE - 1];
1271 		else
1272 			trp--;
1273 		if (trp->cause == 0)
1274 			break;
1275 		printf("%s: ADR %x PC %x CR %x SR %x\n",
1276 			trap_type[(trp->cause & MACH_CR_EXC_CODE) >>
1277 				MACH_CR_EXC_CODE_SHIFT],
1278 			trp->vadr, trp->pc, trp->cause, trp->status);
1279 		printf("   RA %x code %d\n", trp-> ra, trp->code);
1280 	}
1281 	bzero(trapdebug, sizeof(trapdebug));
1282 	trp = trapdebug;
1283 	splx(s);
1284 }
1285 #endif
1286 
1287 /*
1288  *----------------------------------------------------------------------
1289  *
1290  * MemErrorInterrupts --
1291  *   pmax_errintr - for the DS2100/DS3100
1292  *   kn02_errintr - for the DS5000/200
1293  *   kn02ba_errintr - for the DS5000/1xx and DS5000/xx
1294  *
1295  *	Handler an interrupt for the control register.
1296  *
1297  * Results:
1298  *	None.
1299  *
1300  * Side effects:
1301  *	None.
1302  *
1303  *----------------------------------------------------------------------
1304  */
1305 static void
1306 pmax_errintr()
1307 {
1308 	volatile u_short *sysCSRPtr =
1309 		(u_short *)MACH_PHYS_TO_UNCACHED(KN01_SYS_CSR);
1310 	u_short csr;
1311 
1312 	csr = *sysCSRPtr;
1313 
1314 	if (csr & KN01_CSR_MERR) {
1315 		printf("Memory error at 0x%x\n",
1316 			*(unsigned *)MACH_PHYS_TO_UNCACHED(KN01_SYS_ERRADR));
1317 		panic("Mem error interrupt");
1318 	}
1319 	*sysCSRPtr = (csr & ~KN01_CSR_MBZ) | 0xff;
1320 }
1321 
1322 static void
1323 kn02_errintr()
1324 {
1325 	u_int erradr, chksyn, physadr;
1326 	int i;
1327 
1328 	erradr = *(u_int *)MACH_PHYS_TO_UNCACHED(KN02_SYS_ERRADR);
1329 	chksyn = *(u_int *)MACH_PHYS_TO_UNCACHED(KN02_SYS_CHKSYN);
1330 	*(u_int *)MACH_PHYS_TO_UNCACHED(KN02_SYS_ERRADR) = 0;
1331 	MachEmptyWriteBuffer();
1332 
1333 	if (!(erradr & KN02_ERR_VALID))
1334 		return;
1335 	/* extract the physical word address and compensate for pipelining */
1336 	physadr = erradr & KN02_ERR_ADDRESS;
1337 	if (!(erradr & KN02_ERR_WRITE))
1338 		physadr = (physadr & ~0xfff) | ((physadr & 0xfff) - 5);
1339 	physadr <<= 2;
1340 	printf("%s memory %s %s error at 0x%x\n",
1341 		(erradr & KN02_ERR_CPU) ? "CPU" : "DMA",
1342 		(erradr & KN02_ERR_WRITE) ? "write" : "read",
1343 		(erradr & KN02_ERR_ECCERR) ? "ECC" : "timeout",
1344 		physadr);
1345 	if (erradr & KN02_ERR_ECCERR) {
1346 		*(u_int *)MACH_PHYS_TO_UNCACHED(KN02_SYS_CHKSYN) = 0;
1347 		MachEmptyWriteBuffer();
1348 		printf("ECC 0x%x\n", chksyn);
1349 
1350 		/* check for a corrected, single bit, read error */
1351 		if (!(erradr & KN02_ERR_WRITE)) {
1352 			if (physadr & 0x4) {
1353 				/* check high word */
1354 				if (chksyn & KN02_ECC_SNGHI)
1355 					return;
1356 			} else {
1357 				/* check low word */
1358 				if (chksyn & KN02_ECC_SNGLO)
1359 					return;
1360 			}
1361 		}
1362 	}
1363 	panic("Mem error interrupt");
1364 }
1365 
1366 #ifdef DS5000_240
1367 static void
1368 kn03_errintr()
1369 {
1370 
1371 	printf("erradr %x\n", *(unsigned *)MACH_PHYS_TO_UNCACHED(KN03_SYS_ERRADR));
1372 	*(unsigned *)MACH_PHYS_TO_UNCACHED(KN03_SYS_ERRADR) = 0;
1373 	MachEmptyWriteBuffer();
1374 }
1375 #endif /* DS5000_240 */
1376 
1377 static void
1378 kn02ba_errintr()
1379 {
1380 	register int mer, adr, siz;
1381 	static int errintr_cnt = 0;
1382 
1383 	siz = *(volatile int *)MACH_PHYS_TO_UNCACHED(KMIN_REG_MSR);
1384 	mer = *(volatile int *)MACH_PHYS_TO_UNCACHED(KMIN_REG_MER);
1385 	adr = *(volatile int *)MACH_PHYS_TO_UNCACHED(KMIN_REG_AER);
1386 
1387 	/* clear interrupt bit */
1388 	*(unsigned int *)MACH_PHYS_TO_UNCACHED(KMIN_REG_TIMEOUT) = 0;
1389 
1390 	errintr_cnt++;
1391 	printf("(%d)%s%x [%x %x %x]\n", errintr_cnt,
1392 	       "Bad memory chip at phys ",
1393 	       kn02ba_recover_erradr(adr, mer),
1394 	       mer, siz, adr);
1395 }
1396 
1397 static unsigned
1398 kn02ba_recover_erradr(phys, mer)
1399 	register unsigned phys, mer;
1400 {
1401 	/* phys holds bits 28:2, mer knows which byte */
1402 	switch (mer & KMIN_MER_LASTBYTE) {
1403 	case KMIN_LASTB31:
1404 		mer = 3; break;
1405 	case KMIN_LASTB23:
1406 		mer = 2; break;
1407 	case KMIN_LASTB15:
1408 		mer = 1; break;
1409 	case KMIN_LASTB07:
1410 		mer = 0; break;
1411 	}
1412 	return ((phys & KMIN_AER_ADDR_MASK) | mer);
1413 }
1414 
1415 /*
1416  * Return the resulting PC as if the branch was executed.
1417  */
1418 unsigned
1419 MachEmulateBranch(regsPtr, instPC, fpcCSR, allowNonBranch)
1420 	unsigned *regsPtr;
1421 	unsigned instPC;
1422 	unsigned fpcCSR;
1423 	int allowNonBranch;
1424 {
1425 	InstFmt inst;
1426 	unsigned retAddr;
1427 	int condition;
1428 	extern unsigned GetBranchDest();
1429 
1430 
1431 	inst = *(InstFmt *)instPC;
1432 #if 0
1433 	printf("regsPtr=%x PC=%x Inst=%x fpcCsr=%x\n", regsPtr, instPC,
1434 		inst.word, fpcCSR); /* XXX */
1435 #endif
1436 	switch ((int)inst.JType.op) {
1437 	case OP_SPECIAL:
1438 		switch ((int)inst.RType.func) {
1439 		case OP_JR:
1440 		case OP_JALR:
1441 			retAddr = regsPtr[inst.RType.rs];
1442 			break;
1443 
1444 		default:
1445 			if (!allowNonBranch)
1446 				panic("MachEmulateBranch: Non-branch");
1447 			retAddr = instPC + 4;
1448 			break;
1449 		}
1450 		break;
1451 
1452 	case OP_BCOND:
1453 		switch ((int)inst.IType.rt) {
1454 		case OP_BLTZ:
1455 		case OP_BLTZAL:
1456 			if ((int)(regsPtr[inst.RType.rs]) < 0)
1457 				retAddr = GetBranchDest((InstFmt *)instPC);
1458 			else
1459 				retAddr = instPC + 8;
1460 			break;
1461 
1462 		case OP_BGEZAL:
1463 		case OP_BGEZ:
1464 			if ((int)(regsPtr[inst.RType.rs]) >= 0)
1465 				retAddr = GetBranchDest((InstFmt *)instPC);
1466 			else
1467 				retAddr = instPC + 8;
1468 			break;
1469 
1470 		default:
1471 			panic("MachEmulateBranch: Bad branch cond");
1472 		}
1473 		break;
1474 
1475 	case OP_J:
1476 	case OP_JAL:
1477 		retAddr = (inst.JType.target << 2) |
1478 			((unsigned)instPC & 0xF0000000);
1479 		break;
1480 
1481 	case OP_BEQ:
1482 		if (regsPtr[inst.RType.rs] == regsPtr[inst.RType.rt])
1483 			retAddr = GetBranchDest((InstFmt *)instPC);
1484 		else
1485 			retAddr = instPC + 8;
1486 		break;
1487 
1488 	case OP_BNE:
1489 		if (regsPtr[inst.RType.rs] != regsPtr[inst.RType.rt])
1490 			retAddr = GetBranchDest((InstFmt *)instPC);
1491 		else
1492 			retAddr = instPC + 8;
1493 		break;
1494 
1495 	case OP_BLEZ:
1496 		if ((int)(regsPtr[inst.RType.rs]) <= 0)
1497 			retAddr = GetBranchDest((InstFmt *)instPC);
1498 		else
1499 			retAddr = instPC + 8;
1500 		break;
1501 
1502 	case OP_BGTZ:
1503 		if ((int)(regsPtr[inst.RType.rs]) > 0)
1504 			retAddr = GetBranchDest((InstFmt *)instPC);
1505 		else
1506 			retAddr = instPC + 8;
1507 		break;
1508 
1509 	case OP_COP1:
1510 		switch (inst.RType.rs) {
1511 		case OP_BCx:
1512 		case OP_BCy:
1513 			if ((inst.RType.rt & COPz_BC_TF_MASK) == COPz_BC_TRUE)
1514 				condition = fpcCSR & MACH_FPC_COND_BIT;
1515 			else
1516 				condition = !(fpcCSR & MACH_FPC_COND_BIT);
1517 			if (condition)
1518 				retAddr = GetBranchDest((InstFmt *)instPC);
1519 			else
1520 				retAddr = instPC + 8;
1521 			break;
1522 
1523 		default:
1524 			if (!allowNonBranch)
1525 				panic("MachEmulateBranch: Bad coproc branch instruction");
1526 			retAddr = instPC + 4;
1527 		}
1528 		break;
1529 
1530 	default:
1531 		if (!allowNonBranch)
1532 			panic("MachEmulateBranch: Non-branch instruction");
1533 		retAddr = instPC + 4;
1534 	}
1535 #if 0
1536 	printf("Target addr=%x\n", retAddr); /* XXX */
1537 #endif
1538 	return (retAddr);
1539 }
1540 
1541 unsigned
1542 GetBranchDest(InstPtr)
1543 	InstFmt *InstPtr;
1544 {
1545 	return ((unsigned)InstPtr + 4 + ((short)InstPtr->IType.imm << 2));
1546 }
1547 
1548 /*
1549  * This routine is called by procxmt() to single step one instruction.
1550  * We do this by storing a break instruction after the current instruction,
1551  * resuming execution, and then restoring the old instruction.
1552  */
1553 cpu_singlestep(p)
1554 	register struct proc *p;
1555 {
1556 	register unsigned va;
1557 	register int *locr0 = p->p_md.md_regs;
1558 	int i;
1559 
1560 	/* compute next address after current location */
1561 	va = MachEmulateBranch(locr0, locr0[PC], locr0[FSR], 1);
1562 	if (p->p_md.md_ss_addr || p->p_md.md_ss_addr == va ||
1563 	    !useracc((caddr_t)va, 4, B_READ)) {
1564 		printf("SS %s (%d): breakpoint already set at %x (va %x)\n",
1565 			p->p_comm, p->p_pid, p->p_md.md_ss_addr, va); /* XXX */
1566 		return (EFAULT);
1567 	}
1568 	p->p_md.md_ss_addr = va;
1569 	p->p_md.md_ss_instr = fuiword((caddr_t)va);
1570 	i = suiword((caddr_t)va, MACH_BREAK_SSTEP);
1571 	if (i < 0) {
1572 		vm_offset_t sa, ea;
1573 		int rv;
1574 
1575 		sa = trunc_page((vm_offset_t)va);
1576 		ea = round_page((vm_offset_t)va+sizeof(int)-1);
1577 		rv = vm_map_protect(&p->p_vmspace->vm_map, sa, ea,
1578 			VM_PROT_DEFAULT, FALSE);
1579 		if (rv == KERN_SUCCESS) {
1580 			i = suiword((caddr_t)va, MACH_BREAK_SSTEP);
1581 			(void) vm_map_protect(&p->p_vmspace->vm_map,
1582 				sa, ea, VM_PROT_READ|VM_PROT_EXECUTE, FALSE);
1583 		}
1584 	}
1585 	if (i < 0)
1586 		return (EFAULT);
1587 #if 0
1588 	printf("SS %s (%d): breakpoint set at %x: %x (pc %x) br %x\n",
1589 		p->p_comm, p->p_pid, p->p_md.md_ss_addr,
1590 		p->p_md.md_ss_instr, locr0[PC], fuword((caddr_t)va)); /* XXX */
1591 #endif
1592 	return (0);
1593 }
1594 
1595 #ifdef DEBUG
1596 kdbpeek(addr)
1597 {
1598 	if (addr & 3) {
1599 		printf("kdbpeek: unaligned address %x\n", addr);
1600 		return (-1);
1601 	}
1602 	return (*(int *)addr);
1603 }
1604 
1605 #define MIPS_JR_RA	0x03e00008	/* instruction code for jr ra */
1606 
1607 /*
1608  * Print a stack backtrace.
1609  */
1610 void
1611 stacktrace(a0, a1, a2, a3)
1612 	int a0, a1, a2, a3;
1613 {
1614 	unsigned pc, sp, fp, ra, va, subr;
1615 	unsigned instr, mask;
1616 	InstFmt i;
1617 	int more, stksize;
1618 	int regs[3];
1619 	extern setsoftclock();
1620 	extern char start[], edata[];
1621 
1622 	cpu_getregs(regs);
1623 
1624 	/* get initial values from the exception frame */
1625 	sp = regs[0];
1626 	pc = regs[1];
1627 	ra = 0;
1628 	fp = regs[2];
1629 
1630 loop:
1631 	/* check for current PC in the kernel interrupt handler code */
1632 	if (pc >= (unsigned)MachKernIntr && pc < (unsigned)MachUserIntr) {
1633 		/* NOTE: the offsets depend on the code in locore.s */
1634 		printf("interrupt\n");
1635 		a0 = kdbpeek(sp + 36);
1636 		a1 = kdbpeek(sp + 40);
1637 		a2 = kdbpeek(sp + 44);
1638 		a3 = kdbpeek(sp + 48);
1639 		pc = kdbpeek(sp + 20);
1640 		ra = kdbpeek(sp + 92);
1641 		sp = kdbpeek(sp + 100);
1642 		fp = kdbpeek(sp + 104);
1643 	}
1644 
1645 	/* check for current PC in the exception handler code */
1646 	if (pc >= 0x80000000 && pc < (unsigned)setsoftclock) {
1647 		ra = 0;
1648 		subr = 0;
1649 		goto done;
1650 	}
1651 
1652 	/* check for bad PC */
1653 	if (pc & 3 || pc < 0x80000000 || pc >= (unsigned)edata) {
1654 		printf("PC 0x%x: not in kernel\n", pc);
1655 		ra = 0;
1656 		subr = 0;
1657 		goto done;
1658 	}
1659 
1660 	/*
1661 	 * Find the beginning of the current subroutine by scanning backwards
1662 	 * from the current PC for the end of the previous subroutine.
1663 	 */
1664 	va = pc - sizeof(int);
1665 	while ((instr = kdbpeek(va)) != MIPS_JR_RA)
1666 		va -= sizeof(int);
1667 	va += 2 * sizeof(int);	/* skip back over branch & delay slot */
1668 	/* skip over nulls which might separate .o files */
1669 	while ((instr = kdbpeek(va)) == 0)
1670 		va += sizeof(int);
1671 	subr = va;
1672 
1673 	/* scan forwards to find stack size and any saved registers */
1674 	stksize = 0;
1675 	more = 3;
1676 	mask = 0;
1677 	for (; more; va += sizeof(int), more = (more == 3) ? 3 : more - 1) {
1678 		/* stop if hit our current position */
1679 		if (va >= pc)
1680 			break;
1681 		instr = kdbpeek(va);
1682 		i.word = instr;
1683 		switch (i.JType.op) {
1684 		case OP_SPECIAL:
1685 			switch (i.RType.func) {
1686 			case OP_JR:
1687 			case OP_JALR:
1688 				more = 2; /* stop after next instruction */
1689 				break;
1690 
1691 			case OP_SYSCALL:
1692 			case OP_BREAK:
1693 				more = 1; /* stop now */
1694 			};
1695 			break;
1696 
1697 		case OP_BCOND:
1698 		case OP_J:
1699 		case OP_JAL:
1700 		case OP_BEQ:
1701 		case OP_BNE:
1702 		case OP_BLEZ:
1703 		case OP_BGTZ:
1704 			more = 2; /* stop after next instruction */
1705 			break;
1706 
1707 		case OP_COP0:
1708 		case OP_COP1:
1709 		case OP_COP2:
1710 		case OP_COP3:
1711 			switch (i.RType.rs) {
1712 			case OP_BCx:
1713 			case OP_BCy:
1714 				more = 2; /* stop after next instruction */
1715 			};
1716 			break;
1717 
1718 		case OP_SW:
1719 			/* look for saved registers on the stack */
1720 			if (i.IType.rs != 29)
1721 				break;
1722 			/* only restore the first one */
1723 			if (mask & (1 << i.IType.rt))
1724 				break;
1725 			mask |= 1 << i.IType.rt;
1726 			switch (i.IType.rt) {
1727 			case 4: /* a0 */
1728 				a0 = kdbpeek(sp + (short)i.IType.imm);
1729 				break;
1730 
1731 			case 5: /* a1 */
1732 				a1 = kdbpeek(sp + (short)i.IType.imm);
1733 				break;
1734 
1735 			case 6: /* a2 */
1736 				a2 = kdbpeek(sp + (short)i.IType.imm);
1737 				break;
1738 
1739 			case 7: /* a3 */
1740 				a3 = kdbpeek(sp + (short)i.IType.imm);
1741 				break;
1742 
1743 			case 30: /* fp */
1744 				fp = kdbpeek(sp + (short)i.IType.imm);
1745 				break;
1746 
1747 			case 31: /* ra */
1748 				ra = kdbpeek(sp + (short)i.IType.imm);
1749 			}
1750 			break;
1751 
1752 		case OP_ADDI:
1753 		case OP_ADDIU:
1754 			/* look for stack pointer adjustment */
1755 			if (i.IType.rs != 29 || i.IType.rt != 29)
1756 				break;
1757 			stksize = (short)i.IType.imm;
1758 		}
1759 	}
1760 
1761 done:
1762 	printf("%x+%x (%x,%x,%x,%x) ra %x sz %d\n",
1763 		subr, pc - subr, a0, a1, a2, a3, ra, stksize);
1764 
1765 	if (ra) {
1766 		if (pc == ra && stksize == 0)
1767 			printf("stacktrace: loop!\n");
1768 		else {
1769 			pc = ra;
1770 			sp -= stksize;
1771 			goto loop;
1772 		}
1773 	}
1774 }
1775 #endif /* DEBUG */
1776