1/* $NetBSD: trap.c,v 1.126 2011/06/07 00:48:30 matt Exp $ */
2
3/*-
4 * Copyright (c) 2000, 2001 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9 * NASA Ames Research Center, by Charles M. Hannum, and by Ross Harvey.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 *    notice, this list of conditions and the following disclaimer in the
18 *    documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32
33/*
34 * Copyright (c) 1999 Christopher G. Demetriou.  All rights reserved.
35 *
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
38 * are met:
39 * 1. Redistributions of source code must retain the above copyright
40 *    notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright
42 *    notice, this list of conditions and the following disclaimer in the
43 *    documentation and/or other materials provided with the distribution.
44 * 3. All advertising materials mentioning features or use of this software
45 *    must display the following acknowledgement:
46 *      This product includes software developed by Christopher G. Demetriou
47 *	for the NetBSD Project.
48 * 4. The name of the author may not be used to endorse or promote products
49 *    derived from this software without specific prior written permission
50 *
51 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
52 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
53 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
54 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
55 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
56 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
57 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
58 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
59 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
60 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
61 */
62
63/*
64 * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University.
65 * All rights reserved.
66 *
67 * Author: Chris G. Demetriou
68 *
69 * Permission to use, copy, modify and distribute this software and
70 * its documentation is hereby granted, provided that both the copyright
71 * notice and this permission notice appear in all copies of the
72 * software, derivative works or modified versions, and any portions
73 * thereof, and that both notices appear in supporting documentation.
74 *
75 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
76 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
77 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
78 *
79 * Carnegie Mellon requests users of this software to return to
80 *
81 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
82 *  School of Computer Science
83 *  Carnegie Mellon University
84 *  Pittsburgh PA 15213-3890
85 *
86 * any improvements or extensions that they make and grant Carnegie the
87 * rights to redistribute these changes.
88 */
89
90#include "opt_fix_unaligned_vax_fp.h"
91#include "opt_ddb.h"
92#include "opt_multiprocessor.h"
93
94#include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
95
96__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.126 2011/06/07 00:48:30 matt Exp $");
97
98#include <sys/param.h>
99#include <sys/systm.h>
100#include <sys/proc.h>
101#include <sys/sa.h>
102#include <sys/savar.h>
103#include <sys/syscall.h>
104#include <sys/buf.h>
105#include <sys/kauth.h>
106#include <sys/kmem.h>
107#include <sys/cpu.h>
108#include <sys/atomic.h>
109
110#include <uvm/uvm_extern.h>
111
112#include <machine/reg.h>
113#include <machine/alpha.h>
114#include <machine/fpu.h>
115#include <machine/rpb.h>
116#ifdef DDB
117#include <machine/db_machdep.h>
118#endif
119#include <alpha/alpha/db_instruction.h>
120#include <machine/userret.h>
121
122static int unaligned_fixup(u_long, u_long, u_long, struct lwp *);
123static int handle_opdec(struct lwp *l, u_long *ucodep);
124static int alpha_ucode_to_ksiginfo(u_long ucode);
125
126/*
127 * Initialize the trap vectors for the current processor.
128 */
129void
130trap_init(void)
131{
132
133	/*
134	 * Point interrupt/exception vectors to our own.
135	 */
136	alpha_pal_wrent(XentInt, ALPHA_KENTRY_INT);
137	alpha_pal_wrent(XentArith, ALPHA_KENTRY_ARITH);
138	alpha_pal_wrent(XentMM, ALPHA_KENTRY_MM);
139	alpha_pal_wrent(XentIF, ALPHA_KENTRY_IF);
140	alpha_pal_wrent(XentUna, ALPHA_KENTRY_UNA);
141	alpha_pal_wrent(XentSys, ALPHA_KENTRY_SYS);
142
143	/*
144	 * Clear pending machine checks and error reports, and enable
145	 * system- and processor-correctable error reporting.
146	 */
147	alpha_pal_wrmces(alpha_pal_rdmces() &
148	    ~(ALPHA_MCES_DSC|ALPHA_MCES_DPC));
149}
150
151static void
152printtrap(const u_long a0, const u_long a1, const u_long a2,
153    const u_long entry, struct trapframe *framep, int isfatal, int user)
154{
155	char ubuf[64];
156	const char *entryname;
157	u_long cpu_id = cpu_number();
158
159	switch (entry) {
160	case ALPHA_KENTRY_INT:
161		entryname = "interrupt";
162		break;
163	case ALPHA_KENTRY_ARITH:
164		entryname = "arithmetic trap";
165		break;
166	case ALPHA_KENTRY_MM:
167		entryname = "memory management fault";
168		break;
169	case ALPHA_KENTRY_IF:
170		entryname = "instruction fault";
171		break;
172	case ALPHA_KENTRY_UNA:
173		entryname = "unaligned access fault";
174		break;
175	case ALPHA_KENTRY_SYS:
176		entryname = "system call";
177		break;
178	default:
179		sprintf(ubuf, "type %lx", entry);
180		entryname = (const char *) ubuf;
181		break;
182	}
183
184	printf("\n");
185	printf("CPU %lu: %s %s trap:\n", cpu_id, isfatal ? "fatal" : "handled",
186	    user ? "user" : "kernel");
187	printf("\n");
188	printf("CPU %lu    trap entry = 0x%lx (%s)\n", cpu_id, entry,
189	    entryname);
190	printf("CPU %lu    a0         = 0x%lx\n", cpu_id, a0);
191	printf("CPU %lu    a1         = 0x%lx\n", cpu_id, a1);
192	printf("CPU %lu    a2         = 0x%lx\n", cpu_id, a2);
193	printf("CPU %lu    pc         = 0x%lx\n", cpu_id,
194	    framep->tf_regs[FRAME_PC]);
195	printf("CPU %lu    ra         = 0x%lx\n", cpu_id,
196	    framep->tf_regs[FRAME_RA]);
197	printf("CPU %lu    pv         = 0x%lx\n", cpu_id,
198	    framep->tf_regs[FRAME_T12]);
199	printf("CPU %lu    curlwp     = %p\n", cpu_id, curlwp);
200	printf("CPU %lu        pid = %d, comm = %s\n", cpu_id,
201	    curproc->p_pid, curproc->p_comm);
202	printf("\n");
203}
204
205/*
206 * Trap is called from locore to handle most types of processor traps.
207 * System calls are broken out for efficiency and ASTs are broken out
208 * to make the code a bit cleaner and more representative of the
209 * Alpha architecture.
210 */
211/*ARGSUSED*/
212void
213trap(const u_long a0, const u_long a1, const u_long a2, const u_long entry,
214    struct trapframe *framep)
215{
216	struct lwp *l;
217	struct proc *p;
218	struct pcb *pcb;
219	vaddr_t onfault;
220	ksiginfo_t ksi;
221	vm_prot_t ftype;
222	uint64_t ucode;
223	int i, user;
224#if defined(DDB)
225	int call_debugger = 1;
226#endif
227
228	curcpu()->ci_data.cpu_ntrap++;
229
230	l = curlwp;
231
232	user = (framep->tf_regs[FRAME_PS] & ALPHA_PSL_USERMODE) != 0;
233	if (user) {
234		l->l_md.md_tf = framep;
235		p = l->l_proc;
236		(void)memset(&ksi, 0, sizeof(ksi));
237		LWP_CACHE_CREDS(l, p);
238	} else {
239		p = NULL;
240	}
241
242	switch (entry) {
243	case ALPHA_KENTRY_UNA:
244		/*
245		 * If user-land, do whatever fixups, printing, and
246		 * signalling is appropriate (based on system-wide
247		 * and per-process unaligned-access-handling flags).
248		 */
249		if (user) {
250			i = unaligned_fixup(a0, a1, a2, l);
251			if (i == 0)
252				goto out;
253
254			KSI_INIT_TRAP(&ksi);
255			ksi.ksi_signo = i;
256			ksi.ksi_code = BUS_ADRALN;
257			ksi.ksi_addr = (void *)a0;		/* VA */
258			ksi.ksi_trap = BUS_ADRALN;      /* XXX appropriate? */
259			break;
260		}
261
262		/*
263		 * Unaligned access from kernel mode is always an error,
264		 * EVEN IF A COPY FAULT HANDLER IS SET!
265		 *
266		 * It's an error if a copy fault handler is set because
267		 * the various routines which do user-initiated copies
268		 * do so in a memcpy-like manner.  In other words, the
269		 * kernel never assumes that pointers provided by the
270		 * user are properly aligned, and so if the kernel
271		 * does cause an unaligned access it's a kernel bug.
272		 */
273		goto dopanic;
274
275	case ALPHA_KENTRY_ARITH:
276		/*
277		 * Resolve trap shadows, interpret FP ops requiring infinities,
278		 * NaNs, or denorms, and maintain FPCR corrections.
279		 */
280		if (user) {
281			i = alpha_fp_complete(a0, a1, l, &ucode);
282			if (i == 0)
283				goto out;
284			KSI_INIT_TRAP(&ksi);
285			ksi.ksi_signo = i;
286			if (i == SIGSEGV)
287				ksi.ksi_code = SEGV_MAPERR; /* just pick one */
288			else {
289				ksi.ksi_code = alpha_ucode_to_ksiginfo(ucode);
290				ksi.ksi_addr =
291					(void *)l->l_md.md_tf->tf_regs[FRAME_PC];
292				ksi.ksi_trap = (int)ucode;
293			}
294			break;
295		}
296
297		/* Always fatal in kernel.  Should never happen. */
298		goto dopanic;
299
300	case ALPHA_KENTRY_IF:
301		/*
302		 * These are always fatal in kernel, and should never
303		 * happen.  (Debugger entry is handled in XentIF.)
304		 */
305		if (user == 0) {
306#if defined(DDB)
307			/*
308			 * ...unless a debugger is configured.  It will
309			 * inform us if the trap was handled.
310			 */
311			if (alpha_debug(a0, a1, a2, entry, framep))
312				goto out;
313
314			/*
315			 * Debugger did NOT handle the trap, don't
316			 * call the debugger again!
317			 */
318			call_debugger = 0;
319#endif
320			goto dopanic;
321		}
322		i = 0;
323		switch (a0) {
324		case ALPHA_IF_CODE_GENTRAP:
325			if (framep->tf_regs[FRAME_A0] == -2) { /* weird! */
326				KSI_INIT_TRAP(&ksi);
327				ksi.ksi_signo = SIGFPE;
328				ksi.ksi_code =  alpha_ucode_to_ksiginfo(ucode);
329				ksi.ksi_addr =
330					(void *)l->l_md.md_tf->tf_regs[FRAME_PC];
331				ksi.ksi_trap =  a0;	/* exception summary */
332				break;
333			}
334			/* FALLTHROUGH */
335		case ALPHA_IF_CODE_BPT:
336		case ALPHA_IF_CODE_BUGCHK:
337			KSI_INIT_TRAP(&ksi);
338			ksi.ksi_signo = SIGTRAP;
339			ksi.ksi_code = TRAP_BRKPT;
340			ksi.ksi_addr = (void *)l->l_md.md_tf->tf_regs[FRAME_PC];
341			ksi.ksi_trap = a0;		/* trap type */
342			break;
343
344		case ALPHA_IF_CODE_OPDEC:
345			i = handle_opdec(l, &ucode);
346			KSI_INIT_TRAP(&ksi);
347			if (i == 0)
348				goto out;
349			else if (i == SIGSEGV)
350				ksi.ksi_code = SEGV_MAPERR;
351			else if (i == SIGILL)
352				ksi.ksi_code = ILL_ILLOPC;
353			ksi.ksi_signo = i;
354			ksi.ksi_addr =
355				(void *)l->l_md.md_tf->tf_regs[FRAME_PC];
356			ksi.ksi_trap = (int)ucode;
357			break;
358
359		case ALPHA_IF_CODE_FEN:
360			fpu_load();
361			goto out;
362
363		default:
364			printf("trap: unknown IF type 0x%lx\n", a0);
365			goto dopanic;
366		}
367		break;
368
369	case ALPHA_KENTRY_MM:
370		pcb = lwp_getpcb(l);
371		onfault = pcb->pcb_onfault;
372
373		switch (a1) {
374		case ALPHA_MMCSR_FOR:
375		case ALPHA_MMCSR_FOE:
376		case ALPHA_MMCSR_FOW:
377			if (pmap_emulate_reference(l, a0, user, a1)) {
378				ftype = VM_PROT_EXECUTE;
379				goto do_fault;
380			}
381			goto out;
382
383		case ALPHA_MMCSR_INVALTRANS:
384		case ALPHA_MMCSR_ACCESS:
385	    	{
386			vaddr_t va;
387			struct vmspace *vm = NULL;
388			struct vm_map *map;
389			int rv;
390
391			switch (a2) {
392			case -1:		/* instruction fetch fault */
393				ftype = VM_PROT_EXECUTE;
394				break;
395			case 0:			/* load instruction */
396				ftype = VM_PROT_READ;
397				break;
398			case 1:			/* store instruction */
399				ftype = VM_PROT_WRITE;
400				break;
401			default:
402#ifdef DIAGNOSTIC
403				panic("trap: bad fault type");
404#else
405				ftype = VM_PROT_NONE;
406				break;
407#endif
408			}
409
410			if (user) {
411				if (l->l_flag & LW_SA) {
412					l->l_savp->savp_faultaddr = (vaddr_t)a0;
413					l->l_pflag |= LP_SA_PAGEFAULT;
414				}
415			} else {
416				struct cpu_info *ci = curcpu();
417
418				if (l == NULL) {
419					/*
420					 * If there is no current process,
421					 * it can be nothing but a fatal
422					 * error (i.e. memory in this case
423					 * must be wired).
424					 */
425					goto dopanic;
426				}
427
428				/*
429				 * If it was caused by fuswintr or suswintr,
430				 * just punt.  Note that we check the faulting
431				 * address against the address accessed by
432				 * [fs]uswintr, in case another fault happens
433				 * when they are running.
434				 */
435
436				if (onfault == (vaddr_t)fswintrberr &&
437				    pcb->pcb_accessaddr == a0) {
438					framep->tf_regs[FRAME_PC] = onfault;
439					pcb->pcb_onfault = 0;
440					goto out;
441				}
442
443				/*
444				 * If we're in interrupt context at this
445				 * point, this is an error.
446				 */
447				if (ci->ci_intrdepth != 0)
448					goto dopanic;
449			}
450
451			/*
452			 * It is only a kernel address space fault iff:
453			 *	1. !user and
454			 *	2. pcb_onfault not set or
455			 *	3. pcb_onfault set but kernel space data fault
456			 * The last can occur during an exec() copyin where the
457			 * argument space is lazy-allocated.
458			 */
459do_fault:
460			pcb = lwp_getpcb(l);
461			if (user == 0 && (a0 >= VM_MIN_KERNEL_ADDRESS ||
462					  onfault == 0))
463				map = kernel_map;
464			else {
465				vm = l->l_proc->p_vmspace;
466				map = &vm->vm_map;
467			}
468
469			va = trunc_page((vaddr_t)a0);
470			pcb->pcb_onfault = 0;
471			rv = uvm_fault(map, va, ftype);
472			pcb->pcb_onfault = onfault;
473
474			/*
475			 * If this was a stack access we keep track of the
476			 * maximum accessed stack size.  Also, if vm_fault
477			 * gets a protection failure it is due to accessing
478			 * the stack region outside the current limit and
479			 * we need to reflect that as an access error.
480			 */
481			if (map != kernel_map &&
482			    (void *)va >= vm->vm_maxsaddr &&
483			    va < USRSTACK) {
484				if (rv == 0)
485					uvm_grow(l->l_proc, va);
486				else if (rv == EACCES &&
487					   ftype != VM_PROT_EXECUTE)
488					rv = EFAULT;
489			}
490			if (rv == 0) {
491				if (user)
492					l->l_pflag &= ~LP_SA_PAGEFAULT;
493				goto out;
494			}
495
496			if (user == 0) {
497				/* Check for copyin/copyout fault */
498				if (onfault != 0) {
499					framep->tf_regs[FRAME_PC] = onfault;
500					framep->tf_regs[FRAME_V0] = rv;
501					goto out;
502				}
503				goto dopanic;
504			}
505			KSI_INIT_TRAP(&ksi);
506			ksi.ksi_addr = (void *)a0;
507			ksi.ksi_trap = a1; /* MMCSR VALUE */
508			if (rv == ENOMEM) {
509				printf("UVM: pid %d (%s), uid %d killed: "
510				    "out of swap\n", l->l_proc->p_pid,
511				    l->l_proc->p_comm,
512				    l->l_cred ?
513				    kauth_cred_geteuid(l->l_cred) : -1);
514				ksi.ksi_signo = SIGKILL;
515			} else
516				ksi.ksi_signo = SIGSEGV;
517			if (rv == EACCES)
518				ksi.ksi_code = SEGV_ACCERR;
519			else
520				ksi.ksi_code = SEGV_MAPERR;
521			l->l_pflag &= ~LP_SA_PAGEFAULT;
522			break;
523		    }
524
525		default:
526			printf("trap: unknown MMCSR value 0x%lx\n", a1);
527			goto dopanic;
528		}
529		break;
530
531	default:
532		goto dopanic;
533	}
534
535#ifdef DEBUG
536	printtrap(a0, a1, a2, entry, framep, 1, user);
537#endif
538	(*p->p_emul->e_trapsignal)(l, &ksi);
539out:
540	if (user)
541		userret(l);
542	return;
543
544dopanic:
545	printtrap(a0, a1, a2, entry, framep, 1, user);
546
547	/* XXX dump registers */
548
549#if defined(DDB)
550	if (call_debugger && alpha_debug(a0, a1, a2, entry, framep)) {
551		/*
552		 * The debugger has handled the trap; just return.
553		 */
554		goto out;
555	}
556#endif
557
558	panic("trap");
559}
560
561/*
562 * Process an asynchronous software trap.
563 * This is relatively easy.
564 */
565void
566ast(struct trapframe *framep)
567{
568	struct lwp *l;
569
570	/*
571	 * We may not have a current process to do AST processing
572	 * on.  This happens on multiprocessor systems in which
573	 * at least one CPU simply has no current process to run,
574	 * but roundrobin() (called via hardclock()) kicks us to
575	 * attempt to preempt the process running on our CPU.
576	 */
577	l = curlwp;
578	if (l == NULL)
579		return;
580
581	//curcpu()->ci_data.cpu_nast++;
582	l->l_md.md_tf = framep;
583
584	if (l->l_pflag & LP_OWEUPC) {
585		l->l_pflag &= ~LP_OWEUPC;
586		ADDUPROF(l);
587	}
588
589	if (curcpu()->ci_want_resched) {
590		/*
591		 * We are being preempted.
592		 */
593		preempt();
594	}
595
596	userret(l);
597}
598
599/*
600 * Unaligned access handler.  It's not clear that this can get much slower...
601 *
602 */
603static const int reg_to_framereg[32] = {
604	FRAME_V0,	FRAME_T0,	FRAME_T1,	FRAME_T2,
605	FRAME_T3,	FRAME_T4,	FRAME_T5,	FRAME_T6,
606	FRAME_T7,	FRAME_S0,	FRAME_S1,	FRAME_S2,
607	FRAME_S3,	FRAME_S4,	FRAME_S5,	FRAME_S6,
608	FRAME_A0,	FRAME_A1,	FRAME_A2,	FRAME_A3,
609	FRAME_A4,	FRAME_A5,	FRAME_T8,	FRAME_T9,
610	FRAME_T10,	FRAME_T11,	FRAME_RA,	FRAME_T12,
611	FRAME_AT,	FRAME_GP,	FRAME_SP,	-1,
612};
613
614#define	irp(l, reg)							\
615	((reg_to_framereg[(reg)] == -1) ? NULL :			\
616	    &(l)->l_md.md_tf->tf_regs[reg_to_framereg[(reg)]])
617
618#define	frp(l, reg)							\
619	(&pcb->pcb_fp.fpr_regs[(reg)])
620
621#define	unaligned_load(storage, ptrf, mod)				\
622	if (copyin((void *)va, &(storage), sizeof (storage)) != 0)	\
623		break;							\
624	signo = 0;							\
625	if ((regptr = ptrf(l, reg)) != NULL)				\
626		*regptr = mod (storage);
627
628#define	unaligned_store(storage, ptrf, mod)				\
629	if ((regptr = ptrf(l, reg)) != NULL)				\
630		(storage) = mod (*regptr);				\
631	else								\
632		(storage) = 0;						\
633	if (copyout(&(storage), (void *)va, sizeof (storage)) != 0)	\
634		break;							\
635	signo = 0;
636
637#define	unaligned_load_integer(storage)					\
638	unaligned_load(storage, irp, )
639
640#define	unaligned_store_integer(storage)				\
641	unaligned_store(storage, irp, )
642
643#define	unaligned_load_floating(storage, mod) do {			\
644	struct pcb * const pcb = lwp_getpcb(l);				\
645	fpu_save();							\
646	unaligned_load(storage, frp, mod)				\
647} while (/*CONSTCOND*/0)
648
649#define	unaligned_store_floating(storage, mod) do {			\
650	struct pcb * const pcb = lwp_getpcb(l);				\
651	fpu_save();							\
652	unaligned_store(storage, frp, mod)				\
653} while (/*CONSTCOND*/0)
654
655static unsigned long
656Sfloat_to_reg(u_int s)
657{
658	unsigned long sign, expn, frac;
659	unsigned long result;
660
661	sign = (s & 0x80000000) >> 31;
662	expn = (s & 0x7f800000) >> 23;
663	frac = (s & 0x007fffff) >>  0;
664
665	/* map exponent part, as appropriate. */
666	if (expn == 0xff)
667		expn = 0x7ff;
668	else if ((expn & 0x80) != 0)
669		expn = (0x400 | (expn & ~0x80));
670	else if ((expn & 0x80) == 0 && expn != 0)
671		expn = (0x380 | (expn & ~0x80));
672
673	result = (sign << 63) | (expn << 52) | (frac << 29);
674	return (result);
675}
676
677static unsigned int
678reg_to_Sfloat(u_long r)
679{
680	unsigned long sign, expn, frac;
681	unsigned int result;
682
683	sign = (r & 0x8000000000000000) >> 63;
684	expn = (r & 0x7ff0000000000000) >> 52;
685	frac = (r & 0x000fffffe0000000) >> 29;
686
687	/* map exponent part, as appropriate. */
688	expn = (expn & 0x7f) | ((expn & 0x400) != 0 ? 0x80 : 0x00);
689
690	result = (sign << 31) | (expn << 23) | (frac << 0);
691	return (result);
692}
693
694/*
695 * Conversion of T floating datums to and from register format
696 * requires no bit reordering whatsoever.
697 */
698static unsigned long
699Tfloat_reg_cvt(u_long input)
700{
701
702	return (input);
703}
704
705#ifdef FIX_UNALIGNED_VAX_FP
706static unsigned long
707Ffloat_to_reg(u_int f)
708{
709	unsigned long sign, expn, frlo, frhi;
710	unsigned long result;
711
712	sign = (f & 0x00008000) >> 15;
713	expn = (f & 0x00007f80) >>  7;
714	frhi = (f & 0x0000007f) >>  0;
715	frlo = (f & 0xffff0000) >> 16;
716
717	/* map exponent part, as appropriate. */
718	if ((expn & 0x80) != 0)
719		expn = (0x400 | (expn & ~0x80));
720	else if ((expn & 0x80) == 0 && expn != 0)
721		expn = (0x380 | (expn & ~0x80));
722
723	result = (sign << 63) | (expn << 52) | (frhi << 45) | (frlo << 29);
724	return (result);
725}
726
727static unsigned int
728reg_to_Ffloat(u_long r)
729{
730	unsigned long sign, expn, frhi, frlo;
731	unsigned int result;
732
733	sign = (r & 0x8000000000000000) >> 63;
734	expn = (r & 0x7ff0000000000000) >> 52;
735	frhi = (r & 0x000fe00000000000) >> 45;
736	frlo = (r & 0x00001fffe0000000) >> 29;
737
738	/* map exponent part, as appropriate. */
739	expn = (expn & 0x7f) | ((expn & 0x400) != 0 ? 0x80 : 0x00);
740
741	result = (sign << 15) | (expn << 7) | (frhi << 0) | (frlo << 16);
742	return (result);
743}
744
745/*
746 * Conversion of G floating datums to and from register format is
747 * symmetrical.  Just swap shorts in the quad...
748 */
749static unsigned long
750Gfloat_reg_cvt(u_long input)
751{
752	unsigned long a, b, c, d;
753	unsigned long result;
754
755	a = (input & 0x000000000000ffff) >> 0;
756	b = (input & 0x00000000ffff0000) >> 16;
757	c = (input & 0x0000ffff00000000) >> 32;
758	d = (input & 0xffff000000000000) >> 48;
759
760	result = (a << 48) | (b << 32) | (c << 16) | (d << 0);
761	return (result);
762}
763#endif /* FIX_UNALIGNED_VAX_FP */
764
765struct unaligned_fixup_data {
766	const char *type;	/* opcode name */
767	int fixable;		/* fixable, 0 if fixup not supported */
768	int size;		/* size, 0 if unknown */
769};
770
771#define	UNKNOWN()	{ "0x%lx", 0, 0 }
772#define	FIX_LD(n,s)	{ n, 1, s }
773#define	FIX_ST(n,s)	{ n, 1, s }
774#define	NOFIX_LD(n,s)	{ n, 0, s }
775#define	NOFIX_ST(n,s)	{ n, 0, s }
776
777int
778unaligned_fixup(u_long va, u_long opcode, u_long reg, struct lwp *l)
779{
780	static const struct unaligned_fixup_data tab_unknown[1] = {
781		UNKNOWN(),
782	};
783	static const struct unaligned_fixup_data tab_0c[0x02] = {
784		FIX_LD("ldwu", 2),	FIX_ST("stw", 2),
785	};
786	static const struct unaligned_fixup_data tab_20[0x10] = {
787#ifdef FIX_UNALIGNED_VAX_FP
788		FIX_LD("ldf", 4),	FIX_LD("ldg", 8),
789#else
790		NOFIX_LD("ldf", 4),	NOFIX_LD("ldg", 8),
791#endif
792		FIX_LD("lds", 4),	FIX_LD("ldt", 8),
793#ifdef FIX_UNALIGNED_VAX_FP
794		FIX_ST("stf", 4),	FIX_ST("stg", 8),
795#else
796		NOFIX_ST("stf", 4),	NOFIX_ST("stg", 8),
797#endif
798		FIX_ST("sts", 4),	FIX_ST("stt", 8),
799		FIX_LD("ldl", 4),	FIX_LD("ldq", 8),
800		NOFIX_LD("ldl_c", 4),	NOFIX_LD("ldq_c", 8),
801		FIX_ST("stl", 4),	FIX_ST("stq", 8),
802		NOFIX_ST("stl_c", 4),	NOFIX_ST("stq_c", 8),
803	};
804	const struct unaligned_fixup_data *selected_tab;
805	int doprint, dofix, dosigbus, signo;
806	unsigned long *regptr, longdata;
807	int intdata;		/* signed to get extension when storing */
808	uint16_t worddata;	/* unsigned to _avoid_ extension */
809
810	/*
811	 * Read USP into frame in case it's the register to be modified.
812	 * This keeps us from having to check for it in lots of places
813	 * later.
814	 */
815	l->l_md.md_tf->tf_regs[FRAME_SP] = alpha_pal_rdusp();
816
817	/*
818	 * Figure out what actions to take.
819	 *
820	 * XXX In the future, this should have a per-process component
821	 * as well.
822	 */
823	doprint = alpha_unaligned_print;
824	dofix = alpha_unaligned_fix;
825	dosigbus = alpha_unaligned_sigbus;
826
827	/*
828	 * Find out which opcode it is.  Arrange to have the opcode
829	 * printed if it's an unknown opcode.
830	 */
831	if (opcode >= 0x0c && opcode <= 0x0d)
832		selected_tab = &tab_0c[opcode - 0x0c];
833	else if (opcode >= 0x20 && opcode <= 0x2f)
834		selected_tab = &tab_20[opcode - 0x20];
835	else
836		selected_tab = tab_unknown;
837
838	/*
839	 * If we're supposed to be noisy, squawk now.
840	 */
841	if (doprint) {
842		uprintf(
843		"pid %d (%s): unaligned access: "
844		"va=0x%lx pc=0x%lx ra=0x%lx sp=0x%lx op=",
845		    l->l_proc->p_pid, l->l_proc->p_comm, va,
846		    l->l_md.md_tf->tf_regs[FRAME_PC] - 4,
847		    l->l_md.md_tf->tf_regs[FRAME_RA],
848		    l->l_md.md_tf->tf_regs[FRAME_SP]);
849		uprintf(selected_tab->type,opcode);
850		uprintf("\n");
851	}
852
853	/*
854	 * If we should try to fix it and know how, give it a shot.
855	 *
856	 * We never allow bad data to be unknowingly used by the user process.
857	 * That is, if we can't access the address needed to fix up the trap,
858	 * we cause a SIGSEGV rather than letting the user process go on
859	 * without warning.
860	 *
861	 * If we're trying to do a fixup, we assume that things
862	 * will be botched.  If everything works out OK,
863	 * unaligned_{load,store}_* clears the signal flag.
864	 */
865	signo = SIGSEGV;
866	if (dofix && selected_tab->fixable) {
867		switch (opcode) {
868		case 0x0c:			/* ldwu */
869			/* XXX ONLY WORKS ON LITTLE-ENDIAN ALPHA */
870			unaligned_load_integer(worddata);
871			break;
872
873		case 0x0d:			/* stw */
874			/* XXX ONLY WORKS ON LITTLE-ENDIAN ALPHA */
875			unaligned_store_integer(worddata);
876			break;
877
878#ifdef FIX_UNALIGNED_VAX_FP
879		case 0x20:			/* ldf */
880			unaligned_load_floating(intdata, Ffloat_to_reg);
881			break;
882
883		case 0x21:			/* ldg */
884			unaligned_load_floating(longdata, Gfloat_reg_cvt);
885			break;
886#endif
887
888		case 0x22:			/* lds */
889			unaligned_load_floating(intdata, Sfloat_to_reg);
890			break;
891
892		case 0x23:			/* ldt */
893			unaligned_load_floating(longdata, Tfloat_reg_cvt);
894			break;
895
896#ifdef FIX_UNALIGNED_VAX_FP
897		case 0x24:			/* stf */
898			unaligned_store_floating(intdata, reg_to_Ffloat);
899			break;
900
901		case 0x25:			/* stg */
902			unaligned_store_floating(longdata, Gfloat_reg_cvt);
903			break;
904#endif
905
906		case 0x26:			/* sts */
907			unaligned_store_floating(intdata, reg_to_Sfloat);
908			break;
909
910		case 0x27:			/* stt */
911			unaligned_store_floating(longdata, Tfloat_reg_cvt);
912			break;
913
914		case 0x28:			/* ldl */
915			unaligned_load_integer(intdata);
916			break;
917
918		case 0x29:			/* ldq */
919			unaligned_load_integer(longdata);
920			break;
921
922		case 0x2c:			/* stl */
923			unaligned_store_integer(intdata);
924			break;
925
926		case 0x2d:			/* stq */
927			unaligned_store_integer(longdata);
928			break;
929
930#ifdef DIAGNOSTIC
931		default:
932			panic("unaligned_fixup: can't get here");
933#endif
934		}
935	}
936
937	/*
938	 * Force SIGBUS if requested.
939	 */
940	if (dosigbus)
941		signo = SIGBUS;
942
943	/*
944	 * Write back USP.
945	 */
946	alpha_pal_wrusp(l->l_md.md_tf->tf_regs[FRAME_SP]);
947
948	return (signo);
949}
950
951/*
952 * Reserved/unimplemented instruction (opDec fault) handler
953 *
954 * Argument is the process that caused it.  No useful information
955 * is passed to the trap handler other than the fault type.  The
956 * address of the instruction that caused the fault is 4 less than
957 * the PC stored in the trap frame.
958 *
959 * If the instruction is emulated successfully, this function returns 0.
960 * Otherwise, this function returns the signal to deliver to the process,
961 * and fills in *ucodep with the code to be delivered.
962 */
963int
964handle_opdec(struct lwp *l, u_long *ucodep)
965{
966	alpha_instruction inst;
967	register_t *regptr, memaddr;
968	uint64_t inst_pc;
969	int sig;
970
971	/*
972	 * Read USP into frame in case it's going to be used or modified.
973	 * This keeps us from having to check for it in lots of places
974	 * later.
975	 */
976	l->l_md.md_tf->tf_regs[FRAME_SP] = alpha_pal_rdusp();
977
978	inst_pc = memaddr = l->l_md.md_tf->tf_regs[FRAME_PC] - 4;
979	if (copyin((void *)inst_pc, &inst, sizeof (inst)) != 0) {
980		/*
981		 * really, this should never happen, but in case it
982		 * does we handle it.
983		 */
984		printf("WARNING: handle_opdec() couldn't fetch instruction\n");
985		goto sigsegv;
986	}
987
988	switch (inst.generic_format.opcode) {
989	case op_ldbu:
990	case op_ldwu:
991	case op_stw:
992	case op_stb:
993		regptr = irp(l, inst.mem_format.rb);
994		if (regptr != NULL)
995			memaddr = *regptr;
996		else
997			memaddr = 0;
998		memaddr += inst.mem_format.displacement;
999
1000		regptr = irp(l, inst.mem_format.ra);
1001
1002		if (inst.mem_format.opcode == op_ldwu ||
1003		    inst.mem_format.opcode == op_stw) {
1004			if (memaddr & 0x01) {
1005				sig = unaligned_fixup(memaddr,
1006				    inst.mem_format.opcode,
1007				    inst.mem_format.ra, l);
1008				if (sig)
1009					goto unaligned_fixup_sig;
1010				break;
1011			}
1012		}
1013
1014		if (inst.mem_format.opcode == op_ldbu) {
1015			uint8_t b;
1016
1017			/* XXX ONLY WORKS ON LITTLE-ENDIAN ALPHA */
1018			if (copyin((void *)memaddr, &b, sizeof (b)) != 0)
1019				goto sigsegv;
1020			if (regptr != NULL)
1021				*regptr = b;
1022		} else if (inst.mem_format.opcode == op_ldwu) {
1023			uint16_t w;
1024
1025			/* XXX ONLY WORKS ON LITTLE-ENDIAN ALPHA */
1026			if (copyin((void *)memaddr, &w, sizeof (w)) != 0)
1027				goto sigsegv;
1028			if (regptr != NULL)
1029				*regptr = w;
1030		} else if (inst.mem_format.opcode == op_stw) {
1031			uint16_t w;
1032
1033			/* XXX ONLY WORKS ON LITTLE-ENDIAN ALPHA */
1034			w = (regptr != NULL) ? *regptr : 0;
1035			if (copyout(&w, (void *)memaddr, sizeof (w)) != 0)
1036				goto sigsegv;
1037		} else if (inst.mem_format.opcode == op_stb) {
1038			uint8_t b;
1039
1040			/* XXX ONLY WORKS ON LITTLE-ENDIAN ALPHA */
1041			b = (regptr != NULL) ? *regptr : 0;
1042			if (copyout(&b, (void *)memaddr, sizeof (b)) != 0)
1043				goto sigsegv;
1044		}
1045		break;
1046
1047	case op_intmisc:
1048		if (inst.operate_generic_format.function == op_sextb &&
1049		    inst.operate_generic_format.ra == 31) {
1050			int8_t b;
1051
1052			if (inst.operate_generic_format.is_lit) {
1053				b = inst.operate_lit_format.literal;
1054			} else {
1055				if (inst.operate_reg_format.sbz != 0)
1056					goto sigill;
1057				regptr = irp(l, inst.operate_reg_format.rb);
1058				b = (regptr != NULL) ? *regptr : 0;
1059			}
1060
1061			regptr = irp(l, inst.operate_generic_format.rc);
1062			if (regptr != NULL)
1063				*regptr = b;
1064			break;
1065		}
1066		if (inst.operate_generic_format.function == op_sextw &&
1067		    inst.operate_generic_format.ra == 31) {
1068			int16_t w;
1069
1070			if (inst.operate_generic_format.is_lit) {
1071				w = inst.operate_lit_format.literal;
1072			} else {
1073				if (inst.operate_reg_format.sbz != 0)
1074					goto sigill;
1075				regptr = irp(l, inst.operate_reg_format.rb);
1076				w = (regptr != NULL) ? *regptr : 0;
1077			}
1078
1079			regptr = irp(l, inst.operate_generic_format.rc);
1080			if (regptr != NULL)
1081				*regptr = w;
1082			break;
1083		}
1084		goto sigill;
1085
1086	default:
1087		goto sigill;
1088	}
1089
1090	/*
1091	 * Write back USP.  Note that in the error cases below,
1092	 * nothing will have been successfully modified so we don't
1093	 * have to write it out.
1094	 */
1095	alpha_pal_wrusp(l->l_md.md_tf->tf_regs[FRAME_SP]);
1096
1097	return (0);
1098
1099sigill:
1100	*ucodep = ALPHA_IF_CODE_OPDEC;			/* trap type */
1101	return (SIGILL);
1102
1103sigsegv:
1104	sig = SIGSEGV;
1105	l->l_md.md_tf->tf_regs[FRAME_PC] = inst_pc;	/* re-run instr. */
1106unaligned_fixup_sig:
1107	*ucodep = memaddr;				/* faulting address */
1108	return (sig);
1109}
1110
1111/* map alpha fp flags to ksiginfo fp codes */
1112static int
1113alpha_ucode_to_ksiginfo(u_long ucode)
1114{
1115	long i;
1116
1117	static const int alpha_ksiginfo_table[] = { FPE_FLTINV,
1118					     FPE_FLTDIV,
1119					     FPE_FLTOVF,
1120					     FPE_FLTUND,
1121					     FPE_FLTRES,
1122					     FPE_INTOVF };
1123
1124	for(i=0;i < sizeof(alpha_ksiginfo_table)/sizeof(int); i++) {
1125		if (ucode & (1 << i))
1126			return (alpha_ksiginfo_table[i]);
1127	}
1128	/* punt if the flags weren't set */
1129	return (0);
1130}
1131
1132/*
1133 * Start a new LWP
1134 */
1135void
1136startlwp(void *arg)
1137{
1138	ucontext_t *uc = arg;
1139	lwp_t *l = curlwp;
1140	int error;
1141
1142	error = cpu_setmcontext(l, &uc->uc_mcontext, uc->uc_flags);
1143	KASSERT(error == 0);
1144
1145	kmem_free(uc, sizeof(ucontext_t));
1146	userret(l);
1147}
1148
1149/*
1150 * XXX This is a terrible name.
1151 */
1152void
1153upcallret(struct lwp *l)
1154{
1155	KERNEL_UNLOCK_LAST(l);
1156
1157	userret(l);
1158}
1159