1 /*
   2  * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #include "precompiled.hpp"
  26 #include "runtime/os.hpp"
  27 #include "vm_version_sparc.hpp"
  28 
  29 # include <sys/auxv.h>
  30 # include <sys/auxv_SPARC.h>
  31 # include <sys/systeminfo.h>
  32 
  33 // We need to keep these here as long as we have to build on Solaris
  34 // versions before 10.
  35 #ifndef SI_ARCHITECTURE_32
  36 #define SI_ARCHITECTURE_32      516     /* basic 32-bit SI_ARCHITECTURE */
  37 #endif
  38 
  39 #ifndef SI_ARCHITECTURE_64
  40 #define SI_ARCHITECTURE_64      517     /* basic 64-bit SI_ARCHITECTURE */
  41 #endif
  42 
  43 static void do_sysinfo(int si, const char* string, int* features, int mask) {
  44   char   tmp;
  45   size_t bufsize = sysinfo(si, &tmp, 1);
  46 
  47   // All SI defines used below must be supported.
  48   guarantee(bufsize != -1, "must be supported");
  49 
  50   char* buf = (char*) malloc(bufsize);
  51 
  52   if (buf == NULL)
  53     return;
  54 
  55   if (sysinfo(si, buf, bufsize) == bufsize) {
  56     // Compare the string.
  57     if (strcmp(buf, string) == 0) {
  58       *features |= mask;
  59     }
  60   }
  61 
  62   free(buf);
  63 }
  64 
  65 int VM_Version::platform_features(int features) {
  66   // getisax(2), SI_ARCHITECTURE_32, and SI_ARCHITECTURE_64 are
  67   // supported on Solaris 10 and later.
  68   if (os::Solaris::supports_getisax()) {
  69 #ifndef PRODUCT
  70     if (PrintMiscellaneous && Verbose)
  71       tty->print_cr("getisax(2) supported.");
  72 #endif
  73 
  74     // Check 32-bit architecture.
  75     do_sysinfo(SI_ARCHITECTURE_32, "sparc", &features, v8_instructions_m);
  76 
  77     // Check 64-bit architecture.
  78     do_sysinfo(SI_ARCHITECTURE_64, "sparcv9", &features, generic_v9_m);
  79 
  80     // Extract valid instruction set extensions.
  81     uint_t av;
  82     uint_t avn = os::Solaris::getisax(&av, 1);
  83     assert(avn == 1, "should only return one av");
  84 
  85     if (av & AV_SPARC_MUL32)  features |= hardware_mul32_m;
  86     if (av & AV_SPARC_DIV32)  features |= hardware_div32_m;
  87     if (av & AV_SPARC_FSMULD) features |= hardware_fsmuld_m;
  88     if (av & AV_SPARC_V8PLUS) features |= v9_instructions_m;
  89     if (av & AV_SPARC_POPC)   features |= hardware_popc_m;
  90     if (av & AV_SPARC_VIS)    features |= vis1_instructions_m;
  91     if (av & AV_SPARC_VIS2)   features |= vis2_instructions_m;
  92   } else {
  93     // getisax(2) failed, use the old legacy code.
  94 #ifndef PRODUCT
  95     if (PrintMiscellaneous && Verbose)
  96       tty->print_cr("getisax(2) not supported.");
  97 #endif
  98 
  99     char   tmp;
 100     size_t bufsize = sysinfo(SI_ISALIST, &tmp, 1);
 101     char*  buf     = (char*) malloc(bufsize);
 102 
 103     if (buf != NULL) {
 104       if (sysinfo(SI_ISALIST, buf, bufsize) == bufsize) {
 105         // Figure out what kind of sparc we have
 106         char *sparc_string = strstr(buf, "sparc");
 107         if (sparc_string != NULL) {              features |= v8_instructions_m;
 108           if (sparc_string[5] == 'v') {
 109             if (sparc_string[6] == '8') {
 110               if (sparc_string[7] == '-') {      features |= hardware_mul32_m;
 111                                                  features |= hardware_div32_m;
 112               } else if (sparc_string[7] == 'p') features |= generic_v9_m;
 113               else                               features |= generic_v8_m;
 114             } else if (sparc_string[6] == '9')   features |= generic_v9_m;
 115           }
 116         }
 117 
 118         // Check for visualization instructions
 119         char *vis = strstr(buf, "vis");
 120         if (vis != NULL) {                       features |= vis1_instructions_m;
 121           if (vis[3] == '2')                     features |= vis2_instructions_m;
 122         }
 123       }
 124       free(buf);
 125     }
 126   }
 127 
 128   // Determine the machine type.
 129   do_sysinfo(SI_MACHINE, "sun4v", &features, sun4v_m);
 130 
 131   return features;
 132 }