xref: /openbsd-src/sys/arch/m88k/m88k/trap.c (revision 7780107d8d72aead3b07660e6a22b5d218a28425)
1 /*	$OpenBSD: trap.c,v 1.137 2024/10/23 07:41:44 mpi Exp $	*/
2 /*
3  * Copyright (c) 2004, Miodrag Vallat.
4  * Copyright (c) 1998 Steve Murphree, Jr.
5  * Copyright (c) 1996 Nivas Madhur
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *      This product includes software developed by Nivas Madhur.
19  * 4. The name of the author may not be used to endorse or promote products
20  *    derived from this software without specific prior written permission
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  *
33  */
34 /*
35  * Mach Operating System
36  * Copyright (c) 1991 Carnegie Mellon University
37  * Copyright (c) 1991 OMRON Corporation
38  * All Rights Reserved.
39  *
40  * Permission to use, copy, modify and distribute this software and its
41  * documentation is hereby granted, provided that both the copyright
42  * notice and this permission notice appear in all copies of the
43  * software, derivative works or modified versions, and any portions
44  * thereof, and that both notices appear in supporting documentation.
45  *
46  */
47 
48 #include <sys/param.h>
49 #include <sys/proc.h>
50 #include <sys/signalvar.h>
51 #include <sys/user.h>
52 #include <sys/syscall.h>
53 #include <sys/systm.h>
54 #include <sys/syscall_mi.h>
55 
56 #include <uvm/uvm_extern.h>
57 
58 #include <machine/asm_macro.h>
59 #include <machine/cmmu.h>
60 #include <machine/cpu.h>
61 #ifdef M88100
62 #include <machine/m88100.h>
63 #include <machine/m8820x.h>
64 #endif
65 #ifdef M88110
66 #include <machine/m88110.h>
67 #endif
68 #include <machine/fpu.h>
69 #include <machine/pcb.h>
70 #include <machine/psl.h>
71 #include <machine/trap.h>
72 
73 #include <machine/db_machdep.h>
74 
75 #define SSBREAKPOINT (0xF000D1F8U) /* Single Step Breakpoint */
76 
77 #define USERMODE(PSR)   (((PSR) & PSR_MODE) == 0)
78 #define SYSTEMMODE(PSR) (((PSR) & PSR_MODE) != 0)
79 
80 void printtrap(int, struct trapframe *);
81 __dead void panictrap(int, struct trapframe *);
82 __dead void error_fatal(struct trapframe *);
83 int double_reg_fixup(struct trapframe *, int);
84 int ss_put_value(struct proc *, vaddr_t, u_int);
85 
86 extern void regdump(struct trapframe *f);
87 
88 const char *trap_type[] = {
89 	"Reset",
90 	"Interrupt Exception",
91 	"Instruction Access",
92 	"Data Access Exception",
93 	"Misaligned Access",
94 	"Unimplemented Opcode",
95 	"Privilege Violation",
96 	"Bounds Check Violation",
97 	"Illegal Integer Divide",
98 	"Integer Overflow",
99 	"Error Exception",
100 	"Non-Maskable Exception",
101 };
102 
103 const int trap_types = sizeof trap_type / sizeof trap_type[0];
104 
105 #ifdef M88100
106 const char *pbus_exception_type[] = {
107 	"Success (No Fault)",
108 	"unknown 1",
109 	"unknown 2",
110 	"Bus Error",
111 	"Segment Fault",
112 	"Page Fault",
113 	"Supervisor Violation",
114 	"Write Violation",
115 };
116 #endif
117 
118 void
119 printtrap(int type, struct trapframe *frame)
120 {
121 #ifdef M88100
122 	if (CPU_IS88100) {
123 		if (type == 2) {
124 			/* instruction exception */
125 			printf("\nInstr access fault (%s) v = %lx, frame %p\n",
126 			    pbus_exception_type[
127 			      CMMU_PFSR_FAULT(frame->tf_ipfsr)],
128 			    frame->tf_sxip & XIP_ADDR, frame);
129 		} else if (type == 3) {
130 			/* data access exception */
131 			printf("\nData access fault (%s) v = %lx, frame %p\n",
132 			    pbus_exception_type[
133 			      CMMU_PFSR_FAULT(frame->tf_dpfsr)],
134 			    frame->tf_sxip & XIP_ADDR, frame);
135 		} else
136 			printf("\nTrap type %d, v = %lx, frame %p\n",
137 			    type, frame->tf_sxip & XIP_ADDR, frame);
138 	}
139 #endif
140 #ifdef M88110
141 	if (CPU_IS88110) {
142 		printf("\nTrap type %d, v = %lx, frame %p\n",
143 		    type, frame->tf_exip, frame);
144 	}
145 #endif
146 #ifdef DDB
147 	regdump(frame);
148 #endif
149 }
150 
151 __dead void
152 panictrap(int type, struct trapframe *frame)
153 {
154 	static int panicing = 0;
155 
156 	if (panicing++ == 0)
157 		printtrap(type, frame);
158 	if ((u_int)type < trap_types)
159 		panic("%s", trap_type[type]);
160 	else
161 		panic("trap %d", type);
162 	/*NOTREACHED*/
163 }
164 
165 /*
166  * Handle external interrupts.
167  */
168 void
169 interrupt(struct trapframe *frame)
170 {
171 	struct cpu_info *ci = curcpu();
172 
173 	ci->ci_idepth++;
174 	md_interrupt_func(frame);
175 	ci->ci_idepth--;
176 }
177 
178 #ifdef M88110
179 /*
180  * Handle non-maskable interrupts.
181  */
182 int
183 nmi(struct trapframe *frame)
184 {
185 	return md_nmi_func(frame);
186 }
187 
188 /*
189  * Reenable non-maskable interrupts.
190  */
191 void
192 nmi_wrapup(struct trapframe *frame)
193 {
194 	md_nmi_wrapup_func(frame);
195 }
196 #endif
197 
198 /*
199  * Handle asynchronous software traps.
200  */
201 void
202 ast(struct trapframe *frame)
203 {
204 	struct cpu_info *ci = curcpu();
205 	struct proc *p = ci->ci_curproc;
206 
207 	p->p_md.md_astpending = 0;
208 
209 	uvmexp.softs++;
210 	mi_ast(p, ci->ci_want_resched);
211 	userret(p);
212 }
213 
214 #ifdef M88100
215 void
216 m88100_trap(u_int type, struct trapframe *frame)
217 {
218 	struct proc *p;
219 	struct vm_map *map;
220 	vaddr_t va, pcb_onfault;
221 	vm_prot_t access_type;
222 	int fault_type, pbus_type;
223 	u_long fault_code;
224 	vaddr_t fault_addr;
225 	struct vmspace *vm;
226 	union sigval sv;
227 	int result;
228 #ifdef DDB
229 	int s;
230 	u_int psr;
231 #endif
232 	int sig = 0;
233 
234 	uvmexp.traps++;
235 	if ((p = curproc) == NULL)
236 		p = &proc0;
237 
238 	if (USERMODE(frame->tf_epsr)) {
239 		type |= T_USER;
240 		p->p_md.md_tf = frame;	/* for ptrace/signals */
241 		refreshcreds(p);
242 	}
243 	fault_type = SI_NOINFO;
244 	fault_code = 0;
245 	fault_addr = frame->tf_sxip & XIP_ADDR;
246 
247 	switch (type) {
248 	default:
249 	case T_ILLFLT:
250 lose:
251 		panictrap(frame->tf_vector, frame);
252 		break;
253 		/*NOTREACHED*/
254 
255 #if defined(DDB)
256 	case T_KDB_BREAK:
257 		s = splhigh();
258 		set_psr((psr = get_psr()) & ~PSR_IND);
259 		ddb_break_trap(T_KDB_BREAK, (db_regs_t*)frame);
260 		set_psr(psr);
261 		splx(s);
262 		return;
263 	case T_KDB_ENTRY:
264 		s = splhigh();
265 		set_psr((psr = get_psr()) & ~PSR_IND);
266 		ddb_entry_trap(T_KDB_ENTRY, (db_regs_t*)frame);
267 		set_psr(psr);
268 		splx(s);
269 		return;
270 #endif /* DDB */
271 	case T_MISALGNFLT:
272 		printf("kernel misaligned access exception @0x%08lx\n",
273 		    frame->tf_sxip);
274 		goto lose;
275 	case T_INSTFLT:
276 		/* kernel mode instruction access fault.
277 		 * Should never, never happen for a non-paged kernel.
278 		 */
279 #ifdef TRAPDEBUG
280 		pbus_type = CMMU_PFSR_FAULT(frame->tf_ipfsr);
281 		printf("Kernel Instruction fault #%d (%s) v = 0x%x, frame 0x%x cpu %p\n",
282 		    pbus_type, pbus_exception_type[pbus_type],
283 		    fault_addr, frame, frame->tf_cpu);
284 #endif
285 		goto lose;
286 	case T_DATAFLT:
287 		/* kernel mode data fault */
288 
289 		/* data fault on the user address? */
290 		if ((frame->tf_dmt0 & DMT_DAS) == 0)
291 			goto user_fault;
292 
293 		fault_addr = frame->tf_dma0;
294 		if (frame->tf_dmt0 & (DMT_WRITE|DMT_LOCKBAR)) {
295 			access_type = PROT_READ | PROT_WRITE;
296 			fault_code = PROT_WRITE;
297 		} else {
298 			access_type = PROT_READ;
299 			fault_code = PROT_READ;
300 		}
301 
302 		va = trunc_page((vaddr_t)fault_addr);
303 
304 		vm = p->p_vmspace;
305 		map = kernel_map;
306 
307 		pbus_type = CMMU_PFSR_FAULT(frame->tf_dpfsr);
308 #ifdef TRAPDEBUG
309 		printf("Kernel Data access fault #%d (%s) v = 0x%x, frame 0x%x cpu %p\n",
310 		    pbus_type, pbus_exception_type[pbus_type],
311 		    fault_addr, frame, frame->tf_cpu);
312 #endif
313 
314 		pcb_onfault = p->p_addr->u_pcb.pcb_onfault;
315 		switch (pbus_type) {
316 		case CMMU_PFSR_SUCCESS:
317 			/*
318 			 * The fault was resolved. Call data_access_emulation
319 			 * to drain the data unit pipe line and reset dmt0
320 			 * so that trap won't get called again.
321 			 */
322 			p->p_addr->u_pcb.pcb_onfault = 0;
323 			KERNEL_LOCK();
324 			data_access_emulation((u_int *)frame);
325 			KERNEL_UNLOCK();
326 			p->p_addr->u_pcb.pcb_onfault = pcb_onfault;
327 			frame->tf_dmt0 = 0;
328 			frame->tf_dpfsr = 0;
329 			return;
330 		case CMMU_PFSR_SFAULT:
331 		case CMMU_PFSR_PFAULT:
332 			p->p_addr->u_pcb.pcb_onfault = 0;
333 			KERNEL_LOCK();
334 			result = uvm_fault(map, va, 0, access_type);
335 			p->p_addr->u_pcb.pcb_onfault = pcb_onfault;
336 			if (result == 0) {
337 				/*
338 				 * We could resolve the fault. Call
339 				 * data_access_emulation to drain the data
340 				 * unit pipe line and reset dmt0 so that trap
341 				 * won't get called again.
342 				 */
343 				p->p_addr->u_pcb.pcb_onfault = 0;
344 				data_access_emulation((u_int *)frame);
345 				KERNEL_UNLOCK();
346 				p->p_addr->u_pcb.pcb_onfault = pcb_onfault;
347 				frame->tf_dmt0 = 0;
348 				frame->tf_dpfsr = 0;
349 				return;
350 			} else if (pcb_onfault != 0) {
351 				KERNEL_UNLOCK();
352 				/*
353 				 * This could be a fault caused in copyout*()
354 				 * while accessing kernel space.
355 				 */
356 				frame->tf_snip = pcb_onfault | NIP_V;
357 				frame->tf_sfip = (pcb_onfault + 4) | FIP_V;
358 				/*
359 				 * Continue as if the fault had been resolved,
360 				 * but do not try to complete the faulting
361 				 * access.
362 				 */
363 				frame->tf_dmt0 = 0;
364 				frame->tf_dpfsr = 0;
365 				return;
366 			}
367 			KERNEL_UNLOCK();
368 			break;
369 		}
370 #ifdef TRAPDEBUG
371 		printf("PBUS Fault %d (%s) va = 0x%x\n", pbus_type,
372 		    pbus_exception_type[pbus_type], va);
373 #endif
374 		goto lose;
375 		/* NOTREACHED */
376 	case T_INSTFLT+T_USER:
377 		/* User mode instruction access fault */
378 		/* FALLTHROUGH */
379 	case T_DATAFLT+T_USER:
380 		if (!uvm_map_inentry(p, &p->p_spinentry, PROC_STACK(p),
381 		    "[%s]%d/%d sp=%lx inside %lx-%lx: not MAP_STACK\n",
382 		    uvm_map_inentry_sp, p->p_vmspace->vm_map.sserial))
383 			goto userexit;
384 user_fault:
385 		if (type == T_INSTFLT + T_USER) {
386 			pbus_type = CMMU_PFSR_FAULT(frame->tf_ipfsr);
387 #ifdef TRAPDEBUG
388 			printf("User Instruction fault #%d (%s) v = 0x%x, frame 0x%x cpu %p\n",
389 			    pbus_type, pbus_exception_type[pbus_type],
390 			    fault_addr, frame, frame->tf_cpu);
391 #endif
392 			access_type = PROT_EXEC;
393 			fault_code = PROT_EXEC;
394 		} else {
395 			fault_addr = frame->tf_dma0;
396 			pbus_type = CMMU_PFSR_FAULT(frame->tf_dpfsr);
397 #ifdef TRAPDEBUG
398 			printf("User Data access fault #%d (%s) v = 0x%x, frame 0x%x cpu %p\n",
399 			    pbus_type, pbus_exception_type[pbus_type],
400 			    fault_addr, frame, frame->tf_cpu);
401 #endif
402 			if (frame->tf_dmt0 & (DMT_WRITE | DMT_LOCKBAR)) {
403 				access_type = PROT_READ | PROT_WRITE;
404 				fault_code = PROT_WRITE;
405 			} else {
406 				access_type = PROT_READ;
407 				fault_code = PROT_READ;
408 			}
409 		}
410 
411 		va = trunc_page((vaddr_t)fault_addr);
412 
413 		vm = p->p_vmspace;
414 		map = &vm->vm_map;
415 		if ((pcb_onfault = p->p_addr->u_pcb.pcb_onfault) != 0)
416 			p->p_addr->u_pcb.pcb_onfault = 0;
417 
418 		/* Call uvm_fault() to resolve non-bus error faults */
419 		switch (pbus_type) {
420 		case CMMU_PFSR_SUCCESS:
421 			result = 0;
422 			break;
423 		case CMMU_PFSR_BERROR:
424 			result = EACCES;
425 			break;
426 		default:
427 			KERNEL_LOCK();
428 			result = uvm_fault(map, va, 0, access_type);
429 			KERNEL_UNLOCK();
430 			if (result == EACCES)
431 				result = EFAULT;
432 			break;
433 		}
434 
435 		p->p_addr->u_pcb.pcb_onfault = pcb_onfault;
436 
437 		if (result == 0) {
438 			uvm_grow(p, va);
439 
440 			if (type == T_INSTFLT + T_USER) {
441 				m88100_rewind_insn(&(frame->tf_regs));
442 				/* clear the error bit */
443 				frame->tf_sfip &= ~FIP_E;
444 				frame->tf_snip &= ~NIP_E;
445 				frame->tf_ipfsr = 0;
446 			} else {
447 				/*
448 			 	 * We could resolve the fault. Call
449 			 	 * data_access_emulation to drain the data unit
450 			 	 * pipe line and reset dmt0 so that trap won't
451 			 	 * get called again.
452 			 	 */
453 				p->p_addr->u_pcb.pcb_onfault = 0;
454 				KERNEL_LOCK();
455 				data_access_emulation((u_int *)frame);
456 				KERNEL_UNLOCK();
457 				p->p_addr->u_pcb.pcb_onfault = pcb_onfault;
458 				frame->tf_dmt0 = 0;
459 				frame->tf_dpfsr = 0;
460 			}
461 		} else {
462 			/*
463 			 * This could be a fault caused in copyin*()
464 			 * while accessing user space.
465 			 */
466 			if (pcb_onfault != 0) {
467 				frame->tf_snip = pcb_onfault | NIP_V;
468 				frame->tf_sfip = (pcb_onfault + 4) | FIP_V;
469 				/*
470 				 * Continue as if the fault had been resolved,
471 				 * but do not try to complete the faulting
472 				 * access.
473 				 */
474 				frame->tf_dmt0 = 0;
475 				frame->tf_dpfsr = 0;
476 			} else {
477 				sig = result == EACCES ? SIGBUS : SIGSEGV;
478 				fault_type = result == EACCES ?
479 				    BUS_ADRERR : SEGV_MAPERR;
480 			}
481 		}
482 		break;
483 	case T_MISALGNFLT+T_USER:
484 		/* Fix any misaligned ld.d or st.d instructions */
485 		sig = double_reg_fixup(frame, T_MISALGNFLT);
486 		fault_type = BUS_ADRALN;
487 		break;
488 	case T_PRIVINFLT+T_USER:
489 	case T_ILLFLT+T_USER:
490 #ifndef DDB
491 	case T_KDB_BREAK:
492 	case T_KDB_ENTRY:
493 #endif
494 	case T_KDB_BREAK+T_USER:
495 	case T_KDB_ENTRY+T_USER:
496 	case T_KDB_TRACE:
497 	case T_KDB_TRACE+T_USER:
498 		sig = SIGILL;
499 		break;
500 	case T_BNDFLT+T_USER:
501 		sig = SIGFPE;
502 		break;
503 	case T_ZERODIV+T_USER:
504 		sig = SIGFPE;
505 		fault_type = FPE_INTDIV;
506 		break;
507 	case T_OVFFLT+T_USER:
508 		sig = SIGFPE;
509 		fault_type = FPE_INTOVF;
510 		break;
511 	case T_FPEPFLT+T_USER:
512 		m88100_fpu_precise_exception(frame);
513 		goto userexit;
514 	case T_FPEIFLT:
515 		/*
516 		 * Although the kernel does not use FPU instructions,
517 		 * userland-triggered FPU imprecise exceptions may be
518 		 * raised during exception processing, when the FPU gets
519 		 * reenabled (i.e. immediately when returning to
520 		 * m88100_fpu_enable).
521 		 */
522 		/* FALLTHROUGH */
523 	case T_FPEIFLT+T_USER:
524 		m88100_fpu_imprecise_exception(frame);
525 		goto userexit;
526 	case T_SIGSYS+T_USER:
527 		sig = SIGSYS;
528 		break;
529 	case T_STEPBPT+T_USER:
530 #ifdef PTRACE
531 		/*
532 		 * This trap is used by the kernel to support single-step
533 		 * debugging (although any user could generate this trap
534 		 * which should probably be handled differently). When a
535 		 * process is continued by a debugger with the PT_STEP
536 		 * function of ptrace (single step), the kernel inserts
537 		 * one or two breakpoints in the user process so that only
538 		 * one instruction (or two in the case of a delayed branch)
539 		 * is executed.  When this breakpoint is hit, we get the
540 		 * T_STEPBPT trap.
541 		 */
542 		{
543 			u_int instr;
544 			vaddr_t pc = PC_REGS(&frame->tf_regs);
545 
546 			/* read break instruction */
547 			copyinsn(p, (u_int32_t *)pc, (u_int32_t *)&instr);
548 
549 			/* check and see if we got here by accident */
550 			if ((p->p_md.md_bp0va != pc &&
551 			     p->p_md.md_bp1va != pc) ||
552 			    instr != SSBREAKPOINT) {
553 				sig = SIGTRAP;
554 				fault_type = TRAP_TRACE;
555 				break;
556 			}
557 
558 			/* restore original instruction and clear breakpoint */
559 			KERNEL_LOCK();
560 			if (p->p_md.md_bp0va == pc) {
561 				ss_put_value(p, pc, p->p_md.md_bp0save);
562 				p->p_md.md_bp0va = 0;
563 			}
564 			if (p->p_md.md_bp1va == pc) {
565 				ss_put_value(p, pc, p->p_md.md_bp1save);
566 				p->p_md.md_bp1va = 0;
567 			}
568 			KERNEL_UNLOCK();
569 
570 			frame->tf_sxip = pc | NIP_V;
571 			sig = SIGTRAP;
572 			fault_type = TRAP_BRKPT;
573 		}
574 #else
575 		sig = SIGTRAP;
576 		fault_type = TRAP_TRACE;
577 #endif
578 		break;
579 
580 	case T_USERBPT+T_USER:
581 		/*
582 		 * This trap is meant to be used by debuggers to implement
583 		 * breakpoint debugging.  When we get this trap, we just
584 		 * return a signal which gets caught by the debugger.
585 		 */
586 		sig = SIGTRAP;
587 		fault_type = TRAP_BRKPT;
588 		break;
589 
590 	}
591 
592 	/*
593 	 * If trap from supervisor mode, just return
594 	 */
595 	if (type < T_USER)
596 		return;
597 
598 	if (sig) {
599 		sv.sival_ptr = (void *)fault_addr;
600 		trapsignal(p, sig, fault_code, fault_type, sv);
601 		/*
602 		 * don't want multiple faults - we are going to
603 		 * deliver signal.
604 		 */
605 		frame->tf_dmt0 = 0;
606 		frame->tf_ipfsr = frame->tf_dpfsr = 0;
607 	}
608 
609 userexit:
610 	userret(p);
611 }
612 #endif /* M88100 */
613 
614 #ifdef M88110
615 void
616 m88110_trap(u_int type, struct trapframe *frame)
617 {
618 	struct proc *p;
619 	struct vm_map *map;
620 	vaddr_t va, pcb_onfault;
621 	vm_prot_t access_type;
622 	int fault_type;
623 	u_long fault_code;
624 	vaddr_t fault_addr;
625 	struct vmspace *vm;
626 	union sigval sv;
627 	int result;
628 #ifdef DDB
629         int s;
630 	u_int psr;
631 #endif
632 	int sig = 0;
633 
634 	uvmexp.traps++;
635 	if ((p = curproc) == NULL)
636 		p = &proc0;
637 
638 	fault_type = SI_NOINFO;
639 	fault_code = 0;
640 	fault_addr = frame->tf_exip & XIP_ADDR;
641 
642 	/*
643 	 * 88110 errata #16 (4.2) or #3 (5.1.1):
644 	 * ``bsr, br, bcnd, jsr and jmp instructions with the .n extension
645 	 *   can cause the enip value to be incremented by 4 incorrectly
646 	 *   if the instruction in the delay slot is the first word of a
647 	 *   page which misses in the mmu and results in a hardware
648 	 *   tablewalk which encounters an exception or an invalid
649 	 *   descriptor.  The exip value in this case will point to the
650 	 *   first word of the page, and the D bit will be set.
651 	 *
652 	 *   Note: if the instruction is a jsr.n r1, r1 will be overwritten
653 	 *   with erroneous data.  Therefore, no recovery is possible. Do
654 	 *   not allow this instruction to occupy the last word of a page.
655 	 *
656 	 *   Suggested fix: recover in general by backing up the exip by 4
657 	 *   and clearing the delay bit before an rte when the lower 3 hex
658 	 *   digits of the exip are 001.''
659 	 */
660 	if ((frame->tf_exip & PAGE_MASK) == 0x00000001 && type == T_INSTFLT) {
661 		u_int instr;
662 
663 		/*
664 		 * Note that we have initialized fault_addr above, so that
665 		 * signals provide the correct address if necessary.
666 		 */
667 		frame->tf_exip = (frame->tf_exip & ~1) - 4;
668 
669 		/*
670 		 * Check the instruction at the (backed up) exip.
671 		 * If it is a jsr.n, abort.
672 		 */
673 		if (!USERMODE(frame->tf_epsr)) {
674 			instr = *(u_int *)fault_addr;
675 			if (instr == 0xf400cc01)
676 				panic("mc88110 errata #16, exip 0x%lx enip 0x%lx",
677 				    (frame->tf_exip + 4) | 1, frame->tf_enip);
678 		} else {
679 			/* copyin here should not fail */
680 			if (copyinsn(p, (u_int32_t *)frame->tf_exip,
681 			    (u_int32_t *)&instr) == 0 &&
682 			    instr == 0xf400cc01) {
683 				uprintf("mc88110 errata #16, exip 0x%lx enip 0x%lx",
684 				    (frame->tf_exip + 4) | 1, frame->tf_enip);
685 				sig = SIGILL;
686 			}
687 		}
688 	}
689 
690 	if (USERMODE(frame->tf_epsr)) {
691 		type |= T_USER;
692 		p->p_md.md_tf = frame;	/* for ptrace/signals */
693 		refreshcreds(p);
694 	}
695 
696 	if (sig != 0)
697 		goto deliver;
698 
699 	switch (type) {
700 	default:
701 lose:
702 		panictrap(frame->tf_vector, frame);
703 		break;
704 		/*NOTREACHED*/
705 
706 #ifdef DEBUG
707 	case T_110_DRM+T_USER:
708 	case T_110_DRM:
709 		printf("DMMU read miss: Hardware Table Searches should be enabled!\n");
710 		goto lose;
711 	case T_110_DWM+T_USER:
712 	case T_110_DWM:
713 		printf("DMMU write miss: Hardware Table Searches should be enabled!\n");
714 		goto lose;
715 	case T_110_IAM+T_USER:
716 	case T_110_IAM:
717 		printf("IMMU miss: Hardware Table Searches should be enabled!\n");
718 		goto lose;
719 #endif
720 
721 #ifdef DDB
722 	case T_KDB_TRACE:
723 		s = splhigh();
724 		set_psr((psr = get_psr()) & ~PSR_IND);
725 		ddb_break_trap(T_KDB_TRACE, (db_regs_t*)frame);
726 		set_psr(psr);
727 		splx(s);
728 		return;
729 	case T_KDB_BREAK:
730 		s = splhigh();
731 		set_psr((psr = get_psr()) & ~PSR_IND);
732 		ddb_break_trap(T_KDB_BREAK, (db_regs_t*)frame);
733 		set_psr(psr);
734 		splx(s);
735 		return;
736 	case T_KDB_ENTRY:
737 		s = splhigh();
738 		set_psr((psr = get_psr()) & ~PSR_IND);
739 		ddb_entry_trap(T_KDB_ENTRY, (db_regs_t*)frame);
740 		set_psr(psr);
741 		/* skip trap instruction */
742 		m88110_skip_insn(frame);
743 		splx(s);
744 		return;
745 #endif /* DDB */
746 	case T_ILLFLT:
747 		/*
748 		 * The 88110 seems to trigger an instruction fault in
749 		 * supervisor mode when running the following sequence:
750 		 *
751 		 *	bcnd.n cond, reg, 1f
752 		 *	arithmetic insn
753 		 *	...
754 		 *  	the same exact arithmetic insn
755 		 *  1:	another arithmetic insn stalled by the previous one
756 		 *	...
757 		 *
758 		 * The exception is reported with exip pointing to the
759 		 * branch address. I don't know, at this point, if there
760 		 * is any better workaround than the aggressive one
761 		 * implemented below; I don't see how this could relate to
762 		 * any of the 88110 errata (although it might be related to
763 		 * branch prediction).
764 		 *
765 		 * For the record, the exact sequence triggering the
766 		 * spurious exception is:
767 		 *
768 		 *	bcnd.n	eq0, r2,  1f
769 		 *	 or	r25, r0,  r22
770 		 *	bsr	somewhere
771 		 *	or	r25, r0,  r22
772 		 *  1:	cmp	r13, r25, r20
773 		 *
774 		 * within the same cache line.
775 		 *
776 		 * Simply ignoring the exception and returning does not
777 		 * cause the exception to disappear. Clearing the
778 		 * instruction cache works, but on 88110+88410 systems,
779 		 * the 88410 needs to be invalidated as well. (note that
780 		 * the size passed to the flush routines does not matter
781 		 * since there is no way to flush a subset of the 88110
782 		 * I$ anyway)
783 		 */
784 	    {
785 		extern void *kernel_text, *etext;
786 
787 		if (fault_addr >= (vaddr_t)&kernel_text &&
788 		    fault_addr < (vaddr_t)&etext) {
789 			cmmu_icache_inv(curcpu()->ci_cpuid,
790 			    trunc_page(fault_addr), PAGE_SIZE);
791 			cmmu_cache_wbinv(curcpu()->ci_cpuid,
792 			    trunc_page(fault_addr), PAGE_SIZE);
793 			return;
794 		}
795 	    }
796 		goto lose;
797 	case T_MISALGNFLT:
798 		printf("kernel misaligned access exception @%p\n",
799 		    (void *)frame->tf_exip);
800 		goto lose;
801 	case T_INSTFLT:
802 		/* kernel mode instruction access fault.
803 		 * Should never, never happen for a non-paged kernel.
804 		 */
805 #ifdef TRAPDEBUG
806 		printf("Kernel Instruction fault exip %x isr %x ilar %x\n",
807 		    frame->tf_exip, frame->tf_isr, frame->tf_ilar);
808 #endif
809 		goto lose;
810 
811 	case T_DATAFLT:
812 		/* kernel mode data fault */
813 
814 		/* data fault on the user address? */
815 		if ((frame->tf_dsr & CMMU_DSR_SU) == 0)
816 			goto m88110_user_fault;
817 
818 #ifdef TRAPDEBUG
819 		printf("Kernel Data access fault exip %x dsr %x dlar %x\n",
820 		    frame->tf_exip, frame->tf_dsr, frame->tf_dlar);
821 #endif
822 
823 		fault_addr = frame->tf_dlar;
824 		if (frame->tf_dsr & CMMU_DSR_RW) {
825 			access_type = PROT_READ;
826 			fault_code = PROT_READ;
827 		} else {
828 			access_type = PROT_READ | PROT_WRITE;
829 			fault_code = PROT_WRITE;
830 		}
831 
832 		va = trunc_page((vaddr_t)fault_addr);
833 
834 		vm = p->p_vmspace;
835 		map = kernel_map;
836 
837 		if (frame->tf_dsr & (CMMU_DSR_SI | CMMU_DSR_PI)) {
838 			/*
839 			 * On a segment or a page fault, call uvm_fault() to
840 			 * resolve the fault.
841 			 */
842 			if ((pcb_onfault = p->p_addr->u_pcb.pcb_onfault) != 0)
843 				p->p_addr->u_pcb.pcb_onfault = 0;
844 			KERNEL_LOCK();
845 			result = uvm_fault(map, va, 0, access_type);
846 			KERNEL_UNLOCK();
847 			p->p_addr->u_pcb.pcb_onfault = pcb_onfault;
848 			/*
849 			 * This could be a fault caused in copyout*()
850 			 * while accessing kernel space.
851 			 */
852 			if (result != 0 && pcb_onfault != 0) {
853 				frame->tf_exip = pcb_onfault;
854 				/*
855 				 * Continue as if the fault had been resolved.
856 				 */
857 				result = 0;
858 			}
859 			if (result == 0)
860 				return;
861 		}
862 		goto lose;
863 	case T_INSTFLT+T_USER:
864 		/* User mode instruction access fault */
865 		/* FALLTHROUGH */
866 	case T_DATAFLT+T_USER:
867 		if (!uvm_map_inentry(p, &p->p_spinentry, PROC_STACK(p),
868 		    "[%s]%d/%d sp=%lx inside %lx-%lx: not MAP_STACK\n",
869 		    uvm_map_inentry_sp, p->p_vmspace->vm_map.sserial))
870 			goto userexit;
871 m88110_user_fault:
872 		if (type == T_INSTFLT+T_USER) {
873 			access_type = PROT_EXEC;
874 			fault_code = PROT_EXEC;
875 #ifdef TRAPDEBUG
876 			printf("User Instruction fault exip %lx isr %lx ilar %lx\n",
877 			    frame->tf_exip, frame->tf_isr, frame->tf_ilar);
878 #endif
879 		} else {
880 			fault_addr = frame->tf_dlar;
881 			/*
882 			 * Unlike the 88100, there is no specific bit telling
883 			 * us this is the read part of an xmem operation.
884 			 * However, if the WE (Write Exception) bit is set,
885 			 * then obviously this is not a read fault.
886 			 * But the value of this bit can not be relied upon
887 			 * if either PI or SI are set...
888 			 */
889 			if ((frame->tf_dsr & CMMU_DSR_RW) != 0 &&
890 			    ((frame->tf_dsr & (CMMU_DSR_PI|CMMU_DSR_SI)) != 0 ||
891 			     (frame->tf_dsr & CMMU_DSR_WE) == 0)) {
892 				access_type = PROT_READ;
893 				fault_code = PROT_READ;
894 			} else {
895 				access_type = PROT_READ | PROT_WRITE;
896 				fault_code = PROT_WRITE;
897 			}
898 #ifdef TRAPDEBUG
899 			printf("User Data access fault exip %lx dsr %lx dlar %lx\n",
900 			    frame->tf_exip, frame->tf_dsr, frame->tf_dlar);
901 #endif
902 		}
903 
904 		va = trunc_page((vaddr_t)fault_addr);
905 
906 		vm = p->p_vmspace;
907 		map = &vm->vm_map;
908 		if ((pcb_onfault = p->p_addr->u_pcb.pcb_onfault) != 0)
909 			p->p_addr->u_pcb.pcb_onfault = 0;
910 
911 		/*
912 		 * Call uvm_fault() to resolve non-bus error faults
913 		 * whenever possible.
914 		 */
915 		if (type == T_INSTFLT+T_USER) {
916 			/* instruction faults */
917 			if (frame->tf_isr &
918 			    (CMMU_ISR_BE | CMMU_ISR_SP | CMMU_ISR_TBE)) {
919 				/* bus error, supervisor protection */
920 				result = EACCES;
921 			} else
922 			if (frame->tf_isr & (CMMU_ISR_SI | CMMU_ISR_PI)) {
923 				/* segment or page fault */
924 				KERNEL_LOCK();
925 				result = uvm_fault(map, va, 0, access_type);
926 				KERNEL_UNLOCK();
927 				if (result == EACCES)
928 					result = EFAULT;
929 			} else {
930 #ifdef TRAPDEBUG
931 				printf("Unexpected Instruction fault isr %lx\n",
932 				    frame->tf_isr);
933 #endif
934 				goto lose;
935 			}
936 		} else {
937 			/* data faults */
938 			if (frame->tf_dsr & CMMU_DSR_BE) {
939 				/* bus error */
940 				result = EACCES;
941 			} else
942 			if (frame->tf_dsr & (CMMU_DSR_SI | CMMU_DSR_PI)) {
943 				/* segment or page fault */
944 				KERNEL_LOCK();
945 				result = uvm_fault(map, va, 0, access_type);
946 				KERNEL_UNLOCK();
947 				if (result == EACCES)
948 					result = EFAULT;
949 			} else
950 			if (frame->tf_dsr & (CMMU_DSR_CP | CMMU_DSR_WA)) {
951 				/* copyback or write allocate error */
952 				result = EACCES;
953 			} else
954 			if (frame->tf_dsr & CMMU_DSR_WE) {
955 				/* write fault  */
956 				/* This could be a write protection fault or an
957 				 * exception to set the used and modified bits
958 				 * in the pte. Basically, if we got a write
959 				 * error, then we already have a pte entry that
960 				 * faulted in from a previous seg fault or page
961 				 * fault.
962 				 * Get the pte and check the status of the
963 				 * modified and valid bits to determine if this
964 				 * indeed a real write fault.  XXX smurph
965 				 */
966 				if (pmap_set_modify(map->pmap, va)) {
967 #ifdef TRAPDEBUG
968 					printf("Corrected userland write fault, pmap %p va %p\n",
969 					    map->pmap, (void *)va);
970 #endif
971 					result = 0;
972 				} else {
973 					/* must be a real wp fault */
974 #ifdef TRAPDEBUG
975 					printf("Uncorrected userland write fault, pmap %p va %p\n",
976 					    map->pmap, (void *)va);
977 #endif
978 					result = uvm_fault(map, va, 0, access_type);
979 					if (result == EACCES)
980 						result = EFAULT;
981 				}
982 			} else {
983 #ifdef TRAPDEBUG
984 				printf("Unexpected Data access fault dsr %lx\n",
985 				    frame->tf_dsr);
986 #endif
987 				goto lose;
988 			}
989 		}
990 		p->p_addr->u_pcb.pcb_onfault = pcb_onfault;
991 
992 		if (result == 0)
993 			uvm_grow(p, va);
994 
995 		/*
996 		 * This could be a fault caused in copyin*()
997 		 * while accessing user space.
998 		 */
999 		if (result != 0 && pcb_onfault != 0) {
1000 			frame->tf_exip = pcb_onfault;
1001 			/*
1002 			 * Continue as if the fault had been resolved.
1003 			 */
1004 			result = 0;
1005 		}
1006 
1007 		if (result != 0) {
1008 			sig = result == EACCES ? SIGBUS : SIGSEGV;
1009 			fault_type = result == EACCES ?
1010 			    BUS_ADRERR : SEGV_MAPERR;
1011 		}
1012 		break;
1013 	case T_MISALGNFLT+T_USER:
1014 		/* Fix any misaligned ld.d or st.d instructions */
1015 		sig = double_reg_fixup(frame, T_MISALGNFLT);
1016 		fault_type = BUS_ADRALN;
1017 		if (sig == 0) {
1018 			/* skip recovered instruction */
1019 			m88110_skip_insn(frame);
1020 			goto userexit;
1021 		}
1022 		break;
1023 	case T_ILLFLT+T_USER:
1024 		/* Fix any ld.d or st.d instruction with an odd register */
1025 		sig = double_reg_fixup(frame, T_ILLFLT);
1026 		fault_type = ILL_PRVREG;
1027 		if (sig == 0) {
1028 			/* skip recovered instruction */
1029 			m88110_skip_insn(frame);
1030 			goto userexit;
1031 		}
1032 		break;
1033 	case T_PRIVINFLT+T_USER:
1034 		fault_type = ILL_PRVREG;
1035 		/* FALLTHROUGH */
1036 #ifndef DDB
1037 	case T_KDB_BREAK:
1038 	case T_KDB_ENTRY:
1039 	case T_KDB_TRACE:
1040 #endif
1041 	case T_KDB_BREAK+T_USER:
1042 	case T_KDB_ENTRY+T_USER:
1043 	case T_KDB_TRACE+T_USER:
1044 		sig = SIGILL;
1045 		break;
1046 	case T_BNDFLT+T_USER:
1047 		sig = SIGFPE;
1048 		/* skip trap instruction */
1049 		m88110_skip_insn(frame);
1050 		break;
1051 	case T_ZERODIV+T_USER:
1052 		sig = SIGFPE;
1053 		fault_type = FPE_INTDIV;
1054 		/* skip trap instruction */
1055 		m88110_skip_insn(frame);
1056 		break;
1057 	case T_OVFFLT+T_USER:
1058 		sig = SIGFPE;
1059 		fault_type = FPE_INTOVF;
1060 		/* skip trap instruction */
1061 		m88110_skip_insn(frame);
1062 		break;
1063 	case T_FPEPFLT+T_USER:
1064 		m88110_fpu_exception(frame);
1065 		goto userexit;
1066 	case T_SIGSYS+T_USER:
1067 		sig = SIGSYS;
1068 		break;
1069 	case T_STEPBPT+T_USER:
1070 #ifdef PTRACE
1071 		/*
1072 		 * This trap is used by the kernel to support single-step
1073 		 * debugging (although any user could generate this trap
1074 		 * which should probably be handled differently). When a
1075 		 * process is continued by a debugger with the PT_STEP
1076 		 * function of ptrace (single step), the kernel inserts
1077 		 * one or two breakpoints in the user process so that only
1078 		 * one instruction (or two in the case of a delayed branch)
1079 		 * is executed.  When this breakpoint is hit, we get the
1080 		 * T_STEPBPT trap.
1081 		 */
1082 		{
1083 			u_int instr;
1084 			vaddr_t pc = PC_REGS(&frame->tf_regs);
1085 
1086 			/* read break instruction */
1087 			copyinsn(p, (u_int32_t *)pc, (u_int32_t *)&instr);
1088 
1089 			/* check and see if we got here by accident */
1090 			if ((p->p_md.md_bp0va != pc &&
1091 			     p->p_md.md_bp1va != pc) ||
1092 			    instr != SSBREAKPOINT) {
1093 				sig = SIGTRAP;
1094 				fault_type = TRAP_TRACE;
1095 				break;
1096 			}
1097 
1098 			/* restore original instruction and clear breakpoint */
1099 			KERNEL_LOCK();
1100 			if (p->p_md.md_bp0va == pc) {
1101 				ss_put_value(p, pc, p->p_md.md_bp0save);
1102 				p->p_md.md_bp0va = 0;
1103 			}
1104 			if (p->p_md.md_bp1va == pc) {
1105 				ss_put_value(p, pc, p->p_md.md_bp1save);
1106 				p->p_md.md_bp1va = 0;
1107 			}
1108 			KERNEL_UNLOCK();
1109 
1110 			sig = SIGTRAP;
1111 			fault_type = TRAP_BRKPT;
1112 		}
1113 #else
1114 		sig = SIGTRAP;
1115 		fault_type = TRAP_TRACE;
1116 #endif
1117 		break;
1118 	case T_USERBPT+T_USER:
1119 		/*
1120 		 * This trap is meant to be used by debuggers to implement
1121 		 * breakpoint debugging.  When we get this trap, we just
1122 		 * return a signal which gets caught by the debugger.
1123 		 */
1124 		sig = SIGTRAP;
1125 		fault_type = TRAP_BRKPT;
1126 		break;
1127 	}
1128 
1129 	/*
1130 	 * If trap from supervisor mode, just return
1131 	 */
1132 	if (type < T_USER)
1133 		return;
1134 
1135 	if (sig) {
1136 deliver:
1137 		sv.sival_ptr = (void *)fault_addr;
1138 		trapsignal(p, sig, fault_code, fault_type, sv);
1139 	}
1140 
1141 userexit:
1142 	userret(p);
1143 }
1144 #endif /* M88110 */
1145 
1146 __dead void
1147 error_fatal(struct trapframe *frame)
1148 {
1149 	if (frame->tf_vector == 0)
1150 		printf("\nCPU %d Reset Exception\n", cpu_number());
1151 	else
1152 		printf("\nCPU %d Error Exception\n", cpu_number());
1153 
1154 #ifdef DDB
1155 	regdump((struct trapframe*)frame);
1156 #endif
1157 	panic("unrecoverable exception %ld", frame->tf_vector);
1158 }
1159 
1160 #ifdef M88100
1161 void
1162 m88100_syscall(register_t code, struct trapframe *tf)
1163 {
1164 	const struct sysent *callp = sysent;
1165 	struct proc *p = curproc;
1166 	int error;
1167 	register_t *args;
1168 	register_t rval[2] __aligned(8);
1169 
1170 	uvmexp.syscalls++;
1171 
1172 	p->p_md.md_tf = tf;
1173 
1174 	// XXX out of range stays on syscall0, which we assume is enosys
1175 	if (code > 0 && code < SYS_MAXSYSCALL)
1176 		callp += code;
1177 
1178 	/*
1179 	 * For 88k, all the arguments are passed in the registers (r2-r9).
1180 	 */
1181 	args = &tf->tf_r[2];
1182 
1183 	rval[0] = 0;
1184 	rval[1] = tf->tf_r[3];
1185 
1186 	error = mi_syscall(p, code, callp, args, rval);
1187 
1188 	/*
1189 	 * system call will look like:
1190 	 *	 or r13, r0, <code>
1191 	 *       tb0 0, r0, <128> <- sxip
1192 	 *	 br err 	  <- snip
1193 	 *       jmp r1 	  <- sfip
1194 	 *  err: or.u r3, r0, hi16(errno)
1195 	 *	 st r2, r3, lo16(errno)
1196 	 *	 subu r2, r0, 1
1197 	 *	 jmp r1
1198 	 *
1199 	 * So, when we take syscall trap, sxip/snip/sfip will be as
1200 	 * shown above.
1201 	 * Given this,
1202 	 * 1. If the system call returned 0, need to skip nip.
1203 	 *	nip = fip, fip += 4
1204 	 *    (doesn't matter what fip + 4 will be but we will never
1205 	 *    execute this since jmp r1 at nip will change the execution flow.)
1206 	 * 2. If the system call returned an errno > 0, plug the value
1207 	 *    in r2, and leave nip and fip unchanged. This will have us
1208 	 *    executing "br err" on return to user space.
1209 	 * 3. If the system call code returned ERESTART,
1210 	 *    we need to rexecute the trap instruction. Back up the pipe
1211 	 *    line.
1212 	 *     fip = nip, nip = xip
1213 	 * 4. If the system call returned EJUSTRETURN, don't need to adjust
1214 	 *    any pointers.
1215 	 */
1216 
1217 	switch (error) {
1218 	case 0:
1219 		tf->tf_r[2] = rval[0];
1220 		tf->tf_r[3] = rval[1];
1221 		tf->tf_epsr &= ~PSR_C;
1222 		tf->tf_snip = tf->tf_sfip & ~NIP_E;
1223 		tf->tf_sfip = tf->tf_snip + 4;
1224 		break;
1225 	case ERESTART:
1226 		m88100_rewind_insn(&(tf->tf_regs));
1227 		/* clear the error bit */
1228 		tf->tf_sfip &= ~FIP_E;
1229 		tf->tf_snip &= ~NIP_E;
1230 		break;
1231 	case EJUSTRETURN:
1232 		break;
1233 	default:
1234 		tf->tf_r[2] = error;
1235 		tf->tf_epsr |= PSR_C;   /* fail */
1236 		tf->tf_snip = tf->tf_snip & ~NIP_E;
1237 		tf->tf_sfip = tf->tf_sfip & ~FIP_E;
1238 		break;
1239 	}
1240 
1241 	mi_syscall_return(p, code, error, rval);
1242 }
1243 #endif /* M88100 */
1244 
1245 #ifdef M88110
1246 /* Instruction pointers operate differently on mc88110 */
1247 void
1248 m88110_syscall(register_t code, struct trapframe *tf)
1249 {
1250 	const struct sysent *callp = sysent;
1251 	struct proc *p = curproc;
1252 	int error;
1253 	register_t rval[2] __aligned(8);
1254 	register_t *args;
1255 
1256 	uvmexp.syscalls++;
1257 
1258 	p->p_md.md_tf = tf;
1259 
1260 	// XXX out of range stays on syscall0, which we assume is enosys
1261 	if (code > 0 && code < SYS_MAXSYSCALL)
1262 		callp += code;
1263 
1264 	/*
1265 	 * For 88k, all the arguments are passed in the registers (r2-r9).
1266 	 */
1267 	args = &tf->tf_r[2];
1268 
1269 	rval[0] = 0;
1270 	rval[1] = tf->tf_r[3];
1271 
1272 	error = mi_syscall(p, code, callp, args, rval);
1273 
1274 	/*
1275 	 * system call will look like:
1276 	 *	 or r13, r0, <code>
1277 	 *       tb0 0, r0, <128> <- exip
1278 	 *	 br err 	  <- enip
1279 	 *       jmp r1
1280 	 *  err: or.u r3, r0, hi16(errno)
1281 	 *	 st r2, r3, lo16(errno)
1282 	 *	 subu r2, r0, 1
1283 	 *	 jmp r1
1284 	 *
1285 	 * So, when we take syscall trap, exip/enip will be as
1286 	 * shown above.
1287 	 * Given this,
1288 	 * 1. If the system call returned 0, need to jmp r1.
1289 	 *    exip += 8
1290 	 * 2. If the system call returned an errno > 0, increment
1291 	 *    exip += 4 and plug the value in r2. This will have us
1292 	 *    executing "br err" on return to user space.
1293 	 * 3. If the system call code returned ERESTART,
1294 	 *    we need to rexecute the trap instruction. leave exip as is.
1295 	 * 4. If the system call returned EJUSTRETURN, just return.
1296 	 *    exip += 4
1297 	 */
1298 
1299 	switch (error) {
1300 	case 0:
1301 		tf->tf_r[2] = rval[0];
1302 		tf->tf_r[3] = rval[1];
1303 		tf->tf_epsr &= ~PSR_C;
1304 		/* skip two instructions */
1305 		m88110_skip_insn(tf);
1306 		m88110_skip_insn(tf);
1307 		break;
1308 	case ERESTART:
1309 		/*
1310 		 * Reexecute the trap.
1311 		 * exip is already at the trap instruction, so
1312 		 * there is nothing to do.
1313 		 */
1314 		break;
1315 	case EJUSTRETURN:
1316 		/* skip one instruction */
1317 		m88110_skip_insn(tf);
1318 		break;
1319 	default:
1320 		tf->tf_r[2] = error;
1321 		tf->tf_epsr |= PSR_C;   /* fail */
1322 		/* skip one instruction */
1323 		m88110_skip_insn(tf);
1324 		break;
1325 	}
1326 
1327 	mi_syscall_return(p, code, error, rval);
1328 }
1329 #endif	/* M88110 */
1330 
1331 /*
1332  * Set up return-value registers as fork() libc stub expects,
1333  * and do normal return-to-user-mode stuff.
1334  */
1335 void
1336 child_return(arg)
1337 	void *arg;
1338 {
1339 	struct proc *p = arg;
1340 	struct trapframe *tf;
1341 
1342 	tf = (struct trapframe *)USER_REGS(p);
1343 	tf->tf_r[2] = 0;
1344 	tf->tf_epsr &= ~PSR_C;
1345 	/* skip br instruction as in syscall() */
1346 #ifdef M88100
1347 	if (CPU_IS88100) {
1348 		tf->tf_snip = (tf->tf_sfip & XIP_ADDR) | XIP_V;
1349 		tf->tf_sfip = tf->tf_snip + 4;
1350 	}
1351 #endif
1352 #ifdef M88110
1353 	if (CPU_IS88110) {
1354 		/* skip two instructions */
1355 		m88110_skip_insn(tf);
1356 		m88110_skip_insn(tf);
1357 	}
1358 #endif
1359 
1360 	KERNEL_UNLOCK();
1361 
1362 	mi_child_return(p);
1363 }
1364 
1365 #ifdef PTRACE
1366 
1367 /*
1368  * User Single Step Debugging Support
1369  */
1370 
1371 #include <sys/ptrace.h>
1372 
1373 vaddr_t	ss_branch_taken(u_int, vaddr_t, struct reg *);
1374 int	ss_get_value(struct proc *, vaddr_t, u_int *);
1375 int	ss_inst_branch_or_call(u_int);
1376 int	ss_put_breakpoint(struct proc *, vaddr_t, vaddr_t *, u_int *);
1377 
1378 #define	SYSCALL_INSTR	0xf000d080	/* tb0 0,r0,128 */
1379 
1380 int
1381 ss_get_value(struct proc *p, vaddr_t addr, u_int *value)
1382 {
1383 	struct uio uio;
1384 	struct iovec iov;
1385 
1386 	iov.iov_base = (caddr_t)value;
1387 	iov.iov_len = sizeof(u_int);
1388 	uio.uio_iov = &iov;
1389 	uio.uio_iovcnt = 1;
1390 	uio.uio_offset = (off_t)addr;
1391 	uio.uio_resid = sizeof(u_int);
1392 	uio.uio_segflg = UIO_SYSSPACE;
1393 	uio.uio_rw = UIO_READ;
1394 	uio.uio_procp = curproc;
1395 	return (process_domem(curproc, p->p_p, &uio, PT_READ_I));
1396 }
1397 
1398 int
1399 ss_put_value(struct proc *p, vaddr_t addr, u_int value)
1400 {
1401 	struct uio uio;
1402 	struct iovec iov;
1403 
1404 	iov.iov_base = (caddr_t)&value;
1405 	iov.iov_len = sizeof(u_int);
1406 	uio.uio_iov = &iov;
1407 	uio.uio_iovcnt = 1;
1408 	uio.uio_offset = (off_t)addr;
1409 	uio.uio_resid = sizeof(u_int);
1410 	uio.uio_segflg = UIO_SYSSPACE;
1411 	uio.uio_rw = UIO_WRITE;
1412 	uio.uio_procp = curproc;
1413 	return (process_domem(curproc, p->p_p, &uio, PT_WRITE_I));
1414 }
1415 
1416 /*
1417  * ss_branch_taken(instruction, pc, regs)
1418  *
1419  * instruction will be a control flow instruction location at address pc.
1420  * Branch taken is supposed to return the address to which the instruction
1421  * would jump if the branch is taken.
1422  *
1423  * This is different from branch_taken() in ddb, as we also need to process
1424  * system calls.
1425  */
1426 vaddr_t
1427 ss_branch_taken(u_int inst, vaddr_t pc, struct reg *regs)
1428 {
1429 	u_int regno;
1430 
1431 	/*
1432 	 * Quick check of the instruction. Note that we know we are only
1433 	 * invoked if ss_inst_branch_or_call() returns TRUE, so we do not
1434 	 * need to repeat the jpm, jsr and syscall stricter checks here.
1435 	 */
1436 	switch (inst >> (32 - 5)) {
1437 	case 0x18:	/* br */
1438 	case 0x19:	/* bsr */
1439 		/* signed 26 bit pc relative displacement, shift left 2 bits */
1440 		inst = (inst & 0x03ffffff) << 2;
1441 		/* check if sign extension is needed */
1442 		if (inst & 0x08000000)
1443 			inst |= 0xf0000000;
1444 		return (pc + inst);
1445 
1446 	case 0x1a:	/* bb0 */
1447 	case 0x1b:	/* bb1 */
1448 	case 0x1d:	/* bcnd */
1449 		/* signed 16 bit pc relative displacement, shift left 2 bits */
1450 		inst = (inst & 0x0000ffff) << 2;
1451 		/* check if sign extension is needed */
1452 		if (inst & 0x00020000)
1453 			inst |= 0xfffc0000;
1454 		return (pc + inst);
1455 
1456 	case 0x1e:	/* jmp or jsr */
1457 		regno = inst & 0x1f;	/* get the register value */
1458 		return (regno == 0 ? 0 : regs->r[regno]);
1459 
1460 	default:	/* system call */
1461 		/*
1462 		 * The regular (pc + 4) breakpoint will match the error
1463 		 * return. Successful system calls return at (pc + 8),
1464 		 * so we'll set up a branch breakpoint there.
1465 		 */
1466 		return (pc + 8);
1467 	}
1468 }
1469 
1470 int
1471 ss_inst_branch_or_call(u_int ins)
1472 {
1473 	/* check high five bits */
1474 	switch (ins >> (32 - 5)) {
1475 	case 0x18: /* br */
1476 	case 0x19: /* bsr */
1477 	case 0x1a: /* bb0 */
1478 	case 0x1b: /* bb1 */
1479 	case 0x1d: /* bcnd */
1480 		return (TRUE);
1481 	case 0x1e: /* could be jmp or jsr */
1482 		if ((ins & 0xfffff3e0) == 0xf400c000)
1483 			return (TRUE);
1484 	}
1485 
1486 	return (FALSE);
1487 }
1488 
1489 int
1490 ss_put_breakpoint(struct proc *p, vaddr_t va, vaddr_t *bpva, u_int *bpsave)
1491 {
1492 	int rc;
1493 
1494 	/* Restore previous breakpoint if we did not trigger it. */
1495 	if (*bpva != 0) {
1496 		ss_put_value(p, *bpva, *bpsave);
1497 		*bpva = 0;
1498 	}
1499 
1500 	/* Save instruction. */
1501 	if ((rc = ss_get_value(p, va, bpsave)) != 0)
1502 		return (rc);
1503 
1504 	/* Store breakpoint instruction at the location now. */
1505 	*bpva = va;
1506 	return (ss_put_value(p, va, SSBREAKPOINT));
1507 }
1508 
1509 int
1510 process_sstep(struct proc *p, int sstep)
1511 {
1512 	struct reg *sstf = USER_REGS(p);
1513 	vaddr_t pc, brpc;
1514 	u_int32_t instr;
1515 	int rc;
1516 
1517 	if (sstep == 0) {
1518 		/* Restore previous breakpoints if any. */
1519 		if (p->p_md.md_bp0va != 0) {
1520 			ss_put_value(p, p->p_md.md_bp0va, p->p_md.md_bp0save);
1521 			p->p_md.md_bp0va = 0;
1522 		}
1523 		if (p->p_md.md_bp1va != 0) {
1524 			ss_put_value(p, p->p_md.md_bp1va, p->p_md.md_bp1save);
1525 			p->p_md.md_bp1va = 0;
1526 		}
1527 
1528 		return (0);
1529 	}
1530 
1531 	/*
1532 	 * User was stopped at pc, e.g. the instruction at pc was not executed.
1533 	 * Fetch what's at the current location.
1534 	 */
1535 	pc = PC_REGS(sstf);
1536 	if ((rc = ss_get_value(p, pc, &instr)) != 0)
1537 		return (rc);
1538 
1539 	/*
1540 	 * Find if this instruction may cause a branch, and set up a breakpoint
1541 	 * at the branch location.
1542 	 */
1543 	if (ss_inst_branch_or_call(instr) || instr == SYSCALL_INSTR) {
1544 		brpc = ss_branch_taken(instr, pc, sstf);
1545 
1546 		/* self-branches are hopeless */
1547 		if (brpc != pc && brpc != 0) {
1548 			if ((rc = ss_put_breakpoint(p, brpc,
1549 			    &p->p_md.md_bp1va, &p->p_md.md_bp1save)) != 0)
1550 				return (rc);
1551 		}
1552 	}
1553 
1554 	if ((rc = ss_put_breakpoint(p, pc + 4,
1555 	    &p->p_md.md_bp0va, &p->p_md.md_bp0save)) != 0)
1556 		return (rc);
1557 
1558 	return (0);
1559 }
1560 
1561 #endif	/* PTRACE */
1562 
1563 #ifdef DIAGNOSTIC
1564 void
1565 splassert_check(int wantipl, const char *func)
1566 {
1567 	int oldipl;
1568 
1569 	oldipl = getipl();
1570 
1571 	if (oldipl < wantipl) {
1572 		splassert_fail(wantipl, oldipl, func);
1573 		/*
1574 		 * This will raise the spl,
1575 		 * in a feeble attempt to reduce further damage.
1576 		 */
1577 		(void)splraise(wantipl);
1578 	}
1579 }
1580 #endif
1581 
1582 /*
1583  * ld.d and st.d instructions referencing long aligned but not long long
1584  * aligned addresses will trigger a misaligned address exception.
1585  *
1586  * This routine attempts to recover these (valid) statements, by simulating
1587  * the split form of the instruction. If it fails, it returns the appropriate
1588  * signal number to deliver.
1589  *
1590  * Note that we do not attempt to do anything for .d.usr instructions - the
1591  * kernel never issues such instructions, and they cause a privileged
1592  * instruction exception from userland.
1593  */
1594 int
1595 double_reg_fixup(struct trapframe *frame, int fault)
1596 {
1597 	u_int32_t pc, instr, value;
1598 	int regno, store;
1599 	vaddr_t addr;
1600 
1601 	/*
1602 	 * Decode the faulting instruction.
1603 	 */
1604 
1605 	pc = PC_REGS(&frame->tf_regs);
1606 	if (copyinsn(NULL, (u_int32_t *)pc, (u_int32_t *)&instr) != 0)
1607 		return SIGSEGV;
1608 
1609 	switch (instr & 0xfc00ffe0) {
1610 	case 0xf4001000:	/* ld.d rD, rS1, rS2 */
1611 		addr = frame->tf_r[(instr >> 16) & 0x1f]
1612 		    + frame->tf_r[(instr & 0x1f)];
1613 		store = 0;
1614 		break;
1615 	case 0xf4001200:	/* ld.d rD, rS1[rS2] */
1616 		addr = frame->tf_r[(instr >> 16) & 0x1f]
1617 		    + 8 * frame->tf_r[(instr & 0x1f)];
1618 		store = 0;
1619 		break;
1620 	case 0xf4002000:	/* st.d rD, rS1, rS2 */
1621 		addr = frame->tf_r[(instr >> 16) & 0x1f]
1622 		    + frame->tf_r[(instr & 0x1f)];
1623 		store = 1;
1624 		break;
1625 	case 0xf4002200:	/* st.d rD, rS1[rS2] */
1626 		addr = frame->tf_r[(instr >> 16) & 0x1f]
1627 		    + 8 * frame->tf_r[(instr & 0x1f)];
1628 		store = 1;
1629 		break;
1630 	default:
1631 		switch (instr >> 26) {
1632 		case 0x10000000 >> 26:	/* ld.d rD, rS, imm16 */
1633 			addr = (instr & 0x0000ffff) +
1634 			    frame->tf_r[(instr >> 16) & 0x1f];
1635 			store = 0;
1636 			break;
1637 		case 0x20000000 >> 26:	/* st.d rD, rS, imm16 */
1638 			addr = (instr & 0x0000ffff) +
1639 			    frame->tf_r[(instr >> 16) & 0x1f];
1640 			store = 1;
1641 			break;
1642 		default:
1643 			return SIGBUS;
1644 		}
1645 		break;
1646 	}
1647 
1648 	regno = (instr >> 21) & 0x1f;
1649 
1650 	switch (fault) {
1651 	case T_MISALGNFLT:
1652 		/* We only handle long but not long long aligned access here */
1653 		if ((addr & 0x07) != 4)
1654 			return SIGBUS;
1655 		break;
1656 	case T_ILLFLT:
1657 		/* We only handle odd register pair number here */
1658 		if ((regno & 0x01) == 0)
1659 			return SIGILL;
1660 		/* We only handle long aligned access here */
1661 		if ((addr & 0x03) != 0)
1662 			return SIGBUS;
1663 		break;
1664 	}
1665 
1666 	if (store) {
1667 		/*
1668 		 * Two word stores.
1669 		 */
1670 		if (regno == 0)
1671 			value = 0;
1672 		else
1673 			value = frame->tf_r[regno];
1674 		if (copyout(&value, (void *)addr, sizeof(u_int32_t)) != 0)
1675 			return SIGSEGV;
1676 		if (regno == 31)
1677 			value = 0;
1678 		else
1679 			value = frame->tf_r[regno + 1];
1680 		if (copyout(&value, (void *)(addr + 4), sizeof(u_int32_t)) != 0)
1681 			return SIGSEGV;
1682 	} else {
1683 		/*
1684 		 * Two word loads. r0 should be left unaltered, but the
1685 		 * value should still be fetched even if it is discarded.
1686 		 */
1687 		if (copyin((void *)addr, &value, sizeof(u_int32_t)) != 0)
1688 			return SIGSEGV;
1689 		if (regno != 0)
1690 			frame->tf_r[regno] = value;
1691 		if (copyin((void *)(addr + 4), &value, sizeof(u_int32_t)) != 0)
1692 			return SIGSEGV;
1693 		if (regno != 31)
1694 			frame->tf_r[regno + 1] = value;
1695 	}
1696 
1697 	return 0;
1698 }
1699 
1700 void
1701 cache_flush(struct trapframe *tf)
1702 {
1703 	struct proc *p = curproc;
1704 	struct pmap *pmap;
1705 	paddr_t pa;
1706 	vaddr_t va;
1707 	vsize_t len, count;
1708 
1709 	p->p_md.md_tf = tf;
1710 
1711 	pmap = vm_map_pmap(&p->p_vmspace->vm_map);
1712 	va = tf->tf_r[2];
1713 	len = tf->tf_r[3];
1714 
1715 	if (va < VM_MIN_ADDRESS || va >= VM_MAXUSER_ADDRESS ||
1716 	    va + len <= va || va + len >= VM_MAXUSER_ADDRESS)
1717 		len = 0;
1718 
1719 	while (len != 0) {
1720 		count = min(len, PAGE_SIZE - (va & PAGE_MASK));
1721 		if (pmap_extract(pmap, va, &pa) != FALSE)
1722 			dma_cachectl(pa, count, DMA_CACHE_SYNC);
1723 		va += count;
1724 		len -= count;
1725 	}
1726 
1727 #ifdef M88100
1728 	if (CPU_IS88100) {
1729 		/* clear the error bit */
1730 		tf->tf_sfip &= ~FIP_E;
1731 		tf->tf_snip &= ~NIP_E;
1732 	}
1733 #endif
1734 #ifdef M88110
1735 	if (CPU_IS88110) {
1736 		/* skip instruction */
1737 		m88110_skip_insn(tf);
1738 	}
1739 #endif
1740 
1741 	userret(p);
1742 }
1743