Mercurial > hg > truffle
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 } |