blob: 373f8da540589822b5e994db0c16a1e412133c24 [file]
/*
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef CPU_AARCH64_VM_VERSION_AARCH64_HPP
#define CPU_AARCH64_VM_VERSION_AARCH64_HPP
#include "spin_wait_aarch64.hpp"
#include "runtime/abstract_vm_version.hpp"
#include "utilities/sizes.hpp"
class VM_Version : public Abstract_VM_Version {
friend class VMStructs;
friend class JVMCIVMStructs;
protected:
static int _cpu;
static int _model;
static int _model2;
static int _variant;
static int _revision;
static int _stepping;
static int _zva_length;
static int _dcache_line_size;
static int _icache_line_size;
static int _initial_sve_vector_length;
static int _max_supported_sve_vector_length;
static bool _rop_protection;
static uintptr_t _pac_mask;
static SpinWait _spin_wait;
// Read additional info using OS-specific interfaces
static void get_os_cpu_info();
// Sets the SVE length and returns a new actual value or negative on error.
// If the len is larger than the system largest supported SVE vector length,
// the function sets the largest supported value.
static int set_and_get_current_sve_vector_length(int len);
static int get_current_sve_vector_length();
public:
// Initialization
static void initialize();
static void check_virtualizations();
static void print_platform_virtualization_info(outputStream*);
// Asserts
static void assert_is_initialized() {
}
static bool expensive_load(int ld_size, int scale) {
if (cpu_family() == CPU_ARM) {
// Half-word load with index shift by 1 (aka scale is 2) has
// extra cycle latency, e.g. ldrsh w0, [x1,w2,sxtw #1].
if (ld_size == 2 && scale == 2) {
return true;
}
}
return false;
}
// The CPU implementer codes can be found in
// ARM Architecture Reference Manual ARMv8, for ARMv8-A architecture profile
// https://developer.arm.com/docs/ddi0487/latest
// Arm can assign codes that are not published in the manual.
// Apple's code is defined in
// https://github.com/apple/darwin-xnu/blob/33eb983/osfmk/arm/cpuid.h#L62
enum Family {
CPU_AMPERE = 0xC0,
CPU_ARM = 'A',
CPU_BROADCOM = 'B',
CPU_CAVIUM = 'C',
CPU_DEC = 'D',
CPU_HISILICON = 'H',
CPU_INFINEON = 'I',
CPU_MOTOROLA = 'M',
CPU_NVIDIA = 'N',
CPU_AMCC = 'P',
CPU_QUALCOM = 'Q',
CPU_MARVELL = 'V',
CPU_INTEL = 'i',
CPU_APPLE = 'a',
};
enum Ampere_CPU_Model {
CPU_MODEL_EMAG = 0x0, /* CPU implementer is CPU_AMCC */
CPU_MODEL_ALTRA = 0xd0c, /* CPU implementer is CPU_ARM, Neoverse N1 */
CPU_MODEL_ALTRAMAX = 0xd0c, /* CPU implementer is CPU_ARM, Neoverse N1 */
CPU_MODEL_AMPERE_1 = 0xac3, /* CPU implementer is CPU_AMPERE */
CPU_MODEL_AMPERE_1A = 0xac4, /* CPU implementer is CPU_AMPERE */
CPU_MODEL_AMPERE_1B = 0xac5 /* AMPERE_1B core Implements ARMv8.7 with CSSC, MTE, SM3/SM4 extensions */
};
#define CPU_FEATURE_FLAGS(decl) \
decl(FP, fp, 0) \
decl(ASIMD, asimd, 1) \
decl(EVTSTRM, evtstrm, 2) \
decl(AES, aes, 3) \
decl(PMULL, pmull, 4) \
decl(SHA1, sha1, 5) \
decl(SHA2, sha256, 6) \
decl(CRC32, crc32, 7) \
decl(LSE, lse, 8) \
decl(FPHP, fphp, 9) \
decl(ASIMDHP, asimdhp, 10) \
decl(DCPOP, dcpop, 16) \
decl(SHA3, sha3, 17) \
decl(SHA512, sha512, 21) \
decl(SVE, sve, 22) \
decl(PACA, paca, 30) \
/* flags above must follow Linux HWCAP */ \
decl(SVEBITPERM, svebitperm, 27) \
decl(SVE2, sve2, 28) \
decl(A53MAC, a53mac, 31)
enum Feature_Flag {
#define DECLARE_CPU_FEATURE_FLAG(id, name, bit) CPU_##id = (1 << bit),
CPU_FEATURE_FLAGS(DECLARE_CPU_FEATURE_FLAG)
#undef DECLARE_CPU_FEATURE_FLAG
};
// Feature identification
#define CPU_FEATURE_DETECTION(id, name, bit) \
static bool supports_##name() { return (_features & CPU_##id) != 0; };
CPU_FEATURE_FLAGS(CPU_FEATURE_DETECTION)
#undef CPU_FEATURE_DETECTION
static int cpu_family() { return _cpu; }
static int cpu_model() { return _model; }
static int cpu_model2() { return _model2; }
static int cpu_variant() { return _variant; }
static int cpu_revision() { return _revision; }
static bool model_is(int cpu_model) {
return _model == cpu_model || _model2 == cpu_model;
}
static bool is_zva_enabled() { return 0 <= _zva_length; }
static int zva_length() {
assert(is_zva_enabled(), "ZVA not available");
return _zva_length;
}
static int icache_line_size() { return _icache_line_size; }
static int dcache_line_size() { return _dcache_line_size; }
static int get_initial_sve_vector_length() { return _initial_sve_vector_length; };
static int get_max_supported_sve_vector_length() { return _max_supported_sve_vector_length; };
// Aarch64 supports fast class initialization checks
static bool supports_fast_class_init_checks() { return true; }
constexpr static bool supports_stack_watermark_barrier() { return true; }
constexpr static bool supports_recursive_lightweight_locking() { return true; }
constexpr static bool supports_secondary_supers_table() { return true; }
static void get_compatible_board(char *buf, int buflen);
static const SpinWait& spin_wait_desc() { return _spin_wait; }
static bool supports_on_spin_wait() { return _spin_wait.inst() != SpinWait::NONE; }
static bool supports_float16() { return true; }
#ifdef __APPLE__
// Is the CPU running emulated (for example macOS Rosetta running x86_64 code on M1 ARM (aarch64)
static bool is_cpu_emulated();
#endif
static void initialize_cpu_information(void);
static bool use_rop_protection() { return _rop_protection; }
// For common 64/128-bit unpredicated vector operations, we may prefer
// emitting NEON instructions rather than the corresponding SVE instructions.
static bool use_neon_for_vector(int vector_length_in_bytes) {
return vector_length_in_bytes <= 16;
}
};
#endif // CPU_AARCH64_VM_VERSION_AARCH64_HPP