< prev index next >

src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp

Print this page
rev 7968 : 8074552:  SafeFetch32 and SafeFetchN do not work in error handling
Summary: handle SafeFetch faults in secondary signal handlers
Reviewed-by: dholmes
Contributed-by: Thomas Stuefe


  96 void os::initialize_thread(Thread *thread) { }
  97 
  98 // Frame information (pc, sp, fp) retrieved via ucontext
  99 // always looks like a C-frame according to the frame
 100 // conventions in frame_ppc64.hpp.
 101 address os::Linux::ucontext_get_pc(ucontext_t * uc) {
 102   // On powerpc64, ucontext_t is not selfcontained but contains
 103   // a pointer to an optional substructure (mcontext_t.regs) containing the volatile
 104   // registers - NIP, among others.
 105   // This substructure may or may not be there depending where uc came from:
 106   // - if uc was handed over as the argument to a sigaction handler, a pointer to the
 107   //   substructure was provided by the kernel when calling the signal handler, and
 108   //   regs->nip can be accessed.
 109   // - if uc was filled by getcontext(), it is undefined - getcontext() does not fill
 110   //   it because the volatile registers are not needed to make setcontext() work.
 111   //   Hopefully it was zero'd out beforehand.
 112   guarantee(uc->uc_mcontext.regs != NULL, "only use ucontext_get_pc in sigaction context");
 113   return (address)uc->uc_mcontext.regs->nip;
 114 }
 115 








 116 intptr_t* os::Linux::ucontext_get_sp(ucontext_t * uc) {
 117   return (intptr_t*)uc->uc_mcontext.regs->gpr[1/*REG_SP*/];
 118 }
 119 
 120 intptr_t* os::Linux::ucontext_get_fp(ucontext_t * uc) {
 121   return NULL;
 122 }
 123 
 124 ExtendedPC os::fetch_frame_from_context(void* ucVoid,
 125                     intptr_t** ret_sp, intptr_t** ret_fp) {
 126 
 127   ExtendedPC  epc;
 128   ucontext_t* uc = (ucontext_t*)ucVoid;
 129 
 130   if (uc != NULL) {
 131     epc = ExtendedPC(os::Linux::ucontext_get_pc(uc));
 132     if (ret_sp) *ret_sp = os::Linux::ucontext_get_sp(uc);
 133     if (ret_fp) *ret_fp = os::Linux::ucontext_get_fp(uc);
 134   } else {
 135     // construct empty ExtendedPC for return value checking


 196     }
 197   }
 198 
 199   JavaThread* thread = NULL;
 200   VMThread* vmthread = NULL;
 201   if (os::Linux::signal_handlers_are_installed) {
 202     if (t != NULL) {
 203       if(t->is_Java_thread()) {
 204         thread = (JavaThread*)t;
 205       } else if(t->is_VM_thread()) {
 206         vmthread = (VMThread *)t;
 207       }
 208     }
 209   }
 210 
 211   // Moved SafeFetch32 handling outside thread!=NULL conditional block to make
 212   // it work if no associated JavaThread object exists.
 213   if (uc) {
 214     address const pc = os::Linux::ucontext_get_pc(uc);
 215     if (pc && StubRoutines::is_safefetch_fault(pc)) {
 216       uc->uc_mcontext.regs->nip = (unsigned long)StubRoutines::continuation_for_safefetch_fault(pc);
 217       return true;
 218     }
 219   }
 220 
 221   // decide if this trap can be handled by a stub
 222   address stub = NULL;
 223   address pc   = NULL;
 224 
 225   //%note os_trap_1
 226   if (info != NULL && uc != NULL && thread != NULL) {
 227     pc = (address) os::Linux::ucontext_get_pc(uc);
 228 
 229     // Handle ALL stack overflow variations here
 230     if (sig == SIGSEGV) {
 231       // Si_addr may not be valid due to a bug in the linux-ppc64 kernel (see
 232       // comment below). Use get_stack_bang_address instead of si_addr.
 233       address addr = ((NativeInstruction*)pc)->get_stack_bang_address(uc);
 234 
 235       // Check if fault address is within thread stack.
 236       if (addr < thread->stack_base() &&


 343 #ifdef COMPILER2
 344       // SIGTRAP-based implicit range check in compiled code.
 345       else if (sig == SIGTRAP && TrapBasedRangeChecks &&
 346                nativeInstruction_at(pc)->is_sigtrap_range_check()) {
 347         if (TraceTraps) {
 348           tty->print_cr("trap: range_check at " INTPTR_FORMAT " (SIGTRAP)", p2i(pc));
 349         }
 350         stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL);
 351       }
 352 #endif
 353       else if (sig == SIGBUS) {
 354         // BugId 4454115: A read from a MappedByteBuffer can fault here if the
 355         // underlying file has been truncated. Do not crash the VM in such a case.
 356         CodeBlob* cb = CodeCache::find_blob_unsafe(pc);
 357         nmethod* nm = (cb != NULL && cb->is_nmethod()) ? (nmethod*)cb : NULL;
 358         if (nm != NULL && nm->has_unsafe_access()) {
 359           // We don't really need a stub here! Just set the pending exeption and
 360           // continue at the next instruction after the faulting read. Returning
 361           // garbage from this read is ok.
 362           thread->set_pending_unsafe_access_error();
 363           uc->uc_mcontext.regs->nip = ((unsigned long)pc) + 4;
 364           return true;
 365         }
 366       }
 367     }
 368 
 369     else { // thread->thread_state() != _thread_in_Java
 370       if (sig == SIGILL && VM_Version::is_determine_features_test_running()) {
 371         // SIGILL must be caused by VM_Version::determine_features().
 372         *(int *)pc = 0; // patch instruction to 0 to indicate that it causes a SIGILL,
 373                         // flushing of icache is not necessary.
 374         stub = pc + 4;  // continue with next instruction.
 375       }
 376       else if (thread->thread_state() == _thread_in_vm &&
 377                sig == SIGBUS && thread->doing_unsafe_access()) {
 378         // We don't really need a stub here! Just set the pending exeption and
 379         // continue at the next instruction after the faulting read. Returning
 380         // garbage from this read is ok.
 381         thread->set_pending_unsafe_access_error();
 382         uc->uc_mcontext.regs->nip = ((unsigned long)pc) + 4;
 383         return true;
 384       }
 385     }
 386 
 387     // Check to see if we caught the safepoint code in the
 388     // process of write protecting the memory serialization page.
 389     // It write enables the page immediately after protecting it
 390     // so we can just return to retry the write.
 391     if ((sig == SIGSEGV) &&
 392         // Si_addr may not be valid due to a bug in the linux-ppc64 kernel (see comment above).
 393         // Use is_memory_serialization instead of si_addr.
 394         ((NativeInstruction*)pc)->is_memory_serialization(thread, ucVoid)) {
 395       // Synchronization problem in the pseudo memory barrier code (bug id 6546278)
 396       // Block current thread until the memory serialize page permission restored.
 397       os::block_on_serialize_page_trap();
 398       return true;
 399     }
 400   }
 401 
 402   if (stub != NULL) {
 403     // Save all thread context in case we need to restore it.
 404     if (thread != NULL) thread->set_saved_exception_pc(pc);
 405     uc->uc_mcontext.regs->nip = (unsigned long)stub;
 406     return true;
 407   }
 408 
 409   // signal-chaining
 410   if (os::Linux::chained_handler(sig, info, ucVoid)) {
 411     return true;
 412   }
 413 
 414   if (!abort_if_unrecognized) {
 415     // caller wants another chance, so give it to him
 416     return false;
 417   }
 418 
 419   if (pc == NULL && uc != NULL) {
 420     pc = os::Linux::ucontext_get_pc(uc);
 421   }
 422 
 423 report_and_die:
 424   // unmask current signal
 425   sigset_t newset;




  96 void os::initialize_thread(Thread *thread) { }
  97 
  98 // Frame information (pc, sp, fp) retrieved via ucontext
  99 // always looks like a C-frame according to the frame
 100 // conventions in frame_ppc64.hpp.
 101 address os::Linux::ucontext_get_pc(ucontext_t * uc) {
 102   // On powerpc64, ucontext_t is not selfcontained but contains
 103   // a pointer to an optional substructure (mcontext_t.regs) containing the volatile
 104   // registers - NIP, among others.
 105   // This substructure may or may not be there depending where uc came from:
 106   // - if uc was handed over as the argument to a sigaction handler, a pointer to the
 107   //   substructure was provided by the kernel when calling the signal handler, and
 108   //   regs->nip can be accessed.
 109   // - if uc was filled by getcontext(), it is undefined - getcontext() does not fill
 110   //   it because the volatile registers are not needed to make setcontext() work.
 111   //   Hopefully it was zero'd out beforehand.
 112   guarantee(uc->uc_mcontext.regs != NULL, "only use ucontext_get_pc in sigaction context");
 113   return (address)uc->uc_mcontext.regs->nip;
 114 }
 115 
 116 // modify PC in ucontext.
 117 // Note: Only use this for an ucontext handed down to a signal handler. See comment
 118 // in ucontext_get_pc.
 119 void os::Linux::ucontext_set_pc(ucontext_t * uc, address pc) {
 120   guarantee(uc->uc_mcontext.regs != NULL, "only use ucontext_set_pc in sigaction context");
 121   uc->uc_mcontext.regs->nip = (unsigned long)pc;
 122 }
 123 
 124 intptr_t* os::Linux::ucontext_get_sp(ucontext_t * uc) {
 125   return (intptr_t*)uc->uc_mcontext.regs->gpr[1/*REG_SP*/];
 126 }
 127 
 128 intptr_t* os::Linux::ucontext_get_fp(ucontext_t * uc) {
 129   return NULL;
 130 }
 131 
 132 ExtendedPC os::fetch_frame_from_context(void* ucVoid,
 133                     intptr_t** ret_sp, intptr_t** ret_fp) {
 134 
 135   ExtendedPC  epc;
 136   ucontext_t* uc = (ucontext_t*)ucVoid;
 137 
 138   if (uc != NULL) {
 139     epc = ExtendedPC(os::Linux::ucontext_get_pc(uc));
 140     if (ret_sp) *ret_sp = os::Linux::ucontext_get_sp(uc);
 141     if (ret_fp) *ret_fp = os::Linux::ucontext_get_fp(uc);
 142   } else {
 143     // construct empty ExtendedPC for return value checking


 204     }
 205   }
 206 
 207   JavaThread* thread = NULL;
 208   VMThread* vmthread = NULL;
 209   if (os::Linux::signal_handlers_are_installed) {
 210     if (t != NULL) {
 211       if(t->is_Java_thread()) {
 212         thread = (JavaThread*)t;
 213       } else if(t->is_VM_thread()) {
 214         vmthread = (VMThread *)t;
 215       }
 216     }
 217   }
 218 
 219   // Moved SafeFetch32 handling outside thread!=NULL conditional block to make
 220   // it work if no associated JavaThread object exists.
 221   if (uc) {
 222     address const pc = os::Linux::ucontext_get_pc(uc);
 223     if (pc && StubRoutines::is_safefetch_fault(pc)) {
 224       os::Linux::ucontext_set_pc(uc, StubRoutines::continuation_for_safefetch_fault(pc));
 225       return true;
 226     }
 227   }
 228 
 229   // decide if this trap can be handled by a stub
 230   address stub = NULL;
 231   address pc   = NULL;
 232 
 233   //%note os_trap_1
 234   if (info != NULL && uc != NULL && thread != NULL) {
 235     pc = (address) os::Linux::ucontext_get_pc(uc);
 236 
 237     // Handle ALL stack overflow variations here
 238     if (sig == SIGSEGV) {
 239       // Si_addr may not be valid due to a bug in the linux-ppc64 kernel (see
 240       // comment below). Use get_stack_bang_address instead of si_addr.
 241       address addr = ((NativeInstruction*)pc)->get_stack_bang_address(uc);
 242 
 243       // Check if fault address is within thread stack.
 244       if (addr < thread->stack_base() &&


 351 #ifdef COMPILER2
 352       // SIGTRAP-based implicit range check in compiled code.
 353       else if (sig == SIGTRAP && TrapBasedRangeChecks &&
 354                nativeInstruction_at(pc)->is_sigtrap_range_check()) {
 355         if (TraceTraps) {
 356           tty->print_cr("trap: range_check at " INTPTR_FORMAT " (SIGTRAP)", p2i(pc));
 357         }
 358         stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL);
 359       }
 360 #endif
 361       else if (sig == SIGBUS) {
 362         // BugId 4454115: A read from a MappedByteBuffer can fault here if the
 363         // underlying file has been truncated. Do not crash the VM in such a case.
 364         CodeBlob* cb = CodeCache::find_blob_unsafe(pc);
 365         nmethod* nm = (cb != NULL && cb->is_nmethod()) ? (nmethod*)cb : NULL;
 366         if (nm != NULL && nm->has_unsafe_access()) {
 367           // We don't really need a stub here! Just set the pending exeption and
 368           // continue at the next instruction after the faulting read. Returning
 369           // garbage from this read is ok.
 370           thread->set_pending_unsafe_access_error();
 371           os::Linux::ucontext_set_pc(uc, pc + 4);
 372           return true;
 373         }
 374       }
 375     }
 376 
 377     else { // thread->thread_state() != _thread_in_Java
 378       if (sig == SIGILL && VM_Version::is_determine_features_test_running()) {
 379         // SIGILL must be caused by VM_Version::determine_features().
 380         *(int *)pc = 0; // patch instruction to 0 to indicate that it causes a SIGILL,
 381                         // flushing of icache is not necessary.
 382         stub = pc + 4;  // continue with next instruction.
 383       }
 384       else if (thread->thread_state() == _thread_in_vm &&
 385                sig == SIGBUS && thread->doing_unsafe_access()) {
 386         // We don't really need a stub here! Just set the pending exeption and
 387         // continue at the next instruction after the faulting read. Returning
 388         // garbage from this read is ok.
 389         thread->set_pending_unsafe_access_error();
 390         os::Linux::ucontext_set_pc(uc, pc + 4);
 391         return true;
 392       }
 393     }
 394 
 395     // Check to see if we caught the safepoint code in the
 396     // process of write protecting the memory serialization page.
 397     // It write enables the page immediately after protecting it
 398     // so we can just return to retry the write.
 399     if ((sig == SIGSEGV) &&
 400         // Si_addr may not be valid due to a bug in the linux-ppc64 kernel (see comment above).
 401         // Use is_memory_serialization instead of si_addr.
 402         ((NativeInstruction*)pc)->is_memory_serialization(thread, ucVoid)) {
 403       // Synchronization problem in the pseudo memory barrier code (bug id 6546278)
 404       // Block current thread until the memory serialize page permission restored.
 405       os::block_on_serialize_page_trap();
 406       return true;
 407     }
 408   }
 409 
 410   if (stub != NULL) {
 411     // Save all thread context in case we need to restore it.
 412     if (thread != NULL) thread->set_saved_exception_pc(pc);
 413     os::Linux::ucontext_set_pc(uc, stub);
 414     return true;
 415   }
 416 
 417   // signal-chaining
 418   if (os::Linux::chained_handler(sig, info, ucVoid)) {
 419     return true;
 420   }
 421 
 422   if (!abort_if_unrecognized) {
 423     // caller wants another chance, so give it to him
 424     return false;
 425   }
 426 
 427   if (pc == NULL && uc != NULL) {
 428     pc = os::Linux::ucontext_get_pc(uc);
 429   }
 430 
 431 report_and_die:
 432   // unmask current signal
 433   sigset_t newset;


< prev index next >