xref: /netbsd-src/sys/arch/vax/vax/trap.c (revision 68fa58437753598de948829082f591c269b48777)
1 /*	$NetBSD: trap.c,v 1.138 2023/10/05 19:41:06 ad Exp $     */
2 
3 /*
4  * Copyright (c) 1994 Ludd, University of Lule}, Sweden.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28  /* All bugs are subject to removal without further notice */
29 
30 #include <sys/cdefs.h>
31 __KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.138 2023/10/05 19:41:06 ad Exp $");
32 
33 #include "opt_ddb.h"
34 #include "opt_multiprocessor.h"
35 
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/cpu.h>
39 #include <sys/exec.h>
40 #include <sys/kauth.h>
41 #include <sys/proc.h>
42 #include <sys/signalvar.h>
43 
44 #include <uvm/uvm_extern.h>
45 
46 #include <machine/trap.h>
47 #include <machine/userret.h>
48 
49 #ifdef DDB
50 #include <machine/db_machdep.h>
51 #endif
52 #include <vax/vax/db_disasm.h>
53 #include <kern/syscalls.c>
54 #include <sys/ktrace.h>
55 
56 #ifdef TRAPDEBUG
57 volatile int faultdebug = 0;
58 #endif
59 
60 int	cpu_printfataltraps = 0;
61 
62 void	trap (struct trapframe *);
63 
64 const char * const traptypes[]={
65 	"reserved addressing",
66 	"privileged instruction",
67 	"reserved operand",
68 	"breakpoint instruction",
69 	"XFC instruction",
70 	"system call ",
71 	"arithmetic trap",
72 	"asynchronous system trap",
73 	"page table length fault",
74 	"translation violation fault",
75 	"trace trap",
76 	"compatibility mode fault",
77 	"access violation fault",
78 	"",
79 	"",
80 	"KSP invalid",
81 	"",
82 	"kernel debugger trap"
83 };
84 int no_traps = 18;
85 
86 #define USERMODE_P(tf)   ((((tf)->tf_psl) & (PSL_U)) == PSL_U)
87 
88 void
trap(struct trapframe * tf)89 trap(struct trapframe *tf)
90 {
91 	u_int	sig = 0, type = tf->tf_trap, code = 0;
92 	u_int	rv, addr;
93 	bool trapsig = true;
94 	const bool usermode = USERMODE_P(tf);
95 	struct lwp * const l = curlwp;
96 	struct proc * const p = l->l_proc;
97 	struct pcb * const pcb = lwp_getpcb(l);
98 	u_quad_t oticks = 0;
99 	struct vmspace *vm;
100 	struct vm_map *map;
101 	vm_prot_t ftype;
102 	void *onfault = pcb->pcb_onfault;
103 
104 	KASSERT(p != NULL);
105 	curcpu()->ci_data.cpu_ntrap++;
106 	if (usermode) {
107 		type |= T_USER;
108 		oticks = p->p_sticks;
109 		l->l_md.md_utf = tf;
110 	}
111 
112 	type &= ~(T_WRITE|T_PTEFETCH);
113 
114 
115 #ifdef TRAPDEBUG
116 if(tf->tf_trap==7) goto fram;
117 if(faultdebug)printf("Trap: type %lx, code %lx, pc %lx, psl %lx\n",
118 		tf->tf_trap, tf->tf_code, tf->tf_pc, tf->tf_psl);
119 fram:
120 #endif
121 	switch (type) {
122 
123 	default:
124 #ifdef DDB
125 		kdb_trap(tf);
126 #endif
127 		panic("trap: type %x, code %x, pc %x, psl %x",
128 		    (u_int)tf->tf_trap, (u_int)tf->tf_code,
129 		    (u_int)tf->tf_pc, (u_int)tf->tf_psl);
130 
131 	case T_KSPNOTVAL:
132 		panic("%d.%d (%s): KSP invalid %#x@%#x pcb %p fp %#x psl %#x)",
133 		    p->p_pid, l->l_lid, l->l_name ? l->l_name : "??",
134 		    mfpr(PR_KSP), (u_int)tf->tf_pc, pcb,
135 		    (u_int)tf->tf_fp, (u_int)tf->tf_psl);
136 
137 	case T_TRANSFLT|T_USER:
138 	case T_TRANSFLT:
139 		/*
140 		 * BUG! BUG! BUG! BUG! BUG!
141 		 * Due to a hardware bug (at in least KA65x CPUs) a double
142 		 * page table fetch trap will cause a translation fault
143 		 * even if access in the SPT PTE entry specifies 'no access'.
144 		 * In for example section 6.4.2 in VAX Architecture
145 		 * Reference Manual it states that if a page both are invalid
146 		 * and have no access set, a 'access violation fault' occurs.
147 		 * Therefore, we must fall through here...
148 		 */
149 #ifdef nohwbug
150 		panic("translation fault");
151 #endif
152 
153 	case T_PTELEN|T_USER:	/* Page table length exceeded */
154 	case T_ACCFLT|T_USER:
155 		if (tf->tf_code < 0) { /* Check for kernel space */
156 			sig = SIGSEGV;
157 			code = SEGV_ACCERR;
158 			break;
159 		}
160 
161 	case T_PTELEN:
162 #ifndef MULTIPROCESSOR
163 		/*
164 		 * If we referred to an address beyond the end of the system
165 		 * page table, it may be due to a failed CAS
166 		 * restartable-atomic-sequence.  If it is, restart it at the
167 		 * beginning and restart.
168 		 */
169 		{
170 			extern const uint8_t cas32_ras_start[], cas32_ras_end[];
171 			if (tf->tf_code == CASMAGIC
172 			    && tf->tf_pc >= (uintptr_t) cas32_ras_start
173 			    && tf->tf_pc < (uintptr_t) cas32_ras_end) {
174 				tf->tf_pc = (uintptr_t) cas32_ras_start;
175 				trapsig = false;
176 				break;
177 			}
178 		}
179 		/* FALLTHROUGH */
180 #endif
181 	case T_ACCFLT:
182 #ifdef TRAPDEBUG
183 if(faultdebug)printf("trap accflt type %lx, code %lx, pc %lx, psl %lx\n",
184 			tf->tf_trap, tf->tf_code, tf->tf_pc, tf->tf_psl);
185 #endif
186 #ifdef DIAGNOSTIC
187 		if (p == 0)
188 			panic("trap: access fault: addr %lx code %lx",
189 			    tf->tf_pc, tf->tf_code);
190 		if (tf->tf_psl & PSL_IS)
191 			panic("trap: pflt on IS");
192 #endif
193 
194 		/*
195 		 * Page tables are allocated in pmap_enter(). We get
196 		 * info from below if it is a page table fault, but
197 		 * UVM may want to map in pages without faults, so
198 		 * because we must check for PTE pages anyway we don't
199 		 * bother doing it here.
200 		 */
201 		addr = trunc_page(tf->tf_code);
202 		if (!usermode && (tf->tf_code < 0)) {
203 			vm = NULL;
204 			map = kernel_map;
205 
206 		} else {
207 			vm = p->p_vmspace;
208 			map = &vm->vm_map;
209 		}
210 
211 		if (tf->tf_trap & T_WRITE)
212 			ftype = VM_PROT_WRITE;
213 		else
214 			ftype = VM_PROT_READ;
215 
216 		pcb->pcb_onfault = NULL;
217 		rv = uvm_fault(map, addr, ftype);
218 		pcb->pcb_onfault = onfault;
219 		if (rv != 0) {
220 			if (!usermode) {
221 				if (onfault) {
222 					pcb->pcb_onfault = NULL;
223 					tf->tf_pc = (unsigned)onfault;
224 					tf->tf_psl &= ~PSL_FPD;
225 					tf->tf_r0 = rv;
226 					return;
227 				}
228 				printf("r0=%08lx r1=%08lx r2=%08lx r3=%08lx ",
229 				    tf->tf_r0, tf->tf_r1, tf->tf_r2, tf->tf_r3);
230 				printf("r4=%08lx r5=%08lx r6=%08lx r7=%08lx\n",
231 				    tf->tf_r4, tf->tf_r5, tf->tf_r6, tf->tf_r7);
232 				printf(
233 				    "r8=%08lx r9=%08lx r10=%08lx r11=%08lx\n",
234 				    tf->tf_r8, tf->tf_r9, tf->tf_r10,
235 				    tf->tf_r11);
236 				printf("ap=%08lx fp=%08lx sp=%08lx pc=%08lx\n",
237 				    tf->tf_ap, tf->tf_fp, tf->tf_sp, tf->tf_pc);
238 				panic("SEGV in kernel mode: pc %#lx addr %#lx",
239 				    tf->tf_pc, tf->tf_code);
240 			}
241 			switch (rv) {
242 			case ENOMEM:
243 				printf("UVM: pid %d (%s), uid %d killed: "
244 				       "out of swap\n",
245 				       p->p_pid, p->p_comm,
246 				       l->l_cred ?
247 				       kauth_cred_geteuid(l->l_cred) : -1);
248 				sig = SIGKILL;
249 				code = SI_NOINFO;
250 				break;
251 			case EINVAL:
252 				code = BUS_ADRERR;
253 				sig = SIGBUS;
254 				break;
255 			case EACCES:
256 				code = SEGV_ACCERR;
257 				sig = SIGSEGV;
258 				break;
259 			default:
260 				code = SEGV_MAPERR;
261 				sig = SIGSEGV;
262 				break;
263 			}
264 		} else {
265 			trapsig = false;
266 			if (map != kernel_map && addr > 0
267 			    && (void *)addr >= vm->vm_maxsaddr)
268 				uvm_grow(p, addr);
269 		}
270 		break;
271 
272 	case T_BPTFLT|T_USER:
273 		sig = SIGTRAP;
274 		code = TRAP_BRKPT;
275 		break;
276 	case T_TRCTRAP|T_USER:
277 		sig = SIGTRAP;
278 		code = TRAP_TRACE;
279 		tf->tf_psl &= ~PSL_T;
280 		break;
281 
282 	case T_PRIVINFLT|T_USER:
283 		sig = SIGILL;
284 		code = ILL_PRVOPC;
285 		break;
286 	case T_RESADFLT|T_USER:
287 		sig = SIGILL;
288 		code = ILL_ILLADR;
289 		break;
290 	case T_RESOPFLT|T_USER:
291 		sig = SIGILL;
292 		code = ILL_ILLOPC;
293 		break;
294 
295 	case T_XFCFLT|T_USER:
296 		sig = SIGEMT;
297 		break;
298 
299 	case T_ARITHFLT|T_USER:
300 		sig = SIGFPE;
301 		switch (tf->tf_code) {
302 		case ATRP_INTOVF: code = FPE_INTOVF; break;
303 		case ATRP_INTDIV: code = FPE_INTDIV; break;
304 		case ATRP_FLTOVF: code = FPE_FLTOVF; break;
305 		case ATRP_FLTDIV: code = FPE_FLTDIV; break;
306 		case ATRP_FLTUND: code = FPE_FLTUND; break;
307 		case ATRP_DECOVF: code = FPE_INTOVF; break;
308 		case ATRP_FLTSUB: code = FPE_FLTSUB; break;
309 		case AFLT_FLTDIV: code = FPE_FLTDIV; break;
310 		case AFLT_FLTUND: code = FPE_FLTUND; break;
311 		case AFLT_FLTOVF: code = FPE_FLTOVF; break;
312 		default:	  code = FPE_FLTINV; break;
313 		}
314 		break;
315 
316 	case T_ASTFLT|T_USER:
317 		pcb->P0LR = (pcb->P0LR & ~AST_MASK) | AST_PCB;
318 		mtpr(AST_NO,PR_ASTLVL);
319 		trapsig = false;
320 		break;
321 
322 #ifdef DDB
323 	case T_BPTFLT: /* Kernel breakpoint */
324 	case T_KDBTRAP:
325 	case T_KDBTRAP|T_USER:
326 	case T_TRCTRAP:
327 		kdb_trap(tf);
328 		return;
329 #endif
330 	}
331 	if (trapsig) {
332 		ksiginfo_t ksi;
333 		if ((sig == SIGSEGV || sig == SIGILL)
334 		    && cpu_printfataltraps
335 		    && (p->p_slflag & PSL_TRACED) == 0
336 		    && !sigismember(&p->p_sigctx.ps_sigcatch, sig))
337 			printf("pid %d.%d (%s): sig %d: type %lx, code %lx, pc %lx, psl %lx\n",
338 			       p->p_pid, l->l_lid, p->p_comm, sig, tf->tf_trap,
339 			       tf->tf_code, tf->tf_pc, tf->tf_psl);
340 		KSI_INIT_TRAP(&ksi);
341 		ksi.ksi_signo = sig;
342 		ksi.ksi_trap = tf->tf_trap;
343 		ksi.ksi_addr = (void *)tf->tf_code;
344 		ksi.ksi_code = code;
345 
346 		/*
347 		 * Arithmetic exceptions can be of two kinds:
348 		 * - traps (codes 1..7), where pc points to the
349 		 *   next instruction to execute.
350 		 * - faults (codes 8..10), where pc points to the
351 		 *   faulting instruction.
352 		 * In the latter case, we need to advance pc by ourselves
353 		 * to prevent a signal loop.
354 		 *
355 		 * XXX this is gross -- miod
356 		 */
357 		if (type == (T_ARITHFLT | T_USER) && (tf->tf_code & 8))
358 			tf->tf_pc = skip_opcode(tf->tf_pc);
359 
360 		trapsignal(l, &ksi);
361 	}
362 
363 	if (!usermode)
364 		return;
365 
366 	userret(l, tf, oticks);
367 }
368 
369 void
setregs(struct lwp * l,struct exec_package * pack,vaddr_t stack)370 setregs(struct lwp *l, struct exec_package *pack, vaddr_t stack)
371 {
372 	struct trapframe * const tf = l->l_md.md_utf;
373 
374 	tf->tf_pc = pack->ep_entry + 2;
375 	tf->tf_sp = stack;
376 	tf->tf_r6 = stack;				/* for ELF */
377 	tf->tf_r7 = 0;				/* for ELF */
378 	tf->tf_r8 = 0;				/* for ELF */
379 	tf->tf_r9 = l->l_proc->p_psstrp;		/* for ELF */
380 }
381 
382 
383 /*
384  * Start a new LWP
385  */
386 void
startlwp(void * arg)387 startlwp(void *arg)
388 {
389 	ucontext_t * const uc = arg;
390 	lwp_t * const l = curlwp;
391 	int error __diagused;
392 
393 	error = cpu_setmcontext(l, &uc->uc_mcontext, uc->uc_flags);
394 	KASSERT(error == 0);
395 
396 	kmem_free(uc, sizeof(ucontext_t));
397 	/* XXX - profiling spoiled here */
398 	userret(l, l->l_md.md_utf, l->l_proc->p_sticks);
399 }
400