17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5986fd29aSsetje * Common Development and Distribution License (the "License"). 6986fd29aSsetje * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*f6e214c7SGavin Maltby * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved. 237c478bd9Sstevel@tonic-gate */ 247c478bd9Sstevel@tonic-gate 257c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 267c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate #include <sys/param.h> 307c478bd9Sstevel@tonic-gate #include <sys/types.h> 317c478bd9Sstevel@tonic-gate #include <sys/vmparam.h> 327c478bd9Sstevel@tonic-gate #include <sys/systm.h> 337c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 347c478bd9Sstevel@tonic-gate #include <sys/signal.h> 357c478bd9Sstevel@tonic-gate #include <sys/stack.h> 367c478bd9Sstevel@tonic-gate #include <sys/frame.h> 377c478bd9Sstevel@tonic-gate #include <sys/proc.h> 387c478bd9Sstevel@tonic-gate #include <sys/ucontext.h> 397c478bd9Sstevel@tonic-gate #include <sys/siginfo.h> 407c478bd9Sstevel@tonic-gate #include <sys/cpuvar.h> 417c478bd9Sstevel@tonic-gate #include <sys/asm_linkage.h> 427c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 437c478bd9Sstevel@tonic-gate #include <sys/errno.h> 447c478bd9Sstevel@tonic-gate #include <sys/bootconf.h> 457c478bd9Sstevel@tonic-gate #include <sys/archsystm.h> 467c478bd9Sstevel@tonic-gate #include <sys/fpu/fpusystm.h> 477c478bd9Sstevel@tonic-gate #include <sys/auxv.h> 487c478bd9Sstevel@tonic-gate #include <sys/debug.h> 497c478bd9Sstevel@tonic-gate #include <sys/elf.h> 507c478bd9Sstevel@tonic-gate #include <sys/elf_SPARC.h> 517c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 527c478bd9Sstevel@tonic-gate #include <sys/spl.h> 537c478bd9Sstevel@tonic-gate #include <sys/privregs.h> 547c478bd9Sstevel@tonic-gate #include <sys/kobj.h> 557c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 567c478bd9Sstevel@tonic-gate #include <sys/reboot.h> 577c478bd9Sstevel@tonic-gate #include <sys/time.h> 587c478bd9Sstevel@tonic-gate #include <sys/panic.h> 597c478bd9Sstevel@tonic-gate #include <vm/seg_kmem.h> 607c478bd9Sstevel@tonic-gate #include <vm/page.h> 617c478bd9Sstevel@tonic-gate #include <sys/machpcb.h> 627c478bd9Sstevel@tonic-gate 637c478bd9Sstevel@tonic-gate extern struct bootops *bootops; 647c478bd9Sstevel@tonic-gate 657c478bd9Sstevel@tonic-gate /* 667c478bd9Sstevel@tonic-gate * Workaround for broken FDDI driver (remove when 4289172 is fixed) 677c478bd9Sstevel@tonic-gate */ 687c478bd9Sstevel@tonic-gate short cputype = 0x80; 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate extern int getpcstack_top(pc_t *pcstack, int limit, uintptr_t *lastfp, 717c478bd9Sstevel@tonic-gate pc_t *lastpc); 727c478bd9Sstevel@tonic-gate 737c478bd9Sstevel@tonic-gate /* 747c478bd9Sstevel@tonic-gate * Get a pc-only stacktrace. Used for kmem_alloc() buffer ownership tracking. 757c478bd9Sstevel@tonic-gate * Returns MIN(current stack depth, pcstack_limit). 767c478bd9Sstevel@tonic-gate */ 777c478bd9Sstevel@tonic-gate int 787c478bd9Sstevel@tonic-gate getpcstack(pc_t *pcstack, int pcstack_limit) 797c478bd9Sstevel@tonic-gate { 807c478bd9Sstevel@tonic-gate struct frame *fp, *minfp, *stacktop; 817c478bd9Sstevel@tonic-gate uintptr_t nextfp; 827c478bd9Sstevel@tonic-gate pc_t nextpc; 837c478bd9Sstevel@tonic-gate int depth; 847c478bd9Sstevel@tonic-gate int on_intr; 857c478bd9Sstevel@tonic-gate pc_t pcswin[MAXWIN]; 867c478bd9Sstevel@tonic-gate int npcwin = MIN(MAXWIN, pcstack_limit); 877c478bd9Sstevel@tonic-gate 887c478bd9Sstevel@tonic-gate if ((on_intr = CPU_ON_INTR(CPU)) != 0) 897c478bd9Sstevel@tonic-gate stacktop = (struct frame *)(CPU->cpu_intr_stack + SA(MINFRAME)); 907c478bd9Sstevel@tonic-gate else 917c478bd9Sstevel@tonic-gate stacktop = (struct frame *)curthread->t_stk; 927c478bd9Sstevel@tonic-gate 937c478bd9Sstevel@tonic-gate minfp = (struct frame *)((uintptr_t)getfp() + STACK_BIAS); 947c478bd9Sstevel@tonic-gate 957c478bd9Sstevel@tonic-gate /* 967c478bd9Sstevel@tonic-gate * getpcstack_top() processes the frames still in register windows, 977c478bd9Sstevel@tonic-gate * fills nextfp and nextpc with our starting point, and returns 987c478bd9Sstevel@tonic-gate * the number of frames it wrote into pcstack. 997c478bd9Sstevel@tonic-gate * 1007c478bd9Sstevel@tonic-gate * Since we cannot afford to take a relocation trap while we are 1017c478bd9Sstevel@tonic-gate * messing with register windows, we pass getpcstack_top() a buffer 1027c478bd9Sstevel@tonic-gate * on our stack and then copy the result out to the pcstack buffer 1037c478bd9Sstevel@tonic-gate * provided by the caller. The size of this buffer is the maximum 1047c478bd9Sstevel@tonic-gate * supported number of SPARC register windows; however we ASSERT 1057c478bd9Sstevel@tonic-gate * that it returns fewer than that, since it will skip the current 1067c478bd9Sstevel@tonic-gate * frame. 1077c478bd9Sstevel@tonic-gate */ 1087c478bd9Sstevel@tonic-gate npcwin = getpcstack_top(pcswin, npcwin, &nextfp, &nextpc); 1097c478bd9Sstevel@tonic-gate ASSERT(npcwin >= 0 && npcwin < MAXWIN && npcwin <= pcstack_limit); 1107c478bd9Sstevel@tonic-gate for (depth = 0; depth < npcwin; depth++) { 1117c478bd9Sstevel@tonic-gate pcstack[depth] = pcswin[depth]; 1127c478bd9Sstevel@tonic-gate } 1137c478bd9Sstevel@tonic-gate 1147c478bd9Sstevel@tonic-gate fp = (struct frame *)(nextfp + STACK_BIAS); 1157c478bd9Sstevel@tonic-gate 1167c478bd9Sstevel@tonic-gate while (depth < pcstack_limit) { 1177c478bd9Sstevel@tonic-gate if (fp <= minfp || fp >= stacktop) { 1187c478bd9Sstevel@tonic-gate if (on_intr) { 1197c478bd9Sstevel@tonic-gate /* 1207c478bd9Sstevel@tonic-gate * Hop from interrupt stack to thread stack. 1217c478bd9Sstevel@tonic-gate */ 1227c478bd9Sstevel@tonic-gate stacktop = (struct frame *)curthread->t_stk; 1237c478bd9Sstevel@tonic-gate minfp = (struct frame *)curthread->t_stkbase; 1247c478bd9Sstevel@tonic-gate on_intr = 0; 1257c478bd9Sstevel@tonic-gate continue; 1267c478bd9Sstevel@tonic-gate } 1277c478bd9Sstevel@tonic-gate break; 1287c478bd9Sstevel@tonic-gate } 1297c478bd9Sstevel@tonic-gate 1307c478bd9Sstevel@tonic-gate pcstack[depth++] = nextpc; 1317c478bd9Sstevel@tonic-gate minfp = fp; 1327c478bd9Sstevel@tonic-gate 1337c478bd9Sstevel@tonic-gate nextpc = (pc_t)fp->fr_savpc; 1347c478bd9Sstevel@tonic-gate fp = (struct frame *)((uintptr_t)fp->fr_savfp + STACK_BIAS); 1357c478bd9Sstevel@tonic-gate } 1367c478bd9Sstevel@tonic-gate 1377c478bd9Sstevel@tonic-gate return (depth); 1387c478bd9Sstevel@tonic-gate } 1397c478bd9Sstevel@tonic-gate 1407c478bd9Sstevel@tonic-gate /* 1417c478bd9Sstevel@tonic-gate * The following ELF header fields are defined as processor-specific 1427c478bd9Sstevel@tonic-gate * in the SPARC V8 ABI: 1437c478bd9Sstevel@tonic-gate * 1447c478bd9Sstevel@tonic-gate * e_ident[EI_DATA] encoding of the processor-specific 1457c478bd9Sstevel@tonic-gate * data in the object file 1467c478bd9Sstevel@tonic-gate * e_machine processor identification 1477c478bd9Sstevel@tonic-gate * e_flags processor-specific flags associated 1487c478bd9Sstevel@tonic-gate * with the file 1497c478bd9Sstevel@tonic-gate */ 1507c478bd9Sstevel@tonic-gate 1517c478bd9Sstevel@tonic-gate /* 1527c478bd9Sstevel@tonic-gate * The value of at_flags reflects a platform's cpu module support. 1537c478bd9Sstevel@tonic-gate * at_flags is used to check for allowing a binary to execute and 1547c478bd9Sstevel@tonic-gate * is passed as the value of the AT_FLAGS auxiliary vector. 1557c478bd9Sstevel@tonic-gate */ 1567c478bd9Sstevel@tonic-gate int at_flags = 0; 1577c478bd9Sstevel@tonic-gate 1587c478bd9Sstevel@tonic-gate /* 1597c478bd9Sstevel@tonic-gate * Check the processor-specific fields of an ELF header. 1607c478bd9Sstevel@tonic-gate * 1617c478bd9Sstevel@tonic-gate * returns 1 if the fields are valid, 0 otherwise 1627c478bd9Sstevel@tonic-gate */ 1637c478bd9Sstevel@tonic-gate int 1647c478bd9Sstevel@tonic-gate elfheadcheck( 1657c478bd9Sstevel@tonic-gate unsigned char e_data, 1667c478bd9Sstevel@tonic-gate Elf32_Half e_machine, 1677c478bd9Sstevel@tonic-gate Elf32_Word e_flags) 1687c478bd9Sstevel@tonic-gate { 1697c478bd9Sstevel@tonic-gate Elf32_Word needed_flags; 1707c478bd9Sstevel@tonic-gate int supported_flags; 1717c478bd9Sstevel@tonic-gate 1727c478bd9Sstevel@tonic-gate if (e_data != ELFDATA2MSB) 1737c478bd9Sstevel@tonic-gate return (0); 1747c478bd9Sstevel@tonic-gate 1757c478bd9Sstevel@tonic-gate switch (e_machine) { 1767c478bd9Sstevel@tonic-gate case EM_SPARC: 1777c478bd9Sstevel@tonic-gate if (e_flags == 0) 1787c478bd9Sstevel@tonic-gate return (1); 1797c478bd9Sstevel@tonic-gate else 1807c478bd9Sstevel@tonic-gate return (0); 1817c478bd9Sstevel@tonic-gate case EM_SPARCV9: 1827c478bd9Sstevel@tonic-gate /* 1837c478bd9Sstevel@tonic-gate * Check that ELF flags are set to supported SPARC V9 flags 1847c478bd9Sstevel@tonic-gate */ 1857c478bd9Sstevel@tonic-gate needed_flags = e_flags & EF_SPARC_EXT_MASK; 1867c478bd9Sstevel@tonic-gate supported_flags = at_flags & ~EF_SPARC_32PLUS; 1877c478bd9Sstevel@tonic-gate 1887c478bd9Sstevel@tonic-gate if (needed_flags & ~supported_flags) 1897c478bd9Sstevel@tonic-gate return (0); 1907c478bd9Sstevel@tonic-gate else 1917c478bd9Sstevel@tonic-gate return (1); 1927c478bd9Sstevel@tonic-gate case EM_SPARC32PLUS: 1937c478bd9Sstevel@tonic-gate if ((e_flags & EF_SPARC_32PLUS) != 0 && 1947c478bd9Sstevel@tonic-gate ((e_flags & ~at_flags) & EF_SPARC_32PLUS_MASK) == 0) 1957c478bd9Sstevel@tonic-gate return (1); 1967c478bd9Sstevel@tonic-gate else 1977c478bd9Sstevel@tonic-gate return (0); 1987c478bd9Sstevel@tonic-gate default: 1997c478bd9Sstevel@tonic-gate return (0); 2007c478bd9Sstevel@tonic-gate } 2017c478bd9Sstevel@tonic-gate } 2027c478bd9Sstevel@tonic-gate 2037c478bd9Sstevel@tonic-gate uint_t auxv_hwcap_include = 0; /* patch to enable unrecognized features */ 2047c478bd9Sstevel@tonic-gate uint_t auxv_hwcap_exclude = 0; /* patch for broken cpus, debugging */ 2057c478bd9Sstevel@tonic-gate #if defined(_SYSCALL32_IMPL) 2067c478bd9Sstevel@tonic-gate uint_t auxv_hwcap32_include = 0; /* ditto for 32-bit apps */ 2077c478bd9Sstevel@tonic-gate uint_t auxv_hwcap32_exclude = 0; /* ditto for 32-bit apps */ 2087c478bd9Sstevel@tonic-gate #endif 2097c478bd9Sstevel@tonic-gate 2107c478bd9Sstevel@tonic-gate uint_t cpu_hwcap_flags = 0; /* set by cpu-dependent code */ 2117c478bd9Sstevel@tonic-gate 2127c478bd9Sstevel@tonic-gate /* 2137c478bd9Sstevel@tonic-gate * Gather information about the processor and place it into auxv_hwcap 2147c478bd9Sstevel@tonic-gate * so that it can be exported to the linker via the aux vector. 2157c478bd9Sstevel@tonic-gate * 2167c478bd9Sstevel@tonic-gate * We use this seemingly complicated mechanism so that we can ensure 2177c478bd9Sstevel@tonic-gate * that /etc/system can be used to override what the system can or 2187c478bd9Sstevel@tonic-gate * cannot discover for itself. 2197c478bd9Sstevel@tonic-gate */ 2207c478bd9Sstevel@tonic-gate void 2217c478bd9Sstevel@tonic-gate bind_hwcap(void) 2227c478bd9Sstevel@tonic-gate { 2237c478bd9Sstevel@tonic-gate auxv_hwcap = (auxv_hwcap_include | cpu_hwcap_flags) & 2247c478bd9Sstevel@tonic-gate ~auxv_hwcap_exclude; 2257c478bd9Sstevel@tonic-gate 2267c478bd9Sstevel@tonic-gate if (auxv_hwcap_include || auxv_hwcap_exclude) 2277c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "?user ABI extensions: %b\n", 2287c478bd9Sstevel@tonic-gate auxv_hwcap, FMT_AV_SPARC); 2297c478bd9Sstevel@tonic-gate 2307c478bd9Sstevel@tonic-gate #if defined(_SYSCALL32_IMPL) 2317c478bd9Sstevel@tonic-gate /* 2327c478bd9Sstevel@tonic-gate * These are now a compatibility artifact; all supported SPARC CPUs 2337c478bd9Sstevel@tonic-gate * are V9-capable (and thus support v8plus) and fully implement 2347c478bd9Sstevel@tonic-gate * {s,u}mul and {s,u}div. 2357c478bd9Sstevel@tonic-gate */ 2367c478bd9Sstevel@tonic-gate cpu_hwcap_flags |= AV_SPARC_MUL32 | AV_SPARC_DIV32 | AV_SPARC_V8PLUS; 2377c478bd9Sstevel@tonic-gate 2387c478bd9Sstevel@tonic-gate auxv_hwcap32 = (auxv_hwcap32_include | cpu_hwcap_flags) & 2397c478bd9Sstevel@tonic-gate ~auxv_hwcap32_exclude; 2407c478bd9Sstevel@tonic-gate 2417c478bd9Sstevel@tonic-gate if (auxv_hwcap32_include || auxv_hwcap32_exclude) 2427c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "?32-bit user ABI extensions: %b\n", 2437c478bd9Sstevel@tonic-gate auxv_hwcap32, FMT_AV_SPARC); 2447c478bd9Sstevel@tonic-gate #endif 2457c478bd9Sstevel@tonic-gate } 2467c478bd9Sstevel@tonic-gate 2477c478bd9Sstevel@tonic-gate int 2487c478bd9Sstevel@tonic-gate __ipltospl(int ipl) 2497c478bd9Sstevel@tonic-gate { 2507c478bd9Sstevel@tonic-gate return (ipltospl(ipl)); 2517c478bd9Sstevel@tonic-gate } 2527c478bd9Sstevel@tonic-gate 2537c478bd9Sstevel@tonic-gate /* 2547c478bd9Sstevel@tonic-gate * Print a stack backtrace using the specified stack pointer. We delay two 255*f6e214c7SGavin Maltby * seconds before continuing, unless this is the panic traceback. 256*f6e214c7SGavin Maltby * If we are in the process of panicking, we also attempt to write the 257*f6e214c7SGavin Maltby * stack backtrace to a staticly assigned buffer, to allow the panic 258*f6e214c7SGavin Maltby * code to find it and write it in to uncompressed pages within the 259*f6e214c7SGavin Maltby * system crash dump. 260*f6e214c7SGavin Maltby * 261*f6e214c7SGavin Maltby * Note that the frame for the starting stack pointer value is omitted because 2627c478bd9Sstevel@tonic-gate * the corresponding %pc is not known. 2637c478bd9Sstevel@tonic-gate */ 264*f6e214c7SGavin Maltby 265*f6e214c7SGavin Maltby extern char *dump_stack_scratch; 266*f6e214c7SGavin Maltby 2677c478bd9Sstevel@tonic-gate void 2687c478bd9Sstevel@tonic-gate traceback(caddr_t sp) 2697c478bd9Sstevel@tonic-gate { 2707c478bd9Sstevel@tonic-gate struct frame *fp = (struct frame *)(sp + STACK_BIAS); 2717c478bd9Sstevel@tonic-gate struct frame *nextfp, *minfp, *stacktop; 2727c478bd9Sstevel@tonic-gate int on_intr; 2737c478bd9Sstevel@tonic-gate 2747c478bd9Sstevel@tonic-gate cpu_t *cpu; 2757c478bd9Sstevel@tonic-gate 276*f6e214c7SGavin Maltby uint_t offset = 0; 277*f6e214c7SGavin Maltby uint_t next_offset = 0; 278*f6e214c7SGavin Maltby char stack_buffer[2048]; 279*f6e214c7SGavin Maltby char local_buffer[1024]; 280*f6e214c7SGavin Maltby 2817c478bd9Sstevel@tonic-gate flush_windows(); 2827c478bd9Sstevel@tonic-gate 2837c478bd9Sstevel@tonic-gate if (!panicstr) 2847c478bd9Sstevel@tonic-gate printf("traceback: %%sp = %p\n", (void *)sp); 2857c478bd9Sstevel@tonic-gate 286*f6e214c7SGavin Maltby if (panicstr && !dump_stack_scratch) { 287*f6e214c7SGavin Maltby printf("Warning - stack not written to the dumpbuf\n"); 288*f6e214c7SGavin Maltby } 289*f6e214c7SGavin Maltby 2907c478bd9Sstevel@tonic-gate /* 2917c478bd9Sstevel@tonic-gate * If we are panicking, the high-level interrupt information in 2927c478bd9Sstevel@tonic-gate * CPU was overwritten. panic_cpu has the correct values. 2937c478bd9Sstevel@tonic-gate */ 2947c478bd9Sstevel@tonic-gate kpreempt_disable(); /* prevent migration */ 2957c478bd9Sstevel@tonic-gate 2967c478bd9Sstevel@tonic-gate cpu = (panicstr && CPU->cpu_id == panic_cpu.cpu_id)? &panic_cpu : CPU; 2977c478bd9Sstevel@tonic-gate 2987c478bd9Sstevel@tonic-gate if ((on_intr = CPU_ON_INTR(cpu)) != 0) 2997c478bd9Sstevel@tonic-gate stacktop = (struct frame *)(cpu->cpu_intr_stack + SA(MINFRAME)); 3007c478bd9Sstevel@tonic-gate else 3017c478bd9Sstevel@tonic-gate stacktop = (struct frame *)curthread->t_stk; 3027c478bd9Sstevel@tonic-gate 3037c478bd9Sstevel@tonic-gate kpreempt_enable(); 3047c478bd9Sstevel@tonic-gate 3057c478bd9Sstevel@tonic-gate minfp = fp; 3067c478bd9Sstevel@tonic-gate 3077c478bd9Sstevel@tonic-gate while ((uintptr_t)fp >= KERNELBASE) { 3087c478bd9Sstevel@tonic-gate uintptr_t pc = (uintptr_t)fp->fr_savpc; 3097c478bd9Sstevel@tonic-gate ulong_t off; 3107c478bd9Sstevel@tonic-gate char *sym; 3117c478bd9Sstevel@tonic-gate 3127c478bd9Sstevel@tonic-gate nextfp = (struct frame *)((uintptr_t)fp->fr_savfp + STACK_BIAS); 3137c478bd9Sstevel@tonic-gate if (nextfp <= minfp || nextfp >= stacktop) { 3147c478bd9Sstevel@tonic-gate if (on_intr) { 3157c478bd9Sstevel@tonic-gate /* 3167c478bd9Sstevel@tonic-gate * Hop from interrupt stack to thread stack. 3177c478bd9Sstevel@tonic-gate */ 3187c478bd9Sstevel@tonic-gate stacktop = (struct frame *)curthread->t_stk; 3197c478bd9Sstevel@tonic-gate minfp = (struct frame *)curthread->t_stkbase; 3207c478bd9Sstevel@tonic-gate on_intr = 0; 3217c478bd9Sstevel@tonic-gate continue; 3227c478bd9Sstevel@tonic-gate } 3237c478bd9Sstevel@tonic-gate break; /* we're outside of the expected range */ 3247c478bd9Sstevel@tonic-gate } 3257c478bd9Sstevel@tonic-gate 3267c478bd9Sstevel@tonic-gate if ((uintptr_t)nextfp & (STACK_ALIGN - 1)) { 3277c478bd9Sstevel@tonic-gate printf(" >> mis-aligned %%fp = %p\n", (void *)nextfp); 3287c478bd9Sstevel@tonic-gate break; 3297c478bd9Sstevel@tonic-gate } 3307c478bd9Sstevel@tonic-gate 3317c478bd9Sstevel@tonic-gate if ((sym = kobj_getsymname(pc, &off)) != NULL) { 3327c478bd9Sstevel@tonic-gate printf("%016lx %s:%s+%lx " 3337c478bd9Sstevel@tonic-gate "(%lx, %lx, %lx, %lx, %lx, %lx)\n", (ulong_t)nextfp, 3347c478bd9Sstevel@tonic-gate mod_containing_pc((caddr_t)pc), sym, off, 3357c478bd9Sstevel@tonic-gate nextfp->fr_arg[0], nextfp->fr_arg[1], 3367c478bd9Sstevel@tonic-gate nextfp->fr_arg[2], nextfp->fr_arg[3], 3377c478bd9Sstevel@tonic-gate nextfp->fr_arg[4], nextfp->fr_arg[5]); 338*f6e214c7SGavin Maltby (void) snprintf(stack_buffer, sizeof (stack_buffer), 339*f6e214c7SGavin Maltby "%s:%s+%lx " 340*f6e214c7SGavin Maltby "(%lx, %lx, %lx, %lx, %lx, %lx) | ", 341*f6e214c7SGavin Maltby mod_containing_pc((caddr_t)pc), sym, off, 342*f6e214c7SGavin Maltby nextfp->fr_arg[0], nextfp->fr_arg[1], 343*f6e214c7SGavin Maltby nextfp->fr_arg[2], nextfp->fr_arg[3], 344*f6e214c7SGavin Maltby nextfp->fr_arg[4], nextfp->fr_arg[5]); 3457c478bd9Sstevel@tonic-gate } else { 346*f6e214c7SGavin Maltby (void) printf("%016lx %p (%lx, %lx, %lx, " 347*f6e214c7SGavin Maltby "%lx, %lx, %lx)\n", 3487c478bd9Sstevel@tonic-gate (ulong_t)nextfp, (void *)pc, 3497c478bd9Sstevel@tonic-gate nextfp->fr_arg[0], nextfp->fr_arg[1], 3507c478bd9Sstevel@tonic-gate nextfp->fr_arg[2], nextfp->fr_arg[3], 3517c478bd9Sstevel@tonic-gate nextfp->fr_arg[4], nextfp->fr_arg[5]); 352*f6e214c7SGavin Maltby (void) snprintf(stack_buffer, sizeof (stack_buffer), 353*f6e214c7SGavin Maltby "%p (%lx, %lx, %lx, %lx, %lx, %lx) | ", 354*f6e214c7SGavin Maltby (void *)pc, 355*f6e214c7SGavin Maltby nextfp->fr_arg[0], nextfp->fr_arg[1], 356*f6e214c7SGavin Maltby nextfp->fr_arg[2], nextfp->fr_arg[3], 357*f6e214c7SGavin Maltby nextfp->fr_arg[4], nextfp->fr_arg[5]); 3587c478bd9Sstevel@tonic-gate } 3597c478bd9Sstevel@tonic-gate 360*f6e214c7SGavin Maltby (void) snprintf(local_buffer, sizeof (local_buffer), 361*f6e214c7SGavin Maltby " %%l0-3: %016lx %016lx %016lx %016lx\n" 3627c478bd9Sstevel@tonic-gate " %%l4-7: %016lx %016lx %016lx %016lx\n", 3637c478bd9Sstevel@tonic-gate nextfp->fr_local[0], nextfp->fr_local[1], 3647c478bd9Sstevel@tonic-gate nextfp->fr_local[2], nextfp->fr_local[3], 3657c478bd9Sstevel@tonic-gate nextfp->fr_local[4], nextfp->fr_local[5], 3667c478bd9Sstevel@tonic-gate nextfp->fr_local[6], nextfp->fr_local[7]); 367*f6e214c7SGavin Maltby if (panicstr && dump_stack_scratch) { 368*f6e214c7SGavin Maltby next_offset = offset + strlen(stack_buffer); 369*f6e214c7SGavin Maltby if (next_offset < STACK_BUF_SIZE) { 370*f6e214c7SGavin Maltby bcopy(stack_buffer, dump_stack_scratch + offset, 371*f6e214c7SGavin Maltby strlen(stack_buffer)); 372*f6e214c7SGavin Maltby offset = next_offset; 373*f6e214c7SGavin Maltby } else { 374*f6e214c7SGavin Maltby /* 375*f6e214c7SGavin Maltby * In attempting to save the panic stack 376*f6e214c7SGavin Maltby * to the dumpbuf we have overflowed that area. 377*f6e214c7SGavin Maltby * Print a warning and continue to printf the 378*f6e214c7SGavin Maltby * stack to the msgbuf 379*f6e214c7SGavin Maltby */ 380*f6e214c7SGavin Maltby printf("Warning: stack in the dump buffer" 381*f6e214c7SGavin Maltby " may be incomplete\n"); 382*f6e214c7SGavin Maltby } 383*f6e214c7SGavin Maltby } 384*f6e214c7SGavin Maltby printf("%s", local_buffer); 3857c478bd9Sstevel@tonic-gate 3867c478bd9Sstevel@tonic-gate fp = nextfp; 3877c478bd9Sstevel@tonic-gate minfp = fp; 3887c478bd9Sstevel@tonic-gate } 3897c478bd9Sstevel@tonic-gate 3907c478bd9Sstevel@tonic-gate if (!panicstr) { 3917c478bd9Sstevel@tonic-gate printf("end of traceback\n"); 3927c478bd9Sstevel@tonic-gate DELAY(2 * MICROSEC); 393*f6e214c7SGavin Maltby } else if (dump_stack_scratch) { 394*f6e214c7SGavin Maltby dump_stack_scratch[offset] = '\0'; 3957c478bd9Sstevel@tonic-gate } 3967c478bd9Sstevel@tonic-gate } 3977c478bd9Sstevel@tonic-gate 3987c478bd9Sstevel@tonic-gate /* 3997c478bd9Sstevel@tonic-gate * Generate a stack backtrace from a saved register set. 4007c478bd9Sstevel@tonic-gate */ 4017c478bd9Sstevel@tonic-gate void 4027c478bd9Sstevel@tonic-gate traceregs(struct regs *rp) 4037c478bd9Sstevel@tonic-gate { 4047c478bd9Sstevel@tonic-gate traceback((caddr_t)rp->r_sp); 4057c478bd9Sstevel@tonic-gate } 4067c478bd9Sstevel@tonic-gate 4077c478bd9Sstevel@tonic-gate void 4087c478bd9Sstevel@tonic-gate exec_set_sp(size_t stksize) 4097c478bd9Sstevel@tonic-gate { 4107c478bd9Sstevel@tonic-gate klwp_t *lwp = ttolwp(curthread); 4117c478bd9Sstevel@tonic-gate 4127c478bd9Sstevel@tonic-gate lwp->lwp_pcb.pcb_xregstat = XREGNONE; 4137c478bd9Sstevel@tonic-gate if (curproc->p_model == DATAMODEL_NATIVE) 4147c478bd9Sstevel@tonic-gate stksize += sizeof (struct rwindow) + STACK_BIAS; 4157c478bd9Sstevel@tonic-gate else 4167c478bd9Sstevel@tonic-gate stksize += sizeof (struct rwindow32); 4177c478bd9Sstevel@tonic-gate lwptoregs(lwp)->r_sp = (uintptr_t)curproc->p_usrstack - stksize; 4187c478bd9Sstevel@tonic-gate } 4197c478bd9Sstevel@tonic-gate 4207c478bd9Sstevel@tonic-gate /* 4217c478bd9Sstevel@tonic-gate * Allocate a region of virtual address space, unmapped. 4227c478bd9Sstevel@tonic-gate * 4237c478bd9Sstevel@tonic-gate * When a hard-redzone (firewall) is in effect, redzone violations are 4247c478bd9Sstevel@tonic-gate * caught by the hardware the instant they happen because the first byte 4257c478bd9Sstevel@tonic-gate * past the logical end of a firewalled buffer lies at the start of an 4267c478bd9Sstevel@tonic-gate * unmapped page. This firewalling is accomplished by bumping up the 4277c478bd9Sstevel@tonic-gate * requested address allocation, effectively removing an additional page 4287c478bd9Sstevel@tonic-gate * beyond the original request from the available virtual memory arena. 4297c478bd9Sstevel@tonic-gate * However, the size of the allocation passed to boot, in boot_alloc(), 4307c478bd9Sstevel@tonic-gate * doesn't reflect this additional page and fragmentation of the OBP 4317c478bd9Sstevel@tonic-gate * "virtual-memory" "available" lists property occurs. Calling 4327c478bd9Sstevel@tonic-gate * prom_claim_virt() for the firewall page avoids this fragmentation. 4337c478bd9Sstevel@tonic-gate */ 4347c478bd9Sstevel@tonic-gate void * 4357c478bd9Sstevel@tonic-gate boot_virt_alloc(void *addr, size_t size) 4367c478bd9Sstevel@tonic-gate { 437986fd29aSsetje return (BOP_ALLOC_VIRT((caddr_t)addr, size)); 4387c478bd9Sstevel@tonic-gate } 4397c478bd9Sstevel@tonic-gate 4407c478bd9Sstevel@tonic-gate 4417c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 4427c478bd9Sstevel@tonic-gate int 4437c478bd9Sstevel@tonic-gate xcopyin_nta(const void *uaddr, void *kaddr, size_t count, int dummy) 4447c478bd9Sstevel@tonic-gate { 4457c478bd9Sstevel@tonic-gate return (xcopyin(uaddr, kaddr, count)); 4467c478bd9Sstevel@tonic-gate } 4477c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 4487c478bd9Sstevel@tonic-gate int 4497c478bd9Sstevel@tonic-gate xcopyout_nta(const void *kaddr, void *uaddr, size_t count, int dummy) 4507c478bd9Sstevel@tonic-gate { 4517c478bd9Sstevel@tonic-gate return (xcopyout(kaddr, uaddr, count)); 4527c478bd9Sstevel@tonic-gate } 4537c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 4547c478bd9Sstevel@tonic-gate int 4557c478bd9Sstevel@tonic-gate kcopy_nta(const void *from, void *to, size_t count, int dummy) 4567c478bd9Sstevel@tonic-gate { 4577c478bd9Sstevel@tonic-gate return (kcopy(from, to, count)); 4587c478bd9Sstevel@tonic-gate } 459