jdk
222 строки · 6.7 Кб
1/*
2* Copyright (c) 2006, 2023, Oracle and/or its affiliates. All rights reserved.
3* Copyright (c) 2014, 2020, Red Hat Inc. 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*/
25
26#include "precompiled.hpp"27#include "runtime/os.hpp"28#include "runtime/os.inline.hpp"29#include "runtime/vm_version.hpp"30
31#include <asm/hwcap.h>32#include <sys/auxv.h>33#include <sys/prctl.h>34
35#ifndef HWCAP_AES36#define HWCAP_AES (1<<3)37#endif38
39#ifndef HWCAP_PMULL40#define HWCAP_PMULL (1<<4)41#endif42
43#ifndef HWCAP_SHA144#define HWCAP_SHA1 (1<<5)45#endif46
47#ifndef HWCAP_SHA248#define HWCAP_SHA2 (1<<6)49#endif50
51#ifndef HWCAP_CRC3252#define HWCAP_CRC32 (1<<7)53#endif54
55#ifndef HWCAP_ATOMICS56#define HWCAP_ATOMICS (1<<8)57#endif58
59#ifndef HWCAP_DCPOP60#define HWCAP_DCPOP (1<<16)61#endif62
63#ifndef HWCAP_SHA364#define HWCAP_SHA3 (1 << 17)65#endif66
67#ifndef HWCAP_SHA51268#define HWCAP_SHA512 (1 << 21)69#endif70
71#ifndef HWCAP_SVE72#define HWCAP_SVE (1 << 22)73#endif74
75#ifndef HWCAP_PACA76#define HWCAP_PACA (1 << 30)77#endif78
79#ifndef HWCAP2_SVE280#define HWCAP2_SVE2 (1 << 1)81#endif82
83#ifndef HWCAP2_SVEBITPERM84#define HWCAP2_SVEBITPERM (1 << 4)85#endif86
87#ifndef PR_SVE_GET_VL88// For old toolchains which do not have SVE related macros defined.
89#define PR_SVE_SET_VL 5090#define PR_SVE_GET_VL 5191#endif92
93int VM_Version::get_current_sve_vector_length() {94assert(VM_Version::supports_sve(), "should not call this");95return prctl(PR_SVE_GET_VL);96}
97
98int VM_Version::set_and_get_current_sve_vector_length(int length) {99assert(VM_Version::supports_sve(), "should not call this");100int new_length = prctl(PR_SVE_SET_VL, length);101return new_length;102}
103
104void VM_Version::get_os_cpu_info() {105
106uint64_t auxv = getauxval(AT_HWCAP);107uint64_t auxv2 = getauxval(AT_HWCAP2);108
109static_assert(CPU_FP == HWCAP_FP, "Flag CPU_FP must follow Linux HWCAP");110static_assert(CPU_ASIMD == HWCAP_ASIMD, "Flag CPU_ASIMD must follow Linux HWCAP");111static_assert(CPU_EVTSTRM == HWCAP_EVTSTRM, "Flag CPU_EVTSTRM must follow Linux HWCAP");112static_assert(CPU_AES == HWCAP_AES, "Flag CPU_AES must follow Linux HWCAP");113static_assert(CPU_PMULL == HWCAP_PMULL, "Flag CPU_PMULL must follow Linux HWCAP");114static_assert(CPU_SHA1 == HWCAP_SHA1, "Flag CPU_SHA1 must follow Linux HWCAP");115static_assert(CPU_SHA2 == HWCAP_SHA2, "Flag CPU_SHA2 must follow Linux HWCAP");116static_assert(CPU_CRC32 == HWCAP_CRC32, "Flag CPU_CRC32 must follow Linux HWCAP");117static_assert(CPU_LSE == HWCAP_ATOMICS, "Flag CPU_LSE must follow Linux HWCAP");118static_assert(CPU_DCPOP == HWCAP_DCPOP, "Flag CPU_DCPOP must follow Linux HWCAP");119static_assert(CPU_SHA3 == HWCAP_SHA3, "Flag CPU_SHA3 must follow Linux HWCAP");120static_assert(CPU_SHA512 == HWCAP_SHA512, "Flag CPU_SHA512 must follow Linux HWCAP");121static_assert(CPU_SVE == HWCAP_SVE, "Flag CPU_SVE must follow Linux HWCAP");122static_assert(CPU_PACA == HWCAP_PACA, "Flag CPU_PACA must follow Linux HWCAP");123_features = auxv & (124HWCAP_FP |125HWCAP_ASIMD |126HWCAP_EVTSTRM |127HWCAP_AES |128HWCAP_PMULL |129HWCAP_SHA1 |130HWCAP_SHA2 |131HWCAP_CRC32 |132HWCAP_ATOMICS |133HWCAP_DCPOP |134HWCAP_SHA3 |135HWCAP_SHA512 |136HWCAP_SVE |137HWCAP_PACA);138
139if (auxv2 & HWCAP2_SVE2) _features |= CPU_SVE2;140if (auxv2 & HWCAP2_SVEBITPERM) _features |= CPU_SVEBITPERM;141
142uint64_t ctr_el0;143uint64_t dczid_el0;144__asm__ (145"mrs %0, CTR_EL0\n"146"mrs %1, DCZID_EL0\n"147: "=r"(ctr_el0), "=r"(dczid_el0)148);149
150_icache_line_size = (1 << (ctr_el0 & 0x0f)) * 4;151_dcache_line_size = (1 << ((ctr_el0 >> 16) & 0x0f)) * 4;152
153if (!(dczid_el0 & 0x10)) {154_zva_length = 4 << (dczid_el0 & 0xf);155}156
157if (FILE *f = os::fopen("/proc/cpuinfo", "r")) {158// need a large buffer as the flags line may include lots of text159char buf[1024], *p;160while (fgets(buf, sizeof (buf), f) != nullptr) {161if ((p = strchr(buf, ':')) != nullptr) {162long v = strtol(p+1, nullptr, 0);163if (strncmp(buf, "CPU implementer", sizeof "CPU implementer" - 1) == 0) {164_cpu = v;165} else if (strncmp(buf, "CPU variant", sizeof "CPU variant" - 1) == 0) {166_variant = v;167} else if (strncmp(buf, "CPU part", sizeof "CPU part" - 1) == 0) {168if (_model != v) _model2 = _model;169_model = v;170} else if (strncmp(buf, "CPU revision", sizeof "CPU revision" - 1) == 0) {171_revision = v;172} else if (strncmp(buf, "flags", sizeof("flags") - 1) == 0) {173if (strstr(p+1, "dcpop")) {174guarantee(_features & CPU_DCPOP, "dcpop availability should be consistent");175}176}177}178}179fclose(f);180}181}
182
183static bool read_fully(const char *fname, char *buf, size_t buflen) {184assert(buf != nullptr, "invalid argument");185assert(buflen >= 1, "invalid argument");186int fd = os::open(fname, O_RDONLY, 0);187if (fd != -1) {188ssize_t read_sz = ::read(fd, buf, buflen);189::close(fd);190
191// Skip if the contents is just "\n" because some machine only sets192// '\n' to the board name.193// (e.g. esys/devices/virtual/dmi/id/board_name)194if (read_sz > 0 && !(read_sz == 1 && *buf == '\n')) {195// Replace '\0' to ' '196for (char *ch = buf; ch < buf + read_sz - 1; ch++) {197if (*ch == '\0') {198*ch = ' ';199}200}201buf[read_sz - 1] = '\0';202return true;203}204}205*buf = '\0';206return false;207}
208
209void VM_Version::get_compatible_board(char *buf, int buflen) {210const char *board_name_file_list[] = {211"/proc/device-tree/compatible",212"/sys/devices/virtual/dmi/id/board_name",213"/sys/devices/virtual/dmi/id/product_name",214nullptr215};216
217for (const char **fname = board_name_file_list; *fname != nullptr; fname++) {218if (read_fully(*fname, buf, buflen)) {219return;220}221}222}
223