1 /* 2 * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. 3 * Copyright (c) 2015, Red Hat Inc. All rights reserved. 4 * Copyright (c) 2015, Linaro Ltd. All rights reserved. 5 * Copyright (c) 2015-2018, Azul Systems, Inc. All rights reserved. 6 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 7 * 8 * This code is free software; you can redistribute it and/or modify it 9 * under the terms of the GNU General Public License version 2 only, as 10 * published by the Free Software Foundation. 11 * 12 * This code is distributed in the hope that it will be useful, but WITHOUT 13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15 * version 2 for more details (a copy is included in the LICENSE file that 16 * accompanied this code). 17 * 18 * You should have received a copy of the GNU General Public License version 19 * 2 along with this work; if not, write to the Free Software Foundation, 20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 21 * 22 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 23 * or visit www.oracle.com if you need additional information or have any 24 * questions. 25 * 26 */ 27 28 #include "precompiled.hpp" 29 #include "asm/macroAssembler.hpp" 30 #include "asm/macroAssembler.inline.hpp" 31 #include "memory/resourceArea.hpp" 32 #include "runtime/java.hpp" 33 #include "runtime/stubCodeGenerator.hpp" 34 #include "utilities/macros.hpp" 35 #include "vm_version_aarch32.hpp" 36 #include "compiler/disassembler.hpp" 37 38 #include OS_HEADER_INLINE(os) 39 40 // Next function in another compilation unit to prevent inlining and 41 // breaking frame size check 42 extern int aarch32_get_fp_sp_distance(); 43 44 enum ProcessorFeatures VM_Version::_features = FT_NONE; 45 46 static BufferBlob* stub_blob; 47 static const int stub_size = 550; 48 volatile bool VM_Version::_is_determine_features_test_running = false; 49 50 extern "C" { 51 typedef void (*getPsrInfo_stub_t)(void*); 52 } 53 static getPsrInfo_stub_t getPsrInfo_stub = NULL; 54 55 typedef unsigned long (*pgetauxval)(unsigned long type); 56 57 bool VM_Version::identify_procline(const char *tag, char **line) { 58 char *i = *line; 59 const char EOT = '\t', EOT2 = ':'; // the longest has no tabs 60 for (; '\0' != *i && EOT != *i && EOT2 != *i; i++); 61 if (EOT == *i || EOT2 == *i) { 62 if (!memcmp(*line, tag, i - *line)) { 63 for (i++; (EOT == *i || EOT2 == *i || ' ' == *i) && '\0' != *i; i++); 64 if ('\0' != *i) { 65 *line = i; 66 return true; 67 } 68 } 69 } 70 return false; 71 } 72 73 void VM_Version::get_processor_features() { 74 _supports_cx8 = true; 75 _supports_atomic_getset4 = true; 76 _supports_atomic_getadd4 = true; 77 _supports_atomic_getset8 = true; 78 _supports_atomic_getadd8 = true; 79 80 if (FLAG_IS_DEFAULT(AllocatePrefetchDistance)) 81 FLAG_SET_DEFAULT(AllocatePrefetchDistance, 256); 82 if (FLAG_IS_DEFAULT(AllocatePrefetchStepSize)) 83 FLAG_SET_DEFAULT(AllocatePrefetchStepSize, 64); 84 FLAG_SET_DEFAULT(PrefetchScanIntervalInBytes, 256); 85 FLAG_SET_DEFAULT(PrefetchFieldsAhead, 256); 86 FLAG_SET_DEFAULT(PrefetchCopyIntervalInBytes, 256); 87 88 enum ProcessorFeatures f = FT_NONE; 89 90 // Allocate space for the code. 91 const int code_size = 11 * Assembler::instruction_size; 92 ResourceMark rm; 93 CodeBuffer cb("detect_cpu_features", code_size, 0); 94 MacroAssembler* a = new MacroAssembler(&cb); 95 jlong test_area; 96 97 // Must be set to true so we can generate the test code. 98 _features = FT_ALL; 99 // Emit code. 100 uint32_t *const code = (uint32_t *)a->pc(); 101 void (*test)(address addr, uintptr_t offset)=(void(*)(address addr, uintptr_t nonzero))(void *)code; 102 103 a->udiv(r3, r2, r1); // FT_HW_DIVIDE 104 a->bfc(r1, 1, 1); // FT_ARMV6T2 105 a->vneg_f64(d0, d0); // FT_VFPV2 106 a->vmov_f64(d0, 1.); // FT_VFPV3 107 a->dmb(Assembler::ISH); // FT_ARMV7 108 a->ldrexd(r2, r0); // FT_ARMV6K 109 a->vmov_f64(d0, 0.0); // FT_AdvSIMD 110 a->crc32b(r3, r2, r1); // FT_CRC32 111 a->vmov_f64(d16, 1.); // FT_VFPV3D32 112 a->pldw(Address(r0)); // FT_MP_EXT 113 a->aese(q0, q0); // FT_AES 114 a->b(lr); 115 116 uint32_t *const code_end = (uint32_t *)a->pc(); 117 a->flush(); 118 _features = FT_NONE; 119 120 // Print the detection code. 121 if (PrintAssembly) { 122 ttyLocker ttyl; 123 tty->print_cr("Decoding cpu-feature detection stub at " INTPTR_FORMAT " before execution:", p2i(code)); 124 Disassembler::decode((u_char*)code, (u_char*)code_end, tty); 125 } 126 // Execute code. Illegal instructions will be replaced by 0 in the signal handler. 127 VM_Version::_is_determine_features_test_running = true; 128 (*test)((address)&test_area, 1); 129 VM_Version::_is_determine_features_test_running = false; 130 131 uint32_t *insn = code; 132 if (*insn++ != Assembler::nop_insn) f = (ProcessorFeatures) (f | FT_HW_DIVIDE); 133 if (*insn++ != Assembler::nop_insn) f = (ProcessorFeatures) (f | FT_ARMV6T2); 134 if (*insn++ != Assembler::nop_insn) f = (ProcessorFeatures) (f | FT_VFPV2); 135 if (*insn++ != Assembler::nop_insn) f = (ProcessorFeatures) (f | FT_VFPV3); 136 if (*insn++ != Assembler::nop_insn) f = (ProcessorFeatures) (f | FT_ARMV7); 137 if (*insn++ != Assembler::nop_insn) f = (ProcessorFeatures) (f | FT_ARMV6K); 138 if (*insn++ != Assembler::nop_insn) f = (ProcessorFeatures) (f | FT_AdvSIMD); 139 if (*insn++ != Assembler::nop_insn) f = (ProcessorFeatures) (f | FT_CRC32); 140 if (*insn++ != Assembler::nop_insn) f = (ProcessorFeatures) (f | FT_VFPV3D32); 141 if (*insn++ != Assembler::nop_insn) f = (ProcessorFeatures) (f | FT_MP_EXT); 142 if (*insn++ != Assembler::nop_insn) f = (ProcessorFeatures) (f | FT_AES); 143 144 int ncores = 0, cpu = 0, variant = 0, model = 0, revision = 0; 145 char buf[2048], *i; 146 if (FILE * fp = fopen("/proc/cpuinfo", "r")) { 147 while ((i = fgets(buf, 2048, fp))) { 148 if (identify_procline("processor", &i)) { 149 ncores++; 150 } else if (identify_procline("CPU implementer", &i)) { 151 cpu = strtol(i, NULL, 0); 152 } else if (identify_procline("CPU variant", &i)) { 153 variant = strtol(i, NULL, 0); 154 } else if (identify_procline("CPU part", &i)) { 155 model = strtol(i, NULL, 0); 156 } else if (identify_procline("CPU revision", &i)) { 157 revision = strtol(i, NULL, 0); 158 } 159 } 160 fclose(fp); 161 } 162 if (1 == ncores) { 163 f = (ProcessorFeatures) (f | FT_SINGLE_CORE); 164 } 165 166 sprintf(buf, "0x%02x:0x%x:0x%03x:%d", cpu, variant, model, revision); 167 if (f & FT_VFPV2) strcat(buf, ", vfp"); 168 if (f & FT_VFPV3) strcat(buf, ", vfpv3"); 169 if (f & FT_VFPV3D32) strcat(buf, ", vfpd32"); 170 if (f & FT_AdvSIMD) strcat(buf, ", simd, neon"); 171 if (f & FT_CRC32) strcat(buf, ", crc"); 172 if (f & FT_AES) strcat(buf, ", aes"); 173 174 _features_string = os::strdup(buf); 175 176 if (FLAG_IS_DEFAULT(UseCRC32)) { 177 UseCRC32 = (f & FT_CRC32) != 0; 178 } 179 if (UseCRC32 && (f & FT_CRC32) == 0) { 180 warning("UseCRC32 specified, but not supported on this CPU"); 181 FLAG_SET_DEFAULT(UseCRC32, false); 182 } 183 if (FLAG_IS_DEFAULT(UseCRC32Intrinsics)) { 184 FLAG_SET_DEFAULT(UseCRC32Intrinsics, true); 185 } 186 if (FLAG_IS_DEFAULT(UseCRC32CIntrinsics)) { 187 FLAG_SET_DEFAULT(UseCRC32CIntrinsics, true); 188 } 189 if ((f & FT_AdvSIMD) && FLAG_IS_DEFAULT(UseNeon) && (model & ~0x0f0) >= 0xc08) { 190 UseNeon = true; 191 } 192 _features = f; 193 194 #ifdef COMPILER2 195 if (FLAG_IS_DEFAULT(UseMultiplyToLenIntrinsic)) { 196 FLAG_SET_DEFAULT(UseMultiplyToLenIntrinsic, true); 197 } 198 #endif // COMPILER2 199 200 if (f & FT_AdvSIMD) { // don't use UseNeon since Montgomery intrinsics are benefitial even on Cortex-A7 201 if (FLAG_IS_DEFAULT(UseMontgomeryMultiplyIntrinsic)) { 202 FLAG_SET_DEFAULT(UseMontgomeryMultiplyIntrinsic, true); 203 } 204 if (FLAG_IS_DEFAULT(UseMontgomerySquareIntrinsic)) { 205 FLAG_SET_DEFAULT(UseMontgomerySquareIntrinsic, true); 206 } 207 } else { 208 if (UseMontgomeryMultiplyIntrinsic || UseMontgomerySquareIntrinsic) { 209 warning("Montgomery intrinsics are not available on this CPU"); 210 FLAG_SET_DEFAULT(UseMontgomeryMultiplyIntrinsic, false); 211 FLAG_SET_DEFAULT(UseMontgomerySquareIntrinsic, false); 212 } 213 } 214 215 if (FLAG_IS_DEFAULT(UseSIMDForMemoryOps) && (f & (FT_VFPV2 | FT_AdvSIMD))) { 216 FLAG_SET_DEFAULT(UseSIMDForMemoryOps, true); 217 } 218 219 /* if (FLAG_IS_DEFAULT(UseBarriersForVolatile)) { 220 UseBarriersForVolatile = (_cpuFeatures & CPU_DMB_ATOMICS) != 0; 221 }*/ 222 223 /*if(!(f & FT_ARMV7) && FLAG_IS_DEFAULT(UseMembar)) { 224 UseMembar = false; 225 } else if(UseMembar) { 226 fprintf(stderr, "Unable to use memory barriers as not on ARMv7, disabling.\n"); 227 UseMembar = false; 228 }*/ 229 if (UseAES) { 230 if ((f & FT_AES) == 0) 231 warning("UseAES specified, but not supported on this CPU"); 232 else 233 warning("UseAES specified, but not supported"); 234 FLAG_SET_DEFAULT(UseAES, false); 235 } 236 if (FLAG_IS_DEFAULT(UseAESIntrinsics)) { 237 UseAESIntrinsics = true; 238 } 239 240 if (UseSHA) { 241 warning("SHA instructions are not available on this CPU"); 242 FLAG_SET_DEFAULT(UseSHA, false); 243 } 244 if (f & FT_AdvSIMD) { 245 if(FLAG_IS_DEFAULT(UseSHA1Intrinsics)) { 246 FLAG_SET_DEFAULT(UseSHA1Intrinsics, true); 247 } 248 if(FLAG_IS_DEFAULT(UseSHA256Intrinsics)) { 249 FLAG_SET_DEFAULT(UseSHA256Intrinsics, true); 250 } 251 if(FLAG_IS_DEFAULT(UseSHA512Intrinsics)) { 252 FLAG_SET_DEFAULT(UseSHA512Intrinsics, true); 253 } 254 } else if (UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics) { 255 warning("SHA intrinsics are not available on this CPU"); 256 FLAG_SET_DEFAULT(UseSHA1Intrinsics, false); 257 FLAG_SET_DEFAULT(UseSHA256Intrinsics, false); 258 FLAG_SET_DEFAULT(UseSHA512Intrinsics, false); 259 } 260 261 } 262 263 static bool get_is_thumb() { 264 intptr_t x, y; 265 asm ("mov %0, pc\n" 266 "mov %1, pc": "=r"(x), "=r"(y)); 267 return y - x == 2; 268 } 269 270 void VM_Version::initialize() { 271 ResourceMark rm; 272 273 stub_blob = BufferBlob::create("getPsrInfo_stub", stub_size); 274 if (stub_blob == NULL) { 275 vm_exit_during_initialization("Unable to allocate getPsrInfo_stub"); 276 } 277 278 get_processor_features(); 279 280 const bool thumb = get_is_thumb(); 281 282 if (FLAG_IS_DEFAULT(VMFrameAPCS)) { 283 if (thumb) { 284 FLAG_SET_DEFAULT(VMFrameAPCS, false); 285 } else { 286 const int fp_sp_dist = aarch32_get_fp_sp_distance(); 287 // mov r12, sp 288 // push {r11, r12, lr, pc} 289 // sub r11, r12, #4 290 const int apcs_dist = 12; 291 292 assert((0 <= fp_sp_dist) && (fp_sp_dist % 4 == 0), "fp/sp sanity check"); 293 assert(fp_sp_dist <= 16, "Assume leaf function should not save many registers in prolog"); 294 295 FLAG_SET_DEFAULT(VMFrameAPCS, fp_sp_dist == apcs_dist); 296 } 297 } 298 299 if (FLAG_IS_DEFAULT(JNIFrameAPCS)) { 300 FLAG_SET_DEFAULT(JNIFrameAPCS, VMFrameAPCS); 301 } 302 303 // This machine does not allow a lot of forms of unaligned memory accesses 304 if (FLAG_IS_DEFAULT(UseUnalignedAccesses)) { 305 FLAG_SET_DEFAULT(UseUnalignedAccesses, false); 306 } 307 308 if (FrameAPCS && !FLAG_IS_DEFAULT(PreserveFramePointer) && !PreserveFramePointer) { 309 warning("FrameAPCS enabled, so fp will always hold frame pointer, ignoring disabled PreserveFramePointer!"); 310 } 311 312 if (thumb && (VMFrameAPCS || JNIFrameAPCS)) { 313 warning("VM and JNI APCS support is not available when VM is built in Thumb mode"); 314 } 315 316 FLAG_SET_DEFAULT(CriticalJNINatives, false); 317 #ifndef HARD_FLOAT_CC 318 if( !(VM_Version::features() & (FT_VFPV2 | FT_VFPV3)) ) { 319 #ifdef COMPILER2 320 // C2 is only supported on v7+ VFP at this time 321 vm_exit_during_initialization("Server VM is only supported on ARMv7+ VFP"); 322 #else 323 if(FLAG_IS_CMDLINE(UseFPU)) { 324 warning("FPU is not present on this core"); 325 } 326 FLAG_SET_DEFAULT(UseFPU, false); 327 #endif 328 } 329 #endif 330 331 #ifdef COMPILER2 332 if ( !(VM_Version::features() & FT_ARMV7) ) { 333 // C2 is only supported on v7+ VFP at this time 334 vm_exit_during_initialization("Server VM is only supported on ARMv7+"); 335 } 336 337 FLAG_SET_DEFAULT(UseFPUForSpilling, true); 338 339 if (FLAG_IS_DEFAULT(MaxVectorSize)) { 340 // FLAG_SET_DEFAULT(MaxVectorSize, has_simd() ? 16 : 8); 341 // SIMD/NEON can use 16, but default is 8 because currently 342 // larger than 8 will disable instruction scheduling 343 FLAG_SET_DEFAULT(MaxVectorSize, 8); 344 } 345 346 if (MaxVectorSize > 16) { 347 FLAG_SET_DEFAULT(MaxVectorSize, 8); 348 } 349 #endif 350 351 UNSUPPORTED_OPTION(CriticalJNINatives); 352 }