1 /* 2 * SPDX-License-Identifier: GPL-2.0-or-later 3 * Host specific cpu identification for ppc. 4 */ 5 6 #include "qemu/osdep.h" 7 #include "host/cpuinfo.h" 8 9 #ifdef CONFIG_LINUX 10 # include <asm/cputable.h> 11 # ifdef CONFIG_GETAUXVAL 12 # include <sys/auxv.h> 13 # else 14 # include "elf.h" 15 # endif 16 #endif 17 #ifdef __FreeBSD__ 18 # include <machine/cpu.h> 19 # ifndef PPC_FEATURE2_ARCH_3_1 20 # define PPC_FEATURE2_ARCH_3_1 0 21 # endif 22 # define PPC_FEATURE2_VEC_CRYPTO PPC_FEATURE2_HAS_VEC_CRYPTO 23 #endif 24 25 unsigned cpuinfo; 26 27 /* Called both as constructor and (possibly) via other constructors. */ 28 unsigned __attribute__((constructor)) cpuinfo_init(void) 29 { 30 unsigned info = cpuinfo; 31 32 if (info) { 33 return info; 34 } 35 36 info = CPUINFO_ALWAYS; 37 38 #if defined(CONFIG_LINUX) || defined(__FreeBSD__) 39 unsigned long hwcap = qemu_getauxval(AT_HWCAP); 40 unsigned long hwcap2 = qemu_getauxval(AT_HWCAP2); 41 42 /* Version numbers are monotonic, and so imply all lower versions. */ 43 if (hwcap2 & PPC_FEATURE2_ARCH_3_1) { 44 info |= CPUINFO_V3_1 | CPUINFO_V3_0 | CPUINFO_V2_07 | CPUINFO_V2_06; 45 } else if (hwcap2 & PPC_FEATURE2_ARCH_3_00) { 46 info |= CPUINFO_V3_0 | CPUINFO_V2_07 | CPUINFO_V2_06; 47 } else if (hwcap2 & PPC_FEATURE2_ARCH_2_07) { 48 info |= CPUINFO_V2_07 | CPUINFO_V2_06; 49 } else if (hwcap & PPC_FEATURE_ARCH_2_06) { 50 info |= CPUINFO_V2_06; 51 } 52 53 if (hwcap2 & PPC_FEATURE2_ISEL) { 54 info |= CPUINFO_ISEL; 55 } 56 if (hwcap & PPC_FEATURE_HAS_ALTIVEC) { 57 info |= CPUINFO_ALTIVEC; 58 /* We only care about the portion of VSX that overlaps Altivec. */ 59 if (hwcap & PPC_FEATURE_HAS_VSX) { 60 info |= CPUINFO_VSX; 61 /* 62 * We use VSX especially for little-endian, but we should 63 * always have both anyway, since VSX came with Power7 64 * and crypto came with Power8. 65 */ 66 if (hwcap2 & PPC_FEATURE2_VEC_CRYPTO) { 67 info |= CPUINFO_CRYPTO; 68 } 69 } 70 } 71 #endif 72 73 cpuinfo = info; 74 return info; 75 } 76