Statistics
| Branch: | Revision:

root / target-i386 / cpuid.c @ db0ad1ba

History | View | Annotate | Download (40.9 kB)

1 c6dc6f63 Andre Przywara
/*
2 c6dc6f63 Andre Przywara
 *  i386 CPUID helper functions
3 c6dc6f63 Andre Przywara
 *
4 c6dc6f63 Andre Przywara
 *  Copyright (c) 2003 Fabrice Bellard
5 c6dc6f63 Andre Przywara
 *
6 c6dc6f63 Andre Przywara
 * This library is free software; you can redistribute it and/or
7 c6dc6f63 Andre Przywara
 * modify it under the terms of the GNU Lesser General Public
8 c6dc6f63 Andre Przywara
 * License as published by the Free Software Foundation; either
9 c6dc6f63 Andre Przywara
 * version 2 of the License, or (at your option) any later version.
10 c6dc6f63 Andre Przywara
 *
11 c6dc6f63 Andre Przywara
 * This library is distributed in the hope that it will be useful,
12 c6dc6f63 Andre Przywara
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 c6dc6f63 Andre Przywara
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 c6dc6f63 Andre Przywara
 * Lesser General Public License for more details.
15 c6dc6f63 Andre Przywara
 *
16 c6dc6f63 Andre Przywara
 * You should have received a copy of the GNU Lesser General Public
17 c6dc6f63 Andre Przywara
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 c6dc6f63 Andre Przywara
 */
19 c6dc6f63 Andre Przywara
#include <stdlib.h>
20 c6dc6f63 Andre Przywara
#include <stdio.h>
21 c6dc6f63 Andre Przywara
#include <string.h>
22 c6dc6f63 Andre Przywara
#include <inttypes.h>
23 c6dc6f63 Andre Przywara
24 c6dc6f63 Andre Przywara
#include "cpu.h"
25 c6dc6f63 Andre Przywara
#include "kvm.h"
26 c6dc6f63 Andre Przywara
27 c6dc6f63 Andre Przywara
#include "qemu-option.h"
28 c6dc6f63 Andre Przywara
#include "qemu-config.h"
29 c6dc6f63 Andre Przywara
30 c6dc6f63 Andre Przywara
/* feature flags taken from "Intel Processor Identification and the CPUID
31 c6dc6f63 Andre Przywara
 * Instruction" and AMD's "CPUID Specification".  In cases of disagreement
32 c6dc6f63 Andre Przywara
 * between feature naming conventions, aliases may be added.
33 c6dc6f63 Andre Przywara
 */
34 c6dc6f63 Andre Przywara
static const char *feature_name[] = {
35 c6dc6f63 Andre Przywara
    "fpu", "vme", "de", "pse",
36 c6dc6f63 Andre Przywara
    "tsc", "msr", "pae", "mce",
37 c6dc6f63 Andre Przywara
    "cx8", "apic", NULL, "sep",
38 c6dc6f63 Andre Przywara
    "mtrr", "pge", "mca", "cmov",
39 c6dc6f63 Andre Przywara
    "pat", "pse36", "pn" /* Intel psn */, "clflush" /* Intel clfsh */,
40 c6dc6f63 Andre Przywara
    NULL, "ds" /* Intel dts */, "acpi", "mmx",
41 c6dc6f63 Andre Przywara
    "fxsr", "sse", "sse2", "ss",
42 c6dc6f63 Andre Przywara
    "ht" /* Intel htt */, "tm", "ia64", "pbe",
43 c6dc6f63 Andre Przywara
};
44 c6dc6f63 Andre Przywara
static const char *ext_feature_name[] = {
45 e117f772 Andre Przywara
    "pni|sse3" /* Intel,AMD sse3 */, "pclmuldq", "dtes64", "monitor",
46 e117f772 Andre Przywara
    "ds_cpl", "vmx", "smx", "est",
47 c6dc6f63 Andre Przywara
    "tm2", "ssse3", "cid", NULL,
48 e117f772 Andre Przywara
    "fma", "cx16", "xtpr", "pdcm",
49 c6dc6f63 Andre Przywara
    NULL, NULL, "dca", "sse4.1|sse4_1",
50 e117f772 Andre Przywara
    "sse4.2|sse4_2", "x2apic", "movbe", "popcnt",
51 e117f772 Andre Przywara
    NULL, "aes", "xsave", "osxsave",
52 e117f772 Andre Przywara
    "avx", NULL, NULL, "hypervisor",
53 c6dc6f63 Andre Przywara
};
54 c6dc6f63 Andre Przywara
static const char *ext2_feature_name[] = {
55 c6dc6f63 Andre Przywara
    "fpu", "vme", "de", "pse",
56 c6dc6f63 Andre Przywara
    "tsc", "msr", "pae", "mce",
57 c6dc6f63 Andre Przywara
    "cx8" /* AMD CMPXCHG8B */, "apic", NULL, "syscall",
58 c6dc6f63 Andre Przywara
    "mtrr", "pge", "mca", "cmov",
59 c6dc6f63 Andre Przywara
    "pat", "pse36", NULL, NULL /* Linux mp */,
60 c6dc6f63 Andre Przywara
    "nx" /* Intel xd */, NULL, "mmxext", "mmx",
61 c6dc6f63 Andre Przywara
    "fxsr", "fxsr_opt" /* AMD ffxsr */, "pdpe1gb" /* AMD Page1GB */, "rdtscp",
62 c6dc6f63 Andre Przywara
    NULL, "lm" /* Intel 64 */, "3dnowext", "3dnow",
63 c6dc6f63 Andre Przywara
};
64 c6dc6f63 Andre Przywara
static const char *ext3_feature_name[] = {
65 c6dc6f63 Andre Przywara
    "lahf_lm" /* AMD LahfSahf */, "cmp_legacy", "svm", "extapic" /* AMD ExtApicSpace */,
66 c6dc6f63 Andre Przywara
    "cr8legacy" /* AMD AltMovCr8 */, "abm", "sse4a", "misalignsse",
67 e117f772 Andre Przywara
    "3dnowprefetch", "osvw", "ibs", "xop",
68 c6dc6f63 Andre Przywara
    "skinit", "wdt", NULL, NULL,
69 e117f772 Andre Przywara
    "fma4", NULL, "cvt16", "nodeid_msr",
70 c6dc6f63 Andre Przywara
    NULL, NULL, NULL, NULL,
71 c6dc6f63 Andre Przywara
    NULL, NULL, NULL, NULL,
72 c6dc6f63 Andre Przywara
    NULL, NULL, NULL, NULL,
73 c6dc6f63 Andre Przywara
};
74 c6dc6f63 Andre Przywara
75 c6dc6f63 Andre Przywara
static const char *kvm_feature_name[] = {
76 c6dc6f63 Andre Przywara
    "kvmclock", "kvm_nopiodelay", "kvm_mmu", NULL, NULL, NULL, NULL, NULL,
77 c6dc6f63 Andre Przywara
    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
78 c6dc6f63 Andre Przywara
    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
79 c6dc6f63 Andre Przywara
    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
80 c6dc6f63 Andre Przywara
};
81 c6dc6f63 Andre Przywara
82 c6dc6f63 Andre Przywara
/* collects per-function cpuid data
83 c6dc6f63 Andre Przywara
 */
84 c6dc6f63 Andre Przywara
typedef struct model_features_t {
85 c6dc6f63 Andre Przywara
    uint32_t *guest_feat;
86 c6dc6f63 Andre Przywara
    uint32_t *host_feat;
87 c6dc6f63 Andre Przywara
    uint32_t check_feat;
88 c6dc6f63 Andre Przywara
    const char **flag_names;
89 c6dc6f63 Andre Przywara
    uint32_t cpuid;
90 c6dc6f63 Andre Przywara
    } model_features_t;
91 c6dc6f63 Andre Przywara
92 c6dc6f63 Andre Przywara
int check_cpuid = 0;
93 c6dc6f63 Andre Przywara
int enforce_cpuid = 0;
94 c6dc6f63 Andre Przywara
95 bdde476a Andre Przywara
static void host_cpuid(uint32_t function, uint32_t count,
96 bdde476a Andre Przywara
                       uint32_t *eax, uint32_t *ebx,
97 bdde476a Andre Przywara
                       uint32_t *ecx, uint32_t *edx)
98 bdde476a Andre Przywara
{
99 bdde476a Andre Przywara
#if defined(CONFIG_KVM)
100 bdde476a Andre Przywara
    uint32_t vec[4];
101 bdde476a Andre Przywara
102 bdde476a Andre Przywara
#ifdef __x86_64__
103 bdde476a Andre Przywara
    asm volatile("cpuid"
104 bdde476a Andre Przywara
                 : "=a"(vec[0]), "=b"(vec[1]),
105 bdde476a Andre Przywara
                   "=c"(vec[2]), "=d"(vec[3])
106 bdde476a Andre Przywara
                 : "0"(function), "c"(count) : "cc");
107 bdde476a Andre Przywara
#else
108 bdde476a Andre Przywara
    asm volatile("pusha \n\t"
109 bdde476a Andre Przywara
                 "cpuid \n\t"
110 bdde476a Andre Przywara
                 "mov %%eax, 0(%2) \n\t"
111 bdde476a Andre Przywara
                 "mov %%ebx, 4(%2) \n\t"
112 bdde476a Andre Przywara
                 "mov %%ecx, 8(%2) \n\t"
113 bdde476a Andre Przywara
                 "mov %%edx, 12(%2) \n\t"
114 bdde476a Andre Przywara
                 "popa"
115 bdde476a Andre Przywara
                 : : "a"(function), "c"(count), "S"(vec)
116 bdde476a Andre Przywara
                 : "memory", "cc");
117 bdde476a Andre Przywara
#endif
118 bdde476a Andre Przywara
119 bdde476a Andre Przywara
    if (eax)
120 2f7a21c4 Aurelien Jarno
        *eax = vec[0];
121 bdde476a Andre Przywara
    if (ebx)
122 2f7a21c4 Aurelien Jarno
        *ebx = vec[1];
123 bdde476a Andre Przywara
    if (ecx)
124 2f7a21c4 Aurelien Jarno
        *ecx = vec[2];
125 bdde476a Andre Przywara
    if (edx)
126 2f7a21c4 Aurelien Jarno
        *edx = vec[3];
127 bdde476a Andre Przywara
#endif
128 bdde476a Andre Przywara
}
129 c6dc6f63 Andre Przywara
130 c6dc6f63 Andre Przywara
#define iswhite(c) ((c) && ((c) <= ' ' || '~' < (c)))
131 c6dc6f63 Andre Przywara
132 c6dc6f63 Andre Przywara
/* general substring compare of *[s1..e1) and *[s2..e2).  sx is start of
133 c6dc6f63 Andre Przywara
 * a substring.  ex if !NULL points to the first char after a substring,
134 c6dc6f63 Andre Przywara
 * otherwise the string is assumed to sized by a terminating nul.
135 c6dc6f63 Andre Przywara
 * Return lexical ordering of *s1:*s2.
136 c6dc6f63 Andre Przywara
 */
137 c6dc6f63 Andre Przywara
static int sstrcmp(const char *s1, const char *e1, const char *s2,
138 c6dc6f63 Andre Przywara
    const char *e2)
139 c6dc6f63 Andre Przywara
{
140 c6dc6f63 Andre Przywara
    for (;;) {
141 c6dc6f63 Andre Przywara
        if (!*s1 || !*s2 || *s1 != *s2)
142 c6dc6f63 Andre Przywara
            return (*s1 - *s2);
143 c6dc6f63 Andre Przywara
        ++s1, ++s2;
144 c6dc6f63 Andre Przywara
        if (s1 == e1 && s2 == e2)
145 c6dc6f63 Andre Przywara
            return (0);
146 c6dc6f63 Andre Przywara
        else if (s1 == e1)
147 c6dc6f63 Andre Przywara
            return (*s2);
148 c6dc6f63 Andre Przywara
        else if (s2 == e2)
149 c6dc6f63 Andre Przywara
            return (*s1);
150 c6dc6f63 Andre Przywara
    }
151 c6dc6f63 Andre Przywara
}
152 c6dc6f63 Andre Przywara
153 c6dc6f63 Andre Przywara
/* compare *[s..e) to *altstr.  *altstr may be a simple string or multiple
154 c6dc6f63 Andre Przywara
 * '|' delimited (possibly empty) strings in which case search for a match
155 c6dc6f63 Andre Przywara
 * within the alternatives proceeds left to right.  Return 0 for success,
156 c6dc6f63 Andre Przywara
 * non-zero otherwise.
157 c6dc6f63 Andre Przywara
 */
158 c6dc6f63 Andre Przywara
static int altcmp(const char *s, const char *e, const char *altstr)
159 c6dc6f63 Andre Przywara
{
160 c6dc6f63 Andre Przywara
    const char *p, *q;
161 c6dc6f63 Andre Przywara
162 c6dc6f63 Andre Przywara
    for (q = p = altstr; ; ) {
163 c6dc6f63 Andre Przywara
        while (*p && *p != '|')
164 c6dc6f63 Andre Przywara
            ++p;
165 c6dc6f63 Andre Przywara
        if ((q == p && !*s) || (q != p && !sstrcmp(s, e, q, p)))
166 c6dc6f63 Andre Przywara
            return (0);
167 c6dc6f63 Andre Przywara
        if (!*p)
168 c6dc6f63 Andre Przywara
            return (1);
169 c6dc6f63 Andre Przywara
        else
170 c6dc6f63 Andre Przywara
            q = ++p;
171 c6dc6f63 Andre Przywara
    }
172 c6dc6f63 Andre Przywara
}
173 c6dc6f63 Andre Przywara
174 c6dc6f63 Andre Przywara
/* search featureset for flag *[s..e), if found set corresponding bit in
175 c6dc6f63 Andre Przywara
 * *pval and return success, otherwise return zero
176 c6dc6f63 Andre Przywara
 */
177 c6dc6f63 Andre Przywara
static int lookup_feature(uint32_t *pval, const char *s, const char *e,
178 c6dc6f63 Andre Przywara
    const char **featureset)
179 c6dc6f63 Andre Przywara
{
180 c6dc6f63 Andre Przywara
    uint32_t mask;
181 c6dc6f63 Andre Przywara
    const char **ppc;
182 c6dc6f63 Andre Przywara
183 c6dc6f63 Andre Przywara
    for (mask = 1, ppc = featureset; mask; mask <<= 1, ++ppc)
184 c6dc6f63 Andre Przywara
        if (*ppc && !altcmp(s, e, *ppc)) {
185 c6dc6f63 Andre Przywara
            *pval |= mask;
186 c6dc6f63 Andre Przywara
            break;
187 c6dc6f63 Andre Przywara
        }
188 c6dc6f63 Andre Przywara
    return (mask ? 1 : 0);
189 c6dc6f63 Andre Przywara
}
190 c6dc6f63 Andre Przywara
191 c6dc6f63 Andre Przywara
static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features,
192 c6dc6f63 Andre Przywara
                                    uint32_t *ext_features,
193 c6dc6f63 Andre Przywara
                                    uint32_t *ext2_features,
194 c6dc6f63 Andre Przywara
                                    uint32_t *ext3_features,
195 c6dc6f63 Andre Przywara
                                    uint32_t *kvm_features)
196 c6dc6f63 Andre Przywara
{
197 c6dc6f63 Andre Przywara
    if (!lookup_feature(features, flagname, NULL, feature_name) &&
198 c6dc6f63 Andre Przywara
        !lookup_feature(ext_features, flagname, NULL, ext_feature_name) &&
199 c6dc6f63 Andre Przywara
        !lookup_feature(ext2_features, flagname, NULL, ext2_feature_name) &&
200 c6dc6f63 Andre Przywara
        !lookup_feature(ext3_features, flagname, NULL, ext3_feature_name) &&
201 c6dc6f63 Andre Przywara
        !lookup_feature(kvm_features, flagname, NULL, kvm_feature_name))
202 c6dc6f63 Andre Przywara
            fprintf(stderr, "CPU feature %s not found\n", flagname);
203 c6dc6f63 Andre Przywara
}
204 c6dc6f63 Andre Przywara
205 c6dc6f63 Andre Przywara
typedef struct x86_def_t {
206 c6dc6f63 Andre Przywara
    struct x86_def_t *next;
207 c6dc6f63 Andre Przywara
    const char *name;
208 c6dc6f63 Andre Przywara
    uint32_t level;
209 c6dc6f63 Andre Przywara
    uint32_t vendor1, vendor2, vendor3;
210 c6dc6f63 Andre Przywara
    int family;
211 c6dc6f63 Andre Przywara
    int model;
212 c6dc6f63 Andre Przywara
    int stepping;
213 c6dc6f63 Andre Przywara
    uint32_t features, ext_features, ext2_features, ext3_features, kvm_features;
214 c6dc6f63 Andre Przywara
    uint32_t xlevel;
215 c6dc6f63 Andre Przywara
    char model_id[48];
216 c6dc6f63 Andre Przywara
    int vendor_override;
217 c6dc6f63 Andre Przywara
    uint32_t flags;
218 c6dc6f63 Andre Przywara
} x86_def_t;
219 c6dc6f63 Andre Przywara
220 c6dc6f63 Andre Przywara
#define I486_FEATURES (CPUID_FP87 | CPUID_VME | CPUID_PSE)
221 c6dc6f63 Andre Przywara
#define PENTIUM_FEATURES (I486_FEATURES | CPUID_DE | CPUID_TSC | \
222 c6dc6f63 Andre Przywara
          CPUID_MSR | CPUID_MCE | CPUID_CX8 | CPUID_MMX | CPUID_APIC)
223 c6dc6f63 Andre Przywara
#define PENTIUM2_FEATURES (PENTIUM_FEATURES | CPUID_PAE | CPUID_SEP | \
224 c6dc6f63 Andre Przywara
          CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_CMOV | CPUID_PAT | \
225 c6dc6f63 Andre Przywara
          CPUID_PSE36 | CPUID_FXSR)
226 c6dc6f63 Andre Przywara
#define PENTIUM3_FEATURES (PENTIUM2_FEATURES | CPUID_SSE)
227 c6dc6f63 Andre Przywara
#define PPRO_FEATURES (CPUID_FP87 | CPUID_DE | CPUID_PSE | CPUID_TSC | \
228 c6dc6f63 Andre Przywara
          CPUID_MSR | CPUID_MCE | CPUID_CX8 | CPUID_PGE | CPUID_CMOV | \
229 c6dc6f63 Andre Przywara
          CPUID_PAT | CPUID_FXSR | CPUID_MMX | CPUID_SSE | CPUID_SSE2 | \
230 c6dc6f63 Andre Przywara
          CPUID_PAE | CPUID_SEP | CPUID_APIC)
231 42673936 Andre Przywara
#define EXT2_FEATURE_MASK 0x0183F3FF
232 c6dc6f63 Andre Przywara
233 551a2dec Andre Przywara
#define TCG_FEATURES (CPUID_FP87 | CPUID_PSE | CPUID_TSC | CPUID_MSR | \
234 551a2dec Andre Przywara
          CPUID_PAE | CPUID_MCE | CPUID_CX8 | CPUID_APIC | CPUID_SEP | \
235 551a2dec Andre Przywara
          CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_CMOV | CPUID_PAT | \
236 551a2dec Andre Przywara
          CPUID_PSE36 | CPUID_CLFLUSH | CPUID_ACPI | CPUID_MMX | \
237 551a2dec Andre Przywara
          CPUID_FXSR | CPUID_SSE | CPUID_SSE2 | CPUID_SS)
238 8560efed Aurelien Jarno
          /* partly implemented:
239 8560efed Aurelien Jarno
          CPUID_MTRR, CPUID_MCA, CPUID_CLFLUSH (needed for Win64)
240 8560efed Aurelien Jarno
          CPUID_PSE36 (needed for Solaris) */
241 8560efed Aurelien Jarno
          /* missing:
242 8560efed Aurelien Jarno
          CPUID_VME, CPUID_DTS, CPUID_SS, CPUID_HT, CPUID_TM, CPUID_PBE */
243 551a2dec Andre Przywara
#define TCG_EXT_FEATURES (CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | \
244 8713f8ff Andi Kleen
          CPUID_EXT_CX16 | CPUID_EXT_POPCNT | \
245 551a2dec Andre Przywara
          CPUID_EXT_HYPERVISOR)
246 8560efed Aurelien Jarno
          /* missing:
247 8560efed Aurelien Jarno
          CPUID_EXT_DTES64, CPUID_EXT_DSCPL, CPUID_EXT_VMX, CPUID_EXT_EST,
248 8713f8ff Andi Kleen
          CPUID_EXT_TM2, CPUID_EXT_XTPR, CPUID_EXT_PDCM, CPUID_EXT_XSAVE */
249 551a2dec Andre Przywara
#define TCG_EXT2_FEATURES ((TCG_FEATURES & EXT2_FEATURE_MASK) | \
250 551a2dec Andre Przywara
          CPUID_EXT2_NX | CPUID_EXT2_MMXEXT | CPUID_EXT2_RDTSCP | \
251 551a2dec Andre Przywara
          CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT)
252 8560efed Aurelien Jarno
          /* missing:
253 8560efed Aurelien Jarno
          CPUID_EXT2_PDPE1GB */
254 551a2dec Andre Przywara
#define TCG_EXT3_FEATURES (CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM | \
255 551a2dec Andre Przywara
          CPUID_EXT3_CR8LEG | CPUID_EXT3_ABM | CPUID_EXT3_SSE4A)
256 551a2dec Andre Przywara
257 c6dc6f63 Andre Przywara
/* maintains list of cpu model definitions
258 c6dc6f63 Andre Przywara
 */
259 c6dc6f63 Andre Przywara
static x86_def_t *x86_defs = {NULL};
260 c6dc6f63 Andre Przywara
261 c6dc6f63 Andre Przywara
/* built-in cpu model definitions (deprecated)
262 c6dc6f63 Andre Przywara
 */
263 c6dc6f63 Andre Przywara
static x86_def_t builtin_x86_defs[] = {
264 c6dc6f63 Andre Przywara
    {
265 c6dc6f63 Andre Przywara
        .name = "qemu64",
266 c6dc6f63 Andre Przywara
        .level = 4,
267 c6dc6f63 Andre Przywara
        .vendor1 = CPUID_VENDOR_AMD_1,
268 c6dc6f63 Andre Przywara
        .vendor2 = CPUID_VENDOR_AMD_2,
269 c6dc6f63 Andre Przywara
        .vendor3 = CPUID_VENDOR_AMD_3,
270 c6dc6f63 Andre Przywara
        .family = 6,
271 c6dc6f63 Andre Przywara
        .model = 2,
272 c6dc6f63 Andre Przywara
        .stepping = 3,
273 c6dc6f63 Andre Przywara
        .features = PPRO_FEATURES |
274 c6dc6f63 Andre Przywara
            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
275 c6dc6f63 Andre Przywara
            CPUID_PSE36,
276 c6dc6f63 Andre Przywara
        .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_CX16 | CPUID_EXT_POPCNT,
277 42673936 Andre Przywara
        .ext2_features = (PPRO_FEATURES & EXT2_FEATURE_MASK) |
278 c6dc6f63 Andre Przywara
            CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
279 c6dc6f63 Andre Przywara
        .ext3_features = CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM |
280 c6dc6f63 Andre Przywara
            CPUID_EXT3_ABM | CPUID_EXT3_SSE4A,
281 c6dc6f63 Andre Przywara
        .xlevel = 0x8000000A,
282 c6dc6f63 Andre Przywara
        .model_id = "QEMU Virtual CPU version " QEMU_VERSION,
283 c6dc6f63 Andre Przywara
    },
284 c6dc6f63 Andre Przywara
    {
285 c6dc6f63 Andre Przywara
        .name = "phenom",
286 c6dc6f63 Andre Przywara
        .level = 5,
287 c6dc6f63 Andre Przywara
        .vendor1 = CPUID_VENDOR_AMD_1,
288 c6dc6f63 Andre Przywara
        .vendor2 = CPUID_VENDOR_AMD_2,
289 c6dc6f63 Andre Przywara
        .vendor3 = CPUID_VENDOR_AMD_3,
290 c6dc6f63 Andre Przywara
        .family = 16,
291 c6dc6f63 Andre Przywara
        .model = 2,
292 c6dc6f63 Andre Przywara
        .stepping = 3,
293 c6dc6f63 Andre Przywara
        .features = PPRO_FEATURES |
294 c6dc6f63 Andre Przywara
            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
295 8560efed Aurelien Jarno
            CPUID_PSE36 | CPUID_VME | CPUID_HT,
296 c6dc6f63 Andre Przywara
        .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_CX16 |
297 c6dc6f63 Andre Przywara
            CPUID_EXT_POPCNT,
298 42673936 Andre Przywara
        .ext2_features = (PPRO_FEATURES & EXT2_FEATURE_MASK) |
299 c6dc6f63 Andre Przywara
            CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX |
300 c6dc6f63 Andre Przywara
            CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT | CPUID_EXT2_MMXEXT |
301 8560efed Aurelien Jarno
            CPUID_EXT2_FFXSR | CPUID_EXT2_PDPE1GB | CPUID_EXT2_RDTSCP,
302 c6dc6f63 Andre Przywara
        /* Missing: CPUID_EXT3_CMP_LEG, CPUID_EXT3_EXTAPIC,
303 c6dc6f63 Andre Przywara
                    CPUID_EXT3_CR8LEG,
304 c6dc6f63 Andre Przywara
                    CPUID_EXT3_MISALIGNSSE, CPUID_EXT3_3DNOWPREFETCH,
305 c6dc6f63 Andre Przywara
                    CPUID_EXT3_OSVW, CPUID_EXT3_IBS */
306 c6dc6f63 Andre Przywara
        .ext3_features = CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM |
307 c6dc6f63 Andre Przywara
            CPUID_EXT3_ABM | CPUID_EXT3_SSE4A,
308 c6dc6f63 Andre Przywara
        .xlevel = 0x8000001A,
309 c6dc6f63 Andre Przywara
        .model_id = "AMD Phenom(tm) 9550 Quad-Core Processor"
310 c6dc6f63 Andre Przywara
    },
311 c6dc6f63 Andre Przywara
    {
312 c6dc6f63 Andre Przywara
        .name = "core2duo",
313 c6dc6f63 Andre Przywara
        .level = 10,
314 c6dc6f63 Andre Przywara
        .family = 6,
315 c6dc6f63 Andre Przywara
        .model = 15,
316 c6dc6f63 Andre Przywara
        .stepping = 11,
317 c6dc6f63 Andre Przywara
        .features = PPRO_FEATURES |
318 c6dc6f63 Andre Przywara
            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
319 8560efed Aurelien Jarno
            CPUID_PSE36 | CPUID_VME | CPUID_DTS | CPUID_ACPI | CPUID_SS |
320 8560efed Aurelien Jarno
            CPUID_HT | CPUID_TM | CPUID_PBE,
321 8560efed Aurelien Jarno
        .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_SSSE3 |
322 8560efed Aurelien Jarno
            CPUID_EXT_DTES64 | CPUID_EXT_DSCPL | CPUID_EXT_VMX | CPUID_EXT_EST |
323 8560efed Aurelien Jarno
            CPUID_EXT_TM2 | CPUID_EXT_CX16 | CPUID_EXT_XTPR | CPUID_EXT_PDCM,
324 c6dc6f63 Andre Przywara
        .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
325 c6dc6f63 Andre Przywara
        .ext3_features = CPUID_EXT3_LAHF_LM,
326 c6dc6f63 Andre Przywara
        .xlevel = 0x80000008,
327 c6dc6f63 Andre Przywara
        .model_id = "Intel(R) Core(TM)2 Duo CPU     T7700  @ 2.40GHz",
328 c6dc6f63 Andre Przywara
    },
329 c6dc6f63 Andre Przywara
    {
330 c6dc6f63 Andre Przywara
        .name = "kvm64",
331 c6dc6f63 Andre Przywara
        .level = 5,
332 c6dc6f63 Andre Przywara
        .vendor1 = CPUID_VENDOR_INTEL_1,
333 c6dc6f63 Andre Przywara
        .vendor2 = CPUID_VENDOR_INTEL_2,
334 c6dc6f63 Andre Przywara
        .vendor3 = CPUID_VENDOR_INTEL_3,
335 c6dc6f63 Andre Przywara
        .family = 15,
336 c6dc6f63 Andre Przywara
        .model = 6,
337 c6dc6f63 Andre Przywara
        .stepping = 1,
338 c6dc6f63 Andre Przywara
        /* Missing: CPUID_VME, CPUID_HT */
339 c6dc6f63 Andre Przywara
        .features = PPRO_FEATURES |
340 c6dc6f63 Andre Przywara
            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
341 c6dc6f63 Andre Przywara
            CPUID_PSE36,
342 c6dc6f63 Andre Przywara
        /* Missing: CPUID_EXT_POPCNT, CPUID_EXT_MONITOR */
343 c6dc6f63 Andre Przywara
        .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_CX16,
344 c6dc6f63 Andre Przywara
        /* Missing: CPUID_EXT2_PDPE1GB, CPUID_EXT2_RDTSCP */
345 42673936 Andre Przywara
        .ext2_features = (PPRO_FEATURES & EXT2_FEATURE_MASK) |
346 c6dc6f63 Andre Przywara
            CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
347 c6dc6f63 Andre Przywara
        /* Missing: CPUID_EXT3_LAHF_LM, CPUID_EXT3_CMP_LEG, CPUID_EXT3_EXTAPIC,
348 c6dc6f63 Andre Przywara
                    CPUID_EXT3_CR8LEG, CPUID_EXT3_ABM, CPUID_EXT3_SSE4A,
349 c6dc6f63 Andre Przywara
                    CPUID_EXT3_MISALIGNSSE, CPUID_EXT3_3DNOWPREFETCH,
350 c6dc6f63 Andre Przywara
                    CPUID_EXT3_OSVW, CPUID_EXT3_IBS, CPUID_EXT3_SVM */
351 c6dc6f63 Andre Przywara
        .ext3_features = 0,
352 c6dc6f63 Andre Przywara
        .xlevel = 0x80000008,
353 c6dc6f63 Andre Przywara
        .model_id = "Common KVM processor"
354 c6dc6f63 Andre Przywara
    },
355 c6dc6f63 Andre Przywara
    {
356 c6dc6f63 Andre Przywara
        .name = "qemu32",
357 c6dc6f63 Andre Przywara
        .level = 4,
358 c6dc6f63 Andre Przywara
        .family = 6,
359 c6dc6f63 Andre Przywara
        .model = 3,
360 c6dc6f63 Andre Przywara
        .stepping = 3,
361 c6dc6f63 Andre Przywara
        .features = PPRO_FEATURES,
362 c6dc6f63 Andre Przywara
        .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_POPCNT,
363 58012d66 Andre Przywara
        .xlevel = 0x80000004,
364 c6dc6f63 Andre Przywara
        .model_id = "QEMU Virtual CPU version " QEMU_VERSION,
365 c6dc6f63 Andre Przywara
    },
366 c6dc6f63 Andre Przywara
    {
367 eafaf1e5 Andre Przywara
        .name = "kvm32",
368 eafaf1e5 Andre Przywara
        .level = 5,
369 eafaf1e5 Andre Przywara
        .family = 15,
370 eafaf1e5 Andre Przywara
        .model = 6,
371 eafaf1e5 Andre Przywara
        .stepping = 1,
372 eafaf1e5 Andre Przywara
        .features = PPRO_FEATURES |
373 eafaf1e5 Andre Przywara
            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_PSE36,
374 eafaf1e5 Andre Przywara
        .ext_features = CPUID_EXT_SSE3,
375 eafaf1e5 Andre Przywara
        .ext2_features = PPRO_FEATURES & EXT2_FEATURE_MASK,
376 eafaf1e5 Andre Przywara
        .ext3_features = 0,
377 eafaf1e5 Andre Przywara
        .xlevel = 0x80000008,
378 eafaf1e5 Andre Przywara
        .model_id = "Common 32-bit KVM processor"
379 eafaf1e5 Andre Przywara
    },
380 eafaf1e5 Andre Przywara
    {
381 c6dc6f63 Andre Przywara
        .name = "coreduo",
382 c6dc6f63 Andre Przywara
        .level = 10,
383 c6dc6f63 Andre Przywara
        .family = 6,
384 c6dc6f63 Andre Przywara
        .model = 14,
385 c6dc6f63 Andre Przywara
        .stepping = 8,
386 c6dc6f63 Andre Przywara
        .features = PPRO_FEATURES | CPUID_VME |
387 8560efed Aurelien Jarno
            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_DTS | CPUID_ACPI |
388 8560efed Aurelien Jarno
            CPUID_SS | CPUID_HT | CPUID_TM | CPUID_PBE,
389 8560efed Aurelien Jarno
        .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_VMX |
390 8560efed Aurelien Jarno
            CPUID_EXT_EST | CPUID_EXT_TM2 | CPUID_EXT_XTPR | CPUID_EXT_PDCM,
391 c6dc6f63 Andre Przywara
        .ext2_features = CPUID_EXT2_NX,
392 c6dc6f63 Andre Przywara
        .xlevel = 0x80000008,
393 c6dc6f63 Andre Przywara
        .model_id = "Genuine Intel(R) CPU           T2600  @ 2.16GHz",
394 c6dc6f63 Andre Przywara
    },
395 c6dc6f63 Andre Przywara
    {
396 c6dc6f63 Andre Przywara
        .name = "486",
397 58012d66 Andre Przywara
        .level = 1,
398 c6dc6f63 Andre Przywara
        .family = 4,
399 c6dc6f63 Andre Przywara
        .model = 0,
400 c6dc6f63 Andre Przywara
        .stepping = 0,
401 c6dc6f63 Andre Przywara
        .features = I486_FEATURES,
402 c6dc6f63 Andre Przywara
        .xlevel = 0,
403 c6dc6f63 Andre Przywara
    },
404 c6dc6f63 Andre Przywara
    {
405 c6dc6f63 Andre Przywara
        .name = "pentium",
406 c6dc6f63 Andre Przywara
        .level = 1,
407 c6dc6f63 Andre Przywara
        .family = 5,
408 c6dc6f63 Andre Przywara
        .model = 4,
409 c6dc6f63 Andre Przywara
        .stepping = 3,
410 c6dc6f63 Andre Przywara
        .features = PENTIUM_FEATURES,
411 c6dc6f63 Andre Przywara
        .xlevel = 0,
412 c6dc6f63 Andre Przywara
    },
413 c6dc6f63 Andre Przywara
    {
414 c6dc6f63 Andre Przywara
        .name = "pentium2",
415 c6dc6f63 Andre Przywara
        .level = 2,
416 c6dc6f63 Andre Przywara
        .family = 6,
417 c6dc6f63 Andre Przywara
        .model = 5,
418 c6dc6f63 Andre Przywara
        .stepping = 2,
419 c6dc6f63 Andre Przywara
        .features = PENTIUM2_FEATURES,
420 c6dc6f63 Andre Przywara
        .xlevel = 0,
421 c6dc6f63 Andre Przywara
    },
422 c6dc6f63 Andre Przywara
    {
423 c6dc6f63 Andre Przywara
        .name = "pentium3",
424 c6dc6f63 Andre Przywara
        .level = 2,
425 c6dc6f63 Andre Przywara
        .family = 6,
426 c6dc6f63 Andre Przywara
        .model = 7,
427 c6dc6f63 Andre Przywara
        .stepping = 3,
428 c6dc6f63 Andre Przywara
        .features = PENTIUM3_FEATURES,
429 c6dc6f63 Andre Przywara
        .xlevel = 0,
430 c6dc6f63 Andre Przywara
    },
431 c6dc6f63 Andre Przywara
    {
432 c6dc6f63 Andre Przywara
        .name = "athlon",
433 c6dc6f63 Andre Przywara
        .level = 2,
434 c6dc6f63 Andre Przywara
        .vendor1 = CPUID_VENDOR_AMD_1,
435 c6dc6f63 Andre Przywara
        .vendor2 = CPUID_VENDOR_AMD_2,
436 c6dc6f63 Andre Przywara
        .vendor3 = CPUID_VENDOR_AMD_3,
437 c6dc6f63 Andre Przywara
        .family = 6,
438 c6dc6f63 Andre Przywara
        .model = 2,
439 c6dc6f63 Andre Przywara
        .stepping = 3,
440 c6dc6f63 Andre Przywara
        .features = PPRO_FEATURES | CPUID_PSE36 | CPUID_VME | CPUID_MTRR | CPUID_MCA,
441 42673936 Andre Przywara
        .ext2_features = (PPRO_FEATURES & EXT2_FEATURE_MASK) | CPUID_EXT2_MMXEXT | CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT,
442 c6dc6f63 Andre Przywara
        .xlevel = 0x80000008,
443 c6dc6f63 Andre Przywara
        /* XXX: put another string ? */
444 c6dc6f63 Andre Przywara
        .model_id = "QEMU Virtual CPU version " QEMU_VERSION,
445 c6dc6f63 Andre Przywara
    },
446 c6dc6f63 Andre Przywara
    {
447 c6dc6f63 Andre Przywara
        .name = "n270",
448 c6dc6f63 Andre Przywara
        /* original is on level 10 */
449 c6dc6f63 Andre Przywara
        .level = 5,
450 c6dc6f63 Andre Przywara
        .family = 6,
451 c6dc6f63 Andre Przywara
        .model = 28,
452 c6dc6f63 Andre Przywara
        .stepping = 2,
453 c6dc6f63 Andre Przywara
        .features = PPRO_FEATURES |
454 8560efed Aurelien Jarno
            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_VME | CPUID_DTS |
455 8560efed Aurelien Jarno
            CPUID_ACPI | CPUID_SS | CPUID_HT | CPUID_TM | CPUID_PBE,
456 c6dc6f63 Andre Przywara
            /* Some CPUs got no CPUID_SEP */
457 8560efed Aurelien Jarno
        .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_SSSE3 |
458 8560efed Aurelien Jarno
            CPUID_EXT_DSCPL | CPUID_EXT_EST | CPUID_EXT_TM2 | CPUID_EXT_XTPR,
459 42673936 Andre Przywara
        .ext2_features = (PPRO_FEATURES & EXT2_FEATURE_MASK) | CPUID_EXT2_NX,
460 8560efed Aurelien Jarno
        .ext3_features = CPUID_EXT3_LAHF_LM,
461 c6dc6f63 Andre Przywara
        .xlevel = 0x8000000A,
462 c6dc6f63 Andre Przywara
        .model_id = "Intel(R) Atom(TM) CPU N270   @ 1.60GHz",
463 c6dc6f63 Andre Przywara
    },
464 c6dc6f63 Andre Przywara
};
465 c6dc6f63 Andre Przywara
466 c6dc6f63 Andre Przywara
static int cpu_x86_fill_model_id(char *str)
467 c6dc6f63 Andre Przywara
{
468 c6dc6f63 Andre Przywara
    uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
469 c6dc6f63 Andre Przywara
    int i;
470 c6dc6f63 Andre Przywara
471 c6dc6f63 Andre Przywara
    for (i = 0; i < 3; i++) {
472 c6dc6f63 Andre Przywara
        host_cpuid(0x80000002 + i, 0, &eax, &ebx, &ecx, &edx);
473 c6dc6f63 Andre Przywara
        memcpy(str + i * 16 +  0, &eax, 4);
474 c6dc6f63 Andre Przywara
        memcpy(str + i * 16 +  4, &ebx, 4);
475 c6dc6f63 Andre Przywara
        memcpy(str + i * 16 +  8, &ecx, 4);
476 c6dc6f63 Andre Przywara
        memcpy(str + i * 16 + 12, &edx, 4);
477 c6dc6f63 Andre Przywara
    }
478 c6dc6f63 Andre Przywara
    return 0;
479 c6dc6f63 Andre Przywara
}
480 c6dc6f63 Andre Przywara
481 c6dc6f63 Andre Przywara
static int cpu_x86_fill_host(x86_def_t *x86_cpu_def)
482 c6dc6f63 Andre Przywara
{
483 c6dc6f63 Andre Przywara
    uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
484 c6dc6f63 Andre Przywara
485 c6dc6f63 Andre Przywara
    x86_cpu_def->name = "host";
486 c6dc6f63 Andre Przywara
    host_cpuid(0x0, 0, &eax, &ebx, &ecx, &edx);
487 c6dc6f63 Andre Przywara
    x86_cpu_def->level = eax;
488 c6dc6f63 Andre Przywara
    x86_cpu_def->vendor1 = ebx;
489 c6dc6f63 Andre Przywara
    x86_cpu_def->vendor2 = edx;
490 c6dc6f63 Andre Przywara
    x86_cpu_def->vendor3 = ecx;
491 c6dc6f63 Andre Przywara
492 c6dc6f63 Andre Przywara
    host_cpuid(0x1, 0, &eax, &ebx, &ecx, &edx);
493 c6dc6f63 Andre Przywara
    x86_cpu_def->family = ((eax >> 8) & 0x0F) + ((eax >> 20) & 0xFF);
494 c6dc6f63 Andre Przywara
    x86_cpu_def->model = ((eax >> 4) & 0x0F) | ((eax & 0xF0000) >> 12);
495 c6dc6f63 Andre Przywara
    x86_cpu_def->stepping = eax & 0x0F;
496 c6dc6f63 Andre Przywara
    x86_cpu_def->ext_features = ecx;
497 c6dc6f63 Andre Przywara
    x86_cpu_def->features = edx;
498 c6dc6f63 Andre Przywara
499 c6dc6f63 Andre Przywara
    host_cpuid(0x80000000, 0, &eax, &ebx, &ecx, &edx);
500 c6dc6f63 Andre Przywara
    x86_cpu_def->xlevel = eax;
501 c6dc6f63 Andre Przywara
502 c6dc6f63 Andre Przywara
    host_cpuid(0x80000001, 0, &eax, &ebx, &ecx, &edx);
503 c6dc6f63 Andre Przywara
    x86_cpu_def->ext2_features = edx;
504 c6dc6f63 Andre Przywara
    x86_cpu_def->ext3_features = ecx;
505 c6dc6f63 Andre Przywara
    cpu_x86_fill_model_id(x86_cpu_def->model_id);
506 c6dc6f63 Andre Przywara
    x86_cpu_def->vendor_override = 0;
507 c6dc6f63 Andre Przywara
508 c6dc6f63 Andre Przywara
    return 0;
509 c6dc6f63 Andre Przywara
}
510 c6dc6f63 Andre Przywara
511 c6dc6f63 Andre Przywara
static int unavailable_host_feature(struct model_features_t *f, uint32_t mask)
512 c6dc6f63 Andre Przywara
{
513 c6dc6f63 Andre Przywara
    int i;
514 c6dc6f63 Andre Przywara
515 c6dc6f63 Andre Przywara
    for (i = 0; i < 32; ++i)
516 c6dc6f63 Andre Przywara
        if (1 << i & mask) {
517 c6dc6f63 Andre Przywara
            fprintf(stderr, "warning: host cpuid %04x_%04x lacks requested"
518 c6dc6f63 Andre Przywara
                " flag '%s' [0x%08x]\n",
519 c6dc6f63 Andre Przywara
                f->cpuid >> 16, f->cpuid & 0xffff,
520 c6dc6f63 Andre Przywara
                f->flag_names[i] ? f->flag_names[i] : "[reserved]", mask);
521 c6dc6f63 Andre Przywara
            break;
522 c6dc6f63 Andre Przywara
        }
523 c6dc6f63 Andre Przywara
    return 0;
524 c6dc6f63 Andre Przywara
}
525 c6dc6f63 Andre Przywara
526 c6dc6f63 Andre Przywara
/* best effort attempt to inform user requested cpu flags aren't making
527 c6dc6f63 Andre Przywara
 * their way to the guest.  Note: ft[].check_feat ideally should be
528 c6dc6f63 Andre Przywara
 * specified via a guest_def field to suppress report of extraneous flags.
529 c6dc6f63 Andre Przywara
 */
530 c6dc6f63 Andre Przywara
static int check_features_against_host(x86_def_t *guest_def)
531 c6dc6f63 Andre Przywara
{
532 c6dc6f63 Andre Przywara
    x86_def_t host_def;
533 c6dc6f63 Andre Przywara
    uint32_t mask;
534 c6dc6f63 Andre Przywara
    int rv, i;
535 c6dc6f63 Andre Przywara
    struct model_features_t ft[] = {
536 c6dc6f63 Andre Przywara
        {&guest_def->features, &host_def.features,
537 c6dc6f63 Andre Przywara
            ~0, feature_name, 0x00000000},
538 c6dc6f63 Andre Przywara
        {&guest_def->ext_features, &host_def.ext_features,
539 c6dc6f63 Andre Przywara
            ~CPUID_EXT_HYPERVISOR, ext_feature_name, 0x00000001},
540 c6dc6f63 Andre Przywara
        {&guest_def->ext2_features, &host_def.ext2_features,
541 c6dc6f63 Andre Przywara
            ~PPRO_FEATURES, ext2_feature_name, 0x80000000},
542 c6dc6f63 Andre Przywara
        {&guest_def->ext3_features, &host_def.ext3_features,
543 c6dc6f63 Andre Przywara
            ~CPUID_EXT3_SVM, ext3_feature_name, 0x80000001}};
544 c6dc6f63 Andre Przywara
545 c6dc6f63 Andre Przywara
    cpu_x86_fill_host(&host_def);
546 66fe09ee Blue Swirl
    for (rv = 0, i = 0; i < ARRAY_SIZE(ft); ++i)
547 c6dc6f63 Andre Przywara
        for (mask = 1; mask; mask <<= 1)
548 c6dc6f63 Andre Przywara
            if (ft[i].check_feat & mask && *ft[i].guest_feat & mask &&
549 c6dc6f63 Andre Przywara
                !(*ft[i].host_feat & mask)) {
550 c6dc6f63 Andre Przywara
                    unavailable_host_feature(&ft[i], mask);
551 c6dc6f63 Andre Przywara
                    rv = 1;
552 c6dc6f63 Andre Przywara
                }
553 c6dc6f63 Andre Przywara
    return rv;
554 c6dc6f63 Andre Przywara
}
555 c6dc6f63 Andre Przywara
556 c6dc6f63 Andre Przywara
static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
557 c6dc6f63 Andre Przywara
{
558 c6dc6f63 Andre Przywara
    unsigned int i;
559 c6dc6f63 Andre Przywara
    x86_def_t *def;
560 c6dc6f63 Andre Przywara
561 c6dc6f63 Andre Przywara
    char *s = strdup(cpu_model);
562 c6dc6f63 Andre Przywara
    char *featurestr, *name = strtok(s, ",");
563 c6dc6f63 Andre Przywara
    uint32_t plus_features = 0, plus_ext_features = 0, plus_ext2_features = 0, plus_ext3_features = 0, plus_kvm_features = 0;
564 c6dc6f63 Andre Przywara
    uint32_t minus_features = 0, minus_ext_features = 0, minus_ext2_features = 0, minus_ext3_features = 0, minus_kvm_features = 0;
565 c6dc6f63 Andre Przywara
    uint32_t numvalue;
566 c6dc6f63 Andre Przywara
567 c6dc6f63 Andre Przywara
    for (def = x86_defs; def; def = def->next)
568 c6dc6f63 Andre Przywara
        if (!strcmp(name, def->name))
569 c6dc6f63 Andre Przywara
            break;
570 c6dc6f63 Andre Przywara
    if (kvm_enabled() && strcmp(name, "host") == 0) {
571 c6dc6f63 Andre Przywara
        cpu_x86_fill_host(x86_cpu_def);
572 c6dc6f63 Andre Przywara
    } else if (!def) {
573 c6dc6f63 Andre Przywara
        goto error;
574 c6dc6f63 Andre Przywara
    } else {
575 c6dc6f63 Andre Przywara
        memcpy(x86_cpu_def, def, sizeof(*def));
576 c6dc6f63 Andre Przywara
    }
577 c6dc6f63 Andre Przywara
578 c6dc6f63 Andre Przywara
    plus_kvm_features = ~0; /* not supported bits will be filtered out later */
579 c6dc6f63 Andre Przywara
580 c6dc6f63 Andre Przywara
    add_flagname_to_bitmaps("hypervisor", &plus_features,
581 c6dc6f63 Andre Przywara
        &plus_ext_features, &plus_ext2_features, &plus_ext3_features,
582 c6dc6f63 Andre Przywara
        &plus_kvm_features);
583 c6dc6f63 Andre Przywara
584 c6dc6f63 Andre Przywara
    featurestr = strtok(NULL, ",");
585 c6dc6f63 Andre Przywara
586 c6dc6f63 Andre Przywara
    while (featurestr) {
587 c6dc6f63 Andre Przywara
        char *val;
588 c6dc6f63 Andre Przywara
        if (featurestr[0] == '+') {
589 c6dc6f63 Andre Przywara
            add_flagname_to_bitmaps(featurestr + 1, &plus_features, &plus_ext_features, &plus_ext2_features, &plus_ext3_features, &plus_kvm_features);
590 c6dc6f63 Andre Przywara
        } else if (featurestr[0] == '-') {
591 c6dc6f63 Andre Przywara
            add_flagname_to_bitmaps(featurestr + 1, &minus_features, &minus_ext_features, &minus_ext2_features, &minus_ext3_features, &minus_kvm_features);
592 c6dc6f63 Andre Przywara
        } else if ((val = strchr(featurestr, '='))) {
593 c6dc6f63 Andre Przywara
            *val = 0; val++;
594 c6dc6f63 Andre Przywara
            if (!strcmp(featurestr, "family")) {
595 c6dc6f63 Andre Przywara
                char *err;
596 c6dc6f63 Andre Przywara
                numvalue = strtoul(val, &err, 0);
597 c6dc6f63 Andre Przywara
                if (!*val || *err) {
598 c6dc6f63 Andre Przywara
                    fprintf(stderr, "bad numerical value %s\n", val);
599 c6dc6f63 Andre Przywara
                    goto error;
600 c6dc6f63 Andre Przywara
                }
601 c6dc6f63 Andre Przywara
                x86_cpu_def->family = numvalue;
602 c6dc6f63 Andre Przywara
            } else if (!strcmp(featurestr, "model")) {
603 c6dc6f63 Andre Przywara
                char *err;
604 c6dc6f63 Andre Przywara
                numvalue = strtoul(val, &err, 0);
605 c6dc6f63 Andre Przywara
                if (!*val || *err || numvalue > 0xff) {
606 c6dc6f63 Andre Przywara
                    fprintf(stderr, "bad numerical value %s\n", val);
607 c6dc6f63 Andre Przywara
                    goto error;
608 c6dc6f63 Andre Przywara
                }
609 c6dc6f63 Andre Przywara
                x86_cpu_def->model = numvalue;
610 c6dc6f63 Andre Przywara
            } else if (!strcmp(featurestr, "stepping")) {
611 c6dc6f63 Andre Przywara
                char *err;
612 c6dc6f63 Andre Przywara
                numvalue = strtoul(val, &err, 0);
613 c6dc6f63 Andre Przywara
                if (!*val || *err || numvalue > 0xf) {
614 c6dc6f63 Andre Przywara
                    fprintf(stderr, "bad numerical value %s\n", val);
615 c6dc6f63 Andre Przywara
                    goto error;
616 c6dc6f63 Andre Przywara
                }
617 c6dc6f63 Andre Przywara
                x86_cpu_def->stepping = numvalue ;
618 c6dc6f63 Andre Przywara
            } else if (!strcmp(featurestr, "level")) {
619 c6dc6f63 Andre Przywara
                char *err;
620 c6dc6f63 Andre Przywara
                numvalue = strtoul(val, &err, 0);
621 c6dc6f63 Andre Przywara
                if (!*val || *err) {
622 c6dc6f63 Andre Przywara
                    fprintf(stderr, "bad numerical value %s\n", val);
623 c6dc6f63 Andre Przywara
                    goto error;
624 c6dc6f63 Andre Przywara
                }
625 c6dc6f63 Andre Przywara
                x86_cpu_def->level = numvalue;
626 c6dc6f63 Andre Przywara
            } else if (!strcmp(featurestr, "xlevel")) {
627 c6dc6f63 Andre Przywara
                char *err;
628 c6dc6f63 Andre Przywara
                numvalue = strtoul(val, &err, 0);
629 c6dc6f63 Andre Przywara
                if (!*val || *err) {
630 c6dc6f63 Andre Przywara
                    fprintf(stderr, "bad numerical value %s\n", val);
631 c6dc6f63 Andre Przywara
                    goto error;
632 c6dc6f63 Andre Przywara
                }
633 c6dc6f63 Andre Przywara
                if (numvalue < 0x80000000) {
634 2f7a21c4 Aurelien Jarno
                    numvalue += 0x80000000;
635 c6dc6f63 Andre Przywara
                }
636 c6dc6f63 Andre Przywara
                x86_cpu_def->xlevel = numvalue;
637 c6dc6f63 Andre Przywara
            } else if (!strcmp(featurestr, "vendor")) {
638 c6dc6f63 Andre Przywara
                if (strlen(val) != 12) {
639 c6dc6f63 Andre Przywara
                    fprintf(stderr, "vendor string must be 12 chars long\n");
640 c6dc6f63 Andre Przywara
                    goto error;
641 c6dc6f63 Andre Przywara
                }
642 c6dc6f63 Andre Przywara
                x86_cpu_def->vendor1 = 0;
643 c6dc6f63 Andre Przywara
                x86_cpu_def->vendor2 = 0;
644 c6dc6f63 Andre Przywara
                x86_cpu_def->vendor3 = 0;
645 c6dc6f63 Andre Przywara
                for(i = 0; i < 4; i++) {
646 c6dc6f63 Andre Przywara
                    x86_cpu_def->vendor1 |= ((uint8_t)val[i    ]) << (8 * i);
647 c6dc6f63 Andre Przywara
                    x86_cpu_def->vendor2 |= ((uint8_t)val[i + 4]) << (8 * i);
648 c6dc6f63 Andre Przywara
                    x86_cpu_def->vendor3 |= ((uint8_t)val[i + 8]) << (8 * i);
649 c6dc6f63 Andre Przywara
                }
650 c6dc6f63 Andre Przywara
                x86_cpu_def->vendor_override = 1;
651 c6dc6f63 Andre Przywara
            } else if (!strcmp(featurestr, "model_id")) {
652 c6dc6f63 Andre Przywara
                pstrcpy(x86_cpu_def->model_id, sizeof(x86_cpu_def->model_id),
653 c6dc6f63 Andre Przywara
                        val);
654 c6dc6f63 Andre Przywara
            } else {
655 c6dc6f63 Andre Przywara
                fprintf(stderr, "unrecognized feature %s\n", featurestr);
656 c6dc6f63 Andre Przywara
                goto error;
657 c6dc6f63 Andre Przywara
            }
658 c6dc6f63 Andre Przywara
        } else if (!strcmp(featurestr, "check")) {
659 c6dc6f63 Andre Przywara
            check_cpuid = 1;
660 c6dc6f63 Andre Przywara
        } else if (!strcmp(featurestr, "enforce")) {
661 c6dc6f63 Andre Przywara
            check_cpuid = enforce_cpuid = 1;
662 c6dc6f63 Andre Przywara
        } else {
663 c6dc6f63 Andre Przywara
            fprintf(stderr, "feature string `%s' not in format (+feature|-feature|feature=xyz)\n", featurestr);
664 c6dc6f63 Andre Przywara
            goto error;
665 c6dc6f63 Andre Przywara
        }
666 c6dc6f63 Andre Przywara
        featurestr = strtok(NULL, ",");
667 c6dc6f63 Andre Przywara
    }
668 c6dc6f63 Andre Przywara
    x86_cpu_def->features |= plus_features;
669 c6dc6f63 Andre Przywara
    x86_cpu_def->ext_features |= plus_ext_features;
670 c6dc6f63 Andre Przywara
    x86_cpu_def->ext2_features |= plus_ext2_features;
671 c6dc6f63 Andre Przywara
    x86_cpu_def->ext3_features |= plus_ext3_features;
672 c6dc6f63 Andre Przywara
    x86_cpu_def->kvm_features |= plus_kvm_features;
673 c6dc6f63 Andre Przywara
    x86_cpu_def->features &= ~minus_features;
674 c6dc6f63 Andre Przywara
    x86_cpu_def->ext_features &= ~minus_ext_features;
675 c6dc6f63 Andre Przywara
    x86_cpu_def->ext2_features &= ~minus_ext2_features;
676 c6dc6f63 Andre Przywara
    x86_cpu_def->ext3_features &= ~minus_ext3_features;
677 c6dc6f63 Andre Przywara
    x86_cpu_def->kvm_features &= ~minus_kvm_features;
678 c6dc6f63 Andre Przywara
    if (check_cpuid) {
679 c6dc6f63 Andre Przywara
        if (check_features_against_host(x86_cpu_def) && enforce_cpuid)
680 c6dc6f63 Andre Przywara
            goto error;
681 c6dc6f63 Andre Przywara
    }
682 c6dc6f63 Andre Przywara
    free(s);
683 c6dc6f63 Andre Przywara
    return 0;
684 c6dc6f63 Andre Przywara
685 c6dc6f63 Andre Przywara
error:
686 c6dc6f63 Andre Przywara
    free(s);
687 c6dc6f63 Andre Przywara
    return -1;
688 c6dc6f63 Andre Przywara
}
689 c6dc6f63 Andre Przywara
690 c6dc6f63 Andre Przywara
/* generate a composite string into buf of all cpuid names in featureset
691 c6dc6f63 Andre Przywara
 * selected by fbits.  indicate truncation at bufsize in the event of overflow.
692 c6dc6f63 Andre Przywara
 * if flags, suppress names undefined in featureset.
693 c6dc6f63 Andre Przywara
 */
694 c6dc6f63 Andre Przywara
static void listflags(char *buf, int bufsize, uint32_t fbits,
695 c6dc6f63 Andre Przywara
    const char **featureset, uint32_t flags)
696 c6dc6f63 Andre Przywara
{
697 c6dc6f63 Andre Przywara
    const char **p = &featureset[31];
698 c6dc6f63 Andre Przywara
    char *q, *b, bit;
699 c6dc6f63 Andre Przywara
    int nc;
700 c6dc6f63 Andre Przywara
701 c6dc6f63 Andre Przywara
    b = 4 <= bufsize ? buf + (bufsize -= 3) - 1 : NULL;
702 c6dc6f63 Andre Przywara
    *buf = '\0';
703 c6dc6f63 Andre Przywara
    for (q = buf, bit = 31; fbits && bufsize; --p, fbits &= ~(1 << bit), --bit)
704 c6dc6f63 Andre Przywara
        if (fbits & 1 << bit && (*p || !flags)) {
705 c6dc6f63 Andre Przywara
            if (*p)
706 c6dc6f63 Andre Przywara
                nc = snprintf(q, bufsize, "%s%s", q == buf ? "" : " ", *p);
707 c6dc6f63 Andre Przywara
            else
708 c6dc6f63 Andre Przywara
                nc = snprintf(q, bufsize, "%s[%d]", q == buf ? "" : " ", bit);
709 c6dc6f63 Andre Przywara
            if (bufsize <= nc) {
710 c6dc6f63 Andre Przywara
                if (b) {
711 c6dc6f63 Andre Przywara
                    memcpy(b, "...", sizeof("..."));
712 c6dc6f63 Andre Przywara
                }
713 c6dc6f63 Andre Przywara
                return;
714 c6dc6f63 Andre Przywara
            }
715 c6dc6f63 Andre Przywara
            q += nc;
716 c6dc6f63 Andre Przywara
            bufsize -= nc;
717 c6dc6f63 Andre Przywara
        }
718 c6dc6f63 Andre Przywara
}
719 c6dc6f63 Andre Przywara
720 c6dc6f63 Andre Przywara
/* generate CPU information:
721 c6dc6f63 Andre Przywara
 * -?        list model names
722 c6dc6f63 Andre Przywara
 * -?model   list model names/IDs
723 c6dc6f63 Andre Przywara
 * -?dump    output all model (x86_def_t) data
724 c6dc6f63 Andre Przywara
 * -?cpuid   list all recognized cpuid flag names
725 c6dc6f63 Andre Przywara
 */
726 c6dc6f63 Andre Przywara
void x86_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
727 c6dc6f63 Andre Przywara
                  const char *optarg)
728 c6dc6f63 Andre Przywara
{
729 c6dc6f63 Andre Przywara
    unsigned char model = !strcmp("?model", optarg);
730 c6dc6f63 Andre Przywara
    unsigned char dump = !strcmp("?dump", optarg);
731 c6dc6f63 Andre Przywara
    unsigned char cpuid = !strcmp("?cpuid", optarg);
732 c6dc6f63 Andre Przywara
    x86_def_t *def;
733 c6dc6f63 Andre Przywara
    char buf[256];
734 c6dc6f63 Andre Przywara
735 c6dc6f63 Andre Przywara
    if (cpuid) {
736 c6dc6f63 Andre Przywara
        (*cpu_fprintf)(f, "Recognized CPUID flags:\n");
737 c6dc6f63 Andre Przywara
        listflags(buf, sizeof (buf), (uint32_t)~0, feature_name, 1);
738 c6dc6f63 Andre Przywara
        (*cpu_fprintf)(f, "  f_edx: %s\n", buf);
739 c6dc6f63 Andre Przywara
        listflags(buf, sizeof (buf), (uint32_t)~0, ext_feature_name, 1);
740 c6dc6f63 Andre Przywara
        (*cpu_fprintf)(f, "  f_ecx: %s\n", buf);
741 c6dc6f63 Andre Przywara
        listflags(buf, sizeof (buf), (uint32_t)~0, ext2_feature_name, 1);
742 c6dc6f63 Andre Przywara
        (*cpu_fprintf)(f, "  extf_edx: %s\n", buf);
743 c6dc6f63 Andre Przywara
        listflags(buf, sizeof (buf), (uint32_t)~0, ext3_feature_name, 1);
744 c6dc6f63 Andre Przywara
        (*cpu_fprintf)(f, "  extf_ecx: %s\n", buf);
745 c6dc6f63 Andre Przywara
        return;
746 c6dc6f63 Andre Przywara
    }
747 c6dc6f63 Andre Przywara
    for (def = x86_defs; def; def = def->next) {
748 c6dc6f63 Andre Przywara
        snprintf(buf, sizeof (buf), def->flags ? "[%s]": "%s", def->name);
749 c6dc6f63 Andre Przywara
        if (model || dump) {
750 c6dc6f63 Andre Przywara
            (*cpu_fprintf)(f, "x86 %16s  %-48s\n", buf, def->model_id);
751 c6dc6f63 Andre Przywara
        } else {
752 c6dc6f63 Andre Przywara
            (*cpu_fprintf)(f, "x86 %16s\n", buf);
753 c6dc6f63 Andre Przywara
        }
754 c6dc6f63 Andre Przywara
        if (dump) {
755 c6dc6f63 Andre Przywara
            memcpy(buf, &def->vendor1, sizeof (def->vendor1));
756 c6dc6f63 Andre Przywara
            memcpy(buf + 4, &def->vendor2, sizeof (def->vendor2));
757 c6dc6f63 Andre Przywara
            memcpy(buf + 8, &def->vendor3, sizeof (def->vendor3));
758 c6dc6f63 Andre Przywara
            buf[12] = '\0';
759 c6dc6f63 Andre Przywara
            (*cpu_fprintf)(f,
760 c6dc6f63 Andre Przywara
                "  family %d model %d stepping %d level %d xlevel 0x%x"
761 c6dc6f63 Andre Przywara
                " vendor \"%s\"\n",
762 c6dc6f63 Andre Przywara
                def->family, def->model, def->stepping, def->level,
763 c6dc6f63 Andre Przywara
                def->xlevel, buf);
764 c6dc6f63 Andre Przywara
            listflags(buf, sizeof (buf), def->features, feature_name, 0);
765 c6dc6f63 Andre Przywara
            (*cpu_fprintf)(f, "  feature_edx %08x (%s)\n", def->features,
766 c6dc6f63 Andre Przywara
                buf);
767 c6dc6f63 Andre Przywara
            listflags(buf, sizeof (buf), def->ext_features, ext_feature_name,
768 c6dc6f63 Andre Przywara
                0);
769 c6dc6f63 Andre Przywara
            (*cpu_fprintf)(f, "  feature_ecx %08x (%s)\n", def->ext_features,
770 c6dc6f63 Andre Przywara
                buf);
771 c6dc6f63 Andre Przywara
            listflags(buf, sizeof (buf), def->ext2_features, ext2_feature_name,
772 c6dc6f63 Andre Przywara
                0);
773 c6dc6f63 Andre Przywara
            (*cpu_fprintf)(f, "  extfeature_edx %08x (%s)\n",
774 c6dc6f63 Andre Przywara
                def->ext2_features, buf);
775 c6dc6f63 Andre Przywara
            listflags(buf, sizeof (buf), def->ext3_features, ext3_feature_name,
776 c6dc6f63 Andre Przywara
                0);
777 c6dc6f63 Andre Przywara
            (*cpu_fprintf)(f, "  extfeature_ecx %08x (%s)\n",
778 c6dc6f63 Andre Przywara
                def->ext3_features, buf);
779 c6dc6f63 Andre Przywara
            (*cpu_fprintf)(f, "\n");
780 c6dc6f63 Andre Przywara
        }
781 c6dc6f63 Andre Przywara
    }
782 ed2c54d4 Andre Przywara
    if (kvm_enabled()) {
783 ed2c54d4 Andre Przywara
        (*cpu_fprintf)(f, "x86 %16s\n", "[host]");
784 ed2c54d4 Andre Przywara
    }
785 c6dc6f63 Andre Przywara
}
786 c6dc6f63 Andre Przywara
787 c6dc6f63 Andre Przywara
int cpu_x86_register (CPUX86State *env, const char *cpu_model)
788 c6dc6f63 Andre Przywara
{
789 c6dc6f63 Andre Przywara
    x86_def_t def1, *def = &def1;
790 c6dc6f63 Andre Przywara
791 db0ad1ba Joerg Roedel
    memset(def, 0, sizeof(*def));
792 db0ad1ba Joerg Roedel
793 c6dc6f63 Andre Przywara
    if (cpu_x86_find_by_name(def, cpu_model) < 0)
794 c6dc6f63 Andre Przywara
        return -1;
795 c6dc6f63 Andre Przywara
    if (def->vendor1) {
796 c6dc6f63 Andre Przywara
        env->cpuid_vendor1 = def->vendor1;
797 c6dc6f63 Andre Przywara
        env->cpuid_vendor2 = def->vendor2;
798 c6dc6f63 Andre Przywara
        env->cpuid_vendor3 = def->vendor3;
799 c6dc6f63 Andre Przywara
    } else {
800 c6dc6f63 Andre Przywara
        env->cpuid_vendor1 = CPUID_VENDOR_INTEL_1;
801 c6dc6f63 Andre Przywara
        env->cpuid_vendor2 = CPUID_VENDOR_INTEL_2;
802 c6dc6f63 Andre Przywara
        env->cpuid_vendor3 = CPUID_VENDOR_INTEL_3;
803 c6dc6f63 Andre Przywara
    }
804 c6dc6f63 Andre Przywara
    env->cpuid_vendor_override = def->vendor_override;
805 c6dc6f63 Andre Przywara
    env->cpuid_level = def->level;
806 c6dc6f63 Andre Przywara
    if (def->family > 0x0f)
807 c6dc6f63 Andre Przywara
        env->cpuid_version = 0xf00 | ((def->family - 0x0f) << 20);
808 c6dc6f63 Andre Przywara
    else
809 c6dc6f63 Andre Przywara
        env->cpuid_version = def->family << 8;
810 c6dc6f63 Andre Przywara
    env->cpuid_version |= ((def->model & 0xf) << 4) | ((def->model >> 4) << 16);
811 c6dc6f63 Andre Przywara
    env->cpuid_version |= def->stepping;
812 c6dc6f63 Andre Przywara
    env->cpuid_features = def->features;
813 c6dc6f63 Andre Przywara
    env->pat = 0x0007040600070406ULL;
814 c6dc6f63 Andre Przywara
    env->cpuid_ext_features = def->ext_features;
815 c6dc6f63 Andre Przywara
    env->cpuid_ext2_features = def->ext2_features;
816 4d067ed7 Andre Przywara
    env->cpuid_ext3_features = def->ext3_features;
817 c6dc6f63 Andre Przywara
    env->cpuid_xlevel = def->xlevel;
818 c6dc6f63 Andre Przywara
    env->cpuid_kvm_features = def->kvm_features;
819 551a2dec Andre Przywara
    if (!kvm_enabled()) {
820 551a2dec Andre Przywara
        env->cpuid_features &= TCG_FEATURES;
821 551a2dec Andre Przywara
        env->cpuid_ext_features &= TCG_EXT_FEATURES;
822 551a2dec Andre Przywara
        env->cpuid_ext2_features &= (TCG_EXT2_FEATURES
823 551a2dec Andre Przywara
#ifdef TARGET_X86_64
824 551a2dec Andre Przywara
            | CPUID_EXT2_SYSCALL | CPUID_EXT2_LM
825 551a2dec Andre Przywara
#endif
826 551a2dec Andre Przywara
            );
827 551a2dec Andre Przywara
        env->cpuid_ext3_features &= TCG_EXT3_FEATURES;
828 551a2dec Andre Przywara
    }
829 c6dc6f63 Andre Przywara
    {
830 c6dc6f63 Andre Przywara
        const char *model_id = def->model_id;
831 c6dc6f63 Andre Przywara
        int c, len, i;
832 c6dc6f63 Andre Przywara
        if (!model_id)
833 c6dc6f63 Andre Przywara
            model_id = "";
834 c6dc6f63 Andre Przywara
        len = strlen(model_id);
835 c6dc6f63 Andre Przywara
        for(i = 0; i < 48; i++) {
836 c6dc6f63 Andre Przywara
            if (i >= len)
837 c6dc6f63 Andre Przywara
                c = '\0';
838 c6dc6f63 Andre Przywara
            else
839 c6dc6f63 Andre Przywara
                c = (uint8_t)model_id[i];
840 c6dc6f63 Andre Przywara
            env->cpuid_model[i >> 2] |= c << (8 * (i & 3));
841 c6dc6f63 Andre Przywara
        }
842 c6dc6f63 Andre Przywara
    }
843 c6dc6f63 Andre Przywara
    return 0;
844 c6dc6f63 Andre Przywara
}
845 c6dc6f63 Andre Przywara
846 c6dc6f63 Andre Przywara
#if !defined(CONFIG_USER_ONLY)
847 c6dc6f63 Andre Przywara
/* copy vendor id string to 32 bit register, nul pad as needed
848 c6dc6f63 Andre Przywara
 */
849 c6dc6f63 Andre Przywara
static void cpyid(const char *s, uint32_t *id)
850 c6dc6f63 Andre Przywara
{
851 c6dc6f63 Andre Przywara
    char *d = (char *)id;
852 c6dc6f63 Andre Przywara
    char i;
853 c6dc6f63 Andre Przywara
854 c6dc6f63 Andre Przywara
    for (i = sizeof (*id); i--; )
855 c6dc6f63 Andre Przywara
        *d++ = *s ? *s++ : '\0';
856 c6dc6f63 Andre Przywara
}
857 c6dc6f63 Andre Przywara
858 c6dc6f63 Andre Przywara
/* interpret radix and convert from string to arbitrary scalar,
859 c6dc6f63 Andre Przywara
 * otherwise flag failure
860 c6dc6f63 Andre Przywara
 */
861 c6dc6f63 Andre Przywara
#define setscalar(pval, str, perr)                      \
862 c6dc6f63 Andre Przywara
{                                                       \
863 c6dc6f63 Andre Przywara
    char *pend;                                         \
864 c6dc6f63 Andre Przywara
    unsigned long ul;                                   \
865 c6dc6f63 Andre Przywara
                                                        \
866 c6dc6f63 Andre Przywara
    ul = strtoul(str, &pend, 0);                        \
867 c6dc6f63 Andre Przywara
    *str && !*pend ? (*pval = ul) : (*perr = 1);        \
868 c6dc6f63 Andre Przywara
}
869 c6dc6f63 Andre Przywara
870 c6dc6f63 Andre Przywara
/* map cpuid options to feature bits, otherwise return failure
871 c6dc6f63 Andre Przywara
 * (option tags in *str are delimited by whitespace)
872 c6dc6f63 Andre Przywara
 */
873 c6dc6f63 Andre Przywara
static void setfeatures(uint32_t *pval, const char *str,
874 c6dc6f63 Andre Przywara
    const char **featureset, int *perr)
875 c6dc6f63 Andre Przywara
{
876 c6dc6f63 Andre Przywara
    const char *p, *q;
877 c6dc6f63 Andre Przywara
878 c6dc6f63 Andre Przywara
    for (q = p = str; *p || *q; q = p) {
879 c6dc6f63 Andre Przywara
        while (iswhite(*p))
880 c6dc6f63 Andre Przywara
            q = ++p;
881 c6dc6f63 Andre Przywara
        while (*p && !iswhite(*p))
882 c6dc6f63 Andre Przywara
            ++p;
883 c6dc6f63 Andre Przywara
        if (!*q && !*p)
884 c6dc6f63 Andre Przywara
            return;
885 c6dc6f63 Andre Przywara
        if (!lookup_feature(pval, q, p, featureset)) {
886 c6dc6f63 Andre Przywara
            fprintf(stderr, "error: feature \"%.*s\" not available in set\n",
887 c6dc6f63 Andre Przywara
                (int)(p - q), q);
888 c6dc6f63 Andre Przywara
            *perr = 1;
889 c6dc6f63 Andre Przywara
            return;
890 c6dc6f63 Andre Przywara
        }
891 c6dc6f63 Andre Przywara
    }
892 c6dc6f63 Andre Przywara
}
893 c6dc6f63 Andre Przywara
894 c6dc6f63 Andre Przywara
/* map config file options to x86_def_t form
895 c6dc6f63 Andre Przywara
 */
896 c6dc6f63 Andre Przywara
static int cpudef_setfield(const char *name, const char *str, void *opaque)
897 c6dc6f63 Andre Przywara
{
898 c6dc6f63 Andre Przywara
    x86_def_t *def = opaque;
899 c6dc6f63 Andre Przywara
    int err = 0;
900 c6dc6f63 Andre Przywara
901 c6dc6f63 Andre Przywara
    if (!strcmp(name, "name")) {
902 c6dc6f63 Andre Przywara
        def->name = strdup(str);
903 c6dc6f63 Andre Przywara
    } else if (!strcmp(name, "model_id")) {
904 c6dc6f63 Andre Przywara
        strncpy(def->model_id, str, sizeof (def->model_id));
905 c6dc6f63 Andre Przywara
    } else if (!strcmp(name, "level")) {
906 c6dc6f63 Andre Przywara
        setscalar(&def->level, str, &err)
907 c6dc6f63 Andre Przywara
    } else if (!strcmp(name, "vendor")) {
908 c6dc6f63 Andre Przywara
        cpyid(&str[0], &def->vendor1);
909 c6dc6f63 Andre Przywara
        cpyid(&str[4], &def->vendor2);
910 c6dc6f63 Andre Przywara
        cpyid(&str[8], &def->vendor3);
911 c6dc6f63 Andre Przywara
    } else if (!strcmp(name, "family")) {
912 c6dc6f63 Andre Przywara
        setscalar(&def->family, str, &err)
913 c6dc6f63 Andre Przywara
    } else if (!strcmp(name, "model")) {
914 c6dc6f63 Andre Przywara
        setscalar(&def->model, str, &err)
915 c6dc6f63 Andre Przywara
    } else if (!strcmp(name, "stepping")) {
916 c6dc6f63 Andre Przywara
        setscalar(&def->stepping, str, &err)
917 c6dc6f63 Andre Przywara
    } else if (!strcmp(name, "feature_edx")) {
918 c6dc6f63 Andre Przywara
        setfeatures(&def->features, str, feature_name, &err);
919 c6dc6f63 Andre Przywara
    } else if (!strcmp(name, "feature_ecx")) {
920 c6dc6f63 Andre Przywara
        setfeatures(&def->ext_features, str, ext_feature_name, &err);
921 c6dc6f63 Andre Przywara
    } else if (!strcmp(name, "extfeature_edx")) {
922 c6dc6f63 Andre Przywara
        setfeatures(&def->ext2_features, str, ext2_feature_name, &err);
923 c6dc6f63 Andre Przywara
    } else if (!strcmp(name, "extfeature_ecx")) {
924 c6dc6f63 Andre Przywara
        setfeatures(&def->ext3_features, str, ext3_feature_name, &err);
925 c6dc6f63 Andre Przywara
    } else if (!strcmp(name, "xlevel")) {
926 c6dc6f63 Andre Przywara
        setscalar(&def->xlevel, str, &err)
927 c6dc6f63 Andre Przywara
    } else {
928 c6dc6f63 Andre Przywara
        fprintf(stderr, "error: unknown option [%s = %s]\n", name, str);
929 c6dc6f63 Andre Przywara
        return (1);
930 c6dc6f63 Andre Przywara
    }
931 c6dc6f63 Andre Przywara
    if (err) {
932 c6dc6f63 Andre Przywara
        fprintf(stderr, "error: bad option value [%s = %s]\n", name, str);
933 c6dc6f63 Andre Przywara
        return (1);
934 c6dc6f63 Andre Przywara
    }
935 c6dc6f63 Andre Przywara
    return (0);
936 c6dc6f63 Andre Przywara
}
937 c6dc6f63 Andre Przywara
938 c6dc6f63 Andre Przywara
/* register config file entry as x86_def_t
939 c6dc6f63 Andre Przywara
 */
940 c6dc6f63 Andre Przywara
static int cpudef_register(QemuOpts *opts, void *opaque)
941 c6dc6f63 Andre Przywara
{
942 c6dc6f63 Andre Przywara
    x86_def_t *def = qemu_mallocz(sizeof (x86_def_t));
943 c6dc6f63 Andre Przywara
944 c6dc6f63 Andre Przywara
    qemu_opt_foreach(opts, cpudef_setfield, def, 1);
945 c6dc6f63 Andre Przywara
    def->next = x86_defs;
946 c6dc6f63 Andre Przywara
    x86_defs = def;
947 c6dc6f63 Andre Przywara
    return (0);
948 c6dc6f63 Andre Przywara
}
949 0e26b7b8 Blue Swirl
950 0e26b7b8 Blue Swirl
void cpu_clear_apic_feature(CPUX86State *env)
951 0e26b7b8 Blue Swirl
{
952 0e26b7b8 Blue Swirl
    env->cpuid_features &= ~CPUID_APIC;
953 0e26b7b8 Blue Swirl
}
954 0e26b7b8 Blue Swirl
955 c6dc6f63 Andre Przywara
#endif /* !CONFIG_USER_ONLY */
956 c6dc6f63 Andre Przywara
957 c6dc6f63 Andre Przywara
/* register "cpudef" models defined in configuration file.  Here we first
958 c6dc6f63 Andre Przywara
 * preload any built-in definitions
959 c6dc6f63 Andre Przywara
 */
960 c6dc6f63 Andre Przywara
void x86_cpudef_setup(void)
961 c6dc6f63 Andre Przywara
{
962 c6dc6f63 Andre Przywara
    int i;
963 c6dc6f63 Andre Przywara
964 c6dc6f63 Andre Przywara
    for (i = 0; i < ARRAY_SIZE(builtin_x86_defs); ++i) {
965 c6dc6f63 Andre Przywara
        builtin_x86_defs[i].next = x86_defs;
966 c6dc6f63 Andre Przywara
        builtin_x86_defs[i].flags = 1;
967 c6dc6f63 Andre Przywara
        x86_defs = &builtin_x86_defs[i];
968 c6dc6f63 Andre Przywara
    }
969 c6dc6f63 Andre Przywara
#if !defined(CONFIG_USER_ONLY)
970 3329f07b Gerd Hoffmann
    qemu_opts_foreach(qemu_find_opts("cpudef"), cpudef_register, NULL, 0);
971 c6dc6f63 Andre Przywara
#endif
972 c6dc6f63 Andre Przywara
}
973 c6dc6f63 Andre Przywara
974 c6dc6f63 Andre Przywara
static void get_cpuid_vendor(CPUX86State *env, uint32_t *ebx,
975 c6dc6f63 Andre Przywara
                             uint32_t *ecx, uint32_t *edx)
976 c6dc6f63 Andre Przywara
{
977 c6dc6f63 Andre Przywara
    *ebx = env->cpuid_vendor1;
978 c6dc6f63 Andre Przywara
    *edx = env->cpuid_vendor2;
979 c6dc6f63 Andre Przywara
    *ecx = env->cpuid_vendor3;
980 c6dc6f63 Andre Przywara
981 c6dc6f63 Andre Przywara
    /* sysenter isn't supported on compatibility mode on AMD, syscall
982 c6dc6f63 Andre Przywara
     * isn't supported in compatibility mode on Intel.
983 c6dc6f63 Andre Przywara
     * Normally we advertise the actual cpu vendor, but you can override
984 c6dc6f63 Andre Przywara
     * this if you want to use KVM's sysenter/syscall emulation
985 c6dc6f63 Andre Przywara
     * in compatibility mode and when doing cross vendor migration
986 c6dc6f63 Andre Przywara
     */
987 89354998 Andre Przywara
    if (kvm_enabled() && ! env->cpuid_vendor_override) {
988 c6dc6f63 Andre Przywara
        host_cpuid(0, 0, NULL, ebx, ecx, edx);
989 c6dc6f63 Andre Przywara
    }
990 c6dc6f63 Andre Przywara
}
991 c6dc6f63 Andre Przywara
992 c6dc6f63 Andre Przywara
void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
993 c6dc6f63 Andre Przywara
                   uint32_t *eax, uint32_t *ebx,
994 c6dc6f63 Andre Przywara
                   uint32_t *ecx, uint32_t *edx)
995 c6dc6f63 Andre Przywara
{
996 c6dc6f63 Andre Przywara
    /* test if maximum index reached */
997 c6dc6f63 Andre Przywara
    if (index & 0x80000000) {
998 c6dc6f63 Andre Przywara
        if (index > env->cpuid_xlevel)
999 c6dc6f63 Andre Przywara
            index = env->cpuid_level;
1000 c6dc6f63 Andre Przywara
    } else {
1001 c6dc6f63 Andre Przywara
        if (index > env->cpuid_level)
1002 c6dc6f63 Andre Przywara
            index = env->cpuid_level;
1003 c6dc6f63 Andre Przywara
    }
1004 c6dc6f63 Andre Przywara
1005 c6dc6f63 Andre Przywara
    switch(index) {
1006 c6dc6f63 Andre Przywara
    case 0:
1007 c6dc6f63 Andre Przywara
        *eax = env->cpuid_level;
1008 c6dc6f63 Andre Przywara
        get_cpuid_vendor(env, ebx, ecx, edx);
1009 c6dc6f63 Andre Przywara
        break;
1010 c6dc6f63 Andre Przywara
    case 1:
1011 c6dc6f63 Andre Przywara
        *eax = env->cpuid_version;
1012 c6dc6f63 Andre Przywara
        *ebx = (env->cpuid_apic_id << 24) | 8 << 8; /* CLFLUSH size in quad words, Linux wants it. */
1013 c6dc6f63 Andre Przywara
        *ecx = env->cpuid_ext_features;
1014 c6dc6f63 Andre Przywara
        *edx = env->cpuid_features;
1015 c6dc6f63 Andre Przywara
        if (env->nr_cores * env->nr_threads > 1) {
1016 c6dc6f63 Andre Przywara
            *ebx |= (env->nr_cores * env->nr_threads) << 16;
1017 c6dc6f63 Andre Przywara
            *edx |= 1 << 28;    /* HTT bit */
1018 c6dc6f63 Andre Przywara
        }
1019 c6dc6f63 Andre Przywara
        break;
1020 c6dc6f63 Andre Przywara
    case 2:
1021 c6dc6f63 Andre Przywara
        /* cache info: needed for Pentium Pro compatibility */
1022 c6dc6f63 Andre Przywara
        *eax = 1;
1023 c6dc6f63 Andre Przywara
        *ebx = 0;
1024 c6dc6f63 Andre Przywara
        *ecx = 0;
1025 c6dc6f63 Andre Przywara
        *edx = 0x2c307d;
1026 c6dc6f63 Andre Przywara
        break;
1027 c6dc6f63 Andre Przywara
    case 4:
1028 c6dc6f63 Andre Przywara
        /* cache info: needed for Core compatibility */
1029 c6dc6f63 Andre Przywara
        if (env->nr_cores > 1) {
1030 2f7a21c4 Aurelien Jarno
            *eax = (env->nr_cores - 1) << 26;
1031 c6dc6f63 Andre Przywara
        } else {
1032 2f7a21c4 Aurelien Jarno
            *eax = 0;
1033 c6dc6f63 Andre Przywara
        }
1034 c6dc6f63 Andre Przywara
        switch (count) {
1035 c6dc6f63 Andre Przywara
            case 0: /* L1 dcache info */
1036 c6dc6f63 Andre Przywara
                *eax |= 0x0000121;
1037 c6dc6f63 Andre Przywara
                *ebx = 0x1c0003f;
1038 c6dc6f63 Andre Przywara
                *ecx = 0x000003f;
1039 c6dc6f63 Andre Przywara
                *edx = 0x0000001;
1040 c6dc6f63 Andre Przywara
                break;
1041 c6dc6f63 Andre Przywara
            case 1: /* L1 icache info */
1042 c6dc6f63 Andre Przywara
                *eax |= 0x0000122;
1043 c6dc6f63 Andre Przywara
                *ebx = 0x1c0003f;
1044 c6dc6f63 Andre Przywara
                *ecx = 0x000003f;
1045 c6dc6f63 Andre Przywara
                *edx = 0x0000001;
1046 c6dc6f63 Andre Przywara
                break;
1047 c6dc6f63 Andre Przywara
            case 2: /* L2 cache info */
1048 c6dc6f63 Andre Przywara
                *eax |= 0x0000143;
1049 c6dc6f63 Andre Przywara
                if (env->nr_threads > 1) {
1050 c6dc6f63 Andre Przywara
                    *eax |= (env->nr_threads - 1) << 14;
1051 c6dc6f63 Andre Przywara
                }
1052 c6dc6f63 Andre Przywara
                *ebx = 0x3c0003f;
1053 c6dc6f63 Andre Przywara
                *ecx = 0x0000fff;
1054 c6dc6f63 Andre Przywara
                *edx = 0x0000001;
1055 c6dc6f63 Andre Przywara
                break;
1056 c6dc6f63 Andre Przywara
            default: /* end of info */
1057 c6dc6f63 Andre Przywara
                *eax = 0;
1058 c6dc6f63 Andre Przywara
                *ebx = 0;
1059 c6dc6f63 Andre Przywara
                *ecx = 0;
1060 c6dc6f63 Andre Przywara
                *edx = 0;
1061 c6dc6f63 Andre Przywara
                break;
1062 c6dc6f63 Andre Przywara
        }
1063 c6dc6f63 Andre Przywara
        break;
1064 c6dc6f63 Andre Przywara
    case 5:
1065 c6dc6f63 Andre Przywara
        /* mwait info: needed for Core compatibility */
1066 c6dc6f63 Andre Przywara
        *eax = 0; /* Smallest monitor-line size in bytes */
1067 c6dc6f63 Andre Przywara
        *ebx = 0; /* Largest monitor-line size in bytes */
1068 c6dc6f63 Andre Przywara
        *ecx = CPUID_MWAIT_EMX | CPUID_MWAIT_IBE;
1069 c6dc6f63 Andre Przywara
        *edx = 0;
1070 c6dc6f63 Andre Przywara
        break;
1071 c6dc6f63 Andre Przywara
    case 6:
1072 c6dc6f63 Andre Przywara
        /* Thermal and Power Leaf */
1073 c6dc6f63 Andre Przywara
        *eax = 0;
1074 c6dc6f63 Andre Przywara
        *ebx = 0;
1075 c6dc6f63 Andre Przywara
        *ecx = 0;
1076 c6dc6f63 Andre Przywara
        *edx = 0;
1077 c6dc6f63 Andre Przywara
        break;
1078 c6dc6f63 Andre Przywara
    case 9:
1079 c6dc6f63 Andre Przywara
        /* Direct Cache Access Information Leaf */
1080 c6dc6f63 Andre Przywara
        *eax = 0; /* Bits 0-31 in DCA_CAP MSR */
1081 c6dc6f63 Andre Przywara
        *ebx = 0;
1082 c6dc6f63 Andre Przywara
        *ecx = 0;
1083 c6dc6f63 Andre Przywara
        *edx = 0;
1084 c6dc6f63 Andre Przywara
        break;
1085 c6dc6f63 Andre Przywara
    case 0xA:
1086 c6dc6f63 Andre Przywara
        /* Architectural Performance Monitoring Leaf */
1087 c6dc6f63 Andre Przywara
        *eax = 0;
1088 c6dc6f63 Andre Przywara
        *ebx = 0;
1089 c6dc6f63 Andre Przywara
        *ecx = 0;
1090 c6dc6f63 Andre Przywara
        *edx = 0;
1091 c6dc6f63 Andre Przywara
        break;
1092 51e49430 Sheng Yang
    case 0xD:
1093 51e49430 Sheng Yang
        /* Processor Extended State */
1094 51e49430 Sheng Yang
        if (!(env->cpuid_ext_features & CPUID_EXT_XSAVE)) {
1095 51e49430 Sheng Yang
            *eax = 0;
1096 51e49430 Sheng Yang
            *ebx = 0;
1097 51e49430 Sheng Yang
            *ecx = 0;
1098 51e49430 Sheng Yang
            *edx = 0;
1099 51e49430 Sheng Yang
            break;
1100 51e49430 Sheng Yang
        }
1101 51e49430 Sheng Yang
        if (kvm_enabled()) {
1102 51e49430 Sheng Yang
            *eax = kvm_arch_get_supported_cpuid(env, 0xd, count, R_EAX);
1103 51e49430 Sheng Yang
            *ebx = kvm_arch_get_supported_cpuid(env, 0xd, count, R_EBX);
1104 51e49430 Sheng Yang
            *ecx = kvm_arch_get_supported_cpuid(env, 0xd, count, R_ECX);
1105 51e49430 Sheng Yang
            *edx = kvm_arch_get_supported_cpuid(env, 0xd, count, R_EDX);
1106 51e49430 Sheng Yang
        } else {
1107 51e49430 Sheng Yang
            *eax = 0;
1108 51e49430 Sheng Yang
            *ebx = 0;
1109 51e49430 Sheng Yang
            *ecx = 0;
1110 51e49430 Sheng Yang
            *edx = 0;
1111 51e49430 Sheng Yang
        }
1112 51e49430 Sheng Yang
        break;
1113 c6dc6f63 Andre Przywara
    case 0x80000000:
1114 c6dc6f63 Andre Przywara
        *eax = env->cpuid_xlevel;
1115 c6dc6f63 Andre Przywara
        *ebx = env->cpuid_vendor1;
1116 c6dc6f63 Andre Przywara
        *edx = env->cpuid_vendor2;
1117 c6dc6f63 Andre Przywara
        *ecx = env->cpuid_vendor3;
1118 c6dc6f63 Andre Przywara
        break;
1119 c6dc6f63 Andre Przywara
    case 0x80000001:
1120 c6dc6f63 Andre Przywara
        *eax = env->cpuid_version;
1121 c6dc6f63 Andre Przywara
        *ebx = 0;
1122 c6dc6f63 Andre Przywara
        *ecx = env->cpuid_ext3_features;
1123 c6dc6f63 Andre Przywara
        *edx = env->cpuid_ext2_features;
1124 c6dc6f63 Andre Przywara
1125 c6dc6f63 Andre Przywara
        /* The Linux kernel checks for the CMPLegacy bit and
1126 c6dc6f63 Andre Przywara
         * discards multiple thread information if it is set.
1127 c6dc6f63 Andre Przywara
         * So dont set it here for Intel to make Linux guests happy.
1128 c6dc6f63 Andre Przywara
         */
1129 c6dc6f63 Andre Przywara
        if (env->nr_cores * env->nr_threads > 1) {
1130 c6dc6f63 Andre Przywara
            uint32_t tebx, tecx, tedx;
1131 c6dc6f63 Andre Przywara
            get_cpuid_vendor(env, &tebx, &tecx, &tedx);
1132 c6dc6f63 Andre Przywara
            if (tebx != CPUID_VENDOR_INTEL_1 ||
1133 c6dc6f63 Andre Przywara
                tedx != CPUID_VENDOR_INTEL_2 ||
1134 c6dc6f63 Andre Przywara
                tecx != CPUID_VENDOR_INTEL_3) {
1135 c6dc6f63 Andre Przywara
                *ecx |= 1 << 1;    /* CmpLegacy bit */
1136 c6dc6f63 Andre Przywara
            }
1137 c6dc6f63 Andre Przywara
        }
1138 c6dc6f63 Andre Przywara
1139 c6dc6f63 Andre Przywara
        if (kvm_enabled()) {
1140 c6dc6f63 Andre Przywara
            /* Nested SVM not yet supported in upstream QEMU */
1141 c6dc6f63 Andre Przywara
            *ecx &= ~CPUID_EXT3_SVM;
1142 c6dc6f63 Andre Przywara
        }
1143 c6dc6f63 Andre Przywara
        break;
1144 c6dc6f63 Andre Przywara
    case 0x80000002:
1145 c6dc6f63 Andre Przywara
    case 0x80000003:
1146 c6dc6f63 Andre Przywara
    case 0x80000004:
1147 c6dc6f63 Andre Przywara
        *eax = env->cpuid_model[(index - 0x80000002) * 4 + 0];
1148 c6dc6f63 Andre Przywara
        *ebx = env->cpuid_model[(index - 0x80000002) * 4 + 1];
1149 c6dc6f63 Andre Przywara
        *ecx = env->cpuid_model[(index - 0x80000002) * 4 + 2];
1150 c6dc6f63 Andre Przywara
        *edx = env->cpuid_model[(index - 0x80000002) * 4 + 3];
1151 c6dc6f63 Andre Przywara
        break;
1152 c6dc6f63 Andre Przywara
    case 0x80000005:
1153 c6dc6f63 Andre Przywara
        /* cache info (L1 cache) */
1154 c6dc6f63 Andre Przywara
        *eax = 0x01ff01ff;
1155 c6dc6f63 Andre Przywara
        *ebx = 0x01ff01ff;
1156 c6dc6f63 Andre Przywara
        *ecx = 0x40020140;
1157 c6dc6f63 Andre Przywara
        *edx = 0x40020140;
1158 c6dc6f63 Andre Przywara
        break;
1159 c6dc6f63 Andre Przywara
    case 0x80000006:
1160 c6dc6f63 Andre Przywara
        /* cache info (L2 cache) */
1161 c6dc6f63 Andre Przywara
        *eax = 0;
1162 c6dc6f63 Andre Przywara
        *ebx = 0x42004200;
1163 c6dc6f63 Andre Przywara
        *ecx = 0x02008140;
1164 c6dc6f63 Andre Przywara
        *edx = 0;
1165 c6dc6f63 Andre Przywara
        break;
1166 c6dc6f63 Andre Przywara
    case 0x80000008:
1167 c6dc6f63 Andre Przywara
        /* virtual & phys address size in low 2 bytes. */
1168 c6dc6f63 Andre Przywara
/* XXX: This value must match the one used in the MMU code. */
1169 c6dc6f63 Andre Przywara
        if (env->cpuid_ext2_features & CPUID_EXT2_LM) {
1170 c6dc6f63 Andre Przywara
            /* 64 bit processor */
1171 c6dc6f63 Andre Przywara
/* XXX: The physical address space is limited to 42 bits in exec.c. */
1172 c6dc6f63 Andre Przywara
            *eax = 0x00003028;        /* 48 bits virtual, 40 bits physical */
1173 c6dc6f63 Andre Przywara
        } else {
1174 c6dc6f63 Andre Przywara
            if (env->cpuid_features & CPUID_PSE36)
1175 c6dc6f63 Andre Przywara
                *eax = 0x00000024; /* 36 bits physical */
1176 c6dc6f63 Andre Przywara
            else
1177 c6dc6f63 Andre Przywara
                *eax = 0x00000020; /* 32 bits physical */
1178 c6dc6f63 Andre Przywara
        }
1179 c6dc6f63 Andre Przywara
        *ebx = 0;
1180 c6dc6f63 Andre Przywara
        *ecx = 0;
1181 c6dc6f63 Andre Przywara
        *edx = 0;
1182 c6dc6f63 Andre Przywara
        if (env->nr_cores * env->nr_threads > 1) {
1183 c6dc6f63 Andre Przywara
            *ecx |= (env->nr_cores * env->nr_threads) - 1;
1184 c6dc6f63 Andre Przywara
        }
1185 c6dc6f63 Andre Przywara
        break;
1186 c6dc6f63 Andre Przywara
    case 0x8000000A:
1187 c6dc6f63 Andre Przywara
        *eax = 0x00000001; /* SVM Revision */
1188 c6dc6f63 Andre Przywara
        *ebx = 0x00000010; /* nr of ASIDs */
1189 c6dc6f63 Andre Przywara
        *ecx = 0;
1190 c6dc6f63 Andre Przywara
        *edx = 0; /* optional features */
1191 c6dc6f63 Andre Przywara
        break;
1192 c6dc6f63 Andre Przywara
    default:
1193 c6dc6f63 Andre Przywara
        /* reserved values: zero */
1194 c6dc6f63 Andre Przywara
        *eax = 0;
1195 c6dc6f63 Andre Przywara
        *ebx = 0;
1196 c6dc6f63 Andre Przywara
        *ecx = 0;
1197 c6dc6f63 Andre Przywara
        *edx = 0;
1198 c6dc6f63 Andre Przywara
        break;
1199 c6dc6f63 Andre Przywara
    }
1200 c6dc6f63 Andre Przywara
}