8221554: aarch64 cross-modifying code

Reviewed-by: rehn, aph
This commit is contained in:
Alan Hayward 2020-11-19 12:27:22 +00:00 committed by Nick Gasson
parent f626ed6a43
commit d183fc7faa
26 changed files with 134 additions and 49 deletions

View File

@ -2922,7 +2922,6 @@ void LIR_Assembler::rt_call(LIR_Opr result, address dest, const LIR_OprList* arg
if (info != NULL) {
add_call_info_here(info);
}
__ maybe_isb();
}
void LIR_Assembler::volatile_move_op(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmitInfo* info) {

View File

@ -80,7 +80,6 @@ int StubAssembler::call_RT(Register oop_result1, Register metadata_result, addre
pop(r0, sp);
#endif
reset_last_Java_frame(true);
maybe_isb();
// check for pending exceptions
{ Label L;

View File

@ -1617,7 +1617,7 @@ void InterpreterMacroAssembler::call_VM_base(Register oop_result,
Label L;
ldr(rscratch1, Address(rfp, frame::interpreter_frame_last_sp_offset * wordSize));
cbz(rscratch1, L);
stop("InterpreterMacroAssembler::call_VM_leaf_base:"
stop("InterpreterMacroAssembler::call_VM_base:"
" last_sp != NULL");
bind(L);
}

View File

@ -159,7 +159,6 @@ address JNI_FastGetField::generate_fast_get_int_field0(BasicType type) {
__ enter();
__ lea(rscratch1, ExternalAddress(slow_case_addr));
__ blr(rscratch1);
__ maybe_isb();
__ leave();
__ ret(lr);
}

View File

@ -1381,7 +1381,6 @@ void MacroAssembler::call_VM_leaf_base(address entry_point,
bind(*retaddr);
ldp(rscratch1, rmethod, Address(post(sp, 2 * wordSize)));
maybe_isb();
}
void MacroAssembler::call_VM_leaf(address entry_point, int number_of_arguments) {
@ -4387,10 +4386,15 @@ void MacroAssembler::get_polling_page(Register dest, relocInfo::relocType rtype)
// Read the polling page. The address of the polling page must
// already be in r.
address MacroAssembler::read_polling_page(Register r, relocInfo::relocType rtype) {
InstructionMark im(this);
code_section()->relocate(inst_mark(), rtype);
ldrw(zr, Address(r, 0));
return inst_mark();
address mark;
{
InstructionMark im(this);
code_section()->relocate(inst_mark(), rtype);
ldrw(zr, Address(r, 0));
mark = inst_mark();
}
verify_cross_modify_fence_not_required();
return mark;
}
void MacroAssembler::adrp(Register reg1, const Address &dest, uint64_t &byte_offset) {
@ -4455,6 +4459,7 @@ void MacroAssembler::build_frame(int framesize) {
sub(sp, sp, rscratch1);
}
}
verify_cross_modify_fence_not_required();
}
void MacroAssembler::remove_frame(int framesize) {
@ -5315,3 +5320,29 @@ void MacroAssembler::verify_ptrue() {
stop("Error: the preserved predicate register (p7) elements are not all true");
bind(verify_ok);
}
void MacroAssembler::safepoint_isb() {
isb();
#ifndef PRODUCT
if (VerifyCrossModifyFence) {
// Clear the thread state.
strb(zr, Address(rthread, in_bytes(JavaThread::requires_cross_modify_fence_offset())));
}
#endif
}
#ifndef PRODUCT
void MacroAssembler::verify_cross_modify_fence_not_required() {
if (VerifyCrossModifyFence) {
// Check if thread needs a cross modify fence.
ldrb(rscratch1, Address(rthread, in_bytes(JavaThread::requires_cross_modify_fence_offset())));
Label fence_not_required;
cbz(rscratch1, fence_not_required);
// If it does then fail.
lea(rscratch1, CAST_FROM_FN_PTR(address, JavaThread::verify_cross_modify_fence_failure));
mov(c_rarg0, rthread);
blr(rscratch1);
bind(fence_not_required);
}
}
#endif

View File

@ -1315,8 +1315,9 @@ public:
Register zlen, Register tmp1, Register tmp2, Register tmp3,
Register tmp4, Register tmp5, Register tmp6, Register tmp7);
void mul_add(Register out, Register in, Register offs, Register len, Register k);
// ISB may be needed because of a safepoint
void maybe_isb() { isb(); }
// Place an ISB after code may have been modified due to a safepoint.
void safepoint_isb();
private:
// Return the effective address r + (r1 << ext) + offset.
@ -1392,6 +1393,11 @@ public:
}
void cache_wb(Address line);
void cache_wbsync(bool is_pre);
private:
// Check the current thread doesn't need a cross modify fence.
void verify_cross_modify_fence_not_required() PRODUCT_RETURN;
};
#ifdef ASSERT

View File

@ -373,7 +373,10 @@ static void patch_callers_callsite(MacroAssembler *masm) {
__ mov(c_rarg1, lr);
__ lea(rscratch1, RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::fixup_callers_callsite)));
__ blr(rscratch1);
__ maybe_isb();
// Explicit isb required because fixup_callers_callsite may change the code
// stream.
__ safepoint_isb();
__ pop_CPU_state();
// restore sp
@ -1150,7 +1153,6 @@ static void rt_call(MacroAssembler* masm, address dest) {
} else {
__ lea(rscratch1, RuntimeAddress(dest));
__ blr(rscratch1);
__ maybe_isb();
}
}
@ -1857,7 +1859,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
__ verify_sve_vector_length();
}
// check for safepoint operation in progress and/or pending suspend requests
// Check for safepoint operation in progress and/or pending suspend requests.
{
// We need an acquire here to ensure that any subsequent load of the
// global SafepointSynchronize::_state flag is ordered after this load
@ -2081,7 +2083,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
#endif
__ lea(rscratch1, RuntimeAddress(CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans)));
__ blr(rscratch1);
__ maybe_isb();
// Restore any method result value
restore_native_result(masm, ret_type, stack_slots);
@ -2787,7 +2789,6 @@ SafepointBlob* SharedRuntime::generate_handler_blob(address call_ptr, int poll_t
__ reset_last_Java_frame(false);
__ maybe_isb();
__ membar(Assembler::LoadLoad | Assembler::LoadStore);
if (UseSVE > 0 && save_vectors) {
@ -2894,8 +2895,6 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(address destination, const cha
oop_maps->add_gc_map( __ offset() - start, map);
__ maybe_isb();
// r0 contains the address we are going to jump to assuming no exception got installed
// clear last_Java_sp
@ -3017,7 +3016,8 @@ void OptoRuntime::generate_exception_blob() {
__ mov(c_rarg0, rthread);
__ lea(rscratch1, RuntimeAddress(CAST_FROM_FN_PTR(address, OptoRuntime::handle_exception_C)));
__ blr(rscratch1);
__ maybe_isb();
// handle_exception_C is a special VM call which does not require an explicit
// instruction sync afterwards.
// Set an oopmap for the call site. This oopmap will only be used if we
// are unwinding the stack. Hence, all locations will be dead.

View File

@ -5629,7 +5629,6 @@ class StubGenerator: public StubCodeGenerator {
oop_maps->add_gc_map(the_pc - start, map);
__ reset_last_Java_frame(true);
__ maybe_isb();
if (UseSVE > 0) {
// Reinitialize the ptrue predicate register, in case the external runtime

View File

@ -1357,7 +1357,6 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) {
// Call the native method.
__ blr(r10);
__ bind(native_return);
__ maybe_isb();
__ get_method(rmethod);
// result potentially in r0 or v0
@ -1410,7 +1409,6 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) {
__ mov(c_rarg0, rthread);
__ mov(rscratch2, CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans));
__ blr(rscratch2);
__ maybe_isb();
__ get_method(rmethod);
__ reinit_heapbase();
__ bind(Continue);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2019 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@ -73,7 +73,7 @@ inline void OrderAccess::storeload() { inlasm_sync(); }
inline void OrderAccess::acquire() { inlasm_lwsync(); }
inline void OrderAccess::release() { inlasm_lwsync(); }
inline void OrderAccess::fence() { inlasm_sync(); }
inline void OrderAccess::cross_modify_fence()
inline void OrderAccess::cross_modify_fence_impl()
{ inlasm_isync(); }
#undef inlasm_sync

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -59,7 +59,7 @@ inline void OrderAccess::fence() {
compiler_barrier();
}
inline void OrderAccess::cross_modify_fence() {
inline void OrderAccess::cross_modify_fence_impl() {
int idx = 0;
__asm__ volatile ("cpuid " : "+a" (idx) : : "ebx", "ecx", "edx", "memory");
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright 2007, 2008, 2009 Red Hat, Inc.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@ -77,6 +77,6 @@ inline void OrderAccess::storeload() { FULL_MEM_BARRIER; }
inline void OrderAccess::acquire() { LIGHT_MEM_BARRIER; }
inline void OrderAccess::release() { LIGHT_MEM_BARRIER; }
inline void OrderAccess::fence() { FULL_MEM_BARRIER; }
inline void OrderAccess::cross_modify_fence() { }
inline void OrderAccess::cross_modify_fence_impl() { }
#endif // OS_CPU_BSD_ZERO_ORDERACCESS_BSD_ZERO_HPP

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2019, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@ -53,6 +53,8 @@ inline void OrderAccess::fence() {
FULL_MEM_BARRIER;
}
inline void OrderAccess::cross_modify_fence() { }
inline void OrderAccess::cross_modify_fence_impl() {
asm volatile("isb" : : : "memory");
}
#endif // OS_CPU_LINUX_AARCH64_ORDERACCESS_LINUX_AARCH64_HPP

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -101,6 +101,6 @@ inline void OrderAccess::storestore() { dmb_st(); }
inline void OrderAccess::storeload() { dmb_sy(); }
inline void OrderAccess::release() { dmb_sy(); }
inline void OrderAccess::fence() { dmb_sy(); }
inline void OrderAccess::cross_modify_fence() { }
inline void OrderAccess::cross_modify_fence_impl() { }
#endif // OS_CPU_LINUX_ARM_ORDERACCESS_LINUX_ARM_HPP

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2014 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@ -77,7 +77,7 @@ inline void OrderAccess::storeload() { inlasm_sync(); }
inline void OrderAccess::acquire() { inlasm_lwsync(); }
inline void OrderAccess::release() { inlasm_lwsync(); }
inline void OrderAccess::fence() { inlasm_sync(); }
inline void OrderAccess::cross_modify_fence()
inline void OrderAccess::cross_modify_fence_impl()
{ inlasm_isync(); }
#undef inlasm_sync

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2019 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@ -74,7 +74,7 @@ inline void OrderAccess::storeload() { inlasm_zarch_sync(); }
inline void OrderAccess::acquire() { inlasm_zarch_acquire(); }
inline void OrderAccess::release() { inlasm_zarch_release(); }
inline void OrderAccess::fence() { inlasm_zarch_sync(); }
inline void OrderAccess::cross_modify_fence() { inlasm_zarch_sync(); }
inline void OrderAccess::cross_modify_fence_impl() { inlasm_zarch_sync(); }
#undef inlasm_compiler_barrier
#undef inlasm_zarch_sync

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -55,7 +55,7 @@ inline void OrderAccess::fence() {
compiler_barrier();
}
inline void OrderAccess::cross_modify_fence() {
inline void OrderAccess::cross_modify_fence_impl() {
int idx = 0;
#ifdef AMD64
__asm__ volatile ("cpuid " : "+a" (idx) : : "ebx", "ecx", "edx", "memory");

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright 2007, 2008, 2009 Red Hat, Inc.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@ -78,6 +78,6 @@ inline void OrderAccess::acquire() { LIGHT_MEM_BARRIER; }
inline void OrderAccess::release() { LIGHT_MEM_BARRIER; }
inline void OrderAccess::fence() { FULL_MEM_BARRIER; }
inline void OrderAccess::cross_modify_fence() { }
inline void OrderAccess::cross_modify_fence_impl() { }
#endif // OS_CPU_LINUX_ZERO_ORDERACCESS_LINUX_ZERO_HPP

View File

@ -28,7 +28,7 @@
// Included in orderAccess.hpp header file.
#include <atomic>
using std::atomic_thread_fence;
#include <intrin.h>
#include <arm64intr.h>
#include "vm_version_aarch64.hpp"
#include "runtime/vm_version.hpp"
@ -55,6 +55,8 @@ inline void OrderAccess::fence() {
FULL_MEM_BARRIER;
}
inline void OrderAccess::cross_modify_fence() { }
inline void OrderAccess::cross_modify_fence_impl() {
__isb(_ARM64_BARRIER_SY);
}
#endif // OS_CPU_WINDOWS_AARCH64_ORDERACCESS_WINDOWS_AARCH64_HPP

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -58,7 +58,7 @@ inline void OrderAccess::fence() {
compiler_barrier();
}
inline void OrderAccess::cross_modify_fence() {
inline void OrderAccess::cross_modify_fence_impl() {
int regs[4];
__cpuid(regs, 0);
}

View File

@ -2490,7 +2490,12 @@ const intx ObjectAlignmentInBytes = 8;
"Allow allocating fields in empty slots of super-classes") \
\
product(bool, DeoptimizeNMethodBarriersALot, false, DIAGNOSTIC, \
"Make nmethod barriers deoptimise a lot.")
"Make nmethod barriers deoptimise a lot.") \
\
develop(bool, VerifyCrossModifyFence, \
false AARCH64_ONLY(DEBUG_ONLY(||true)), \
"Mark all threads after a safepoint, and clear on a modify " \
"fence. Add cleanliness checks.") \
// end of RUNTIME_FLAGS

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,7 +25,10 @@
#include "precompiled.hpp"
#include "runtime/orderAccess.hpp"
#include "runtime/stubRoutines.hpp"
#ifndef PRODUCT
#include "runtime/thread.hpp"
#endif
void OrderAccess::StubRoutines_fence() {
// Use a stub if it exists. It may not exist during bootstrap so do
@ -38,3 +41,11 @@ void OrderAccess::StubRoutines_fence() {
}
assert(Threads::number_of_threads() == 0, "for bootstrap only");
}
#ifndef PRODUCT
void OrderAccess::cross_modify_fence_verify() {
if (VerifyCrossModifyFence) {
JavaThread::current()->set_requires_cross_modify_fence(false);
}
}
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -112,7 +112,7 @@
// may be more conservative in implementations. We advise using the bound
// variants whenever possible.
//
// Finally, we define a "fence" operation, as a bidirectional barrier.
// We define a "fence" operation, as a bidirectional barrier.
// It guarantees that any memory access preceding the fence is not
// reordered w.r.t. any memory accesses subsequent to the fence in program
// order. This may be used to prevent sequences of loads from floating up
@ -229,6 +229,10 @@
// order*. And that their destructors do a release and unlock, in *that*
// order. If their implementations change such that these assumptions
// are violated, a whole lot of code will break.
//
// Finally, we define an "instruction_fence" operation, which ensures that all
// instructions that come after the fence in program order are fetched
// from the cache or memory after the fence has completed.
class OrderAccess : public AllStatic {
public:
@ -242,7 +246,10 @@ class OrderAccess : public AllStatic {
static void release();
static void fence();
static void cross_modify_fence();
static void cross_modify_fence() {
cross_modify_fence_impl();
cross_modify_fence_verify();
}
// Processors which are not multi-copy-atomic require a full fence
// to enforce a globally consistent order of Independent Reads of
@ -259,6 +266,10 @@ private:
// routine if it exists, It should only be used by platforms that
// don't have another way to do the inline assembly.
static void StubRoutines_fence();
static void cross_modify_fence_impl();
static void cross_modify_fence_verify() PRODUCT_RETURN;
};
#include OS_CPU_HEADER(orderAccess)

View File

@ -381,6 +381,14 @@ void SafepointSynchronize::begin() {
assert(_waiting_to_block == 0, "No thread should be running");
#ifndef PRODUCT
// Mark all threads
if (VerifyCrossModifyFence) {
JavaThreadIteratorWithHandle jtiwh;
for (; JavaThread *cur = jtiwh.next(); ) {
cur->set_requires_cross_modify_fence(true);
}
}
if (safepoint_limit_time != 0) {
jlong current_time = os::javaTimeNanos();
if (safepoint_limit_time < current_time) {

View File

@ -1580,6 +1580,9 @@ JavaThread::JavaThread() :
ThreadSafepointState::create(this);
SafepointMechanism::initialize_header(this);
set_requires_cross_modify_fence(false);
pd_initialize();
assert(deferred_card_mark().is_empty(), "Default MemRegion ctor");
}
@ -4646,3 +4649,9 @@ void Threads::verify() {
VMThread* thread = VMThread::vm_thread();
if (thread != NULL) thread->verify();
}
#ifndef PRODUCT
void JavaThread::verify_cross_modify_fence_failure(JavaThread *thread) {
report_vm_error(__FILE__, __LINE__, "Cross modify fence failure", "%p", thread);
}
#endif

View File

@ -1093,6 +1093,7 @@ class JavaThread: public Thread {
private:
ThreadSafepointState* _safepoint_state; // Holds information about a thread during a safepoint
address _saved_exception_pc; // Saved pc of instruction where last implicit exception happened
NOT_PRODUCT(bool _requires_cross_modify_fence;) // State used by VerifyCrossModifyFence
// JavaThread termination support
enum TerminatedTypes {
@ -1324,6 +1325,8 @@ class JavaThread: public Thread {
SafepointMechanism::ThreadData* poll_data() { return &_poll_data; }
void set_requires_cross_modify_fence(bool val) PRODUCT_RETURN NOT_PRODUCT({ _requires_cross_modify_fence = val; })
private:
// Support for thread handshake operations
HandshakeState _handshake;
@ -1599,6 +1602,7 @@ class JavaThread: public Thread {
return byte_offset_of(JavaThread, _should_post_on_exceptions_flag);
}
static ByteSize doing_unsafe_access_offset() { return byte_offset_of(JavaThread, _doing_unsafe_access); }
NOT_PRODUCT(static ByteSize requires_cross_modify_fence_offset() { return byte_offset_of(JavaThread, _requires_cross_modify_fence); })
// Returns the jni environment for this thread
JNIEnv* jni_environment() { return &_jni_environment; }
@ -1888,6 +1892,8 @@ public:
bool is_interrupted(bool clear_interrupted);
static OopStorage* thread_oop_storage();
static void verify_cross_modify_fence_failure(JavaThread *thread) PRODUCT_RETURN;
};
// Inline implementation of JavaThread::current