Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
8253015: Aarch64: Move linux code out from generic CPU feature detection
Reviewed-by: aph
  • Loading branch information
AntonKozlov authored and Andrew Haley committed Sep 28, 2020
1 parent 16b8c39 commit ec9bee6
Show file tree
Hide file tree
Showing 7 changed files with 220 additions and 209 deletions.
2 changes: 1 addition & 1 deletion src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp
Expand Up @@ -5266,7 +5266,7 @@ void MacroAssembler::cache_wb(Address line) {
assert(line.offset() == 0, "offset should be 0");
// would like to assert this
// assert(line._ext.shift == 0, "shift should be zero");
if (VM_Version::supports_dcpop()) {
if (VM_Version::features() & VM_Version::CPU_DCPOP) {
// writeback using clear virtual address to point of persistence
dc(Assembler::CVAP, line.base());
} else {
Expand Down
206 changes: 34 additions & 172 deletions src/hotspot/cpu/aarch64/vm_version_aarch64.cpp
Expand Up @@ -24,124 +24,36 @@
*/

#include "precompiled.hpp"
#include "asm/macroAssembler.hpp"
#include "asm/macroAssembler.inline.hpp"
#include "memory/resourceArea.hpp"
#include "runtime/arguments.hpp"
#include "runtime/globals_extension.hpp"
#include "runtime/java.hpp"
#include "runtime/os.hpp"
#include "runtime/stubCodeGenerator.hpp"
#include "runtime/vm_version.hpp"
#include "utilities/formatBuffer.hpp"
#include "utilities/macros.hpp"

#include OS_HEADER_INLINE(os)

#include <asm/hwcap.h>
#include <sys/auxv.h>
#include <sys/prctl.h>

#ifndef HWCAP_AES
#define HWCAP_AES (1<<3)
#endif

#ifndef HWCAP_PMULL
#define HWCAP_PMULL (1<<4)
#endif

#ifndef HWCAP_SHA1
#define HWCAP_SHA1 (1<<5)
#endif

#ifndef HWCAP_SHA2
#define HWCAP_SHA2 (1<<6)
#endif

#ifndef HWCAP_CRC32
#define HWCAP_CRC32 (1<<7)
#endif

#ifndef HWCAP_ATOMICS
#define HWCAP_ATOMICS (1<<8)
#endif

#ifndef HWCAP_SHA512
#define HWCAP_SHA512 (1 << 21)
#endif

#ifndef HWCAP_SVE
#define HWCAP_SVE (1 << 22)
#endif

#ifndef HWCAP2_SVE2
#define HWCAP2_SVE2 (1 << 1)
#endif

#ifndef PR_SVE_GET_VL
// For old toolchains which do not have SVE related macros defined.
#define PR_SVE_SET_VL 50
#define PR_SVE_GET_VL 51
#endif

int VM_Version::_cpu;
int VM_Version::_model;
int VM_Version::_model2;
int VM_Version::_variant;
int VM_Version::_revision;
int VM_Version::_stepping;
bool VM_Version::_dcpop;
int VM_Version::_initial_sve_vector_length;
VM_Version::PsrInfo VM_Version::_psr_info = { 0, };

static BufferBlob* stub_blob;
static const int stub_size = 550;

extern "C" {
typedef void (*getPsrInfo_stub_t)(void*);
}
static getPsrInfo_stub_t getPsrInfo_stub = NULL;


class VM_Version_StubGenerator: public StubCodeGenerator {
public:

VM_Version_StubGenerator(CodeBuffer *c) : StubCodeGenerator(c) {}

address generate_getPsrInfo() {
StubCodeMark mark(this, "VM_Version", "getPsrInfo_stub");
# define __ _masm->
address start = __ pc();

// void getPsrInfo(VM_Version::PsrInfo* psr_info);

address entry = __ pc();

__ enter();

__ get_dczid_el0(rscratch1);
__ strw(rscratch1, Address(c_rarg0, in_bytes(VM_Version::dczid_el0_offset())));

__ get_ctr_el0(rscratch1);
__ strw(rscratch1, Address(c_rarg0, in_bytes(VM_Version::ctr_el0_offset())));

__ leave();
__ ret(lr);

# undef __

return start;
}
};
int VM_Version::_zva_length;
int VM_Version::_dcache_line_size;
int VM_Version::_icache_line_size;
int VM_Version::_initial_sve_vector_length;

void VM_Version::get_processor_features() {
void VM_Version::initialize() {
_supports_cx8 = true;
_supports_atomic_getset4 = true;
_supports_atomic_getadd4 = true;
_supports_atomic_getset8 = true;
_supports_atomic_getadd8 = true;

getPsrInfo_stub(&_psr_info);
get_os_cpu_info();

int dcache_line = VM_Version::dcache_line_size();

Expand Down Expand Up @@ -183,45 +95,12 @@ void VM_Version::get_processor_features() {
SoftwarePrefetchHintDistance &= ~7;
}

uint64_t auxv = getauxval(AT_HWCAP);
uint64_t auxv2 = getauxval(AT_HWCAP2);

char buf[512];

_features = auxv;

int cpu_lines = 0;
if (FILE *f = fopen("/proc/cpuinfo", "r")) {
// need a large buffer as the flags line may include lots of text
char buf[1024], *p;
while (fgets(buf, sizeof (buf), f) != NULL) {
if ((p = strchr(buf, ':')) != NULL) {
long v = strtol(p+1, NULL, 0);
if (strncmp(buf, "CPU implementer", sizeof "CPU implementer" - 1) == 0) {
_cpu = v;
cpu_lines++;
} else if (strncmp(buf, "CPU variant", sizeof "CPU variant" - 1) == 0) {
_variant = v;
} else if (strncmp(buf, "CPU part", sizeof "CPU part" - 1) == 0) {
if (_model != v) _model2 = _model;
_model = v;
} else if (strncmp(buf, "CPU revision", sizeof "CPU revision" - 1) == 0) {
_revision = v;
} else if (strncmp(buf, "flags", sizeof("flags") - 1) == 0) {
if (strstr(p+1, "dcpop")) {
_dcpop = true;
}
}
}
}
fclose(f);
}

if (os::supports_map_sync()) {
// if dcpop is available publish data cache line flush size via
// generic field, otherwise let if default to zero thereby
// disabling writeback
if (_dcpop) {
if (_features & CPU_DCPOP) {
_data_cache_line_flush_size = dcache_line;
}
}
Expand Down Expand Up @@ -302,30 +181,31 @@ void VM_Version::get_processor_features() {
}

if (_cpu == CPU_ARM && (_model == 0xd07 || _model2 == 0xd07)) _features |= CPU_STXR_PREFETCH;
// If an olde style /proc/cpuinfo (cpu_lines == 1) then if _model is an A57 (0xd07)
// If an olde style /proc/cpuinfo (cores == 1) then if _model is an A57 (0xd07)
// we assume the worst and assume we could be on a big little system and have
// undisclosed A53 cores which we could be swapped to at any stage
if (_cpu == CPU_ARM && cpu_lines == 1 && _model == 0xd07) _features |= CPU_A53MAC;
if (_cpu == CPU_ARM && os::processor_count() == 1 && _model == 0xd07) _features |= CPU_A53MAC;

char buf[512];
sprintf(buf, "0x%02x:0x%x:0x%03x:%d", _cpu, _variant, _model, _revision);
if (_model2) sprintf(buf+strlen(buf), "(0x%03x)", _model2);
if (auxv & HWCAP_ASIMD) strcat(buf, ", simd");
if (auxv & HWCAP_CRC32) strcat(buf, ", crc");
if (auxv & HWCAP_AES) strcat(buf, ", aes");
if (auxv & HWCAP_SHA1) strcat(buf, ", sha1");
if (auxv & HWCAP_SHA2) strcat(buf, ", sha256");
if (auxv & HWCAP_SHA512) strcat(buf, ", sha512");
if (auxv & HWCAP_ATOMICS) strcat(buf, ", lse");
if (auxv & HWCAP_SVE) strcat(buf, ", sve");
if (auxv2 & HWCAP2_SVE2) strcat(buf, ", sve2");
if (_features & CPU_ASIMD) strcat(buf, ", simd");
if (_features & CPU_CRC32) strcat(buf, ", crc");
if (_features & CPU_AES) strcat(buf, ", aes");
if (_features & CPU_SHA1) strcat(buf, ", sha1");
if (_features & CPU_SHA2) strcat(buf, ", sha256");
if (_features & CPU_SHA512) strcat(buf, ", sha512");
if (_features & CPU_LSE) strcat(buf, ", lse");
if (_features & CPU_SVE) strcat(buf, ", sve");
if (_features & CPU_SVE2) strcat(buf, ", sve2");

_features_string = os::strdup(buf);

if (FLAG_IS_DEFAULT(UseCRC32)) {
UseCRC32 = (auxv & HWCAP_CRC32) != 0;
UseCRC32 = (_features & CPU_CRC32) != 0;
}

if (UseCRC32 && (auxv & HWCAP_CRC32) == 0) {
if (UseCRC32 && (_features & CPU_CRC32) == 0) {
warning("UseCRC32 specified, but not supported on this CPU");
FLAG_SET_DEFAULT(UseCRC32, false);
}
Expand All @@ -339,7 +219,7 @@ void VM_Version::get_processor_features() {
FLAG_SET_DEFAULT(UseVectorizedMismatchIntrinsic, false);
}

if (auxv & HWCAP_ATOMICS) {
if (_features & CPU_LSE) {
if (FLAG_IS_DEFAULT(UseLSE))
FLAG_SET_DEFAULT(UseLSE, true);
} else {
Expand All @@ -349,7 +229,7 @@ void VM_Version::get_processor_features() {
}
}

if (auxv & HWCAP_AES) {
if (_features & CPU_AES) {
UseAES = UseAES || FLAG_IS_DEFAULT(UseAES);
UseAESIntrinsics =
UseAESIntrinsics || (UseAES && FLAG_IS_DEFAULT(UseAESIntrinsics));
Expand Down Expand Up @@ -377,7 +257,7 @@ void VM_Version::get_processor_features() {
UseCRC32Intrinsics = true;
}

if (auxv & HWCAP_CRC32) {
if (_features & CPU_CRC32) {
if (FLAG_IS_DEFAULT(UseCRC32CIntrinsics)) {
FLAG_SET_DEFAULT(UseCRC32CIntrinsics, true);
}
Expand All @@ -395,7 +275,7 @@ void VM_Version::get_processor_features() {
FLAG_SET_DEFAULT(UseMD5Intrinsics, false);
}

if (auxv & (HWCAP_SHA1 | HWCAP_SHA2)) {
if (_features & (CPU_SHA1 | CPU_SHA2)) {
if (FLAG_IS_DEFAULT(UseSHA)) {
FLAG_SET_DEFAULT(UseSHA, true);
}
Expand All @@ -404,7 +284,7 @@ void VM_Version::get_processor_features() {
FLAG_SET_DEFAULT(UseSHA, false);
}

if (UseSHA && (auxv & HWCAP_SHA1)) {
if (UseSHA && (_features & CPU_SHA1)) {
if (FLAG_IS_DEFAULT(UseSHA1Intrinsics)) {
FLAG_SET_DEFAULT(UseSHA1Intrinsics, true);
}
Expand All @@ -413,7 +293,7 @@ void VM_Version::get_processor_features() {
FLAG_SET_DEFAULT(UseSHA1Intrinsics, false);
}

if (UseSHA && (auxv & HWCAP_SHA2)) {
if (UseSHA && (_features & CPU_SHA2)) {
if (FLAG_IS_DEFAULT(UseSHA256Intrinsics)) {
FLAG_SET_DEFAULT(UseSHA256Intrinsics, true);
}
Expand All @@ -422,7 +302,7 @@ void VM_Version::get_processor_features() {
FLAG_SET_DEFAULT(UseSHA256Intrinsics, false);
}

if (UseSHA && (auxv & HWCAP_SHA512)) {
if (UseSHA && (_features & CPU_SHA512)) {
// Do not auto-enable UseSHA512Intrinsics until it has been fully tested on hardware
// if (FLAG_IS_DEFAULT(UseSHA512Intrinsics)) {
// FLAG_SET_DEFAULT(UseSHA512Intrinsics, true);
Expand All @@ -436,7 +316,7 @@ void VM_Version::get_processor_features() {
FLAG_SET_DEFAULT(UseSHA, false);
}

if (auxv & HWCAP_PMULL) {
if (_features & CPU_PMULL) {
if (FLAG_IS_DEFAULT(UseGHASHIntrinsics)) {
FLAG_SET_DEFAULT(UseGHASHIntrinsics, true);
}
Expand All @@ -457,12 +337,12 @@ void VM_Version::get_processor_features() {
FLAG_SET_DEFAULT(UseBlockZeroing, false);
}

if (auxv & HWCAP_SVE) {
if (_features & CPU_SVE) {
if (FLAG_IS_DEFAULT(UseSVE)) {
FLAG_SET_DEFAULT(UseSVE, (auxv2 & HWCAP2_SVE2) ? 2 : 1);
FLAG_SET_DEFAULT(UseSVE, (_features & CPU_SVE2) ? 2 : 1);
}
if (UseSVE > 0) {
_initial_sve_vector_length = prctl(PR_SVE_GET_VL);
_initial_sve_vector_length = get_current_sve_vector_length();
}
} else if (UseSVE > 0) {
warning("UseSVE specified, but not supported on current CPU. Disabling SVE.");
Expand Down Expand Up @@ -510,11 +390,9 @@ void VM_Version::get_processor_features() {
warning("SVE does not support vector length less than 16 bytes. Disabling SVE.");
UseSVE = 0;
} else if ((MaxVectorSize % 16) == 0 && is_power_of_2(MaxVectorSize)) {
int new_vl = prctl(PR_SVE_SET_VL, MaxVectorSize);
int new_vl = set_and_get_current_sve_vector_lenght(MaxVectorSize);
_initial_sve_vector_length = new_vl;
// If MaxVectorSize is larger than system largest supported SVE vector length, above prctl()
// call will set task vector length to the system largest supported value. So, we also update
// MaxVectorSize to that largest supported value.
// Update MaxVectorSize to the largest supported value.
if (new_vl < 0) {
vm_exit_during_initialization(
err_msg("Current system does not support SVE vector length for MaxVectorSize: %d",
Expand Down Expand Up @@ -555,22 +433,6 @@ void VM_Version::get_processor_features() {
AlignVector = AvoidUnalignedAccesses;
}
#endif
}

void VM_Version::initialize() {
ResourceMark rm;

stub_blob = BufferBlob::create("getPsrInfo_stub", stub_size);
if (stub_blob == NULL) {
vm_exit_during_initialization("Unable to allocate getPsrInfo_stub");
}

CodeBuffer c(stub_blob);
VM_Version_StubGenerator g(&c);
getPsrInfo_stub = CAST_TO_FN_PTR(getPsrInfo_stub_t,
g.generate_getPsrInfo());

get_processor_features();

UNSUPPORTED_OPTION(CriticalJNINatives);
}

1 comment on commit ec9bee6

@bridgekeeper
Copy link

@bridgekeeper bridgekeeper bot commented on ec9bee6 Sep 28, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.