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 18 unsigned cpuinfo; 19 20 /* Called both as constructor and (possibly) via other constructors. */ 21 unsigned __attribute__((constructor)) cpuinfo_init(void) 22 { 23 unsigned info = cpuinfo; 24 25 if (info) { 26 return info; 27 } 28 29 info = CPUINFO_ALWAYS; 30 31 #ifdef CONFIG_LINUX 32 unsigned long hwcap = qemu_getauxval(AT_HWCAP); 33 unsigned long hwcap2 = qemu_getauxval(AT_HWCAP2); 34 35 /* Version numbers are monotonic, and so imply all lower versions. */ 36 if (hwcap2 & PPC_FEATURE2_ARCH_3_1) { 37 info |= CPUINFO_V3_1 | CPUINFO_V3_0 | CPUINFO_V2_07 | CPUINFO_V2_06; 38 } else if (hwcap2 & PPC_FEATURE2_ARCH_3_00) { 39 info |= CPUINFO_V3_0 | CPUINFO_V2_07 | CPUINFO_V2_06; 40 } else if (hwcap2 & PPC_FEATURE2_ARCH_2_07) { 41 info |= CPUINFO_V2_07 | CPUINFO_V2_06; 42 } else if (hwcap & PPC_FEATURE_ARCH_2_06) { 43 info |= CPUINFO_V2_06; 44 } 45 46 if (hwcap2 & PPC_FEATURE2_ISEL) { 47 info |= CPUINFO_ISEL; 48 } 49 if (hwcap & PPC_FEATURE_HAS_ALTIVEC) { 50 info |= CPUINFO_ALTIVEC; 51 /* We only care about the portion of VSX that overlaps Altivec. */ 52 if (hwcap & PPC_FEATURE_HAS_VSX) { 53 info |= CPUINFO_VSX; 54 /* 55 * We use VSX especially for little-endian, but we should 56 * always have both anyway, since VSX came with Power7 57 * and crypto came with Power8. 58 */ 59 if (hwcap2 & PPC_FEATURE2_VEC_CRYPTO) { 60 info |= CPUINFO_CRYPTO; 61 } 62 } 63 } 64 #endif 65 66 cpuinfo = info; 67 return info; 68 } 69