Path: blob/master/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp
41144 views
/*1* Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved.2* Copyright (c) 2014, Red Hat Inc. All rights reserved.3* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.4*5* This code is free software; you can redistribute it and/or modify it6* under the terms of the GNU General Public License version 2 only, as7* published by the Free Software Foundation.8*9* This code is distributed in the hope that it will be useful, but WITHOUT10* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or11* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License12* version 2 for more details (a copy is included in the LICENSE file that13* accompanied this code).14*15* You should have received a copy of the GNU General Public License version16* 2 along with this work; if not, write to the Free Software Foundation,17* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.18*19* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA20* or visit www.oracle.com if you need additional information or have any21* questions.22*23*/2425// no precompiled headers26#include "jvm.h"27#include "asm/macroAssembler.hpp"28#include "classfile/vmSymbols.hpp"29#include "code/codeCache.hpp"30#include "code/icBuffer.hpp"31#include "code/vtableStubs.hpp"32#include "code/nativeInst.hpp"33#include "interpreter/interpreter.hpp"34#include "memory/allocation.inline.hpp"35#include "os_share_linux.hpp"36#include "prims/jniFastGetField.hpp"37#include "prims/jvm_misc.hpp"38#include "runtime/arguments.hpp"39#include "runtime/frame.inline.hpp"40#include "runtime/interfaceSupport.inline.hpp"41#include "runtime/java.hpp"42#include "runtime/javaCalls.hpp"43#include "runtime/mutexLocker.hpp"44#include "runtime/osThread.hpp"45#include "runtime/safepointMechanism.hpp"46#include "runtime/sharedRuntime.hpp"47#include "runtime/stubRoutines.hpp"48#include "runtime/thread.inline.hpp"49#include "runtime/timer.hpp"50#include "signals_posix.hpp"51#include "utilities/debug.hpp"52#include "utilities/events.hpp"53#include "utilities/vmError.hpp"5455// put OS-includes here56# include <sys/types.h>57# include <sys/mman.h>58# include <pthread.h>59# include <signal.h>60# include <errno.h>61# include <dlfcn.h>62# include <stdlib.h>63# include <stdio.h>64# include <unistd.h>65# include <sys/resource.h>66# include <pthread.h>67# include <sys/stat.h>68# include <sys/time.h>69# include <sys/utsname.h>70# include <sys/socket.h>71# include <sys/wait.h>72# include <pwd.h>73# include <poll.h>74# include <ucontext.h>7576#define REG_FP 2977#define REG_LR 307879NOINLINE address os::current_stack_pointer() {80return (address)__builtin_frame_address(0);81}8283char* os::non_memory_address_word() {84// Must never look like an address returned by reserve_memory,85// even in its subfields (as defined by the CPU immediate fields,86// if the CPU splits constants across multiple instructions).8788return (char*) 0xffffffffffff;89}9091address os::Posix::ucontext_get_pc(const ucontext_t * uc) {92return (address)uc->uc_mcontext.pc;93}9495void os::Posix::ucontext_set_pc(ucontext_t * uc, address pc) {96uc->uc_mcontext.pc = (intptr_t)pc;97}9899intptr_t* os::Linux::ucontext_get_sp(const ucontext_t * uc) {100return (intptr_t*)uc->uc_mcontext.sp;101}102103intptr_t* os::Linux::ucontext_get_fp(const ucontext_t * uc) {104return (intptr_t*)uc->uc_mcontext.regs[REG_FP];105}106107address os::fetch_frame_from_context(const void* ucVoid,108intptr_t** ret_sp, intptr_t** ret_fp) {109110address epc;111const ucontext_t* uc = (const ucontext_t*)ucVoid;112113if (uc != NULL) {114epc = os::Posix::ucontext_get_pc(uc);115if (ret_sp) *ret_sp = os::Linux::ucontext_get_sp(uc);116if (ret_fp) *ret_fp = os::Linux::ucontext_get_fp(uc);117} else {118epc = NULL;119if (ret_sp) *ret_sp = (intptr_t *)NULL;120if (ret_fp) *ret_fp = (intptr_t *)NULL;121}122123return epc;124}125126frame os::fetch_frame_from_context(const void* ucVoid) {127intptr_t* sp;128intptr_t* fp;129address epc = fetch_frame_from_context(ucVoid, &sp, &fp);130return frame(sp, fp, epc);131}132133frame os::fetch_compiled_frame_from_context(const void* ucVoid) {134const ucontext_t* uc = (const ucontext_t*)ucVoid;135// In compiled code, the stack banging is performed before LR136// has been saved in the frame. LR is live, and SP and FP137// belong to the caller.138intptr_t* fp = os::Linux::ucontext_get_fp(uc);139intptr_t* sp = os::Linux::ucontext_get_sp(uc);140address pc = (address)(uc->uc_mcontext.regs[REG_LR]141- NativeInstruction::instruction_size);142return frame(sp, fp, pc);143}144145// By default, gcc always saves frame pointer rfp on this stack. This146// may get turned off by -fomit-frame-pointer.147frame os::get_sender_for_C_frame(frame* fr) {148return frame(fr->link(), fr->link(), fr->sender_pc());149}150151NOINLINE frame os::current_frame() {152intptr_t *fp = *(intptr_t **)__builtin_frame_address(0);153frame myframe((intptr_t*)os::current_stack_pointer(),154(intptr_t*)fp,155CAST_FROM_FN_PTR(address, os::current_frame));156if (os::is_first_C_frame(&myframe)) {157// stack is not walkable158return frame();159} else {160return os::get_sender_for_C_frame(&myframe);161}162}163164bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info,165ucontext_t* uc, JavaThread* thread) {166167/*168NOTE: does not seem to work on linux.169if (info == NULL || info->si_code <= 0 || info->si_code == SI_NOINFO) {170// can't decode this kind of signal171info = NULL;172} else {173assert(sig == info->si_signo, "bad siginfo");174}175*/176// decide if this trap can be handled by a stub177address stub = NULL;178179address pc = NULL;180181//%note os_trap_1182if (info != NULL && uc != NULL && thread != NULL) {183pc = (address) os::Posix::ucontext_get_pc(uc);184185address addr = (address) info->si_addr;186187// Make sure the high order byte is sign extended, as it may be masked away by the hardware.188if ((uintptr_t(addr) & (uintptr_t(1) << 55)) != 0) {189addr = address(uintptr_t(addr) | (uintptr_t(0xFF) << 56));190}191192// Handle ALL stack overflow variations here193if (sig == SIGSEGV) {194// check if fault address is within thread stack195if (thread->is_in_full_stack(addr)) {196if (os::Posix::handle_stack_overflow(thread, addr, pc, uc, &stub)) {197return true; // continue198}199}200}201202if (thread->thread_state() == _thread_in_Java) {203// Java thread running in Java code => find exception handler if any204// a fault inside compiled code, the interpreter, or a stub205206// Handle signal from NativeJump::patch_verified_entry().207if ((sig == SIGILL || sig == SIGTRAP)208&& nativeInstruction_at(pc)->is_sigill_zombie_not_entrant()) {209if (TraceTraps) {210tty->print_cr("trap: zombie_not_entrant (%s)", (sig == SIGTRAP) ? "SIGTRAP" : "SIGILL");211}212stub = SharedRuntime::get_handle_wrong_method_stub();213} else if (sig == SIGSEGV && SafepointMechanism::is_poll_address((address)info->si_addr)) {214stub = SharedRuntime::get_poll_stub(pc);215} else if (sig == SIGBUS /* && info->si_code == BUS_OBJERR */) {216// BugId 4454115: A read from a MappedByteBuffer can fault217// here if the underlying file has been truncated.218// Do not crash the VM in such a case.219CodeBlob* cb = CodeCache::find_blob_unsafe(pc);220CompiledMethod* nm = (cb != NULL) ? cb->as_compiled_method_or_null() : NULL;221bool is_unsafe_arraycopy = (thread->doing_unsafe_access() && UnsafeCopyMemory::contains_pc(pc));222if ((nm != NULL && nm->has_unsafe_access()) || is_unsafe_arraycopy) {223address next_pc = pc + NativeCall::instruction_size;224if (is_unsafe_arraycopy) {225next_pc = UnsafeCopyMemory::page_error_continue_pc(pc);226}227stub = SharedRuntime::handle_unsafe_access(thread, next_pc);228}229} else if (sig == SIGILL && nativeInstruction_at(pc)->is_stop()) {230// Pull a pointer to the error message out of the instruction231// stream.232const uint64_t *detail_msg_ptr233= (uint64_t*)(pc + NativeInstruction::instruction_size);234const char *detail_msg = (const char *)*detail_msg_ptr;235const char *msg = "stop";236if (TraceTraps) {237tty->print_cr("trap: %s: (SIGILL)", msg);238}239240// End life with a fatal error, message and detail message and the context.241// Note: no need to do any post-processing here (e.g. signal chaining)242va_list va_dummy;243VMError::report_and_die(thread, uc, NULL, 0, msg, detail_msg, va_dummy);244va_end(va_dummy);245246ShouldNotReachHere();247248}249else250251if (sig == SIGFPE &&252(info->si_code == FPE_INTDIV || info->si_code == FPE_FLTDIV)) {253stub =254SharedRuntime::255continuation_for_implicit_exception(thread,256pc,257SharedRuntime::258IMPLICIT_DIVIDE_BY_ZERO);259} else if (sig == SIGSEGV &&260MacroAssembler::uses_implicit_null_check((void*)addr)) {261// Determination of interpreter/vtable stub/compiled code null exception262stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL);263}264} else if ((thread->thread_state() == _thread_in_vm ||265thread->thread_state() == _thread_in_native) &&266sig == SIGBUS && /* info->si_code == BUS_OBJERR && */267thread->doing_unsafe_access()) {268address next_pc = pc + NativeCall::instruction_size;269if (UnsafeCopyMemory::contains_pc(pc)) {270next_pc = UnsafeCopyMemory::page_error_continue_pc(pc);271}272stub = SharedRuntime::handle_unsafe_access(thread, next_pc);273}274275// jni_fast_Get<Primitive>Field can trap at certain pc's if a GC kicks in276// and the heap gets shrunk before the field access.277if ((sig == SIGSEGV) || (sig == SIGBUS)) {278address addr = JNI_FastGetField::find_slowcase_pc(pc);279if (addr != (address)-1) {280stub = addr;281}282}283}284285if (stub != NULL) {286// save all thread context in case we need to restore it287if (thread != NULL) thread->set_saved_exception_pc(pc);288289os::Posix::ucontext_set_pc(uc, stub);290return true;291}292293return false; // Mute compiler294}295296void os::Linux::init_thread_fpu_state(void) {297}298299int os::Linux::get_fpu_control_word(void) {300return 0;301}302303void os::Linux::set_fpu_control_word(int fpu_control) {304}305306////////////////////////////////////////////////////////////////////////////////307// thread stack308309// Minimum usable stack sizes required to get to user code. Space for310// HotSpot guard pages is added later.311size_t os::Posix::_compiler_thread_min_stack_allowed = 72 * K;312size_t os::Posix::_java_thread_min_stack_allowed = 72 * K;313size_t os::Posix::_vm_internal_thread_min_stack_allowed = 72 * K;314315// return default stack size for thr_type316size_t os::Posix::default_stack_size(os::ThreadType thr_type) {317// default stack size (compiler thread needs larger stack)318size_t s = (thr_type == os::compiler_thread ? 4 * M : 1 * M);319return s;320}321322/////////////////////////////////////////////////////////////////////////////323// helper functions for fatal error handler324325void os::print_context(outputStream *st, const void *context) {326if (context == NULL) return;327328const ucontext_t *uc = (const ucontext_t*)context;329st->print_cr("Registers:");330for (int r = 0; r < 31; r++) {331st->print("R%-2d=", r);332print_location(st, uc->uc_mcontext.regs[r]);333}334st->cr();335336intptr_t *sp = (intptr_t *)os::Linux::ucontext_get_sp(uc);337st->print_cr("Top of Stack: (sp=" PTR_FORMAT ")", p2i(sp));338print_hex_dump(st, (address)sp, (address)(sp + 8*sizeof(intptr_t)), sizeof(intptr_t));339st->cr();340341// Note: it may be unsafe to inspect memory near pc. For example, pc may342// point to garbage if entry point in an nmethod is corrupted. Leave343// this at the end, and hope for the best.344address pc = os::Posix::ucontext_get_pc(uc);345print_instructions(st, pc, 4/*native instruction size*/);346st->cr();347}348349void os::print_register_info(outputStream *st, const void *context) {350if (context == NULL) return;351352const ucontext_t *uc = (const ucontext_t*)context;353354st->print_cr("Register to memory mapping:");355st->cr();356357// this is horrendously verbose but the layout of the registers in the358// context does not match how we defined our abstract Register set, so359// we can't just iterate through the gregs area360361// this is only for the "general purpose" registers362363for (int r = 0; r < 31; r++)364st->print_cr( "R%d=" INTPTR_FORMAT, r, (uintptr_t)uc->uc_mcontext.regs[r]);365st->cr();366}367368void os::setup_fpu() {369}370371#ifndef PRODUCT372void os::verify_stack_alignment() {373assert(((intptr_t)os::current_stack_pointer() & (StackAlignmentInBytes-1)) == 0, "incorrect stack alignment");374}375#endif376377int os::extra_bang_size_in_bytes() {378// AArch64 does not require the additional stack bang.379return 0;380}381382extern "C" {383int SpinPause() {384return 0;385}386387void _Copy_conjoint_jshorts_atomic(const jshort* from, jshort* to, size_t count) {388if (from > to) {389const jshort *end = from + count;390while (from < end)391*(to++) = *(from++);392}393else if (from < to) {394const jshort *end = from;395from += count - 1;396to += count - 1;397while (from >= end)398*(to--) = *(from--);399}400}401void _Copy_conjoint_jints_atomic(const jint* from, jint* to, size_t count) {402if (from > to) {403const jint *end = from + count;404while (from < end)405*(to++) = *(from++);406}407else if (from < to) {408const jint *end = from;409from += count - 1;410to += count - 1;411while (from >= end)412*(to--) = *(from--);413}414}415void _Copy_conjoint_jlongs_atomic(const jlong* from, jlong* to, size_t count) {416if (from > to) {417const jlong *end = from + count;418while (from < end)419os::atomic_copy64(from++, to++);420}421else if (from < to) {422const jlong *end = from;423from += count - 1;424to += count - 1;425while (from >= end)426os::atomic_copy64(from--, to--);427}428}429430void _Copy_arrayof_conjoint_bytes(const HeapWord* from,431HeapWord* to,432size_t count) {433memmove(to, from, count);434}435void _Copy_arrayof_conjoint_jshorts(const HeapWord* from,436HeapWord* to,437size_t count) {438memmove(to, from, count * 2);439}440void _Copy_arrayof_conjoint_jints(const HeapWord* from,441HeapWord* to,442size_t count) {443memmove(to, from, count * 4);444}445void _Copy_arrayof_conjoint_jlongs(const HeapWord* from,446HeapWord* to,447size_t count) {448memmove(to, from, count * 8);449}450};451452453