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 }