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 5*986fd29aSsetje * Common Development and Distribution License (the "License"). 6*986fd29aSsetje * 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*986fd29aSsetje * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 277c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 317c478bd9Sstevel@tonic-gate 327c478bd9Sstevel@tonic-gate #include <sys/param.h> 337c478bd9Sstevel@tonic-gate #include <sys/types.h> 347c478bd9Sstevel@tonic-gate #include <sys/vmparam.h> 357c478bd9Sstevel@tonic-gate #include <sys/systm.h> 367c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 377c478bd9Sstevel@tonic-gate #include <sys/signal.h> 387c478bd9Sstevel@tonic-gate #include <sys/stack.h> 397c478bd9Sstevel@tonic-gate #include <sys/frame.h> 407c478bd9Sstevel@tonic-gate #include <sys/proc.h> 417c478bd9Sstevel@tonic-gate #include <sys/ucontext.h> 427c478bd9Sstevel@tonic-gate #include <sys/siginfo.h> 437c478bd9Sstevel@tonic-gate #include <sys/cpuvar.h> 447c478bd9Sstevel@tonic-gate #include <sys/asm_linkage.h> 457c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 467c478bd9Sstevel@tonic-gate #include <sys/errno.h> 477c478bd9Sstevel@tonic-gate #include <sys/bootconf.h> 487c478bd9Sstevel@tonic-gate #include <sys/archsystm.h> 497c478bd9Sstevel@tonic-gate #include <sys/fpu/fpusystm.h> 507c478bd9Sstevel@tonic-gate #include <sys/auxv.h> 517c478bd9Sstevel@tonic-gate #include <sys/debug.h> 527c478bd9Sstevel@tonic-gate #include <sys/elf.h> 537c478bd9Sstevel@tonic-gate #include <sys/elf_SPARC.h> 547c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 557c478bd9Sstevel@tonic-gate #include <sys/spl.h> 567c478bd9Sstevel@tonic-gate #include <sys/privregs.h> 577c478bd9Sstevel@tonic-gate #include <sys/kobj.h> 587c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 597c478bd9Sstevel@tonic-gate #include <sys/reboot.h> 607c478bd9Sstevel@tonic-gate #include <sys/time.h> 617c478bd9Sstevel@tonic-gate #include <sys/panic.h> 627c478bd9Sstevel@tonic-gate #include <vm/seg_kmem.h> 637c478bd9Sstevel@tonic-gate #include <vm/page.h> 647c478bd9Sstevel@tonic-gate #include <sys/machpcb.h> 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gate extern struct bootops *bootops; 677c478bd9Sstevel@tonic-gate 687c478bd9Sstevel@tonic-gate /* 697c478bd9Sstevel@tonic-gate * Workaround for broken FDDI driver (remove when 4289172 is fixed) 707c478bd9Sstevel@tonic-gate */ 717c478bd9Sstevel@tonic-gate short cputype = 0x80; 727c478bd9Sstevel@tonic-gate 737c478bd9Sstevel@tonic-gate extern int getpcstack_top(pc_t *pcstack, int limit, uintptr_t *lastfp, 747c478bd9Sstevel@tonic-gate pc_t *lastpc); 757c478bd9Sstevel@tonic-gate 767c478bd9Sstevel@tonic-gate /* 777c478bd9Sstevel@tonic-gate * Get a pc-only stacktrace. Used for kmem_alloc() buffer ownership tracking. 787c478bd9Sstevel@tonic-gate * Returns MIN(current stack depth, pcstack_limit). 797c478bd9Sstevel@tonic-gate */ 807c478bd9Sstevel@tonic-gate int 817c478bd9Sstevel@tonic-gate getpcstack(pc_t *pcstack, int pcstack_limit) 827c478bd9Sstevel@tonic-gate { 837c478bd9Sstevel@tonic-gate struct frame *fp, *minfp, *stacktop; 847c478bd9Sstevel@tonic-gate uintptr_t nextfp; 857c478bd9Sstevel@tonic-gate pc_t nextpc; 867c478bd9Sstevel@tonic-gate int depth; 877c478bd9Sstevel@tonic-gate int on_intr; 887c478bd9Sstevel@tonic-gate pc_t pcswin[MAXWIN]; 897c478bd9Sstevel@tonic-gate int npcwin = MIN(MAXWIN, pcstack_limit); 907c478bd9Sstevel@tonic-gate 917c478bd9Sstevel@tonic-gate if ((on_intr = CPU_ON_INTR(CPU)) != 0) 927c478bd9Sstevel@tonic-gate stacktop = (struct frame *)(CPU->cpu_intr_stack + SA(MINFRAME)); 937c478bd9Sstevel@tonic-gate else 947c478bd9Sstevel@tonic-gate stacktop = (struct frame *)curthread->t_stk; 957c478bd9Sstevel@tonic-gate 967c478bd9Sstevel@tonic-gate minfp = (struct frame *)((uintptr_t)getfp() + STACK_BIAS); 977c478bd9Sstevel@tonic-gate 987c478bd9Sstevel@tonic-gate /* 997c478bd9Sstevel@tonic-gate * getpcstack_top() processes the frames still in register windows, 1007c478bd9Sstevel@tonic-gate * fills nextfp and nextpc with our starting point, and returns 1017c478bd9Sstevel@tonic-gate * the number of frames it wrote into pcstack. 1027c478bd9Sstevel@tonic-gate * 1037c478bd9Sstevel@tonic-gate * Since we cannot afford to take a relocation trap while we are 1047c478bd9Sstevel@tonic-gate * messing with register windows, we pass getpcstack_top() a buffer 1057c478bd9Sstevel@tonic-gate * on our stack and then copy the result out to the pcstack buffer 1067c478bd9Sstevel@tonic-gate * provided by the caller. The size of this buffer is the maximum 1077c478bd9Sstevel@tonic-gate * supported number of SPARC register windows; however we ASSERT 1087c478bd9Sstevel@tonic-gate * that it returns fewer than that, since it will skip the current 1097c478bd9Sstevel@tonic-gate * frame. 1107c478bd9Sstevel@tonic-gate */ 1117c478bd9Sstevel@tonic-gate npcwin = getpcstack_top(pcswin, npcwin, &nextfp, &nextpc); 1127c478bd9Sstevel@tonic-gate ASSERT(npcwin >= 0 && npcwin < MAXWIN && npcwin <= pcstack_limit); 1137c478bd9Sstevel@tonic-gate for (depth = 0; depth < npcwin; depth++) { 1147c478bd9Sstevel@tonic-gate pcstack[depth] = pcswin[depth]; 1157c478bd9Sstevel@tonic-gate } 1167c478bd9Sstevel@tonic-gate 1177c478bd9Sstevel@tonic-gate fp = (struct frame *)(nextfp + STACK_BIAS); 1187c478bd9Sstevel@tonic-gate 1197c478bd9Sstevel@tonic-gate while (depth < pcstack_limit) { 1207c478bd9Sstevel@tonic-gate if (fp <= minfp || fp >= stacktop) { 1217c478bd9Sstevel@tonic-gate if (on_intr) { 1227c478bd9Sstevel@tonic-gate /* 1237c478bd9Sstevel@tonic-gate * Hop from interrupt stack to thread stack. 1247c478bd9Sstevel@tonic-gate */ 1257c478bd9Sstevel@tonic-gate stacktop = (struct frame *)curthread->t_stk; 1267c478bd9Sstevel@tonic-gate minfp = (struct frame *)curthread->t_stkbase; 1277c478bd9Sstevel@tonic-gate on_intr = 0; 1287c478bd9Sstevel@tonic-gate continue; 1297c478bd9Sstevel@tonic-gate } 1307c478bd9Sstevel@tonic-gate break; 1317c478bd9Sstevel@tonic-gate } 1327c478bd9Sstevel@tonic-gate 1337c478bd9Sstevel@tonic-gate pcstack[depth++] = nextpc; 1347c478bd9Sstevel@tonic-gate minfp = fp; 1357c478bd9Sstevel@tonic-gate 1367c478bd9Sstevel@tonic-gate nextpc = (pc_t)fp->fr_savpc; 1377c478bd9Sstevel@tonic-gate fp = (struct frame *)((uintptr_t)fp->fr_savfp + STACK_BIAS); 1387c478bd9Sstevel@tonic-gate } 1397c478bd9Sstevel@tonic-gate 1407c478bd9Sstevel@tonic-gate return (depth); 1417c478bd9Sstevel@tonic-gate } 1427c478bd9Sstevel@tonic-gate 1437c478bd9Sstevel@tonic-gate /* 1447c478bd9Sstevel@tonic-gate * The following ELF header fields are defined as processor-specific 1457c478bd9Sstevel@tonic-gate * in the SPARC V8 ABI: 1467c478bd9Sstevel@tonic-gate * 1477c478bd9Sstevel@tonic-gate * e_ident[EI_DATA] encoding of the processor-specific 1487c478bd9Sstevel@tonic-gate * data in the object file 1497c478bd9Sstevel@tonic-gate * e_machine processor identification 1507c478bd9Sstevel@tonic-gate * e_flags processor-specific flags associated 1517c478bd9Sstevel@tonic-gate * with the file 1527c478bd9Sstevel@tonic-gate */ 1537c478bd9Sstevel@tonic-gate 1547c478bd9Sstevel@tonic-gate /* 1557c478bd9Sstevel@tonic-gate * The value of at_flags reflects a platform's cpu module support. 1567c478bd9Sstevel@tonic-gate * at_flags is used to check for allowing a binary to execute and 1577c478bd9Sstevel@tonic-gate * is passed as the value of the AT_FLAGS auxiliary vector. 1587c478bd9Sstevel@tonic-gate */ 1597c478bd9Sstevel@tonic-gate int at_flags = 0; 1607c478bd9Sstevel@tonic-gate 1617c478bd9Sstevel@tonic-gate /* 1627c478bd9Sstevel@tonic-gate * Check the processor-specific fields of an ELF header. 1637c478bd9Sstevel@tonic-gate * 1647c478bd9Sstevel@tonic-gate * returns 1 if the fields are valid, 0 otherwise 1657c478bd9Sstevel@tonic-gate */ 1667c478bd9Sstevel@tonic-gate int 1677c478bd9Sstevel@tonic-gate elfheadcheck( 1687c478bd9Sstevel@tonic-gate unsigned char e_data, 1697c478bd9Sstevel@tonic-gate Elf32_Half e_machine, 1707c478bd9Sstevel@tonic-gate Elf32_Word e_flags) 1717c478bd9Sstevel@tonic-gate { 1727c478bd9Sstevel@tonic-gate Elf32_Word needed_flags; 1737c478bd9Sstevel@tonic-gate int supported_flags; 1747c478bd9Sstevel@tonic-gate 1757c478bd9Sstevel@tonic-gate if (e_data != ELFDATA2MSB) 1767c478bd9Sstevel@tonic-gate return (0); 1777c478bd9Sstevel@tonic-gate 1787c478bd9Sstevel@tonic-gate switch (e_machine) { 1797c478bd9Sstevel@tonic-gate case EM_SPARC: 1807c478bd9Sstevel@tonic-gate if (e_flags == 0) 1817c478bd9Sstevel@tonic-gate return (1); 1827c478bd9Sstevel@tonic-gate else 1837c478bd9Sstevel@tonic-gate return (0); 1847c478bd9Sstevel@tonic-gate case EM_SPARCV9: 1857c478bd9Sstevel@tonic-gate /* 1867c478bd9Sstevel@tonic-gate * Check that ELF flags are set to supported SPARC V9 flags 1877c478bd9Sstevel@tonic-gate */ 1887c478bd9Sstevel@tonic-gate needed_flags = e_flags & EF_SPARC_EXT_MASK; 1897c478bd9Sstevel@tonic-gate supported_flags = at_flags & ~EF_SPARC_32PLUS; 1907c478bd9Sstevel@tonic-gate 1917c478bd9Sstevel@tonic-gate if (needed_flags & ~supported_flags) 1927c478bd9Sstevel@tonic-gate return (0); 1937c478bd9Sstevel@tonic-gate else 1947c478bd9Sstevel@tonic-gate return (1); 1957c478bd9Sstevel@tonic-gate case EM_SPARC32PLUS: 1967c478bd9Sstevel@tonic-gate if ((e_flags & EF_SPARC_32PLUS) != 0 && 1977c478bd9Sstevel@tonic-gate ((e_flags & ~at_flags) & EF_SPARC_32PLUS_MASK) == 0) 1987c478bd9Sstevel@tonic-gate return (1); 1997c478bd9Sstevel@tonic-gate else 2007c478bd9Sstevel@tonic-gate return (0); 2017c478bd9Sstevel@tonic-gate default: 2027c478bd9Sstevel@tonic-gate return (0); 2037c478bd9Sstevel@tonic-gate } 2047c478bd9Sstevel@tonic-gate } 2057c478bd9Sstevel@tonic-gate 2067c478bd9Sstevel@tonic-gate uint_t auxv_hwcap_include = 0; /* patch to enable unrecognized features */ 2077c478bd9Sstevel@tonic-gate uint_t auxv_hwcap_exclude = 0; /* patch for broken cpus, debugging */ 2087c478bd9Sstevel@tonic-gate #if defined(_SYSCALL32_IMPL) 2097c478bd9Sstevel@tonic-gate uint_t auxv_hwcap32_include = 0; /* ditto for 32-bit apps */ 2107c478bd9Sstevel@tonic-gate uint_t auxv_hwcap32_exclude = 0; /* ditto for 32-bit apps */ 2117c478bd9Sstevel@tonic-gate #endif 2127c478bd9Sstevel@tonic-gate 2137c478bd9Sstevel@tonic-gate uint_t cpu_hwcap_flags = 0; /* set by cpu-dependent code */ 2147c478bd9Sstevel@tonic-gate 2157c478bd9Sstevel@tonic-gate /* 2167c478bd9Sstevel@tonic-gate * Gather information about the processor and place it into auxv_hwcap 2177c478bd9Sstevel@tonic-gate * so that it can be exported to the linker via the aux vector. 2187c478bd9Sstevel@tonic-gate * 2197c478bd9Sstevel@tonic-gate * We use this seemingly complicated mechanism so that we can ensure 2207c478bd9Sstevel@tonic-gate * that /etc/system can be used to override what the system can or 2217c478bd9Sstevel@tonic-gate * cannot discover for itself. 2227c478bd9Sstevel@tonic-gate */ 2237c478bd9Sstevel@tonic-gate void 2247c478bd9Sstevel@tonic-gate bind_hwcap(void) 2257c478bd9Sstevel@tonic-gate { 2267c478bd9Sstevel@tonic-gate auxv_hwcap = (auxv_hwcap_include | cpu_hwcap_flags) & 2277c478bd9Sstevel@tonic-gate ~auxv_hwcap_exclude; 2287c478bd9Sstevel@tonic-gate 2297c478bd9Sstevel@tonic-gate if (auxv_hwcap_include || auxv_hwcap_exclude) 2307c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "?user ABI extensions: %b\n", 2317c478bd9Sstevel@tonic-gate auxv_hwcap, FMT_AV_SPARC); 2327c478bd9Sstevel@tonic-gate 2337c478bd9Sstevel@tonic-gate #if defined(_SYSCALL32_IMPL) 2347c478bd9Sstevel@tonic-gate /* 2357c478bd9Sstevel@tonic-gate * These are now a compatibility artifact; all supported SPARC CPUs 2367c478bd9Sstevel@tonic-gate * are V9-capable (and thus support v8plus) and fully implement 2377c478bd9Sstevel@tonic-gate * {s,u}mul and {s,u}div. 2387c478bd9Sstevel@tonic-gate */ 2397c478bd9Sstevel@tonic-gate cpu_hwcap_flags |= AV_SPARC_MUL32 | AV_SPARC_DIV32 | AV_SPARC_V8PLUS; 2407c478bd9Sstevel@tonic-gate 2417c478bd9Sstevel@tonic-gate auxv_hwcap32 = (auxv_hwcap32_include | cpu_hwcap_flags) & 2427c478bd9Sstevel@tonic-gate ~auxv_hwcap32_exclude; 2437c478bd9Sstevel@tonic-gate 2447c478bd9Sstevel@tonic-gate if (auxv_hwcap32_include || auxv_hwcap32_exclude) 2457c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "?32-bit user ABI extensions: %b\n", 2467c478bd9Sstevel@tonic-gate auxv_hwcap32, FMT_AV_SPARC); 2477c478bd9Sstevel@tonic-gate #endif 2487c478bd9Sstevel@tonic-gate } 2497c478bd9Sstevel@tonic-gate 2507c478bd9Sstevel@tonic-gate int 2517c478bd9Sstevel@tonic-gate __ipltospl(int ipl) 2527c478bd9Sstevel@tonic-gate { 2537c478bd9Sstevel@tonic-gate return (ipltospl(ipl)); 2547c478bd9Sstevel@tonic-gate } 2557c478bd9Sstevel@tonic-gate 2567c478bd9Sstevel@tonic-gate /* 2577c478bd9Sstevel@tonic-gate * Print a stack backtrace using the specified stack pointer. We delay two 2587c478bd9Sstevel@tonic-gate * seconds before continuing, unless this is the panic traceback. Note 2597c478bd9Sstevel@tonic-gate * that the frame for the starting stack pointer value is omitted because 2607c478bd9Sstevel@tonic-gate * the corresponding %pc is not known. 2617c478bd9Sstevel@tonic-gate */ 2627c478bd9Sstevel@tonic-gate void 2637c478bd9Sstevel@tonic-gate traceback(caddr_t sp) 2647c478bd9Sstevel@tonic-gate { 2657c478bd9Sstevel@tonic-gate struct frame *fp = (struct frame *)(sp + STACK_BIAS); 2667c478bd9Sstevel@tonic-gate struct frame *nextfp, *minfp, *stacktop; 2677c478bd9Sstevel@tonic-gate int on_intr; 2687c478bd9Sstevel@tonic-gate 2697c478bd9Sstevel@tonic-gate cpu_t *cpu; 2707c478bd9Sstevel@tonic-gate 2717c478bd9Sstevel@tonic-gate flush_windows(); 2727c478bd9Sstevel@tonic-gate 2737c478bd9Sstevel@tonic-gate if (!panicstr) 2747c478bd9Sstevel@tonic-gate printf("traceback: %%sp = %p\n", (void *)sp); 2757c478bd9Sstevel@tonic-gate 2767c478bd9Sstevel@tonic-gate /* 2777c478bd9Sstevel@tonic-gate * If we are panicking, the high-level interrupt information in 2787c478bd9Sstevel@tonic-gate * CPU was overwritten. panic_cpu has the correct values. 2797c478bd9Sstevel@tonic-gate */ 2807c478bd9Sstevel@tonic-gate kpreempt_disable(); /* prevent migration */ 2817c478bd9Sstevel@tonic-gate 2827c478bd9Sstevel@tonic-gate cpu = (panicstr && CPU->cpu_id == panic_cpu.cpu_id)? &panic_cpu : CPU; 2837c478bd9Sstevel@tonic-gate 2847c478bd9Sstevel@tonic-gate if ((on_intr = CPU_ON_INTR(cpu)) != 0) 2857c478bd9Sstevel@tonic-gate stacktop = (struct frame *)(cpu->cpu_intr_stack + SA(MINFRAME)); 2867c478bd9Sstevel@tonic-gate else 2877c478bd9Sstevel@tonic-gate stacktop = (struct frame *)curthread->t_stk; 2887c478bd9Sstevel@tonic-gate 2897c478bd9Sstevel@tonic-gate kpreempt_enable(); 2907c478bd9Sstevel@tonic-gate 2917c478bd9Sstevel@tonic-gate minfp = fp; 2927c478bd9Sstevel@tonic-gate 2937c478bd9Sstevel@tonic-gate while ((uintptr_t)fp >= KERNELBASE) { 2947c478bd9Sstevel@tonic-gate uintptr_t pc = (uintptr_t)fp->fr_savpc; 2957c478bd9Sstevel@tonic-gate ulong_t off; 2967c478bd9Sstevel@tonic-gate char *sym; 2977c478bd9Sstevel@tonic-gate 2987c478bd9Sstevel@tonic-gate nextfp = (struct frame *)((uintptr_t)fp->fr_savfp + STACK_BIAS); 2997c478bd9Sstevel@tonic-gate if (nextfp <= minfp || nextfp >= stacktop) { 3007c478bd9Sstevel@tonic-gate if (on_intr) { 3017c478bd9Sstevel@tonic-gate /* 3027c478bd9Sstevel@tonic-gate * Hop from interrupt stack to thread stack. 3037c478bd9Sstevel@tonic-gate */ 3047c478bd9Sstevel@tonic-gate stacktop = (struct frame *)curthread->t_stk; 3057c478bd9Sstevel@tonic-gate minfp = (struct frame *)curthread->t_stkbase; 3067c478bd9Sstevel@tonic-gate on_intr = 0; 3077c478bd9Sstevel@tonic-gate continue; 3087c478bd9Sstevel@tonic-gate } 3097c478bd9Sstevel@tonic-gate break; /* we're outside of the expected range */ 3107c478bd9Sstevel@tonic-gate } 3117c478bd9Sstevel@tonic-gate 3127c478bd9Sstevel@tonic-gate if ((uintptr_t)nextfp & (STACK_ALIGN - 1)) { 3137c478bd9Sstevel@tonic-gate printf(" >> mis-aligned %%fp = %p\n", (void *)nextfp); 3147c478bd9Sstevel@tonic-gate break; 3157c478bd9Sstevel@tonic-gate } 3167c478bd9Sstevel@tonic-gate 3177c478bd9Sstevel@tonic-gate if ((sym = kobj_getsymname(pc, &off)) != NULL) { 3187c478bd9Sstevel@tonic-gate printf("%016lx %s:%s+%lx " 3197c478bd9Sstevel@tonic-gate "(%lx, %lx, %lx, %lx, %lx, %lx)\n", (ulong_t)nextfp, 3207c478bd9Sstevel@tonic-gate mod_containing_pc((caddr_t)pc), sym, off, 3217c478bd9Sstevel@tonic-gate nextfp->fr_arg[0], nextfp->fr_arg[1], 3227c478bd9Sstevel@tonic-gate nextfp->fr_arg[2], nextfp->fr_arg[3], 3237c478bd9Sstevel@tonic-gate nextfp->fr_arg[4], nextfp->fr_arg[5]); 3247c478bd9Sstevel@tonic-gate } else { 3257c478bd9Sstevel@tonic-gate printf("%016lx %p (%lx, %lx, %lx, %lx, %lx, %lx)\n", 3267c478bd9Sstevel@tonic-gate (ulong_t)nextfp, (void *)pc, 3277c478bd9Sstevel@tonic-gate nextfp->fr_arg[0], nextfp->fr_arg[1], 3287c478bd9Sstevel@tonic-gate nextfp->fr_arg[2], nextfp->fr_arg[3], 3297c478bd9Sstevel@tonic-gate nextfp->fr_arg[4], nextfp->fr_arg[5]); 3307c478bd9Sstevel@tonic-gate } 3317c478bd9Sstevel@tonic-gate 3327c478bd9Sstevel@tonic-gate printf(" %%l0-3: %016lx %016lx %016lx %016lx\n" 3337c478bd9Sstevel@tonic-gate " %%l4-7: %016lx %016lx %016lx %016lx\n", 3347c478bd9Sstevel@tonic-gate nextfp->fr_local[0], nextfp->fr_local[1], 3357c478bd9Sstevel@tonic-gate nextfp->fr_local[2], nextfp->fr_local[3], 3367c478bd9Sstevel@tonic-gate nextfp->fr_local[4], nextfp->fr_local[5], 3377c478bd9Sstevel@tonic-gate nextfp->fr_local[6], nextfp->fr_local[7]); 3387c478bd9Sstevel@tonic-gate 3397c478bd9Sstevel@tonic-gate fp = nextfp; 3407c478bd9Sstevel@tonic-gate minfp = fp; 3417c478bd9Sstevel@tonic-gate } 3427c478bd9Sstevel@tonic-gate 3437c478bd9Sstevel@tonic-gate if (!panicstr) { 3447c478bd9Sstevel@tonic-gate printf("end of traceback\n"); 3457c478bd9Sstevel@tonic-gate DELAY(2 * MICROSEC); 3467c478bd9Sstevel@tonic-gate } 3477c478bd9Sstevel@tonic-gate } 3487c478bd9Sstevel@tonic-gate 3497c478bd9Sstevel@tonic-gate /* 3507c478bd9Sstevel@tonic-gate * Generate a stack backtrace from a saved register set. 3517c478bd9Sstevel@tonic-gate */ 3527c478bd9Sstevel@tonic-gate void 3537c478bd9Sstevel@tonic-gate traceregs(struct regs *rp) 3547c478bd9Sstevel@tonic-gate { 3557c478bd9Sstevel@tonic-gate traceback((caddr_t)rp->r_sp); 3567c478bd9Sstevel@tonic-gate } 3577c478bd9Sstevel@tonic-gate 3587c478bd9Sstevel@tonic-gate void 3597c478bd9Sstevel@tonic-gate exec_set_sp(size_t stksize) 3607c478bd9Sstevel@tonic-gate { 3617c478bd9Sstevel@tonic-gate klwp_t *lwp = ttolwp(curthread); 3627c478bd9Sstevel@tonic-gate 3637c478bd9Sstevel@tonic-gate lwp->lwp_pcb.pcb_xregstat = XREGNONE; 3647c478bd9Sstevel@tonic-gate if (curproc->p_model == DATAMODEL_NATIVE) 3657c478bd9Sstevel@tonic-gate stksize += sizeof (struct rwindow) + STACK_BIAS; 3667c478bd9Sstevel@tonic-gate else 3677c478bd9Sstevel@tonic-gate stksize += sizeof (struct rwindow32); 3687c478bd9Sstevel@tonic-gate lwptoregs(lwp)->r_sp = (uintptr_t)curproc->p_usrstack - stksize; 3697c478bd9Sstevel@tonic-gate } 3707c478bd9Sstevel@tonic-gate 3717c478bd9Sstevel@tonic-gate /* 3727c478bd9Sstevel@tonic-gate * Allocate a region of virtual address space, unmapped. 3737c478bd9Sstevel@tonic-gate * 3747c478bd9Sstevel@tonic-gate * When a hard-redzone (firewall) is in effect, redzone violations are 3757c478bd9Sstevel@tonic-gate * caught by the hardware the instant they happen because the first byte 3767c478bd9Sstevel@tonic-gate * past the logical end of a firewalled buffer lies at the start of an 3777c478bd9Sstevel@tonic-gate * unmapped page. This firewalling is accomplished by bumping up the 3787c478bd9Sstevel@tonic-gate * requested address allocation, effectively removing an additional page 3797c478bd9Sstevel@tonic-gate * beyond the original request from the available virtual memory arena. 3807c478bd9Sstevel@tonic-gate * However, the size of the allocation passed to boot, in boot_alloc(), 3817c478bd9Sstevel@tonic-gate * doesn't reflect this additional page and fragmentation of the OBP 3827c478bd9Sstevel@tonic-gate * "virtual-memory" "available" lists property occurs. Calling 3837c478bd9Sstevel@tonic-gate * prom_claim_virt() for the firewall page avoids this fragmentation. 3847c478bd9Sstevel@tonic-gate */ 3857c478bd9Sstevel@tonic-gate void * 3867c478bd9Sstevel@tonic-gate boot_virt_alloc(void *addr, size_t size) 3877c478bd9Sstevel@tonic-gate { 388*986fd29aSsetje return (BOP_ALLOC_VIRT((caddr_t)addr, size)); 3897c478bd9Sstevel@tonic-gate } 3907c478bd9Sstevel@tonic-gate 3917c478bd9Sstevel@tonic-gate 3927c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 3937c478bd9Sstevel@tonic-gate int 3947c478bd9Sstevel@tonic-gate xcopyin_nta(const void *uaddr, void *kaddr, size_t count, int dummy) 3957c478bd9Sstevel@tonic-gate { 3967c478bd9Sstevel@tonic-gate return (xcopyin(uaddr, kaddr, count)); 3977c478bd9Sstevel@tonic-gate } 3987c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 3997c478bd9Sstevel@tonic-gate int 4007c478bd9Sstevel@tonic-gate xcopyout_nta(const void *kaddr, void *uaddr, size_t count, int dummy) 4017c478bd9Sstevel@tonic-gate { 4027c478bd9Sstevel@tonic-gate return (xcopyout(kaddr, uaddr, count)); 4037c478bd9Sstevel@tonic-gate } 4047c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 4057c478bd9Sstevel@tonic-gate int 4067c478bd9Sstevel@tonic-gate kcopy_nta(const void *from, void *to, size_t count, int dummy) 4077c478bd9Sstevel@tonic-gate { 4087c478bd9Sstevel@tonic-gate return (kcopy(from, to, count)); 4097c478bd9Sstevel@tonic-gate } 410