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 set_feature(CPU_FP); 71 set_feature(CPU_ASIMD); 72 73 // All Apple-darwin Arm processors have AES, PMULL, SHA1 and SHA2. 74 // See https://github.com/apple-oss-distributions/xnu/blob/main/osfmk/arm/commpage/commpage.c#L412 75 // Note that we ought to add assertions to check sysctlbyname parameters for 76 // these four CPU features, e.g., "hw.optional.arm.FEAT_AES", but the 77 // corresponding string names are not available before xnu-8019 version. 78 // Hence, assertions are omitted considering backward compatibility. 79 set_feature(CPU_AES); 80 set_feature(CPU_PMULL); 81 set_feature(CPU_SHA1); 82 set_feature(CPU_SHA2); 83 84 if (cpu_has("hw.optional.armv8_crc32")) { 85 set_feature(CPU_CRC32); 86 } 87 if (cpu_has("hw.optional.arm.FEAT_LSE") || 88 cpu_has("hw.optional.armv8_1_atomics")) { 89 set_feature(CPU_LSE); 90 } 91 if (cpu_has("hw.optional.arm.FEAT_SHA512") || 92 cpu_has("hw.optional.armv8_2_sha512")) { 93 set_feature(CPU_SHA512); 94 } 95 if (cpu_has("hw.optional.arm.FEAT_SHA3") || 96 cpu_has("hw.optional.armv8_2_sha3")) { 97 set_feature(CPU_SHA3); 98 } 99 100 int cache_line_size; 101 int hw_conf_cache_line[] = { CTL_HW, HW_CACHELINE }; 102 sysctllen = sizeof(cache_line_size); 103 if (sysctl(hw_conf_cache_line, 2, &cache_line_size, &sysctllen, nullptr, 0)) { 104 cache_line_size = 16; 105 } 106 _icache_line_size = 16; // minimal line length CCSIDR_EL1 can hold 107 _dcache_line_size = cache_line_size; 108 109 uint64_t dczid_el0; 110 __asm__ ( 111 "mrs %0, DCZID_EL0\n" 112 : "=r"(dczid_el0) 113 ); 114 if (!(dczid_el0 & 0x10)) { 115 _zva_length = 4 << (dczid_el0 & 0xf); 116 } 117 118 int family; 119 sysctllen = sizeof(family); 120 if (sysctlbyname("hw.cpufamily", &family, &sysctllen, nullptr, 0)) { 121 family = 0; 122 } 123 124 _model = family; 125 _cpu = CPU_APPLE; 126 } 127 128 void VM_Version::get_compatible_board(char *buf, int buflen) { 129 assert(buf != nullptr, "invalid argument"); 130 assert(buflen >= 1, "invalid argument"); 131 *buf = '\0'; 132 } 133 134 #ifdef __APPLE__ 135 136 bool VM_Version::is_cpu_emulated() { 137 return false; 138 } 139 140 #endif