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