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