diff options
| author | 2018-07-11 15:14:10 +0100 | |
|---|---|---|
| committer | 2018-09-06 13:47:10 +0100 | |
| commit | f233136f2ca25316643b7f409df7af55a762f98a (patch) | |
| tree | a5aee0db607b4dc4d08e695426ebb74abcaabc35 /runtime/jit/jit_code_cache.cc | |
| parent | 9999327c8fbcab1d57f609457d68085ddefb7eb7 (diff) | |
ART: Add FlushInstructionPipeline()
Use membarrier(MEMBARRIER_CMD_PRIVATE_EXPEDITED), where available, to
flush CPU instruction pipelines after JIT code cache updates. This is
needed on architectures where TLB updates do not require a TLB
shootdown.
Bug: 65312375
Bug: 66095511
Bug: 111199492
Test: manual (requires kernel >= 4.16).
Change-Id: I96811c611133ba765a546a09432c0c951ad39e10
Diffstat (limited to 'runtime/jit/jit_code_cache.cc')
| -rw-r--r-- | runtime/jit/jit_code_cache.cc | 16 |
1 files changed, 14 insertions, 2 deletions
diff --git a/runtime/jit/jit_code_cache.cc b/runtime/jit/jit_code_cache.cc index 2b2898c195..461eb810c2 100644 --- a/runtime/jit/jit_code_cache.cc +++ b/runtime/jit/jit_code_cache.cc @@ -28,6 +28,7 @@ #include "base/stl_util.h" #include "base/systrace.h" #include "base/time_utils.h" +#include "base/utils.h" #include "cha.h" #include "debugger_interface.h" #include "dex/dex_file_loader.h" @@ -53,8 +54,9 @@ namespace art { namespace jit { -static constexpr int kProtData = PROT_READ | PROT_WRITE; static constexpr int kProtCode = PROT_READ | PROT_EXEC; +static constexpr int kProtData = PROT_READ | PROT_WRITE; +static constexpr int kProtProfile = PROT_READ; static constexpr size_t kCodeSizeLogThreshold = 50 * KB; static constexpr size_t kStackMapSizeLogThreshold = 50 * KB; @@ -192,7 +194,7 @@ JitCodeCache* JitCodeCache::Create(size_t initial_capacity, // to profile system server. // NOTE 2: We could just not create the code section at all but we will need to // special case too many cases. - int memmap_flags_prot_code = used_only_for_profile_data ? (kProtCode & ~PROT_EXEC) : kProtCode; + int memmap_flags_prot_code = used_only_for_profile_data ? kProtProfile : kProtCode; std::string error_str; // Map name specific for android_os_Debug.cpp accounting. @@ -801,6 +803,16 @@ uint8_t* JitCodeCache::CommitCodeInternal(Thread* self, // https://android.googlesource.com/kernel/msm/+/3fbe6bc28a6b9939d0650f2f17eb5216c719950c FlushInstructionCache(reinterpret_cast<char*>(code_ptr), reinterpret_cast<char*>(code_ptr + code_size)); + + // Ensure CPU instruction pipelines are flushed for all cores. This is necessary for + // correctness as code may still be in instruction pipelines despite the i-cache flush. It is + // not safe to assume that changing permissions with mprotect (RX->RWX->RX) will cause a TLB + // shootdown (incidentally invalidating the CPU pipelines by sending an IPI to all cores to + // notify them of the TLB invalidation). Some architectures, notably ARM and ARM64, have + // hardware support that broadcasts TLB invalidations and so their kernels have no software + // based TLB shootdown. FlushInstructionPipeline() is a wrapper around the Linux + // membarrier(MEMBARRIER_CMD_PRIVATE_EXPEDITED) syscall which does the appropriate flushing. + FlushInstructionPipeline(); DCHECK(!Runtime::Current()->IsAotCompiler()); if (has_should_deoptimize_flag) { method_header->SetHasShouldDeoptimizeFlag(); |