blob: 78876f632bdae1d3a3f43ed9d0f100d41bf57e35 [file] [log] [blame]
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001/*
2 * i386 CPUID helper functions
3 *
4 * Copyright (c) 2003 Fabrice Bellard
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 */
19#include <stdlib.h>
20#include <stdio.h>
21#include <string.h>
22#include <inttypes.h>
23
24#include "cpu.h"
25#include "kvm.h"
26
27#include "qemu-option.h"
28#include "qemu-config.h"
29
Andreas Färber71ad61d2012-04-17 12:10:29 +020030#include "qapi/qapi-visit-core.h"
Anthony Liguori76b64a72012-08-14 22:17:36 -050031#include "arch_init.h"
Andreas Färber71ad61d2012-04-17 12:10:29 +020032
Vadim Rozenfeld28f52cc2011-12-18 22:48:13 +020033#include "hyperv.h"
34
Igor Mammedov65dee382012-07-23 15:22:28 +020035#include "hw/hw.h"
Stefan Weilb834b502012-08-30 22:28:31 +020036#if defined(CONFIG_KVM)
Anthony Liguorief8621b2012-08-29 09:32:41 -050037#include <linux/kvm_para.h>
Stefan Weilb834b502012-08-30 22:28:31 +020038#endif
Igor Mammedov65dee382012-07-23 15:22:28 +020039
Andre Przywarac6dc6f62010-03-11 14:38:55 +010040/* feature flags taken from "Intel Processor Identification and the CPUID
41 * Instruction" and AMD's "CPUID Specification". In cases of disagreement
42 * between feature naming conventions, aliases may be added.
43 */
44static const char *feature_name[] = {
45 "fpu", "vme", "de", "pse",
46 "tsc", "msr", "pae", "mce",
47 "cx8", "apic", NULL, "sep",
48 "mtrr", "pge", "mca", "cmov",
49 "pat", "pse36", "pn" /* Intel psn */, "clflush" /* Intel clfsh */,
50 NULL, "ds" /* Intel dts */, "acpi", "mmx",
51 "fxsr", "sse", "sse2", "ss",
52 "ht" /* Intel htt */, "tm", "ia64", "pbe",
53};
54static const char *ext_feature_name[] = {
Eduardo Habkostf370be32012-02-17 14:41:20 -020055 "pni|sse3" /* Intel,AMD sse3 */, "pclmulqdq|pclmuldq", "dtes64", "monitor",
Andre Przywarae117f772010-03-11 14:38:59 +010056 "ds_cpl", "vmx", "smx", "est",
Andre Przywarac6dc6f62010-03-11 14:38:55 +010057 "tm2", "ssse3", "cid", NULL,
Andre Przywarae117f772010-03-11 14:38:59 +010058 "fma", "cx16", "xtpr", "pdcm",
Mao, Junjie434acb82012-07-20 07:08:21 +000059 NULL, "pcid", "dca", "sse4.1|sse4_1",
Andre Przywarae117f772010-03-11 14:38:59 +010060 "sse4.2|sse4_2", "x2apic", "movbe", "popcnt",
Eduardo Habkosteaf3f092012-03-06 15:11:30 -030061 "tsc-deadline", "aes", "xsave", "osxsave",
Andre Przywarae117f772010-03-11 14:38:59 +010062 "avx", NULL, NULL, "hypervisor",
Andre Przywarac6dc6f62010-03-11 14:38:55 +010063};
Eduardo Habkost3b671a42012-09-06 10:05:38 +000064/* Feature names that are already defined on feature_name[] but are set on
65 * CPUID[8000_0001].EDX on AMD CPUs don't have their names on
66 * ext2_feature_name[]. They are copied automatically to cpuid_ext2_features
67 * if and only if CPU vendor is AMD.
68 */
Andre Przywarac6dc6f62010-03-11 14:38:55 +010069static const char *ext2_feature_name[] = {
Eduardo Habkost3b671a42012-09-06 10:05:38 +000070 NULL /* fpu */, NULL /* vme */, NULL /* de */, NULL /* pse */,
71 NULL /* tsc */, NULL /* msr */, NULL /* pae */, NULL /* mce */,
72 NULL /* cx8 */ /* AMD CMPXCHG8B */, NULL /* apic */, NULL, "syscall",
73 NULL /* mtrr */, NULL /* pge */, NULL /* mca */, NULL /* cmov */,
74 NULL /* pat */, NULL /* pse36 */, NULL, NULL /* Linux mp */,
75 "nx|xd", NULL, "mmxext", NULL /* mmx */,
76 NULL /* fxsr */, "fxsr_opt|ffxsr", "pdpe1gb" /* AMD Page1GB */, "rdtscp",
Eduardo Habkost01f590d2012-10-24 12:10:33 -020077 NULL, "lm|i64", "3dnowext", "3dnow",
Andre Przywarac6dc6f62010-03-11 14:38:55 +010078};
79static const char *ext3_feature_name[] = {
80 "lahf_lm" /* AMD LahfSahf */, "cmp_legacy", "svm", "extapic" /* AMD ExtApicSpace */,
81 "cr8legacy" /* AMD AltMovCr8 */, "abm", "sse4a", "misalignsse",
Andre Przywarae117f772010-03-11 14:38:59 +010082 "3dnowprefetch", "osvw", "ibs", "xop",
Andre Przywarac6dc6f62010-03-11 14:38:55 +010083 "skinit", "wdt", NULL, NULL,
Andre Przywarae117f772010-03-11 14:38:59 +010084 "fma4", NULL, "cvt16", "nodeid_msr",
Andre Przywarac6dc6f62010-03-11 14:38:55 +010085 NULL, NULL, NULL, NULL,
86 NULL, NULL, NULL, NULL,
87 NULL, NULL, NULL, NULL,
88};
89
90static const char *kvm_feature_name[] = {
Michael S. Tsirkinbfee7542012-07-01 18:08:30 +030091 "kvmclock", "kvm_nopiodelay", "kvm_mmu", "kvmclock", "kvm_asyncpf", NULL, "kvm_pv_eoi", NULL,
Andre Przywarac6dc6f62010-03-11 14:38:55 +010092 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
93 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
94 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
95};
96
Joerg Roedel296acb62010-09-27 15:16:17 +020097static const char *svm_feature_name[] = {
98 "npt", "lbrv", "svm_lock", "nrip_save",
99 "tsc_scale", "vmcb_clean", "flushbyasid", "decodeassists",
100 NULL, NULL, "pause_filter", NULL,
101 "pfthreshold", NULL, NULL, NULL,
102 NULL, NULL, NULL, NULL,
103 NULL, NULL, NULL, NULL,
104 NULL, NULL, NULL, NULL,
105 NULL, NULL, NULL, NULL,
106};
107
H. Peter Anvina9321a42012-09-26 13:18:43 -0700108static const char *cpuid_7_0_ebx_feature_name[] = {
109 NULL, NULL, NULL, NULL, NULL, NULL, NULL, "smep",
110 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
111 NULL, NULL, NULL, NULL, "smap", NULL, NULL, NULL,
112 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
113};
114
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100115/* collects per-function cpuid data
116 */
117typedef struct model_features_t {
118 uint32_t *guest_feat;
119 uint32_t *host_feat;
120 uint32_t check_feat;
121 const char **flag_names;
122 uint32_t cpuid;
123 } model_features_t;
124
125int check_cpuid = 0;
126int enforce_cpuid = 0;
127
Michael S. Tsirkindc599442012-10-18 00:15:48 +0200128#if defined(CONFIG_KVM)
129static uint32_t kvm_default_features = (1 << KVM_FEATURE_CLOCKSOURCE) |
130 (1 << KVM_FEATURE_NOP_IO_DELAY) |
131 (1 << KVM_FEATURE_MMU_OP) |
132 (1 << KVM_FEATURE_CLOCKSOURCE2) |
133 (1 << KVM_FEATURE_ASYNC_PF) |
134 (1 << KVM_FEATURE_STEAL_TIME) |
135 (1 << KVM_FEATURE_CLOCKSOURCE_STABLE_BIT);
136static const uint32_t kvm_pv_eoi_features = (0x1 << KVM_FEATURE_PV_EOI);
137#else
138static uint32_t kvm_default_features = 0;
139static const uint32_t kvm_pv_eoi_features = 0;
140#endif
141
142void enable_kvm_pv_eoi(void)
143{
144 kvm_default_features |= kvm_pv_eoi_features;
145}
146
Jan Kiszkabb44e0d2011-01-21 21:48:07 +0100147void host_cpuid(uint32_t function, uint32_t count,
148 uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
Andre Przywarabdde4762010-03-11 14:38:58 +0100149{
150#if defined(CONFIG_KVM)
Anthony Liguoria1fd24a2011-11-27 11:13:01 -0600151 uint32_t vec[4];
152
153#ifdef __x86_64__
154 asm volatile("cpuid"
155 : "=a"(vec[0]), "=b"(vec[1]),
156 "=c"(vec[2]), "=d"(vec[3])
157 : "0"(function), "c"(count) : "cc");
158#else
159 asm volatile("pusha \n\t"
160 "cpuid \n\t"
161 "mov %%eax, 0(%2) \n\t"
162 "mov %%ebx, 4(%2) \n\t"
163 "mov %%ecx, 8(%2) \n\t"
164 "mov %%edx, 12(%2) \n\t"
165 "popa"
166 : : "a"(function), "c"(count), "S"(vec)
167 : "memory", "cc");
168#endif
169
Andre Przywarabdde4762010-03-11 14:38:58 +0100170 if (eax)
Anthony Liguoria1fd24a2011-11-27 11:13:01 -0600171 *eax = vec[0];
Andre Przywarabdde4762010-03-11 14:38:58 +0100172 if (ebx)
Anthony Liguoria1fd24a2011-11-27 11:13:01 -0600173 *ebx = vec[1];
Andre Przywarabdde4762010-03-11 14:38:58 +0100174 if (ecx)
Anthony Liguoria1fd24a2011-11-27 11:13:01 -0600175 *ecx = vec[2];
Andre Przywarabdde4762010-03-11 14:38:58 +0100176 if (edx)
Anthony Liguoria1fd24a2011-11-27 11:13:01 -0600177 *edx = vec[3];
Andre Przywarabdde4762010-03-11 14:38:58 +0100178#endif
179}
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100180
181#define iswhite(c) ((c) && ((c) <= ' ' || '~' < (c)))
182
183/* general substring compare of *[s1..e1) and *[s2..e2). sx is start of
184 * a substring. ex if !NULL points to the first char after a substring,
185 * otherwise the string is assumed to sized by a terminating nul.
186 * Return lexical ordering of *s1:*s2.
187 */
188static int sstrcmp(const char *s1, const char *e1, const char *s2,
189 const char *e2)
190{
191 for (;;) {
192 if (!*s1 || !*s2 || *s1 != *s2)
193 return (*s1 - *s2);
194 ++s1, ++s2;
195 if (s1 == e1 && s2 == e2)
196 return (0);
197 else if (s1 == e1)
198 return (*s2);
199 else if (s2 == e2)
200 return (*s1);
201 }
202}
203
204/* compare *[s..e) to *altstr. *altstr may be a simple string or multiple
205 * '|' delimited (possibly empty) strings in which case search for a match
206 * within the alternatives proceeds left to right. Return 0 for success,
207 * non-zero otherwise.
208 */
209static int altcmp(const char *s, const char *e, const char *altstr)
210{
211 const char *p, *q;
212
213 for (q = p = altstr; ; ) {
214 while (*p && *p != '|')
215 ++p;
216 if ((q == p && !*s) || (q != p && !sstrcmp(s, e, q, p)))
217 return (0);
218 if (!*p)
219 return (1);
220 else
221 q = ++p;
222 }
223}
224
225/* search featureset for flag *[s..e), if found set corresponding bit in
Jan Kiszkae41e0fc2011-04-19 13:06:06 +0200226 * *pval and return true, otherwise return false
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100227 */
Jan Kiszkae41e0fc2011-04-19 13:06:06 +0200228static bool lookup_feature(uint32_t *pval, const char *s, const char *e,
229 const char **featureset)
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100230{
231 uint32_t mask;
232 const char **ppc;
Jan Kiszkae41e0fc2011-04-19 13:06:06 +0200233 bool found = false;
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100234
Jan Kiszkae41e0fc2011-04-19 13:06:06 +0200235 for (mask = 1, ppc = featureset; mask; mask <<= 1, ++ppc) {
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100236 if (*ppc && !altcmp(s, e, *ppc)) {
237 *pval |= mask;
Jan Kiszkae41e0fc2011-04-19 13:06:06 +0200238 found = true;
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100239 }
Jan Kiszkae41e0fc2011-04-19 13:06:06 +0200240 }
241 return found;
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100242}
243
244static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features,
245 uint32_t *ext_features,
246 uint32_t *ext2_features,
247 uint32_t *ext3_features,
Joerg Roedel296acb62010-09-27 15:16:17 +0200248 uint32_t *kvm_features,
H. Peter Anvina9321a42012-09-26 13:18:43 -0700249 uint32_t *svm_features,
250 uint32_t *cpuid_7_0_ebx_features)
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100251{
252 if (!lookup_feature(features, flagname, NULL, feature_name) &&
253 !lookup_feature(ext_features, flagname, NULL, ext_feature_name) &&
254 !lookup_feature(ext2_features, flagname, NULL, ext2_feature_name) &&
255 !lookup_feature(ext3_features, flagname, NULL, ext3_feature_name) &&
Joerg Roedel296acb62010-09-27 15:16:17 +0200256 !lookup_feature(kvm_features, flagname, NULL, kvm_feature_name) &&
H. Peter Anvina9321a42012-09-26 13:18:43 -0700257 !lookup_feature(svm_features, flagname, NULL, svm_feature_name) &&
258 !lookup_feature(cpuid_7_0_ebx_features, flagname, NULL,
259 cpuid_7_0_ebx_feature_name))
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100260 fprintf(stderr, "CPU feature %s not found\n", flagname);
261}
262
263typedef struct x86_def_t {
264 struct x86_def_t *next;
265 const char *name;
266 uint32_t level;
267 uint32_t vendor1, vendor2, vendor3;
268 int family;
269 int model;
270 int stepping;
Joerg Roedelb862d1f2011-07-07 16:13:12 +0200271 int tsc_khz;
Joerg Roedel296acb62010-09-27 15:16:17 +0200272 uint32_t features, ext_features, ext2_features, ext3_features;
273 uint32_t kvm_features, svm_features;
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100274 uint32_t xlevel;
275 char model_id[48];
276 int vendor_override;
brillywu@viatech.com.cnb3baa152011-06-01 09:59:52 +0800277 /* Store the results of Centaur's CPUID instructions */
278 uint32_t ext4_features;
279 uint32_t xlevel2;
Eduardo Habkost13526722012-05-21 11:27:02 -0300280 /* The feature bits on CPUID[EAX=7,ECX=0].EBX */
281 uint32_t cpuid_7_0_ebx_features;
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100282} x86_def_t;
283
284#define I486_FEATURES (CPUID_FP87 | CPUID_VME | CPUID_PSE)
285#define PENTIUM_FEATURES (I486_FEATURES | CPUID_DE | CPUID_TSC | \
286 CPUID_MSR | CPUID_MCE | CPUID_CX8 | CPUID_MMX | CPUID_APIC)
287#define PENTIUM2_FEATURES (PENTIUM_FEATURES | CPUID_PAE | CPUID_SEP | \
288 CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_CMOV | CPUID_PAT | \
289 CPUID_PSE36 | CPUID_FXSR)
290#define PENTIUM3_FEATURES (PENTIUM2_FEATURES | CPUID_SSE)
291#define PPRO_FEATURES (CPUID_FP87 | CPUID_DE | CPUID_PSE | CPUID_TSC | \
292 CPUID_MSR | CPUID_MCE | CPUID_CX8 | CPUID_PGE | CPUID_CMOV | \
293 CPUID_PAT | CPUID_FXSR | CPUID_MMX | CPUID_SSE | CPUID_SSE2 | \
294 CPUID_PAE | CPUID_SEP | CPUID_APIC)
295
Andre Przywara551a2de2010-03-11 14:39:03 +0100296#define TCG_FEATURES (CPUID_FP87 | CPUID_PSE | CPUID_TSC | CPUID_MSR | \
297 CPUID_PAE | CPUID_MCE | CPUID_CX8 | CPUID_APIC | CPUID_SEP | \
298 CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_CMOV | CPUID_PAT | \
299 CPUID_PSE36 | CPUID_CLFLUSH | CPUID_ACPI | CPUID_MMX | \
300 CPUID_FXSR | CPUID_SSE | CPUID_SSE2 | CPUID_SS)
Aurelien Jarno8560efe2010-03-13 16:43:15 +0100301 /* partly implemented:
302 CPUID_MTRR, CPUID_MCA, CPUID_CLFLUSH (needed for Win64)
303 CPUID_PSE36 (needed for Solaris) */
304 /* missing:
305 CPUID_VME, CPUID_DTS, CPUID_SS, CPUID_HT, CPUID_TM, CPUID_PBE */
Andre Przywara551a2de2010-03-11 14:39:03 +0100306#define TCG_EXT_FEATURES (CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | \
Andi Kleen8713f8f2010-06-26 22:54:21 +0200307 CPUID_EXT_CX16 | CPUID_EXT_POPCNT | \
Andre Przywara551a2de2010-03-11 14:39:03 +0100308 CPUID_EXT_HYPERVISOR)
Aurelien Jarno8560efe2010-03-13 16:43:15 +0100309 /* missing:
310 CPUID_EXT_DTES64, CPUID_EXT_DSCPL, CPUID_EXT_VMX, CPUID_EXT_EST,
Andi Kleen8713f8f2010-06-26 22:54:21 +0200311 CPUID_EXT_TM2, CPUID_EXT_XTPR, CPUID_EXT_PDCM, CPUID_EXT_XSAVE */
Eduardo Habkost60032ac2012-09-06 10:05:37 +0000312#define TCG_EXT2_FEATURES ((TCG_FEATURES & CPUID_EXT2_AMD_ALIASES) | \
Andre Przywara551a2de2010-03-11 14:39:03 +0100313 CPUID_EXT2_NX | CPUID_EXT2_MMXEXT | CPUID_EXT2_RDTSCP | \
314 CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT)
Aurelien Jarno8560efe2010-03-13 16:43:15 +0100315 /* missing:
316 CPUID_EXT2_PDPE1GB */
Andre Przywara551a2de2010-03-11 14:39:03 +0100317#define TCG_EXT3_FEATURES (CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM | \
318 CPUID_EXT3_CR8LEG | CPUID_EXT3_ABM | CPUID_EXT3_SSE4A)
Joerg Roedel296acb62010-09-27 15:16:17 +0200319#define TCG_SVM_FEATURES 0
H. Peter Anvina9321a42012-09-26 13:18:43 -0700320#define TCG_7_0_EBX_FEATURES (CPUID_7_0_EBX_SMEP | CPUID_7_0_EBX_SMAP)
Andre Przywara551a2de2010-03-11 14:39:03 +0100321
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100322/* maintains list of cpu model definitions
323 */
324static x86_def_t *x86_defs = {NULL};
325
326/* built-in cpu model definitions (deprecated)
327 */
328static x86_def_t builtin_x86_defs[] = {
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100329 {
330 .name = "qemu64",
331 .level = 4,
332 .vendor1 = CPUID_VENDOR_AMD_1,
333 .vendor2 = CPUID_VENDOR_AMD_2,
334 .vendor3 = CPUID_VENDOR_AMD_3,
335 .family = 6,
336 .model = 2,
337 .stepping = 3,
338 .features = PPRO_FEATURES |
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100339 CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100340 CPUID_PSE36,
341 .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_CX16 | CPUID_EXT_POPCNT,
Eduardo Habkost60032ac2012-09-06 10:05:37 +0000342 .ext2_features = (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) |
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100343 CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
344 .ext3_features = CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM |
345 CPUID_EXT3_ABM | CPUID_EXT3_SSE4A,
346 .xlevel = 0x8000000A,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100347 },
348 {
349 .name = "phenom",
350 .level = 5,
351 .vendor1 = CPUID_VENDOR_AMD_1,
352 .vendor2 = CPUID_VENDOR_AMD_2,
353 .vendor3 = CPUID_VENDOR_AMD_3,
354 .family = 16,
355 .model = 2,
356 .stepping = 3,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100357 .features = PPRO_FEATURES |
358 CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
Aurelien Jarno8560efe2010-03-13 16:43:15 +0100359 CPUID_PSE36 | CPUID_VME | CPUID_HT,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100360 .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_CX16 |
361 CPUID_EXT_POPCNT,
Eduardo Habkost60032ac2012-09-06 10:05:37 +0000362 .ext2_features = (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) |
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100363 CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX |
364 CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT | CPUID_EXT2_MMXEXT |
Aurelien Jarno8560efe2010-03-13 16:43:15 +0100365 CPUID_EXT2_FFXSR | CPUID_EXT2_PDPE1GB | CPUID_EXT2_RDTSCP,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100366 /* Missing: CPUID_EXT3_CMP_LEG, CPUID_EXT3_EXTAPIC,
367 CPUID_EXT3_CR8LEG,
368 CPUID_EXT3_MISALIGNSSE, CPUID_EXT3_3DNOWPREFETCH,
369 CPUID_EXT3_OSVW, CPUID_EXT3_IBS */
370 .ext3_features = CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM |
371 CPUID_EXT3_ABM | CPUID_EXT3_SSE4A,
Joerg Roedel296acb62010-09-27 15:16:17 +0200372 .svm_features = CPUID_SVM_NPT | CPUID_SVM_LBRV,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100373 .xlevel = 0x8000001A,
374 .model_id = "AMD Phenom(tm) 9550 Quad-Core Processor"
375 },
376 {
377 .name = "core2duo",
378 .level = 10,
379 .family = 6,
380 .model = 15,
381 .stepping = 11,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100382 .features = PPRO_FEATURES |
383 CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
Aurelien Jarno8560efe2010-03-13 16:43:15 +0100384 CPUID_PSE36 | CPUID_VME | CPUID_DTS | CPUID_ACPI | CPUID_SS |
385 CPUID_HT | CPUID_TM | CPUID_PBE,
386 .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_SSSE3 |
387 CPUID_EXT_DTES64 | CPUID_EXT_DSCPL | CPUID_EXT_VMX | CPUID_EXT_EST |
388 CPUID_EXT_TM2 | CPUID_EXT_CX16 | CPUID_EXT_XTPR | CPUID_EXT_PDCM,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100389 .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
390 .ext3_features = CPUID_EXT3_LAHF_LM,
391 .xlevel = 0x80000008,
392 .model_id = "Intel(R) Core(TM)2 Duo CPU T7700 @ 2.40GHz",
393 },
394 {
395 .name = "kvm64",
396 .level = 5,
397 .vendor1 = CPUID_VENDOR_INTEL_1,
398 .vendor2 = CPUID_VENDOR_INTEL_2,
399 .vendor3 = CPUID_VENDOR_INTEL_3,
400 .family = 15,
401 .model = 6,
402 .stepping = 1,
403 /* Missing: CPUID_VME, CPUID_HT */
404 .features = PPRO_FEATURES |
405 CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
406 CPUID_PSE36,
407 /* Missing: CPUID_EXT_POPCNT, CPUID_EXT_MONITOR */
408 .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_CX16,
409 /* Missing: CPUID_EXT2_PDPE1GB, CPUID_EXT2_RDTSCP */
Eduardo Habkost60032ac2012-09-06 10:05:37 +0000410 .ext2_features = (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) |
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100411 CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
412 /* Missing: CPUID_EXT3_LAHF_LM, CPUID_EXT3_CMP_LEG, CPUID_EXT3_EXTAPIC,
413 CPUID_EXT3_CR8LEG, CPUID_EXT3_ABM, CPUID_EXT3_SSE4A,
414 CPUID_EXT3_MISALIGNSSE, CPUID_EXT3_3DNOWPREFETCH,
415 CPUID_EXT3_OSVW, CPUID_EXT3_IBS, CPUID_EXT3_SVM */
416 .ext3_features = 0,
417 .xlevel = 0x80000008,
418 .model_id = "Common KVM processor"
419 },
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100420 {
421 .name = "qemu32",
422 .level = 4,
423 .family = 6,
424 .model = 3,
425 .stepping = 3,
426 .features = PPRO_FEATURES,
427 .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_POPCNT,
Andre Przywara58012d62010-03-11 14:39:06 +0100428 .xlevel = 0x80000004,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100429 },
430 {
Andre Przywaraeafaf1e2010-05-21 09:50:51 +0200431 .name = "kvm32",
432 .level = 5,
433 .family = 15,
434 .model = 6,
435 .stepping = 1,
436 .features = PPRO_FEATURES |
437 CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_PSE36,
438 .ext_features = CPUID_EXT_SSE3,
Eduardo Habkost60032ac2012-09-06 10:05:37 +0000439 .ext2_features = PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES,
Andre Przywaraeafaf1e2010-05-21 09:50:51 +0200440 .ext3_features = 0,
441 .xlevel = 0x80000008,
442 .model_id = "Common 32-bit KVM processor"
443 },
444 {
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100445 .name = "coreduo",
446 .level = 10,
447 .family = 6,
448 .model = 14,
449 .stepping = 8,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100450 .features = PPRO_FEATURES | CPUID_VME |
Aurelien Jarno8560efe2010-03-13 16:43:15 +0100451 CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_DTS | CPUID_ACPI |
452 CPUID_SS | CPUID_HT | CPUID_TM | CPUID_PBE,
453 .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_VMX |
454 CPUID_EXT_EST | CPUID_EXT_TM2 | CPUID_EXT_XTPR | CPUID_EXT_PDCM,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100455 .ext2_features = CPUID_EXT2_NX,
456 .xlevel = 0x80000008,
457 .model_id = "Genuine Intel(R) CPU T2600 @ 2.16GHz",
458 },
459 {
460 .name = "486",
Andre Przywara58012d62010-03-11 14:39:06 +0100461 .level = 1,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100462 .family = 4,
463 .model = 0,
464 .stepping = 0,
465 .features = I486_FEATURES,
466 .xlevel = 0,
467 },
468 {
469 .name = "pentium",
470 .level = 1,
471 .family = 5,
472 .model = 4,
473 .stepping = 3,
474 .features = PENTIUM_FEATURES,
475 .xlevel = 0,
476 },
477 {
478 .name = "pentium2",
479 .level = 2,
480 .family = 6,
481 .model = 5,
482 .stepping = 2,
483 .features = PENTIUM2_FEATURES,
484 .xlevel = 0,
485 },
486 {
487 .name = "pentium3",
488 .level = 2,
489 .family = 6,
490 .model = 7,
491 .stepping = 3,
492 .features = PENTIUM3_FEATURES,
493 .xlevel = 0,
494 },
495 {
496 .name = "athlon",
497 .level = 2,
498 .vendor1 = CPUID_VENDOR_AMD_1,
499 .vendor2 = CPUID_VENDOR_AMD_2,
500 .vendor3 = CPUID_VENDOR_AMD_3,
501 .family = 6,
502 .model = 2,
503 .stepping = 3,
Eduardo Habkost60032ac2012-09-06 10:05:37 +0000504 .features = PPRO_FEATURES | CPUID_PSE36 | CPUID_VME | CPUID_MTRR |
505 CPUID_MCA,
506 .ext2_features = (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) |
507 CPUID_EXT2_MMXEXT | CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100508 .xlevel = 0x80000008,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100509 },
510 {
511 .name = "n270",
512 /* original is on level 10 */
513 .level = 5,
514 .family = 6,
515 .model = 28,
516 .stepping = 2,
517 .features = PPRO_FEATURES |
Aurelien Jarno8560efe2010-03-13 16:43:15 +0100518 CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_VME | CPUID_DTS |
519 CPUID_ACPI | CPUID_SS | CPUID_HT | CPUID_TM | CPUID_PBE,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100520 /* Some CPUs got no CPUID_SEP */
Aurelien Jarno8560efe2010-03-13 16:43:15 +0100521 .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_SSSE3 |
522 CPUID_EXT_DSCPL | CPUID_EXT_EST | CPUID_EXT_TM2 | CPUID_EXT_XTPR,
Eduardo Habkost60032ac2012-09-06 10:05:37 +0000523 .ext2_features = (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) |
524 CPUID_EXT2_NX,
Aurelien Jarno8560efe2010-03-13 16:43:15 +0100525 .ext3_features = CPUID_EXT3_LAHF_LM,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100526 .xlevel = 0x8000000A,
527 .model_id = "Intel(R) Atom(TM) CPU N270 @ 1.60GHz",
528 },
Eduardo Habkost3eca4642012-09-05 17:41:10 -0300529 {
530 .name = "Conroe",
531 .level = 2,
532 .vendor1 = CPUID_VENDOR_INTEL_1,
533 .vendor2 = CPUID_VENDOR_INTEL_2,
534 .vendor3 = CPUID_VENDOR_INTEL_3,
535 .family = 6,
536 .model = 2,
537 .stepping = 3,
538 .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
539 CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
540 CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
541 CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
542 CPUID_DE | CPUID_FP87,
543 .ext_features = CPUID_EXT_SSSE3 | CPUID_EXT_SSE3,
544 .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_NX | CPUID_EXT2_SYSCALL,
545 .ext3_features = CPUID_EXT3_LAHF_LM,
546 .xlevel = 0x8000000A,
547 .model_id = "Intel Celeron_4x0 (Conroe/Merom Class Core 2)",
548 },
549 {
550 .name = "Penryn",
551 .level = 2,
552 .vendor1 = CPUID_VENDOR_INTEL_1,
553 .vendor2 = CPUID_VENDOR_INTEL_2,
554 .vendor3 = CPUID_VENDOR_INTEL_3,
555 .family = 6,
556 .model = 2,
557 .stepping = 3,
558 .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
559 CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
560 CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
561 CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
562 CPUID_DE | CPUID_FP87,
563 .ext_features = CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 |
564 CPUID_EXT_SSE3,
565 .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_NX | CPUID_EXT2_SYSCALL,
566 .ext3_features = CPUID_EXT3_LAHF_LM,
567 .xlevel = 0x8000000A,
568 .model_id = "Intel Core 2 Duo P9xxx (Penryn Class Core 2)",
569 },
570 {
571 .name = "Nehalem",
572 .level = 2,
573 .vendor1 = CPUID_VENDOR_INTEL_1,
574 .vendor2 = CPUID_VENDOR_INTEL_2,
575 .vendor3 = CPUID_VENDOR_INTEL_3,
576 .family = 6,
577 .model = 2,
578 .stepping = 3,
579 .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
580 CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
581 CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
582 CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
583 CPUID_DE | CPUID_FP87,
584 .ext_features = CPUID_EXT_POPCNT | CPUID_EXT_SSE42 | CPUID_EXT_SSE41 |
585 CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | CPUID_EXT_SSE3,
586 .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
587 .ext3_features = CPUID_EXT3_LAHF_LM,
588 .xlevel = 0x8000000A,
589 .model_id = "Intel Core i7 9xx (Nehalem Class Core i7)",
590 },
591 {
592 .name = "Westmere",
593 .level = 11,
594 .vendor1 = CPUID_VENDOR_INTEL_1,
595 .vendor2 = CPUID_VENDOR_INTEL_2,
596 .vendor3 = CPUID_VENDOR_INTEL_3,
597 .family = 6,
598 .model = 44,
599 .stepping = 1,
600 .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
601 CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
602 CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
603 CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
604 CPUID_DE | CPUID_FP87,
605 .ext_features = CPUID_EXT_AES | CPUID_EXT_POPCNT | CPUID_EXT_SSE42 |
606 CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 |
607 CPUID_EXT_SSE3,
608 .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
609 .ext3_features = CPUID_EXT3_LAHF_LM,
610 .xlevel = 0x8000000A,
611 .model_id = "Westmere E56xx/L56xx/X56xx (Nehalem-C)",
612 },
613 {
614 .name = "SandyBridge",
615 .level = 0xd,
616 .vendor1 = CPUID_VENDOR_INTEL_1,
617 .vendor2 = CPUID_VENDOR_INTEL_2,
618 .vendor3 = CPUID_VENDOR_INTEL_3,
619 .family = 6,
620 .model = 42,
621 .stepping = 1,
622 .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
623 CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
624 CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
625 CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
626 CPUID_DE | CPUID_FP87,
627 .ext_features = CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES |
628 CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_POPCNT |
629 CPUID_EXT_X2APIC | CPUID_EXT_SSE42 | CPUID_EXT_SSE41 |
630 CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | CPUID_EXT_PCLMULQDQ |
631 CPUID_EXT_SSE3,
632 .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX |
633 CPUID_EXT2_SYSCALL,
634 .ext3_features = CPUID_EXT3_LAHF_LM,
635 .xlevel = 0x8000000A,
636 .model_id = "Intel Xeon E312xx (Sandy Bridge)",
637 },
638 {
639 .name = "Opteron_G1",
640 .level = 5,
641 .vendor1 = CPUID_VENDOR_AMD_1,
642 .vendor2 = CPUID_VENDOR_AMD_2,
643 .vendor3 = CPUID_VENDOR_AMD_3,
644 .family = 15,
645 .model = 6,
646 .stepping = 1,
647 .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
648 CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
649 CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
650 CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
651 CPUID_DE | CPUID_FP87,
652 .ext_features = CPUID_EXT_SSE3,
653 .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_FXSR | CPUID_EXT2_MMX |
654 CPUID_EXT2_NX | CPUID_EXT2_PSE36 | CPUID_EXT2_PAT |
655 CPUID_EXT2_CMOV | CPUID_EXT2_MCA | CPUID_EXT2_PGE |
656 CPUID_EXT2_MTRR | CPUID_EXT2_SYSCALL | CPUID_EXT2_APIC |
657 CPUID_EXT2_CX8 | CPUID_EXT2_MCE | CPUID_EXT2_PAE | CPUID_EXT2_MSR |
658 CPUID_EXT2_TSC | CPUID_EXT2_PSE | CPUID_EXT2_DE | CPUID_EXT2_FPU,
659 .xlevel = 0x80000008,
660 .model_id = "AMD Opteron 240 (Gen 1 Class Opteron)",
661 },
662 {
663 .name = "Opteron_G2",
664 .level = 5,
665 .vendor1 = CPUID_VENDOR_AMD_1,
666 .vendor2 = CPUID_VENDOR_AMD_2,
667 .vendor3 = CPUID_VENDOR_AMD_3,
668 .family = 15,
669 .model = 6,
670 .stepping = 1,
671 .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
672 CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
673 CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
674 CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
675 CPUID_DE | CPUID_FP87,
676 .ext_features = CPUID_EXT_CX16 | CPUID_EXT_SSE3,
677 .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_FXSR |
678 CPUID_EXT2_MMX | CPUID_EXT2_NX | CPUID_EXT2_PSE36 |
679 CPUID_EXT2_PAT | CPUID_EXT2_CMOV | CPUID_EXT2_MCA |
680 CPUID_EXT2_PGE | CPUID_EXT2_MTRR | CPUID_EXT2_SYSCALL |
681 CPUID_EXT2_APIC | CPUID_EXT2_CX8 | CPUID_EXT2_MCE |
682 CPUID_EXT2_PAE | CPUID_EXT2_MSR | CPUID_EXT2_TSC | CPUID_EXT2_PSE |
683 CPUID_EXT2_DE | CPUID_EXT2_FPU,
684 .ext3_features = CPUID_EXT3_SVM | CPUID_EXT3_LAHF_LM,
685 .xlevel = 0x80000008,
686 .model_id = "AMD Opteron 22xx (Gen 2 Class Opteron)",
687 },
688 {
689 .name = "Opteron_G3",
690 .level = 5,
691 .vendor1 = CPUID_VENDOR_AMD_1,
692 .vendor2 = CPUID_VENDOR_AMD_2,
693 .vendor3 = CPUID_VENDOR_AMD_3,
694 .family = 15,
695 .model = 6,
696 .stepping = 1,
697 .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
698 CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
699 CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
700 CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
701 CPUID_DE | CPUID_FP87,
702 .ext_features = CPUID_EXT_POPCNT | CPUID_EXT_CX16 | CPUID_EXT_MONITOR |
703 CPUID_EXT_SSE3,
704 .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_FXSR |
705 CPUID_EXT2_MMX | CPUID_EXT2_NX | CPUID_EXT2_PSE36 |
706 CPUID_EXT2_PAT | CPUID_EXT2_CMOV | CPUID_EXT2_MCA |
707 CPUID_EXT2_PGE | CPUID_EXT2_MTRR | CPUID_EXT2_SYSCALL |
708 CPUID_EXT2_APIC | CPUID_EXT2_CX8 | CPUID_EXT2_MCE |
709 CPUID_EXT2_PAE | CPUID_EXT2_MSR | CPUID_EXT2_TSC | CPUID_EXT2_PSE |
710 CPUID_EXT2_DE | CPUID_EXT2_FPU,
711 .ext3_features = CPUID_EXT3_MISALIGNSSE | CPUID_EXT3_SSE4A |
712 CPUID_EXT3_ABM | CPUID_EXT3_SVM | CPUID_EXT3_LAHF_LM,
713 .xlevel = 0x80000008,
714 .model_id = "AMD Opteron 23xx (Gen 3 Class Opteron)",
715 },
716 {
717 .name = "Opteron_G4",
718 .level = 0xd,
719 .vendor1 = CPUID_VENDOR_AMD_1,
720 .vendor2 = CPUID_VENDOR_AMD_2,
721 .vendor3 = CPUID_VENDOR_AMD_3,
722 .family = 21,
723 .model = 1,
724 .stepping = 2,
725 .features = CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
726 CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
727 CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
728 CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
729 CPUID_DE | CPUID_FP87,
730 .ext_features = CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES |
731 CPUID_EXT_POPCNT | CPUID_EXT_SSE42 | CPUID_EXT_SSE41 |
732 CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | CPUID_EXT_PCLMULQDQ |
733 CPUID_EXT_SSE3,
734 .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_RDTSCP |
735 CPUID_EXT2_PDPE1GB | CPUID_EXT2_FXSR | CPUID_EXT2_MMX |
736 CPUID_EXT2_NX | CPUID_EXT2_PSE36 | CPUID_EXT2_PAT |
737 CPUID_EXT2_CMOV | CPUID_EXT2_MCA | CPUID_EXT2_PGE |
738 CPUID_EXT2_MTRR | CPUID_EXT2_SYSCALL | CPUID_EXT2_APIC |
739 CPUID_EXT2_CX8 | CPUID_EXT2_MCE | CPUID_EXT2_PAE | CPUID_EXT2_MSR |
740 CPUID_EXT2_TSC | CPUID_EXT2_PSE | CPUID_EXT2_DE | CPUID_EXT2_FPU,
741 .ext3_features = CPUID_EXT3_FMA4 | CPUID_EXT3_XOP |
742 CPUID_EXT3_3DNOWPREFETCH | CPUID_EXT3_MISALIGNSSE |
743 CPUID_EXT3_SSE4A | CPUID_EXT3_ABM | CPUID_EXT3_SVM |
744 CPUID_EXT3_LAHF_LM,
745 .xlevel = 0x8000001A,
746 .model_id = "AMD Opteron 62xx class CPU",
747 },
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100748};
749
750static int cpu_x86_fill_model_id(char *str)
751{
752 uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
753 int i;
754
755 for (i = 0; i < 3; i++) {
756 host_cpuid(0x80000002 + i, 0, &eax, &ebx, &ecx, &edx);
757 memcpy(str + i * 16 + 0, &eax, 4);
758 memcpy(str + i * 16 + 4, &ebx, 4);
759 memcpy(str + i * 16 + 8, &ecx, 4);
760 memcpy(str + i * 16 + 12, &edx, 4);
761 }
762 return 0;
763}
764
765static int cpu_x86_fill_host(x86_def_t *x86_cpu_def)
766{
767 uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
768
769 x86_cpu_def->name = "host";
770 host_cpuid(0x0, 0, &eax, &ebx, &ecx, &edx);
771 x86_cpu_def->level = eax;
772 x86_cpu_def->vendor1 = ebx;
773 x86_cpu_def->vendor2 = edx;
774 x86_cpu_def->vendor3 = ecx;
775
776 host_cpuid(0x1, 0, &eax, &ebx, &ecx, &edx);
777 x86_cpu_def->family = ((eax >> 8) & 0x0F) + ((eax >> 20) & 0xFF);
778 x86_cpu_def->model = ((eax >> 4) & 0x0F) | ((eax & 0xF0000) >> 12);
779 x86_cpu_def->stepping = eax & 0x0F;
780 x86_cpu_def->ext_features = ecx;
781 x86_cpu_def->features = edx;
782
Eduardo Habkost13526722012-05-21 11:27:02 -0300783 if (kvm_enabled() && x86_cpu_def->level >= 7) {
784 x86_cpu_def->cpuid_7_0_ebx_features = kvm_arch_get_supported_cpuid(kvm_state, 0x7, 0, R_EBX);
785 } else {
786 x86_cpu_def->cpuid_7_0_ebx_features = 0;
787 }
788
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100789 host_cpuid(0x80000000, 0, &eax, &ebx, &ecx, &edx);
790 x86_cpu_def->xlevel = eax;
791
792 host_cpuid(0x80000001, 0, &eax, &ebx, &ecx, &edx);
793 x86_cpu_def->ext2_features = edx;
794 x86_cpu_def->ext3_features = ecx;
795 cpu_x86_fill_model_id(x86_cpu_def->model_id);
796 x86_cpu_def->vendor_override = 0;
797
brillywu@viatech.com.cnb3baa152011-06-01 09:59:52 +0800798 /* Call Centaur's CPUID instruction. */
799 if (x86_cpu_def->vendor1 == CPUID_VENDOR_VIA_1 &&
800 x86_cpu_def->vendor2 == CPUID_VENDOR_VIA_2 &&
801 x86_cpu_def->vendor3 == CPUID_VENDOR_VIA_3) {
802 host_cpuid(0xC0000000, 0, &eax, &ebx, &ecx, &edx);
803 if (eax >= 0xC0000001) {
804 /* Support VIA max extended level */
805 x86_cpu_def->xlevel2 = eax;
806 host_cpuid(0xC0000001, 0, &eax, &ebx, &ecx, &edx);
807 x86_cpu_def->ext4_features = edx;
808 }
809 }
Joerg Roedel296acb62010-09-27 15:16:17 +0200810
811 /*
812 * Every SVM feature requires emulation support in KVM - so we can't just
813 * read the host features here. KVM might even support SVM features not
814 * available on the host hardware. Just set all bits and mask out the
815 * unsupported ones later.
816 */
817 x86_cpu_def->svm_features = -1;
818
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100819 return 0;
820}
821
822static int unavailable_host_feature(struct model_features_t *f, uint32_t mask)
823{
824 int i;
825
826 for (i = 0; i < 32; ++i)
827 if (1 << i & mask) {
828 fprintf(stderr, "warning: host cpuid %04x_%04x lacks requested"
829 " flag '%s' [0x%08x]\n",
830 f->cpuid >> 16, f->cpuid & 0xffff,
831 f->flag_names[i] ? f->flag_names[i] : "[reserved]", mask);
832 break;
833 }
834 return 0;
835}
836
837/* best effort attempt to inform user requested cpu flags aren't making
838 * their way to the guest. Note: ft[].check_feat ideally should be
839 * specified via a guest_def field to suppress report of extraneous flags.
840 */
841static int check_features_against_host(x86_def_t *guest_def)
842{
843 x86_def_t host_def;
844 uint32_t mask;
845 int rv, i;
846 struct model_features_t ft[] = {
847 {&guest_def->features, &host_def.features,
848 ~0, feature_name, 0x00000000},
849 {&guest_def->ext_features, &host_def.ext_features,
850 ~CPUID_EXT_HYPERVISOR, ext_feature_name, 0x00000001},
851 {&guest_def->ext2_features, &host_def.ext2_features,
852 ~PPRO_FEATURES, ext2_feature_name, 0x80000000},
853 {&guest_def->ext3_features, &host_def.ext3_features,
854 ~CPUID_EXT3_SVM, ext3_feature_name, 0x80000001}};
855
856 cpu_x86_fill_host(&host_def);
Blue Swirl66fe09e2010-08-20 21:03:24 +0000857 for (rv = 0, i = 0; i < ARRAY_SIZE(ft); ++i)
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100858 for (mask = 1; mask; mask <<= 1)
859 if (ft[i].check_feat & mask && *ft[i].guest_feat & mask &&
860 !(*ft[i].host_feat & mask)) {
861 unavailable_host_feature(&ft[i], mask);
862 rv = 1;
863 }
864 return rv;
865}
866
Andreas Färber95b85192012-04-17 14:42:22 +0200867static void x86_cpuid_version_get_family(Object *obj, Visitor *v, void *opaque,
868 const char *name, Error **errp)
869{
870 X86CPU *cpu = X86_CPU(obj);
871 CPUX86State *env = &cpu->env;
872 int64_t value;
873
874 value = (env->cpuid_version >> 8) & 0xf;
875 if (value == 0xf) {
876 value += (env->cpuid_version >> 20) & 0xff;
877 }
878 visit_type_int(v, &value, name, errp);
879}
880
Andreas Färber71ad61d2012-04-17 12:10:29 +0200881static void x86_cpuid_version_set_family(Object *obj, Visitor *v, void *opaque,
882 const char *name, Error **errp)
Andreas Färbered5e1ec2012-02-17 17:46:01 +0100883{
Andreas Färber71ad61d2012-04-17 12:10:29 +0200884 X86CPU *cpu = X86_CPU(obj);
885 CPUX86State *env = &cpu->env;
886 const int64_t min = 0;
887 const int64_t max = 0xff + 0xf;
888 int64_t value;
889
890 visit_type_int(v, &value, name, errp);
891 if (error_is_set(errp)) {
892 return;
893 }
894 if (value < min || value > max) {
895 error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE, "",
896 name ? name : "null", value, min, max);
897 return;
898 }
899
Andreas Färbered5e1ec2012-02-17 17:46:01 +0100900 env->cpuid_version &= ~0xff00f00;
Andreas Färber71ad61d2012-04-17 12:10:29 +0200901 if (value > 0x0f) {
902 env->cpuid_version |= 0xf00 | ((value - 0x0f) << 20);
Andreas Färbered5e1ec2012-02-17 17:46:01 +0100903 } else {
Andreas Färber71ad61d2012-04-17 12:10:29 +0200904 env->cpuid_version |= value << 8;
Andreas Färbered5e1ec2012-02-17 17:46:01 +0100905 }
906}
907
Andreas Färber67e30c82012-04-17 14:48:14 +0200908static void x86_cpuid_version_get_model(Object *obj, Visitor *v, void *opaque,
909 const char *name, Error **errp)
910{
911 X86CPU *cpu = X86_CPU(obj);
912 CPUX86State *env = &cpu->env;
913 int64_t value;
914
915 value = (env->cpuid_version >> 4) & 0xf;
916 value |= ((env->cpuid_version >> 16) & 0xf) << 4;
917 visit_type_int(v, &value, name, errp);
918}
919
Andreas Färberc5291a42012-04-17 12:16:39 +0200920static void x86_cpuid_version_set_model(Object *obj, Visitor *v, void *opaque,
921 const char *name, Error **errp)
Andreas Färberb0704cb2012-02-17 17:46:02 +0100922{
Andreas Färberc5291a42012-04-17 12:16:39 +0200923 X86CPU *cpu = X86_CPU(obj);
924 CPUX86State *env = &cpu->env;
925 const int64_t min = 0;
926 const int64_t max = 0xff;
927 int64_t value;
928
929 visit_type_int(v, &value, name, errp);
930 if (error_is_set(errp)) {
931 return;
932 }
933 if (value < min || value > max) {
934 error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE, "",
935 name ? name : "null", value, min, max);
936 return;
937 }
938
Andreas Färberb0704cb2012-02-17 17:46:02 +0100939 env->cpuid_version &= ~0xf00f0;
Andreas Färberc5291a42012-04-17 12:16:39 +0200940 env->cpuid_version |= ((value & 0xf) << 4) | ((value >> 4) << 16);
Andreas Färberb0704cb2012-02-17 17:46:02 +0100941}
942
Andreas Färber35112e42012-04-17 14:50:53 +0200943static void x86_cpuid_version_get_stepping(Object *obj, Visitor *v,
944 void *opaque, const char *name,
945 Error **errp)
946{
947 X86CPU *cpu = X86_CPU(obj);
948 CPUX86State *env = &cpu->env;
949 int64_t value;
950
951 value = env->cpuid_version & 0xf;
952 visit_type_int(v, &value, name, errp);
953}
954
Andreas Färber036e2222012-04-17 14:14:18 +0200955static void x86_cpuid_version_set_stepping(Object *obj, Visitor *v,
956 void *opaque, const char *name,
957 Error **errp)
Andreas Färber38c3dc42012-02-17 17:46:03 +0100958{
Andreas Färber036e2222012-04-17 14:14:18 +0200959 X86CPU *cpu = X86_CPU(obj);
960 CPUX86State *env = &cpu->env;
961 const int64_t min = 0;
962 const int64_t max = 0xf;
963 int64_t value;
964
965 visit_type_int(v, &value, name, errp);
966 if (error_is_set(errp)) {
967 return;
968 }
969 if (value < min || value > max) {
970 error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE, "",
971 name ? name : "null", value, min, max);
972 return;
973 }
974
Andreas Färber38c3dc42012-02-17 17:46:03 +0100975 env->cpuid_version &= ~0xf;
Andreas Färber036e2222012-04-17 14:14:18 +0200976 env->cpuid_version |= value & 0xf;
Andreas Färber38c3dc42012-02-17 17:46:03 +0100977}
978
Andreas Färber8e1898b2012-04-17 18:41:40 +0200979static void x86_cpuid_get_level(Object *obj, Visitor *v, void *opaque,
980 const char *name, Error **errp)
981{
982 X86CPU *cpu = X86_CPU(obj);
Andreas Färber8e1898b2012-04-17 18:41:40 +0200983
Andreas Färberfa029882012-05-01 23:33:13 +0200984 visit_type_uint32(v, &cpu->env.cpuid_level, name, errp);
Andreas Färber8e1898b2012-04-17 18:41:40 +0200985}
986
987static void x86_cpuid_set_level(Object *obj, Visitor *v, void *opaque,
988 const char *name, Error **errp)
989{
990 X86CPU *cpu = X86_CPU(obj);
Andreas Färber8e1898b2012-04-17 18:41:40 +0200991
Andreas Färberfa029882012-05-01 23:33:13 +0200992 visit_type_uint32(v, &cpu->env.cpuid_level, name, errp);
Andreas Färber8e1898b2012-04-17 18:41:40 +0200993}
994
Andreas Färber16b93aa2012-04-17 18:44:07 +0200995static void x86_cpuid_get_xlevel(Object *obj, Visitor *v, void *opaque,
996 const char *name, Error **errp)
997{
998 X86CPU *cpu = X86_CPU(obj);
Andreas Färber16b93aa2012-04-17 18:44:07 +0200999
Andreas Färberfa029882012-05-01 23:33:13 +02001000 visit_type_uint32(v, &cpu->env.cpuid_xlevel, name, errp);
Andreas Färber16b93aa2012-04-17 18:44:07 +02001001}
1002
1003static void x86_cpuid_set_xlevel(Object *obj, Visitor *v, void *opaque,
1004 const char *name, Error **errp)
1005{
1006 X86CPU *cpu = X86_CPU(obj);
Andreas Färber16b93aa2012-04-17 18:44:07 +02001007
Andreas Färberfa029882012-05-01 23:33:13 +02001008 visit_type_uint32(v, &cpu->env.cpuid_xlevel, name, errp);
Andreas Färber16b93aa2012-04-17 18:44:07 +02001009}
1010
Andreas Färberd480e1a2012-04-17 19:22:58 +02001011static char *x86_cpuid_get_vendor(Object *obj, Error **errp)
1012{
1013 X86CPU *cpu = X86_CPU(obj);
1014 CPUX86State *env = &cpu->env;
1015 char *value;
1016 int i;
1017
1018 value = (char *)g_malloc(12 + 1);
1019 for (i = 0; i < 4; i++) {
1020 value[i ] = env->cpuid_vendor1 >> (8 * i);
1021 value[i + 4] = env->cpuid_vendor2 >> (8 * i);
1022 value[i + 8] = env->cpuid_vendor3 >> (8 * i);
1023 }
1024 value[12] = '\0';
1025 return value;
1026}
1027
1028static void x86_cpuid_set_vendor(Object *obj, const char *value,
1029 Error **errp)
1030{
1031 X86CPU *cpu = X86_CPU(obj);
1032 CPUX86State *env = &cpu->env;
1033 int i;
1034
1035 if (strlen(value) != 12) {
1036 error_set(errp, QERR_PROPERTY_VALUE_BAD, "",
1037 "vendor", value);
1038 return;
1039 }
1040
1041 env->cpuid_vendor1 = 0;
1042 env->cpuid_vendor2 = 0;
1043 env->cpuid_vendor3 = 0;
1044 for (i = 0; i < 4; i++) {
1045 env->cpuid_vendor1 |= ((uint8_t)value[i ]) << (8 * i);
1046 env->cpuid_vendor2 |= ((uint8_t)value[i + 4]) << (8 * i);
1047 env->cpuid_vendor3 |= ((uint8_t)value[i + 8]) << (8 * i);
1048 }
1049 env->cpuid_vendor_override = 1;
1050}
1051
Andreas Färber63e886e2012-04-17 23:02:26 +02001052static char *x86_cpuid_get_model_id(Object *obj, Error **errp)
1053{
1054 X86CPU *cpu = X86_CPU(obj);
1055 CPUX86State *env = &cpu->env;
1056 char *value;
1057 int i;
1058
1059 value = g_malloc(48 + 1);
1060 for (i = 0; i < 48; i++) {
1061 value[i] = env->cpuid_model[i >> 2] >> (8 * (i & 3));
1062 }
1063 value[48] = '\0';
1064 return value;
1065}
1066
Andreas Färber938d4c22012-04-17 15:17:27 +02001067static void x86_cpuid_set_model_id(Object *obj, const char *model_id,
1068 Error **errp)
Andreas Färberdcce6672012-02-17 17:46:04 +01001069{
Andreas Färber938d4c22012-04-17 15:17:27 +02001070 X86CPU *cpu = X86_CPU(obj);
1071 CPUX86State *env = &cpu->env;
Andreas Färberdcce6672012-02-17 17:46:04 +01001072 int c, len, i;
1073
1074 if (model_id == NULL) {
1075 model_id = "";
1076 }
1077 len = strlen(model_id);
Andreas Färberd0a6acf2012-04-17 18:21:52 +02001078 memset(env->cpuid_model, 0, 48);
Andreas Färberdcce6672012-02-17 17:46:04 +01001079 for (i = 0; i < 48; i++) {
1080 if (i >= len) {
1081 c = '\0';
1082 } else {
1083 c = (uint8_t)model_id[i];
1084 }
1085 env->cpuid_model[i >> 2] |= c << (8 * (i & 3));
1086 }
1087}
1088
Andreas Färber89e48962012-04-18 00:12:23 +02001089static void x86_cpuid_get_tsc_freq(Object *obj, Visitor *v, void *opaque,
1090 const char *name, Error **errp)
1091{
1092 X86CPU *cpu = X86_CPU(obj);
1093 int64_t value;
1094
1095 value = cpu->env.tsc_khz * 1000;
1096 visit_type_int(v, &value, name, errp);
1097}
1098
1099static void x86_cpuid_set_tsc_freq(Object *obj, Visitor *v, void *opaque,
1100 const char *name, Error **errp)
1101{
1102 X86CPU *cpu = X86_CPU(obj);
1103 const int64_t min = 0;
Don Slutz2e848492012-09-21 20:13:13 -04001104 const int64_t max = INT64_MAX;
Andreas Färber89e48962012-04-18 00:12:23 +02001105 int64_t value;
1106
1107 visit_type_int(v, &value, name, errp);
1108 if (error_is_set(errp)) {
1109 return;
1110 }
1111 if (value < min || value > max) {
1112 error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE, "",
1113 name ? name : "null", value, min, max);
1114 return;
1115 }
1116
1117 cpu->env.tsc_khz = value / 1000;
1118}
1119
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001120static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
1121{
1122 unsigned int i;
1123 x86_def_t *def;
1124
Markus Armbrusterd3c481b2011-11-08 15:36:48 +01001125 char *s = g_strdup(cpu_model);
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001126 char *featurestr, *name = strtok(s, ",");
Joerg Roedel296acb62010-09-27 15:16:17 +02001127 /* Features to be added*/
1128 uint32_t plus_features = 0, plus_ext_features = 0;
1129 uint32_t plus_ext2_features = 0, plus_ext3_features = 0;
Michael S. Tsirkindc599442012-10-18 00:15:48 +02001130 uint32_t plus_kvm_features = kvm_default_features, plus_svm_features = 0;
H. Peter Anvina9321a42012-09-26 13:18:43 -07001131 uint32_t plus_7_0_ebx_features = 0;
Joerg Roedel296acb62010-09-27 15:16:17 +02001132 /* Features to be removed */
1133 uint32_t minus_features = 0, minus_ext_features = 0;
1134 uint32_t minus_ext2_features = 0, minus_ext3_features = 0;
1135 uint32_t minus_kvm_features = 0, minus_svm_features = 0;
H. Peter Anvina9321a42012-09-26 13:18:43 -07001136 uint32_t minus_7_0_ebx_features = 0;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001137 uint32_t numvalue;
1138
1139 for (def = x86_defs; def; def = def->next)
Markus Armbruster04c5b172011-11-08 15:36:50 +01001140 if (name && !strcmp(name, def->name))
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001141 break;
Markus Armbruster04c5b172011-11-08 15:36:50 +01001142 if (kvm_enabled() && name && strcmp(name, "host") == 0) {
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001143 cpu_x86_fill_host(x86_cpu_def);
1144 } else if (!def) {
1145 goto error;
1146 } else {
1147 memcpy(x86_cpu_def, def, sizeof(*def));
1148 }
1149
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001150 add_flagname_to_bitmaps("hypervisor", &plus_features,
H. Peter Anvina9321a42012-09-26 13:18:43 -07001151 &plus_ext_features, &plus_ext2_features, &plus_ext3_features,
1152 &plus_kvm_features, &plus_svm_features, &plus_7_0_ebx_features);
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001153
1154 featurestr = strtok(NULL, ",");
1155
1156 while (featurestr) {
1157 char *val;
1158 if (featurestr[0] == '+') {
Joerg Roedel296acb62010-09-27 15:16:17 +02001159 add_flagname_to_bitmaps(featurestr + 1, &plus_features,
1160 &plus_ext_features, &plus_ext2_features,
1161 &plus_ext3_features, &plus_kvm_features,
H. Peter Anvina9321a42012-09-26 13:18:43 -07001162 &plus_svm_features, &plus_7_0_ebx_features);
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001163 } else if (featurestr[0] == '-') {
Joerg Roedel296acb62010-09-27 15:16:17 +02001164 add_flagname_to_bitmaps(featurestr + 1, &minus_features,
1165 &minus_ext_features, &minus_ext2_features,
1166 &minus_ext3_features, &minus_kvm_features,
H. Peter Anvina9321a42012-09-26 13:18:43 -07001167 &minus_svm_features, &minus_7_0_ebx_features);
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001168 } else if ((val = strchr(featurestr, '='))) {
1169 *val = 0; val++;
1170 if (!strcmp(featurestr, "family")) {
1171 char *err;
1172 numvalue = strtoul(val, &err, 0);
Andreas Färbera88a6772012-04-17 16:15:15 +02001173 if (!*val || *err || numvalue > 0xff + 0xf) {
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001174 fprintf(stderr, "bad numerical value %s\n", val);
1175 goto error;
1176 }
1177 x86_cpu_def->family = numvalue;
1178 } else if (!strcmp(featurestr, "model")) {
1179 char *err;
1180 numvalue = strtoul(val, &err, 0);
1181 if (!*val || *err || numvalue > 0xff) {
1182 fprintf(stderr, "bad numerical value %s\n", val);
1183 goto error;
1184 }
1185 x86_cpu_def->model = numvalue;
1186 } else if (!strcmp(featurestr, "stepping")) {
1187 char *err;
1188 numvalue = strtoul(val, &err, 0);
1189 if (!*val || *err || numvalue > 0xf) {
1190 fprintf(stderr, "bad numerical value %s\n", val);
1191 goto error;
1192 }
1193 x86_cpu_def->stepping = numvalue ;
1194 } else if (!strcmp(featurestr, "level")) {
1195 char *err;
1196 numvalue = strtoul(val, &err, 0);
1197 if (!*val || *err) {
1198 fprintf(stderr, "bad numerical value %s\n", val);
1199 goto error;
1200 }
1201 x86_cpu_def->level = numvalue;
1202 } else if (!strcmp(featurestr, "xlevel")) {
1203 char *err;
1204 numvalue = strtoul(val, &err, 0);
1205 if (!*val || *err) {
1206 fprintf(stderr, "bad numerical value %s\n", val);
1207 goto error;
1208 }
1209 if (numvalue < 0x80000000) {
Aurelien Jarno2f7a21c2010-03-13 16:46:33 +01001210 numvalue += 0x80000000;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001211 }
1212 x86_cpu_def->xlevel = numvalue;
1213 } else if (!strcmp(featurestr, "vendor")) {
1214 if (strlen(val) != 12) {
1215 fprintf(stderr, "vendor string must be 12 chars long\n");
1216 goto error;
1217 }
1218 x86_cpu_def->vendor1 = 0;
1219 x86_cpu_def->vendor2 = 0;
1220 x86_cpu_def->vendor3 = 0;
1221 for(i = 0; i < 4; i++) {
1222 x86_cpu_def->vendor1 |= ((uint8_t)val[i ]) << (8 * i);
1223 x86_cpu_def->vendor2 |= ((uint8_t)val[i + 4]) << (8 * i);
1224 x86_cpu_def->vendor3 |= ((uint8_t)val[i + 8]) << (8 * i);
1225 }
1226 x86_cpu_def->vendor_override = 1;
1227 } else if (!strcmp(featurestr, "model_id")) {
1228 pstrcpy(x86_cpu_def->model_id, sizeof(x86_cpu_def->model_id),
1229 val);
Joerg Roedelb862d1f2011-07-07 16:13:12 +02001230 } else if (!strcmp(featurestr, "tsc_freq")) {
1231 int64_t tsc_freq;
1232 char *err;
1233
1234 tsc_freq = strtosz_suffix_unit(val, &err,
1235 STRTOSZ_DEFSUFFIX_B, 1000);
Markus Armbruster45009a32011-11-22 09:46:04 +01001236 if (tsc_freq < 0 || *err) {
Joerg Roedelb862d1f2011-07-07 16:13:12 +02001237 fprintf(stderr, "bad numerical value %s\n", val);
1238 goto error;
1239 }
1240 x86_cpu_def->tsc_khz = tsc_freq / 1000;
Vadim Rozenfeld28f52cc2011-12-18 22:48:13 +02001241 } else if (!strcmp(featurestr, "hv_spinlocks")) {
1242 char *err;
1243 numvalue = strtoul(val, &err, 0);
1244 if (!*val || *err) {
1245 fprintf(stderr, "bad numerical value %s\n", val);
1246 goto error;
1247 }
1248 hyperv_set_spinlock_retries(numvalue);
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001249 } else {
1250 fprintf(stderr, "unrecognized feature %s\n", featurestr);
1251 goto error;
1252 }
1253 } else if (!strcmp(featurestr, "check")) {
1254 check_cpuid = 1;
1255 } else if (!strcmp(featurestr, "enforce")) {
1256 check_cpuid = enforce_cpuid = 1;
Vadim Rozenfeld28f52cc2011-12-18 22:48:13 +02001257 } else if (!strcmp(featurestr, "hv_relaxed")) {
1258 hyperv_enable_relaxed_timing(true);
1259 } else if (!strcmp(featurestr, "hv_vapic")) {
1260 hyperv_enable_vapic_recommended(true);
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001261 } else {
1262 fprintf(stderr, "feature string `%s' not in format (+feature|-feature|feature=xyz)\n", featurestr);
1263 goto error;
1264 }
1265 featurestr = strtok(NULL, ",");
1266 }
1267 x86_cpu_def->features |= plus_features;
1268 x86_cpu_def->ext_features |= plus_ext_features;
1269 x86_cpu_def->ext2_features |= plus_ext2_features;
1270 x86_cpu_def->ext3_features |= plus_ext3_features;
1271 x86_cpu_def->kvm_features |= plus_kvm_features;
Joerg Roedel296acb62010-09-27 15:16:17 +02001272 x86_cpu_def->svm_features |= plus_svm_features;
H. Peter Anvina9321a42012-09-26 13:18:43 -07001273 x86_cpu_def->cpuid_7_0_ebx_features |= plus_7_0_ebx_features;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001274 x86_cpu_def->features &= ~minus_features;
1275 x86_cpu_def->ext_features &= ~minus_ext_features;
1276 x86_cpu_def->ext2_features &= ~minus_ext2_features;
1277 x86_cpu_def->ext3_features &= ~minus_ext3_features;
1278 x86_cpu_def->kvm_features &= ~minus_kvm_features;
Joerg Roedel296acb62010-09-27 15:16:17 +02001279 x86_cpu_def->svm_features &= ~minus_svm_features;
H. Peter Anvina9321a42012-09-26 13:18:43 -07001280 x86_cpu_def->cpuid_7_0_ebx_features &= ~minus_7_0_ebx_features;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001281 if (check_cpuid) {
1282 if (check_features_against_host(x86_cpu_def) && enforce_cpuid)
1283 goto error;
1284 }
H. Peter Anvina9321a42012-09-26 13:18:43 -07001285 if (x86_cpu_def->cpuid_7_0_ebx_features && x86_cpu_def->level < 7) {
1286 x86_cpu_def->level = 7;
1287 }
Markus Armbrusterd3c481b2011-11-08 15:36:48 +01001288 g_free(s);
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001289 return 0;
1290
1291error:
Markus Armbrusterd3c481b2011-11-08 15:36:48 +01001292 g_free(s);
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001293 return -1;
1294}
1295
1296/* generate a composite string into buf of all cpuid names in featureset
1297 * selected by fbits. indicate truncation at bufsize in the event of overflow.
1298 * if flags, suppress names undefined in featureset.
1299 */
1300static void listflags(char *buf, int bufsize, uint32_t fbits,
1301 const char **featureset, uint32_t flags)
1302{
1303 const char **p = &featureset[31];
1304 char *q, *b, bit;
1305 int nc;
1306
1307 b = 4 <= bufsize ? buf + (bufsize -= 3) - 1 : NULL;
1308 *buf = '\0';
1309 for (q = buf, bit = 31; fbits && bufsize; --p, fbits &= ~(1 << bit), --bit)
1310 if (fbits & 1 << bit && (*p || !flags)) {
1311 if (*p)
1312 nc = snprintf(q, bufsize, "%s%s", q == buf ? "" : " ", *p);
1313 else
1314 nc = snprintf(q, bufsize, "%s[%d]", q == buf ? "" : " ", bit);
1315 if (bufsize <= nc) {
1316 if (b) {
1317 memcpy(b, "...", sizeof("..."));
1318 }
1319 return;
1320 }
1321 q += nc;
1322 bufsize -= nc;
1323 }
1324}
1325
Peter Maydelle916cbf2012-09-05 17:41:08 -03001326/* generate CPU information. */
1327void x86_cpu_list(FILE *f, fprintf_function cpu_fprintf)
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001328{
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001329 x86_def_t *def;
1330 char buf[256];
1331
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001332 for (def = x86_defs; def; def = def->next) {
Eduardo Habkostc04321b2012-09-05 17:41:13 -03001333 snprintf(buf, sizeof(buf), "%s", def->name);
Peter Maydell6cdf8852012-09-05 17:41:07 -03001334 (*cpu_fprintf)(f, "x86 %16s %-48s\n", buf, def->model_id);
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001335 }
Andre Przywaraed2c54d2010-03-11 14:39:00 +01001336 if (kvm_enabled()) {
1337 (*cpu_fprintf)(f, "x86 %16s\n", "[host]");
1338 }
Peter Maydell6cdf8852012-09-05 17:41:07 -03001339 (*cpu_fprintf)(f, "\nRecognized CPUID flags:\n");
1340 listflags(buf, sizeof(buf), (uint32_t)~0, feature_name, 1);
Eduardo Habkost4a19e502012-09-06 10:05:39 +00001341 (*cpu_fprintf)(f, " %s\n", buf);
Peter Maydell6cdf8852012-09-05 17:41:07 -03001342 listflags(buf, sizeof(buf), (uint32_t)~0, ext_feature_name, 1);
Eduardo Habkost4a19e502012-09-06 10:05:39 +00001343 (*cpu_fprintf)(f, " %s\n", buf);
Peter Maydell6cdf8852012-09-05 17:41:07 -03001344 listflags(buf, sizeof(buf), (uint32_t)~0, ext2_feature_name, 1);
Eduardo Habkost4a19e502012-09-06 10:05:39 +00001345 (*cpu_fprintf)(f, " %s\n", buf);
Peter Maydell6cdf8852012-09-05 17:41:07 -03001346 listflags(buf, sizeof(buf), (uint32_t)~0, ext3_feature_name, 1);
Eduardo Habkost4a19e502012-09-06 10:05:39 +00001347 (*cpu_fprintf)(f, " %s\n", buf);
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001348}
1349
Anthony Liguori76b64a72012-08-14 22:17:36 -05001350CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp)
Anthony Liguorie3966122012-08-10 11:04:14 -05001351{
1352 CpuDefinitionInfoList *cpu_list = NULL;
1353 x86_def_t *def;
1354
1355 for (def = x86_defs; def; def = def->next) {
1356 CpuDefinitionInfoList *entry;
1357 CpuDefinitionInfo *info;
1358
1359 info = g_malloc0(sizeof(*info));
1360 info->name = g_strdup(def->name);
1361
1362 entry = g_malloc0(sizeof(*entry));
1363 entry->value = info;
1364 entry->next = cpu_list;
1365 cpu_list = entry;
1366 }
1367
1368 return cpu_list;
1369}
1370
Eduardo Habkostbc74b7d2012-10-04 17:49:05 -03001371#ifdef CONFIG_KVM
1372static void filter_features_for_kvm(X86CPU *cpu)
1373{
1374 CPUX86State *env = &cpu->env;
1375 KVMState *s = kvm_state;
1376
1377 env->cpuid_features &= kvm_arch_get_supported_cpuid(s, 1, 0, R_EDX);
1378
1379 env->cpuid_ext_features &= kvm_arch_get_supported_cpuid(s, 1, 0, R_ECX);
1380
1381 env->cpuid_ext2_features &= kvm_arch_get_supported_cpuid(s, 0x80000001,
1382 0, R_EDX);
1383 env->cpuid_ext3_features &= kvm_arch_get_supported_cpuid(s, 0x80000001,
1384 0, R_ECX);
1385 env->cpuid_svm_features &= kvm_arch_get_supported_cpuid(s, 0x8000000A,
1386 0, R_EDX);
1387
1388 env->cpuid_kvm_features &=
1389 kvm_arch_get_supported_cpuid(s, KVM_CPUID_FEATURES, 0, R_EAX);
1390
1391 env->cpuid_ext4_features &= kvm_arch_get_supported_cpuid(s, 0xC0000001,
1392 0, R_EDX);
1393
1394}
1395#endif
1396
Andreas Färber61dcd772012-04-17 12:00:51 +02001397int cpu_x86_register(X86CPU *cpu, const char *cpu_model)
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001398{
Andreas Färber61dcd772012-04-17 12:00:51 +02001399 CPUX86State *env = &cpu->env;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001400 x86_def_t def1, *def = &def1;
Andreas Färber71ad61d2012-04-17 12:10:29 +02001401 Error *error = NULL;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001402
Joerg Roedeldb0ad1b2010-09-27 15:16:16 +02001403 memset(def, 0, sizeof(*def));
1404
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001405 if (cpu_x86_find_by_name(def, cpu_model) < 0)
1406 return -1;
1407 if (def->vendor1) {
1408 env->cpuid_vendor1 = def->vendor1;
1409 env->cpuid_vendor2 = def->vendor2;
1410 env->cpuid_vendor3 = def->vendor3;
1411 } else {
1412 env->cpuid_vendor1 = CPUID_VENDOR_INTEL_1;
1413 env->cpuid_vendor2 = CPUID_VENDOR_INTEL_2;
1414 env->cpuid_vendor3 = CPUID_VENDOR_INTEL_3;
1415 }
1416 env->cpuid_vendor_override = def->vendor_override;
Andreas Färber8e1898b2012-04-17 18:41:40 +02001417 object_property_set_int(OBJECT(cpu), def->level, "level", &error);
Andreas Färber71ad61d2012-04-17 12:10:29 +02001418 object_property_set_int(OBJECT(cpu), def->family, "family", &error);
Andreas Färberc5291a42012-04-17 12:16:39 +02001419 object_property_set_int(OBJECT(cpu), def->model, "model", &error);
Andreas Färber036e2222012-04-17 14:14:18 +02001420 object_property_set_int(OBJECT(cpu), def->stepping, "stepping", &error);
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001421 env->cpuid_features = def->features;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001422 env->cpuid_ext_features = def->ext_features;
1423 env->cpuid_ext2_features = def->ext2_features;
Andre Przywara4d067ed2010-03-11 14:38:57 +01001424 env->cpuid_ext3_features = def->ext3_features;
Andreas Färber16b93aa2012-04-17 18:44:07 +02001425 object_property_set_int(OBJECT(cpu), def->xlevel, "xlevel", &error);
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001426 env->cpuid_kvm_features = def->kvm_features;
Joerg Roedel296acb62010-09-27 15:16:17 +02001427 env->cpuid_svm_features = def->svm_features;
brillywu@viatech.com.cnb3baa152011-06-01 09:59:52 +08001428 env->cpuid_ext4_features = def->ext4_features;
H. Peter Anvina9321a42012-09-26 13:18:43 -07001429 env->cpuid_7_0_ebx_features = def->cpuid_7_0_ebx_features;
brillywu@viatech.com.cnb3baa152011-06-01 09:59:52 +08001430 env->cpuid_xlevel2 = def->xlevel2;
Andreas Färber89e48962012-04-18 00:12:23 +02001431 object_property_set_int(OBJECT(cpu), (int64_t)def->tsc_khz * 1000,
1432 "tsc-frequency", &error);
Eduardo Habkost3b671a42012-09-06 10:05:38 +00001433
1434 /* On AMD CPUs, some CPUID[8000_0001].EDX bits must match the bits on
1435 * CPUID[1].EDX.
1436 */
1437 if (env->cpuid_vendor1 == CPUID_VENDOR_AMD_1 &&
1438 env->cpuid_vendor2 == CPUID_VENDOR_AMD_2 &&
1439 env->cpuid_vendor3 == CPUID_VENDOR_AMD_3) {
1440 env->cpuid_ext2_features &= ~CPUID_EXT2_AMD_ALIASES;
1441 env->cpuid_ext2_features |= (def->features & CPUID_EXT2_AMD_ALIASES);
1442 }
1443
Andre Przywara551a2de2010-03-11 14:39:03 +01001444 if (!kvm_enabled()) {
1445 env->cpuid_features &= TCG_FEATURES;
1446 env->cpuid_ext_features &= TCG_EXT_FEATURES;
1447 env->cpuid_ext2_features &= (TCG_EXT2_FEATURES
1448#ifdef TARGET_X86_64
1449 | CPUID_EXT2_SYSCALL | CPUID_EXT2_LM
1450#endif
1451 );
1452 env->cpuid_ext3_features &= TCG_EXT3_FEATURES;
Joerg Roedel296acb62010-09-27 15:16:17 +02001453 env->cpuid_svm_features &= TCG_SVM_FEATURES;
Eduardo Habkostbc74b7d2012-10-04 17:49:05 -03001454 } else {
1455#ifdef CONFIG_KVM
1456 filter_features_for_kvm(cpu);
1457#endif
Andre Przywara551a2de2010-03-11 14:39:03 +01001458 }
Andreas Färber938d4c22012-04-17 15:17:27 +02001459 object_property_set_str(OBJECT(cpu), def->model_id, "model-id", &error);
Andreas Färber71ad61d2012-04-17 12:10:29 +02001460 if (error_is_set(&error)) {
1461 error_free(error);
1462 return -1;
1463 }
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001464 return 0;
1465}
1466
1467#if !defined(CONFIG_USER_ONLY)
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001468
Blue Swirl0e26b7b2010-06-19 10:42:34 +03001469void cpu_clear_apic_feature(CPUX86State *env)
1470{
1471 env->cpuid_features &= ~CPUID_APIC;
1472}
1473
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001474#endif /* !CONFIG_USER_ONLY */
1475
Eduardo Habkostc04321b2012-09-05 17:41:13 -03001476/* Initialize list of CPU models, filling some non-static fields if necessary
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001477 */
1478void x86_cpudef_setup(void)
1479{
Crístian Viana93bfef42012-05-30 00:35:51 -03001480 int i, j;
1481 static const char *model_with_versions[] = { "qemu32", "qemu64", "athlon" };
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001482
1483 for (i = 0; i < ARRAY_SIZE(builtin_x86_defs); ++i) {
Eduardo Habkostbc3e1292012-09-05 17:41:12 -03001484 x86_def_t *def = &builtin_x86_defs[i];
1485 def->next = x86_defs;
Crístian Viana93bfef42012-05-30 00:35:51 -03001486
1487 /* Look for specific "cpudef" models that */
Stefan Weil09faecf2012-06-20 06:05:51 +02001488 /* have the QEMU version in .model_id */
Crístian Viana93bfef42012-05-30 00:35:51 -03001489 for (j = 0; j < ARRAY_SIZE(model_with_versions); j++) {
Eduardo Habkostbc3e1292012-09-05 17:41:12 -03001490 if (strcmp(model_with_versions[j], def->name) == 0) {
1491 pstrcpy(def->model_id, sizeof(def->model_id),
1492 "QEMU Virtual CPU version ");
1493 pstrcat(def->model_id, sizeof(def->model_id),
1494 qemu_get_version());
Crístian Viana93bfef42012-05-30 00:35:51 -03001495 break;
1496 }
1497 }
1498
Eduardo Habkostbc3e1292012-09-05 17:41:12 -03001499 x86_defs = def;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001500 }
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001501}
1502
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001503static void get_cpuid_vendor(CPUX86State *env, uint32_t *ebx,
1504 uint32_t *ecx, uint32_t *edx)
1505{
1506 *ebx = env->cpuid_vendor1;
1507 *edx = env->cpuid_vendor2;
1508 *ecx = env->cpuid_vendor3;
1509
1510 /* sysenter isn't supported on compatibility mode on AMD, syscall
1511 * isn't supported in compatibility mode on Intel.
1512 * Normally we advertise the actual cpu vendor, but you can override
1513 * this if you want to use KVM's sysenter/syscall emulation
1514 * in compatibility mode and when doing cross vendor migration
1515 */
Andre Przywara89354992010-06-02 11:57:47 +02001516 if (kvm_enabled() && ! env->cpuid_vendor_override) {
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001517 host_cpuid(0, 0, NULL, ebx, ecx, edx);
1518 }
1519}
1520
1521void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
1522 uint32_t *eax, uint32_t *ebx,
1523 uint32_t *ecx, uint32_t *edx)
1524{
1525 /* test if maximum index reached */
1526 if (index & 0x80000000) {
brillywu@viatech.com.cnb3baa152011-06-01 09:59:52 +08001527 if (index > env->cpuid_xlevel) {
1528 if (env->cpuid_xlevel2 > 0) {
1529 /* Handle the Centaur's CPUID instruction. */
1530 if (index > env->cpuid_xlevel2) {
1531 index = env->cpuid_xlevel2;
1532 } else if (index < 0xC0000000) {
1533 index = env->cpuid_xlevel;
1534 }
1535 } else {
1536 index = env->cpuid_xlevel;
1537 }
1538 }
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001539 } else {
1540 if (index > env->cpuid_level)
1541 index = env->cpuid_level;
1542 }
1543
1544 switch(index) {
1545 case 0:
1546 *eax = env->cpuid_level;
1547 get_cpuid_vendor(env, ebx, ecx, edx);
1548 break;
1549 case 1:
1550 *eax = env->cpuid_version;
1551 *ebx = (env->cpuid_apic_id << 24) | 8 << 8; /* CLFLUSH size in quad words, Linux wants it. */
1552 *ecx = env->cpuid_ext_features;
1553 *edx = env->cpuid_features;
1554 if (env->nr_cores * env->nr_threads > 1) {
1555 *ebx |= (env->nr_cores * env->nr_threads) << 16;
1556 *edx |= 1 << 28; /* HTT bit */
1557 }
1558 break;
1559 case 2:
1560 /* cache info: needed for Pentium Pro compatibility */
1561 *eax = 1;
1562 *ebx = 0;
1563 *ecx = 0;
1564 *edx = 0x2c307d;
1565 break;
1566 case 4:
1567 /* cache info: needed for Core compatibility */
1568 if (env->nr_cores > 1) {
Aurelien Jarno2f7a21c2010-03-13 16:46:33 +01001569 *eax = (env->nr_cores - 1) << 26;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001570 } else {
Aurelien Jarno2f7a21c2010-03-13 16:46:33 +01001571 *eax = 0;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001572 }
1573 switch (count) {
1574 case 0: /* L1 dcache info */
1575 *eax |= 0x0000121;
1576 *ebx = 0x1c0003f;
1577 *ecx = 0x000003f;
1578 *edx = 0x0000001;
1579 break;
1580 case 1: /* L1 icache info */
1581 *eax |= 0x0000122;
1582 *ebx = 0x1c0003f;
1583 *ecx = 0x000003f;
1584 *edx = 0x0000001;
1585 break;
1586 case 2: /* L2 cache info */
1587 *eax |= 0x0000143;
1588 if (env->nr_threads > 1) {
1589 *eax |= (env->nr_threads - 1) << 14;
1590 }
1591 *ebx = 0x3c0003f;
1592 *ecx = 0x0000fff;
1593 *edx = 0x0000001;
1594 break;
1595 default: /* end of info */
1596 *eax = 0;
1597 *ebx = 0;
1598 *ecx = 0;
1599 *edx = 0;
1600 break;
1601 }
1602 break;
1603 case 5:
1604 /* mwait info: needed for Core compatibility */
1605 *eax = 0; /* Smallest monitor-line size in bytes */
1606 *ebx = 0; /* Largest monitor-line size in bytes */
1607 *ecx = CPUID_MWAIT_EMX | CPUID_MWAIT_IBE;
1608 *edx = 0;
1609 break;
1610 case 6:
1611 /* Thermal and Power Leaf */
1612 *eax = 0;
1613 *ebx = 0;
1614 *ecx = 0;
1615 *edx = 0;
1616 break;
Yang, Wei Yf7911682011-05-30 23:17:42 +08001617 case 7:
Eduardo Habkost13526722012-05-21 11:27:02 -03001618 /* Structured Extended Feature Flags Enumeration Leaf */
1619 if (count == 0) {
1620 *eax = 0; /* Maximum ECX value for sub-leaves */
H. Peter Anvina9321a42012-09-26 13:18:43 -07001621 *ebx = env->cpuid_7_0_ebx_features; /* Feature flags */
Eduardo Habkost13526722012-05-21 11:27:02 -03001622 *ecx = 0; /* Reserved */
1623 *edx = 0; /* Reserved */
Yang, Wei Yf7911682011-05-30 23:17:42 +08001624 } else {
1625 *eax = 0;
1626 *ebx = 0;
1627 *ecx = 0;
1628 *edx = 0;
1629 }
1630 break;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001631 case 9:
1632 /* Direct Cache Access Information Leaf */
1633 *eax = 0; /* Bits 0-31 in DCA_CAP MSR */
1634 *ebx = 0;
1635 *ecx = 0;
1636 *edx = 0;
1637 break;
1638 case 0xA:
1639 /* Architectural Performance Monitoring Leaf */
Gleb Natapova0fa8202011-12-15 12:44:05 +02001640 if (kvm_enabled()) {
1641 KVMState *s = env->kvm_state;
1642
1643 *eax = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EAX);
1644 *ebx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EBX);
1645 *ecx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_ECX);
1646 *edx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EDX);
1647 } else {
1648 *eax = 0;
1649 *ebx = 0;
1650 *ecx = 0;
1651 *edx = 0;
1652 }
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001653 break;
Sheng Yang51e49432010-06-17 15:18:14 +08001654 case 0xD:
1655 /* Processor Extended State */
1656 if (!(env->cpuid_ext_features & CPUID_EXT_XSAVE)) {
1657 *eax = 0;
1658 *ebx = 0;
1659 *ecx = 0;
1660 *edx = 0;
1661 break;
1662 }
1663 if (kvm_enabled()) {
Jan Kiszkaba9bc592011-06-08 16:11:05 +02001664 KVMState *s = env->kvm_state;
1665
1666 *eax = kvm_arch_get_supported_cpuid(s, 0xd, count, R_EAX);
1667 *ebx = kvm_arch_get_supported_cpuid(s, 0xd, count, R_EBX);
1668 *ecx = kvm_arch_get_supported_cpuid(s, 0xd, count, R_ECX);
1669 *edx = kvm_arch_get_supported_cpuid(s, 0xd, count, R_EDX);
Sheng Yang51e49432010-06-17 15:18:14 +08001670 } else {
1671 *eax = 0;
1672 *ebx = 0;
1673 *ecx = 0;
1674 *edx = 0;
1675 }
1676 break;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001677 case 0x80000000:
1678 *eax = env->cpuid_xlevel;
1679 *ebx = env->cpuid_vendor1;
1680 *edx = env->cpuid_vendor2;
1681 *ecx = env->cpuid_vendor3;
1682 break;
1683 case 0x80000001:
1684 *eax = env->cpuid_version;
1685 *ebx = 0;
1686 *ecx = env->cpuid_ext3_features;
1687 *edx = env->cpuid_ext2_features;
1688
1689 /* The Linux kernel checks for the CMPLegacy bit and
1690 * discards multiple thread information if it is set.
1691 * So dont set it here for Intel to make Linux guests happy.
1692 */
1693 if (env->nr_cores * env->nr_threads > 1) {
1694 uint32_t tebx, tecx, tedx;
1695 get_cpuid_vendor(env, &tebx, &tecx, &tedx);
1696 if (tebx != CPUID_VENDOR_INTEL_1 ||
1697 tedx != CPUID_VENDOR_INTEL_2 ||
1698 tecx != CPUID_VENDOR_INTEL_3) {
1699 *ecx |= 1 << 1; /* CmpLegacy bit */
1700 }
1701 }
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001702 break;
1703 case 0x80000002:
1704 case 0x80000003:
1705 case 0x80000004:
1706 *eax = env->cpuid_model[(index - 0x80000002) * 4 + 0];
1707 *ebx = env->cpuid_model[(index - 0x80000002) * 4 + 1];
1708 *ecx = env->cpuid_model[(index - 0x80000002) * 4 + 2];
1709 *edx = env->cpuid_model[(index - 0x80000002) * 4 + 3];
1710 break;
1711 case 0x80000005:
1712 /* cache info (L1 cache) */
1713 *eax = 0x01ff01ff;
1714 *ebx = 0x01ff01ff;
1715 *ecx = 0x40020140;
1716 *edx = 0x40020140;
1717 break;
1718 case 0x80000006:
1719 /* cache info (L2 cache) */
1720 *eax = 0;
1721 *ebx = 0x42004200;
1722 *ecx = 0x02008140;
1723 *edx = 0;
1724 break;
1725 case 0x80000008:
1726 /* virtual & phys address size in low 2 bytes. */
1727/* XXX: This value must match the one used in the MMU code. */
1728 if (env->cpuid_ext2_features & CPUID_EXT2_LM) {
1729 /* 64 bit processor */
1730/* XXX: The physical address space is limited to 42 bits in exec.c. */
1731 *eax = 0x00003028; /* 48 bits virtual, 40 bits physical */
1732 } else {
1733 if (env->cpuid_features & CPUID_PSE36)
1734 *eax = 0x00000024; /* 36 bits physical */
1735 else
1736 *eax = 0x00000020; /* 32 bits physical */
1737 }
1738 *ebx = 0;
1739 *ecx = 0;
1740 *edx = 0;
1741 if (env->nr_cores * env->nr_threads > 1) {
1742 *ecx |= (env->nr_cores * env->nr_threads) - 1;
1743 }
1744 break;
1745 case 0x8000000A:
Joerg Roedel296acb62010-09-27 15:16:17 +02001746 if (env->cpuid_ext3_features & CPUID_EXT3_SVM) {
1747 *eax = 0x00000001; /* SVM Revision */
1748 *ebx = 0x00000010; /* nr of ASIDs */
1749 *ecx = 0;
1750 *edx = env->cpuid_svm_features; /* optional features */
1751 } else {
1752 *eax = 0;
1753 *ebx = 0;
1754 *ecx = 0;
1755 *edx = 0;
1756 }
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001757 break;
brillywu@viatech.com.cnb3baa152011-06-01 09:59:52 +08001758 case 0xC0000000:
1759 *eax = env->cpuid_xlevel2;
1760 *ebx = 0;
1761 *ecx = 0;
1762 *edx = 0;
1763 break;
1764 case 0xC0000001:
1765 /* Support for VIA CPU's CPUID instruction */
1766 *eax = env->cpuid_version;
1767 *ebx = 0;
1768 *ecx = 0;
1769 *edx = env->cpuid_ext4_features;
1770 break;
1771 case 0xC0000002:
1772 case 0xC0000003:
1773 case 0xC0000004:
1774 /* Reserved for the future, and now filled with zero */
1775 *eax = 0;
1776 *ebx = 0;
1777 *ecx = 0;
1778 *edx = 0;
1779 break;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001780 default:
1781 /* reserved values: zero */
1782 *eax = 0;
1783 *ebx = 0;
1784 *ecx = 0;
1785 *edx = 0;
1786 break;
1787 }
1788}
Andreas Färber5fd20872012-04-02 23:20:08 +02001789
1790/* CPUClass::reset() */
1791static void x86_cpu_reset(CPUState *s)
1792{
1793 X86CPU *cpu = X86_CPU(s);
1794 X86CPUClass *xcc = X86_CPU_GET_CLASS(cpu);
1795 CPUX86State *env = &cpu->env;
Andreas Färberc1958ae2012-04-03 00:16:24 +02001796 int i;
1797
1798 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
1799 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
Peter Maydell6fd2a022012-10-05 15:04:43 +01001800 log_cpu_state(env, CPU_DUMP_FPU | CPU_DUMP_CCOP);
Andreas Färberc1958ae2012-04-03 00:16:24 +02001801 }
Andreas Färber5fd20872012-04-02 23:20:08 +02001802
1803 xcc->parent_reset(s);
1804
Andreas Färberc1958ae2012-04-03 00:16:24 +02001805
1806 memset(env, 0, offsetof(CPUX86State, breakpoints));
1807
1808 tlb_flush(env, 1);
1809
1810 env->old_exception = -1;
1811
1812 /* init to reset state */
1813
1814#ifdef CONFIG_SOFTMMU
1815 env->hflags |= HF_SOFTMMU_MASK;
1816#endif
1817 env->hflags2 |= HF2_GIF_MASK;
1818
1819 cpu_x86_update_cr0(env, 0x60000010);
1820 env->a20_mask = ~0x0;
1821 env->smbase = 0x30000;
1822
1823 env->idt.limit = 0xffff;
1824 env->gdt.limit = 0xffff;
1825 env->ldt.limit = 0xffff;
1826 env->ldt.flags = DESC_P_MASK | (2 << DESC_TYPE_SHIFT);
1827 env->tr.limit = 0xffff;
1828 env->tr.flags = DESC_P_MASK | (11 << DESC_TYPE_SHIFT);
1829
1830 cpu_x86_load_seg_cache(env, R_CS, 0xf000, 0xffff0000, 0xffff,
1831 DESC_P_MASK | DESC_S_MASK | DESC_CS_MASK |
1832 DESC_R_MASK | DESC_A_MASK);
1833 cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0xffff,
1834 DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
1835 DESC_A_MASK);
1836 cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0xffff,
1837 DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
1838 DESC_A_MASK);
1839 cpu_x86_load_seg_cache(env, R_SS, 0, 0, 0xffff,
1840 DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
1841 DESC_A_MASK);
1842 cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0xffff,
1843 DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
1844 DESC_A_MASK);
1845 cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0xffff,
1846 DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
1847 DESC_A_MASK);
1848
1849 env->eip = 0xfff0;
1850 env->regs[R_EDX] = env->cpuid_version;
1851
1852 env->eflags = 0x2;
1853
1854 /* FPU init */
1855 for (i = 0; i < 8; i++) {
1856 env->fptags[i] = 1;
1857 }
1858 env->fpuc = 0x37f;
1859
1860 env->mxcsr = 0x1f80;
1861
1862 env->pat = 0x0007040600070406ULL;
1863 env->msr_ia32_misc_enable = MSR_IA32_MISC_ENABLE_DEFAULT;
1864
1865 memset(env->dr, 0, sizeof(env->dr));
1866 env->dr[6] = DR6_FIXED_1;
1867 env->dr[7] = DR7_FIXED_1;
1868 cpu_breakpoint_remove_all(env, BP_CPU);
1869 cpu_watchpoint_remove_all(env, BP_CPU);
Igor Mammedovdd673282012-07-23 15:22:27 +02001870
1871#if !defined(CONFIG_USER_ONLY)
1872 /* We hard-wire the BSP to the first CPU. */
1873 if (env->cpu_index == 0) {
1874 apic_designate_bsp(env->apic_state);
1875 }
1876
1877 env->halted = !cpu_is_bsp(cpu);
1878#endif
Andreas Färber5fd20872012-04-02 23:20:08 +02001879}
1880
Igor Mammedovdd673282012-07-23 15:22:27 +02001881#ifndef CONFIG_USER_ONLY
1882bool cpu_is_bsp(X86CPU *cpu)
1883{
1884 return cpu_get_apic_base(cpu->env.apic_state) & MSR_IA32_APICBASE_BSP;
1885}
Igor Mammedov65dee382012-07-23 15:22:28 +02001886
1887/* TODO: remove me, when reset over QOM tree is implemented */
1888static void x86_cpu_machine_reset_cb(void *opaque)
1889{
1890 X86CPU *cpu = opaque;
1891 cpu_reset(CPU(cpu));
1892}
Igor Mammedovdd673282012-07-23 15:22:27 +02001893#endif
1894
Andreas Färberde024812012-04-03 00:00:17 +02001895static void mce_init(X86CPU *cpu)
1896{
1897 CPUX86State *cenv = &cpu->env;
1898 unsigned int bank;
1899
1900 if (((cenv->cpuid_version >> 8) & 0xf) >= 6
1901 && (cenv->cpuid_features & (CPUID_MCE | CPUID_MCA)) ==
1902 (CPUID_MCE | CPUID_MCA)) {
1903 cenv->mcg_cap = MCE_CAP_DEF | MCE_BANKS_DEF;
1904 cenv->mcg_ctl = ~(uint64_t)0;
1905 for (bank = 0; bank < MCE_BANKS_DEF; bank++) {
1906 cenv->mce_banks[bank * 4] = ~(uint64_t)0;
1907 }
1908 }
1909}
1910
Andreas Färber7a059952012-05-09 23:15:32 +02001911void x86_cpu_realize(Object *obj, Error **errp)
1912{
1913 X86CPU *cpu = X86_CPU(obj);
1914
Igor Mammedov65dee382012-07-23 15:22:28 +02001915#ifndef CONFIG_USER_ONLY
1916 qemu_register_reset(x86_cpu_machine_reset_cb, cpu);
1917#endif
1918
Andreas Färber7a059952012-05-09 23:15:32 +02001919 mce_init(cpu);
1920 qemu_init_vcpu(&cpu->env);
Igor Mammedov65dee382012-07-23 15:22:28 +02001921 cpu_reset(CPU(cpu));
Andreas Färber7a059952012-05-09 23:15:32 +02001922}
1923
Andreas Färberde024812012-04-03 00:00:17 +02001924static void x86_cpu_initfn(Object *obj)
1925{
1926 X86CPU *cpu = X86_CPU(obj);
1927 CPUX86State *env = &cpu->env;
Igor Mammedovd65e9812012-06-19 15:39:46 +02001928 static int inited;
Andreas Färberde024812012-04-03 00:00:17 +02001929
1930 cpu_exec_init(env);
Andreas Färber71ad61d2012-04-17 12:10:29 +02001931
1932 object_property_add(obj, "family", "int",
Andreas Färber95b85192012-04-17 14:42:22 +02001933 x86_cpuid_version_get_family,
Andreas Färber71ad61d2012-04-17 12:10:29 +02001934 x86_cpuid_version_set_family, NULL, NULL, NULL);
Andreas Färberc5291a42012-04-17 12:16:39 +02001935 object_property_add(obj, "model", "int",
Andreas Färber67e30c82012-04-17 14:48:14 +02001936 x86_cpuid_version_get_model,
Andreas Färberc5291a42012-04-17 12:16:39 +02001937 x86_cpuid_version_set_model, NULL, NULL, NULL);
Andreas Färber036e2222012-04-17 14:14:18 +02001938 object_property_add(obj, "stepping", "int",
Andreas Färber35112e42012-04-17 14:50:53 +02001939 x86_cpuid_version_get_stepping,
Andreas Färber036e2222012-04-17 14:14:18 +02001940 x86_cpuid_version_set_stepping, NULL, NULL, NULL);
Andreas Färber8e1898b2012-04-17 18:41:40 +02001941 object_property_add(obj, "level", "int",
1942 x86_cpuid_get_level,
1943 x86_cpuid_set_level, NULL, NULL, NULL);
Andreas Färber16b93aa2012-04-17 18:44:07 +02001944 object_property_add(obj, "xlevel", "int",
1945 x86_cpuid_get_xlevel,
1946 x86_cpuid_set_xlevel, NULL, NULL, NULL);
Andreas Färberd480e1a2012-04-17 19:22:58 +02001947 object_property_add_str(obj, "vendor",
1948 x86_cpuid_get_vendor,
1949 x86_cpuid_set_vendor, NULL);
Andreas Färber938d4c22012-04-17 15:17:27 +02001950 object_property_add_str(obj, "model-id",
Andreas Färber63e886e2012-04-17 23:02:26 +02001951 x86_cpuid_get_model_id,
Andreas Färber938d4c22012-04-17 15:17:27 +02001952 x86_cpuid_set_model_id, NULL);
Andreas Färber89e48962012-04-18 00:12:23 +02001953 object_property_add(obj, "tsc-frequency", "int",
1954 x86_cpuid_get_tsc_freq,
1955 x86_cpuid_set_tsc_freq, NULL, NULL, NULL);
Andreas Färber71ad61d2012-04-17 12:10:29 +02001956
Andreas Färberde024812012-04-03 00:00:17 +02001957 env->cpuid_apic_id = env->cpu_index;
Igor Mammedovd65e9812012-06-19 15:39:46 +02001958
1959 /* init various static tables used in TCG mode */
1960 if (tcg_enabled() && !inited) {
1961 inited = 1;
1962 optimize_flags_init();
1963#ifndef CONFIG_USER_ONLY
1964 cpu_set_debug_excp_handler(breakpoint_handler);
1965#endif
1966 }
Andreas Färberde024812012-04-03 00:00:17 +02001967}
1968
Andreas Färber5fd20872012-04-02 23:20:08 +02001969static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
1970{
1971 X86CPUClass *xcc = X86_CPU_CLASS(oc);
1972 CPUClass *cc = CPU_CLASS(oc);
1973
1974 xcc->parent_reset = cc->reset;
1975 cc->reset = x86_cpu_reset;
1976}
1977
1978static const TypeInfo x86_cpu_type_info = {
1979 .name = TYPE_X86_CPU,
1980 .parent = TYPE_CPU,
1981 .instance_size = sizeof(X86CPU),
Andreas Färberde024812012-04-03 00:00:17 +02001982 .instance_init = x86_cpu_initfn,
Andreas Färber5fd20872012-04-02 23:20:08 +02001983 .abstract = false,
1984 .class_size = sizeof(X86CPUClass),
1985 .class_init = x86_cpu_common_class_init,
1986};
1987
1988static void x86_cpu_register_types(void)
1989{
1990 type_register_static(&x86_cpu_type_info);
1991}
1992
1993type_init(x86_cpu_register_types)