src/cpu/mips/vm/vm_version_mips.cpp

Thu, 05 Sep 2019 13:07:31 +0800

author
aoqi
date
Thu, 05 Sep 2019 13:07:31 +0800
changeset 9644
3089aa0aa0ee
parent 9639
38d2ba487173
child 9808
a9451177555c
permissions
-rw-r--r--

#9372 Refactor VM_Version, removed UseLoongsonISA and Use3A3000, added UseLEXT1, UseLEXT2, UseLEXT3.
Summary: used cpucfg to detect cpu features
Reviewed-by: wanghaomin

     1 /*
     2  * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
     3  * Copyright (c) 2015, 2019, Loongson Technology. 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  */
    26 #include "precompiled.hpp"
    27 #include "asm/macroAssembler.hpp"
    28 #include "asm/macroAssembler.inline.hpp"
    29 #include "memory/resourceArea.hpp"
    30 #include "runtime/java.hpp"
    31 #include "runtime/stubCodeGenerator.hpp"
    32 #include "vm_version_mips.hpp"
    33 #ifdef TARGET_OS_FAMILY_linux
    34 # include "os_linux.inline.hpp"
    35 #endif
    37 int VM_Version::_cpuFeatures;
    38 const char* VM_Version::_features_str = "";
    39 VM_Version::CpuidInfo VM_Version::_cpuid_info   = { 0, };
    40 volatile bool VM_Version::_is_determine_cpucfg_supported_running = false;
    41 bool VM_Version::_is_cpucfg_instruction_supported = true;
    42 bool VM_Version::_cpu_info_is_initialized = false;
    44 static BufferBlob* stub_blob;
    45 static const int stub_size = 600;
    47 extern "C" {
    48   typedef void (*get_cpu_info_stub_t)(void*);
    49 }
    50 static get_cpu_info_stub_t get_cpu_info_stub = NULL;
    53 class VM_Version_StubGenerator: public StubCodeGenerator {
    54  public:
    56   VM_Version_StubGenerator(CodeBuffer *c) : StubCodeGenerator(c) {}
    58   address generate_get_cpu_info() {
    59     assert(!VM_Version::cpu_info_is_initialized(), "VM_Version should not be initialized");
    60     StubCodeMark mark(this, "VM_Version", "get_cpu_info_stub");
    61 #   define __ _masm->
    63     address start = __ pc();
    65     __ enter();
    66     __ push(AT);
    67     __ push(V0);
    69     __ li(AT, (long)0);
    70     __ cpucfg(V0, AT);
    71     __ lw(AT, A0, in_bytes(VM_Version::Loongson_Cpucfg_id0_offset()));
    72     __ sw(V0, A0, in_bytes(VM_Version::Loongson_Cpucfg_id0_offset()));
    74     __ li(AT, 1);
    75     __ cpucfg(V0, AT);
    76     __ lw(AT, A0, in_bytes(VM_Version::Loongson_Cpucfg_id1_offset()));
    77     __ sw(V0, A0, in_bytes(VM_Version::Loongson_Cpucfg_id1_offset()));
    79     __ li(AT, 2);
    80     __ cpucfg(V0, AT);
    81     __ lw(AT, A0, in_bytes(VM_Version::Loongson_Cpucfg_id2_offset()));
    82     __ sw(V0, A0, in_bytes(VM_Version::Loongson_Cpucfg_id2_offset()));
    84     __ pop(V0);
    85     __ pop(AT);
    86     __ leave();
    87     __ jr(RA);
    88     __ delayed()->nop();
    89 #   undef __
    91     return start;
    92   };
    93 };
    95 uint32_t VM_Version::get_feature_flags_by_cpucfg() {
    96   uint32_t result = 0;
    97   if (_cpuid_info.cpucfg_info_id1.bits.MMI != 0)
    98     result |= CPU_MMI;
    99   if (_cpuid_info.cpucfg_info_id1.bits.MSA1 != 0)
   100     result |= CPU_MSA1_0;
   101   if (_cpuid_info.cpucfg_info_id1.bits.MSA2 != 0)
   102     result |= CPU_MSA2_0;
   103   if (_cpuid_info.cpucfg_info_id1.bits.CGP != 0)
   104     result |= CPU_CGP;
   105   if (_cpuid_info.cpucfg_info_id1.bits.LSX1 != 0)
   106     result |= CPU_LSX1;
   107   if (_cpuid_info.cpucfg_info_id1.bits.LSX2 != 0)
   108     result |= CPU_LSX2;
   109   if (_cpuid_info.cpucfg_info_id1.bits.LASX != 0)
   110     result |= CPU_LASX;
   111   if (_cpuid_info.cpucfg_info_id1.bits.LLSYNC != 0)
   112     result |= CPU_LLSYNC;
   113   if (_cpuid_info.cpucfg_info_id1.bits.TGTSYNC != 0)
   114     result |= CPU_TGTSYNC;
   115   if (_cpuid_info.cpucfg_info_id1.bits.MUALP != 0)
   116     result |= CPU_MUALP;
   117   if (_cpuid_info.cpucfg_info_id2.bits.LEXT1 != 0)
   118     result |= CPU_LEXT1;
   119   if (_cpuid_info.cpucfg_info_id2.bits.LEXT2 != 0)
   120     result |= CPU_LEXT2;
   121   if (_cpuid_info.cpucfg_info_id2.bits.LEXT3 != 0)
   122     result |= CPU_LEXT3;
   123   if (_cpuid_info.cpucfg_info_id2.bits.LAMO != 0)
   124     result |= CPU_LAMO;
   125   if (_cpuid_info.cpucfg_info_id2.bits.LPIXU != 0)
   126     result |= CPU_LPIXU;
   128   result |= CPU_ULSYNC;
   130   return result;
   131 }
   133 void read_cpu_info(const char *path, char *result) {
   134   FILE *ptr;
   135   char buf[1024];
   136   int i = 0;
   137   if((ptr=fopen(path, "r")) != NULL) {
   138     while(fgets(buf, 1024, ptr)!=NULL) {
   139       strcat(result,buf);
   140       i++;
   141       if (i == 10) break;
   142     }
   143     fclose(ptr);
   144   } else {
   145     warning("Can't detect CPU info - cannot open %s", path);
   146   }
   147 }
   149 void strlwr(char *str) {
   150   for (; *str!='\0'; str++)
   151     *str = tolower(*str);
   152 }
   154 int VM_Version::get_feature_flags_by_cpuinfo(int features) {
   155   assert(!cpu_info_is_initialized(), "VM_Version should not be initialized");
   157   char res[10240];
   158   int i;
   159   memset(res, '\0', 10240 * sizeof(char));
   160   read_cpu_info("/proc/cpuinfo", res);
   161   // res is converted to lower case
   162   strlwr(res);
   164   if (strstr(res, "loongson")) {
   165     // Loongson CPU
   166     features |= CPU_LOONGSON;
   168     const struct Loongson_Cpuinfo loongson_cpuinfo[] = {
   169       {L_3A1000,  "3a1000"},
   170       {L_3B1500,  "3b1500"},
   171       {L_3A2000,  "3a2000"},
   172       {L_3B2000,  "3b2000"},
   173       {L_3A3000,  "3a3000"},
   174       {L_3B3000,  "3b3000"},
   175       {L_2K1000,  "2k1000"},
   176       {L_UNKNOWN, "unknown"}
   177     };
   179     // Loongson Family
   180     int detected = 0;
   181     for (i = 0; i <= L_UNKNOWN; i++) {
   182       switch (i) {
   183         // 3A1000 and 3B1500 may use an old kernel and further comparsion is needed
   184         // test PRID REV in /proc/cpuinfo
   185         // 3A1000: V0.5, model name: ICT Loongson-3A V0.5  FPU V0.1
   186         // 3B1500: V0.7, model name: ICT Loongson-3B V0.7  FPU V0.1
   187         case L_3A1000:
   188           if (strstr(res, loongson_cpuinfo[i].match_str) || strstr(res, "loongson-3a v0.5")) {
   189             features |= CPU_LOONGSON_GS464;
   190             detected++;
   191             //tty->print_cr("3A1000 platform");
   192           }
   193           break;
   194         case L_3B1500:
   195           if (strstr(res, loongson_cpuinfo[i].match_str) || strstr(res, "loongson-3b v0.7")) {
   196             features |= CPU_LOONGSON_GS464;
   197             detected++;
   198             //tty->print_cr("3B1500 platform");
   199           }
   200           break;
   201         case L_3A2000:
   202         case L_3B2000:
   203         case L_3A3000:
   204         case L_3B3000:
   205           if (strstr(res, loongson_cpuinfo[i].match_str)) {
   206             features |= CPU_LOONGSON_GS464E;
   207             detected++;
   208             //tty->print_cr("3A2000/3A3000/3B2000/3B3000 platform");
   209           }
   210           break;
   211         case L_2K1000:
   212           if (strstr(res, loongson_cpuinfo[i].match_str)) {
   213             features |= CPU_LOONGSON_GS264;
   214             detected++;
   215             //tty->print_cr("2K1000 platform");
   216           }
   217           break;
   218         case L_UNKNOWN:
   219           if (detected == 0) {
   220             detected++;
   221             //tty->print_cr("unknown Loongson platform");
   222           }
   223           break;
   224         default:
   225           ShouldNotReachHere();
   226       }
   227     }
   228     assert (detected == 1, "one and only one of LOONGSON_CPU_FAMILY should be detected");
   229   } else { // not Loongson
   230     // Not Loongson CPU
   231     //tty->print_cr("MIPS platform");
   232   }
   234   if (features & CPU_LOONGSON_GS264) {
   235     features |= CPU_LEXT1;
   236     features |= CPU_LEXT2;
   237     features |= CPU_TGTSYNC;
   238     features |= CPU_ULSYNC;
   239     features |= CPU_MSA1_0;
   240     features |= CPU_LSX1;
   241   } else if (features & CPU_LOONGSON_GS464) {
   242     features |= CPU_LEXT1;
   243     features |= CPU_LLSYNC;
   244     features |= CPU_TGTSYNC;
   245   } else if (features & CPU_LOONGSON_GS464E) {
   246     features |= CPU_LEXT1;
   247     features |= CPU_LEXT2;
   248     features |= CPU_LEXT3;
   249     features |= CPU_TGTSYNC;
   250     features |= CPU_ULSYNC;
   251   } else if (features & CPU_LOONGSON) {
   252     // unknow loongson
   253     features |= CPU_LLSYNC;
   254     features |= CPU_TGTSYNC;
   255     features |= CPU_ULSYNC;
   256   }
   257   VM_Version::_cpu_info_is_initialized = true;
   259   return features;
   260 }
   262 void VM_Version::get_processor_features() {
   264   clean_cpuFeatures();
   266   // test if cpucfg instruction is supported
   267   VM_Version::_is_determine_cpucfg_supported_running = true;
   268   __asm__ __volatile__(
   269     ".insn \n\t"
   270     ".word (0xc8080118)\n\t" // cpucfg zero, zero
   271     :
   272     :
   273     :
   274     );
   275   VM_Version::_is_determine_cpucfg_supported_running = false;
   277   if (supports_cpucfg()) {
   278     get_cpu_info_stub(&_cpuid_info);
   279     _cpuFeatures = get_feature_flags_by_cpucfg();
   280     // Only Loongson CPUs support cpucfg
   281     _cpuFeatures |= CPU_LOONGSON;
   282   } else {
   283     _cpuFeatures = get_feature_flags_by_cpuinfo(0);
   284   }
   286   _supports_cx8 = true;
   288   if (UseG1GC && FLAG_IS_DEFAULT(MaxGCPauseMillis)) {
   289     FLAG_SET_CMDLINE(uintx, MaxGCPauseMillis, 650);
   290   }
   292 #ifdef COMPILER2
   293   if (MaxVectorSize > 0) {
   294     if (!is_power_of_2(MaxVectorSize)) {
   295       warning("MaxVectorSize must be a power of 2");
   296       MaxVectorSize = 8;
   297     }
   298     if (MaxVectorSize > 0 && supports_ps()) {
   299       MaxVectorSize = 8;
   300     } else {
   301       MaxVectorSize = 0;
   302     }
   303   }
   304   //
   305   // Vector optimization of MIPS works in most cases, but cannot pass hotspot/test/compiler/6340864/TestFloatVect.java.
   306   // Vector optimization was closed by default.
   307   // The reasons:
   308   // 1. The kernel does not have emulation of PS instructions yet, so the emulation of PS instructions must be done in JVM, see JVM_handle_linux_signal.
   309   // 2. It seems the gcc4.4.7 had some bug related to ucontext_t, which is used in signal handler to emulate PS instructions.
   310   //
   311   if (FLAG_IS_DEFAULT(MaxVectorSize)) {
   312     MaxVectorSize = 0;
   313   }
   315 #endif
   317   if (needs_llsync() && needs_tgtsync() && !needs_ulsync()) {
   318     if (FLAG_IS_DEFAULT(UseSyncLevel)) {
   319       FLAG_SET_DEFAULT(UseSyncLevel, 1000);
   320     }
   321   } else if (!needs_llsync() && needs_tgtsync() && needs_ulsync()) {
   322     if (FLAG_IS_DEFAULT(UseSyncLevel)) {
   323       FLAG_SET_DEFAULT(UseSyncLevel, 2000);
   324     }
   325   } else if (needs_llsync() && needs_llsync() && needs_ulsync()) {
   326     if (FLAG_IS_DEFAULT(UseSyncLevel)) {
   327       FLAG_SET_DEFAULT(UseSyncLevel, 3000);
   328     }
   329   } else if (!needs_llsync() && !needs_llsync() && !needs_ulsync()) {
   330     if (FLAG_IS_DEFAULT(UseSyncLevel)) {
   331       FLAG_SET_DEFAULT(UseSyncLevel, 0);
   332     }
   333   } else {
   334     assert(false, "Should Not Reach Here, what is the cpu type?");
   335   }
   337   if (supports_lext1()) {
   338     if (FLAG_IS_DEFAULT(UseLEXT1)) {
   339       FLAG_SET_DEFAULT(UseLEXT1, true);
   340     }
   341   } else if (UseLEXT1) {
   342     warning("LEXT1 instructions are not available on this CPU");
   343     FLAG_SET_DEFAULT(UseLEXT1, false);
   344   }
   346   if (supports_lext2()) {
   347     if (FLAG_IS_DEFAULT(UseLEXT2)) {
   348       FLAG_SET_DEFAULT(UseLEXT2, true);
   349     }
   350   } else if (UseLEXT2) {
   351     warning("LEXT2 instructions are not available on this CPU");
   352     FLAG_SET_DEFAULT(UseLEXT2, false);
   353   }
   355   if (supports_lext3()) {
   356     if (FLAG_IS_DEFAULT(UseLEXT3)) {
   357       FLAG_SET_DEFAULT(UseLEXT3, true);
   358     }
   359   } else if (UseLEXT3) {
   360     warning("LEXT3 instructions are not available on this CPU");
   361     FLAG_SET_DEFAULT(UseLEXT3, false);
   362   }
   364   if (UseLEXT2) {
   365     if (FLAG_IS_DEFAULT(UseCountTrailingZerosInstructionMIPS64)) {
   366       FLAG_SET_DEFAULT(UseCountTrailingZerosInstructionMIPS64, 1);
   367     }
   368   } else if (UseCountTrailingZerosInstructionMIPS64) {
   369     if (!FLAG_IS_DEFAULT(UseCountTrailingZerosInstructionMIPS64))
   370       warning("ctz/dctz instructions are not available on this CPU");
   371     FLAG_SET_DEFAULT(UseCountTrailingZerosInstructionMIPS64, 0);
   372   }
   374   if (TieredCompilation) {
   375     if (!FLAG_IS_DEFAULT(TieredCompilation))
   376       warning("TieredCompilation not supported");
   377     FLAG_SET_DEFAULT(TieredCompilation, false);
   378   }
   380   char buf[256];
   381   bool is_unknown_loongson_cpu = is_loongson() && !is_gs464() && !is_gs464e() && !is_gs264() && !supports_cpucfg();
   383   jio_snprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s, UseSyncLevel:%d",
   384               (is_loongson()           ?  "MIPS-compatible Loongson CPU"  : "MIPS CPU"),
   385               (is_gs464()              ?  ", GS464 (3A1000/3B1500)" : ""),
   386               (is_gs464e()             ?  ", GS464E (3A2000/3A3000/3B2000/3B3000)" : ""),
   387               (is_gs264()              ?  ", GS264 (2K1000)" : ""),
   388               (is_unknown_loongson_cpu ?  ", Unknown Loongson CPU" : ""),
   389               (supports_dsp()          ?  ", dsp" : ""),
   390               (supports_ps()           ?  ", ps" : ""),
   391               (supports_3d()           ?  ", 3d" : ""),
   392               (supports_mmi()          ?  ", mmi" : ""),
   393               (supports_msa1_0()       ?  ", msa1_0" : ""),
   394               (supports_msa2_0()       ?  ", msa2_0" : ""),
   395               (supports_lsx1()         ?  ", lsx1" : ""),
   396               (supports_lsx2()         ?  ", lsx2" : ""),
   397               (supports_lasx()         ?  ", lasx" : ""),
   398               (supports_lext1()        ?  ", lext1" : ""),
   399               (supports_lext2()        ?  ", lext2" : ""),
   400               (supports_lext3()        ?  ", lext3" : ""),
   401               (supports_cgp()          ?  ", aes, crc, sha1, sha256, sha512" : ""),
   402               (supports_lamo()         ?  ", lamo" : ""),
   403               (supports_lpixu()        ?  ", lpixu" : ""),
   404               (needs_llsync()          ?  ", llsync" : ""),
   405               (needs_tgtsync()         ?  ", tgtsync": ""),
   406               (needs_ulsync()          ?  ", ulsync": ""),
   407               (supports_mualp()        ?  ", mualp" : ""),
   408               UseSyncLevel);
   409   _features_str = strdup(buf);
   411   if (FLAG_IS_DEFAULT(AllocatePrefetchStyle)) {
   412     FLAG_SET_DEFAULT(AllocatePrefetchStyle, 1);
   413   }
   415   if (FLAG_IS_DEFAULT(AllocatePrefetchLines)) {
   416     FLAG_SET_DEFAULT(AllocatePrefetchLines, 1);
   417   }
   419   if (FLAG_IS_DEFAULT(AllocatePrefetchStepSize)) {
   420     FLAG_SET_DEFAULT(AllocatePrefetchStepSize, 64);
   421   }
   423   if (FLAG_IS_DEFAULT(AllocatePrefetchDistance)) {
   424     FLAG_SET_DEFAULT(AllocatePrefetchDistance, 64);
   425   }
   427   if (FLAG_IS_DEFAULT(AllocateInstancePrefetchLines)) {
   428     FLAG_SET_DEFAULT(AllocateInstancePrefetchLines, 1);
   429   }
   431   if (UseSHA) {
   432     warning("SHA instructions are not available on this CPU");
   433     FLAG_SET_DEFAULT(UseSHA, false);
   434   }
   436   if (UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics) {
   437     warning("SHA intrinsics are not available on this CPU");
   438     FLAG_SET_DEFAULT(UseSHA1Intrinsics, false);
   439     FLAG_SET_DEFAULT(UseSHA256Intrinsics, false);
   440     FLAG_SET_DEFAULT(UseSHA512Intrinsics, false);
   441   }
   443   if (UseAES) {
   444     if (!FLAG_IS_DEFAULT(UseAES)) {
   445       warning("AES instructions are not available on this CPU");
   446       FLAG_SET_DEFAULT(UseAES, false);
   447     }
   448   }
   450   if (UseCRC32Intrinsics) {
   451     if (!FLAG_IS_DEFAULT(UseCRC32Intrinsics)) {
   452       warning("CRC32Intrinsics instructions are not available on this CPU");
   453       FLAG_SET_DEFAULT(UseCRC32Intrinsics, false);
   454     }
   455   }
   457   if (UseAESIntrinsics) {
   458     if (!FLAG_IS_DEFAULT(UseAESIntrinsics)) {
   459       warning("AES intrinsics are not available on this CPU");
   460       FLAG_SET_DEFAULT(UseAESIntrinsics, false);
   461     }
   462   }
   464   if (FLAG_IS_DEFAULT(UseMontgomeryMultiplyIntrinsic)) {
   465     UseMontgomeryMultiplyIntrinsic = true;
   466   }
   467   if (FLAG_IS_DEFAULT(UseMontgomerySquareIntrinsic)) {
   468     UseMontgomerySquareIntrinsic = true;
   469   }
   471 }
   473 void VM_Version::initialize() {
   474   ResourceMark rm;
   475   // Making this stub must be FIRST use of assembler
   477   stub_blob = BufferBlob::create("get_cpu_info_stub", stub_size);
   478   if (stub_blob == NULL) {
   479     vm_exit_during_initialization("Unable to allocate get_cpu_info_stub");
   480   }
   481   CodeBuffer c(stub_blob);
   482   VM_Version_StubGenerator g(&c);
   483   get_cpu_info_stub = CAST_TO_FN_PTR(get_cpu_info_stub_t,
   484                                      g.generate_get_cpu_info());
   486   get_processor_features();
   487 }

mercurial