comparison src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp @ 20804:7848fc12602b

Merge with jdk8u40-b25
author Gilles Duboscq <gilles.m.duboscq@oracle.com>
date Tue, 07 Apr 2015 14:58:49 +0200
parents 52b4284cb496 c49cd31b6da6
children
comparison
equal deleted inserted replaced
20184:84105dcdb05b 20804:7848fc12602b
1 /* 1 /*
2 * Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved. 2 * Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 * 4 *
5 * This code is free software; you can redistribute it and/or modify it 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 6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
24 24
25 #include "precompiled.hpp" 25 #include "precompiled.hpp"
26 #include "runtime/os.hpp" 26 #include "runtime/os.hpp"
27 #include "vm_version_sparc.hpp" 27 #include "vm_version_sparc.hpp"
28 28
29 # include <sys/auxv.h> 29 #include <sys/auxv.h>
30 # include <sys/auxv_SPARC.h> 30 #include <sys/auxv_SPARC.h>
31 # include <sys/systeminfo.h> 31 #include <sys/systeminfo.h>
32 # include <kstat.h> 32 #include <kstat.h>
33 #include <picl.h>
34 #include <dlfcn.h>
35 #include <link.h>
36
37 extern "C" static int PICL_get_l1_data_cache_line_size_helper(picl_nodehdl_t nodeh, void *result);
38 extern "C" static int PICL_get_l2_cache_line_size_helper(picl_nodehdl_t nodeh, void *result);
39
40 // Functions from the library we need (signatures should match those in picl.h)
41 extern "C" {
42 typedef int (*picl_initialize_func_t)(void);
43 typedef int (*picl_shutdown_func_t)(void);
44 typedef int (*picl_get_root_func_t)(picl_nodehdl_t *nodehandle);
45 typedef int (*picl_walk_tree_by_class_func_t)(picl_nodehdl_t rooth,
46 const char *classname, void *c_args,
47 int (*callback_fn)(picl_nodehdl_t hdl, void *args));
48 typedef int (*picl_get_prop_by_name_func_t)(picl_nodehdl_t nodeh, const char *nm,
49 picl_prophdl_t *ph);
50 typedef int (*picl_get_propval_func_t)(picl_prophdl_t proph, void *valbuf, size_t sz);
51 typedef int (*picl_get_propinfo_func_t)(picl_prophdl_t proph, picl_propinfo_t *pi);
52 }
53
54 class PICL {
55 // Pointers to functions in the library
56 picl_initialize_func_t _picl_initialize;
57 picl_shutdown_func_t _picl_shutdown;
58 picl_get_root_func_t _picl_get_root;
59 picl_walk_tree_by_class_func_t _picl_walk_tree_by_class;
60 picl_get_prop_by_name_func_t _picl_get_prop_by_name;
61 picl_get_propval_func_t _picl_get_propval;
62 picl_get_propinfo_func_t _picl_get_propinfo;
63 // Handle to the library that is returned by dlopen
64 void *_dl_handle;
65
66 bool open_library();
67 void close_library();
68
69 template<typename FuncType> bool bind(FuncType& func, const char* name);
70 bool bind_library_functions();
71
72 // Get a value of the integer property. The value in the tree can be either 32 or 64 bit
73 // depending on the platform. The result is converted to int.
74 int get_int_property(picl_nodehdl_t nodeh, const char* name, int* result) {
75 picl_propinfo_t pinfo;
76 picl_prophdl_t proph;
77 if (_picl_get_prop_by_name(nodeh, name, &proph) != PICL_SUCCESS ||
78 _picl_get_propinfo(proph, &pinfo) != PICL_SUCCESS) {
79 return PICL_FAILURE;
80 }
81
82 if (pinfo.type != PICL_PTYPE_INT && pinfo.type != PICL_PTYPE_UNSIGNED_INT) {
83 assert(false, "Invalid property type");
84 return PICL_FAILURE;
85 }
86 if (pinfo.size == sizeof(int64_t)) {
87 int64_t val;
88 if (_picl_get_propval(proph, &val, sizeof(int64_t)) != PICL_SUCCESS) {
89 return PICL_FAILURE;
90 }
91 *result = static_cast<int>(val);
92 } else if (pinfo.size == sizeof(int32_t)) {
93 int32_t val;
94 if (_picl_get_propval(proph, &val, sizeof(int32_t)) != PICL_SUCCESS) {
95 return PICL_FAILURE;
96 }
97 *result = static_cast<int>(val);
98 } else {
99 assert(false, "Unexpected integer property size");
100 return PICL_FAILURE;
101 }
102 return PICL_SUCCESS;
103 }
104
105 // Visitor and a state machine that visits integer properties and verifies that the
106 // values are the same. Stores the unique value observed.
107 class UniqueValueVisitor {
108 PICL *_picl;
109 enum {
110 INITIAL, // Start state, no assignments happened
111 ASSIGNED, // Assigned a value
112 INCONSISTENT // Inconsistent value seen
113 } _state;
114 int _value;
115 public:
116 UniqueValueVisitor(PICL* picl) : _picl(picl), _state(INITIAL) { }
117 int value() {
118 assert(_state == ASSIGNED, "Precondition");
119 return _value;
120 }
121 void set_value(int value) {
122 assert(_state == INITIAL, "Precondition");
123 _value = value;
124 _state = ASSIGNED;
125 }
126 bool is_initial() { return _state == INITIAL; }
127 bool is_assigned() { return _state == ASSIGNED; }
128 bool is_inconsistent() { return _state == INCONSISTENT; }
129 void set_inconsistent() { _state = INCONSISTENT; }
130
131 static int visit(picl_nodehdl_t nodeh, const char* name, void *arg) {
132 UniqueValueVisitor *state = static_cast<UniqueValueVisitor*>(arg);
133 PICL* picl = state->_picl;
134 assert(!state->is_inconsistent(), "Precondition");
135 int curr;
136 if (picl->get_int_property(nodeh, name, &curr) == PICL_SUCCESS) {
137 if (!state->is_assigned()) { // first iteration
138 state->set_value(curr);
139 } else if (curr != state->value()) { // following iterations
140 state->set_inconsistent();
141 }
142 }
143 if (state->is_inconsistent()) {
144 return PICL_WALK_TERMINATE;
145 }
146 return PICL_WALK_CONTINUE;
147 }
148 };
149
150 int _L1_data_cache_line_size;
151 int _L2_cache_line_size;
152 public:
153 static int get_l1_data_cache_line_size(picl_nodehdl_t nodeh, void *state) {
154 return UniqueValueVisitor::visit(nodeh, "l1-dcache-line-size", state);
155 }
156 static int get_l2_cache_line_size(picl_nodehdl_t nodeh, void *state) {
157 return UniqueValueVisitor::visit(nodeh, "l2-cache-line-size", state);
158 }
159
160 PICL() : _L1_data_cache_line_size(0), _L2_cache_line_size(0), _dl_handle(NULL) {
161 if (!open_library()) {
162 return;
163 }
164 if (_picl_initialize() == PICL_SUCCESS) {
165 picl_nodehdl_t rooth;
166 if (_picl_get_root(&rooth) == PICL_SUCCESS) {
167 UniqueValueVisitor L1_state(this);
168 // Visit all "cpu" class instances
169 _picl_walk_tree_by_class(rooth, "cpu", &L1_state, PICL_get_l1_data_cache_line_size_helper);
170 if (L1_state.is_initial()) { // Still initial, iteration found no values
171 // Try walk all "core" class instances, it might be a Fujitsu machine
172 _picl_walk_tree_by_class(rooth, "core", &L1_state, PICL_get_l1_data_cache_line_size_helper);
173 }
174 if (L1_state.is_assigned()) { // Is there a value?
175 _L1_data_cache_line_size = L1_state.value();
176 }
177
178 UniqueValueVisitor L2_state(this);
179 _picl_walk_tree_by_class(rooth, "cpu", &L2_state, PICL_get_l2_cache_line_size_helper);
180 if (L2_state.is_initial()) {
181 _picl_walk_tree_by_class(rooth, "core", &L2_state, PICL_get_l2_cache_line_size_helper);
182 }
183 if (L2_state.is_assigned()) {
184 _L2_cache_line_size = L2_state.value();
185 }
186 }
187 _picl_shutdown();
188 }
189 close_library();
190 }
191
192 unsigned int L1_data_cache_line_size() const { return _L1_data_cache_line_size; }
193 unsigned int L2_cache_line_size() const { return _L2_cache_line_size; }
194 };
195
196 extern "C" static int PICL_get_l1_data_cache_line_size_helper(picl_nodehdl_t nodeh, void *result) {
197 return PICL::get_l1_data_cache_line_size(nodeh, result);
198 }
199 extern "C" static int PICL_get_l2_cache_line_size_helper(picl_nodehdl_t nodeh, void *result) {
200 return PICL::get_l2_cache_line_size(nodeh, result);
201 }
202
203 template<typename FuncType>
204 bool PICL::bind(FuncType& func, const char* name) {
205 func = reinterpret_cast<FuncType>(dlsym(_dl_handle, name));
206 return func != NULL;
207 }
208
209 bool PICL::bind_library_functions() {
210 assert(_dl_handle != NULL, "library should be open");
211 return bind(_picl_initialize, "picl_initialize" ) &&
212 bind(_picl_shutdown, "picl_shutdown" ) &&
213 bind(_picl_get_root, "picl_get_root" ) &&
214 bind(_picl_walk_tree_by_class, "picl_walk_tree_by_class") &&
215 bind(_picl_get_prop_by_name, "picl_get_prop_by_name" ) &&
216 bind(_picl_get_propval, "picl_get_propval" ) &&
217 bind(_picl_get_propinfo, "picl_get_propinfo" );
218 }
219
220 bool PICL::open_library() {
221 _dl_handle = dlopen("libpicl.so.1", RTLD_LAZY);
222 if (_dl_handle == NULL) {
223 warning("PICL (libpicl.so.1) is missing. Performance will not be optimal.");
224 return false;
225 }
226 if (!bind_library_functions()) {
227 assert(false, "unexpected PICL API change");
228 close_library();
229 return false;
230 }
231 return true;
232 }
233
234 void PICL::close_library() {
235 assert(_dl_handle != NULL, "library should be open");
236 dlclose(_dl_handle);
237 _dl_handle = NULL;
238 }
33 239
34 // We need to keep these here as long as we have to build on Solaris 240 // We need to keep these here as long as we have to build on Solaris
35 // versions before 10. 241 // versions before 10.
36 #ifndef SI_ARCHITECTURE_32 242 #ifndef SI_ARCHITECTURE_32
37 #define SI_ARCHITECTURE_32 516 /* basic 32-bit SI_ARCHITECTURE */ 243 #define SI_ARCHITECTURE_32 516 /* basic 32-bit SI_ARCHITECTURE */
134 340
135 #ifndef AV_SPARC_AES 341 #ifndef AV_SPARC_AES
136 #define AV_SPARC_AES 0x00020000 /* aes instrs supported */ 342 #define AV_SPARC_AES 0x00020000 /* aes instrs supported */
137 #endif 343 #endif
138 if (av & AV_SPARC_AES) features |= aes_instructions_m; 344 if (av & AV_SPARC_AES) features |= aes_instructions_m;
345
346 #ifndef AV_SPARC_SHA1
347 #define AV_SPARC_SHA1 0x00400000 /* sha1 instruction supported */
348 #endif
349 if (av & AV_SPARC_SHA1) features |= sha1_instruction_m;
350
351 #ifndef AV_SPARC_SHA256
352 #define AV_SPARC_SHA256 0x00800000 /* sha256 instruction supported */
353 #endif
354 if (av & AV_SPARC_SHA256) features |= sha256_instruction_m;
355
356 #ifndef AV_SPARC_SHA512
357 #define AV_SPARC_SHA512 0x01000000 /* sha512 instruction supported */
358 #endif
359 if (av & AV_SPARC_SHA512) features |= sha512_instruction_m;
139 360
140 } else { 361 } else {
141 // getisax(2) failed, use the old legacy code. 362 // getisax(2) failed, use the old legacy code.
142 #ifndef PRODUCT 363 #ifndef PRODUCT
143 if (PrintMiscellaneous && Verbose) 364 if (PrintMiscellaneous && Verbose)
246 assert(strcmp(implementation, "UNKNOWN") != 0, 467 assert(strcmp(implementation, "UNKNOWN") != 0,
247 "unknown cpu info (changed kstat interface?)"); 468 "unknown cpu info (changed kstat interface?)");
248 kstat_close(kc); 469 kstat_close(kc);
249 } 470 }
250 471
472 // Figure out cache line sizes using PICL
473 PICL picl;
474 _L2_cache_line_size = picl.L2_cache_line_size();
475
251 return features; 476 return features;
252 } 477 }