xref: /illumos-gate/usr/src/uts/sparc/os/archdep.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
28*7c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
29*7c478bd9Sstevel@tonic-gate 
30*7c478bd9Sstevel@tonic-gate 
31*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
32*7c478bd9Sstevel@tonic-gate 
33*7c478bd9Sstevel@tonic-gate #include <sys/param.h>
34*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
35*7c478bd9Sstevel@tonic-gate #include <sys/vmparam.h>
36*7c478bd9Sstevel@tonic-gate #include <sys/systm.h>
37*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
38*7c478bd9Sstevel@tonic-gate #include <sys/signal.h>
39*7c478bd9Sstevel@tonic-gate #include <sys/stack.h>
40*7c478bd9Sstevel@tonic-gate #include <sys/frame.h>
41*7c478bd9Sstevel@tonic-gate #include <sys/proc.h>
42*7c478bd9Sstevel@tonic-gate #include <sys/ucontext.h>
43*7c478bd9Sstevel@tonic-gate #include <sys/siginfo.h>
44*7c478bd9Sstevel@tonic-gate #include <sys/cpuvar.h>
45*7c478bd9Sstevel@tonic-gate #include <sys/asm_linkage.h>
46*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
47*7c478bd9Sstevel@tonic-gate #include <sys/errno.h>
48*7c478bd9Sstevel@tonic-gate #include <sys/bootconf.h>
49*7c478bd9Sstevel@tonic-gate #include <sys/archsystm.h>
50*7c478bd9Sstevel@tonic-gate #include <sys/fpu/fpusystm.h>
51*7c478bd9Sstevel@tonic-gate #include <sys/auxv.h>
52*7c478bd9Sstevel@tonic-gate #include <sys/debug.h>
53*7c478bd9Sstevel@tonic-gate #include <sys/elf.h>
54*7c478bd9Sstevel@tonic-gate #include <sys/elf_SPARC.h>
55*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
56*7c478bd9Sstevel@tonic-gate #include <sys/spl.h>
57*7c478bd9Sstevel@tonic-gate #include <sys/privregs.h>
58*7c478bd9Sstevel@tonic-gate #include <sys/kobj.h>
59*7c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
60*7c478bd9Sstevel@tonic-gate #include <sys/reboot.h>
61*7c478bd9Sstevel@tonic-gate #include <sys/time.h>
62*7c478bd9Sstevel@tonic-gate #include <sys/panic.h>
63*7c478bd9Sstevel@tonic-gate #include <vm/seg_kmem.h>
64*7c478bd9Sstevel@tonic-gate #include <vm/page.h>
65*7c478bd9Sstevel@tonic-gate #include <sys/machpcb.h>
66*7c478bd9Sstevel@tonic-gate 
67*7c478bd9Sstevel@tonic-gate extern struct bootops *bootops;
68*7c478bd9Sstevel@tonic-gate 
69*7c478bd9Sstevel@tonic-gate /*
70*7c478bd9Sstevel@tonic-gate  * Workaround for broken FDDI driver (remove when 4289172 is fixed)
71*7c478bd9Sstevel@tonic-gate  */
72*7c478bd9Sstevel@tonic-gate short cputype = 0x80;
73*7c478bd9Sstevel@tonic-gate 
74*7c478bd9Sstevel@tonic-gate extern int getpcstack_top(pc_t *pcstack, int limit, uintptr_t *lastfp,
75*7c478bd9Sstevel@tonic-gate     pc_t *lastpc);
76*7c478bd9Sstevel@tonic-gate 
77*7c478bd9Sstevel@tonic-gate /*
78*7c478bd9Sstevel@tonic-gate  * Get a pc-only stacktrace.  Used for kmem_alloc() buffer ownership tracking.
79*7c478bd9Sstevel@tonic-gate  * Returns MIN(current stack depth, pcstack_limit).
80*7c478bd9Sstevel@tonic-gate  */
81*7c478bd9Sstevel@tonic-gate int
82*7c478bd9Sstevel@tonic-gate getpcstack(pc_t *pcstack, int pcstack_limit)
83*7c478bd9Sstevel@tonic-gate {
84*7c478bd9Sstevel@tonic-gate 	struct frame *fp, *minfp, *stacktop;
85*7c478bd9Sstevel@tonic-gate 	uintptr_t nextfp;
86*7c478bd9Sstevel@tonic-gate 	pc_t nextpc;
87*7c478bd9Sstevel@tonic-gate 	int depth;
88*7c478bd9Sstevel@tonic-gate 	int on_intr;
89*7c478bd9Sstevel@tonic-gate 	pc_t pcswin[MAXWIN];
90*7c478bd9Sstevel@tonic-gate 	int npcwin = MIN(MAXWIN, pcstack_limit);
91*7c478bd9Sstevel@tonic-gate 
92*7c478bd9Sstevel@tonic-gate 	if ((on_intr = CPU_ON_INTR(CPU)) != 0)
93*7c478bd9Sstevel@tonic-gate 		stacktop = (struct frame *)(CPU->cpu_intr_stack + SA(MINFRAME));
94*7c478bd9Sstevel@tonic-gate 	else
95*7c478bd9Sstevel@tonic-gate 		stacktop = (struct frame *)curthread->t_stk;
96*7c478bd9Sstevel@tonic-gate 
97*7c478bd9Sstevel@tonic-gate 	minfp = (struct frame *)((uintptr_t)getfp() + STACK_BIAS);
98*7c478bd9Sstevel@tonic-gate 
99*7c478bd9Sstevel@tonic-gate 	/*
100*7c478bd9Sstevel@tonic-gate 	 * getpcstack_top() processes the frames still in register windows,
101*7c478bd9Sstevel@tonic-gate 	 * fills nextfp and nextpc with our starting point, and returns
102*7c478bd9Sstevel@tonic-gate 	 * the number of frames it wrote into pcstack.
103*7c478bd9Sstevel@tonic-gate 	 *
104*7c478bd9Sstevel@tonic-gate 	 * Since we cannot afford to take a relocation trap while we are
105*7c478bd9Sstevel@tonic-gate 	 * messing with register windows, we pass getpcstack_top() a buffer
106*7c478bd9Sstevel@tonic-gate 	 * on our stack and then copy the result out to the pcstack buffer
107*7c478bd9Sstevel@tonic-gate 	 * provided by the caller.  The size of this buffer is the maximum
108*7c478bd9Sstevel@tonic-gate 	 * supported number of SPARC register windows; however we ASSERT
109*7c478bd9Sstevel@tonic-gate 	 * that it returns fewer than that, since it will skip the current
110*7c478bd9Sstevel@tonic-gate 	 * frame.
111*7c478bd9Sstevel@tonic-gate 	 */
112*7c478bd9Sstevel@tonic-gate 	npcwin = getpcstack_top(pcswin, npcwin, &nextfp, &nextpc);
113*7c478bd9Sstevel@tonic-gate 	ASSERT(npcwin >= 0 && npcwin < MAXWIN && npcwin <= pcstack_limit);
114*7c478bd9Sstevel@tonic-gate 	for (depth = 0; depth < npcwin; depth++) {
115*7c478bd9Sstevel@tonic-gate 		pcstack[depth] = pcswin[depth];
116*7c478bd9Sstevel@tonic-gate 	}
117*7c478bd9Sstevel@tonic-gate 
118*7c478bd9Sstevel@tonic-gate 	fp = (struct frame *)(nextfp + STACK_BIAS);
119*7c478bd9Sstevel@tonic-gate 
120*7c478bd9Sstevel@tonic-gate 	while (depth < pcstack_limit) {
121*7c478bd9Sstevel@tonic-gate 		if (fp <= minfp || fp >= stacktop) {
122*7c478bd9Sstevel@tonic-gate 			if (on_intr) {
123*7c478bd9Sstevel@tonic-gate 				/*
124*7c478bd9Sstevel@tonic-gate 				 * Hop from interrupt stack to thread stack.
125*7c478bd9Sstevel@tonic-gate 				 */
126*7c478bd9Sstevel@tonic-gate 				stacktop = (struct frame *)curthread->t_stk;
127*7c478bd9Sstevel@tonic-gate 				minfp = (struct frame *)curthread->t_stkbase;
128*7c478bd9Sstevel@tonic-gate 				on_intr = 0;
129*7c478bd9Sstevel@tonic-gate 				continue;
130*7c478bd9Sstevel@tonic-gate 			}
131*7c478bd9Sstevel@tonic-gate 			break;
132*7c478bd9Sstevel@tonic-gate 		}
133*7c478bd9Sstevel@tonic-gate 
134*7c478bd9Sstevel@tonic-gate 		pcstack[depth++] = nextpc;
135*7c478bd9Sstevel@tonic-gate 		minfp = fp;
136*7c478bd9Sstevel@tonic-gate 
137*7c478bd9Sstevel@tonic-gate 		nextpc = (pc_t)fp->fr_savpc;
138*7c478bd9Sstevel@tonic-gate 		fp = (struct frame *)((uintptr_t)fp->fr_savfp + STACK_BIAS);
139*7c478bd9Sstevel@tonic-gate 	}
140*7c478bd9Sstevel@tonic-gate 
141*7c478bd9Sstevel@tonic-gate 	return (depth);
142*7c478bd9Sstevel@tonic-gate }
143*7c478bd9Sstevel@tonic-gate 
144*7c478bd9Sstevel@tonic-gate /*
145*7c478bd9Sstevel@tonic-gate  * The following ELF header fields are defined as processor-specific
146*7c478bd9Sstevel@tonic-gate  * in the SPARC V8 ABI:
147*7c478bd9Sstevel@tonic-gate  *
148*7c478bd9Sstevel@tonic-gate  *	e_ident[EI_DATA]	encoding of the processor-specific
149*7c478bd9Sstevel@tonic-gate  *				data in the object file
150*7c478bd9Sstevel@tonic-gate  *	e_machine		processor identification
151*7c478bd9Sstevel@tonic-gate  *	e_flags			processor-specific flags associated
152*7c478bd9Sstevel@tonic-gate  *				with the file
153*7c478bd9Sstevel@tonic-gate  */
154*7c478bd9Sstevel@tonic-gate 
155*7c478bd9Sstevel@tonic-gate /*
156*7c478bd9Sstevel@tonic-gate  * The value of at_flags reflects a platform's cpu module support.
157*7c478bd9Sstevel@tonic-gate  * at_flags is used to check for allowing a binary to execute and
158*7c478bd9Sstevel@tonic-gate  * is passed as the value of the AT_FLAGS auxiliary vector.
159*7c478bd9Sstevel@tonic-gate  */
160*7c478bd9Sstevel@tonic-gate int at_flags = 0;
161*7c478bd9Sstevel@tonic-gate 
162*7c478bd9Sstevel@tonic-gate /*
163*7c478bd9Sstevel@tonic-gate  * Check the processor-specific fields of an ELF header.
164*7c478bd9Sstevel@tonic-gate  *
165*7c478bd9Sstevel@tonic-gate  * returns 1 if the fields are valid, 0 otherwise
166*7c478bd9Sstevel@tonic-gate  */
167*7c478bd9Sstevel@tonic-gate int
168*7c478bd9Sstevel@tonic-gate elfheadcheck(
169*7c478bd9Sstevel@tonic-gate 	unsigned char e_data,
170*7c478bd9Sstevel@tonic-gate 	Elf32_Half e_machine,
171*7c478bd9Sstevel@tonic-gate 	Elf32_Word e_flags)
172*7c478bd9Sstevel@tonic-gate {
173*7c478bd9Sstevel@tonic-gate 	Elf32_Word needed_flags;
174*7c478bd9Sstevel@tonic-gate 	int supported_flags;
175*7c478bd9Sstevel@tonic-gate 
176*7c478bd9Sstevel@tonic-gate 	if (e_data != ELFDATA2MSB)
177*7c478bd9Sstevel@tonic-gate 		return (0);
178*7c478bd9Sstevel@tonic-gate 
179*7c478bd9Sstevel@tonic-gate 	switch (e_machine) {
180*7c478bd9Sstevel@tonic-gate 	case EM_SPARC:
181*7c478bd9Sstevel@tonic-gate 		if (e_flags == 0)
182*7c478bd9Sstevel@tonic-gate 			return (1);
183*7c478bd9Sstevel@tonic-gate 		else
184*7c478bd9Sstevel@tonic-gate 			return (0);
185*7c478bd9Sstevel@tonic-gate 	case EM_SPARCV9:
186*7c478bd9Sstevel@tonic-gate 		/*
187*7c478bd9Sstevel@tonic-gate 		 * Check that ELF flags are set to supported SPARC V9 flags
188*7c478bd9Sstevel@tonic-gate 		 */
189*7c478bd9Sstevel@tonic-gate 		needed_flags = e_flags & EF_SPARC_EXT_MASK;
190*7c478bd9Sstevel@tonic-gate 		supported_flags = at_flags & ~EF_SPARC_32PLUS;
191*7c478bd9Sstevel@tonic-gate 
192*7c478bd9Sstevel@tonic-gate 		if (needed_flags & ~supported_flags)
193*7c478bd9Sstevel@tonic-gate 			return (0);
194*7c478bd9Sstevel@tonic-gate 		else
195*7c478bd9Sstevel@tonic-gate 			return (1);
196*7c478bd9Sstevel@tonic-gate 	case EM_SPARC32PLUS:
197*7c478bd9Sstevel@tonic-gate 		if ((e_flags & EF_SPARC_32PLUS) != 0 &&
198*7c478bd9Sstevel@tonic-gate 		    ((e_flags & ~at_flags) & EF_SPARC_32PLUS_MASK) == 0)
199*7c478bd9Sstevel@tonic-gate 			return (1);
200*7c478bd9Sstevel@tonic-gate 		else
201*7c478bd9Sstevel@tonic-gate 			return (0);
202*7c478bd9Sstevel@tonic-gate 	default:
203*7c478bd9Sstevel@tonic-gate 		return (0);
204*7c478bd9Sstevel@tonic-gate 	}
205*7c478bd9Sstevel@tonic-gate }
206*7c478bd9Sstevel@tonic-gate 
207*7c478bd9Sstevel@tonic-gate uint_t auxv_hwcap_include = 0;	/* patch to enable unrecognized features */
208*7c478bd9Sstevel@tonic-gate uint_t auxv_hwcap_exclude = 0;	/* patch for broken cpus, debugging */
209*7c478bd9Sstevel@tonic-gate #if defined(_SYSCALL32_IMPL)
210*7c478bd9Sstevel@tonic-gate uint_t auxv_hwcap32_include = 0;	/* ditto for 32-bit apps */
211*7c478bd9Sstevel@tonic-gate uint_t auxv_hwcap32_exclude = 0;	/* ditto for 32-bit apps */
212*7c478bd9Sstevel@tonic-gate #endif
213*7c478bd9Sstevel@tonic-gate 
214*7c478bd9Sstevel@tonic-gate uint_t cpu_hwcap_flags = 0;	/* set by cpu-dependent code */
215*7c478bd9Sstevel@tonic-gate 
216*7c478bd9Sstevel@tonic-gate /*
217*7c478bd9Sstevel@tonic-gate  * Gather information about the processor and place it into auxv_hwcap
218*7c478bd9Sstevel@tonic-gate  * so that it can be exported to the linker via the aux vector.
219*7c478bd9Sstevel@tonic-gate  *
220*7c478bd9Sstevel@tonic-gate  * We use this seemingly complicated mechanism so that we can ensure
221*7c478bd9Sstevel@tonic-gate  * that /etc/system can be used to override what the system can or
222*7c478bd9Sstevel@tonic-gate  * cannot discover for itself.
223*7c478bd9Sstevel@tonic-gate  */
224*7c478bd9Sstevel@tonic-gate void
225*7c478bd9Sstevel@tonic-gate bind_hwcap(void)
226*7c478bd9Sstevel@tonic-gate {
227*7c478bd9Sstevel@tonic-gate 	auxv_hwcap = (auxv_hwcap_include | cpu_hwcap_flags) &
228*7c478bd9Sstevel@tonic-gate 	    ~auxv_hwcap_exclude;
229*7c478bd9Sstevel@tonic-gate 
230*7c478bd9Sstevel@tonic-gate 	if (auxv_hwcap_include || auxv_hwcap_exclude)
231*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, "?user ABI extensions: %b\n",
232*7c478bd9Sstevel@tonic-gate 		    auxv_hwcap, FMT_AV_SPARC);
233*7c478bd9Sstevel@tonic-gate 
234*7c478bd9Sstevel@tonic-gate #if defined(_SYSCALL32_IMPL)
235*7c478bd9Sstevel@tonic-gate 	/*
236*7c478bd9Sstevel@tonic-gate 	 * These are now a compatibility artifact; all supported SPARC CPUs
237*7c478bd9Sstevel@tonic-gate 	 * are V9-capable (and thus support v8plus) and fully implement
238*7c478bd9Sstevel@tonic-gate 	 * {s,u}mul and {s,u}div.
239*7c478bd9Sstevel@tonic-gate 	 */
240*7c478bd9Sstevel@tonic-gate 	cpu_hwcap_flags |= AV_SPARC_MUL32 | AV_SPARC_DIV32 | AV_SPARC_V8PLUS;
241*7c478bd9Sstevel@tonic-gate 
242*7c478bd9Sstevel@tonic-gate 	auxv_hwcap32 = (auxv_hwcap32_include | cpu_hwcap_flags) &
243*7c478bd9Sstevel@tonic-gate 	    ~auxv_hwcap32_exclude;
244*7c478bd9Sstevel@tonic-gate 
245*7c478bd9Sstevel@tonic-gate 	if (auxv_hwcap32_include || auxv_hwcap32_exclude)
246*7c478bd9Sstevel@tonic-gate 		cmn_err(CE_CONT, "?32-bit user ABI extensions: %b\n",
247*7c478bd9Sstevel@tonic-gate 		    auxv_hwcap32, FMT_AV_SPARC);
248*7c478bd9Sstevel@tonic-gate #endif
249*7c478bd9Sstevel@tonic-gate }
250*7c478bd9Sstevel@tonic-gate 
251*7c478bd9Sstevel@tonic-gate int
252*7c478bd9Sstevel@tonic-gate __ipltospl(int ipl)
253*7c478bd9Sstevel@tonic-gate {
254*7c478bd9Sstevel@tonic-gate 	return (ipltospl(ipl));
255*7c478bd9Sstevel@tonic-gate }
256*7c478bd9Sstevel@tonic-gate 
257*7c478bd9Sstevel@tonic-gate /*
258*7c478bd9Sstevel@tonic-gate  * Print a stack backtrace using the specified stack pointer.  We delay two
259*7c478bd9Sstevel@tonic-gate  * seconds before continuing, unless this is the panic traceback.  Note
260*7c478bd9Sstevel@tonic-gate  * that the frame for the starting stack pointer value is omitted because
261*7c478bd9Sstevel@tonic-gate  * the corresponding %pc is not known.
262*7c478bd9Sstevel@tonic-gate  */
263*7c478bd9Sstevel@tonic-gate void
264*7c478bd9Sstevel@tonic-gate traceback(caddr_t sp)
265*7c478bd9Sstevel@tonic-gate {
266*7c478bd9Sstevel@tonic-gate 	struct frame *fp = (struct frame *)(sp + STACK_BIAS);
267*7c478bd9Sstevel@tonic-gate 	struct frame *nextfp, *minfp, *stacktop;
268*7c478bd9Sstevel@tonic-gate 	int on_intr;
269*7c478bd9Sstevel@tonic-gate 
270*7c478bd9Sstevel@tonic-gate 	cpu_t *cpu;
271*7c478bd9Sstevel@tonic-gate 
272*7c478bd9Sstevel@tonic-gate 	flush_windows();
273*7c478bd9Sstevel@tonic-gate 
274*7c478bd9Sstevel@tonic-gate 	if (!panicstr)
275*7c478bd9Sstevel@tonic-gate 		printf("traceback: %%sp = %p\n", (void *)sp);
276*7c478bd9Sstevel@tonic-gate 
277*7c478bd9Sstevel@tonic-gate 	/*
278*7c478bd9Sstevel@tonic-gate 	 * If we are panicking, the high-level interrupt information in
279*7c478bd9Sstevel@tonic-gate 	 * CPU was overwritten.  panic_cpu has the correct values.
280*7c478bd9Sstevel@tonic-gate 	 */
281*7c478bd9Sstevel@tonic-gate 	kpreempt_disable();			/* prevent migration */
282*7c478bd9Sstevel@tonic-gate 
283*7c478bd9Sstevel@tonic-gate 	cpu = (panicstr && CPU->cpu_id == panic_cpu.cpu_id)? &panic_cpu : CPU;
284*7c478bd9Sstevel@tonic-gate 
285*7c478bd9Sstevel@tonic-gate 	if ((on_intr = CPU_ON_INTR(cpu)) != 0)
286*7c478bd9Sstevel@tonic-gate 		stacktop = (struct frame *)(cpu->cpu_intr_stack + SA(MINFRAME));
287*7c478bd9Sstevel@tonic-gate 	else
288*7c478bd9Sstevel@tonic-gate 		stacktop = (struct frame *)curthread->t_stk;
289*7c478bd9Sstevel@tonic-gate 
290*7c478bd9Sstevel@tonic-gate 	kpreempt_enable();
291*7c478bd9Sstevel@tonic-gate 
292*7c478bd9Sstevel@tonic-gate 	minfp = fp;
293*7c478bd9Sstevel@tonic-gate 
294*7c478bd9Sstevel@tonic-gate 	while ((uintptr_t)fp >= KERNELBASE) {
295*7c478bd9Sstevel@tonic-gate 		uintptr_t pc = (uintptr_t)fp->fr_savpc;
296*7c478bd9Sstevel@tonic-gate 		ulong_t off;
297*7c478bd9Sstevel@tonic-gate 		char *sym;
298*7c478bd9Sstevel@tonic-gate 
299*7c478bd9Sstevel@tonic-gate 		nextfp = (struct frame *)((uintptr_t)fp->fr_savfp + STACK_BIAS);
300*7c478bd9Sstevel@tonic-gate 		if (nextfp <= minfp || nextfp >= stacktop) {
301*7c478bd9Sstevel@tonic-gate 			if (on_intr) {
302*7c478bd9Sstevel@tonic-gate 				/*
303*7c478bd9Sstevel@tonic-gate 				 * Hop from interrupt stack to thread stack.
304*7c478bd9Sstevel@tonic-gate 				 */
305*7c478bd9Sstevel@tonic-gate 				stacktop = (struct frame *)curthread->t_stk;
306*7c478bd9Sstevel@tonic-gate 				minfp = (struct frame *)curthread->t_stkbase;
307*7c478bd9Sstevel@tonic-gate 				on_intr = 0;
308*7c478bd9Sstevel@tonic-gate 				continue;
309*7c478bd9Sstevel@tonic-gate 			}
310*7c478bd9Sstevel@tonic-gate 			break; /* we're outside of the expected range */
311*7c478bd9Sstevel@tonic-gate 		}
312*7c478bd9Sstevel@tonic-gate 
313*7c478bd9Sstevel@tonic-gate 		if ((uintptr_t)nextfp & (STACK_ALIGN - 1)) {
314*7c478bd9Sstevel@tonic-gate 			printf("  >> mis-aligned %%fp = %p\n", (void *)nextfp);
315*7c478bd9Sstevel@tonic-gate 			break;
316*7c478bd9Sstevel@tonic-gate 		}
317*7c478bd9Sstevel@tonic-gate 
318*7c478bd9Sstevel@tonic-gate 		if ((sym = kobj_getsymname(pc, &off)) != NULL) {
319*7c478bd9Sstevel@tonic-gate 			printf("%016lx %s:%s+%lx "
320*7c478bd9Sstevel@tonic-gate 			    "(%lx, %lx, %lx, %lx, %lx, %lx)\n", (ulong_t)nextfp,
321*7c478bd9Sstevel@tonic-gate 			    mod_containing_pc((caddr_t)pc), sym, off,
322*7c478bd9Sstevel@tonic-gate 			    nextfp->fr_arg[0], nextfp->fr_arg[1],
323*7c478bd9Sstevel@tonic-gate 			    nextfp->fr_arg[2], nextfp->fr_arg[3],
324*7c478bd9Sstevel@tonic-gate 			    nextfp->fr_arg[4], nextfp->fr_arg[5]);
325*7c478bd9Sstevel@tonic-gate 		} else {
326*7c478bd9Sstevel@tonic-gate 			printf("%016lx %p (%lx, %lx, %lx, %lx, %lx, %lx)\n",
327*7c478bd9Sstevel@tonic-gate 			    (ulong_t)nextfp, (void *)pc,
328*7c478bd9Sstevel@tonic-gate 			    nextfp->fr_arg[0], nextfp->fr_arg[1],
329*7c478bd9Sstevel@tonic-gate 			    nextfp->fr_arg[2], nextfp->fr_arg[3],
330*7c478bd9Sstevel@tonic-gate 			    nextfp->fr_arg[4], nextfp->fr_arg[5]);
331*7c478bd9Sstevel@tonic-gate 		}
332*7c478bd9Sstevel@tonic-gate 
333*7c478bd9Sstevel@tonic-gate 		printf("  %%l0-3: %016lx %016lx %016lx %016lx\n"
334*7c478bd9Sstevel@tonic-gate 		    "  %%l4-7: %016lx %016lx %016lx %016lx\n",
335*7c478bd9Sstevel@tonic-gate 		    nextfp->fr_local[0], nextfp->fr_local[1],
336*7c478bd9Sstevel@tonic-gate 		    nextfp->fr_local[2], nextfp->fr_local[3],
337*7c478bd9Sstevel@tonic-gate 		    nextfp->fr_local[4], nextfp->fr_local[5],
338*7c478bd9Sstevel@tonic-gate 		    nextfp->fr_local[6], nextfp->fr_local[7]);
339*7c478bd9Sstevel@tonic-gate 
340*7c478bd9Sstevel@tonic-gate 		fp = nextfp;
341*7c478bd9Sstevel@tonic-gate 		minfp = fp;
342*7c478bd9Sstevel@tonic-gate 	}
343*7c478bd9Sstevel@tonic-gate 
344*7c478bd9Sstevel@tonic-gate 	if (!panicstr) {
345*7c478bd9Sstevel@tonic-gate 		printf("end of traceback\n");
346*7c478bd9Sstevel@tonic-gate 		DELAY(2 * MICROSEC);
347*7c478bd9Sstevel@tonic-gate 	}
348*7c478bd9Sstevel@tonic-gate }
349*7c478bd9Sstevel@tonic-gate 
350*7c478bd9Sstevel@tonic-gate /*
351*7c478bd9Sstevel@tonic-gate  * Generate a stack backtrace from a saved register set.
352*7c478bd9Sstevel@tonic-gate  */
353*7c478bd9Sstevel@tonic-gate void
354*7c478bd9Sstevel@tonic-gate traceregs(struct regs *rp)
355*7c478bd9Sstevel@tonic-gate {
356*7c478bd9Sstevel@tonic-gate 	traceback((caddr_t)rp->r_sp);
357*7c478bd9Sstevel@tonic-gate }
358*7c478bd9Sstevel@tonic-gate 
359*7c478bd9Sstevel@tonic-gate void
360*7c478bd9Sstevel@tonic-gate exec_set_sp(size_t stksize)
361*7c478bd9Sstevel@tonic-gate {
362*7c478bd9Sstevel@tonic-gate 	klwp_t *lwp = ttolwp(curthread);
363*7c478bd9Sstevel@tonic-gate 
364*7c478bd9Sstevel@tonic-gate 	lwp->lwp_pcb.pcb_xregstat = XREGNONE;
365*7c478bd9Sstevel@tonic-gate 	if (curproc->p_model == DATAMODEL_NATIVE)
366*7c478bd9Sstevel@tonic-gate 		stksize += sizeof (struct rwindow) + STACK_BIAS;
367*7c478bd9Sstevel@tonic-gate 	else
368*7c478bd9Sstevel@tonic-gate 		stksize += sizeof (struct rwindow32);
369*7c478bd9Sstevel@tonic-gate 	lwptoregs(lwp)->r_sp = (uintptr_t)curproc->p_usrstack - stksize;
370*7c478bd9Sstevel@tonic-gate }
371*7c478bd9Sstevel@tonic-gate 
372*7c478bd9Sstevel@tonic-gate /*
373*7c478bd9Sstevel@tonic-gate  * Allocate a region of virtual address space, unmapped.
374*7c478bd9Sstevel@tonic-gate  *
375*7c478bd9Sstevel@tonic-gate  * When a hard-redzone (firewall) is in effect, redzone violations are
376*7c478bd9Sstevel@tonic-gate  * caught by the hardware the instant they happen because the first byte
377*7c478bd9Sstevel@tonic-gate  * past the logical end of a firewalled buffer lies at the start of an
378*7c478bd9Sstevel@tonic-gate  * unmapped page.  This firewalling is accomplished by bumping up the
379*7c478bd9Sstevel@tonic-gate  * requested address allocation, effectively removing an additional page
380*7c478bd9Sstevel@tonic-gate  * beyond the original request from the available virtual memory arena.
381*7c478bd9Sstevel@tonic-gate  * However, the size of the allocation passed to boot, in boot_alloc(),
382*7c478bd9Sstevel@tonic-gate  * doesn't reflect this additional page and fragmentation of the OBP
383*7c478bd9Sstevel@tonic-gate  * "virtual-memory" "available" lists property occurs.  Calling
384*7c478bd9Sstevel@tonic-gate  * prom_claim_virt() for the firewall page avoids this fragmentation.
385*7c478bd9Sstevel@tonic-gate  */
386*7c478bd9Sstevel@tonic-gate void *
387*7c478bd9Sstevel@tonic-gate boot_virt_alloc(void *addr, size_t size)
388*7c478bd9Sstevel@tonic-gate {
389*7c478bd9Sstevel@tonic-gate 	return (BOP_ALLOC_VIRT(bootops, (caddr_t)addr, size));
390*7c478bd9Sstevel@tonic-gate }
391*7c478bd9Sstevel@tonic-gate 
392*7c478bd9Sstevel@tonic-gate 
393*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
394*7c478bd9Sstevel@tonic-gate int
395*7c478bd9Sstevel@tonic-gate xcopyin_nta(const void *uaddr, void *kaddr, size_t count, int dummy)
396*7c478bd9Sstevel@tonic-gate {
397*7c478bd9Sstevel@tonic-gate 	return (xcopyin(uaddr, kaddr, count));
398*7c478bd9Sstevel@tonic-gate }
399*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
400*7c478bd9Sstevel@tonic-gate int
401*7c478bd9Sstevel@tonic-gate xcopyout_nta(const void *kaddr, void *uaddr, size_t count, int dummy)
402*7c478bd9Sstevel@tonic-gate {
403*7c478bd9Sstevel@tonic-gate 	return (xcopyout(kaddr, uaddr, count));
404*7c478bd9Sstevel@tonic-gate }
405*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
406*7c478bd9Sstevel@tonic-gate int
407*7c478bd9Sstevel@tonic-gate kcopy_nta(const void *from, void *to, size_t count, int dummy)
408*7c478bd9Sstevel@tonic-gate {
409*7c478bd9Sstevel@tonic-gate 	return (kcopy(from, to, count));
410*7c478bd9Sstevel@tonic-gate }
411