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