src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp

Fri, 06 Sep 2013 20:16:09 +0200

author
simonis
date
Fri, 06 Sep 2013 20:16:09 +0200
changeset 6465
666e6ce3976c
child 6495
67fa91961822
permissions
-rw-r--r--

8023038: PPC64 (part 15): Platform files for AIX/PPC64 support
Reviewed-by: kvn

simonis@6465 1 /*
simonis@6465 2 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
simonis@6465 3 * Copyright 2012, 2013 SAP AG. All rights reserved.
simonis@6465 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
simonis@6465 5 *
simonis@6465 6 * This code is free software; you can redistribute it and/or modify it
simonis@6465 7 * under the terms of the GNU General Public License version 2 only, as
simonis@6465 8 * published by the Free Software Foundation.
simonis@6465 9 *
simonis@6465 10 * This code is distributed in the hope that it will be useful, but WITHOUT
simonis@6465 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
simonis@6465 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
simonis@6465 13 * version 2 for more details (a copy is included in the LICENSE file that
simonis@6465 14 * accompanied this code).
simonis@6465 15 *
simonis@6465 16 * You should have received a copy of the GNU General Public License version
simonis@6465 17 * 2 along with this work; if not, write to the Free Software Foundation,
simonis@6465 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
simonis@6465 19 *
simonis@6465 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
simonis@6465 21 * or visit www.oracle.com if you need additional information or have any
simonis@6465 22 * questions.
simonis@6465 23 *
simonis@6465 24 */
simonis@6465 25
simonis@6465 26 // no precompiled headers
simonis@6465 27 #include "assembler_ppc.inline.hpp"
simonis@6465 28 #include "classfile/classLoader.hpp"
simonis@6465 29 #include "classfile/systemDictionary.hpp"
simonis@6465 30 #include "classfile/vmSymbols.hpp"
simonis@6465 31 #include "code/icBuffer.hpp"
simonis@6465 32 #include "code/vtableStubs.hpp"
simonis@6465 33 #include "interpreter/interpreter.hpp"
simonis@6465 34 #include "jvm_aix.h"
simonis@6465 35 #include "memory/allocation.inline.hpp"
simonis@6465 36 #include "mutex_aix.inline.hpp"
simonis@6465 37 #include "nativeInst_ppc.hpp"
simonis@6465 38 #include "os_share_aix.hpp"
simonis@6465 39 #include "prims/jniFastGetField.hpp"
simonis@6465 40 #include "prims/jvm.h"
simonis@6465 41 #include "prims/jvm_misc.hpp"
simonis@6465 42 #include "runtime/arguments.hpp"
simonis@6465 43 #include "runtime/extendedPC.hpp"
simonis@6465 44 #include "runtime/frame.inline.hpp"
simonis@6465 45 #include "runtime/interfaceSupport.hpp"
simonis@6465 46 #include "runtime/java.hpp"
simonis@6465 47 #include "runtime/javaCalls.hpp"
simonis@6465 48 #include "runtime/mutexLocker.hpp"
simonis@6465 49 #include "runtime/osThread.hpp"
simonis@6465 50 #include "runtime/sharedRuntime.hpp"
simonis@6465 51 #include "runtime/stubRoutines.hpp"
simonis@6465 52 #include "runtime/timer.hpp"
simonis@6465 53 #include "thread_aix.inline.hpp"
simonis@6465 54 #include "utilities/events.hpp"
simonis@6465 55 #include "utilities/vmError.hpp"
simonis@6465 56 #ifdef COMPILER1
simonis@6465 57 #include "c1/c1_Runtime1.hpp"
simonis@6465 58 #endif
simonis@6465 59 #ifdef COMPILER2
simonis@6465 60 #include "opto/runtime.hpp"
simonis@6465 61 #endif
simonis@6465 62
simonis@6465 63 // put OS-includes here
simonis@6465 64 # include <ucontext.h>
simonis@6465 65
simonis@6465 66 address os::current_stack_pointer() {
simonis@6465 67 address csp;
simonis@6465 68
simonis@6465 69 #if !defined(USE_XLC_BUILTINS)
simonis@6465 70 // inline assembly for `ppc_mr regno(csp), PPC_SP':
simonis@6465 71 __asm__ __volatile__ ("mr %0, 1":"=r"(csp):);
simonis@6465 72 #else
simonis@6465 73 csp = (address) __builtin_frame_address(0);
simonis@6465 74 #endif
simonis@6465 75
simonis@6465 76 return csp;
simonis@6465 77 }
simonis@6465 78
simonis@6465 79 char* os::non_memory_address_word() {
simonis@6465 80 // Must never look like an address returned by reserve_memory,
simonis@6465 81 // even in its subfields (as defined by the CPU immediate fields,
simonis@6465 82 // if the CPU splits constants across multiple instructions).
simonis@6465 83
simonis@6465 84 return (char*) -1;
simonis@6465 85 }
simonis@6465 86
simonis@6465 87 // OS specific thread initialization
simonis@6465 88 //
simonis@6465 89 // Calculate and store the limits of the memory stack.
simonis@6465 90 void os::initialize_thread(Thread *thread) { }
simonis@6465 91
simonis@6465 92 // Frame information (pc, sp, fp) retrieved via ucontext
simonis@6465 93 // always looks like a C-frame according to the frame
simonis@6465 94 // conventions in frame_ppc64.hpp.
simonis@6465 95 address os::Aix::ucontext_get_pc(ucontext_t * uc) {
simonis@6465 96 return (address)uc->uc_mcontext.jmp_context.iar;
simonis@6465 97 }
simonis@6465 98
simonis@6465 99 intptr_t* os::Aix::ucontext_get_sp(ucontext_t * uc) {
simonis@6465 100 // gpr1 holds the stack pointer on aix
simonis@6465 101 return (intptr_t*)uc->uc_mcontext.jmp_context.gpr[1/*REG_SP*/];
simonis@6465 102 }
simonis@6465 103
simonis@6465 104 intptr_t* os::Aix::ucontext_get_fp(ucontext_t * uc) {
simonis@6465 105 return NULL;
simonis@6465 106 }
simonis@6465 107
simonis@6465 108 void os::Aix::ucontext_set_pc(ucontext_t* uc, address new_pc) {
simonis@6465 109 uc->uc_mcontext.jmp_context.iar = (uint64_t) new_pc;
simonis@6465 110 }
simonis@6465 111
simonis@6465 112 ExtendedPC os::fetch_frame_from_context(void* ucVoid,
simonis@6465 113 intptr_t** ret_sp, intptr_t** ret_fp) {
simonis@6465 114
simonis@6465 115 ExtendedPC epc;
simonis@6465 116 ucontext_t* uc = (ucontext_t*)ucVoid;
simonis@6465 117
simonis@6465 118 if (uc != NULL) {
simonis@6465 119 epc = ExtendedPC(os::Aix::ucontext_get_pc(uc));
simonis@6465 120 if (ret_sp) *ret_sp = os::Aix::ucontext_get_sp(uc);
simonis@6465 121 if (ret_fp) *ret_fp = os::Aix::ucontext_get_fp(uc);
simonis@6465 122 } else {
simonis@6465 123 // construct empty ExtendedPC for return value checking
simonis@6465 124 epc = ExtendedPC(NULL);
simonis@6465 125 if (ret_sp) *ret_sp = (intptr_t *)NULL;
simonis@6465 126 if (ret_fp) *ret_fp = (intptr_t *)NULL;
simonis@6465 127 }
simonis@6465 128
simonis@6465 129 return epc;
simonis@6465 130 }
simonis@6465 131
simonis@6465 132 frame os::fetch_frame_from_context(void* ucVoid) {
simonis@6465 133 intptr_t* sp;
simonis@6465 134 intptr_t* fp;
simonis@6465 135 ExtendedPC epc = fetch_frame_from_context(ucVoid, &sp, &fp);
simonis@6465 136 // Avoid crash during crash if pc broken.
simonis@6465 137 if (epc.pc()) {
simonis@6465 138 frame fr(sp, epc.pc());
simonis@6465 139 return fr;
simonis@6465 140 }
simonis@6465 141 frame fr(sp);
simonis@6465 142 return fr;
simonis@6465 143 }
simonis@6465 144
simonis@6465 145 frame os::get_sender_for_C_frame(frame* fr) {
simonis@6465 146 if (*fr->sp() == NULL) {
simonis@6465 147 // fr is the last C frame
simonis@6465 148 return frame(NULL, NULL);
simonis@6465 149 }
simonis@6465 150 return frame(fr->sender_sp(), fr->sender_pc());
simonis@6465 151 }
simonis@6465 152
simonis@6465 153
simonis@6465 154 frame os::current_frame() {
simonis@6465 155 intptr_t* csp = (intptr_t*) *((intptr_t*) os::current_stack_pointer());
simonis@6465 156 // hack.
simonis@6465 157 frame topframe(csp, (address)0x8);
simonis@6465 158 // return sender of current topframe which hopefully has pc != NULL.
simonis@6465 159 return os::get_sender_for_C_frame(&topframe);
simonis@6465 160 }
simonis@6465 161
simonis@6465 162 // Utility functions
simonis@6465 163
simonis@6465 164 extern "C" JNIEXPORT int
simonis@6465 165 JVM_handle_aix_signal(int sig, siginfo_t* info, void* ucVoid, int abort_if_unrecognized) {
simonis@6465 166
simonis@6465 167 ucontext_t* uc = (ucontext_t*) ucVoid;
simonis@6465 168
simonis@6465 169 Thread* t = ThreadLocalStorage::get_thread_slow(); // slow & steady
simonis@6465 170
simonis@6465 171 SignalHandlerMark shm(t);
simonis@6465 172
simonis@6465 173 // Note: it's not uncommon that JNI code uses signal/sigset to install
simonis@6465 174 // then restore certain signal handler (e.g. to temporarily block SIGPIPE,
simonis@6465 175 // or have a SIGILL handler when detecting CPU type). When that happens,
simonis@6465 176 // JVM_handle_aix_signal() might be invoked with junk info/ucVoid. To
simonis@6465 177 // avoid unnecessary crash when libjsig is not preloaded, try handle signals
simonis@6465 178 // that do not require siginfo/ucontext first.
simonis@6465 179
simonis@6465 180 if (sig == SIGPIPE) {
simonis@6465 181 if (os::Aix::chained_handler(sig, info, ucVoid)) {
simonis@6465 182 return 1;
simonis@6465 183 } else {
simonis@6465 184 if (PrintMiscellaneous && (WizardMode || Verbose)) {
simonis@6465 185 warning("Ignoring SIGPIPE - see bug 4229104");
simonis@6465 186 }
simonis@6465 187 return 1;
simonis@6465 188 }
simonis@6465 189 }
simonis@6465 190
simonis@6465 191 JavaThread* thread = NULL;
simonis@6465 192 VMThread* vmthread = NULL;
simonis@6465 193 if (os::Aix::signal_handlers_are_installed) {
simonis@6465 194 if (t != NULL) {
simonis@6465 195 if(t->is_Java_thread()) {
simonis@6465 196 thread = (JavaThread*)t;
simonis@6465 197 }
simonis@6465 198 else if(t->is_VM_thread()) {
simonis@6465 199 vmthread = (VMThread *)t;
simonis@6465 200 }
simonis@6465 201 }
simonis@6465 202 }
simonis@6465 203
simonis@6465 204 // Decide if this trap can be handled by a stub.
simonis@6465 205 address stub = NULL;
simonis@6465 206
simonis@6465 207 // retrieve program counter
simonis@6465 208 address const pc = uc ? os::Aix::ucontext_get_pc(uc) : NULL;
simonis@6465 209
simonis@6465 210 // retrieve crash address
simonis@6465 211 address const addr = info ? (const address) info->si_addr : NULL;
simonis@6465 212
simonis@6465 213 // SafeFetch 32 handling:
simonis@6465 214 // - make it work if _thread is null
simonis@6465 215 // - make it use the standard os::...::ucontext_get/set_pc APIs
simonis@6465 216 if (uc) {
simonis@6465 217 address const pc = os::Aix::ucontext_get_pc(uc);
simonis@6465 218 if (pc && StubRoutines::is_safefetch_fault(pc)) {
simonis@6465 219 os::Aix::ucontext_set_pc(uc, StubRoutines::continuation_for_safefetch_fault(pc));
simonis@6465 220 return true;
simonis@6465 221 }
simonis@6465 222 }
simonis@6465 223
simonis@6465 224 // Handle SIGDANGER right away. AIX would raise SIGDANGER whenever available swap
simonis@6465 225 // space falls below 30%. This is only a chance for the process to gracefully abort.
simonis@6465 226 // We can't hope to proceed after SIGDANGER since SIGKILL tailgates.
simonis@6465 227 if (sig == SIGDANGER) {
simonis@6465 228 goto report_and_die;
simonis@6465 229 }
simonis@6465 230
simonis@6465 231 if (info == NULL || uc == NULL || thread == NULL && vmthread == NULL) {
simonis@6465 232 goto run_chained_handler;
simonis@6465 233 }
simonis@6465 234
simonis@6465 235 // If we are a java thread...
simonis@6465 236 if (thread != NULL) {
simonis@6465 237
simonis@6465 238 // Handle ALL stack overflow variations here
simonis@6465 239 if (sig == SIGSEGV && (addr < thread->stack_base() &&
simonis@6465 240 addr >= thread->stack_base() - thread->stack_size())) {
simonis@6465 241 // stack overflow
simonis@6465 242 //
simonis@6465 243 // If we are in a yellow zone and we are inside java, we disable the yellow zone and
simonis@6465 244 // throw a stack overflow exception.
simonis@6465 245 // If we are in native code or VM C code, we report-and-die. The original coding tried
simonis@6465 246 // to continue with yellow zone disabled, but that doesn't buy us much and prevents
simonis@6465 247 // hs_err_pid files.
simonis@6465 248 if (thread->in_stack_yellow_zone(addr)) {
simonis@6465 249 thread->disable_stack_yellow_zone();
simonis@6465 250 if (thread->thread_state() == _thread_in_Java) {
simonis@6465 251 // Throw a stack overflow exception.
simonis@6465 252 // Guard pages will be reenabled while unwinding the stack.
simonis@6465 253 stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW);
simonis@6465 254 goto run_stub;
simonis@6465 255 } else {
simonis@6465 256 // Thread was in the vm or native code. Return and try to finish.
simonis@6465 257 return 1;
simonis@6465 258 }
simonis@6465 259 } else if (thread->in_stack_red_zone(addr)) {
simonis@6465 260 // Fatal red zone violation. Disable the guard pages and fall through
simonis@6465 261 // to handle_unexpected_exception way down below.
simonis@6465 262 thread->disable_stack_red_zone();
simonis@6465 263 tty->print_raw_cr("An irrecoverable stack overflow has occurred.");
simonis@6465 264 goto report_and_die;
simonis@6465 265 } else {
simonis@6465 266 // this means a segv happened inside our stack, but not in
simonis@6465 267 // the guarded zone. I'd like to know when this happens,
simonis@6465 268 tty->print_raw_cr("SIGSEGV happened inside stack but outside yellow and red zone.");
simonis@6465 269 goto report_and_die;
simonis@6465 270 }
simonis@6465 271
simonis@6465 272 } // end handle SIGSEGV inside stack boundaries
simonis@6465 273
simonis@6465 274 if (thread->thread_state() == _thread_in_Java) {
simonis@6465 275 // Java thread running in Java code
simonis@6465 276
simonis@6465 277 // The following signals are used for communicating VM events:
simonis@6465 278 //
simonis@6465 279 // SIGILL: the compiler generates illegal opcodes
simonis@6465 280 // at places where it wishes to interrupt the VM:
simonis@6465 281 // Safepoints, Unreachable Code, Entry points of Zombie methods,
simonis@6465 282 // This results in a SIGILL with (*pc) == inserted illegal instruction.
simonis@6465 283 //
simonis@6465 284 // (so, SIGILLs with a pc inside the zero page are real errors)
simonis@6465 285 //
simonis@6465 286 // SIGTRAP:
simonis@6465 287 // The ppc trap instruction raises a SIGTRAP and is very efficient if it
simonis@6465 288 // does not trap. It is used for conditional branches that are expected
simonis@6465 289 // to be never taken. These are:
simonis@6465 290 // - zombie methods
simonis@6465 291 // - IC (inline cache) misses.
simonis@6465 292 // - null checks leading to UncommonTraps.
simonis@6465 293 // - range checks leading to Uncommon Traps.
simonis@6465 294 // On Aix, these are especially null checks, as the ImplicitNullCheck
simonis@6465 295 // optimization works only in rare cases, as the page at address 0 is only
simonis@6465 296 // write protected. //
simonis@6465 297 // Note: !UseSIGTRAP is used to prevent SIGTRAPS altogether, to facilitate debugging.
simonis@6465 298 //
simonis@6465 299 // SIGSEGV:
simonis@6465 300 // used for safe point polling:
simonis@6465 301 // To notify all threads that they have to reach a safe point, safe point polling is used:
simonis@6465 302 // All threads poll a certain mapped memory page. Normally, this page has read access.
simonis@6465 303 // If the VM wants to inform the threads about impending safe points, it puts this
simonis@6465 304 // page to read only ("poisens" the page), and the threads then reach a safe point.
simonis@6465 305 // used for null checks:
simonis@6465 306 // If the compiler finds a store it uses it for a null check. Unfortunately this
simonis@6465 307 // happens rarely. In heap based and disjoint base compressd oop modes also loads
simonis@6465 308 // are used for null checks.
simonis@6465 309
simonis@6465 310 // A VM-related SIGILL may only occur if we are not in the zero page.
simonis@6465 311 // On AIX, we get a SIGILL if we jump to 0x0 or to somewhere else
simonis@6465 312 // in the zero page, because it is filled with 0x0. We ignore
simonis@6465 313 // explicit SIGILLs in the zero page.
simonis@6465 314 if (sig == SIGILL && (pc < (address) 0x200)) {
simonis@6465 315 if (TraceTraps)
simonis@6465 316 tty->print_raw_cr("SIGILL happened inside zero page.");
simonis@6465 317 goto report_and_die;
simonis@6465 318 }
simonis@6465 319
simonis@6465 320 // Handle signal from NativeJump::patch_verified_entry().
simonis@6465 321 if (( TrapBasedNotEntrantChecks && sig == SIGTRAP && nativeInstruction_at(pc)->is_sigtrap_zombie_not_entrant()) ||
simonis@6465 322 (!TrapBasedNotEntrantChecks && sig == SIGILL && nativeInstruction_at(pc)->is_sigill_zombie_not_entrant())) {
simonis@6465 323 if (TraceTraps)
simonis@6465 324 tty->print_cr("trap: zombie_not_entrant (%s)", (sig == SIGTRAP) ? "SIGTRAP" : "SIGILL");
simonis@6465 325 stub = SharedRuntime::get_handle_wrong_method_stub();
simonis@6465 326 goto run_stub;
simonis@6465 327 }
simonis@6465 328
simonis@6465 329 else if (sig == SIGSEGV && os::is_poll_address(addr)) {
simonis@6465 330 if (TraceTraps)
simonis@6465 331 tty->print_cr("trap: safepoint_poll at " INTPTR_FORMAT " (SIGSEGV)", pc);
simonis@6465 332 stub = SharedRuntime::get_poll_stub(pc);
simonis@6465 333 goto run_stub;
simonis@6465 334 }
simonis@6465 335
simonis@6465 336 // SIGTRAP-based ic miss check in compiled code
simonis@6465 337 else if (sig == SIGTRAP && TrapBasedICMissChecks &&
simonis@6465 338 nativeInstruction_at(pc)->is_sigtrap_ic_miss_check()) {
simonis@6465 339 if (TraceTraps)
simonis@6465 340 tty->print_cr("trap: ic_miss_check at " INTPTR_FORMAT " (SIGTRAP)", pc);
simonis@6465 341 stub = SharedRuntime::get_ic_miss_stub();
simonis@6465 342 goto run_stub;
simonis@6465 343 }
simonis@6465 344
simonis@6465 345 #ifdef COMPILER2
simonis@6465 346 // SIGTRAP-based implicit null check in compiled code.
simonis@6465 347 else if (sig == SIGTRAP && TrapBasedNullChecks &&
simonis@6465 348 nativeInstruction_at(pc)->is_sigtrap_null_check()) {
simonis@6465 349 if (TraceTraps)
simonis@6465 350 tty->print_cr("trap: null_check at " INTPTR_FORMAT " (SIGTRAP)", pc);
simonis@6465 351 stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL);
simonis@6465 352 goto run_stub;
simonis@6465 353 }
simonis@6465 354 #endif
simonis@6465 355
simonis@6465 356 // SIGSEGV-based implicit null check in compiled code.
simonis@6465 357 else if (sig == SIGSEGV && ImplicitNullChecks &&
simonis@6465 358 CodeCache::contains((void*) pc) &&
simonis@6465 359 !MacroAssembler::needs_explicit_null_check((intptr_t) info->si_addr)) {
simonis@6465 360 if (TraceTraps)
simonis@6465 361 tty->print_cr("trap: null_check at " INTPTR_FORMAT " (SIGSEGV)", pc);
simonis@6465 362 stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL);
simonis@6465 363 }
simonis@6465 364
simonis@6465 365 #ifdef COMPILER2
simonis@6465 366 // SIGTRAP-based implicit range check in compiled code.
simonis@6465 367 else if (sig == SIGTRAP && TrapBasedRangeChecks &&
simonis@6465 368 nativeInstruction_at(pc)->is_sigtrap_range_check()) {
simonis@6465 369 if (TraceTraps)
simonis@6465 370 tty->print_cr("trap: range_check at " INTPTR_FORMAT " (SIGTRAP)", pc);
simonis@6465 371 stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL);
simonis@6465 372 goto run_stub;
simonis@6465 373 }
simonis@6465 374 #endif
simonis@6465 375
simonis@6465 376 else if (sig == SIGFPE /* && info->si_code == FPE_INTDIV */) {
simonis@6465 377 if (TraceTraps) {
simonis@6465 378 tty->print_raw_cr("Fix SIGFPE handler, trying divide by zero handler.");
simonis@6465 379 }
simonis@6465 380 stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_DIVIDE_BY_ZERO);
simonis@6465 381 goto run_stub;
simonis@6465 382 }
simonis@6465 383
simonis@6465 384 else if (sig == SIGBUS) {
simonis@6465 385 // BugId 4454115: A read from a MappedByteBuffer can fault here if the
simonis@6465 386 // underlying file has been truncated. Do not crash the VM in such a case.
simonis@6465 387 CodeBlob* cb = CodeCache::find_blob_unsafe(pc);
simonis@6465 388 nmethod* nm = cb->is_nmethod() ? (nmethod*)cb : NULL;
simonis@6465 389 if (nm != NULL && nm->has_unsafe_access()) {
simonis@6465 390 // We don't really need a stub here! Just set the pending exeption and
simonis@6465 391 // continue at the next instruction after the faulting read. Returning
simonis@6465 392 // garbage from this read is ok.
simonis@6465 393 thread->set_pending_unsafe_access_error();
simonis@6465 394 uc->uc_mcontext.jmp_context.iar = ((unsigned long)pc) + 4;
simonis@6465 395 return 1;
simonis@6465 396 }
simonis@6465 397 }
simonis@6465 398 }
simonis@6465 399
simonis@6465 400 else { // thread->thread_state() != _thread_in_Java
simonis@6465 401 // Detect CPU features. This is only done at the very start of the VM. Later, the
simonis@6465 402 // VM_Version::is_determine_features_test_running() flag should be false.
simonis@6465 403
simonis@6465 404 if (sig == SIGILL && VM_Version::is_determine_features_test_running()) {
simonis@6465 405 // SIGILL must be caused by VM_Version::determine_features().
simonis@6465 406 *(int *)pc = 0; // patch instruction to 0 to indicate that it causes a SIGILL,
simonis@6465 407 // flushing of icache is not necessary.
simonis@6465 408 stub = pc + 4; // continue with next instruction.
simonis@6465 409 goto run_stub;
simonis@6465 410 }
simonis@6465 411 else if (thread->thread_state() == _thread_in_vm &&
simonis@6465 412 sig == SIGBUS && thread->doing_unsafe_access()) {
simonis@6465 413 // We don't really need a stub here! Just set the pending exeption and
simonis@6465 414 // continue at the next instruction after the faulting read. Returning
simonis@6465 415 // garbage from this read is ok.
simonis@6465 416 thread->set_pending_unsafe_access_error();
simonis@6465 417 uc->uc_mcontext.jmp_context.iar = ((unsigned long)pc) + 4;
simonis@6465 418 return 1;
simonis@6465 419 }
simonis@6465 420 }
simonis@6465 421
simonis@6465 422 // Check to see if we caught the safepoint code in the
simonis@6465 423 // process of write protecting the memory serialization page.
simonis@6465 424 // It write enables the page immediately after protecting it
simonis@6465 425 // so we can just return to retry the write.
simonis@6465 426 if ((sig == SIGSEGV) &&
simonis@6465 427 os::is_memory_serialize_page(thread, addr)) {
simonis@6465 428 // Synchronization problem in the pseudo memory barrier code (bug id 6546278)
simonis@6465 429 // Block current thread until the memory serialize page permission restored.
simonis@6465 430 os::block_on_serialize_page_trap();
simonis@6465 431 return true;
simonis@6465 432 }
simonis@6465 433 }
simonis@6465 434
simonis@6465 435 run_stub:
simonis@6465 436
simonis@6465 437 // One of the above code blocks ininitalized the stub, so we want to
simonis@6465 438 // delegate control to that stub.
simonis@6465 439 if (stub != NULL) {
simonis@6465 440 // Save all thread context in case we need to restore it.
simonis@6465 441 if (thread != NULL) thread->set_saved_exception_pc(pc);
simonis@6465 442 uc->uc_mcontext.jmp_context.iar = (unsigned long)stub;
simonis@6465 443 return 1;
simonis@6465 444 }
simonis@6465 445
simonis@6465 446 run_chained_handler:
simonis@6465 447
simonis@6465 448 // signal-chaining
simonis@6465 449 if (os::Aix::chained_handler(sig, info, ucVoid)) {
simonis@6465 450 return 1;
simonis@6465 451 }
simonis@6465 452 if (!abort_if_unrecognized) {
simonis@6465 453 // caller wants another chance, so give it to him
simonis@6465 454 return 0;
simonis@6465 455 }
simonis@6465 456
simonis@6465 457 report_and_die:
simonis@6465 458
simonis@6465 459 // Use sigthreadmask instead of sigprocmask on AIX and unmask current signal.
simonis@6465 460 sigset_t newset;
simonis@6465 461 sigemptyset(&newset);
simonis@6465 462 sigaddset(&newset, sig);
simonis@6465 463 sigthreadmask(SIG_UNBLOCK, &newset, NULL);
simonis@6465 464
simonis@6465 465 VMError err(t, sig, pc, info, ucVoid);
simonis@6465 466 err.report_and_die();
simonis@6465 467
simonis@6465 468 ShouldNotReachHere();
simonis@6465 469 return 0;
simonis@6465 470 }
simonis@6465 471
simonis@6465 472 void os::Aix::init_thread_fpu_state(void) {
simonis@6465 473 #if !defined(USE_XLC_BUILTINS)
simonis@6465 474 // Disable FP exceptions.
simonis@6465 475 __asm__ __volatile__ ("mtfsfi 6,0");
simonis@6465 476 #else
simonis@6465 477 __mtfsfi(6, 0);
simonis@6465 478 #endif
simonis@6465 479 }
simonis@6465 480
simonis@6465 481 ////////////////////////////////////////////////////////////////////////////////
simonis@6465 482 // thread stack
simonis@6465 483
simonis@6465 484 size_t os::Aix::min_stack_allowed = 768*K;
simonis@6465 485
simonis@6465 486 // Aix is always in floating stack mode. The stack size for a new
simonis@6465 487 // thread can be set via pthread_attr_setstacksize().
simonis@6465 488 bool os::Aix::supports_variable_stack_size() { return true; }
simonis@6465 489
simonis@6465 490 // return default stack size for thr_type
simonis@6465 491 size_t os::Aix::default_stack_size(os::ThreadType thr_type) {
simonis@6465 492 // default stack size (compiler thread needs larger stack)
simonis@6465 493 // Notice that the setting for compiler threads here have no impact
simonis@6465 494 // because of the strange 'fallback logic' in os::create_thread().
simonis@6465 495 // Better set CompilerThreadStackSize in globals_<os_cpu>.hpp if you want to
simonis@6465 496 // specify a different stack size for compiler threads!
simonis@6465 497 size_t s = (thr_type == os::compiler_thread ? 4 * M : 1024 * K);
simonis@6465 498 return s;
simonis@6465 499 }
simonis@6465 500
simonis@6465 501 size_t os::Aix::default_guard_size(os::ThreadType thr_type) {
simonis@6465 502 return 2 * page_size();
simonis@6465 503 }
simonis@6465 504
simonis@6465 505 /////////////////////////////////////////////////////////////////////////////
simonis@6465 506 // helper functions for fatal error handler
simonis@6465 507
simonis@6465 508 void os::print_context(outputStream *st, void *context) {
simonis@6465 509 if (context == NULL) return;
simonis@6465 510
simonis@6465 511 ucontext_t* uc = (ucontext_t*)context;
simonis@6465 512
simonis@6465 513 st->print_cr("Registers:");
simonis@6465 514 st->print("pc =" INTPTR_FORMAT " ", uc->uc_mcontext.jmp_context.iar);
simonis@6465 515 st->print("lr =" INTPTR_FORMAT " ", uc->uc_mcontext.jmp_context.lr);
simonis@6465 516 st->print("ctr=" INTPTR_FORMAT " ", uc->uc_mcontext.jmp_context.ctr);
simonis@6465 517 st->cr();
simonis@6465 518 for (int i = 0; i < 32; i++) {
simonis@6465 519 st->print("r%-2d=" INTPTR_FORMAT " ", i, uc->uc_mcontext.jmp_context.gpr[i]);
simonis@6465 520 if (i % 3 == 2) st->cr();
simonis@6465 521 }
simonis@6465 522 st->cr();
simonis@6465 523 st->cr();
simonis@6465 524
simonis@6465 525 intptr_t *sp = (intptr_t *)os::Aix::ucontext_get_sp(uc);
simonis@6465 526 st->print_cr("Top of Stack: (sp=" PTR_FORMAT ")", sp);
simonis@6465 527 print_hex_dump(st, (address)sp, (address)(sp + 128), sizeof(intptr_t));
simonis@6465 528 st->cr();
simonis@6465 529
simonis@6465 530 // Note: it may be unsafe to inspect memory near pc. For example, pc may
simonis@6465 531 // point to garbage if entry point in an nmethod is corrupted. Leave
simonis@6465 532 // this at the end, and hope for the best.
simonis@6465 533 address pc = os::Aix::ucontext_get_pc(uc);
simonis@6465 534 st->print_cr("Instructions: (pc=" PTR_FORMAT ")", pc);
simonis@6465 535 print_hex_dump(st, pc - 64, pc + 64, /*instrsize=*/4);
simonis@6465 536 st->cr();
simonis@6465 537
simonis@6465 538 // Try to decode the instructions.
simonis@6465 539 st->print_cr("Decoded instructions: (pc=" PTR_FORMAT ")", pc);
simonis@6465 540 st->print("<TODO: PPC port - print_context>");
simonis@6465 541 // TODO: PPC port Disassembler::decode(pc, 16, 16, st);
simonis@6465 542 st->cr();
simonis@6465 543 }
simonis@6465 544
simonis@6465 545 void os::print_register_info(outputStream *st, void *context) {
simonis@6465 546 if (context == NULL) return;
simonis@6465 547 st->print("Not ported - print_register_info\n");
simonis@6465 548 }
simonis@6465 549
simonis@6465 550 extern "C" {
simonis@6465 551 int SpinPause() {
simonis@6465 552 return 0;
simonis@6465 553 }
simonis@6465 554 }
simonis@6465 555
simonis@6465 556 #ifndef PRODUCT
simonis@6465 557 void os::verify_stack_alignment() {
simonis@6465 558 assert(((intptr_t)os::current_stack_pointer() & (StackAlignmentInBytes-1)) == 0, "incorrect stack alignment");
simonis@6465 559 }
simonis@6465 560 #endif

mercurial