1 /* 2 * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. 3 * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 * 24 */ 25 26 #ifndef CPU_AARCH64_VM_VERSION_AARCH64_HPP 27 #define CPU_AARCH64_VM_VERSION_AARCH64_HPP 28 29 #include "spin_wait_aarch64.hpp" 30 #include "runtime/abstract_vm_version.hpp" 31 #include "utilities/sizes.hpp" 32 33 class stringStream; 34 35 #define BIT_MASK(flag) (1ULL<<(flag)) 36 37 class VM_Version : public Abstract_VM_Version { 38 friend class VMStructs; 39 friend class JVMCIVMStructs; 40 41 protected: 42 static int _cpu; 43 static int _model; 44 static int _model2; 45 static int _variant; 46 static int _revision; 47 static int _stepping; 48 49 static int _zva_length; 50 static int _dcache_line_size; 51 static int _icache_line_size; 52 static int _initial_sve_vector_length; 53 static int _max_supported_sve_vector_length; 54 static bool _rop_protection; 55 static uintptr_t _pac_mask; 56 57 static SpinWait _spin_wait; 58 59 // Read additional info using OS-specific interfaces 60 static void get_os_cpu_info(); 61 62 // Sets the SVE length and returns a new actual value or negative on error. 63 // If the len is larger than the system largest supported SVE vector length, 64 // the function sets the largest supported value. 65 static int set_and_get_current_sve_vector_length(int len); 66 static int get_current_sve_vector_length(); 67 68 static void insert_features_names(uint64_t features, stringStream& ss); 69 70 public: 71 // Initialization 72 static void initialize(); 73 static void check_virtualizations(); 74 75 static void print_platform_virtualization_info(outputStream*); 76 77 // Asserts 78 static void assert_is_initialized() { 79 } 80 81 static bool expensive_load(int ld_size, int scale) { 82 if (cpu_family() == CPU_ARM) { 83 // Half-word load with index shift by 1 (aka scale is 2) has 84 // extra cycle latency, e.g. ldrsh w0, [x1,w2,sxtw #1]. 85 if (ld_size == 2 && scale == 2) { 86 return true; 87 } 88 } 89 return false; 90 } 91 92 // The CPU implementer codes can be found in 93 // ARM Architecture Reference Manual ARMv8, for ARMv8-A architecture profile 94 // https://developer.arm.com/docs/ddi0487/latest 95 // Arm can assign codes that are not published in the manual. 96 // Apple's code is defined in 97 // https://github.com/apple/darwin-xnu/blob/33eb983/osfmk/arm/cpuid.h#L62 98 enum Family { 99 CPU_AMPERE = 0xC0, 100 CPU_ARM = 'A', 101 CPU_BROADCOM = 'B', 102 CPU_CAVIUM = 'C', 103 CPU_DEC = 'D', 104 CPU_HISILICON = 'H', 105 CPU_INFINEON = 'I', 106 CPU_MOTOROLA = 'M', 107 CPU_NVIDIA = 'N', 108 CPU_AMCC = 'P', 109 CPU_QUALCOM = 'Q', 110 CPU_MARVELL = 'V', 111 CPU_INTEL = 'i', 112 CPU_APPLE = 'a', 113 }; 114 115 enum Ampere_CPU_Model { 116 CPU_MODEL_EMAG = 0x0, /* CPU implementer is CPU_AMCC */ 117 CPU_MODEL_ALTRA = 0xd0c, /* CPU implementer is CPU_ARM, Neoverse N1 */ 118 CPU_MODEL_ALTRAMAX = 0xd0c, /* CPU implementer is CPU_ARM, Neoverse N1 */ 119 CPU_MODEL_AMPERE_1 = 0xac3, /* CPU implementer is CPU_AMPERE */ 120 CPU_MODEL_AMPERE_1A = 0xac4, /* CPU implementer is CPU_AMPERE */ 121 CPU_MODEL_AMPERE_1B = 0xac5 /* AMPERE_1B core Implements ARMv8.7 with CSSC, MTE, SM3/SM4 extensions */ 122 }; 123 124 #define CPU_FEATURE_FLAGS(decl) \ 125 decl(FP, fp, 0) \ 126 decl(ASIMD, asimd, 1) \ 127 decl(EVTSTRM, evtstrm, 2) \ 128 decl(AES, aes, 3) \ 129 decl(PMULL, pmull, 4) \ 130 decl(SHA1, sha1, 5) \ 131 decl(SHA2, sha256, 6) \ 132 decl(CRC32, crc32, 7) \ 133 decl(LSE, lse, 8) \ 134 decl(FPHP, fphp, 9) \ 135 decl(ASIMDHP, asimdhp, 10) \ 136 decl(DCPOP, dcpop, 16) \ 137 decl(SHA3, sha3, 17) \ 138 decl(SHA512, sha512, 21) \ 139 decl(SVE, sve, 22) \ 140 decl(PACA, paca, 30) \ 141 /* flags above must follow Linux HWCAP */ \ 142 decl(SVEBITPERM, svebitperm, 27) \ 143 decl(SVE2, sve2, 28) \ 144 decl(A53MAC, a53mac, 31) 145 146 enum Feature_Flag { 147 #define DECLARE_CPU_FEATURE_FLAG(id, name, bit) CPU_##id = bit, 148 CPU_FEATURE_FLAGS(DECLARE_CPU_FEATURE_FLAG) 149 #undef DECLARE_CPU_FEATURE_FLAG 150 MAX_CPU_FEATURES 151 }; 152 153 STATIC_ASSERT(sizeof(_features) * BitsPerByte >= MAX_CPU_FEATURES); 154 155 static const char* _features_names[MAX_CPU_FEATURES]; 156 157 // Feature identification 158 #define CPU_FEATURE_DETECTION(id, name, bit) \ 159 static bool supports_##name() { return supports_feature(CPU_##id); } 160 CPU_FEATURE_FLAGS(CPU_FEATURE_DETECTION) 161 #undef CPU_FEATURE_DETECTION 162 163 static void set_feature(Feature_Flag flag) { 164 _features |= BIT_MASK(flag); 165 } 166 static void clear_feature(Feature_Flag flag) { 167 _features &= (~BIT_MASK(flag)); 168 } 169 static bool supports_feature(Feature_Flag flag) { 170 return (_features & BIT_MASK(flag)) != 0; 171 } 172 static bool supports_feature(uint64_t features, Feature_Flag flag) { 173 return (features & BIT_MASK(flag)) != 0; 174 } 175 176 static int cpu_family() { return _cpu; } 177 static int cpu_model() { return _model; } 178 static int cpu_model2() { return _model2; } 179 static int cpu_variant() { return _variant; } 180 static int cpu_revision() { return _revision; } 181 182 static bool model_is(int cpu_model) { 183 return _model == cpu_model || _model2 == cpu_model; 184 } 185 186 static bool is_zva_enabled() { return 0 <= _zva_length; } 187 static int zva_length() { 188 assert(is_zva_enabled(), "ZVA not available"); 189 return _zva_length; 190 } 191 192 static int icache_line_size() { return _icache_line_size; } 193 static int dcache_line_size() { return _dcache_line_size; } 194 static int get_initial_sve_vector_length() { return _initial_sve_vector_length; }; 195 static int get_max_supported_sve_vector_length() { return _max_supported_sve_vector_length; }; 196 197 // Aarch64 supports fast class initialization checks 198 static bool supports_fast_class_init_checks() { return true; } 199 constexpr static bool supports_stack_watermark_barrier() { return true; } 200 constexpr static bool supports_recursive_lightweight_locking() { return true; } 201 202 constexpr static bool supports_secondary_supers_table() { return true; } 203 204 static void get_compatible_board(char *buf, int buflen); 205 206 static const SpinWait& spin_wait_desc() { return _spin_wait; } 207 208 static bool supports_on_spin_wait() { return _spin_wait.inst() != SpinWait::NONE; } 209 210 static bool supports_float16() { return true; } 211 212 #ifdef __APPLE__ 213 // Is the CPU running emulated (for example macOS Rosetta running x86_64 code on M1 ARM (aarch64) 214 static bool is_cpu_emulated(); 215 #endif 216 217 static void initialize_cpu_information(void); 218 219 static bool use_rop_protection() { return _rop_protection; } 220 221 // For common 64/128-bit unpredicated vector operations, we may prefer 222 // emitting NEON instructions rather than the corresponding SVE instructions. 223 static bool use_neon_for_vector(int vector_length_in_bytes) { 224 return vector_length_in_bytes <= 16; 225 } 226 227 static void get_cpu_features_name(void* features_buffer, stringStream& ss); 228 static void get_missing_features_name(void* features_buffer, stringStream& ss); 229 230 // Returns number of bytes required to store cpu features representation 231 static int cpu_features_size(); 232 233 // Stores cpu features representation in the provided buffer. This representation is arch dependent. 234 // Size of the buffer must be same as returned by cpu_features_size() 235 static void store_cpu_features(void* buf); 236 237 static bool supports_features(void* features_to_test); 238 }; 239 240 #endif // CPU_AARCH64_VM_VERSION_AARCH64_HPP