1 /* 2 * Copyright (c) 2006, 2025, Oracle and/or its affiliates. All rights reserved. 3 * Copyright (c) 2014, 2019, Red Hat Inc. All rights reserved. 4 * Copyright (c) 2021, Azul Systems, Inc. All rights reserved. 5 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 6 * 7 * This code is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License version 2 only, as 9 * published by the Free Software Foundation. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 * 25 */ 26 27 #include "runtime/java.hpp" 28 #include "runtime/os.hpp" 29 #include "runtime/vm_version.hpp" 30 31 #include <sys/sysctl.h> 32 33 int VM_Version::get_current_sve_vector_length() { 34 ShouldNotCallThis(); 35 return -1; 36 } 37 38 int VM_Version::set_and_get_current_sve_vector_length(int length) { 39 ShouldNotCallThis(); 40 return -1; 41 } 42 43 static bool cpu_has(const char* optional) { 44 uint32_t val; 45 size_t len = sizeof(val); 46 if (sysctlbyname(optional, &val, &len, nullptr, 0)) { 47 return false; 48 } 49 return val; 50 } 51 52 void VM_Version::get_os_cpu_info() { 53 size_t sysctllen; 54 55 // cpu_has() uses sysctlbyname function to check the existence of CPU 56 // features. References: Apple developer document [1] and XNU kernel [2]. 57 // [1] https://developer.apple.com/documentation/kernel/1387446-sysctlbyname/determining_instruction_set_characteristics 58 // [2] https://github.com/apple-oss-distributions/xnu/blob/main/bsd/kern/kern_mib.c 59 // 60 // Note that for some features (e.g., LSE, SHA512 and SHA3) there are two 61 // parameters for sysctlbyname, which are invented at different times. 62 // Considering backward compatibility, we check both here. 63 // 64 // Floating-point and Advance SIMD features are standard in Apple processors 65 // beginning with M1 and A7, and don't need to be checked [1]. 66 // 1) hw.optional.floatingpoint always returns 1 [2]. 67 // 2) ID_AA64PFR0_EL1 describes AdvSIMD always equals to FP field. 68 // See the Arm ARM, section "ID_AA64PFR0_EL1, AArch64 Processor Feature 69 // Register 0". 70 _features = CPU_FP | CPU_ASIMD; 71 72 // All Apple-darwin Arm processors have AES, PMULL, SHA1 and SHA2. 73 // See https://github.com/apple-oss-distributions/xnu/blob/main/osfmk/arm/commpage/commpage.c#L412 74 // Note that we ought to add assertions to check sysctlbyname parameters for 75 // these four CPU features, e.g., "hw.optional.arm.FEAT_AES", but the 76 // corresponding string names are not available before xnu-8019 version. 77 // Hence, assertions are omitted considering backward compatibility. 78 _features |= CPU_AES | CPU_PMULL | CPU_SHA1 | CPU_SHA2; 79 80 if (cpu_has("hw.optional.armv8_crc32")) { 81 _features |= CPU_CRC32; 82 } 83 if (cpu_has("hw.optional.arm.FEAT_LSE") || 84 cpu_has("hw.optional.armv8_1_atomics")) { 85 _features |= CPU_LSE; 86 } 87 if (cpu_has("hw.optional.arm.FEAT_SHA512") || 88 cpu_has("hw.optional.armv8_2_sha512")) { 89 _features |= CPU_SHA512; 90 } 91 if (cpu_has("hw.optional.arm.FEAT_SHA3") || 92 cpu_has("hw.optional.armv8_2_sha3")) { 93 _features |= CPU_SHA3; 94 } 95 96 int cache_line_size; 97 int hw_conf_cache_line[] = { CTL_HW, HW_CACHELINE }; 98 sysctllen = sizeof(cache_line_size); 99 if (sysctl(hw_conf_cache_line, 2, &cache_line_size, &sysctllen, nullptr, 0)) { 100 cache_line_size = 16; 101 } 102 _icache_line_size = 16; // minimal line length CCSIDR_EL1 can hold 103 _dcache_line_size = cache_line_size; 104 105 uint64_t dczid_el0; 106 __asm__ ( 107 "mrs %0, DCZID_EL0\n" 108 : "=r"(dczid_el0) 109 ); 110 if (!(dczid_el0 & 0x10)) { 111 _zva_length = 4 << (dczid_el0 & 0xf); 112 } 113 114 int family; 115 sysctllen = sizeof(family); 116 if (sysctlbyname("hw.cpufamily", &family, &sysctllen, nullptr, 0)) { 117 family = 0; 118 } 119 120 _model = family; 121 _cpu = CPU_APPLE; 122 } 123 124 void VM_Version::get_compatible_board(char *buf, int buflen) { 125 assert(buf != nullptr, "invalid argument"); 126 assert(buflen >= 1, "invalid argument"); 127 *buf = '\0'; 128 } 129 130 #ifdef __APPLE__ 131 132 bool VM_Version::is_cpu_emulated() { 133 return false; 134 } 135 136 #endif