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