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