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
8255716: AArch64: Regression: JVM crashes if manually offline a core

Co-authored-by: Bernhard Urban-Forster <burban@openjdk.org>
Reviewed-by: akozlov, mdoerr
Backport-of: ec9bee6
  • Loading branch information
2 people authored and RealCLanger committed Oct 12, 2021
1 parent 2a028c4 commit d336b24
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 156 deletions.
162 changes: 27 additions & 135 deletions src/hotspot/cpu/aarch64/vm_version_aarch64.cpp
Expand Up @@ -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();

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
}
Expand All @@ -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 {
Expand All @@ -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));
Expand Down Expand Up @@ -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);
}
Expand All @@ -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);
}
Expand All @@ -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);
}
Expand All @@ -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);
}
Expand All @@ -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);
}
Expand Down Expand Up @@ -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);
}
34 changes: 13 additions & 21 deletions src/hotspot/cpu/aarch64/vm_version_aarch64.hpp
Expand Up @@ -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
Expand Down Expand Up @@ -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),
Expand All @@ -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

1 comment on commit d336b24

@openjdk-notifier
Copy link

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.