Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8253015: Aarch64: Move linux code out from generic CPU feature detection #299

Closed
wants to merge 2 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -24,100 +24,35 @@
*/

#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/stubCodeGenerator.hpp"
#include "runtime/os.hpp"
#include "runtime/vm_version.hpp"
#include "utilities/formatBuffer.hpp"
#include "utilities/macros.hpp"

#include OS_HEADER_INLINE(os)

#include <sys/auxv.h>
#include <asm/hwcap.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

int VM_Version::_cpu;
int VM_Version::_model;
int VM_Version::_model2;
int VM_Version::_variant;
int VM_Version::_revision;
int VM_Version::_stepping;
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();
int VM_Version::_zva_length;
int VM_Version::_dcache_line_size;
int VM_Version::_icache_line_size;

__ 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;
}
};


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();

@@ -163,34 +98,6 @@ void VM_Version::get_processor_features() {
ContendedPaddingWidth = dcache_line;
}

uint64_t auxv = getauxval(AT_HWCAP);

char buf[512];

_features = auxv;

int cpu_lines = 0;
if (FILE *f = fopen("/proc/cpuinfo", "r")) {
char buf[128], *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;
}
}
}
fclose(f);
}

// Enable vendor specific features

// ThunderX
@@ -256,27 +163,28 @@ 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_ATOMICS) strcat(buf, ", lse");
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_LSE) strcat(buf, ", lse");

_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);
}
@@ -290,7 +198,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 {
@@ -300,7 +208,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));
@@ -328,7 +236,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);
}
@@ -341,7 +249,7 @@ void VM_Version::get_processor_features() {
FLAG_SET_DEFAULT(UseFMA, true);
}

if (auxv & (HWCAP_SHA1 | HWCAP_SHA2)) {
if (_features & (CPU_SHA1 | CPU_SHA2)) {
if (FLAG_IS_DEFAULT(UseSHA)) {
FLAG_SET_DEFAULT(UseSHA, true);
}
@@ -350,7 +258,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);
}
@@ -359,7 +267,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);
}
@@ -377,7 +285,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);
}
@@ -439,22 +347,6 @@ void VM_Version::get_processor_features() {
OptoScheduling = true;
}
#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);
}
@@ -41,12 +41,12 @@ class VM_Version : public Abstract_VM_Version {
static int _revision;
static int _stepping;

struct PsrInfo {
uint32_t dczid_el0;
uint32_t ctr_el0;
};
static PsrInfo _psr_info;
static void get_processor_features();
static int _zva_length;
static int _dcache_line_size;
static int _icache_line_size;

// Read additional info using OS-specific interfaces
static void get_os_cpu_info();

public:
// Initialization
@@ -91,6 +91,7 @@ class VM_Version : public Abstract_VM_Version {
CPU_SHA2 = (1<<6),
CPU_CRC32 = (1<<7),
CPU_LSE = (1<<8),
// flags above must follow Linux HWCAP
CPU_STXR_PREFETCH= (1 << 29),
CPU_A53MAC = (1 << 30),
CPU_DMB_ATOMICS = (1 << 31),
@@ -101,24 +102,15 @@ class VM_Version : public Abstract_VM_Version {
static int cpu_model2() { return _model2; }
static int cpu_variant() { return _variant; }
static int cpu_revision() { return _revision; }
static ByteSize dczid_el0_offset() { return byte_offset_of(PsrInfo, dczid_el0); }
static ByteSize ctr_el0_offset() { return byte_offset_of(PsrInfo, ctr_el0); }
static bool is_zva_enabled() {
// Check the DZP bit (bit 4) of dczid_el0 is zero
// and block size (bit 0~3) is not zero.
return ((_psr_info.dczid_el0 & 0x10) == 0 &&
(_psr_info.dczid_el0 & 0xf) != 0);
}

static bool is_zva_enabled() { return 0 <= _zva_length; }
static int zva_length() {
assert(is_zva_enabled(), "ZVA not available");
return 4 << (_psr_info.dczid_el0 & 0xf);
}
static int icache_line_size() {
return (1 << (_psr_info.ctr_el0 & 0x0f)) * 4;
}
static int dcache_line_size() {
return (1 << ((_psr_info.ctr_el0 >> 16) & 0x0f)) * 4;
return _zva_length;
}

static int icache_line_size() { return _icache_line_size; }
static int dcache_line_size() { return _dcache_line_size; }
};

#endif // CPU_AARCH64_VM_VM_VERSION_AARCH64_HPP