Skip to content

Commit 49a1dea

Browse files
committed
[BACKOUT] Mitigate Neoverse-N1 erratum 1542419 negative impact on GCs
and JIT performance
1 parent 6466d98 commit 49a1dea

24 files changed

Lines changed: 51 additions & 1246 deletions

src/hotspot/cpu/aarch64/gc/z/zBarrierSetAssembler_aarch64.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -879,9 +879,7 @@ void ZBarrierSetAssembler::patch_barrier_relocation(address addr, int format) {
879879
ShouldNotReachHere();
880880
}
881881

882-
if (!UseSingleICacheInvalidation) {
883-
ICache::invalidate_word((address)patch_addr);
884-
}
882+
ICache::invalidate_word((address)patch_addr);
885883
}
886884

887885
#ifdef COMPILER1

src/hotspot/cpu/aarch64/globals_aarch64.hpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,6 @@ define_pd_global(intx, InlineSmallCode, 1000);
127127
"Branch Protection to use: none, standard, pac-ret") \
128128
product(bool, AlwaysMergeDMB, true, DIAGNOSTIC, \
129129
"Always merge DMB instructions in code emission") \
130-
product(bool, NeoverseN1ICacheErratumMitigation, false, DIAGNOSTIC, \
131-
"Enable workaround for Neoverse N1 erratum 1542419") \
132130

133131
// end of ARCH_FLAGS
134132

src/hotspot/cpu/aarch64/relocInfo_aarch64.cpp

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,7 @@ void Relocation::pd_set_data_value(address x, bool verify_only) {
5454
bytes = MacroAssembler::pd_patch_instruction_size(addr(), x);
5555
break;
5656
}
57-
58-
if (UseSingleICacheInvalidation) {
59-
assert(_binding != nullptr, "expect to be called with RelocIterator in use");
60-
} else {
61-
ICache::invalidate_range(addr(), bytes);
62-
}
57+
ICache::invalidate_range(addr(), bytes);
6358
}
6459

6560
address Relocation::pd_call_destination(address orig_addr) {

src/hotspot/cpu/aarch64/vm_version_aarch64.cpp

Lines changed: 0 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,6 @@ uintptr_t VM_Version::_pac_mask;
5252

5353
SpinWait VM_Version::_spin_wait;
5454

55-
bool VM_Version::_cache_dic_enabled;
56-
bool VM_Version::_cache_idc_enabled;
57-
5855
const char* VM_Version::_features_names[MAX_CPU_FEATURES] = { nullptr };
5956

6057
static SpinWait get_spin_wait_desc() {
@@ -66,19 +63,6 @@ static SpinWait get_spin_wait_desc() {
6663
return spin_wait;
6764
}
6865

69-
static bool has_neoverse_n1_errata_1542419() {
70-
const int major_rev_num = VM_Version::cpu_variant();
71-
const int minor_rev_num = VM_Version::cpu_revision();
72-
// Neoverse N1: 0xd0c
73-
// Erratum 1542419 affects r3p0, r3p1 and r4p0.
74-
// It is fixed in r4p1 and later revisions, which are not affected.
75-
return (VM_Version::cpu_family() == VM_Version::CPU_ARM &&
76-
VM_Version::model_is(0xd0c) &&
77-
((major_rev_num == 3 && minor_rev_num == 0) ||
78-
(major_rev_num == 3 && minor_rev_num == 1) ||
79-
(major_rev_num == 4 && minor_rev_num == 0)));
80-
}
81-
8266
void VM_Version::initialize() {
8367
#define SET_CPU_FEATURE_NAME(id, name, bit) \
8468
_features_names[bit] = XSTR(name);
@@ -90,9 +74,6 @@ void VM_Version::initialize() {
9074
_supports_atomic_getset8 = true;
9175
_supports_atomic_getadd8 = true;
9276

93-
_cache_dic_enabled = false;
94-
_cache_idc_enabled = false;
95-
9677
get_os_cpu_info();
9778

9879
int dcache_line = VM_Version::dcache_line_size();
@@ -680,32 +661,6 @@ void VM_Version::initialize() {
680661
clear_feature(CPU_SVE);
681662
}
682663

683-
if (FLAG_IS_DEFAULT(UseSingleICacheInvalidation) && is_cache_idc_enabled() && is_cache_dic_enabled()) {
684-
FLAG_SET_DEFAULT(UseSingleICacheInvalidation, true);
685-
}
686-
687-
if (FLAG_IS_DEFAULT(NeoverseN1ICacheErratumMitigation) && has_neoverse_n1_errata_1542419()) {
688-
FLAG_SET_DEFAULT(NeoverseN1ICacheErratumMitigation, true);
689-
}
690-
691-
if (NeoverseN1ICacheErratumMitigation) {
692-
if (!has_neoverse_n1_errata_1542419()) {
693-
vm_exit_during_initialization("NeoverseN1ICacheErratumMitigation is set for the CPU not having Neoverse N1 errata 1542419");
694-
}
695-
if (FLAG_IS_DEFAULT(UseSingleICacheInvalidation)) {
696-
FLAG_SET_DEFAULT(UseSingleICacheInvalidation, true);
697-
}
698-
699-
if (!UseSingleICacheInvalidation) {
700-
vm_exit_during_initialization("NeoverseN1ICacheErratumMitigation is set but UseSingleICacheInvalidation is not enabled");
701-
}
702-
}
703-
704-
if (UseSingleICacheInvalidation
705-
&& (!is_cache_idc_enabled() || (!is_cache_dic_enabled() && !NeoverseN1ICacheErratumMitigation))) {
706-
vm_exit_during_initialization("UseSingleICacheInvalidation is set but neither IDC nor DIC nor NeoverseN1ICacheErratumMitigation is enabled");
707-
}
708-
709664
// Construct the "features" string
710665
stringStream ss(512);
711666
ss.print("0x%02x:0x%x:0x%03x:%d", _cpu, _variant, _model, _revision);

src/hotspot/cpu/aarch64/vm_version_aarch64.hpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,6 @@ class VM_Version : public Abstract_VM_Version {
5858
// When _prefer_sve_merging_mode_cpy is true, `cpy (imm, zeroing)` is
5959
// implemented as `movi; cpy(imm, merging)`.
6060
static constexpr bool _prefer_sve_merging_mode_cpy = true;
61-
static bool _cache_dic_enabled;
62-
static bool _cache_idc_enabled;
6361

6462
static SpinWait _spin_wait;
6563

@@ -255,9 +253,6 @@ class VM_Version : public Abstract_VM_Version {
255253
return vector_length_in_bytes <= 16;
256254
}
257255

258-
static bool is_cache_dic_enabled() { return _cache_dic_enabled; }
259-
static bool is_cache_idc_enabled() { return _cache_idc_enabled; }
260-
261256
static void get_cpu_features_name(void* features_buffer, stringStream& ss);
262257

263258
// Returns names of features present in features_set1 but not in features_set2

src/hotspot/os_cpu/linux_aarch64/icache_linux_aarch64.cpp

Lines changed: 0 additions & 28 deletions
This file was deleted.

src/hotspot/os_cpu/linux_aarch64/icache_linux_aarch64.hpp

Lines changed: 1 addition & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,6 @@
2626
#ifndef OS_CPU_LINUX_AARCH64_ICACHE_AARCH64_HPP
2727
#define OS_CPU_LINUX_AARCH64_ICACHE_AARCH64_HPP
2828

29-
#include "memory/allocation.hpp"
30-
#include "runtime/vm_version.hpp"
31-
#include "utilities/globalDefinitions.hpp"
32-
3329
// Interface for updating the instruction cache. Whenever the VM
3430
// modifies code, part of the processor instruction cache potentially
3531
// has to be flushed.
@@ -41,103 +37,8 @@ class ICache : public AbstractICache {
4137
__builtin___clear_cache((char *)addr, (char *)(addr + 4));
4238
}
4339
static void invalidate_range(address start, int nbytes) {
44-
if (NeoverseN1ICacheErratumMitigation) {
45-
assert(VM_Version::is_cache_idc_enabled(),
46-
"Expect CTR_EL0.IDC to be enabled for Neoverse N1 with erratum "
47-
"1542419");
48-
assert(!VM_Version::is_cache_dic_enabled(),
49-
"Expect CTR_EL0.DIC to be disabled for Neoverse N1 with erratum "
50-
"1542419");
51-
asm volatile("dsb ish \n"
52-
"ic ivau, xzr \n"
53-
"dsb ish \n"
54-
"isb \n"
55-
: : : "memory");
56-
} else {
57-
__builtin___clear_cache((char *)start, (char *)(start + nbytes));
58-
}
40+
__builtin___clear_cache((char *)start, (char *)(start + nbytes));
5941
}
6042
};
6143

62-
class AArch64ICacheInvalidationContext : StackObj {
63-
private:
64-
65-
#ifdef ASSERT
66-
static THREAD_LOCAL AArch64ICacheInvalidationContext* _current_context;
67-
#endif
68-
69-
bool _has_modified_code;
70-
71-
public:
72-
NONCOPYABLE(AArch64ICacheInvalidationContext);
73-
74-
AArch64ICacheInvalidationContext()
75-
: _has_modified_code(false) {
76-
assert(_current_context == nullptr, "nested ICacheInvalidationContext not supported");
77-
#ifdef ASSERT
78-
_current_context = this;
79-
#endif
80-
}
81-
82-
~AArch64ICacheInvalidationContext() {
83-
NOT_PRODUCT(_current_context = nullptr);
84-
85-
if (!_has_modified_code || !UseSingleICacheInvalidation) {
86-
return;
87-
}
88-
89-
assert(VM_Version::is_cache_idc_enabled(), "Expect CTR_EL0.IDC to be enabled");
90-
91-
asm volatile("dsb ish" : : : "memory");
92-
93-
if (NeoverseN1ICacheErratumMitigation) {
94-
assert(!VM_Version::is_cache_dic_enabled(),
95-
"Expect CTR_EL0.DIC to be disabled for Neoverse N1 with erratum "
96-
"1542419");
97-
98-
// Errata 1542419: Neoverse N1 cores with the 'COHERENT_ICACHE' feature
99-
// may fetch stale instructions when software depends on
100-
// prefetch-speculation-protection instead of explicit synchronization.
101-
//
102-
// Neoverse-N1 implementation mitigates the errata 1542419 with a
103-
// workaround:
104-
// - Disable coherent icache.
105-
// - Trap IC IVAU instructions.
106-
// - Execute:
107-
// - tlbi vae3is, xzr
108-
// - dsb sy
109-
// - Ignore trapped IC IVAU instructions.
110-
//
111-
// `tlbi vae3is, xzr` invalidates all translation entries (all VAs, all
112-
// possible levels). It waits for all memory accesses using in-scope old
113-
// translation information to complete before it is considered complete.
114-
//
115-
// As this workaround has significant overhead, Arm Neoverse N1 (MP050)
116-
// Software Developer Errata Notice version 29.0 suggests:
117-
//
118-
// "Since one TLB inner-shareable invalidation is enough to avoid this
119-
// erratum, the number of injected TLB invalidations should be minimized
120-
// in the trap handler to mitigate the performance impact due to this
121-
// workaround."
122-
// As the address for icache invalidation is not relevant and
123-
// IC IVAU instruction is ignored, we use XZR in it.
124-
asm volatile(
125-
"ic ivau, xzr \n"
126-
"dsb ish \n"
127-
:
128-
:
129-
: "memory");
130-
} else {
131-
assert(VM_Version::is_cache_dic_enabled(), "Expect CTR_EL0.DIC to be enabled");
132-
}
133-
asm volatile("isb" : : : "memory");
134-
}
135-
136-
void set_has_modified_code() {
137-
_has_modified_code = true;
138-
}
139-
};
140-
141-
#define PD_ICACHE_INVALIDATION_CONTEXT AArch64ICacheInvalidationContext
142-
14344
#endif // OS_CPU_LINUX_AARCH64_ICACHE_AARCH64_HPP

src/hotspot/os_cpu/linux_aarch64/vm_version_linux_aarch64.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,8 +169,6 @@ void VM_Version::get_os_cpu_info() {
169169

170170
_icache_line_size = (1 << (ctr_el0 & 0x0f)) * 4;
171171
_dcache_line_size = (1 << ((ctr_el0 >> 16) & 0x0f)) * 4;
172-
_cache_idc_enabled = ((ctr_el0 >> 28) & 0x1) != 0;
173-
_cache_dic_enabled = ((ctr_el0 >> 29) & 0x1) != 0;
174172

175173
if (!(dczid_el0 & 0x10)) {
176174
_zva_length = 4 << (dczid_el0 & 0xf);

src/hotspot/share/asm/codeBuffer.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -745,6 +745,9 @@ void CodeBuffer::copy_code_to(CodeBlob* dest_blob) {
745745

746746
// Done moving code bytes; were they the right size?
747747
assert((int)align_up(dest.total_content_size(), oopSize) == dest_blob->content_size(), "sanity");
748+
749+
// Flush generated code
750+
ICache::invalidate_range(dest_blob->code_begin(), dest_blob->code_size());
748751
}
749752

750753
// Move all my code into another code buffer. Consult applicable

src/hotspot/share/code/codeBlob.cpp

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -331,13 +331,7 @@ RuntimeBlob::RuntimeBlob(
331331
: CodeBlob(name, kind, cb, size, header_size, frame_complete, frame_size, oop_maps, caller_must_gc_arguments,
332332
align_up(cb->total_relocation_size(), oopSize))
333333
{
334-
if (code_size() == 0) {
335-
// Nothing to copy
336-
return;
337-
}
338-
339334
cb->copy_code_and_locs_to(this);
340-
ICache::invalidate_range(code_begin(), code_size());
341335
}
342336

343337
void RuntimeBlob::free(RuntimeBlob* blob) {

0 commit comments

Comments
 (0)