1 /*
   2  * Copyright (c) 2006, 2009, 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 "incls/_precompiled.incl"
  26 # include "incls/_vm_version_solaris_sparc.cpp.incl"
  27 
  28 # include <sys/auxv.h>
  29 # include <sys/auxv_SPARC.h>
  30 # include <sys/systeminfo.h>
  31 
  32 // We need to keep these here as long as we have to build on Solaris
  33 // versions before 10.
  34 #ifndef SI_ARCHITECTURE_32
  35 #define SI_ARCHITECTURE_32      516     /* basic 32-bit SI_ARCHITECTURE */
  36 #endif
  37 
  38 #ifndef SI_ARCHITECTURE_64
  39 #define SI_ARCHITECTURE_64      517     /* basic 64-bit SI_ARCHITECTURE */
  40 #endif
  41 
  42 static void do_sysinfo(int si, const char* string, int* features, int mask) {
  43   char   tmp;
  44   size_t bufsize = sysinfo(si, &tmp, 1);
  45 
  46   // All SI defines used below must be supported.
  47   guarantee(bufsize != -1, "must be supported");
  48 
  49   char* buf = (char*) malloc(bufsize);
  50 
  51   if (buf == NULL)
  52     return;
  53 
  54   if (sysinfo(si, buf, bufsize) == bufsize) {
  55     // Compare the string.
  56     if (strcmp(buf, string) == 0) {
  57       *features |= mask;
  58     }
  59   }
  60 
  61   free(buf);
  62 }
  63 
  64 int VM_Version::platform_features(int features) {
  65   // getisax(2), SI_ARCHITECTURE_32, and SI_ARCHITECTURE_64 are
  66   // supported on Solaris 10 and later.
  67   if (os::Solaris::supports_getisax()) {
  68 #ifndef PRODUCT
  69     if (PrintMiscellaneous && Verbose)
  70       tty->print_cr("getisax(2) supported.");
  71 #endif
  72 
  73     // Check 32-bit architecture.
  74     do_sysinfo(SI_ARCHITECTURE_32, "sparc", &features, v8_instructions_m);
  75 
  76     // Check 64-bit architecture.
  77     do_sysinfo(SI_ARCHITECTURE_64, "sparcv9", &features, generic_v9_m);
  78 
  79     // Extract valid instruction set extensions.
  80     uint_t av;
  81     uint_t avn = os::Solaris::getisax(&av, 1);
  82     assert(avn == 1, "should only return one av");
  83 
  84     if (av & AV_SPARC_MUL32)  features |= hardware_mul32_m;
  85     if (av & AV_SPARC_DIV32)  features |= hardware_div32_m;
  86     if (av & AV_SPARC_FSMULD) features |= hardware_fsmuld_m;
  87     if (av & AV_SPARC_V8PLUS) features |= v9_instructions_m;
  88     if (av & AV_SPARC_POPC)   features |= hardware_popc_m;
  89     if (av & AV_SPARC_VIS)    features |= vis1_instructions_m;
  90     if (av & AV_SPARC_VIS2)   features |= vis2_instructions_m;
  91   } else {
  92     // getisax(2) failed, use the old legacy code.
  93 #ifndef PRODUCT
  94     if (PrintMiscellaneous && Verbose)
  95       tty->print_cr("getisax(2) not supported.");
  96 #endif
  97 
  98     char   tmp;
  99     size_t bufsize = sysinfo(SI_ISALIST, &tmp, 1);
 100     char*  buf     = (char*) malloc(bufsize);
 101 
 102     if (buf != NULL) {
 103       if (sysinfo(SI_ISALIST, buf, bufsize) == bufsize) {
 104         // Figure out what kind of sparc we have
 105         char *sparc_string = strstr(buf, "sparc");
 106         if (sparc_string != NULL) {              features |= v8_instructions_m;
 107           if (sparc_string[5] == 'v') {
 108             if (sparc_string[6] == '8') {
 109               if (sparc_string[7] == '-') {      features |= hardware_mul32_m;
 110                                                  features |= hardware_div32_m;
 111               } else if (sparc_string[7] == 'p') features |= generic_v9_m;
 112               else                               features |= generic_v8_m;
 113             } else if (sparc_string[6] == '9')   features |= generic_v9_m;
 114           }
 115         }
 116 
 117         // Check for visualization instructions
 118         char *vis = strstr(buf, "vis");
 119         if (vis != NULL) {                       features |= vis1_instructions_m;
 120           if (vis[3] == '2')                     features |= vis2_instructions_m;
 121         }
 122       }
 123       free(buf);
 124     }
 125   }
 126 
 127   // Determine the machine type.
 128   do_sysinfo(SI_MACHINE, "sun4v", &features, sun4v_m);
 129 
 130   return features;
 131 }