xref: /qemu/util/cpuinfo-ppc.c (revision 1d513e06)
1623d7e35SRichard Henderson /*
2623d7e35SRichard Henderson  * SPDX-License-Identifier: GPL-2.0-or-later
3d02d06f8SMichael Tokarev  * Host specific cpu identification for ppc.
4623d7e35SRichard Henderson  */
5623d7e35SRichard Henderson 
6623d7e35SRichard Henderson #include "qemu/osdep.h"
7623d7e35SRichard Henderson #include "host/cpuinfo.h"
8623d7e35SRichard Henderson 
91d513e06SNatanael Copa #include <asm/cputable.h>
10623d7e35SRichard Henderson #ifdef CONFIG_GETAUXVAL
11623d7e35SRichard Henderson # include <sys/auxv.h>
12623d7e35SRichard Henderson #else
13623d7e35SRichard Henderson # include "elf.h"
14623d7e35SRichard Henderson #endif
15623d7e35SRichard Henderson 
16623d7e35SRichard Henderson unsigned cpuinfo;
17623d7e35SRichard Henderson 
18623d7e35SRichard Henderson /* Called both as constructor and (possibly) via other constructors. */
cpuinfo_init(void)19623d7e35SRichard Henderson unsigned __attribute__((constructor)) cpuinfo_init(void)
20623d7e35SRichard Henderson {
21623d7e35SRichard Henderson     unsigned info = cpuinfo;
22623d7e35SRichard Henderson     unsigned long hwcap, hwcap2;
23623d7e35SRichard Henderson 
24623d7e35SRichard Henderson     if (info) {
25623d7e35SRichard Henderson         return info;
26623d7e35SRichard Henderson     }
27623d7e35SRichard Henderson 
28623d7e35SRichard Henderson     hwcap = qemu_getauxval(AT_HWCAP);
29623d7e35SRichard Henderson     hwcap2 = qemu_getauxval(AT_HWCAP2);
30623d7e35SRichard Henderson     info = CPUINFO_ALWAYS;
31623d7e35SRichard Henderson 
32623d7e35SRichard Henderson     /* Version numbers are monotonic, and so imply all lower versions. */
33623d7e35SRichard Henderson     if (hwcap2 & PPC_FEATURE2_ARCH_3_1) {
34623d7e35SRichard Henderson         info |= CPUINFO_V3_1 | CPUINFO_V3_0 | CPUINFO_V2_07 | CPUINFO_V2_06;
35623d7e35SRichard Henderson     } else if (hwcap2 & PPC_FEATURE2_ARCH_3_00) {
36623d7e35SRichard Henderson         info |= CPUINFO_V3_0 | CPUINFO_V2_07 | CPUINFO_V2_06;
37623d7e35SRichard Henderson     } else if (hwcap2 & PPC_FEATURE2_ARCH_2_07) {
38623d7e35SRichard Henderson         info |= CPUINFO_V2_07 | CPUINFO_V2_06;
39623d7e35SRichard Henderson     } else if (hwcap & PPC_FEATURE_ARCH_2_06) {
40623d7e35SRichard Henderson         info |= CPUINFO_V2_06;
41623d7e35SRichard Henderson     }
42623d7e35SRichard Henderson 
431d513e06SNatanael Copa     if (hwcap2 & PPC_FEATURE2_ISEL) {
44623d7e35SRichard Henderson         info |= CPUINFO_ISEL;
45623d7e35SRichard Henderson     }
46623d7e35SRichard Henderson     if (hwcap & PPC_FEATURE_HAS_ALTIVEC) {
47623d7e35SRichard Henderson         info |= CPUINFO_ALTIVEC;
48623d7e35SRichard Henderson         /* We only care about the portion of VSX that overlaps Altivec. */
49623d7e35SRichard Henderson         if (hwcap & PPC_FEATURE_HAS_VSX) {
50623d7e35SRichard Henderson             info |= CPUINFO_VSX;
5157357322SRichard Henderson             /*
5257357322SRichard Henderson              * We use VSX especially for little-endian, but we should
5357357322SRichard Henderson              * always have both anyway, since VSX came with Power7
5457357322SRichard Henderson              * and crypto came with Power8.
5557357322SRichard Henderson              */
561d513e06SNatanael Copa             if (hwcap2 & PPC_FEATURE2_VEC_CRYPTO) {
5757357322SRichard Henderson                 info |= CPUINFO_CRYPTO;
5857357322SRichard Henderson             }
59623d7e35SRichard Henderson         }
60623d7e35SRichard Henderson     }
61623d7e35SRichard Henderson 
62623d7e35SRichard Henderson     cpuinfo = info;
63623d7e35SRichard Henderson     return info;
64623d7e35SRichard Henderson }
65