xref: /original-bsd/sys/news3400/news3400/trap.c (revision 68d9582f)
1 /*
2  * Copyright (c) 1988 University of Utah.
3  * Copyright (c) 1992 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, Ralph Campbell, Sony Corp. and Kazumasa Utashiro
9  * of Software Research Associates, Inc.
10  *
11  * %sccs.include.redist.c%
12  *
13  * from: Utah $Hdr: trap.c 1.32 91/04/06$
14  *
15  *	@(#)trap.c	7.1 (Berkeley) 06/04/92
16  */
17 
18 #include "../include/fix_machine_type.h"
19 #include "param.h"
20 #include "systm.h"
21 #include "proc.h"
22 #include "kernel.h"
23 #include "signalvar.h"
24 #include "user.h"
25 #include "buf.h"
26 #ifdef KTRACE
27 #include "ktrace.h"
28 #endif
29 #include "net/netisr.h"
30 
31 #include "../include/trap.h"
32 #include "../include/psl.h"
33 #include "../include/reg.h"
34 #include "../include/cpu.h"
35 #include "../include/pte.h"
36 #include "../include/mips_opcode.h"
37 #include "../include/adrsmap.h"
38 #if defined(DS3100) || defined(DS5000)
39 #include "clockreg.h"
40 #endif
41 
42 #include "vm/vm.h"
43 #include "vm/vm_kern.h"
44 #include "vm/vm_page.h"
45 
46 #ifdef news3400
47 #include "lp.h"
48 #include "bm.h"
49 #include "ms.h"
50 #include "en.h"
51 #include "../hbdev/dmac_0448.h"
52 #include "../sio/scc.h"
53 #endif
54 
55 /*
56  * This is a kludge to allow X windows to work.
57  */
58 #define X_KLUGE
59 
60 #ifdef X_KLUGE
61 #define USER_MAP_ADDR	0x4000
62 #define NPTES 300
63 static pt_entry_t UserMapPtes[NPTES];
64 static unsigned nUserMapPtes;
65 static pid_t UserMapPid;
66 #endif
67 
68 struct	proc *machFPCurProcPtr;		/* pointer to last proc to use FP */
69 
70 extern void MachKernGenException();
71 extern void MachUserGenException();
72 extern void MachKernIntr();
73 extern void MachUserIntr();
74 extern void MachTLBModException();
75 extern void MachTLBMissException();
76 extern void MemErrorInterrupt();
77 extern unsigned MachEmulateBranch();
78 
79 void (*machExceptionTable[])() = {
80 /*
81  * The kernel exception handlers.
82  */
83 	MachKernIntr,			/* external interrupt */
84 	MachKernGenException,		/* TLB modification */
85 	MachTLBMissException,		/* TLB miss (load or instr. fetch) */
86 	MachTLBMissException,		/* TLB miss (store) */
87 	MachKernGenException,		/* address error (load or I-fetch) */
88 	MachKernGenException,		/* address error (store) */
89 	MachKernGenException,		/* bus error (I-fetch) */
90 	MachKernGenException,		/* bus error (load or store) */
91 	MachKernGenException,		/* system call */
92 	MachKernGenException,		/* breakpoint */
93 	MachKernGenException,		/* reserved instruction */
94 	MachKernGenException,		/* coprocessor unusable */
95 	MachKernGenException,		/* arithmetic overflow */
96 	MachKernGenException,		/* reserved */
97 	MachKernGenException,		/* reserved */
98 	MachKernGenException,		/* reserved */
99 /*
100  * The user exception handlers.
101  */
102 	MachUserIntr,
103 	MachUserGenException,
104 	MachUserGenException,
105 	MachUserGenException,
106 	MachUserGenException,
107 	MachUserGenException,
108 	MachUserGenException,
109 	MachUserGenException,
110 	MachUserGenException,
111 	MachUserGenException,
112 	MachUserGenException,
113 	MachUserGenException,
114 	MachUserGenException,
115 	MachUserGenException,
116 	MachUserGenException,
117 	MachUserGenException,
118 };
119 
120 char	*trap_type[] = {
121 	"external interrupt",
122 	"TLB modification",
123 	"TLB miss (load or instr. fetch)",
124 	"TLB miss (store)",
125 	"address error (load or I-fetch)",
126 	"address error (store)",
127 	"bus error (I-fetch)",
128 	"bus error (load or store)",
129 	"system call",
130 	"breakpoint",
131 	"reserved instruction",
132 	"coprocessor unusable",
133 	"arithmetic overflow",
134 	"reserved 13",
135 	"reserved 14",
136 	"reserved 15",
137 };
138 
139 #ifdef DEBUG
140 #define TRAPSIZE	10
141 struct trapdebug {		/* trap history buffer for debugging */
142 	u_int	status;
143 	u_int	cause;
144 	u_int	vadr;
145 	u_int	pc;
146 	u_int	ra;
147 	u_int	code;
148 } trapdebug[TRAPSIZE], *trp = trapdebug;
149 #endif
150 
151 /*
152  * Handle an exception.
153  * Called from MachKernGenException() or MachUserGenException()
154  * when a processor trap occurs.
155  * In the case of a kernel trap, we return the pc where to resume if
156  * ((struct pcb *)UADDR)->pcb_onfault is set, otherwise, return old pc.
157  */
158 unsigned
159 trap(statusReg, causeReg, vadr, pc, args)
160 	unsigned statusReg;	/* status register at time of the exception */
161 	unsigned causeReg;	/* cause register at time of exception */
162 	unsigned vadr;		/* address (if any) the fault occured on */
163 	unsigned pc;		/* program counter where to continue */
164 {
165 	register int type, i;
166 	unsigned ucode = 0;
167 	register struct proc *p = curproc;
168 	struct timeval syst;
169 	vm_prot_t ftype;
170 	extern unsigned onfault_table[];
171 
172 #ifdef DEBUG
173 	trp->status = statusReg;
174 	trp->cause = causeReg;
175 	trp->vadr = vadr;
176 	trp->pc = pc;
177 	trp->ra = !USERMODE(statusReg) ? ((int *)&args)[19] :
178 		p->p_md.md_regs[RA];
179 	trp->code = 0;
180 	if (++trp == &trapdebug[TRAPSIZE])
181 		trp = trapdebug;
182 #endif
183 
184 	cnt.v_trap++;
185 	type = (causeReg & MACH_CR_EXC_CODE) >> MACH_CR_EXC_CODE_SHIFT;
186 	if (USERMODE(statusReg)) {
187 		type |= T_USER;
188 		syst = p->p_stime;
189 	}
190 
191 	/*
192 	 * Enable hardware interrupts if they were on before.
193 	 * We only respond to software interrupts when returning to user mode.
194 	 */
195 	if (statusReg & MACH_SR_INT_ENA_PREV)
196 		splx((statusReg & MACH_HARD_INT_MASK) | MACH_SR_INT_ENA_CUR);
197 
198 	switch (type) {
199 	case T_TLB_MOD:
200 		if ((int)vadr < 0) {
201 			register pt_entry_t *pte;
202 			register unsigned entry;
203 #ifndef ATTR
204 			register vm_offset_t pa;
205 #endif
206 
207 			pte = kvtopte(vadr);
208 			entry = pte->pt_entry;
209 			if (entry & PG_RO) {
210 				/* write to read only page in the kernel */
211 				ftype = VM_PROT_WRITE;
212 				goto kernel_fault;
213 			}
214 			entry |= PG_M;
215 			pte->pt_entry = entry;
216 			vadr &= PG_FRAME;
217 			printf("trap: TLBupdate hi %x lo %x i %x\n", vadr,
218 				entry, MachTLBUpdate(vadr, entry)); /* XXX */
219 #ifdef ATTR
220 			pmap_attributes[atop(entry - KERNBASE)] |= PMAP_ATTR_MOD;
221 #else
222 			pa = entry & PG_FRAME;
223 			if (!IS_VM_PHYSADDR(pa))
224 				panic("trap: kmod");
225 			PHYS_TO_VM_PAGE(pa)->clean = FALSE;
226 #endif
227 			return (pc);
228 		}
229 		/* FALLTHROUGH */
230 
231 	case T_TLB_MOD+T_USER:
232 	    {
233 		pmap_hash_t hp;
234 #ifndef ATTR
235 		vm_offset_t pa;
236 #endif
237 #ifdef DIAGNOSTIC
238 		extern pmap_hash_t zero_pmap_hash;
239 		extern pmap_t cur_pmap;
240 
241 		if (cur_pmap->pm_hash == zero_pmap_hash)
242 			panic("tlbmod");
243 #endif
244 		hp = &((pmap_hash_t)PMAP_HASH_UADDR)[PMAP_HASH(vadr)];
245 		if (hp->low & PG_RO) {
246 			ftype = VM_PROT_WRITE;
247 			goto dofault;
248 		}
249 		hp->low |= PG_M;
250 		printf("trap: TLBupdate hi %x lo %x i %x\n", hp->high, hp->low,
251 			MachTLBUpdate(hp->high, hp->low)); /* XXX */
252 #ifdef ATTR
253 		pmap_attributes[atop(hp->low - KERNBASE)] |= PMAP_ATTR_MOD;
254 #else
255 		pa = hp->low & PG_FRAME;
256 		if (!IS_VM_PHYSADDR(pa))
257 			panic("trap: umod");
258 		PHYS_TO_VM_PAGE(pa)->clean = FALSE;
259 #endif
260 		if (!USERMODE(statusReg))
261 			return (pc);
262 		goto out;
263 	    }
264 
265 	case T_TLB_LD_MISS:
266 	case T_TLB_ST_MISS:
267 		ftype = (type == T_TLB_ST_MISS) ? VM_PROT_WRITE : VM_PROT_READ;
268 		if ((int)vadr < 0) {
269 			register vm_offset_t va;
270 			int rv;
271 
272 		kernel_fault:
273 			va = trunc_page((vm_offset_t)vadr);
274 			rv = vm_fault(kernel_map, va, ftype, FALSE);
275 			if (rv == KERN_SUCCESS)
276 				return (pc);
277 			if (i = ((struct pcb *)UADDR)->pcb_onfault) {
278 				((struct pcb *)UADDR)->pcb_onfault = 0;
279 				return (onfault_table[i]);
280 			}
281 			goto err;
282 		}
283 		goto dofault;
284 
285 	case T_TLB_LD_MISS+T_USER:
286 		ftype = VM_PROT_READ;
287 		goto dofault;
288 
289 	case T_TLB_ST_MISS+T_USER:
290 		ftype = VM_PROT_WRITE;
291 	dofault:
292 	    {
293 		register vm_offset_t va;
294 		register struct vmspace *vm = p->p_vmspace;
295 		register vm_map_t map = &vm->vm_map;
296 		int rv;
297 
298 #ifdef X_KLUGE
299 		if (p->p_pid == UserMapPid &&
300 		    (va = pmax_btop(vadr - USER_MAP_ADDR)) < nUserMapPtes) {
301 			register pt_entry_t *pte;
302 
303 			pte = &UserMapPtes[va];
304 			MachTLBWriteRandom((vadr & PG_FRAME) |
305 				(vm->vm_pmap.pm_tlbpid << VMMACH_TLB_PID_SHIFT),
306 				pte->pt_entry);
307 			return (pc);
308 		}
309 #endif
310 		va = trunc_page((vm_offset_t)vadr);
311 		rv = vm_fault(map, va, ftype, FALSE);
312 		if (rv != KERN_SUCCESS) {
313 			printf("vm_fault(%x, %x, %x, 0) -> %x ADR %x PC %x RA %x\n",
314 				map, va, ftype, rv, vadr, pc,
315 				!USERMODE(statusReg) ? ((int *)&args)[19] :
316 					p->p_md.md_regs[RA]); /* XXX */
317 			printf("\tpid %d %s PC %x RA %x\n", p->p_pid,
318 				p->p_comm, p->p_md.md_regs[PC],
319 				p->p_md.md_regs[RA]); /* XXX */
320 #ifdef DEBUG
321 			trapDump("vm_fault");
322 #endif
323 		}
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 		if (vadr == KERNBASE) {
360 			struct args {
361 				int	i[1];
362 			} args;
363 			int rval[2];
364 
365 			/*
366 			 * Assume a signal handler is trying to return
367 			 * (see sendsig() and sigreturn()). We have to
368 			 * pop the sigframe struct to get the address of
369 			 * the sigcontext.
370 			 */
371 			args.i[0] = p->p_md.md_regs[SP] + 4 * sizeof(int);
372 			(void) sigreturn(curproc, &args, rval);
373 			goto out;
374 		}
375 		/* FALLTHROUGH */
376 
377 	case T_ADDR_ERR_ST+T_USER:	/* misaligned or kseg access */
378 	case T_BUS_ERR_IFETCH+T_USER:	/* BERR asserted to cpu */
379 	case T_BUS_ERR_LD_ST+T_USER:	/* BERR asserted to cpu */
380 		i = SIGSEGV;
381 		break;
382 
383 	case T_SYSCALL+T_USER:
384 	    {
385 		register int *locr0 = p->p_md.md_regs;
386 		register struct sysent *callp;
387 		unsigned int code;
388 		int numsys;
389 		struct args {
390 			int i[8];
391 		} args;
392 		int rval[2];
393 		struct sysent *systab;
394 		extern int nsysent;
395 #ifdef ULTRIXCOMPAT
396 		extern struct sysent ultrixsysent[];
397 		extern int ultrixnsysent;
398 #endif
399 
400 		cnt.v_syscall++;
401 		/* compute next PC after syscall instruction */
402 		if ((int)causeReg < 0)
403 			locr0[PC] = MachEmulateBranch(locr0, pc, 0, 0);
404 		else
405 			locr0[PC] += 4;
406 		systab = sysent;
407 		numsys = nsysent;
408 #ifdef ULTRIXCOMPAT
409 		if (p->p_md.md_flags & MDP_ULTRIX) {
410 			systab = ultrixsysent;
411 			numsys = ultrixnsysent;
412 		}
413 #endif
414 		code = locr0[V0];
415 #ifdef COMPAT_NEWSOS
416 #define	SYSCALL_BSDOFFSET	1000
417 		if (code >= SYSCALL_BSDOFFSET)
418 			code -= SYSCALL_BSDOFFSET;
419 #endif
420 		if (code == 0) {			/* indir */
421 			code = locr0[A0];
422 #ifdef COMPAT_NEWSOS
423 			if (code >= SYSCALL_BSDOFFSET)
424 				code -= SYSCALL_BSDOFFSET;
425 #endif
426 			if (code >= numsys)
427 				callp = &systab[0];	/* indir (illegal) */
428 			else
429 				callp = &systab[code];
430 			i = callp->sy_narg;
431 			args.i[0] = locr0[A1];
432 			args.i[1] = locr0[A2];
433 			args.i[2] = locr0[A3];
434 			if (i > 3) {
435 				i = copyin((caddr_t)(locr0[SP] +
436 						3 * sizeof(int)),
437 					(caddr_t)&args.i[3],
438 					(u_int)(i - 3) * sizeof(int));
439 				if (i) {
440 					locr0[V0] = i;
441 					locr0[A3] = 1;
442 #ifdef KTRACE
443 					if (KTRPOINT(p, KTR_SYSCALL))
444 						ktrsyscall(p->p_tracep, code,
445 							callp->sy_narg, args.i);
446 #endif
447 					goto done;
448 				}
449 			}
450 		} else {
451 			if (code >= numsys)
452 				callp = &systab[0];	/* indir (illegal) */
453 			else
454 				callp = &systab[code];
455 			i = callp->sy_narg;
456 			args.i[0] = locr0[A0];
457 			args.i[1] = locr0[A1];
458 			args.i[2] = locr0[A2];
459 			args.i[3] = locr0[A3];
460 			if (i > 4) {
461 				i = copyin((caddr_t)(locr0[SP] +
462 						4 * sizeof(int)),
463 					(caddr_t)&args.i[4],
464 					(u_int)(i - 4) * sizeof(int));
465 				if (i) {
466 					locr0[V0] = i;
467 					locr0[A3] = 1;
468 #ifdef KTRACE
469 					if (KTRPOINT(p, KTR_SYSCALL))
470 						ktrsyscall(p->p_tracep, code,
471 							callp->sy_narg, args.i);
472 #endif
473 					goto done;
474 				}
475 			}
476 		}
477 #ifdef KTRACE
478 		if (KTRPOINT(p, KTR_SYSCALL))
479 			ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i);
480 #endif
481 /*
482 if (!strcmp(p->p_comm, "ftp"))
483 printf("syscall: pid=%d, code=%d, pc=0x%x\n", p->p_pid, code, pc);
484 */
485 		rval[0] = 0;
486 		rval[1] = locr0[V1];
487 #ifdef DEBUG
488 		if (trp == trapdebug)
489 			trapdebug[TRAPSIZE - 1].code = code;
490 		else
491 			trp[-1].code = code;
492 #endif
493 #ifdef COMPAT_NEWSOS
494 	/* 151 = setenvp, 152 = sysnews, 162 = getdomainname KU:XXX */
495 	if (code == 151 || code == 152 || code == 162)
496 		i = 0;
497 	else
498 #endif
499 		i = (*callp->sy_call)(p, &args, rval);
500 if(i==EINVAL)
501 printf("EINVAL: pid=%d, code=%d\n", p->p_pid, code);
502 		/*
503 		 * Reinitialize proc pointer `p' as it may be different
504 		 * if this is a child returning from fork syscall.
505 		 */
506 		p = curproc;
507 		locr0 = p->p_md.md_regs;
508 #ifdef DEBUG
509 		{ int s;
510 		s = splhigh();
511 		trp->status = statusReg;
512 		trp->cause = causeReg;
513 		trp->vadr = locr0[SP];
514 		trp->pc = locr0[PC];
515 		trp->ra = locr0[RA];
516 		trp->code = -code;
517 		if (++trp == &trapdebug[TRAPSIZE])
518 			trp = trapdebug;
519 		splx(s);
520 		}
521 #endif
522 		if (i == ERESTART)
523 			locr0[PC] = pc;
524 		else if (i != EJUSTRETURN) {
525 			if (i) {
526 				locr0[V0] = i;
527 				locr0[A3] = 1;
528 			} else {
529 				locr0[V0] = rval[0];
530 				locr0[V1] = rval[1];
531 				locr0[A3] = 0;
532 			}
533 		}
534 		/* else if (i == EJUSTRETURN) */
535 			/* nothing to do */
536 	done:
537 #ifdef KTRACE
538 		if (KTRPOINT(p, KTR_SYSRET))
539 			ktrsysret(p->p_tracep, code, i, rval[0]);
540 #endif
541 
542 		goto out;
543 	    }
544 
545 	case T_BREAK+T_USER:
546 	    {
547 		register unsigned va, instr;
548 
549 		/* compute address of break instruction */
550 		va = pc;
551 		if ((int)causeReg < 0)
552 			va += 4;
553 
554 		/* read break instruction */
555 		instr = fuiword(va);
556 #ifdef KADB
557 		if (instr == MACH_BREAK_BRKPT || instr == MACH_BREAK_SSTEP)
558 			goto err;
559 #endif
560 		if (p->p_md.md_ss_addr != va || instr != MACH_BREAK_SSTEP) {
561 			i = SIGTRAP;
562 			break;
563 		}
564 
565 		/* restore original instruction and clear BP  */
566 		i = suiword((caddr_t)va, p->p_md.md_ss_instr);
567 		if (i < 0) {
568 			vm_offset_t sa, ea;
569 			int rv;
570 
571 			sa = trunc_page((vm_offset_t)va);
572 			ea = round_page((vm_offset_t)va+sizeof(int)-1);
573 			rv = vm_map_protect(&p->p_vmspace->vm_map, sa, ea,
574 				VM_PROT_DEFAULT, FALSE);
575 			if (rv == KERN_SUCCESS) {
576 				i = suiword((caddr_t)va, p->p_md.md_ss_instr);
577 				(void) vm_map_protect(&p->p_vmspace->vm_map,
578 					sa, ea, VM_PROT_READ|VM_PROT_EXECUTE,
579 					FALSE);
580 			}
581 		}
582 		if (i < 0) {
583 			i = SIGTRAP;
584 			break;
585 		}
586 		p->p_md.md_ss_addr = 0;
587 		goto out;
588 	    }
589 
590 	case T_RES_INST+T_USER:
591 		i = SIGILL;
592 		break;
593 
594 	case T_COP_UNUSABLE+T_USER:
595 		if ((causeReg & MACH_CR_COP_ERR) != 0x10000000) {
596 			i = SIGILL;	/* only FPU instructions allowed */
597 			break;
598 		}
599 		MachSwitchFPState(machFPCurProcPtr, p->p_md.md_regs);
600 		machFPCurProcPtr = p;
601 		p->p_md.md_regs[PS] |= MACH_SR_COP_1_BIT;
602 		p->p_md.md_flags |= MDP_FPUSED;
603 		goto out;
604 
605 	case T_OVFLOW+T_USER:
606 		i = SIGFPE;
607 		break;
608 
609 	case T_ADDR_ERR_LD:	/* misaligned access */
610 	case T_ADDR_ERR_ST:	/* misaligned access */
611 	case T_BUS_ERR_LD_ST:	/* BERR asserted to cpu */
612 		if (i = ((struct pcb *)UADDR)->pcb_onfault) {
613 			((struct pcb *)UADDR)->pcb_onfault = 0;
614 			return (onfault_table[i]);
615 		}
616 		/* FALLTHROUGH */
617 
618 	default:
619 	err:
620 #ifdef KADB
621 	    {
622 		extern struct pcb kdbpcb;
623 
624 		if (USERMODE(statusReg))
625 			kdbpcb = p->p_addr->u_pcb;
626 		else {
627 			kdbpcb.pcb_regs[ZERO] = 0;
628 			kdbpcb.pcb_regs[AST] = ((int *)&args)[2];
629 			kdbpcb.pcb_regs[V0] = ((int *)&args)[3];
630 			kdbpcb.pcb_regs[V1] = ((int *)&args)[4];
631 			kdbpcb.pcb_regs[A0] = ((int *)&args)[5];
632 			kdbpcb.pcb_regs[A1] = ((int *)&args)[6];
633 			kdbpcb.pcb_regs[A2] = ((int *)&args)[7];
634 			kdbpcb.pcb_regs[A3] = ((int *)&args)[8];
635 			kdbpcb.pcb_regs[T0] = ((int *)&args)[9];
636 			kdbpcb.pcb_regs[T1] = ((int *)&args)[10];
637 			kdbpcb.pcb_regs[T2] = ((int *)&args)[11];
638 			kdbpcb.pcb_regs[T3] = ((int *)&args)[12];
639 			kdbpcb.pcb_regs[T4] = ((int *)&args)[13];
640 			kdbpcb.pcb_regs[T5] = ((int *)&args)[14];
641 			kdbpcb.pcb_regs[T6] = ((int *)&args)[15];
642 			kdbpcb.pcb_regs[T7] = ((int *)&args)[16];
643 			kdbpcb.pcb_regs[T8] = ((int *)&args)[17];
644 			kdbpcb.pcb_regs[T9] = ((int *)&args)[18];
645 			kdbpcb.pcb_regs[RA] = ((int *)&args)[19];
646 			kdbpcb.pcb_regs[MULLO] = ((int *)&args)[21];
647 			kdbpcb.pcb_regs[MULHI] = ((int *)&args)[22];
648 			kdbpcb.pcb_regs[PC] = pc;
649 			kdbpcb.pcb_regs[SR] = statusReg;
650 			bzero((caddr_t)&kdbpcb.pcb_regs[F0], 33 * sizeof(int));
651 		}
652 		if (kdb(causeReg, vadr, p, !USERMODE(statusReg)))
653 			return (kdbpcb.pcb_regs[PC]);
654 	    }
655 #endif
656 		printf("trap: pid %d %s sig %d adr %x pc %x ra %x\n", p->p_pid,
657 			p->p_comm, i, vadr, pc, p->p_md.md_regs[RA]); /* XXX */
658 		trapDump("unkown exception");
659 		panic("trap");
660 	}
661 	printf("trap: pid %d %s sig %d adr %x pc %x ra %x\n", p->p_pid,
662 		p->p_comm, i, vadr, pc, p->p_md.md_regs[RA]); /* XXX */
663 	trapsignal(p, i, ucode);
664 out:
665 	/*
666 	 * Note: we should only get here if returning to user mode.
667 	 */
668 	astpending = 0;
669 	while (i = CURSIG(p))
670 		psig(i);
671 	p->p_pri = p->p_usrpri;
672 	if (want_resched) {
673 		int s;
674 
675 		/*
676 		 * Since we are curproc, clock will normally just change
677 		 * our priority without moving us from one queue to another
678 		 * (since the running process is not on a queue.)
679 		 * If that happened after we setrq ourselves but before we
680 		 * swtch()'ed, we might not be on the queue indicated by
681 		 * our priority.
682 		 */
683 		s = splclock();
684 		setrq(p);
685 		p->p_stats->p_ru.ru_nivcsw++;
686 		swtch();
687 		splx(s);
688 		while (i = CURSIG(p))
689 			psig(i);
690 	}
691 	if (p->p_stats->p_prof.pr_scale) {
692 		int ticks;
693 		struct timeval *tv = &p->p_stime;
694 
695 		ticks = ((tv->tv_sec - syst.tv_sec) * 1000 +
696 			(tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000);
697 		if (ticks)
698 			addupc(pc, &p->p_stats->p_prof, ticks);
699 	}
700 	curpri = p->p_pri;
701 	return (pc);
702 }
703 
704 #ifdef DS5000
705 struct	intr_tab intr_tab[8];
706 #endif
707 
708 #if defined(DS3100) || defined(DS5100)
709 int temp; /* XXX ULTRIX compiler bug with -O */
710 #endif
711 
712 /*
713  * Handle an interrupt.
714  * Called from MachKernIntr() or MachUserIntr()
715  * Note: curproc might be NULL.
716  */
717 interrupt(statusReg, causeReg, pc)
718 	unsigned statusReg;	/* status register at time of the exception */
719 	unsigned causeReg;	/* cause register at time of exception */
720 	unsigned pc;		/* program counter where to continue */
721 {
722 	register unsigned mask;
723 	clockframe cf;
724 
725 #ifdef DEBUG
726 	trp->status = statusReg;
727 	trp->cause = causeReg;
728 	trp->vadr = 0;
729 	trp->pc = pc;
730 	trp->ra = 0;
731 	trp->code = 0;
732 	if (++trp == &trapdebug[TRAPSIZE])
733 		trp = trapdebug;
734 #endif
735 
736 	mask = causeReg & statusReg;	/* pending interrupts & enable mask */
737 #ifdef news3400
738 #ifndef NOPRIORITY
739 	if (mask & MACH_INT_MASK_5) {		/* level 5 interrupt */
740 		splx((MACH_SPL_MASK_8 & ~causeReg) | MACH_SR_INT_ENA_CUR);
741 		printf("level 5 interrupt: PC %x CR %x SR %x\n",
742 			pc, causeReg, statusReg);
743 		causeReg &= ~MACH_INT_MASK_5;
744 	}
745 	if (mask & MACH_INT_MASK_4) {		/* level 4 interrupt */
746 		/*
747 		 * asynchronous bus error
748 		 */
749 		splx((MACH_SPL_MASK_7 & ~causeReg) | MACH_SR_INT_ENA_CUR);
750 		printf("level 4 interrupt: PC %x CR %x SR %x\n",
751 			pc, causeReg, statusReg);
752 		*(char *)INTCLR0 = INTCLR0_BERR;
753 		causeReg &= ~MACH_INT_MASK_4;
754 	}
755 	if (mask & MACH_INT_MASK_3) {		/* level 3 interrupt */
756 		/*
757 		 * fp error
758 		 */
759 		splx((MACH_SPL_MASK_6 & ~causeReg) | MACH_SR_INT_ENA_CUR);
760 		if (!USERMODE(statusReg)) {
761 #ifdef DEBUG
762 			trapDump("fpintr");
763 #else
764 			printf("FPU interrupt: PC %x CR %x SR %x\n",
765 				pc, causeReg, statusReg);
766 #endif
767 		} else
768 			MachFPInterrupt(statusReg, causeReg, pc);
769 		causeReg &= ~MACH_INT_MASK_3;
770 	}
771 	if (mask & MACH_INT_MASK_2) {		/* level 2 interrupt */
772 		register int stat;
773 
774 		splx((MACH_SPL_MASK_5 & ~causeReg) | MACH_SR_INT_ENA_CUR);
775 		stat = *(volatile u_char *)INTST0;
776 		if (stat & INTST0_TIMINT) {	/* timer */
777 			static int led_count = 0;
778 
779 			*(volatile u_char *)INTCLR0 = INTCLR0_TIMINT;
780 			cf.pc = pc;
781 			cf.ps = statusReg;
782 			hardclock(cf);
783 			if (++led_count > hz) {
784 				led_count = 0;
785 				*(volatile u_char *)DEBUG_PORT ^= DP_LED1;
786 			}
787 		}
788 #if NBM > 0
789 		if (stat & INTST0_KBDINT)	/* keyboard */
790 			kbm_rint(SCC_KEYBOARD);
791 #endif
792 #if NMS > 0
793 		if (stat & INTST0_MSINT)	/* mouse */
794 			kbm_rint(SCC_MOUSE);
795 #endif
796 		causeReg &= ~MACH_INT_MASK_2;
797 	}
798 	if (mask & MACH_INT_MASK_1) {		/* level 1 interrupt */
799 		splx((MACH_SPL_MASK_4 & ~causeReg) | MACH_SR_INT_ENA_CUR);
800 		level1_intr();
801 		causeReg &= ~MACH_INT_MASK_1;
802 	}
803 	if (mask & MACH_INT_MASK_0) {		/* level 0 interrupt */
804 		splx((MACH_SPL_MASK_3 & ~causeReg) | MACH_SR_INT_ENA_CUR);
805 		level0_intr();
806 		causeReg &= ~MACH_INT_MASK_0;
807 	}
808 	splx((MACH_SPL_MASK_3 & ~causeReg) | MACH_SR_INT_ENA_CUR);
809 #else /* NOPRIORITY */
810 	/* handle clock interrupts ASAP */
811 	if (mask & MACH_INT_MASK_2) {		/* level 2 interrupt */
812 		register int stat;
813 
814 		stat = *(volatile u_char *)INTST0;
815 		if (stat & INTST0_TIMINT) {	/* timer */
816 			static int led_count = 0;
817 
818 			*(volatile u_char *)INTCLR0 = INTCLR0_TIMINT;
819 			cf.pc = pc;
820 			cf.ps = statusReg;
821 			hardclock(cf);
822 			if (++led_count > hz) {
823 				led_count = 0;
824 				*(volatile u_char *)DEBUG_PORT ^= DP_LED1;
825 			}
826 		}
827 #if NBM > 0
828 		if (stat & INTST0_KBDINT)	/* keyboard */
829 			kbm_rint(SCC_KEYBOARD);
830 #endif
831 #if NMS > 0
832 		if (stat & INTST0_MSINT)	/* mouse */
833 			kbm_rint(SCC_MOUSE);
834 #endif
835 		causeReg &= ~MACH_INT_MASK_2;	/* reenable clock interrupts */
836 	}
837 	/*
838 	 * Enable hardware interrupts which were enabled but not pending.
839 	 * We only respond to software interrupts when returning to spl0.
840 	 */
841 	splx((statusReg & ~causeReg & MACH_HARD_INT_MASK)|MACH_SR_INT_ENA_CUR);
842 
843 	if (mask & MACH_INT_MASK_5) {		/* level 5 interrupt */
844 		printf("level 5 interrupt: PC %x CR %x SR %x\n",
845 			pc, causeReg, statusReg);
846 		;
847 	}
848 	if (mask & MACH_INT_MASK_4) {		/* level 4 interrupt */
849 		/*
850 		 * asynchronous bus error
851 		 */
852 		printf("level 4 interrupt: PC %x CR %x SR %x\n",
853 			pc, causeReg, statusReg);
854 		*(char *)INTCLR0 = INTCLR0_BERR;
855 	}
856 	if (mask & MACH_INT_MASK_3) {		/* level 3 interrupt */
857 		/*
858 		 * fp error
859 		 */
860 		if (!USERMODE(statusReg)) {
861 #ifdef DEBUG
862 			trapDump("fpintr");
863 #else
864 			printf("FPU interrupt: PC %x CR %x SR %x\n",
865 				pc, causeReg, statusReg);
866 #endif
867 		} else
868 			MachFPInterrupt(statusReg, causeReg, pc);
869 	}
870 	if (mask & MACH_INT_MASK_1)		/* level 1 interrupt */
871 		level1_intr();
872 	if (mask & MACH_INT_MASK_0)		/* level 0 interrupt */
873 		level0_intr();
874 #endif /* NOPRIORITY */
875 #endif /* news3400 */
876 #ifdef DS3100
877 	/* handle clock interrupts ASAP */
878 	if (mask & MACH_INT_MASK_3) {
879 		register volatile struct chiptime *c =
880 			(volatile struct chiptime *)MACH_CLOCK_ADDR;
881 
882 		temp = c->regc;	/* clear interrupt bits */
883 		cf.pc = pc;
884 		cf.ps = statusReg;
885 		hardclock(cf);
886 		causeReg &= ~MACH_INT_MASK_3;	/* reenable clock interrupts */
887 	}
888 	/*
889 	 * Enable hardware interrupts which were enabled but not pending.
890 	 * We only respond to software interrupts when returning to spl0.
891 	 */
892 	splx((statusReg & ~causeReg & MACH_HARD_INT_MASK) |
893 		MACH_SR_INT_ENA_CUR);
894 	if (mask & MACH_INT_MASK_0)
895 		siiintr(0);
896 	if (mask & MACH_INT_MASK_1)
897 		leintr(0);
898 	if (mask & MACH_INT_MASK_2)
899 		dcintr(0);
900 	if (mask & MACH_INT_MASK_4)
901 		MemErrorInterrupt();
902 #endif /* DS3100 */
903 #ifdef DS5000
904 	/* handle clock interrupts ASAP */
905 	if (mask & MACH_INT_MASK_1) {
906 		register volatile struct chiptime *c =
907 			(volatile struct chiptime *)MACH_CLOCK_ADDR;
908 		register unsigned csr;
909 		static int warned = 0;
910 
911 		csr = *(unsigned *)MACH_SYS_CSR_ADDR;
912 		if ((csr & MACH_CSR_PSWARN) && !warned) {
913 			warned = 1;
914 			printf("WARNING: power supply is overheating!\n");
915 		} else if (warned && !(csr & MACH_CSR_PSWARN)) {
916 			warned = 0;
917 			printf("WARNING: power supply is OK again\n");
918 		}
919 
920 		temp = c->regc;	/* clear interrupt bits */
921 		cf.pc = pc;
922 		cf.ps = statusReg;
923 		hardclock(cf);
924 		causeReg &= ~MACH_INT_MASK_1;	/* reenable clock interrupts */
925 	}
926 	if (mask & MACH_INT_MASK_0) {
927 		register unsigned csr;
928 		register unsigned i, m;
929 
930 		csr = *(unsigned *)MACH_SYS_CSR_ADDR;
931 		m = csr & (csr >> MACH_CSR_IOINTEN_SHIFT) & MACH_CSR_IOINT_MASK;
932 #if 0
933 		*(unsigned *)MACH_SYS_CSR_ADDR =
934 			(csr & ~(MACH_CSR_MBZ | 0xFF)) |
935 			(m << MACH_CSR_IOINTEN_SHIFT);
936 #endif
937 		/*
938 		 * Enable hardware interrupts which were enabled but not
939 		 * pending. We only respond to software interrupts when
940 		 * returning to spl0.
941 		 */
942 		splx((statusReg & ~causeReg & MACH_HARD_INT_MASK) |
943 			MACH_SR_INT_ENA_CUR);
944 		for (i = 0; m; i++, m >>= 1) {
945 			if (!(m & 1))
946 				continue;
947 			if (intr_tab[i].func)
948 				(*intr_tab[i].func)(intr_tab[i].unit);
949 			else
950 				printf("spurious interrupt %d\n", i);
951 		}
952 #if 0
953 		*(unsigned *)MACH_SYS_CSR_ADDR =
954 			csr & ~(MACH_CSR_MBZ | 0xFF);
955 #endif
956 	} else {
957 		/*
958 		 * Enable hardware interrupts which were enabled but not
959 		 * pending. We only respond to software interrupts when
960 		 * returning to spl0.
961 		 */
962 		splx((statusReg & ~causeReg & MACH_HARD_INT_MASK) |
963 			MACH_SR_INT_ENA_CUR);
964 	}
965 	if (mask & MACH_INT_MASK_3)
966 		MemErrorInterrupt();
967 #endif /* DS5000 */
968 #if defined(DS3100) || defined(DS5000)
969 	if (mask & MACH_INT_MASK_5) {
970 		if (!USERMODE(statusReg)) {
971 #ifdef DEBUG
972 			trapDump("fpintr");
973 #else
974 			printf("FPU interrupt: PC %x CR %x SR %x\n",
975 				pc, causeReg, statusReg);
976 #endif
977 		} else
978 			MachFPInterrupt(statusReg, causeReg, pc);
979 	}
980 #endif /* DS3100 || DS5000 */
981 	if (mask & MACH_SOFT_INT_MASK_0) {
982 		clockframe cf;
983 
984 		clearsoftclock();
985 		cf.pc = pc;
986 		cf.ps = statusReg;
987 		softclock(cf);
988 	}
989 	/* process network interrupt if we trapped or will very soon */
990 	if ((mask & MACH_SOFT_INT_MASK_1) ||
991 	    netisr && (statusReg & MACH_SOFT_INT_MASK_1)) {
992 		clearsoftnet();
993 #ifdef INET
994 		if (netisr & (1 << NETISR_ARP)) {
995 			netisr &= ~(1 << NETISR_ARP);
996 			arpintr();
997 		}
998 		if (netisr & (1 << NETISR_IP)) {
999 			netisr &= ~(1 << NETISR_IP);
1000 			ipintr();
1001 		}
1002 #endif
1003 #ifdef NS
1004 		if (netisr & (1 << NETISR_NS)) {
1005 			netisr &= ~(1 << NETISR_NS);
1006 			nsintr();
1007 		}
1008 #endif
1009 #ifdef ISO
1010 		if (netisr & (1 << NETISR_ISO)) {
1011 			netisr &= ~(1 << NETISR_ISO);
1012 			clnlintr();
1013 		}
1014 #endif
1015 	}
1016 }
1017 
1018 /*
1019  * This is called from MachUserIntr() if astpending is set.
1020  * This is very similar to the tail of trap().
1021  */
1022 softintr(statusReg, pc)
1023 	unsigned statusReg;	/* status register at time of the exception */
1024 	unsigned pc;		/* program counter where to continue */
1025 {
1026 	register struct proc *p = curproc;
1027 	register int i;
1028 
1029 	cnt.v_soft++;
1030 	astpending = 0;
1031 	while (i = CURSIG(p))
1032 		psig(i);
1033 	p->p_pri = p->p_usrpri;
1034 	if (want_resched) {
1035 		int s;
1036 
1037 		/*
1038 		 * Since we are curproc, clock will normally just change
1039 		 * our priority without moving us from one queue to another
1040 		 * (since the running process is not on a queue.)
1041 		 * If that happened after we setrq ourselves but before we
1042 		 * swtch()'ed, we might not be on the queue indicated by
1043 		 * our priority.
1044 		 */
1045 		s = splclock();
1046 		setrq(p);
1047 		p->p_stats->p_ru.ru_nivcsw++;
1048 		swtch();
1049 		splx(s);
1050 		while (i = CURSIG(p))
1051 			psig(i);
1052 	}
1053 	curpri = p->p_pri;
1054 }
1055 
1056 #ifdef DEBUG
1057 trapDump(msg)
1058 	char *msg;
1059 {
1060 	register int i;
1061 	int s;
1062 
1063 	s = splhigh();
1064 	printf("trapDump(%s)\n", msg);
1065 	for (i = 0; i < TRAPSIZE; i++) {
1066 		if (trp == trapdebug)
1067 			trp = &trapdebug[TRAPSIZE - 1];
1068 		else
1069 			trp--;
1070 		if (trp->cause == 0)
1071 			break;
1072 		printf("%s: ADR %x PC %x CR %x SR %x\n",
1073 			trap_type[(trp->cause & MACH_CR_EXC_CODE) >>
1074 				MACH_CR_EXC_CODE_SHIFT],
1075 			trp->vadr, trp->pc, trp->cause, trp->status);
1076 		printf("   RA %x code %d\n", trp-> ra, trp->code);
1077 	}
1078 	bzero(trapdebug, sizeof(trapdebug));
1079 	trp = trapdebug;
1080 	splx(s);
1081 }
1082 #endif
1083 
1084 #ifdef X_KLUGE
1085 /*
1086  * This is a kludge to allow X windows to work.
1087  */
1088 caddr_t
1089 vmUserMap(size, pa)
1090 	int size;
1091 	unsigned pa;
1092 {
1093 	register caddr_t v;
1094 	unsigned off, entry;
1095 
1096 	if (nUserMapPtes == 0)
1097 		UserMapPid = curproc->p_pid;
1098 	else if (UserMapPid != curproc->p_pid)
1099 		return ((caddr_t)0);
1100 	off = pa & PGOFSET;
1101 	size = btoc(off + size);
1102 	if (nUserMapPtes + size > NPTES)
1103 		return ((caddr_t)0);
1104 	v = (caddr_t)(USER_MAP_ADDR + pmax_ptob(nUserMapPtes) + off);
1105 	entry = (pa & 0x9ffff000) | PG_V | PG_M;
1106 	if (pa >= MACH_UNCACHED_MEMORY_ADDR)
1107 		entry |= PG_N;
1108 	while (size > 0) {
1109 		UserMapPtes[nUserMapPtes].pt_entry = entry;
1110 		entry += NBPG;
1111 		nUserMapPtes++;
1112 		size--;
1113 	}
1114 	return (v);
1115 }
1116 
1117 vmUserUnmap()
1118 {
1119 	int id;
1120 
1121 	nUserMapPtes = 0;
1122 	if (UserMapPid == curproc->p_pid) {
1123 		id = curproc->p_vmspace->vm_pmap.pm_tlbpid;
1124 		if (id >= 0)
1125 			MachTLBFlushPID(id);
1126 	}
1127 	UserMapPid = 0;
1128 }
1129 #endif
1130 
1131 /*
1132  *----------------------------------------------------------------------
1133  *
1134  * MemErrorInterrupt --
1135  *
1136  *	Handler an interrupt for the control register.
1137  *
1138  * Results:
1139  *	None.
1140  *
1141  * Side effects:
1142  *	None.
1143  *
1144  *----------------------------------------------------------------------
1145  */
1146 static void
1147 MemErrorInterrupt()
1148 {
1149 #ifdef DS3100
1150 	volatile u_short *sysCSRPtr = (u_short *)MACH_SYS_CSR_ADDR;
1151 	u_short csr;
1152 
1153 	csr = *sysCSRPtr;
1154 
1155 	if (csr & MACH_CSR_MEM_ERR) {
1156 		printf("Memory error at 0x%x\n",
1157 			*(unsigned *)MACH_WRITE_ERROR_ADDR);
1158 		panic("Mem error interrupt");
1159 	}
1160 	*sysCSRPtr = (csr & ~MACH_CSR_MBZ) | 0xff;
1161 #endif /* DS3100 */
1162 #ifdef DS5000
1163 	printf("erradr %x\n", *(unsigned *)MACH_ERROR_ADDR);
1164 	*(unsigned *)MACH_ERROR_ADDR = 0;
1165 	MachEmptyWriteBuffer();
1166 #endif /* DS5000 */
1167 }
1168 
1169 /*
1170  * Return the resulting PC as if the branch was executed.
1171  */
1172 unsigned
1173 MachEmulateBranch(regsPtr, instPC, fpcCSR, allowNonBranch)
1174 	unsigned *regsPtr;
1175 	unsigned instPC;
1176 	unsigned fpcCSR;
1177 	int allowNonBranch;
1178 {
1179 	InstFmt inst;
1180 	unsigned retAddr;
1181 	int condition;
1182 	extern unsigned GetBranchDest();
1183 
1184 #if 0
1185 	printf("regsPtr=%x PC=%x Inst=%x fpcCsr=%x\n", regsPtr, instPC,
1186 		*(unsigned *)instPC, fpcCSR);
1187 #endif
1188 
1189 	inst = *(InstFmt *)instPC;
1190 	switch ((int)inst.JType.op) {
1191 	case OP_SPECIAL:
1192 		switch ((int)inst.RType.func) {
1193 		case OP_JR:
1194 		case OP_JALR:
1195 			retAddr = regsPtr[inst.RType.rs];
1196 			break;
1197 
1198 		default:
1199 			if (!allowNonBranch)
1200 				panic("MachEmulateBranch: Non-branch");
1201 			retAddr = instPC + 4;
1202 			break;
1203 		}
1204 		break;
1205 
1206 	case OP_BCOND:
1207 		switch ((int)inst.IType.rt) {
1208 		case OP_BLTZ:
1209 		case OP_BLTZAL:
1210 			if ((int)(regsPtr[inst.RType.rs]) < 0)
1211 				retAddr = GetBranchDest((InstFmt *)instPC);
1212 			else
1213 				retAddr = instPC + 8;
1214 			break;
1215 
1216 		case OP_BGEZAL:
1217 		case OP_BGEZ:
1218 			if ((int)(regsPtr[inst.RType.rs]) >= 0)
1219 				retAddr = GetBranchDest((InstFmt *)instPC);
1220 			else
1221 				retAddr = instPC + 8;
1222 			break;
1223 
1224 		default:
1225 			panic("MachEmulateBranch: Bad branch cond");
1226 		}
1227 		break;
1228 
1229 	case OP_J:
1230 	case OP_JAL:
1231 		retAddr = (inst.JType.target << 2) |
1232 			((unsigned)instPC & 0xF0000000);
1233 		break;
1234 
1235 	case OP_BEQ:
1236 		if (regsPtr[inst.RType.rs] == regsPtr[inst.RType.rt])
1237 			retAddr = GetBranchDest((InstFmt *)instPC);
1238 		else
1239 			retAddr = instPC + 8;
1240 		break;
1241 
1242 	case OP_BNE:
1243 		if (regsPtr[inst.RType.rs] != regsPtr[inst.RType.rt])
1244 			retAddr = GetBranchDest((InstFmt *)instPC);
1245 		else
1246 			retAddr = instPC + 8;
1247 		break;
1248 
1249 	case OP_BLEZ:
1250 		if ((int)(regsPtr[inst.RType.rs]) <= 0)
1251 			retAddr = GetBranchDest((InstFmt *)instPC);
1252 		else
1253 			retAddr = instPC + 8;
1254 		break;
1255 
1256 	case OP_BGTZ:
1257 		if ((int)(regsPtr[inst.RType.rs]) > 0)
1258 			retAddr = GetBranchDest((InstFmt *)instPC);
1259 		else
1260 			retAddr = instPC + 8;
1261 		break;
1262 
1263 	case OP_COP1:
1264 		switch (inst.RType.rs) {
1265 		case OP_BCx:
1266 		case OP_BCy:
1267 			if ((inst.RType.rt & COPz_BC_TF_MASK) == COPz_BC_TRUE)
1268 				condition = fpcCSR & MACH_FPC_COND_BIT;
1269 			else
1270 				condition = !(fpcCSR & MACH_FPC_COND_BIT);
1271 			if (condition)
1272 				retAddr = GetBranchDest((InstFmt *)instPC);
1273 			else
1274 				retAddr = instPC + 8;
1275 			break;
1276 
1277 		default:
1278 			if (!allowNonBranch)
1279 				panic("MachEmulateBranch: Bad coproc branch instruction");
1280 			retAddr = instPC + 4;
1281 		}
1282 		break;
1283 
1284 	default:
1285 		if (!allowNonBranch)
1286 			panic("MachEmulateBranch: Non-branch instruction");
1287 		retAddr = instPC + 4;
1288 	}
1289 #if 0
1290 	printf("Target addr=%x\n", retAddr);
1291 #endif
1292 	return (retAddr);
1293 }
1294 
1295 unsigned
1296 GetBranchDest(InstPtr)
1297 	InstFmt *InstPtr;
1298 {
1299 	return ((unsigned)InstPtr + 4 + ((short)InstPtr->IType.imm << 2));
1300 }
1301 
1302 /*
1303  * This routine is called by procxmt() to single step one instruction.
1304  * We do this by storing a break instruction after the current instruction,
1305  * resuming execution, and then restoring the old instruction.
1306  */
1307 cpu_singlestep(p)
1308 	register struct proc *p;
1309 {
1310 	register unsigned va;
1311 	register int *locr0 = p->p_md.md_regs;
1312 	int i;
1313 
1314 	/* compute next address after current location */
1315 	va = MachEmulateBranch(locr0, locr0[PC], 0, 1);
1316 	if (p->p_md.md_ss_addr || p->p_md.md_ss_addr == va ||
1317 	    !useracc((caddr_t)va, 4, B_READ)) {
1318 		printf("SS %s (%d): breakpoint already set at %x (va %x)\n",
1319 			p->p_comm, p->p_pid, p->p_md.md_ss_addr, va); /* XXX */
1320 		return (EFAULT);
1321 	}
1322 	p->p_md.md_ss_addr = va;
1323 	p->p_md.md_ss_instr = fuiword(va);
1324 	i = suiword((caddr_t)va, MACH_BREAK_SSTEP);
1325 	if (i < 0) {
1326 		vm_offset_t sa, ea;
1327 		int rv;
1328 
1329 		sa = trunc_page((vm_offset_t)va);
1330 		ea = round_page((vm_offset_t)va+sizeof(int)-1);
1331 		rv = vm_map_protect(&p->p_vmspace->vm_map, sa, ea,
1332 			VM_PROT_DEFAULT, FALSE);
1333 		if (rv == KERN_SUCCESS) {
1334 			i = suiword((caddr_t)va, MACH_BREAK_SSTEP);
1335 			(void) vm_map_protect(&p->p_vmspace->vm_map,
1336 				sa, ea, VM_PROT_READ|VM_PROT_EXECUTE, FALSE);
1337 		}
1338 	}
1339 	if (i < 0)
1340 		return (EFAULT);
1341 	printf("SS %s (%d): breakpoint set at %x: %x (pc %x)\n",
1342 		p->p_comm, p->p_pid, p->p_md.md_ss_addr,
1343 		p->p_md.md_ss_instr, locr0[PC]); /* XXX */
1344 	return (0);
1345 }
1346 
1347 #ifdef news3400
1348 /*
1349  * news3400 - INT0 service routine.
1350  *
1351  * INTST0 bit	4:	dma
1352  *		3:	slot #1
1353  *		2:	slot #3
1354  *		1:	external #1
1355  *		0:	external #3
1356  */
1357 
1358 #define	LEVEL0_MASK	\
1359 	(INTST1_DMA|INTST1_SLOT1|INTST1_SLOT3|INTST1_EXT1|INTST1_EXT3)
1360 
1361 level0_intr()
1362 {
1363 	register int stat;
1364 
1365 	stat = *(volatile u_char *)INTST1 & LEVEL0_MASK;
1366 	*(u_char *)INTCLR1 = stat;
1367 
1368 	if (stat & INTST1_DMA)
1369 		dma_intr();
1370 	if (stat & INTST1_SLOT1)
1371 		exec_hb_intr2();
1372 #if NEN > 0
1373 	if (stat & INTST1_SLOT3) {
1374 		int s, t;
1375 
1376 		s = splimp();
1377 		t = lance_intr();
1378 		(void) splx(s);
1379 		if (t == 0)
1380 			exec_hb_intr4();
1381 	}
1382 #endif
1383 #if NLE > 0
1384 	if (stat & INTST1_SLOT3) {
1385 		int s;
1386 
1387 		s = splimp();
1388 		leintr(0);
1389 		(void) splx(s);
1390 	}
1391 #endif
1392 	if (stat & INTST1_EXT1)
1393 		print_int_stat("EXT #1");
1394 	if (stat & INTST1_EXT3)
1395 		print_int_stat("EXT #3");
1396 }
1397 
1398 /*
1399  * news3400 - INT1 service routine.
1400  *
1401  * INTST0 bit	1:	centro fault
1402  *		0:	centro busy
1403  * INTST1 bit	7:	beep
1404  *		6:	scc
1405  *		5:	lance
1406  */
1407 
1408 #define LEVEL1_MASK2	(INTST0_CFLT|INTST0_CBSY)
1409 #define LEVEL1_MASK1	(INTST1_BEEP|INTST1_SCC|INTST1_LANCE)
1410 
1411 level1_intr(pc)
1412 	unsigned pc;
1413 {
1414 	register int stat;
1415 	register u_int saved_inten1 = *(u_char *)INTEN1;
1416 
1417 	*(u_char *)INTEN1 = 0;		/* disable intr: beep, lance, scc */
1418 
1419 	stat = *(volatile u_char *)INTST1 & LEVEL1_MASK1;
1420 	*(u_char *)INTCLR1 = stat;
1421 
1422 	stat &= saved_inten1;
1423 
1424 	if (stat & INTST1_BEEP) {
1425 		*(volatile u_char *)INTCLR1 = INTCLR1_BEEP;
1426 		print_int_stat("BEEP");
1427 	}
1428 	if (stat & INTST1_SCC) {
1429 		scc_intr();
1430 		if (saved_inten1 & *(u_char *)INTST1 & INTST1_SCC)
1431 			scc_intr();
1432 	}
1433 #if NEN > 0
1434 	if (stat & INTST1_LANCE)
1435 		lance_intr();
1436 #endif
1437 #if NLE > 0
1438 	if (stat & INTST1_LANCE)
1439 		leintr(0);
1440 #endif
1441 
1442 	*(u_char *)INTEN1 = saved_inten1;
1443 
1444 #if NLP > 0
1445 	/*
1446 	 * The PARK2 cannot find centro interrupt correctly.
1447 	 * We must check it by reading the cause register of cpu
1448 	 * while other interrupts are disabled.
1449 	 */
1450 	{
1451 		register int causereg;
1452 		int s = splhigh();
1453 
1454 		causereg = get_causereg();
1455 		(void) splx(s);
1456 
1457 		if ((causereg & CAUSE_IP4) == 0)
1458 			return;
1459 	}
1460 #endif
1461 
1462 	stat = (int)(*(u_char *)INTST0) & LEVEL1_MASK2;
1463 	*(u_char *)INTCLR0 = stat;
1464 
1465 	if (stat & INTST0_CBSY)		/* centro busy */
1466 #if NLP > 0
1467 		lpxint(0);
1468 #else
1469 		printf("stray intr: CBSY\n");
1470 #endif
1471 }
1472 
1473 /*
1474  * DMA interrupt service routine.
1475  */
1476 dma_intr()
1477 {
1478         register volatile u_char *gsp = (u_char *)DMAC_GSTAT;
1479         register u_int gstat = *gsp;
1480         register int mrqb, i;
1481 
1482 	/*
1483 	 * when DMA intrrupt occurs there remain some untransferred data.
1484 	 * wait data transfer completion.
1485 	 */
1486 	mrqb = (gstat & (CH0_INT|CH1_INT|CH2_INT|CH3_INT)) << 1;
1487 	if (gstat & mrqb) {
1488 		/*
1489 		 * SHOULD USE DELAY()
1490 		 */
1491 		for (i = 0; i < 50; i++)
1492 			;
1493 		if (*gsp & mrqb)
1494 			printf("dma_intr: MRQ\n");
1495 	}
1496 
1497 	/* SCSI Dispatch */
1498 	if (gstat & CH_INT(CH_SCSI))
1499 		scintr();
1500 
1501 #include "fd.h"
1502 #if NFD > 0
1503         /* FDC Interrupt Dispatch */
1504 	if (gstat & CH_INT(CH_FDC))
1505 		fdc_intr(0);
1506 #endif /* NFD > 0 */
1507 
1508 #include "sb.h"
1509 #if NSB > 0
1510         /* Audio Interface Dispatch */
1511 	sbintr(0);
1512 #endif /* NSB > 0 */
1513 
1514         /* Video I/F Dispatch */
1515 	if (gstat & CH_INT(CH_VIDEO))
1516 		;
1517 }
1518 
1519 /*
1520  * SCC vector interrupt service routine.
1521  */
1522 scc_intr()
1523 {
1524 	int vec;
1525 	extern int scc_xint(), scc_sint(), scc_rint(), scc_cint();
1526 	static int (*func[])() = {
1527 		scc_xint,
1528 		scc_sint,
1529 		scc_rint,
1530 		scc_cint
1531 	};
1532 
1533 	vec = *(volatile u_char *)SCCVECT;
1534 	(*func[(vec & SCC_INT_MASK) >> 1])(vec);
1535 }
1536 
1537 print_int_stat(msg)
1538 	char *msg;
1539 {
1540 	int s0 = *(volatile u_char *)INTST0;
1541 	int s1 = *(volatile u_char *)INTST1;
1542 
1543 	if (msg)
1544 		printf("%s: ", msg);
1545 	else
1546 		printf("intr: ");
1547 	printf("INTST0=0x%x, INTST1=0x%x.\n", s0, s1);
1548 }
1549 #endif /* news3400 */
1550