trap.c revision 271113
1/*-
2 * Copyright (C) 1995, 1996 Wolfgang Solfrank.
3 * Copyright (C) 1995, 1996 TooLs GmbH.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 *    must display the following acknowledgement:
16 *	This product includes software developed by TooLs GmbH.
17 * 4. The name of TooLs GmbH may not be used to endorse or promote products
18 *    derived from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 *
31 * $NetBSD: trap.c,v 1.58 2002/03/04 04:07:35 dbj Exp $
32 */
33
34#include <sys/cdefs.h>
35__FBSDID("$FreeBSD: stable/10/sys/powerpc/aim/trap.c 271113 2014-09-04 18:24:47Z nwhitehorn $");
36
37#include "opt_kdtrace.h"
38
39#include <sys/param.h>
40#include <sys/kdb.h>
41#include <sys/proc.h>
42#include <sys/ktr.h>
43#include <sys/lock.h>
44#include <sys/mutex.h>
45#include <sys/pioctl.h>
46#include <sys/ptrace.h>
47#include <sys/reboot.h>
48#include <sys/syscall.h>
49#include <sys/sysent.h>
50#include <sys/systm.h>
51#include <sys/uio.h>
52#include <sys/signalvar.h>
53#include <sys/vmmeter.h>
54
55#include <security/audit/audit.h>
56
57#include <vm/vm.h>
58#include <vm/pmap.h>
59#include <vm/vm_extern.h>
60#include <vm/vm_param.h>
61#include <vm/vm_kern.h>
62#include <vm/vm_map.h>
63#include <vm/vm_page.h>
64
65#include <machine/_inttypes.h>
66#include <machine/altivec.h>
67#include <machine/cpu.h>
68#include <machine/db_machdep.h>
69#include <machine/fpu.h>
70#include <machine/frame.h>
71#include <machine/pcb.h>
72#include <machine/pmap.h>
73#include <machine/psl.h>
74#include <machine/trap.h>
75#include <machine/spr.h>
76#include <machine/sr.h>
77
78static void	trap_fatal(struct trapframe *frame);
79static void	printtrap(u_int vector, struct trapframe *frame, int isfatal,
80		    int user);
81static int	trap_pfault(struct trapframe *frame, int user);
82static int	fix_unaligned(struct thread *td, struct trapframe *frame);
83static int	handle_onfault(struct trapframe *frame);
84static void	syscall(struct trapframe *frame);
85
86#ifdef __powerpc64__
87       void	handle_kernel_slb_spill(int, register_t, register_t);
88static int	handle_user_slb_spill(pmap_t pm, vm_offset_t addr);
89extern int	n_slbs;
90#endif
91
92struct powerpc_exception {
93	u_int	vector;
94	char	*name;
95};
96
97#ifdef KDTRACE_HOOKS
98#include <sys/dtrace_bsd.h>
99
100int (*dtrace_invop_jump_addr)(struct trapframe *);
101#endif
102
103static struct powerpc_exception powerpc_exceptions[] = {
104	{ 0x0100, "system reset" },
105	{ 0x0200, "machine check" },
106	{ 0x0300, "data storage interrupt" },
107	{ 0x0380, "data segment exception" },
108	{ 0x0400, "instruction storage interrupt" },
109	{ 0x0480, "instruction segment exception" },
110	{ 0x0500, "external interrupt" },
111	{ 0x0600, "alignment" },
112	{ 0x0700, "program" },
113	{ 0x0800, "floating-point unavailable" },
114	{ 0x0900, "decrementer" },
115	{ 0x0c00, "system call" },
116	{ 0x0d00, "trace" },
117	{ 0x0e00, "floating-point assist" },
118	{ 0x0f00, "performance monitoring" },
119	{ 0x0f20, "altivec unavailable" },
120	{ 0x1000, "instruction tlb miss" },
121	{ 0x1100, "data load tlb miss" },
122	{ 0x1200, "data store tlb miss" },
123	{ 0x1300, "instruction breakpoint" },
124	{ 0x1400, "system management" },
125	{ 0x1600, "altivec assist" },
126	{ 0x1700, "thermal management" },
127	{ 0x2000, "run mode/trace" },
128	{ 0x3000, NULL }
129};
130
131static const char *
132trapname(u_int vector)
133{
134	struct	powerpc_exception *pe;
135
136	for (pe = powerpc_exceptions; pe->vector != 0x3000; pe++) {
137		if (pe->vector == vector)
138			return (pe->name);
139	}
140
141	return ("unknown");
142}
143
144void
145trap(struct trapframe *frame)
146{
147	struct thread	*td;
148	struct proc	*p;
149#ifdef KDTRACE_HOOKS
150	uint32_t inst;
151#endif
152	int		sig, type, user;
153	u_int		ucode;
154	ksiginfo_t	ksi;
155
156	PCPU_INC(cnt.v_trap);
157
158	td = curthread;
159	p = td->td_proc;
160
161	type = ucode = frame->exc;
162	sig = 0;
163	user = frame->srr1 & PSL_PR;
164
165	CTR3(KTR_TRAP, "trap: %s type=%s (%s)", td->td_name,
166	    trapname(type), user ? "user" : "kernel");
167
168#ifdef KDTRACE_HOOKS
169	/*
170	 * A trap can occur while DTrace executes a probe. Before
171	 * executing the probe, DTrace blocks re-scheduling and sets
172	 * a flag in it's per-cpu flags to indicate that it doesn't
173	 * want to fault. On returning from the probe, the no-fault
174	 * flag is cleared and finally re-scheduling is enabled.
175	 *
176	 * If the DTrace kernel module has registered a trap handler,
177	 * call it and if it returns non-zero, assume that it has
178	 * handled the trap and modified the trap frame so that this
179	 * function can return normally.
180	 */
181	/*
182	 * XXXDTRACE: add pid probe handler here (if ever)
183	 */
184	if (dtrace_trap_func != NULL && (*dtrace_trap_func)(frame, type))
185		return;
186#endif
187
188	if (user) {
189		td->td_pticks = 0;
190		td->td_frame = frame;
191		if (td->td_ucred != p->p_ucred)
192			cred_update_thread(td);
193
194		/* User Mode Traps */
195		switch (type) {
196		case EXC_RUNMODETRC:
197		case EXC_TRC:
198			frame->srr1 &= ~PSL_SE;
199			sig = SIGTRAP;
200			break;
201
202#ifdef __powerpc64__
203		case EXC_ISE:
204		case EXC_DSE:
205			if (handle_user_slb_spill(&p->p_vmspace->vm_pmap,
206			    (type == EXC_ISE) ? frame->srr0 :
207			    frame->cpu.aim.dar) != 0)
208				sig = SIGSEGV;
209			break;
210#endif
211		case EXC_DSI:
212		case EXC_ISI:
213			sig = trap_pfault(frame, 1);
214			break;
215
216		case EXC_SC:
217			syscall(frame);
218			break;
219
220		case EXC_FPU:
221			KASSERT((td->td_pcb->pcb_flags & PCB_FPU) != PCB_FPU,
222			    ("FPU already enabled for thread"));
223			enable_fpu(td);
224			break;
225
226		case EXC_VEC:
227			KASSERT((td->td_pcb->pcb_flags & PCB_VEC) != PCB_VEC,
228			    ("Altivec already enabled for thread"));
229			enable_vec(td);
230			break;
231
232		case EXC_VECAST_G4:
233		case EXC_VECAST_G5:
234			/*
235			 * We get a VPU assist exception for IEEE mode
236			 * vector operations on denormalized floats.
237			 * Emulating this is a giant pain, so for now,
238			 * just switch off IEEE mode and treat them as
239			 * zero.
240			 */
241
242			save_vec(td);
243			td->td_pcb->pcb_vec.vscr |= ALTIVEC_VSCR_NJ;
244			enable_vec(td);
245			break;
246
247		case EXC_ALI:
248			if (fix_unaligned(td, frame) != 0)
249				sig = SIGBUS;
250			else
251				frame->srr0 += 4;
252			break;
253
254		case EXC_PGM:
255			/* Identify the trap reason */
256			if (frame->srr1 & EXC_PGM_TRAP) {
257#ifdef KDTRACE_HOOKS
258				inst = fuword32((const void *)frame->srr0);
259				if (inst == 0x0FFFDDDD && dtrace_pid_probe_ptr != NULL) {
260					struct reg regs;
261					fill_regs(td, &regs);
262					(*dtrace_pid_probe_ptr)(&regs);
263					break;
264				}
265#endif
266 				sig = SIGTRAP;
267			} else {
268				sig = ppc_instr_emulate(frame, td->td_pcb);
269			}
270			break;
271
272		case EXC_MCHK:
273			/*
274			 * Note that this may not be recoverable for the user
275			 * process, depending on the type of machine check,
276			 * but it at least prevents the kernel from dying.
277			 */
278			sig = SIGBUS;
279			break;
280
281		default:
282			trap_fatal(frame);
283		}
284	} else {
285		/* Kernel Mode Traps */
286
287		KASSERT(cold || td->td_ucred != NULL,
288		    ("kernel trap doesn't have ucred"));
289		switch (type) {
290#ifdef KDTRACE_HOOKS
291		case EXC_PGM:
292			if (frame->srr1 & EXC_PGM_TRAP) {
293				if (*(uint32_t *)frame->srr0 == 0x7c810808) {
294					if (dtrace_invop_jump_addr != NULL) {
295						dtrace_invop_jump_addr(frame);
296						return;
297					}
298				}
299			}
300			break;
301#endif
302#ifdef __powerpc64__
303		case EXC_DSE:
304			if ((frame->cpu.aim.dar & SEGMENT_MASK) == USER_ADDR) {
305				__asm __volatile ("slbmte %0, %1" ::
306					"r"(td->td_pcb->pcb_cpu.aim.usr_vsid),
307					"r"(USER_SLB_SLBE));
308				return;
309			}
310			break;
311#endif
312		case EXC_DSI:
313			if (trap_pfault(frame, 0) == 0)
314 				return;
315			break;
316		case EXC_MCHK:
317			if (handle_onfault(frame))
318 				return;
319			break;
320		default:
321			break;
322		}
323		trap_fatal(frame);
324	}
325
326	if (sig != 0) {
327		if (p->p_sysent->sv_transtrap != NULL)
328			sig = (p->p_sysent->sv_transtrap)(sig, type);
329		ksiginfo_init_trap(&ksi);
330		ksi.ksi_signo = sig;
331		ksi.ksi_code = (int) ucode; /* XXX, not POSIX */
332		/* ksi.ksi_addr = ? */
333		ksi.ksi_trapno = type;
334		trapsignal(td, &ksi);
335	}
336
337	userret(td, frame);
338}
339
340static void
341trap_fatal(struct trapframe *frame)
342{
343
344	printtrap(frame->exc, frame, 1, (frame->srr1 & PSL_PR));
345#ifdef KDB
346	if ((debugger_on_panic || kdb_active) &&
347	    kdb_trap(frame->exc, 0, frame))
348		return;
349#endif
350	panic("%s trap", trapname(frame->exc));
351}
352
353static void
354printtrap(u_int vector, struct trapframe *frame, int isfatal, int user)
355{
356
357	printf("\n");
358	printf("%s %s trap:\n", isfatal ? "fatal" : "handled",
359	    user ? "user" : "kernel");
360	printf("\n");
361	printf("   exception       = 0x%x (%s)\n", vector, trapname(vector));
362	switch (vector) {
363	case EXC_DSE:
364	case EXC_DSI:
365		printf("   virtual address = 0x%" PRIxPTR "\n",
366		    frame->cpu.aim.dar);
367		printf("   dsisr           = 0x%" PRIxPTR "\n",
368		    frame->cpu.aim.dsisr);
369		break;
370	case EXC_ISE:
371	case EXC_ISI:
372		printf("   virtual address = 0x%" PRIxPTR "\n", frame->srr0);
373		break;
374	}
375	printf("   srr0            = 0x%" PRIxPTR "\n", frame->srr0);
376	printf("   srr1            = 0x%" PRIxPTR "\n", frame->srr1);
377	printf("   lr              = 0x%" PRIxPTR "\n", frame->lr);
378	printf("   curthread       = %p\n", curthread);
379	if (curthread != NULL)
380		printf("          pid = %d, comm = %s\n",
381		    curthread->td_proc->p_pid, curthread->td_name);
382	printf("\n");
383}
384
385/*
386 * Handles a fatal fault when we have onfault state to recover.  Returns
387 * non-zero if there was onfault recovery state available.
388 */
389static int
390handle_onfault(struct trapframe *frame)
391{
392	struct		thread *td;
393	faultbuf	*fb;
394
395	td = curthread;
396	fb = td->td_pcb->pcb_onfault;
397	if (fb != NULL) {
398		frame->srr0 = (*fb)[0];
399		frame->fixreg[1] = (*fb)[1];
400		frame->fixreg[2] = (*fb)[2];
401		frame->fixreg[3] = 1;
402		frame->cr = (*fb)[3];
403		bcopy(&(*fb)[4], &frame->fixreg[13],
404		    19 * sizeof(register_t));
405		return (1);
406	}
407	return (0);
408}
409
410int
411cpu_fetch_syscall_args(struct thread *td, struct syscall_args *sa)
412{
413	struct proc *p;
414	struct trapframe *frame;
415	caddr_t	params;
416	size_t argsz;
417	int error, n, i;
418
419	p = td->td_proc;
420	frame = td->td_frame;
421
422	sa->code = frame->fixreg[0];
423	params = (caddr_t)(frame->fixreg + FIRSTARG);
424	n = NARGREG;
425
426	if (sa->code == SYS_syscall) {
427		/*
428		 * code is first argument,
429		 * followed by actual args.
430		 */
431		sa->code = *(register_t *) params;
432		params += sizeof(register_t);
433		n -= 1;
434	} else if (sa->code == SYS___syscall) {
435		/*
436		 * Like syscall, but code is a quad,
437		 * so as to maintain quad alignment
438		 * for the rest of the args.
439		 */
440		if (SV_PROC_FLAG(p, SV_ILP32)) {
441			params += sizeof(register_t);
442			sa->code = *(register_t *) params;
443			params += sizeof(register_t);
444			n -= 2;
445		} else {
446			sa->code = *(register_t *) params;
447			params += sizeof(register_t);
448			n -= 1;
449		}
450	}
451
452 	if (p->p_sysent->sv_mask)
453		sa->code &= p->p_sysent->sv_mask;
454	if (sa->code >= p->p_sysent->sv_size)
455		sa->callp = &p->p_sysent->sv_table[0];
456	else
457		sa->callp = &p->p_sysent->sv_table[sa->code];
458
459	sa->narg = sa->callp->sy_narg;
460
461	if (SV_PROC_FLAG(p, SV_ILP32)) {
462		argsz = sizeof(uint32_t);
463
464		for (i = 0; i < n; i++)
465			sa->args[i] = ((u_register_t *)(params))[i] &
466			    0xffffffff;
467	} else {
468		argsz = sizeof(uint64_t);
469
470		for (i = 0; i < n; i++)
471			sa->args[i] = ((u_register_t *)(params))[i];
472	}
473
474	if (sa->narg > n)
475		error = copyin(MOREARGS(frame->fixreg[1]), sa->args + n,
476			       (sa->narg - n) * argsz);
477	else
478		error = 0;
479
480#ifdef __powerpc64__
481	if (SV_PROC_FLAG(p, SV_ILP32) && sa->narg > n) {
482		/* Expand the size of arguments copied from the stack */
483
484		for (i = sa->narg; i >= n; i--)
485			sa->args[i] = ((uint32_t *)(&sa->args[n]))[i-n];
486	}
487#endif
488
489	if (error == 0) {
490		td->td_retval[0] = 0;
491		td->td_retval[1] = frame->fixreg[FIRSTARG + 1];
492	}
493	return (error);
494}
495
496#include "../../kern/subr_syscall.c"
497
498void
499syscall(struct trapframe *frame)
500{
501	struct thread *td;
502	struct syscall_args sa;
503	int error;
504
505	td = curthread;
506	td->td_frame = frame;
507
508#ifdef __powerpc64__
509	/*
510	 * Speculatively restore last user SLB segment, which we know is
511	 * invalid already, since we are likely to do copyin()/copyout().
512	 */
513	__asm __volatile ("slbmte %0, %1; isync" ::
514            "r"(td->td_pcb->pcb_cpu.aim.usr_vsid), "r"(USER_SLB_SLBE));
515#endif
516
517	error = syscallenter(td, &sa);
518	syscallret(td, error, &sa);
519}
520
521#ifdef __powerpc64__
522/* Handle kernel SLB faults -- runs in real mode, all seat belts off */
523void
524handle_kernel_slb_spill(int type, register_t dar, register_t srr0)
525{
526	struct slb *slbcache;
527	uint64_t slbe, slbv;
528	uint64_t esid, addr;
529	int i;
530
531	addr = (type == EXC_ISE) ? srr0 : dar;
532	slbcache = PCPU_GET(slb);
533	esid = (uintptr_t)addr >> ADDR_SR_SHFT;
534	slbe = (esid << SLBE_ESID_SHIFT) | SLBE_VALID;
535
536	/* See if the hardware flushed this somehow (can happen in LPARs) */
537	for (i = 0; i < n_slbs; i++)
538		if (slbcache[i].slbe == (slbe | (uint64_t)i))
539			return;
540
541	/* Not in the map, needs to actually be added */
542	slbv = kernel_va_to_slbv(addr);
543	if (slbcache[USER_SLB_SLOT].slbe == 0) {
544		for (i = 0; i < n_slbs; i++) {
545			if (i == USER_SLB_SLOT)
546				continue;
547			if (!(slbcache[i].slbe & SLBE_VALID))
548				goto fillkernslb;
549		}
550
551		if (i == n_slbs)
552			slbcache[USER_SLB_SLOT].slbe = 1;
553	}
554
555	/* Sacrifice a random SLB entry that is not the user entry */
556	i = mftb() % n_slbs;
557	if (i == USER_SLB_SLOT)
558		i = (i+1) % n_slbs;
559
560fillkernslb:
561	/* Write new entry */
562	slbcache[i].slbv = slbv;
563	slbcache[i].slbe = slbe | (uint64_t)i;
564
565	/* Trap handler will restore from cache on exit */
566}
567
568static int
569handle_user_slb_spill(pmap_t pm, vm_offset_t addr)
570{
571	struct slb *user_entry;
572	uint64_t esid;
573	int i;
574
575	esid = (uintptr_t)addr >> ADDR_SR_SHFT;
576
577	PMAP_LOCK(pm);
578	user_entry = user_va_to_slb_entry(pm, addr);
579
580	if (user_entry == NULL) {
581		/* allocate_vsid auto-spills it */
582		(void)allocate_user_vsid(pm, esid, 0);
583	} else {
584		/*
585		 * Check that another CPU has not already mapped this.
586		 * XXX: Per-thread SLB caches would be better.
587		 */
588		for (i = 0; i < pm->pm_slb_len; i++)
589			if (pm->pm_slb[i] == user_entry)
590				break;
591
592		if (i == pm->pm_slb_len)
593			slb_insert_user(pm, user_entry);
594	}
595	PMAP_UNLOCK(pm);
596
597	return (0);
598}
599#endif
600
601static int
602trap_pfault(struct trapframe *frame, int user)
603{
604	vm_offset_t	eva, va;
605	struct		thread *td;
606	struct		proc *p;
607	vm_map_t	map;
608	vm_prot_t	ftype;
609	int		rv;
610	register_t	user_sr;
611
612	td = curthread;
613	p = td->td_proc;
614	if (frame->exc == EXC_ISI) {
615		eva = frame->srr0;
616		ftype = VM_PROT_EXECUTE;
617		if (frame->srr1 & SRR1_ISI_PFAULT)
618			ftype |= VM_PROT_READ;
619	} else {
620		eva = frame->cpu.aim.dar;
621		if (frame->cpu.aim.dsisr & DSISR_STORE)
622			ftype = VM_PROT_WRITE;
623		else
624			ftype = VM_PROT_READ;
625	}
626
627	if (user) {
628		map = &p->p_vmspace->vm_map;
629	} else {
630		if ((eva >> ADDR_SR_SHFT) == (USER_ADDR >> ADDR_SR_SHFT)) {
631			if (p->p_vmspace == NULL)
632				return (SIGSEGV);
633
634			map = &p->p_vmspace->vm_map;
635
636			user_sr = td->td_pcb->pcb_cpu.aim.usr_segm;
637			eva &= ADDR_PIDX | ADDR_POFF;
638			eva |= user_sr << ADDR_SR_SHFT;
639		} else {
640			map = kernel_map;
641		}
642	}
643	va = trunc_page(eva);
644
645	if (map != kernel_map) {
646		/*
647		 * Keep swapout from messing with us during this
648		 *	critical time.
649		 */
650		PROC_LOCK(p);
651		++p->p_lock;
652		PROC_UNLOCK(p);
653
654		/* Fault in the user page: */
655		rv = vm_fault(map, va, ftype, VM_FAULT_NORMAL);
656
657		PROC_LOCK(p);
658		--p->p_lock;
659		PROC_UNLOCK(p);
660		/*
661		 * XXXDTRACE: add dtrace_doubletrap_func here?
662		 */
663	} else {
664		/*
665		 * Don't have to worry about process locking or stacks in the
666		 * kernel.
667		 */
668		rv = vm_fault(map, va, ftype, VM_FAULT_NORMAL);
669	}
670
671	if (rv == KERN_SUCCESS)
672		return (0);
673
674	if (!user && handle_onfault(frame))
675		return (0);
676
677	return (SIGSEGV);
678}
679
680/*
681 * For now, this only deals with the particular unaligned access case
682 * that gcc tends to generate.  Eventually it should handle all of the
683 * possibilities that can happen on a 32-bit PowerPC in big-endian mode.
684 */
685
686static int
687fix_unaligned(struct thread *td, struct trapframe *frame)
688{
689	struct thread	*fputhread;
690	int		indicator, reg;
691	double		*fpr;
692
693	indicator = EXC_ALI_OPCODE_INDICATOR(frame->cpu.aim.dsisr);
694
695	switch (indicator) {
696	case EXC_ALI_LFD:
697	case EXC_ALI_STFD:
698		reg = EXC_ALI_RST(frame->cpu.aim.dsisr);
699		fpr = &td->td_pcb->pcb_fpu.fpr[reg];
700		fputhread = PCPU_GET(fputhread);
701
702		/* Juggle the FPU to ensure that we've initialized
703		 * the FPRs, and that their current state is in
704		 * the PCB.
705		 */
706		if (fputhread != td) {
707			if (fputhread)
708				save_fpu(fputhread);
709			enable_fpu(td);
710		}
711		save_fpu(td);
712
713		if (indicator == EXC_ALI_LFD) {
714			if (copyin((void *)frame->cpu.aim.dar, fpr,
715			    sizeof(double)) != 0)
716				return -1;
717			enable_fpu(td);
718		} else {
719			if (copyout(fpr, (void *)frame->cpu.aim.dar,
720			    sizeof(double)) != 0)
721				return -1;
722		}
723		return 0;
724		break;
725	}
726
727	return -1;
728}
729
730