Fri, 30 Nov 2012 15:23:16 -0800
8003240: x86: move MacroAssembler into separate file
Reviewed-by: kvn
duke@435 | 1 | /* |
mikael@4153 | 2 | * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. |
duke@435 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
duke@435 | 4 | * |
duke@435 | 5 | * This code is free software; you can redistribute it and/or modify it |
duke@435 | 6 | * under the terms of the GNU General Public License version 2 only, as |
duke@435 | 7 | * published by the Free Software Foundation. |
duke@435 | 8 | * |
duke@435 | 9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
duke@435 | 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
duke@435 | 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
duke@435 | 12 | * version 2 for more details (a copy is included in the LICENSE file that |
duke@435 | 13 | * accompanied this code). |
duke@435 | 14 | * |
duke@435 | 15 | * You should have received a copy of the GNU General Public License version |
duke@435 | 16 | * 2 along with this work; if not, write to the Free Software Foundation, |
duke@435 | 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
duke@435 | 18 | * |
trims@1907 | 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
trims@1907 | 20 | * or visit www.oracle.com if you need additional information or have any |
trims@1907 | 21 | * questions. |
duke@435 | 22 | * |
duke@435 | 23 | */ |
duke@435 | 24 | |
stefank@2314 | 25 | // no precompiled headers |
twisti@4318 | 26 | #include "asm/macroAssembler.hpp" |
stefank@2314 | 27 | #include "classfile/classLoader.hpp" |
stefank@2314 | 28 | #include "classfile/systemDictionary.hpp" |
stefank@2314 | 29 | #include "classfile/vmSymbols.hpp" |
stefank@2314 | 30 | #include "code/icBuffer.hpp" |
stefank@2314 | 31 | #include "code/vtableStubs.hpp" |
stefank@2314 | 32 | #include "interpreter/interpreter.hpp" |
stefank@2314 | 33 | #include "jvm_solaris.h" |
stefank@2314 | 34 | #include "memory/allocation.inline.hpp" |
stefank@2314 | 35 | #include "mutex_solaris.inline.hpp" |
stefank@2314 | 36 | #include "os_share_solaris.hpp" |
stefank@2314 | 37 | #include "prims/jniFastGetField.hpp" |
stefank@2314 | 38 | #include "prims/jvm.h" |
stefank@2314 | 39 | #include "prims/jvm_misc.hpp" |
stefank@2314 | 40 | #include "runtime/arguments.hpp" |
stefank@2314 | 41 | #include "runtime/extendedPC.hpp" |
stefank@2314 | 42 | #include "runtime/frame.inline.hpp" |
stefank@2314 | 43 | #include "runtime/interfaceSupport.hpp" |
stefank@2314 | 44 | #include "runtime/java.hpp" |
stefank@2314 | 45 | #include "runtime/javaCalls.hpp" |
stefank@2314 | 46 | #include "runtime/mutexLocker.hpp" |
stefank@2314 | 47 | #include "runtime/osThread.hpp" |
stefank@2314 | 48 | #include "runtime/sharedRuntime.hpp" |
stefank@2314 | 49 | #include "runtime/stubRoutines.hpp" |
stefank@2314 | 50 | #include "runtime/timer.hpp" |
stefank@2314 | 51 | #include "thread_solaris.inline.hpp" |
stefank@2314 | 52 | #include "utilities/events.hpp" |
stefank@2314 | 53 | #include "utilities/vmError.hpp" |
duke@435 | 54 | |
duke@435 | 55 | // put OS-includes here |
duke@435 | 56 | # include <sys/types.h> |
duke@435 | 57 | # include <sys/mman.h> |
duke@435 | 58 | # include <pthread.h> |
duke@435 | 59 | # include <signal.h> |
duke@435 | 60 | # include <setjmp.h> |
duke@435 | 61 | # include <errno.h> |
duke@435 | 62 | # include <dlfcn.h> |
duke@435 | 63 | # include <stdio.h> |
duke@435 | 64 | # include <unistd.h> |
duke@435 | 65 | # include <sys/resource.h> |
duke@435 | 66 | # include <thread.h> |
duke@435 | 67 | # include <sys/stat.h> |
duke@435 | 68 | # include <sys/time.h> |
duke@435 | 69 | # include <sys/filio.h> |
duke@435 | 70 | # include <sys/utsname.h> |
duke@435 | 71 | # include <sys/systeminfo.h> |
duke@435 | 72 | # include <sys/socket.h> |
duke@435 | 73 | # include <sys/trap.h> |
duke@435 | 74 | # include <sys/lwp.h> |
duke@435 | 75 | # include <pwd.h> |
duke@435 | 76 | # include <poll.h> |
duke@435 | 77 | # include <sys/lwp.h> |
duke@435 | 78 | # include <procfs.h> // see comment in <sys/procfs.h> |
duke@435 | 79 | |
duke@435 | 80 | #ifndef AMD64 |
duke@435 | 81 | // QQQ seems useless at this point |
duke@435 | 82 | # define _STRUCTURED_PROC 1 // this gets us the new structured proc interfaces of 5.6 & later |
duke@435 | 83 | #endif // AMD64 |
duke@435 | 84 | # include <sys/procfs.h> // see comment in <sys/procfs.h> |
duke@435 | 85 | |
duke@435 | 86 | |
duke@435 | 87 | #define MAX_PATH (2 * K) |
duke@435 | 88 | |
duke@435 | 89 | // Minimum stack size for the VM. It's easier to document a constant value |
duke@435 | 90 | // but it's different for x86 and sparc because the page sizes are different. |
duke@435 | 91 | #ifdef AMD64 |
duke@435 | 92 | size_t os::Solaris::min_stack_allowed = 224*K; |
duke@435 | 93 | #define REG_SP REG_RSP |
duke@435 | 94 | #define REG_PC REG_RIP |
duke@435 | 95 | #define REG_FP REG_RBP |
duke@435 | 96 | #else |
duke@435 | 97 | size_t os::Solaris::min_stack_allowed = 64*K; |
duke@435 | 98 | #define REG_SP UESP |
duke@435 | 99 | #define REG_PC EIP |
duke@435 | 100 | #define REG_FP EBP |
duke@435 | 101 | // 4900493 counter to prevent runaway LDTR refresh attempt |
duke@435 | 102 | |
duke@435 | 103 | static volatile int ldtr_refresh = 0; |
duke@435 | 104 | // the libthread instruction that faults because of the stale LDTR |
duke@435 | 105 | |
duke@435 | 106 | static const unsigned char movlfs[] = { 0x8e, 0xe0 // movl %eax,%fs |
duke@435 | 107 | }; |
duke@435 | 108 | #endif // AMD64 |
duke@435 | 109 | |
duke@435 | 110 | char* os::non_memory_address_word() { |
duke@435 | 111 | // Must never look like an address returned by reserve_memory, |
duke@435 | 112 | // even in its subfields (as defined by the CPU immediate fields, |
duke@435 | 113 | // if the CPU splits constants across multiple instructions). |
duke@435 | 114 | return (char*) -1; |
duke@435 | 115 | } |
duke@435 | 116 | |
duke@435 | 117 | // |
duke@435 | 118 | // Validate a ucontext retrieved from walking a uc_link of a ucontext. |
duke@435 | 119 | // There are issues with libthread giving out uc_links for different threads |
duke@435 | 120 | // on the same uc_link chain and bad or circular links. |
duke@435 | 121 | // |
duke@435 | 122 | bool os::Solaris::valid_ucontext(Thread* thread, ucontext_t* valid, ucontext_t* suspect) { |
duke@435 | 123 | if (valid >= suspect || |
duke@435 | 124 | valid->uc_stack.ss_flags != suspect->uc_stack.ss_flags || |
duke@435 | 125 | valid->uc_stack.ss_sp != suspect->uc_stack.ss_sp || |
duke@435 | 126 | valid->uc_stack.ss_size != suspect->uc_stack.ss_size) { |
duke@435 | 127 | DEBUG_ONLY(tty->print_cr("valid_ucontext: failed test 1");) |
duke@435 | 128 | return false; |
duke@435 | 129 | } |
duke@435 | 130 | |
duke@435 | 131 | if (thread->is_Java_thread()) { |
duke@435 | 132 | if (!valid_stack_address(thread, (address)suspect)) { |
duke@435 | 133 | DEBUG_ONLY(tty->print_cr("valid_ucontext: uc_link not in thread stack");) |
duke@435 | 134 | return false; |
duke@435 | 135 | } |
duke@435 | 136 | if (!valid_stack_address(thread, (address) suspect->uc_mcontext.gregs[REG_SP])) { |
duke@435 | 137 | DEBUG_ONLY(tty->print_cr("valid_ucontext: stackpointer not in thread stack");) |
duke@435 | 138 | return false; |
duke@435 | 139 | } |
duke@435 | 140 | } |
duke@435 | 141 | return true; |
duke@435 | 142 | } |
duke@435 | 143 | |
duke@435 | 144 | // We will only follow one level of uc_link since there are libthread |
duke@435 | 145 | // issues with ucontext linking and it is better to be safe and just |
duke@435 | 146 | // let caller retry later. |
duke@435 | 147 | ucontext_t* os::Solaris::get_valid_uc_in_signal_handler(Thread *thread, |
duke@435 | 148 | ucontext_t *uc) { |
duke@435 | 149 | |
duke@435 | 150 | ucontext_t *retuc = NULL; |
duke@435 | 151 | |
duke@435 | 152 | if (uc != NULL) { |
duke@435 | 153 | if (uc->uc_link == NULL) { |
duke@435 | 154 | // cannot validate without uc_link so accept current ucontext |
duke@435 | 155 | retuc = uc; |
duke@435 | 156 | } else if (os::Solaris::valid_ucontext(thread, uc, uc->uc_link)) { |
duke@435 | 157 | // first ucontext is valid so try the next one |
duke@435 | 158 | uc = uc->uc_link; |
duke@435 | 159 | if (uc->uc_link == NULL) { |
duke@435 | 160 | // cannot validate without uc_link so accept current ucontext |
duke@435 | 161 | retuc = uc; |
duke@435 | 162 | } else if (os::Solaris::valid_ucontext(thread, uc, uc->uc_link)) { |
duke@435 | 163 | // the ucontext one level down is also valid so return it |
duke@435 | 164 | retuc = uc; |
duke@435 | 165 | } |
duke@435 | 166 | } |
duke@435 | 167 | } |
duke@435 | 168 | return retuc; |
duke@435 | 169 | } |
duke@435 | 170 | |
duke@435 | 171 | // Assumes ucontext is valid |
duke@435 | 172 | ExtendedPC os::Solaris::ucontext_get_ExtendedPC(ucontext_t *uc) { |
duke@435 | 173 | return ExtendedPC((address)uc->uc_mcontext.gregs[REG_PC]); |
duke@435 | 174 | } |
duke@435 | 175 | |
duke@435 | 176 | // Assumes ucontext is valid |
duke@435 | 177 | intptr_t* os::Solaris::ucontext_get_sp(ucontext_t *uc) { |
duke@435 | 178 | return (intptr_t*)uc->uc_mcontext.gregs[REG_SP]; |
duke@435 | 179 | } |
duke@435 | 180 | |
duke@435 | 181 | // Assumes ucontext is valid |
duke@435 | 182 | intptr_t* os::Solaris::ucontext_get_fp(ucontext_t *uc) { |
duke@435 | 183 | return (intptr_t*)uc->uc_mcontext.gregs[REG_FP]; |
duke@435 | 184 | } |
duke@435 | 185 | |
duke@435 | 186 | // For Forte Analyzer AsyncGetCallTrace profiling support - thread |
duke@435 | 187 | // is currently interrupted by SIGPROF. |
duke@435 | 188 | // |
duke@435 | 189 | // The difference between this and os::fetch_frame_from_context() is that |
duke@435 | 190 | // here we try to skip nested signal frames. |
duke@435 | 191 | ExtendedPC os::Solaris::fetch_frame_from_ucontext(Thread* thread, |
duke@435 | 192 | ucontext_t* uc, intptr_t** ret_sp, intptr_t** ret_fp) { |
duke@435 | 193 | |
duke@435 | 194 | assert(thread != NULL, "just checking"); |
duke@435 | 195 | assert(ret_sp != NULL, "just checking"); |
duke@435 | 196 | assert(ret_fp != NULL, "just checking"); |
duke@435 | 197 | |
duke@435 | 198 | ucontext_t *luc = os::Solaris::get_valid_uc_in_signal_handler(thread, uc); |
duke@435 | 199 | return os::fetch_frame_from_context(luc, ret_sp, ret_fp); |
duke@435 | 200 | } |
duke@435 | 201 | |
duke@435 | 202 | ExtendedPC os::fetch_frame_from_context(void* ucVoid, |
duke@435 | 203 | intptr_t** ret_sp, intptr_t** ret_fp) { |
duke@435 | 204 | |
duke@435 | 205 | ExtendedPC epc; |
duke@435 | 206 | ucontext_t *uc = (ucontext_t*)ucVoid; |
duke@435 | 207 | |
duke@435 | 208 | if (uc != NULL) { |
duke@435 | 209 | epc = os::Solaris::ucontext_get_ExtendedPC(uc); |
duke@435 | 210 | if (ret_sp) *ret_sp = os::Solaris::ucontext_get_sp(uc); |
duke@435 | 211 | if (ret_fp) *ret_fp = os::Solaris::ucontext_get_fp(uc); |
duke@435 | 212 | } else { |
duke@435 | 213 | // construct empty ExtendedPC for return value checking |
duke@435 | 214 | epc = ExtendedPC(NULL); |
duke@435 | 215 | if (ret_sp) *ret_sp = (intptr_t *)NULL; |
duke@435 | 216 | if (ret_fp) *ret_fp = (intptr_t *)NULL; |
duke@435 | 217 | } |
duke@435 | 218 | |
duke@435 | 219 | return epc; |
duke@435 | 220 | } |
duke@435 | 221 | |
duke@435 | 222 | frame os::fetch_frame_from_context(void* ucVoid) { |
duke@435 | 223 | intptr_t* sp; |
duke@435 | 224 | intptr_t* fp; |
duke@435 | 225 | ExtendedPC epc = fetch_frame_from_context(ucVoid, &sp, &fp); |
duke@435 | 226 | return frame(sp, fp, epc.pc()); |
duke@435 | 227 | } |
duke@435 | 228 | |
duke@435 | 229 | frame os::get_sender_for_C_frame(frame* fr) { |
duke@435 | 230 | return frame(fr->sender_sp(), fr->link(), fr->sender_pc()); |
duke@435 | 231 | } |
duke@435 | 232 | |
roland@3606 | 233 | extern "C" intptr_t *_get_current_sp(); // in .il file |
roland@3606 | 234 | |
roland@3606 | 235 | address os::current_stack_pointer() { |
roland@3606 | 236 | return (address)_get_current_sp(); |
roland@3606 | 237 | } |
roland@3606 | 238 | |
coleenp@907 | 239 | extern "C" intptr_t *_get_current_fp(); // in .il file |
duke@435 | 240 | |
duke@435 | 241 | frame os::current_frame() { |
coleenp@907 | 242 | intptr_t* fp = _get_current_fp(); // it's inlined so want current fp |
duke@435 | 243 | frame myframe((intptr_t*)os::current_stack_pointer(), |
duke@435 | 244 | (intptr_t*)fp, |
duke@435 | 245 | CAST_FROM_FN_PTR(address, os::current_frame)); |
duke@435 | 246 | if (os::is_first_C_frame(&myframe)) { |
duke@435 | 247 | // stack is not walkable |
sgoldman@542 | 248 | frame ret; // This will be a null useless frame |
sgoldman@542 | 249 | return ret; |
duke@435 | 250 | } else { |
duke@435 | 251 | return os::get_sender_for_C_frame(&myframe); |
duke@435 | 252 | } |
duke@435 | 253 | } |
duke@435 | 254 | |
duke@435 | 255 | // This is a simple callback that just fetches a PC for an interrupted thread. |
duke@435 | 256 | // The thread need not be suspended and the fetched PC is just a hint. |
duke@435 | 257 | // This one is currently used for profiling the VMThread ONLY! |
duke@435 | 258 | |
duke@435 | 259 | // Must be synchronous |
duke@435 | 260 | void GetThreadPC_Callback::execute(OSThread::InterruptArguments *args) { |
duke@435 | 261 | Thread* thread = args->thread(); |
duke@435 | 262 | ucontext_t* uc = args->ucontext(); |
duke@435 | 263 | intptr_t* sp; |
duke@435 | 264 | |
duke@435 | 265 | assert(ProfileVM && thread->is_VM_thread(), "just checking"); |
duke@435 | 266 | |
duke@435 | 267 | ExtendedPC new_addr((address)uc->uc_mcontext.gregs[REG_PC]); |
duke@435 | 268 | _addr = new_addr; |
duke@435 | 269 | } |
duke@435 | 270 | |
duke@435 | 271 | static int threadgetstate(thread_t tid, int *flags, lwpid_t *lwp, stack_t *ss, gregset_t rs, lwpstatus_t *lwpstatus) { |
duke@435 | 272 | char lwpstatusfile[PROCFILE_LENGTH]; |
duke@435 | 273 | int lwpfd, err; |
duke@435 | 274 | |
duke@435 | 275 | if (err = os::Solaris::thr_getstate(tid, flags, lwp, ss, rs)) |
duke@435 | 276 | return (err); |
duke@435 | 277 | if (*flags == TRS_LWPID) { |
duke@435 | 278 | sprintf(lwpstatusfile, "/proc/%d/lwp/%d/lwpstatus", getpid(), |
duke@435 | 279 | *lwp); |
duke@435 | 280 | if ((lwpfd = open(lwpstatusfile, O_RDONLY)) < 0) { |
duke@435 | 281 | perror("thr_mutator_status: open lwpstatus"); |
duke@435 | 282 | return (EINVAL); |
duke@435 | 283 | } |
duke@435 | 284 | if (pread(lwpfd, lwpstatus, sizeof (lwpstatus_t), (off_t)0) != |
duke@435 | 285 | sizeof (lwpstatus_t)) { |
duke@435 | 286 | perror("thr_mutator_status: read lwpstatus"); |
duke@435 | 287 | (void) close(lwpfd); |
duke@435 | 288 | return (EINVAL); |
duke@435 | 289 | } |
duke@435 | 290 | (void) close(lwpfd); |
duke@435 | 291 | } |
duke@435 | 292 | return (0); |
duke@435 | 293 | } |
duke@435 | 294 | |
duke@435 | 295 | #ifndef AMD64 |
duke@435 | 296 | |
duke@435 | 297 | // Detecting SSE support by OS |
duke@435 | 298 | // From solaris_i486.s |
duke@435 | 299 | extern "C" bool sse_check(); |
duke@435 | 300 | extern "C" bool sse_unavailable(); |
duke@435 | 301 | |
duke@435 | 302 | enum { SSE_UNKNOWN, SSE_NOT_SUPPORTED, SSE_SUPPORTED}; |
duke@435 | 303 | static int sse_status = SSE_UNKNOWN; |
duke@435 | 304 | |
duke@435 | 305 | |
duke@435 | 306 | static void check_for_sse_support() { |
duke@435 | 307 | if (!VM_Version::supports_sse()) { |
duke@435 | 308 | sse_status = SSE_NOT_SUPPORTED; |
duke@435 | 309 | return; |
duke@435 | 310 | } |
duke@435 | 311 | // looking for _sse_hw in libc.so, if it does not exist or |
duke@435 | 312 | // the value (int) is 0, OS has no support for SSE |
duke@435 | 313 | int *sse_hwp; |
duke@435 | 314 | void *h; |
duke@435 | 315 | |
duke@435 | 316 | if ((h=dlopen("/usr/lib/libc.so", RTLD_LAZY)) == NULL) { |
duke@435 | 317 | //open failed, presume no support for SSE |
duke@435 | 318 | sse_status = SSE_NOT_SUPPORTED; |
duke@435 | 319 | return; |
duke@435 | 320 | } |
duke@435 | 321 | if ((sse_hwp = (int *)dlsym(h, "_sse_hw")) == NULL) { |
duke@435 | 322 | sse_status = SSE_NOT_SUPPORTED; |
duke@435 | 323 | } else if (*sse_hwp == 0) { |
duke@435 | 324 | sse_status = SSE_NOT_SUPPORTED; |
duke@435 | 325 | } |
duke@435 | 326 | dlclose(h); |
duke@435 | 327 | |
duke@435 | 328 | if (sse_status == SSE_UNKNOWN) { |
duke@435 | 329 | bool (*try_sse)() = (bool (*)())sse_check; |
duke@435 | 330 | sse_status = (*try_sse)() ? SSE_SUPPORTED : SSE_NOT_SUPPORTED; |
duke@435 | 331 | } |
duke@435 | 332 | |
duke@435 | 333 | } |
duke@435 | 334 | |
twisti@1020 | 335 | #endif // AMD64 |
twisti@1020 | 336 | |
duke@435 | 337 | bool os::supports_sse() { |
twisti@1020 | 338 | #ifdef AMD64 |
twisti@1020 | 339 | return true; |
twisti@1020 | 340 | #else |
duke@435 | 341 | if (sse_status == SSE_UNKNOWN) |
duke@435 | 342 | check_for_sse_support(); |
duke@435 | 343 | return sse_status == SSE_SUPPORTED; |
twisti@1020 | 344 | #endif // AMD64 |
duke@435 | 345 | } |
duke@435 | 346 | |
duke@435 | 347 | bool os::is_allocatable(size_t bytes) { |
duke@435 | 348 | #ifdef AMD64 |
duke@435 | 349 | return true; |
duke@435 | 350 | #else |
duke@435 | 351 | |
duke@435 | 352 | if (bytes < 2 * G) { |
duke@435 | 353 | return true; |
duke@435 | 354 | } |
duke@435 | 355 | |
duke@435 | 356 | char* addr = reserve_memory(bytes, NULL); |
duke@435 | 357 | |
duke@435 | 358 | if (addr != NULL) { |
duke@435 | 359 | release_memory(addr, bytes); |
duke@435 | 360 | } |
duke@435 | 361 | |
duke@435 | 362 | return addr != NULL; |
duke@435 | 363 | #endif // AMD64 |
duke@435 | 364 | |
duke@435 | 365 | } |
duke@435 | 366 | |
duke@435 | 367 | extern "C" void Fetch32PFI () ; |
duke@435 | 368 | extern "C" void Fetch32Resume () ; |
duke@435 | 369 | #ifdef AMD64 |
duke@435 | 370 | extern "C" void FetchNPFI () ; |
duke@435 | 371 | extern "C" void FetchNResume () ; |
duke@435 | 372 | #endif // AMD64 |
duke@435 | 373 | |
coleenp@2507 | 374 | extern "C" JNIEXPORT int |
coleenp@2507 | 375 | JVM_handle_solaris_signal(int sig, siginfo_t* info, void* ucVoid, |
coleenp@2507 | 376 | int abort_if_unrecognized) { |
duke@435 | 377 | ucontext_t* uc = (ucontext_t*) ucVoid; |
duke@435 | 378 | |
duke@435 | 379 | #ifndef AMD64 |
duke@435 | 380 | if (sig == SIGILL && info->si_addr == (caddr_t)sse_check) { |
duke@435 | 381 | // the SSE instruction faulted. supports_sse() need return false. |
duke@435 | 382 | uc->uc_mcontext.gregs[EIP] = (greg_t)sse_unavailable; |
duke@435 | 383 | return true; |
duke@435 | 384 | } |
duke@435 | 385 | #endif // !AMD64 |
duke@435 | 386 | |
duke@435 | 387 | Thread* t = ThreadLocalStorage::get_thread_slow(); // slow & steady |
duke@435 | 388 | |
duke@435 | 389 | SignalHandlerMark shm(t); |
duke@435 | 390 | |
duke@435 | 391 | if(sig == SIGPIPE || sig == SIGXFSZ) { |
duke@435 | 392 | if (os::Solaris::chained_handler(sig, info, ucVoid)) { |
duke@435 | 393 | return true; |
duke@435 | 394 | } else { |
duke@435 | 395 | if (PrintMiscellaneous && (WizardMode || Verbose)) { |
duke@435 | 396 | char buf[64]; |
duke@435 | 397 | warning("Ignoring %s - see 4229104 or 6499219", |
duke@435 | 398 | os::exception_name(sig, buf, sizeof(buf))); |
duke@435 | 399 | |
duke@435 | 400 | } |
duke@435 | 401 | return true; |
duke@435 | 402 | } |
duke@435 | 403 | } |
duke@435 | 404 | |
duke@435 | 405 | JavaThread* thread = NULL; |
duke@435 | 406 | VMThread* vmthread = NULL; |
duke@435 | 407 | |
duke@435 | 408 | if (os::Solaris::signal_handlers_are_installed) { |
duke@435 | 409 | if (t != NULL ){ |
duke@435 | 410 | if(t->is_Java_thread()) { |
duke@435 | 411 | thread = (JavaThread*)t; |
duke@435 | 412 | } |
duke@435 | 413 | else if(t->is_VM_thread()){ |
duke@435 | 414 | vmthread = (VMThread *)t; |
duke@435 | 415 | } |
duke@435 | 416 | } |
duke@435 | 417 | } |
duke@435 | 418 | |
duke@435 | 419 | guarantee(sig != os::Solaris::SIGinterrupt(), "Can not chain VM interrupt signal, try -XX:+UseAltSigs"); |
duke@435 | 420 | |
duke@435 | 421 | if (sig == os::Solaris::SIGasync()) { |
duke@435 | 422 | if(thread){ |
duke@435 | 423 | OSThread::InterruptArguments args(thread, uc); |
duke@435 | 424 | thread->osthread()->do_interrupt_callbacks_at_interrupt(&args); |
duke@435 | 425 | return true; |
duke@435 | 426 | } |
duke@435 | 427 | else if(vmthread){ |
duke@435 | 428 | OSThread::InterruptArguments args(vmthread, uc); |
duke@435 | 429 | vmthread->osthread()->do_interrupt_callbacks_at_interrupt(&args); |
duke@435 | 430 | return true; |
duke@435 | 431 | } else if (os::Solaris::chained_handler(sig, info, ucVoid)) { |
duke@435 | 432 | return true; |
duke@435 | 433 | } else { |
duke@435 | 434 | // If os::Solaris::SIGasync not chained, and this is a non-vm and |
duke@435 | 435 | // non-java thread |
duke@435 | 436 | return true; |
duke@435 | 437 | } |
duke@435 | 438 | } |
duke@435 | 439 | |
duke@435 | 440 | if (info == NULL || info->si_code <= 0 || info->si_code == SI_NOINFO) { |
duke@435 | 441 | // can't decode this kind of signal |
duke@435 | 442 | info = NULL; |
duke@435 | 443 | } else { |
duke@435 | 444 | assert(sig == info->si_signo, "bad siginfo"); |
duke@435 | 445 | } |
duke@435 | 446 | |
duke@435 | 447 | // decide if this trap can be handled by a stub |
duke@435 | 448 | address stub = NULL; |
duke@435 | 449 | |
duke@435 | 450 | address pc = NULL; |
duke@435 | 451 | |
duke@435 | 452 | //%note os_trap_1 |
duke@435 | 453 | if (info != NULL && uc != NULL && thread != NULL) { |
duke@435 | 454 | // factor me: getPCfromContext |
duke@435 | 455 | pc = (address) uc->uc_mcontext.gregs[REG_PC]; |
duke@435 | 456 | |
duke@435 | 457 | // SafeFetch32() support |
duke@435 | 458 | if (pc == (address) Fetch32PFI) { |
duke@435 | 459 | uc->uc_mcontext.gregs[REG_PC] = intptr_t(Fetch32Resume) ; |
duke@435 | 460 | return true ; |
duke@435 | 461 | } |
duke@435 | 462 | #ifdef AMD64 |
duke@435 | 463 | if (pc == (address) FetchNPFI) { |
duke@435 | 464 | uc->uc_mcontext.gregs [REG_PC] = intptr_t(FetchNResume) ; |
duke@435 | 465 | return true ; |
duke@435 | 466 | } |
duke@435 | 467 | #endif // AMD64 |
duke@435 | 468 | |
duke@435 | 469 | // Handle ALL stack overflow variations here |
duke@435 | 470 | if (sig == SIGSEGV && info->si_code == SEGV_ACCERR) { |
duke@435 | 471 | address addr = (address) info->si_addr; |
duke@435 | 472 | if (thread->in_stack_yellow_zone(addr)) { |
duke@435 | 473 | thread->disable_stack_yellow_zone(); |
duke@435 | 474 | if (thread->thread_state() == _thread_in_Java) { |
duke@435 | 475 | // Throw a stack overflow exception. Guard pages will be reenabled |
duke@435 | 476 | // while unwinding the stack. |
duke@435 | 477 | stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW); |
duke@435 | 478 | } else { |
duke@435 | 479 | // Thread was in the vm or native code. Return and try to finish. |
duke@435 | 480 | return true; |
duke@435 | 481 | } |
duke@435 | 482 | } else if (thread->in_stack_red_zone(addr)) { |
duke@435 | 483 | // Fatal red zone violation. Disable the guard pages and fall through |
duke@435 | 484 | // to handle_unexpected_exception way down below. |
duke@435 | 485 | thread->disable_stack_red_zone(); |
duke@435 | 486 | tty->print_raw_cr("An irrecoverable stack overflow has occurred."); |
duke@435 | 487 | } |
duke@435 | 488 | } |
duke@435 | 489 | |
duke@435 | 490 | if (thread->thread_state() == _thread_in_vm) { |
duke@435 | 491 | if (sig == SIGBUS && info->si_code == BUS_OBJERR && thread->doing_unsafe_access()) { |
duke@435 | 492 | stub = StubRoutines::handler_for_unsafe_access(); |
duke@435 | 493 | } |
duke@435 | 494 | } |
duke@435 | 495 | |
duke@435 | 496 | if (thread->thread_state() == _thread_in_Java) { |
duke@435 | 497 | // Support Safepoint Polling |
duke@435 | 498 | if ( sig == SIGSEGV && os::is_poll_address((address)info->si_addr)) { |
duke@435 | 499 | stub = SharedRuntime::get_poll_stub(pc); |
duke@435 | 500 | } |
duke@435 | 501 | else if (sig == SIGBUS && info->si_code == BUS_OBJERR) { |
duke@435 | 502 | // BugId 4454115: A read from a MappedByteBuffer can fault |
duke@435 | 503 | // here if the underlying file has been truncated. |
duke@435 | 504 | // Do not crash the VM in such a case. |
duke@435 | 505 | CodeBlob* cb = CodeCache::find_blob_unsafe(pc); |
duke@435 | 506 | nmethod* nm = cb->is_nmethod() ? (nmethod*)cb : NULL; |
duke@435 | 507 | if (nm != NULL && nm->has_unsafe_access()) { |
duke@435 | 508 | stub = StubRoutines::handler_for_unsafe_access(); |
duke@435 | 509 | } |
duke@435 | 510 | } |
duke@435 | 511 | else |
duke@435 | 512 | if (sig == SIGFPE && info->si_code == FPE_INTDIV) { |
duke@435 | 513 | // integer divide by zero |
duke@435 | 514 | stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_DIVIDE_BY_ZERO); |
duke@435 | 515 | } |
duke@435 | 516 | #ifndef AMD64 |
duke@435 | 517 | else if (sig == SIGFPE && info->si_code == FPE_FLTDIV) { |
duke@435 | 518 | // floating-point divide by zero |
duke@435 | 519 | stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_DIVIDE_BY_ZERO); |
duke@435 | 520 | } |
duke@435 | 521 | else if (sig == SIGFPE && info->si_code == FPE_FLTINV) { |
duke@435 | 522 | // The encoding of D2I in i486.ad can cause an exception prior |
duke@435 | 523 | // to the fist instruction if there was an invalid operation |
duke@435 | 524 | // pending. We want to dismiss that exception. From the win_32 |
duke@435 | 525 | // side it also seems that if it really was the fist causing |
duke@435 | 526 | // the exception that we do the d2i by hand with different |
duke@435 | 527 | // rounding. Seems kind of weird. QQQ TODO |
duke@435 | 528 | // Note that we take the exception at the NEXT floating point instruction. |
duke@435 | 529 | if (pc[0] == 0xDB) { |
duke@435 | 530 | assert(pc[0] == 0xDB, "not a FIST opcode"); |
duke@435 | 531 | assert(pc[1] == 0x14, "not a FIST opcode"); |
duke@435 | 532 | assert(pc[2] == 0x24, "not a FIST opcode"); |
duke@435 | 533 | return true; |
duke@435 | 534 | } else { |
duke@435 | 535 | assert(pc[-3] == 0xDB, "not an flt invalid opcode"); |
duke@435 | 536 | assert(pc[-2] == 0x14, "not an flt invalid opcode"); |
duke@435 | 537 | assert(pc[-1] == 0x24, "not an flt invalid opcode"); |
duke@435 | 538 | } |
duke@435 | 539 | } |
duke@435 | 540 | else if (sig == SIGFPE ) { |
duke@435 | 541 | tty->print_cr("caught SIGFPE, info 0x%x.", info->si_code); |
duke@435 | 542 | } |
duke@435 | 543 | #endif // !AMD64 |
duke@435 | 544 | |
duke@435 | 545 | // QQQ It doesn't seem that we need to do this on x86 because we should be able |
duke@435 | 546 | // to return properly from the handler without this extra stuff on the back side. |
duke@435 | 547 | |
duke@435 | 548 | else if (sig == SIGSEGV && info->si_code > 0 && !MacroAssembler::needs_explicit_null_check((intptr_t)info->si_addr)) { |
duke@435 | 549 | // Determination of interpreter/vtable stub/compiled code null exception |
duke@435 | 550 | stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL); |
duke@435 | 551 | } |
duke@435 | 552 | } |
duke@435 | 553 | |
duke@435 | 554 | // jni_fast_Get<Primitive>Field can trap at certain pc's if a GC kicks in |
duke@435 | 555 | // and the heap gets shrunk before the field access. |
duke@435 | 556 | if ((sig == SIGSEGV) || (sig == SIGBUS)) { |
duke@435 | 557 | address addr = JNI_FastGetField::find_slowcase_pc(pc); |
duke@435 | 558 | if (addr != (address)-1) { |
duke@435 | 559 | stub = addr; |
duke@435 | 560 | } |
duke@435 | 561 | } |
duke@435 | 562 | |
duke@435 | 563 | // Check to see if we caught the safepoint code in the |
duke@435 | 564 | // process of write protecting the memory serialization page. |
duke@435 | 565 | // It write enables the page immediately after protecting it |
duke@435 | 566 | // so we can just return to retry the write. |
duke@435 | 567 | if ((sig == SIGSEGV) && |
duke@435 | 568 | os::is_memory_serialize_page(thread, (address)info->si_addr)) { |
duke@435 | 569 | // Block current thread until the memory serialize page permission restored. |
duke@435 | 570 | os::block_on_serialize_page_trap(); |
duke@435 | 571 | return true; |
duke@435 | 572 | } |
duke@435 | 573 | } |
duke@435 | 574 | |
duke@435 | 575 | // Execution protection violation |
duke@435 | 576 | // |
duke@435 | 577 | // Preventative code for future versions of Solaris which may |
duke@435 | 578 | // enable execution protection when running the 32-bit VM on AMD64. |
duke@435 | 579 | // |
duke@435 | 580 | // This should be kept as the last step in the triage. We don't |
duke@435 | 581 | // have a dedicated trap number for a no-execute fault, so be |
duke@435 | 582 | // conservative and allow other handlers the first shot. |
duke@435 | 583 | // |
duke@435 | 584 | // Note: We don't test that info->si_code == SEGV_ACCERR here. |
duke@435 | 585 | // this si_code is so generic that it is almost meaningless; and |
duke@435 | 586 | // the si_code for this condition may change in the future. |
duke@435 | 587 | // Furthermore, a false-positive should be harmless. |
duke@435 | 588 | if (UnguardOnExecutionViolation > 0 && |
duke@435 | 589 | (sig == SIGSEGV || sig == SIGBUS) && |
duke@435 | 590 | uc->uc_mcontext.gregs[TRAPNO] == T_PGFLT) { // page fault |
duke@435 | 591 | int page_size = os::vm_page_size(); |
duke@435 | 592 | address addr = (address) info->si_addr; |
duke@435 | 593 | address pc = (address) uc->uc_mcontext.gregs[REG_PC]; |
duke@435 | 594 | // Make sure the pc and the faulting address are sane. |
duke@435 | 595 | // |
duke@435 | 596 | // If an instruction spans a page boundary, and the page containing |
duke@435 | 597 | // the beginning of the instruction is executable but the following |
duke@435 | 598 | // page is not, the pc and the faulting address might be slightly |
duke@435 | 599 | // different - we still want to unguard the 2nd page in this case. |
duke@435 | 600 | // |
duke@435 | 601 | // 15 bytes seems to be a (very) safe value for max instruction size. |
duke@435 | 602 | bool pc_is_near_addr = |
duke@435 | 603 | (pointer_delta((void*) addr, (void*) pc, sizeof(char)) < 15); |
duke@435 | 604 | bool instr_spans_page_boundary = |
duke@435 | 605 | (align_size_down((intptr_t) pc ^ (intptr_t) addr, |
duke@435 | 606 | (intptr_t) page_size) > 0); |
duke@435 | 607 | |
duke@435 | 608 | if (pc == addr || (pc_is_near_addr && instr_spans_page_boundary)) { |
duke@435 | 609 | static volatile address last_addr = |
duke@435 | 610 | (address) os::non_memory_address_word(); |
duke@435 | 611 | |
duke@435 | 612 | // In conservative mode, don't unguard unless the address is in the VM |
duke@435 | 613 | if (addr != last_addr && |
duke@435 | 614 | (UnguardOnExecutionViolation > 1 || os::address_is_in_vm(addr))) { |
duke@435 | 615 | |
coleenp@912 | 616 | // Make memory rwx and retry |
duke@435 | 617 | address page_start = |
duke@435 | 618 | (address) align_size_down((intptr_t) addr, (intptr_t) page_size); |
coleenp@912 | 619 | bool res = os::protect_memory((char*) page_start, page_size, |
coleenp@912 | 620 | os::MEM_PROT_RWX); |
duke@435 | 621 | |
duke@435 | 622 | if (PrintMiscellaneous && Verbose) { |
duke@435 | 623 | char buf[256]; |
duke@435 | 624 | jio_snprintf(buf, sizeof(buf), "Execution protection violation " |
duke@435 | 625 | "at " INTPTR_FORMAT |
duke@435 | 626 | ", unguarding " INTPTR_FORMAT ": %s, errno=%d", addr, |
duke@435 | 627 | page_start, (res ? "success" : "failed"), errno); |
duke@435 | 628 | tty->print_raw_cr(buf); |
duke@435 | 629 | } |
duke@435 | 630 | stub = pc; |
duke@435 | 631 | |
duke@435 | 632 | // Set last_addr so if we fault again at the same address, we don't end |
duke@435 | 633 | // up in an endless loop. |
duke@435 | 634 | // |
duke@435 | 635 | // There are two potential complications here. Two threads trapping at |
duke@435 | 636 | // the same address at the same time could cause one of the threads to |
duke@435 | 637 | // think it already unguarded, and abort the VM. Likely very rare. |
duke@435 | 638 | // |
duke@435 | 639 | // The other race involves two threads alternately trapping at |
duke@435 | 640 | // different addresses and failing to unguard the page, resulting in |
duke@435 | 641 | // an endless loop. This condition is probably even more unlikely than |
duke@435 | 642 | // the first. |
duke@435 | 643 | // |
duke@435 | 644 | // Although both cases could be avoided by using locks or thread local |
duke@435 | 645 | // last_addr, these solutions are unnecessary complication: this |
duke@435 | 646 | // handler is a best-effort safety net, not a complete solution. It is |
duke@435 | 647 | // disabled by default and should only be used as a workaround in case |
duke@435 | 648 | // we missed any no-execute-unsafe VM code. |
duke@435 | 649 | |
duke@435 | 650 | last_addr = addr; |
duke@435 | 651 | } |
duke@435 | 652 | } |
duke@435 | 653 | } |
duke@435 | 654 | |
duke@435 | 655 | if (stub != NULL) { |
duke@435 | 656 | // save all thread context in case we need to restore it |
duke@435 | 657 | |
duke@435 | 658 | if (thread != NULL) thread->set_saved_exception_pc(pc); |
duke@435 | 659 | // 12/02/99: On Sparc it appears that the full context is also saved |
duke@435 | 660 | // but as yet, no one looks at or restores that saved context |
duke@435 | 661 | // factor me: setPC |
duke@435 | 662 | uc->uc_mcontext.gregs[REG_PC] = (greg_t)stub; |
duke@435 | 663 | return true; |
duke@435 | 664 | } |
duke@435 | 665 | |
duke@435 | 666 | // signal-chaining |
duke@435 | 667 | if (os::Solaris::chained_handler(sig, info, ucVoid)) { |
duke@435 | 668 | return true; |
duke@435 | 669 | } |
duke@435 | 670 | |
duke@435 | 671 | #ifndef AMD64 |
duke@435 | 672 | // Workaround (bug 4900493) for Solaris kernel bug 4966651. |
duke@435 | 673 | // Handle an undefined selector caused by an attempt to assign |
duke@435 | 674 | // fs in libthread getipriptr(). With the current libthread design every 512 |
duke@435 | 675 | // thread creations the LDT for a private thread data structure is extended |
duke@435 | 676 | // and thre is a hazard that and another thread attempting a thread creation |
duke@435 | 677 | // will use a stale LDTR that doesn't reflect the structure's growth, |
duke@435 | 678 | // causing a GP fault. |
duke@435 | 679 | // Enforce the probable limit of passes through here to guard against an |
duke@435 | 680 | // infinite loop if some other move to fs caused the GP fault. Note that |
duke@435 | 681 | // this loop counter is ultimately a heuristic as it is possible for |
duke@435 | 682 | // more than one thread to generate this fault at a time in an MP system. |
duke@435 | 683 | // In the case of the loop count being exceeded or if the poll fails |
duke@435 | 684 | // just fall through to a fatal error. |
duke@435 | 685 | // If there is some other source of T_GPFLT traps and the text at EIP is |
duke@435 | 686 | // unreadable this code will loop infinitely until the stack is exausted. |
duke@435 | 687 | // The key to diagnosis in this case is to look for the bottom signal handler |
duke@435 | 688 | // frame. |
duke@435 | 689 | |
duke@435 | 690 | if(! IgnoreLibthreadGPFault) { |
duke@435 | 691 | if (sig == SIGSEGV && uc->uc_mcontext.gregs[TRAPNO] == T_GPFLT) { |
duke@435 | 692 | const unsigned char *p = |
duke@435 | 693 | (unsigned const char *) uc->uc_mcontext.gregs[EIP]; |
duke@435 | 694 | |
duke@435 | 695 | // Expected instruction? |
duke@435 | 696 | |
duke@435 | 697 | if(p[0] == movlfs[0] && p[1] == movlfs[1]) { |
duke@435 | 698 | |
duke@435 | 699 | Atomic::inc(&ldtr_refresh); |
duke@435 | 700 | |
duke@435 | 701 | // Infinite loop? |
duke@435 | 702 | |
duke@435 | 703 | if(ldtr_refresh < ((2 << 16) / PAGESIZE)) { |
duke@435 | 704 | |
duke@435 | 705 | // No, force scheduling to get a fresh view of the LDTR |
duke@435 | 706 | |
duke@435 | 707 | if(poll(NULL, 0, 10) == 0) { |
duke@435 | 708 | |
duke@435 | 709 | // Retry the move |
duke@435 | 710 | |
duke@435 | 711 | return false; |
duke@435 | 712 | } |
duke@435 | 713 | } |
duke@435 | 714 | } |
duke@435 | 715 | } |
duke@435 | 716 | } |
duke@435 | 717 | #endif // !AMD64 |
duke@435 | 718 | |
duke@435 | 719 | if (!abort_if_unrecognized) { |
duke@435 | 720 | // caller wants another chance, so give it to him |
duke@435 | 721 | return false; |
duke@435 | 722 | } |
duke@435 | 723 | |
duke@435 | 724 | if (!os::Solaris::libjsig_is_loaded) { |
duke@435 | 725 | struct sigaction oldAct; |
duke@435 | 726 | sigaction(sig, (struct sigaction *)0, &oldAct); |
duke@435 | 727 | if (oldAct.sa_sigaction != signalHandler) { |
duke@435 | 728 | void* sighand = oldAct.sa_sigaction ? CAST_FROM_FN_PTR(void*, oldAct.sa_sigaction) |
duke@435 | 729 | : CAST_FROM_FN_PTR(void*, oldAct.sa_handler); |
twisti@1040 | 730 | warning("Unexpected Signal %d occurred under user-defined signal handler %#lx", sig, (long)sighand); |
duke@435 | 731 | } |
duke@435 | 732 | } |
duke@435 | 733 | |
duke@435 | 734 | if (pc == NULL && uc != NULL) { |
duke@435 | 735 | pc = (address) uc->uc_mcontext.gregs[REG_PC]; |
duke@435 | 736 | } |
duke@435 | 737 | |
duke@435 | 738 | // unmask current signal |
duke@435 | 739 | sigset_t newset; |
duke@435 | 740 | sigemptyset(&newset); |
duke@435 | 741 | sigaddset(&newset, sig); |
duke@435 | 742 | sigprocmask(SIG_UNBLOCK, &newset, NULL); |
duke@435 | 743 | |
coleenp@2418 | 744 | // Determine which sort of error to throw. Out of swap may signal |
coleenp@2418 | 745 | // on the thread stack, which could get a mapping error when touched. |
coleenp@2418 | 746 | address addr = (address) info->si_addr; |
coleenp@2418 | 747 | if (sig == SIGBUS && info->si_code == BUS_OBJERR && info->si_errno == ENOMEM) { |
coleenp@2418 | 748 | vm_exit_out_of_memory(0, "Out of swap space to map in thread stack."); |
coleenp@2418 | 749 | } |
coleenp@2418 | 750 | |
duke@435 | 751 | VMError err(t, sig, pc, info, ucVoid); |
duke@435 | 752 | err.report_and_die(); |
duke@435 | 753 | |
duke@435 | 754 | ShouldNotReachHere(); |
duke@435 | 755 | } |
duke@435 | 756 | |
duke@435 | 757 | void os::print_context(outputStream *st, void *context) { |
duke@435 | 758 | if (context == NULL) return; |
duke@435 | 759 | |
duke@435 | 760 | ucontext_t *uc = (ucontext_t*)context; |
duke@435 | 761 | st->print_cr("Registers:"); |
duke@435 | 762 | #ifdef AMD64 |
duke@435 | 763 | st->print( "RAX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RAX]); |
duke@435 | 764 | st->print(", RBX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RBX]); |
duke@435 | 765 | st->print(", RCX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RCX]); |
duke@435 | 766 | st->print(", RDX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RDX]); |
duke@435 | 767 | st->cr(); |
duke@435 | 768 | st->print( "RSP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RSP]); |
duke@435 | 769 | st->print(", RBP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RBP]); |
duke@435 | 770 | st->print(", RSI=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RSI]); |
duke@435 | 771 | st->print(", RDI=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RDI]); |
duke@435 | 772 | st->cr(); |
never@2262 | 773 | st->print( "R8 =" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R8]); |
never@2262 | 774 | st->print(", R9 =" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R9]); |
duke@435 | 775 | st->print(", R10=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R10]); |
duke@435 | 776 | st->print(", R11=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R11]); |
never@1685 | 777 | st->cr(); |
never@1685 | 778 | st->print( "R12=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R12]); |
duke@435 | 779 | st->print(", R13=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R13]); |
duke@435 | 780 | st->print(", R14=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R14]); |
duke@435 | 781 | st->print(", R15=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_R15]); |
duke@435 | 782 | st->cr(); |
duke@435 | 783 | st->print( "RIP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RIP]); |
duke@435 | 784 | st->print(", RFLAGS=" INTPTR_FORMAT, uc->uc_mcontext.gregs[REG_RFL]); |
duke@435 | 785 | #else |
duke@435 | 786 | st->print( "EAX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[EAX]); |
duke@435 | 787 | st->print(", EBX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[EBX]); |
duke@435 | 788 | st->print(", ECX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[ECX]); |
duke@435 | 789 | st->print(", EDX=" INTPTR_FORMAT, uc->uc_mcontext.gregs[EDX]); |
duke@435 | 790 | st->cr(); |
duke@435 | 791 | st->print( "ESP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[UESP]); |
duke@435 | 792 | st->print(", EBP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[EBP]); |
duke@435 | 793 | st->print(", ESI=" INTPTR_FORMAT, uc->uc_mcontext.gregs[ESI]); |
duke@435 | 794 | st->print(", EDI=" INTPTR_FORMAT, uc->uc_mcontext.gregs[EDI]); |
duke@435 | 795 | st->cr(); |
duke@435 | 796 | st->print( "EIP=" INTPTR_FORMAT, uc->uc_mcontext.gregs[EIP]); |
duke@435 | 797 | st->print(", EFLAGS=" INTPTR_FORMAT, uc->uc_mcontext.gregs[EFL]); |
duke@435 | 798 | #endif // AMD64 |
duke@435 | 799 | st->cr(); |
duke@435 | 800 | st->cr(); |
duke@435 | 801 | |
duke@435 | 802 | intptr_t *sp = (intptr_t *)os::Solaris::ucontext_get_sp(uc); |
duke@435 | 803 | st->print_cr("Top of Stack: (sp=" PTR_FORMAT ")", sp); |
duke@435 | 804 | print_hex_dump(st, (address)sp, (address)(sp + 8*sizeof(intptr_t)), sizeof(intptr_t)); |
duke@435 | 805 | st->cr(); |
duke@435 | 806 | |
duke@435 | 807 | // Note: it may be unsafe to inspect memory near pc. For example, pc may |
duke@435 | 808 | // point to garbage if entry point in an nmethod is corrupted. Leave |
duke@435 | 809 | // this at the end, and hope for the best. |
duke@435 | 810 | ExtendedPC epc = os::Solaris::ucontext_get_ExtendedPC(uc); |
duke@435 | 811 | address pc = epc.pc(); |
duke@435 | 812 | st->print_cr("Instructions: (pc=" PTR_FORMAT ")", pc); |
never@2262 | 813 | print_hex_dump(st, pc - 32, pc + 32, sizeof(char)); |
never@2262 | 814 | } |
never@2262 | 815 | |
never@2262 | 816 | void os::print_register_info(outputStream *st, void *context) { |
never@2262 | 817 | if (context == NULL) return; |
never@2262 | 818 | |
never@2262 | 819 | ucontext_t *uc = (ucontext_t*)context; |
never@2262 | 820 | |
never@2262 | 821 | st->print_cr("Register to memory mapping:"); |
never@2262 | 822 | st->cr(); |
never@2262 | 823 | |
never@2262 | 824 | // this is horrendously verbose but the layout of the registers in the |
never@2262 | 825 | // context does not match how we defined our abstract Register set, so |
never@2262 | 826 | // we can't just iterate through the gregs area |
never@2262 | 827 | |
never@2262 | 828 | // this is only for the "general purpose" registers |
never@2262 | 829 | |
never@2262 | 830 | #ifdef AMD64 |
never@2262 | 831 | st->print("RAX="); print_location(st, uc->uc_mcontext.gregs[REG_RAX]); |
never@2262 | 832 | st->print("RBX="); print_location(st, uc->uc_mcontext.gregs[REG_RBX]); |
never@2262 | 833 | st->print("RCX="); print_location(st, uc->uc_mcontext.gregs[REG_RCX]); |
never@2262 | 834 | st->print("RDX="); print_location(st, uc->uc_mcontext.gregs[REG_RDX]); |
never@2262 | 835 | st->print("RSP="); print_location(st, uc->uc_mcontext.gregs[REG_RSP]); |
never@2262 | 836 | st->print("RBP="); print_location(st, uc->uc_mcontext.gregs[REG_RBP]); |
never@2262 | 837 | st->print("RSI="); print_location(st, uc->uc_mcontext.gregs[REG_RSI]); |
never@2262 | 838 | st->print("RDI="); print_location(st, uc->uc_mcontext.gregs[REG_RDI]); |
never@2262 | 839 | st->print("R8 ="); print_location(st, uc->uc_mcontext.gregs[REG_R8]); |
never@2262 | 840 | st->print("R9 ="); print_location(st, uc->uc_mcontext.gregs[REG_R9]); |
never@2262 | 841 | st->print("R10="); print_location(st, uc->uc_mcontext.gregs[REG_R10]); |
never@2262 | 842 | st->print("R11="); print_location(st, uc->uc_mcontext.gregs[REG_R11]); |
never@2262 | 843 | st->print("R12="); print_location(st, uc->uc_mcontext.gregs[REG_R12]); |
never@2262 | 844 | st->print("R13="); print_location(st, uc->uc_mcontext.gregs[REG_R13]); |
never@2262 | 845 | st->print("R14="); print_location(st, uc->uc_mcontext.gregs[REG_R14]); |
never@2262 | 846 | st->print("R15="); print_location(st, uc->uc_mcontext.gregs[REG_R15]); |
never@2262 | 847 | #else |
never@2262 | 848 | st->print("EAX="); print_location(st, uc->uc_mcontext.gregs[EAX]); |
never@2262 | 849 | st->print("EBX="); print_location(st, uc->uc_mcontext.gregs[EBX]); |
never@2262 | 850 | st->print("ECX="); print_location(st, uc->uc_mcontext.gregs[ECX]); |
never@2262 | 851 | st->print("EDX="); print_location(st, uc->uc_mcontext.gregs[EDX]); |
never@2262 | 852 | st->print("ESP="); print_location(st, uc->uc_mcontext.gregs[UESP]); |
never@2262 | 853 | st->print("EBP="); print_location(st, uc->uc_mcontext.gregs[EBP]); |
never@2262 | 854 | st->print("ESI="); print_location(st, uc->uc_mcontext.gregs[ESI]); |
never@2262 | 855 | st->print("EDI="); print_location(st, uc->uc_mcontext.gregs[EDI]); |
never@2262 | 856 | #endif |
never@2262 | 857 | |
never@2262 | 858 | st->cr(); |
duke@435 | 859 | } |
duke@435 | 860 | |
bobv@2036 | 861 | |
duke@435 | 862 | #ifdef AMD64 |
duke@435 | 863 | void os::Solaris::init_thread_fpu_state(void) { |
duke@435 | 864 | // Nothing to do |
duke@435 | 865 | } |
duke@435 | 866 | #else |
duke@435 | 867 | // From solaris_i486.s |
duke@435 | 868 | extern "C" void fixcw(); |
duke@435 | 869 | |
duke@435 | 870 | void os::Solaris::init_thread_fpu_state(void) { |
duke@435 | 871 | // Set fpu to 53 bit precision. This happens too early to use a stub. |
duke@435 | 872 | fixcw(); |
duke@435 | 873 | } |
duke@435 | 874 | |
duke@435 | 875 | // These routines are the initial value of atomic_xchg_entry(), |
duke@435 | 876 | // atomic_cmpxchg_entry(), atomic_inc_entry() and fence_entry() |
duke@435 | 877 | // until initialization is complete. |
duke@435 | 878 | // TODO - replace with .il implementation when compiler supports it. |
duke@435 | 879 | |
duke@435 | 880 | typedef jint xchg_func_t (jint, volatile jint*); |
duke@435 | 881 | typedef jint cmpxchg_func_t (jint, volatile jint*, jint); |
duke@435 | 882 | typedef jlong cmpxchg_long_func_t(jlong, volatile jlong*, jlong); |
duke@435 | 883 | typedef jint add_func_t (jint, volatile jint*); |
duke@435 | 884 | |
duke@435 | 885 | jint os::atomic_xchg_bootstrap(jint exchange_value, volatile jint* dest) { |
duke@435 | 886 | // try to use the stub: |
duke@435 | 887 | xchg_func_t* func = CAST_TO_FN_PTR(xchg_func_t*, StubRoutines::atomic_xchg_entry()); |
duke@435 | 888 | |
duke@435 | 889 | if (func != NULL) { |
duke@435 | 890 | os::atomic_xchg_func = func; |
duke@435 | 891 | return (*func)(exchange_value, dest); |
duke@435 | 892 | } |
duke@435 | 893 | assert(Threads::number_of_threads() == 0, "for bootstrap only"); |
duke@435 | 894 | |
duke@435 | 895 | jint old_value = *dest; |
duke@435 | 896 | *dest = exchange_value; |
duke@435 | 897 | return old_value; |
duke@435 | 898 | } |
duke@435 | 899 | |
duke@435 | 900 | jint os::atomic_cmpxchg_bootstrap(jint exchange_value, volatile jint* dest, jint compare_value) { |
duke@435 | 901 | // try to use the stub: |
duke@435 | 902 | cmpxchg_func_t* func = CAST_TO_FN_PTR(cmpxchg_func_t*, StubRoutines::atomic_cmpxchg_entry()); |
duke@435 | 903 | |
duke@435 | 904 | if (func != NULL) { |
duke@435 | 905 | os::atomic_cmpxchg_func = func; |
duke@435 | 906 | return (*func)(exchange_value, dest, compare_value); |
duke@435 | 907 | } |
duke@435 | 908 | assert(Threads::number_of_threads() == 0, "for bootstrap only"); |
duke@435 | 909 | |
duke@435 | 910 | jint old_value = *dest; |
duke@435 | 911 | if (old_value == compare_value) |
duke@435 | 912 | *dest = exchange_value; |
duke@435 | 913 | return old_value; |
duke@435 | 914 | } |
duke@435 | 915 | |
duke@435 | 916 | jlong os::atomic_cmpxchg_long_bootstrap(jlong exchange_value, volatile jlong* dest, jlong compare_value) { |
duke@435 | 917 | // try to use the stub: |
duke@435 | 918 | cmpxchg_long_func_t* func = CAST_TO_FN_PTR(cmpxchg_long_func_t*, StubRoutines::atomic_cmpxchg_long_entry()); |
duke@435 | 919 | |
duke@435 | 920 | if (func != NULL) { |
duke@435 | 921 | os::atomic_cmpxchg_long_func = func; |
duke@435 | 922 | return (*func)(exchange_value, dest, compare_value); |
duke@435 | 923 | } |
duke@435 | 924 | assert(Threads::number_of_threads() == 0, "for bootstrap only"); |
duke@435 | 925 | |
duke@435 | 926 | jlong old_value = *dest; |
duke@435 | 927 | if (old_value == compare_value) |
duke@435 | 928 | *dest = exchange_value; |
duke@435 | 929 | return old_value; |
duke@435 | 930 | } |
duke@435 | 931 | |
duke@435 | 932 | jint os::atomic_add_bootstrap(jint add_value, volatile jint* dest) { |
duke@435 | 933 | // try to use the stub: |
duke@435 | 934 | add_func_t* func = CAST_TO_FN_PTR(add_func_t*, StubRoutines::atomic_add_entry()); |
duke@435 | 935 | |
duke@435 | 936 | if (func != NULL) { |
duke@435 | 937 | os::atomic_add_func = func; |
duke@435 | 938 | return (*func)(add_value, dest); |
duke@435 | 939 | } |
duke@435 | 940 | assert(Threads::number_of_threads() == 0, "for bootstrap only"); |
duke@435 | 941 | |
duke@435 | 942 | return (*dest) += add_value; |
duke@435 | 943 | } |
duke@435 | 944 | |
duke@435 | 945 | xchg_func_t* os::atomic_xchg_func = os::atomic_xchg_bootstrap; |
duke@435 | 946 | cmpxchg_func_t* os::atomic_cmpxchg_func = os::atomic_cmpxchg_bootstrap; |
duke@435 | 947 | cmpxchg_long_func_t* os::atomic_cmpxchg_long_func = os::atomic_cmpxchg_long_bootstrap; |
duke@435 | 948 | add_func_t* os::atomic_add_func = os::atomic_add_bootstrap; |
duke@435 | 949 | |
zgu@1979 | 950 | extern "C" void _solaris_raw_setup_fpu(address ptr); |
duke@435 | 951 | void os::setup_fpu() { |
duke@435 | 952 | address fpu_cntrl = StubRoutines::addr_fpu_cntrl_wrd_std(); |
duke@435 | 953 | _solaris_raw_setup_fpu(fpu_cntrl); |
duke@435 | 954 | } |
duke@435 | 955 | #endif // AMD64 |
roland@3606 | 956 | |
roland@3606 | 957 | #ifndef PRODUCT |
roland@3606 | 958 | void os::verify_stack_alignment() { |
roland@3606 | 959 | #ifdef AMD64 |
roland@3606 | 960 | assert(((intptr_t)os::current_stack_pointer() & (StackAlignmentInBytes-1)) == 0, "incorrect stack alignment"); |
roland@3606 | 961 | #endif |
roland@3606 | 962 | } |
roland@3606 | 963 | #endif |