1 /*
  2  * Copyright (c) 1997, 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 #ifndef CPU_AARCH64_VM_VERSION_AARCH64_HPP
 27 #define CPU_AARCH64_VM_VERSION_AARCH64_HPP
 28 
 29 #include "spin_wait_aarch64.hpp"
 30 #include "runtime/abstract_vm_version.hpp"
 31 #include "utilities/sizes.hpp"
 32 
 33 class VM_Version : public Abstract_VM_Version {
 34   friend class JVMCIVMStructs;
 35 
 36 protected:
 37   static int _cpu;
 38   static int _model;
 39   static int _model2;
 40   static int _variant;
 41   static int _revision;
 42   static int _stepping;
 43 
 44   static int _zva_length;
 45   static int _dcache_line_size;
 46   static int _icache_line_size;
 47   static int _initial_sve_vector_length;
 48 
 49   static SpinWait _spin_wait;
 50 
 51   // Read additional info using OS-specific interfaces
 52   static void get_os_cpu_info();
 53 
 54   // Sets the SVE length and returns a new actual value or negative on error.
 55   // If the len is larger than the system largest supported SVE vector length,
 56   // the function sets the largest supported value.
 57   static int set_and_get_current_sve_vector_length(int len);
 58   static int get_current_sve_vector_length();
 59 
 60 public:
 61   // Initialization
 62   static void initialize();
 63   static void check_virtualizations();
 64 
 65   static void print_platform_virtualization_info(outputStream*);
 66 
 67   // Asserts
 68   static void assert_is_initialized() {
 69   }
 70 
 71   static bool expensive_load(int ld_size, int scale) {
 72     if (cpu_family() == CPU_ARM) {
 73       // Half-word load with index shift by 1 (aka scale is 2) has
 74       // extra cycle latency, e.g. ldrsh w0, [x1,w2,sxtw #1].
 75       if (ld_size == 2 && scale == 2) {
 76         return true;
 77       }
 78     }
 79     return false;
 80   }
 81 
 82   // The CPU implementer codes can be found in
 83   // ARM Architecture Reference Manual ARMv8, for ARMv8-A architecture profile
 84   // https://developer.arm.com/docs/ddi0487/latest
 85   // Arm can assign codes that are not published in the manual.
 86   // Apple's code is defined in
 87   // https://github.com/apple/darwin-xnu/blob/33eb983/osfmk/arm/cpuid.h#L62
 88   enum Family {
 89     CPU_AMPERE    = 0xC0,
 90     CPU_ARM       = 'A',
 91     CPU_BROADCOM  = 'B',
 92     CPU_CAVIUM    = 'C',
 93     CPU_DEC       = 'D',
 94     CPU_HISILICON = 'H',
 95     CPU_INFINEON  = 'I',
 96     CPU_MOTOROLA  = 'M',
 97     CPU_NVIDIA    = 'N',
 98     CPU_AMCC      = 'P',
 99     CPU_QUALCOM   = 'Q',
100     CPU_MARVELL   = 'V',
101     CPU_INTEL     = 'i',
102     CPU_APPLE     = 'a',
103   };
104 
105   enum Ampere_CPU_Model {
106     CPU_MODEL_EMAG      = 0x0,   /* CPU implementer is CPU_AMCC */
107     CPU_MODEL_ALTRA     = 0xd0c, /* CPU implementer is CPU_ARM, Neoverse N1 */
108     CPU_MODEL_ALTRAMAX  = 0xd0c, /* CPU implementer is CPU_ARM, Neoverse N1 */
109     CPU_MODEL_AMPERE_1  = 0xac3, /* CPU implementer is CPU_AMPERE */
110     CPU_MODEL_AMPERE_1A = 0xac4  /* CPU implementer is CPU_AMPERE */
111   };
112 
113   enum Feature_Flag {
114 #define CPU_FEATURE_FLAGS(decl)               \
115     decl(FP,            "fp",            0)   \
116     decl(ASIMD,         "simd",          1)   \
117     decl(EVTSTRM,       "evtstrm",       2)   \
118     decl(AES,           "aes",           3)   \
119     decl(PMULL,         "pmull",         4)   \
120     decl(SHA1,          "sha1",          5)   \
121     decl(SHA2,          "sha256",        6)   \
122     decl(CRC32,         "crc",           7)   \
123     decl(LSE,           "lse",           8)   \
124     decl(DCPOP,         "dcpop",         16)  \
125     decl(SHA3,          "sha3",          17)  \
126     decl(SHA512,        "sha512",        21)  \
127     decl(SVE,           "sve",           22)  \
128     /* flags above must follow Linux HWCAP */ \
129     decl(SVE2,          "sve2",          28)  \
130     decl(STXR_PREFETCH, "stxr_prefetch", 29)  \
131     decl(A53MAC,        "a53mac",        30)
132 
133 #define DECLARE_CPU_FEATURE_FLAG(id, name, bit) CPU_##id = (1 << bit),
134     CPU_FEATURE_FLAGS(DECLARE_CPU_FEATURE_FLAG)
135 #undef DECLARE_CPU_FEATURE_FLAG
136   };
137 
138   static int cpu_family()                     { return _cpu; }
139   static int cpu_model()                      { return _model; }
140   static int cpu_model2()                     { return _model2; }
141   static int cpu_variant()                    { return _variant; }
142   static int cpu_revision()                   { return _revision; }
143 
144   static bool is_zva_enabled() { return 0 <= _zva_length; }
145   static int zva_length() {
146     assert(is_zva_enabled(), "ZVA not available");
147     return _zva_length;
148   }
149 
150   static int icache_line_size() { return _icache_line_size; }
151   static int dcache_line_size() { return _dcache_line_size; }
152   static int get_initial_sve_vector_length()  { return _initial_sve_vector_length; };
153 
154   static bool supports_fast_class_init_checks() { return true; }
155   constexpr static bool supports_stack_watermark_barrier() { return true; }
156 
157   static void get_compatible_board(char *buf, int buflen);
158 
159   static const SpinWait& spin_wait_desc() { return _spin_wait; }
160 
161   static bool supports_on_spin_wait() { return _spin_wait.inst() != SpinWait::NONE; }
162 
163 #ifdef __APPLE__
164   // Is the CPU running emulated (for example macOS Rosetta running x86_64 code on M1 ARM (aarch64)
165   static bool is_cpu_emulated();
166 #endif
167 };
168 
169 #endif // CPU_AARCH64_VM_VERSION_AARCH64_HPP