aoqi@0: /* dbuck@9289: * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. aoqi@0: * Copyright 2007, 2008, 2009, 2010 Red Hat, Inc. aoqi@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. aoqi@0: * aoqi@0: * This code is free software; you can redistribute it and/or modify it aoqi@0: * under the terms of the GNU General Public License version 2 only, as aoqi@0: * published by the Free Software Foundation. aoqi@0: * aoqi@0: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@0: * version 2 for more details (a copy is included in the LICENSE file that aoqi@0: * accompanied this code). aoqi@0: * aoqi@0: * You should have received a copy of the GNU General Public License version aoqi@0: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. aoqi@0: * aoqi@0: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@0: * or visit www.oracle.com if you need additional information or have any aoqi@0: * questions. aoqi@0: * aoqi@0: */ aoqi@0: aoqi@0: // no precompiled headers aoqi@0: #include "assembler_zero.inline.hpp" aoqi@0: #include "classfile/classLoader.hpp" aoqi@0: #include "classfile/systemDictionary.hpp" aoqi@0: #include "classfile/vmSymbols.hpp" aoqi@0: #include "code/icBuffer.hpp" aoqi@0: #include "code/vtableStubs.hpp" aoqi@0: #include "interpreter/interpreter.hpp" aoqi@0: #include "jvm_linux.h" aoqi@0: #include "memory/allocation.inline.hpp" aoqi@0: #include "mutex_linux.inline.hpp" aoqi@0: #include "nativeInst_zero.hpp" aoqi@0: #include "os_share_linux.hpp" aoqi@0: #include "prims/jniFastGetField.hpp" aoqi@0: #include "prims/jvm.h" aoqi@0: #include "prims/jvm_misc.hpp" aoqi@0: #include "runtime/arguments.hpp" aoqi@0: #include "runtime/extendedPC.hpp" aoqi@0: #include "runtime/frame.inline.hpp" aoqi@0: #include "runtime/interfaceSupport.hpp" aoqi@0: #include "runtime/java.hpp" aoqi@0: #include "runtime/javaCalls.hpp" aoqi@0: #include "runtime/mutexLocker.hpp" aoqi@0: #include "runtime/osThread.hpp" aoqi@0: #include "runtime/sharedRuntime.hpp" aoqi@0: #include "runtime/stubRoutines.hpp" aoqi@0: #include "runtime/thread.inline.hpp" aoqi@0: #include "runtime/timer.hpp" aoqi@0: #include "utilities/events.hpp" aoqi@0: #include "utilities/vmError.hpp" aoqi@0: aoqi@0: address os::current_stack_pointer() { sgehwolf@8178: // return the address of the current function sgehwolf@8178: return (address)__builtin_frame_address(0); aoqi@0: } aoqi@0: aoqi@0: frame os::get_sender_for_C_frame(frame* fr) { aoqi@0: ShouldNotCallThis(); aoqi@0: } aoqi@0: aoqi@0: frame os::current_frame() { aoqi@0: // The only thing that calls this is the stack printing code in aoqi@0: // VMError::report: aoqi@0: // - Step 110 (printing stack bounds) uses the sp in the frame aoqi@0: // to determine the amount of free space on the stack. We aoqi@0: // set the sp to a close approximation of the real value in aoqi@0: // order to allow this step to complete. aoqi@0: // - Step 120 (printing native stack) tries to walk the stack. aoqi@0: // The frame we create has a NULL pc, which is ignored as an aoqi@0: // invalid frame. aoqi@0: frame dummy = frame(); aoqi@0: dummy.set_sp((intptr_t *) current_stack_pointer()); aoqi@0: return dummy; aoqi@0: } aoqi@0: aoqi@0: char* os::non_memory_address_word() { aoqi@0: // Must never look like an address returned by reserve_memory, aoqi@0: // even in its subfields (as defined by the CPU immediate fields, aoqi@0: // if the CPU splits constants across multiple instructions). aoqi@0: #ifdef SPARC aoqi@0: // On SPARC, 0 != %hi(any real address), because there is no aoqi@0: // allocation in the first 1Kb of the virtual address space. aoqi@0: return (char *) 0; aoqi@0: #else aoqi@0: // This is the value for x86; works pretty well for PPC too. aoqi@0: return (char *) -1; aoqi@0: #endif // SPARC aoqi@0: } aoqi@0: aoqi@0: void os::initialize_thread(Thread * thr){ aoqi@0: // Nothing to do. aoqi@0: } aoqi@0: aoqi@0: address os::Linux::ucontext_get_pc(ucontext_t* uc) { aoqi@0: ShouldNotCallThis(); aoqi@0: } aoqi@0: aoqi@0: ExtendedPC os::fetch_frame_from_context(void* ucVoid, aoqi@0: intptr_t** ret_sp, aoqi@0: intptr_t** ret_fp) { aoqi@0: ShouldNotCallThis(); aoqi@0: } aoqi@0: aoqi@0: frame os::fetch_frame_from_context(void* ucVoid) { aoqi@0: ShouldNotCallThis(); aoqi@0: } aoqi@0: aoqi@0: extern "C" JNIEXPORT int aoqi@0: JVM_handle_linux_signal(int sig, aoqi@0: siginfo_t* info, aoqi@0: void* ucVoid, aoqi@0: int abort_if_unrecognized) { aoqi@0: ucontext_t* uc = (ucontext_t*) ucVoid; aoqi@0: aoqi@0: Thread* t = ThreadLocalStorage::get_thread_slow(); aoqi@0: aoqi@0: SignalHandlerMark shm(t); aoqi@0: aoqi@0: // Note: it's not uncommon that JNI code uses signal/sigset to aoqi@0: // install then restore certain signal handler (e.g. to temporarily aoqi@0: // block SIGPIPE, or have a SIGILL handler when detecting CPU aoqi@0: // type). When that happens, JVM_handle_linux_signal() might be aoqi@0: // invoked with junk info/ucVoid. To avoid unnecessary crash when aoqi@0: // libjsig is not preloaded, try handle signals that do not require aoqi@0: // siginfo/ucontext first. aoqi@0: aoqi@0: if (sig == SIGPIPE || sig == SIGXFSZ) { aoqi@0: // allow chained handler to go first aoqi@0: if (os::Linux::chained_handler(sig, info, ucVoid)) { aoqi@0: return true; aoqi@0: } else { aoqi@0: if (PrintMiscellaneous && (WizardMode || Verbose)) { aoqi@0: char buf[64]; aoqi@0: warning("Ignoring %s - see bugs 4229104 or 646499219", aoqi@0: os::exception_name(sig, buf, sizeof(buf))); aoqi@0: } aoqi@0: return true; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: JavaThread* thread = NULL; aoqi@0: VMThread* vmthread = NULL; aoqi@0: if (os::Linux::signal_handlers_are_installed) { aoqi@0: if (t != NULL ){ aoqi@0: if(t->is_Java_thread()) { aoqi@0: thread = (JavaThread*)t; aoqi@0: } aoqi@0: else if(t->is_VM_thread()){ aoqi@0: vmthread = (VMThread *)t; aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: if (info != NULL && thread != NULL) { aoqi@0: // Handle ALL stack overflow variations here aoqi@0: if (sig == SIGSEGV) { aoqi@0: address addr = (address) info->si_addr; aoqi@0: aoqi@0: // check if fault address is within thread stack aoqi@0: if (addr < thread->stack_base() && aoqi@0: addr >= thread->stack_base() - thread->stack_size()) { aoqi@0: // stack overflow aoqi@0: if (thread->in_stack_yellow_zone(addr)) { aoqi@0: thread->disable_stack_yellow_zone(); aoqi@0: ShouldNotCallThis(); aoqi@0: } aoqi@0: else if (thread->in_stack_red_zone(addr)) { aoqi@0: thread->disable_stack_red_zone(); aoqi@0: ShouldNotCallThis(); aoqi@0: } aoqi@0: else { aoqi@0: // Accessing stack address below sp may cause SEGV if aoqi@0: // current thread has MAP_GROWSDOWN stack. This should aoqi@0: // only happen when current thread was created by user aoqi@0: // code with MAP_GROWSDOWN flag and then attached to VM. aoqi@0: // See notes in os_linux.cpp. aoqi@0: if (thread->osthread()->expanding_stack() == 0) { aoqi@0: thread->osthread()->set_expanding_stack(); aoqi@0: if (os::Linux::manually_expand_stack(thread, addr)) { aoqi@0: thread->osthread()->clear_expanding_stack(); aoqi@0: return true; aoqi@0: } aoqi@0: thread->osthread()->clear_expanding_stack(); aoqi@0: } aoqi@0: else { aoqi@0: fatal("recursive segv. expanding stack."); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: /*if (thread->thread_state() == _thread_in_Java) { aoqi@0: ShouldNotCallThis(); aoqi@0: } aoqi@0: else*/ if (thread->thread_state() == _thread_in_vm && aoqi@0: sig == SIGBUS && thread->doing_unsafe_access()) { aoqi@0: ShouldNotCallThis(); aoqi@0: } aoqi@0: aoqi@0: // jni_fast_GetField can trap at certain pc's if a GC aoqi@0: // kicks in and the heap gets shrunk before the field access. aoqi@0: /*if (sig == SIGSEGV || sig == SIGBUS) { aoqi@0: address addr = JNI_FastGetField::find_slowcase_pc(pc); aoqi@0: if (addr != (address)-1) { aoqi@0: stub = addr; aoqi@0: } aoqi@0: }*/ aoqi@0: aoqi@0: // Check to see if we caught the safepoint code in the process aoqi@0: // of write protecting the memory serialization page. It write aoqi@0: // enables the page immediately after protecting it so we can aoqi@0: // just return to retry the write. aoqi@0: if (sig == SIGSEGV && aoqi@0: os::is_memory_serialize_page(thread, (address) info->si_addr)) { aoqi@0: // Block current thread until permission is restored. aoqi@0: os::block_on_serialize_page_trap(); aoqi@0: return true; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: // signal-chaining aoqi@0: if (os::Linux::chained_handler(sig, info, ucVoid)) { aoqi@0: return true; aoqi@0: } aoqi@0: aoqi@0: if (!abort_if_unrecognized) { aoqi@0: // caller wants another chance, so give it to him aoqi@0: return false; aoqi@0: } aoqi@0: aoqi@0: #ifndef PRODUCT aoqi@0: if (sig == SIGSEGV) { aoqi@0: fatal("\n#" aoqi@0: "\n# /--------------------\\" aoqi@0: "\n# | segmentation fault |" aoqi@0: "\n# \\---\\ /--------------/" aoqi@0: "\n# /" aoqi@0: "\n# [-] |\\_/| " aoqi@0: "\n# (+)=C |o o|__ " aoqi@0: "\n# | | =-*-=__\\ " aoqi@0: "\n# OOO c_c_(___)"); aoqi@0: } aoqi@0: #endif // !PRODUCT aoqi@0: aoqi@0: const char *fmt = "caught unhandled signal %d"; aoqi@0: char buf[64]; aoqi@0: aoqi@0: sprintf(buf, fmt, sig); aoqi@0: fatal(buf); aoqi@0: } aoqi@0: aoqi@0: void os::Linux::init_thread_fpu_state(void) { aoqi@0: // Nothing to do aoqi@0: } aoqi@0: aoqi@0: int os::Linux::get_fpu_control_word() { aoqi@0: ShouldNotCallThis(); aoqi@0: } aoqi@0: aoqi@0: void os::Linux::set_fpu_control_word(int fpu) { aoqi@0: ShouldNotCallThis(); aoqi@0: } aoqi@0: aoqi@0: bool os::is_allocatable(size_t bytes) { aoqi@0: #ifdef _LP64 aoqi@0: return true; aoqi@0: #else aoqi@0: if (bytes < 2 * G) { aoqi@0: return true; aoqi@0: } aoqi@0: aoqi@0: char* addr = reserve_memory(bytes, NULL); aoqi@0: aoqi@0: if (addr != NULL) { aoqi@0: release_memory(addr, bytes); aoqi@0: } aoqi@0: aoqi@0: return addr != NULL; aoqi@0: #endif // _LP64 aoqi@0: } aoqi@0: aoqi@0: /////////////////////////////////////////////////////////////////////////////// aoqi@0: // thread stack aoqi@0: aoqi@0: size_t os::Linux::min_stack_allowed = 64 * K; aoqi@0: aoqi@0: bool os::Linux::supports_variable_stack_size() { aoqi@0: return true; aoqi@0: } aoqi@0: aoqi@0: size_t os::Linux::default_stack_size(os::ThreadType thr_type) { aoqi@0: #ifdef _LP64 aoqi@0: size_t s = (thr_type == os::compiler_thread ? 4 * M : 1 * M); aoqi@0: #else aoqi@0: size_t s = (thr_type == os::compiler_thread ? 2 * M : 512 * K); aoqi@0: #endif // _LP64 aoqi@0: return s; aoqi@0: } aoqi@0: aoqi@0: size_t os::Linux::default_guard_size(os::ThreadType thr_type) { aoqi@0: // Only enable glibc guard pages for non-Java threads aoqi@0: // (Java threads have HotSpot guard pages) aoqi@0: return (thr_type == java_thread ? 0 : page_size()); aoqi@0: } aoqi@0: aoqi@0: static void current_stack_region(address *bottom, size_t *size) { aoqi@0: pthread_attr_t attr; aoqi@0: int res = pthread_getattr_np(pthread_self(), &attr); aoqi@0: if (res != 0) { aoqi@0: if (res == ENOMEM) { aoqi@0: vm_exit_out_of_memory(0, OOM_MMAP_ERROR, "pthread_getattr_np"); aoqi@0: } aoqi@0: else { aoqi@0: fatal(err_msg("pthread_getattr_np failed with errno = %d", res)); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: address stack_bottom; aoqi@0: size_t stack_bytes; aoqi@0: res = pthread_attr_getstack(&attr, (void **) &stack_bottom, &stack_bytes); aoqi@0: if (res != 0) { aoqi@0: fatal(err_msg("pthread_attr_getstack failed with errno = %d", res)); aoqi@0: } aoqi@0: address stack_top = stack_bottom + stack_bytes; aoqi@0: aoqi@0: // The block of memory returned by pthread_attr_getstack() includes aoqi@0: // guard pages where present. We need to trim these off. aoqi@0: size_t page_bytes = os::Linux::page_size(); aoqi@0: assert(((intptr_t) stack_bottom & (page_bytes - 1)) == 0, "unaligned stack"); aoqi@0: aoqi@0: size_t guard_bytes; aoqi@0: res = pthread_attr_getguardsize(&attr, &guard_bytes); aoqi@0: if (res != 0) { aoqi@0: fatal(err_msg("pthread_attr_getguardsize failed with errno = %d", res)); aoqi@0: } aoqi@0: int guard_pages = align_size_up(guard_bytes, page_bytes) / page_bytes; aoqi@0: assert(guard_bytes == guard_pages * page_bytes, "unaligned guard"); aoqi@0: aoqi@0: #ifdef IA64 aoqi@0: // IA64 has two stacks sharing the same area of memory, a normal aoqi@0: // stack growing downwards and a register stack growing upwards. aoqi@0: // Guard pages, if present, are in the centre. This code splits aoqi@0: // the stack in two even without guard pages, though in theory aoqi@0: // there's nothing to stop us allocating more to the normal stack aoqi@0: // or more to the register stack if one or the other were found aoqi@0: // to grow faster. aoqi@0: int total_pages = align_size_down(stack_bytes, page_bytes) / page_bytes; aoqi@0: stack_bottom += (total_pages - guard_pages) / 2 * page_bytes; aoqi@0: #endif // IA64 aoqi@0: aoqi@0: stack_bottom += guard_bytes; aoqi@0: aoqi@0: pthread_attr_destroy(&attr); aoqi@0: aoqi@0: // The initial thread has a growable stack, and the size reported aoqi@0: // by pthread_attr_getstack is the maximum size it could possibly aoqi@0: // be given what currently mapped. This can be huge, so we cap it. dbuck@9289: if (os::is_primordial_thread()) { aoqi@0: stack_bytes = stack_top - stack_bottom; aoqi@0: aoqi@0: if (stack_bytes > JavaThread::stack_size_at_create()) aoqi@0: stack_bytes = JavaThread::stack_size_at_create(); aoqi@0: aoqi@0: stack_bottom = stack_top - stack_bytes; aoqi@0: } aoqi@0: aoqi@0: assert(os::current_stack_pointer() >= stack_bottom, "should do"); aoqi@0: assert(os::current_stack_pointer() < stack_top, "should do"); aoqi@0: aoqi@0: *bottom = stack_bottom; aoqi@0: *size = stack_top - stack_bottom; aoqi@0: } aoqi@0: aoqi@0: address os::current_stack_base() { aoqi@0: address bottom; aoqi@0: size_t size; aoqi@0: current_stack_region(&bottom, &size); aoqi@0: return bottom + size; aoqi@0: } aoqi@0: aoqi@0: size_t os::current_stack_size() { aoqi@0: // stack size includes normal stack and HotSpot guard pages aoqi@0: address bottom; aoqi@0: size_t size; aoqi@0: current_stack_region(&bottom, &size); aoqi@0: return size; aoqi@0: } aoqi@0: aoqi@0: ///////////////////////////////////////////////////////////////////////////// aoqi@0: // helper functions for fatal error handler aoqi@0: aoqi@0: void os::print_context(outputStream* st, void* context) { aoqi@0: ShouldNotCallThis(); aoqi@0: } aoqi@0: aoqi@0: void os::print_register_info(outputStream *st, void *context) { aoqi@0: ShouldNotCallThis(); aoqi@0: } aoqi@0: aoqi@0: ///////////////////////////////////////////////////////////////////////////// aoqi@0: // Stubs for things that would be in linux_zero.s if it existed. aoqi@0: // You probably want to disassemble these monkeys to check they're ok. aoqi@0: aoqi@0: extern "C" { aoqi@0: int SpinPause() { sgehwolf@9317: return 0; // Shouldn't matter. aoqi@0: } aoqi@0: aoqi@0: aoqi@0: void _Copy_conjoint_jshorts_atomic(jshort* from, jshort* to, size_t count) { aoqi@0: if (from > to) { aoqi@0: jshort *end = from + count; aoqi@0: while (from < end) aoqi@0: *(to++) = *(from++); aoqi@0: } aoqi@0: else if (from < to) { aoqi@0: jshort *end = from; aoqi@0: from += count - 1; aoqi@0: to += count - 1; aoqi@0: while (from >= end) aoqi@0: *(to--) = *(from--); aoqi@0: } aoqi@0: } aoqi@0: void _Copy_conjoint_jints_atomic(jint* from, jint* to, size_t count) { aoqi@0: if (from > to) { aoqi@0: jint *end = from + count; aoqi@0: while (from < end) aoqi@0: *(to++) = *(from++); aoqi@0: } aoqi@0: else if (from < to) { aoqi@0: jint *end = from; aoqi@0: from += count - 1; aoqi@0: to += count - 1; aoqi@0: while (from >= end) aoqi@0: *(to--) = *(from--); aoqi@0: } aoqi@0: } aoqi@0: void _Copy_conjoint_jlongs_atomic(jlong* from, jlong* to, size_t count) { aoqi@0: if (from > to) { aoqi@0: jlong *end = from + count; aoqi@0: while (from < end) aoqi@0: os::atomic_copy64(from++, to++); aoqi@0: } aoqi@0: else if (from < to) { aoqi@0: jlong *end = from; aoqi@0: from += count - 1; aoqi@0: to += count - 1; aoqi@0: while (from >= end) aoqi@0: os::atomic_copy64(from--, to--); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: void _Copy_arrayof_conjoint_bytes(HeapWord* from, aoqi@0: HeapWord* to, aoqi@0: size_t count) { aoqi@0: memmove(to, from, count); aoqi@0: } aoqi@0: void _Copy_arrayof_conjoint_jshorts(HeapWord* from, aoqi@0: HeapWord* to, aoqi@0: size_t count) { aoqi@0: memmove(to, from, count * 2); aoqi@0: } aoqi@0: void _Copy_arrayof_conjoint_jints(HeapWord* from, aoqi@0: HeapWord* to, aoqi@0: size_t count) { aoqi@0: memmove(to, from, count * 4); aoqi@0: } aoqi@0: void _Copy_arrayof_conjoint_jlongs(HeapWord* from, aoqi@0: HeapWord* to, aoqi@0: size_t count) { aoqi@0: memmove(to, from, count * 8); aoqi@0: } aoqi@0: }; aoqi@0: aoqi@0: ///////////////////////////////////////////////////////////////////////////// aoqi@0: // Implementations of atomic operations not supported by processors. aoqi@0: // -- http://gcc.gnu.org/onlinedocs/gcc-4.2.1/gcc/Atomic-Builtins.html aoqi@0: aoqi@0: #ifndef _LP64 aoqi@0: extern "C" { aoqi@0: long long unsigned int __sync_val_compare_and_swap_8( aoqi@0: volatile void *ptr, aoqi@0: long long unsigned int oldval, aoqi@0: long long unsigned int newval) { aoqi@0: ShouldNotCallThis(); aoqi@0: } aoqi@0: }; aoqi@0: #endif // !_LP64 aoqi@0: aoqi@0: #ifndef PRODUCT aoqi@0: void os::verify_stack_alignment() { aoqi@0: } aoqi@0: #endif