blob: e20b0c8158a69b1493bb1db281a5217dd5a249e5 [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"
Paolo Bonzini9c17d612012-12-17 18:20:04 +010025#include "sysemu/kvm.h"
Eduardo Habkost8932cfd2013-01-22 18:25:09 -020026#include "sysemu/cpus.h"
27#include "topology.h"
Andre Przywarac6dc6f62010-03-11 14:38:55 +010028
Paolo Bonzini1de7afc2012-12-17 18:20:00 +010029#include "qemu/option.h"
30#include "qemu/config-file.h"
Paolo Bonzini7b1b5d12012-12-17 18:19:43 +010031#include "qapi/qmp/qerror.h"
Andre Przywarac6dc6f62010-03-11 14:38:55 +010032
Eduardo Habkost8e8aba52013-05-06 13:20:07 -030033#include "qapi-types.h"
34#include "qapi-visit.h"
Paolo Bonzini7b1b5d12012-12-17 18:19:43 +010035#include "qapi/visitor.h"
Paolo Bonzini9c17d612012-12-17 18:20:04 +010036#include "sysemu/arch_init.h"
Andreas Färber71ad61d2012-04-17 12:10:29 +020037
Igor Mammedov65dee382012-07-23 15:22:28 +020038#include "hw/hw.h"
Stefan Weilb834b502012-08-30 22:28:31 +020039#if defined(CONFIG_KVM)
Anthony Liguorief8621b2012-08-29 09:32:41 -050040#include <linux/kvm_para.h>
Stefan Weilb834b502012-08-30 22:28:31 +020041#endif
Igor Mammedov65dee382012-07-23 15:22:28 +020042
Paolo Bonzini9c17d612012-12-17 18:20:04 +010043#include "sysemu/sysemu.h"
Igor Mammedov53a89e22013-04-29 19:03:01 +020044#include "hw/qdev-properties.h"
Igor Mammedov62fc4032013-04-29 18:54:13 +020045#include "hw/cpu/icc_bus.h"
Igor Mammedovbdeec802012-10-13 22:35:39 +020046#ifndef CONFIG_USER_ONLY
Paolo Bonzini0d09e412013-02-05 17:06:20 +010047#include "hw/xen/xen.h"
Paolo Bonzini0d09e412013-02-05 17:06:20 +010048#include "hw/i386/apic_internal.h"
Igor Mammedovbdeec802012-10-13 22:35:39 +020049#endif
50
Eduardo Habkost5e891bf2013-08-27 12:24:37 -030051
52/* Cache topology CPUID constants: */
53
54/* CPUID Leaf 2 Descriptors */
55
56#define CPUID_2_L1D_32KB_8WAY_64B 0x2c
57#define CPUID_2_L1I_32KB_8WAY_64B 0x30
58#define CPUID_2_L2_2MB_8WAY_64B 0x7d
59
60
61/* CPUID Leaf 4 constants: */
62
63/* EAX: */
64#define CPUID_4_TYPE_DCACHE 1
65#define CPUID_4_TYPE_ICACHE 2
66#define CPUID_4_TYPE_UNIFIED 3
67
68#define CPUID_4_LEVEL(l) ((l) << 5)
69
70#define CPUID_4_SELF_INIT_LEVEL (1 << 8)
71#define CPUID_4_FULLY_ASSOC (1 << 9)
72
73/* EDX: */
74#define CPUID_4_NO_INVD_SHARING (1 << 0)
75#define CPUID_4_INCLUSIVE (1 << 1)
76#define CPUID_4_COMPLEX_IDX (1 << 2)
77
78#define ASSOC_FULL 0xFF
79
80/* AMD associativity encoding used on CPUID Leaf 0x80000006: */
81#define AMD_ENC_ASSOC(a) (a <= 1 ? a : \
82 a == 2 ? 0x2 : \
83 a == 4 ? 0x4 : \
84 a == 8 ? 0x6 : \
85 a == 16 ? 0x8 : \
86 a == 32 ? 0xA : \
87 a == 48 ? 0xB : \
88 a == 64 ? 0xC : \
89 a == 96 ? 0xD : \
90 a == 128 ? 0xE : \
91 a == ASSOC_FULL ? 0xF : \
92 0 /* invalid value */)
93
94
95/* Definitions of the hardcoded cache entries we expose: */
96
97/* L1 data cache: */
98#define L1D_LINE_SIZE 64
99#define L1D_ASSOCIATIVITY 8
100#define L1D_SETS 64
101#define L1D_PARTITIONS 1
102/* Size = LINE_SIZE*ASSOCIATIVITY*SETS*PARTITIONS = 32KiB */
103#define L1D_DESCRIPTOR CPUID_2_L1D_32KB_8WAY_64B
104/*FIXME: CPUID leaf 0x80000005 is inconsistent with leaves 2 & 4 */
105#define L1D_LINES_PER_TAG 1
106#define L1D_SIZE_KB_AMD 64
107#define L1D_ASSOCIATIVITY_AMD 2
108
109/* L1 instruction cache: */
110#define L1I_LINE_SIZE 64
111#define L1I_ASSOCIATIVITY 8
112#define L1I_SETS 64
113#define L1I_PARTITIONS 1
114/* Size = LINE_SIZE*ASSOCIATIVITY*SETS*PARTITIONS = 32KiB */
115#define L1I_DESCRIPTOR CPUID_2_L1I_32KB_8WAY_64B
116/*FIXME: CPUID leaf 0x80000005 is inconsistent with leaves 2 & 4 */
117#define L1I_LINES_PER_TAG 1
118#define L1I_SIZE_KB_AMD 64
119#define L1I_ASSOCIATIVITY_AMD 2
120
121/* Level 2 unified cache: */
122#define L2_LINE_SIZE 64
123#define L2_ASSOCIATIVITY 16
124#define L2_SETS 4096
125#define L2_PARTITIONS 1
126/* Size = LINE_SIZE*ASSOCIATIVITY*SETS*PARTITIONS = 4MiB */
127/*FIXME: CPUID leaf 2 descriptor is inconsistent with CPUID leaf 4 */
128#define L2_DESCRIPTOR CPUID_2_L2_2MB_8WAY_64B
129/*FIXME: CPUID leaf 0x80000006 is inconsistent with leaves 2 & 4 */
130#define L2_LINES_PER_TAG 1
131#define L2_SIZE_KB_AMD 512
132
133/* No L3 cache: */
134#define L3_SIZE_KB 0 /* disabled */
135#define L3_ASSOCIATIVITY 0 /* disabled */
136#define L3_LINES_PER_TAG 0 /* disabled */
137#define L3_LINE_SIZE 0 /* disabled */
138
139/* TLB definitions: */
140
141#define L1_DTLB_2M_ASSOC 1
142#define L1_DTLB_2M_ENTRIES 255
143#define L1_DTLB_4K_ASSOC 1
144#define L1_DTLB_4K_ENTRIES 255
145
146#define L1_ITLB_2M_ASSOC 1
147#define L1_ITLB_2M_ENTRIES 255
148#define L1_ITLB_4K_ASSOC 1
149#define L1_ITLB_4K_ENTRIES 255
150
151#define L2_DTLB_2M_ASSOC 0 /* disabled */
152#define L2_DTLB_2M_ENTRIES 0 /* disabled */
153#define L2_DTLB_4K_ASSOC 4
154#define L2_DTLB_4K_ENTRIES 512
155
156#define L2_ITLB_2M_ASSOC 0 /* disabled */
157#define L2_ITLB_2M_ENTRIES 0 /* disabled */
158#define L2_ITLB_4K_ASSOC 4
159#define L2_ITLB_4K_ENTRIES 512
160
161
162
Igor Mammedov99b88a12013-01-21 15:06:36 +0100163static void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1,
164 uint32_t vendor2, uint32_t vendor3)
165{
166 int i;
167 for (i = 0; i < 4; i++) {
168 dst[i] = vendor1 >> (8 * i);
169 dst[i + 4] = vendor2 >> (8 * i);
170 dst[i + 8] = vendor3 >> (8 * i);
171 }
172 dst[CPUID_VENDOR_SZ] = '\0';
173}
174
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100175/* feature flags taken from "Intel Processor Identification and the CPUID
176 * Instruction" and AMD's "CPUID Specification". In cases of disagreement
177 * between feature naming conventions, aliases may be added.
178 */
179static const char *feature_name[] = {
180 "fpu", "vme", "de", "pse",
181 "tsc", "msr", "pae", "mce",
182 "cx8", "apic", NULL, "sep",
183 "mtrr", "pge", "mca", "cmov",
184 "pat", "pse36", "pn" /* Intel psn */, "clflush" /* Intel clfsh */,
185 NULL, "ds" /* Intel dts */, "acpi", "mmx",
186 "fxsr", "sse", "sse2", "ss",
187 "ht" /* Intel htt */, "tm", "ia64", "pbe",
188};
189static const char *ext_feature_name[] = {
Eduardo Habkostf370be32012-02-17 14:41:20 -0200190 "pni|sse3" /* Intel,AMD sse3 */, "pclmulqdq|pclmuldq", "dtes64", "monitor",
Andre Przywarae117f772010-03-11 14:38:59 +0100191 "ds_cpl", "vmx", "smx", "est",
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100192 "tm2", "ssse3", "cid", NULL,
Andre Przywarae117f772010-03-11 14:38:59 +0100193 "fma", "cx16", "xtpr", "pdcm",
Mao, Junjie434acb82012-07-20 07:08:21 +0000194 NULL, "pcid", "dca", "sse4.1|sse4_1",
Andre Przywarae117f772010-03-11 14:38:59 +0100195 "sse4.2|sse4_2", "x2apic", "movbe", "popcnt",
Eduardo Habkosteaf3f092012-03-06 15:11:30 -0300196 "tsc-deadline", "aes", "xsave", "osxsave",
Andre Przywarac8acc382012-11-14 16:28:52 -0200197 "avx", "f16c", "rdrand", "hypervisor",
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100198};
Eduardo Habkost3b671a42012-09-06 10:05:38 +0000199/* Feature names that are already defined on feature_name[] but are set on
200 * CPUID[8000_0001].EDX on AMD CPUs don't have their names on
201 * ext2_feature_name[]. They are copied automatically to cpuid_ext2_features
202 * if and only if CPU vendor is AMD.
203 */
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100204static const char *ext2_feature_name[] = {
Eduardo Habkost3b671a42012-09-06 10:05:38 +0000205 NULL /* fpu */, NULL /* vme */, NULL /* de */, NULL /* pse */,
206 NULL /* tsc */, NULL /* msr */, NULL /* pae */, NULL /* mce */,
207 NULL /* cx8 */ /* AMD CMPXCHG8B */, NULL /* apic */, NULL, "syscall",
208 NULL /* mtrr */, NULL /* pge */, NULL /* mca */, NULL /* cmov */,
209 NULL /* pat */, NULL /* pse36 */, NULL, NULL /* Linux mp */,
210 "nx|xd", NULL, "mmxext", NULL /* mmx */,
211 NULL /* fxsr */, "fxsr_opt|ffxsr", "pdpe1gb" /* AMD Page1GB */, "rdtscp",
Eduardo Habkost01f590d2012-10-24 12:10:33 -0200212 NULL, "lm|i64", "3dnowext", "3dnow",
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100213};
214static const char *ext3_feature_name[] = {
215 "lahf_lm" /* AMD LahfSahf */, "cmp_legacy", "svm", "extapic" /* AMD ExtApicSpace */,
216 "cr8legacy" /* AMD AltMovCr8 */, "abm", "sse4a", "misalignsse",
Andre Przywarae117f772010-03-11 14:38:59 +0100217 "3dnowprefetch", "osvw", "ibs", "xop",
Andre Przywarac8acc382012-11-14 16:28:52 -0200218 "skinit", "wdt", NULL, "lwp",
219 "fma4", "tce", NULL, "nodeid_msr",
220 NULL, "tbm", "topoext", "perfctr_core",
221 "perfctr_nb", NULL, NULL, NULL,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100222 NULL, NULL, NULL, NULL,
223};
224
Eduardo Habkost89e49c82013-01-07 16:20:47 -0200225static const char *ext4_feature_name[] = {
226 NULL, NULL, "xstore", "xstore-en",
227 NULL, NULL, "xcrypt", "xcrypt-en",
228 "ace2", "ace2-en", "phe", "phe-en",
229 "pmm", "pmm-en", NULL, NULL,
230 NULL, NULL, NULL, NULL,
231 NULL, NULL, NULL, NULL,
232 NULL, NULL, NULL, NULL,
233 NULL, NULL, NULL, NULL,
234};
235
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100236static const char *kvm_feature_name[] = {
Don Slutzc3d39802012-10-12 15:43:23 -0400237 "kvmclock", "kvm_nopiodelay", "kvm_mmu", "kvmclock",
Andrew Jonesf010bc62013-09-18 16:41:45 +0200238 "kvm_asyncpf", "kvm_steal_time", "kvm_pv_eoi", "kvm_pv_unhalt",
Don Slutzc3d39802012-10-12 15:43:23 -0400239 NULL, NULL, NULL, NULL,
240 NULL, NULL, NULL, NULL,
241 NULL, NULL, NULL, NULL,
242 NULL, NULL, NULL, NULL,
243 NULL, NULL, NULL, NULL,
244 NULL, NULL, NULL, NULL,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100245};
246
Joerg Roedel296acb62010-09-27 15:16:17 +0200247static const char *svm_feature_name[] = {
248 "npt", "lbrv", "svm_lock", "nrip_save",
249 "tsc_scale", "vmcb_clean", "flushbyasid", "decodeassists",
250 NULL, NULL, "pause_filter", NULL,
251 "pfthreshold", NULL, NULL, NULL,
252 NULL, NULL, NULL, NULL,
253 NULL, NULL, NULL, NULL,
254 NULL, NULL, NULL, NULL,
255 NULL, NULL, NULL, NULL,
256};
257
H. Peter Anvina9321a42012-09-26 13:18:43 -0700258static const char *cpuid_7_0_ebx_feature_name[] = {
Eduardo Habkost811a8ae2012-10-09 11:03:59 -0300259 "fsgsbase", NULL, NULL, "bmi1", "hle", "avx2", NULL, "smep",
260 "bmi2", "erms", "invpcid", "rtm", NULL, NULL, NULL, NULL,
Andre Przywarac8acc382012-11-14 16:28:52 -0200261 NULL, NULL, "rdseed", "adx", "smap", NULL, NULL, NULL,
H. Peter Anvina9321a42012-09-26 13:18:43 -0700262 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
263};
264
Eduardo Habkost5ef57872013-01-07 16:20:45 -0200265typedef struct FeatureWordInfo {
266 const char **feat_names;
Eduardo Habkost04d104b2013-04-22 16:00:16 -0300267 uint32_t cpuid_eax; /* Input EAX for CPUID */
268 bool cpuid_needs_ecx; /* CPUID instruction uses ECX as input */
269 uint32_t cpuid_ecx; /* Input ECX value for CPUID */
270 int cpuid_reg; /* output register (R_* constant) */
Eduardo Habkost5ef57872013-01-07 16:20:45 -0200271} FeatureWordInfo;
272
273static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
Eduardo Habkostbffd67b2013-01-07 16:20:46 -0200274 [FEAT_1_EDX] = {
275 .feat_names = feature_name,
276 .cpuid_eax = 1, .cpuid_reg = R_EDX,
277 },
278 [FEAT_1_ECX] = {
279 .feat_names = ext_feature_name,
280 .cpuid_eax = 1, .cpuid_reg = R_ECX,
281 },
282 [FEAT_8000_0001_EDX] = {
283 .feat_names = ext2_feature_name,
284 .cpuid_eax = 0x80000001, .cpuid_reg = R_EDX,
285 },
286 [FEAT_8000_0001_ECX] = {
287 .feat_names = ext3_feature_name,
288 .cpuid_eax = 0x80000001, .cpuid_reg = R_ECX,
289 },
Eduardo Habkost89e49c82013-01-07 16:20:47 -0200290 [FEAT_C000_0001_EDX] = {
291 .feat_names = ext4_feature_name,
292 .cpuid_eax = 0xC0000001, .cpuid_reg = R_EDX,
293 },
Eduardo Habkostbffd67b2013-01-07 16:20:46 -0200294 [FEAT_KVM] = {
295 .feat_names = kvm_feature_name,
296 .cpuid_eax = KVM_CPUID_FEATURES, .cpuid_reg = R_EAX,
297 },
298 [FEAT_SVM] = {
299 .feat_names = svm_feature_name,
300 .cpuid_eax = 0x8000000A, .cpuid_reg = R_EDX,
301 },
302 [FEAT_7_0_EBX] = {
303 .feat_names = cpuid_7_0_ebx_feature_name,
Eduardo Habkost04d104b2013-04-22 16:00:16 -0300304 .cpuid_eax = 7,
305 .cpuid_needs_ecx = true, .cpuid_ecx = 0,
306 .cpuid_reg = R_EBX,
Eduardo Habkostbffd67b2013-01-07 16:20:46 -0200307 },
Eduardo Habkost5ef57872013-01-07 16:20:45 -0200308};
309
Eduardo Habkost8e8aba52013-05-06 13:20:07 -0300310typedef struct X86RegisterInfo32 {
311 /* Name of register */
312 const char *name;
313 /* QAPI enum value register */
314 X86CPURegister32 qapi_enum;
315} X86RegisterInfo32;
316
317#define REGISTER(reg) \
318 [R_##reg] = { .name = #reg, .qapi_enum = X86_C_P_U_REGISTER32_##reg }
319X86RegisterInfo32 x86_reg_info_32[CPU_NB_REGS32] = {
320 REGISTER(EAX),
321 REGISTER(ECX),
322 REGISTER(EDX),
323 REGISTER(EBX),
324 REGISTER(ESP),
325 REGISTER(EBP),
326 REGISTER(ESI),
327 REGISTER(EDI),
328};
329#undef REGISTER
330
Paolo Bonzini2560f192013-10-02 17:54:57 +0200331typedef struct ExtSaveArea {
332 uint32_t feature, bits;
333 uint32_t offset, size;
334} ExtSaveArea;
335
336static const ExtSaveArea ext_save_areas[] = {
337 [2] = { .feature = FEAT_1_ECX, .bits = CPUID_EXT_AVX,
Liu Jinsong33f373d2013-12-03 04:17:50 +0800338 .offset = 0x240, .size = 0x100 },
Paolo Bonzini2560f192013-10-02 17:54:57 +0200339};
Eduardo Habkost8e8aba52013-05-06 13:20:07 -0300340
Eduardo Habkost8b4bedd2013-01-04 20:01:06 -0200341const char *get_register_name_32(unsigned int reg)
342{
Igor Mammedov31ccdde2013-06-03 18:23:27 +0200343 if (reg >= CPU_NB_REGS32) {
Eduardo Habkost8b4bedd2013-01-04 20:01:06 -0200344 return NULL;
345 }
Eduardo Habkost8e8aba52013-05-06 13:20:07 -0300346 return x86_reg_info_32[reg].name;
Eduardo Habkost8b4bedd2013-01-04 20:01:06 -0200347}
348
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100349/* collects per-function cpuid data
350 */
351typedef struct model_features_t {
352 uint32_t *guest_feat;
353 uint32_t *host_feat;
Eduardo Habkostbffd67b2013-01-07 16:20:46 -0200354 FeatureWord feat_word;
Eduardo Habkost8b4bedd2013-01-04 20:01:06 -0200355} model_features_t;
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100356
357int check_cpuid = 0;
358int enforce_cpuid = 0;
359
Michael S. Tsirkindc599442012-10-18 00:15:48 +0200360static uint32_t kvm_default_features = (1 << KVM_FEATURE_CLOCKSOURCE) |
361 (1 << KVM_FEATURE_NOP_IO_DELAY) |
Michael S. Tsirkindc599442012-10-18 00:15:48 +0200362 (1 << KVM_FEATURE_CLOCKSOURCE2) |
363 (1 << KVM_FEATURE_ASYNC_PF) |
364 (1 << KVM_FEATURE_STEAL_TIME) |
Eduardo Habkost29694752013-01-17 18:59:29 -0200365 (1 << KVM_FEATURE_PV_EOI) |
Michael S. Tsirkindc599442012-10-18 00:15:48 +0200366 (1 << KVM_FEATURE_CLOCKSOURCE_STABLE_BIT);
Michael S. Tsirkindc599442012-10-18 00:15:48 +0200367
Eduardo Habkost29694752013-01-17 18:59:29 -0200368void disable_kvm_pv_eoi(void)
Michael S. Tsirkindc599442012-10-18 00:15:48 +0200369{
Eduardo Habkost29694752013-01-17 18:59:29 -0200370 kvm_default_features &= ~(1UL << KVM_FEATURE_PV_EOI);
Michael S. Tsirkindc599442012-10-18 00:15:48 +0200371}
372
Jan Kiszkabb44e0d2011-01-21 21:48:07 +0100373void host_cpuid(uint32_t function, uint32_t count,
374 uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
Andre Przywarabdde4762010-03-11 14:38:58 +0100375{
376#if defined(CONFIG_KVM)
Anthony Liguoria1fd24a2011-11-27 11:13:01 -0600377 uint32_t vec[4];
378
379#ifdef __x86_64__
380 asm volatile("cpuid"
381 : "=a"(vec[0]), "=b"(vec[1]),
382 "=c"(vec[2]), "=d"(vec[3])
383 : "0"(function), "c"(count) : "cc");
384#else
385 asm volatile("pusha \n\t"
386 "cpuid \n\t"
387 "mov %%eax, 0(%2) \n\t"
388 "mov %%ebx, 4(%2) \n\t"
389 "mov %%ecx, 8(%2) \n\t"
390 "mov %%edx, 12(%2) \n\t"
391 "popa"
392 : : "a"(function), "c"(count), "S"(vec)
393 : "memory", "cc");
394#endif
395
Andre Przywarabdde4762010-03-11 14:38:58 +0100396 if (eax)
Anthony Liguoria1fd24a2011-11-27 11:13:01 -0600397 *eax = vec[0];
Andre Przywarabdde4762010-03-11 14:38:58 +0100398 if (ebx)
Anthony Liguoria1fd24a2011-11-27 11:13:01 -0600399 *ebx = vec[1];
Andre Przywarabdde4762010-03-11 14:38:58 +0100400 if (ecx)
Anthony Liguoria1fd24a2011-11-27 11:13:01 -0600401 *ecx = vec[2];
Andre Przywarabdde4762010-03-11 14:38:58 +0100402 if (edx)
Anthony Liguoria1fd24a2011-11-27 11:13:01 -0600403 *edx = vec[3];
Andre Przywarabdde4762010-03-11 14:38:58 +0100404#endif
405}
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100406
407#define iswhite(c) ((c) && ((c) <= ' ' || '~' < (c)))
408
409/* general substring compare of *[s1..e1) and *[s2..e2). sx is start of
410 * a substring. ex if !NULL points to the first char after a substring,
411 * otherwise the string is assumed to sized by a terminating nul.
412 * Return lexical ordering of *s1:*s2.
413 */
414static int sstrcmp(const char *s1, const char *e1, const char *s2,
415 const char *e2)
416{
417 for (;;) {
418 if (!*s1 || !*s2 || *s1 != *s2)
419 return (*s1 - *s2);
420 ++s1, ++s2;
421 if (s1 == e1 && s2 == e2)
422 return (0);
423 else if (s1 == e1)
424 return (*s2);
425 else if (s2 == e2)
426 return (*s1);
427 }
428}
429
430/* compare *[s..e) to *altstr. *altstr may be a simple string or multiple
431 * '|' delimited (possibly empty) strings in which case search for a match
432 * within the alternatives proceeds left to right. Return 0 for success,
433 * non-zero otherwise.
434 */
435static int altcmp(const char *s, const char *e, const char *altstr)
436{
437 const char *p, *q;
438
439 for (q = p = altstr; ; ) {
440 while (*p && *p != '|')
441 ++p;
442 if ((q == p && !*s) || (q != p && !sstrcmp(s, e, q, p)))
443 return (0);
444 if (!*p)
445 return (1);
446 else
447 q = ++p;
448 }
449}
450
451/* search featureset for flag *[s..e), if found set corresponding bit in
Jan Kiszkae41e0fc2011-04-19 13:06:06 +0200452 * *pval and return true, otherwise return false
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100453 */
Jan Kiszkae41e0fc2011-04-19 13:06:06 +0200454static bool lookup_feature(uint32_t *pval, const char *s, const char *e,
455 const char **featureset)
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100456{
457 uint32_t mask;
458 const char **ppc;
Jan Kiszkae41e0fc2011-04-19 13:06:06 +0200459 bool found = false;
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100460
Jan Kiszkae41e0fc2011-04-19 13:06:06 +0200461 for (mask = 1, ppc = featureset; mask; mask <<= 1, ++ppc) {
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100462 if (*ppc && !altcmp(s, e, *ppc)) {
463 *pval |= mask;
Jan Kiszkae41e0fc2011-04-19 13:06:06 +0200464 found = true;
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100465 }
Jan Kiszkae41e0fc2011-04-19 13:06:06 +0200466 }
467 return found;
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100468}
469
Eduardo Habkost5ef57872013-01-07 16:20:45 -0200470static void add_flagname_to_bitmaps(const char *flagname,
471 FeatureWordArray words)
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100472{
Eduardo Habkost5ef57872013-01-07 16:20:45 -0200473 FeatureWord w;
474 for (w = 0; w < FEATURE_WORDS; w++) {
475 FeatureWordInfo *wi = &feature_word_info[w];
476 if (wi->feat_names &&
477 lookup_feature(&words[w], flagname, NULL, wi->feat_names)) {
478 break;
479 }
480 }
481 if (w == FEATURE_WORDS) {
482 fprintf(stderr, "CPU feature %s not found\n", flagname);
483 }
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100484}
485
486typedef struct x86_def_t {
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100487 const char *name;
488 uint32_t level;
Eduardo Habkost90e4b0c2013-04-22 16:00:12 -0300489 uint32_t xlevel;
490 uint32_t xlevel2;
Igor Mammedov99b88a12013-01-21 15:06:36 +0100491 /* vendor is zero-terminated, 12 character ASCII string */
492 char vendor[CPUID_VENDOR_SZ + 1];
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100493 int family;
494 int model;
495 int stepping;
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300496 FeatureWordArray features;
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100497 char model_id[48];
Benoît Canet787aaf52013-09-02 17:06:37 +0200498 bool cache_info_passthrough;
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100499} x86_def_t;
500
501#define I486_FEATURES (CPUID_FP87 | CPUID_VME | CPUID_PSE)
502#define PENTIUM_FEATURES (I486_FEATURES | CPUID_DE | CPUID_TSC | \
503 CPUID_MSR | CPUID_MCE | CPUID_CX8 | CPUID_MMX | CPUID_APIC)
504#define PENTIUM2_FEATURES (PENTIUM_FEATURES | CPUID_PAE | CPUID_SEP | \
505 CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_CMOV | CPUID_PAT | \
506 CPUID_PSE36 | CPUID_FXSR)
507#define PENTIUM3_FEATURES (PENTIUM2_FEATURES | CPUID_SSE)
508#define PPRO_FEATURES (CPUID_FP87 | CPUID_DE | CPUID_PSE | CPUID_TSC | \
509 CPUID_MSR | CPUID_MCE | CPUID_CX8 | CPUID_PGE | CPUID_CMOV | \
510 CPUID_PAT | CPUID_FXSR | CPUID_MMX | CPUID_SSE | CPUID_SSE2 | \
511 CPUID_PAE | CPUID_SEP | CPUID_APIC)
512
Andre Przywara551a2de2010-03-11 14:39:03 +0100513#define TCG_FEATURES (CPUID_FP87 | CPUID_PSE | CPUID_TSC | CPUID_MSR | \
514 CPUID_PAE | CPUID_MCE | CPUID_CX8 | CPUID_APIC | CPUID_SEP | \
515 CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_CMOV | CPUID_PAT | \
516 CPUID_PSE36 | CPUID_CLFLUSH | CPUID_ACPI | CPUID_MMX | \
517 CPUID_FXSR | CPUID_SSE | CPUID_SSE2 | CPUID_SS)
Aurelien Jarno8560efe2010-03-13 16:43:15 +0100518 /* partly implemented:
519 CPUID_MTRR, CPUID_MCA, CPUID_CLFLUSH (needed for Win64)
520 CPUID_PSE36 (needed for Solaris) */
521 /* missing:
522 CPUID_VME, CPUID_DTS, CPUID_SS, CPUID_HT, CPUID_TM, CPUID_PBE */
Aurelien Jarnoe71827b2013-03-31 12:58:30 +0200523#define TCG_EXT_FEATURES (CPUID_EXT_SSE3 | CPUID_EXT_PCLMULQDQ | \
524 CPUID_EXT_MONITOR | CPUID_EXT_SSSE3 | CPUID_EXT_CX16 | \
525 CPUID_EXT_SSE41 | CPUID_EXT_SSE42 | CPUID_EXT_POPCNT | \
Aurelien Jarnod6400452013-03-31 12:58:31 +0200526 CPUID_EXT_MOVBE | CPUID_EXT_AES | CPUID_EXT_HYPERVISOR)
Aurelien Jarno8560efe2010-03-13 16:43:15 +0100527 /* missing:
Aurelien Jarnoe71827b2013-03-31 12:58:30 +0200528 CPUID_EXT_DTES64, CPUID_EXT_DSCPL, CPUID_EXT_VMX, CPUID_EXT_SMX,
529 CPUID_EXT_EST, CPUID_EXT_TM2, CPUID_EXT_CID, CPUID_EXT_FMA,
530 CPUID_EXT_XTPR, CPUID_EXT_PDCM, CPUID_EXT_PCID, CPUID_EXT_DCA,
Aurelien Jarnod6400452013-03-31 12:58:31 +0200531 CPUID_EXT_X2APIC, CPUID_EXT_TSC_DEADLINE_TIMER, CPUID_EXT_XSAVE,
532 CPUID_EXT_OSXSAVE, CPUID_EXT_AVX, CPUID_EXT_F16C,
Aurelien Jarno83f7dc22013-03-26 19:56:02 +0100533 CPUID_EXT_RDRAND */
Eduardo Habkost60032ac2012-09-06 10:05:37 +0000534#define TCG_EXT2_FEATURES ((TCG_FEATURES & CPUID_EXT2_AMD_ALIASES) | \
Andre Przywara551a2de2010-03-11 14:39:03 +0100535 CPUID_EXT2_NX | CPUID_EXT2_MMXEXT | CPUID_EXT2_RDTSCP | \
536 CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT)
Aurelien Jarno8560efe2010-03-13 16:43:15 +0100537 /* missing:
538 CPUID_EXT2_PDPE1GB */
Andre Przywara551a2de2010-03-11 14:39:03 +0100539#define TCG_EXT3_FEATURES (CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM | \
540 CPUID_EXT3_CR8LEG | CPUID_EXT3_ABM | CPUID_EXT3_SSE4A)
Joerg Roedel296acb62010-09-27 15:16:17 +0200541#define TCG_SVM_FEATURES 0
Richard Henderson7073fba2013-01-23 16:17:10 -0800542#define TCG_7_0_EBX_FEATURES (CPUID_7_0_EBX_SMEP | CPUID_7_0_EBX_SMAP \
Richard Hendersoncd7f97c2013-01-23 18:17:33 -0800543 CPUID_7_0_EBX_BMI1 | CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ADX)
Richard Henderson111994e2013-01-10 12:06:59 -0800544 /* missing:
Richard Henderson7073fba2013-01-23 16:17:10 -0800545 CPUID_7_0_EBX_FSGSBASE, CPUID_7_0_EBX_HLE, CPUID_7_0_EBX_AVX2,
546 CPUID_7_0_EBX_ERMS, CPUID_7_0_EBX_INVPCID, CPUID_7_0_EBX_RTM,
Richard Hendersoncd7f97c2013-01-23 18:17:33 -0800547 CPUID_7_0_EBX_RDSEED */
Andre Przywara551a2de2010-03-11 14:39:03 +0100548
Andreas Färber7fc9b712013-01-21 01:02:28 +0100549/* built-in CPU model definitions
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100550 */
551static x86_def_t builtin_x86_defs[] = {
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100552 {
553 .name = "qemu64",
554 .level = 4,
Igor Mammedov99b88a12013-01-21 15:06:36 +0100555 .vendor = CPUID_VENDOR_AMD,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100556 .family = 6,
Eduardo Habkostf8e6a112013-09-10 17:48:59 -0300557 .model = 6,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100558 .stepping = 3,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300559 .features[FEAT_1_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300560 PPRO_FEATURES |
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100561 CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100562 CPUID_PSE36,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300563 .features[FEAT_1_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300564 CPUID_EXT_SSE3 | CPUID_EXT_CX16 | CPUID_EXT_POPCNT,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300565 .features[FEAT_8000_0001_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300566 (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) |
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100567 CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300568 .features[FEAT_8000_0001_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300569 CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM |
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100570 CPUID_EXT3_ABM | CPUID_EXT3_SSE4A,
571 .xlevel = 0x8000000A,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100572 },
573 {
574 .name = "phenom",
575 .level = 5,
Igor Mammedov99b88a12013-01-21 15:06:36 +0100576 .vendor = CPUID_VENDOR_AMD,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100577 .family = 16,
578 .model = 2,
579 .stepping = 3,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300580 .features[FEAT_1_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300581 PPRO_FEATURES |
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100582 CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
Aurelien Jarno8560efe2010-03-13 16:43:15 +0100583 CPUID_PSE36 | CPUID_VME | CPUID_HT,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300584 .features[FEAT_1_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300585 CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_CX16 |
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100586 CPUID_EXT_POPCNT,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300587 .features[FEAT_8000_0001_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300588 (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) |
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100589 CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX |
590 CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT | CPUID_EXT2_MMXEXT |
Aurelien Jarno8560efe2010-03-13 16:43:15 +0100591 CPUID_EXT2_FFXSR | CPUID_EXT2_PDPE1GB | CPUID_EXT2_RDTSCP,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100592 /* Missing: CPUID_EXT3_CMP_LEG, CPUID_EXT3_EXTAPIC,
593 CPUID_EXT3_CR8LEG,
594 CPUID_EXT3_MISALIGNSSE, CPUID_EXT3_3DNOWPREFETCH,
595 CPUID_EXT3_OSVW, CPUID_EXT3_IBS */
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300596 .features[FEAT_8000_0001_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300597 CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM |
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100598 CPUID_EXT3_ABM | CPUID_EXT3_SSE4A,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300599 .features[FEAT_SVM] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300600 CPUID_SVM_NPT | CPUID_SVM_LBRV,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100601 .xlevel = 0x8000001A,
602 .model_id = "AMD Phenom(tm) 9550 Quad-Core Processor"
603 },
604 {
605 .name = "core2duo",
606 .level = 10,
Igor Mammedov99b88a12013-01-21 15:06:36 +0100607 .vendor = CPUID_VENDOR_INTEL,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100608 .family = 6,
609 .model = 15,
610 .stepping = 11,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300611 .features[FEAT_1_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300612 PPRO_FEATURES |
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100613 CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
Aurelien Jarno8560efe2010-03-13 16:43:15 +0100614 CPUID_PSE36 | CPUID_VME | CPUID_DTS | CPUID_ACPI | CPUID_SS |
615 CPUID_HT | CPUID_TM | CPUID_PBE,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300616 .features[FEAT_1_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300617 CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_SSSE3 |
Aurelien Jarno8560efe2010-03-13 16:43:15 +0100618 CPUID_EXT_DTES64 | CPUID_EXT_DSCPL | CPUID_EXT_VMX | CPUID_EXT_EST |
619 CPUID_EXT_TM2 | CPUID_EXT_CX16 | CPUID_EXT_XTPR | CPUID_EXT_PDCM,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300620 .features[FEAT_8000_0001_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300621 CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300622 .features[FEAT_8000_0001_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300623 CPUID_EXT3_LAHF_LM,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100624 .xlevel = 0x80000008,
625 .model_id = "Intel(R) Core(TM)2 Duo CPU T7700 @ 2.40GHz",
626 },
627 {
628 .name = "kvm64",
629 .level = 5,
Igor Mammedov99b88a12013-01-21 15:06:36 +0100630 .vendor = CPUID_VENDOR_INTEL,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100631 .family = 15,
632 .model = 6,
633 .stepping = 1,
634 /* Missing: CPUID_VME, CPUID_HT */
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300635 .features[FEAT_1_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300636 PPRO_FEATURES |
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100637 CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
638 CPUID_PSE36,
639 /* Missing: CPUID_EXT_POPCNT, CPUID_EXT_MONITOR */
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300640 .features[FEAT_1_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300641 CPUID_EXT_SSE3 | CPUID_EXT_CX16,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100642 /* Missing: CPUID_EXT2_PDPE1GB, CPUID_EXT2_RDTSCP */
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300643 .features[FEAT_8000_0001_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300644 (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) |
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100645 CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
646 /* Missing: CPUID_EXT3_LAHF_LM, CPUID_EXT3_CMP_LEG, CPUID_EXT3_EXTAPIC,
647 CPUID_EXT3_CR8LEG, CPUID_EXT3_ABM, CPUID_EXT3_SSE4A,
648 CPUID_EXT3_MISALIGNSSE, CPUID_EXT3_3DNOWPREFETCH,
649 CPUID_EXT3_OSVW, CPUID_EXT3_IBS, CPUID_EXT3_SVM */
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300650 .features[FEAT_8000_0001_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300651 0,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100652 .xlevel = 0x80000008,
653 .model_id = "Common KVM processor"
654 },
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100655 {
656 .name = "qemu32",
657 .level = 4,
Igor Mammedov99b88a12013-01-21 15:06:36 +0100658 .vendor = CPUID_VENDOR_INTEL,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100659 .family = 6,
Eduardo Habkostf8e6a112013-09-10 17:48:59 -0300660 .model = 6,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100661 .stepping = 3,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300662 .features[FEAT_1_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300663 PPRO_FEATURES,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300664 .features[FEAT_1_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300665 CPUID_EXT_SSE3 | CPUID_EXT_POPCNT,
Andre Przywara58012d62010-03-11 14:39:06 +0100666 .xlevel = 0x80000004,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100667 },
668 {
Andre Przywaraeafaf1e2010-05-21 09:50:51 +0200669 .name = "kvm32",
670 .level = 5,
Igor Mammedov99b88a12013-01-21 15:06:36 +0100671 .vendor = CPUID_VENDOR_INTEL,
Andre Przywaraeafaf1e2010-05-21 09:50:51 +0200672 .family = 15,
673 .model = 6,
674 .stepping = 1,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300675 .features[FEAT_1_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300676 PPRO_FEATURES |
Andre Przywaraeafaf1e2010-05-21 09:50:51 +0200677 CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_PSE36,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300678 .features[FEAT_1_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300679 CPUID_EXT_SSE3,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300680 .features[FEAT_8000_0001_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300681 PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300682 .features[FEAT_8000_0001_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300683 0,
Andre Przywaraeafaf1e2010-05-21 09:50:51 +0200684 .xlevel = 0x80000008,
685 .model_id = "Common 32-bit KVM processor"
686 },
687 {
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100688 .name = "coreduo",
689 .level = 10,
Igor Mammedov99b88a12013-01-21 15:06:36 +0100690 .vendor = CPUID_VENDOR_INTEL,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100691 .family = 6,
692 .model = 14,
693 .stepping = 8,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300694 .features[FEAT_1_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300695 PPRO_FEATURES | CPUID_VME |
Aurelien Jarno8560efe2010-03-13 16:43:15 +0100696 CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_DTS | CPUID_ACPI |
697 CPUID_SS | CPUID_HT | CPUID_TM | CPUID_PBE,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300698 .features[FEAT_1_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300699 CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_VMX |
Aurelien Jarno8560efe2010-03-13 16:43:15 +0100700 CPUID_EXT_EST | CPUID_EXT_TM2 | CPUID_EXT_XTPR | CPUID_EXT_PDCM,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300701 .features[FEAT_8000_0001_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300702 CPUID_EXT2_NX,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100703 .xlevel = 0x80000008,
704 .model_id = "Genuine Intel(R) CPU T2600 @ 2.16GHz",
705 },
706 {
707 .name = "486",
Andre Przywara58012d62010-03-11 14:39:06 +0100708 .level = 1,
Igor Mammedov99b88a12013-01-21 15:06:36 +0100709 .vendor = CPUID_VENDOR_INTEL,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100710 .family = 4,
Andreas Färberb2a856d2013-05-01 17:30:51 +0200711 .model = 8,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100712 .stepping = 0,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300713 .features[FEAT_1_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300714 I486_FEATURES,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100715 .xlevel = 0,
716 },
717 {
718 .name = "pentium",
719 .level = 1,
Igor Mammedov99b88a12013-01-21 15:06:36 +0100720 .vendor = CPUID_VENDOR_INTEL,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100721 .family = 5,
722 .model = 4,
723 .stepping = 3,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300724 .features[FEAT_1_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300725 PENTIUM_FEATURES,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100726 .xlevel = 0,
727 },
728 {
729 .name = "pentium2",
730 .level = 2,
Igor Mammedov99b88a12013-01-21 15:06:36 +0100731 .vendor = CPUID_VENDOR_INTEL,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100732 .family = 6,
733 .model = 5,
734 .stepping = 2,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300735 .features[FEAT_1_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300736 PENTIUM2_FEATURES,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100737 .xlevel = 0,
738 },
739 {
740 .name = "pentium3",
741 .level = 2,
Igor Mammedov99b88a12013-01-21 15:06:36 +0100742 .vendor = CPUID_VENDOR_INTEL,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100743 .family = 6,
744 .model = 7,
745 .stepping = 3,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300746 .features[FEAT_1_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300747 PENTIUM3_FEATURES,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100748 .xlevel = 0,
749 },
750 {
751 .name = "athlon",
752 .level = 2,
Igor Mammedov99b88a12013-01-21 15:06:36 +0100753 .vendor = CPUID_VENDOR_AMD,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100754 .family = 6,
755 .model = 2,
756 .stepping = 3,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300757 .features[FEAT_1_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300758 PPRO_FEATURES | CPUID_PSE36 | CPUID_VME | CPUID_MTRR |
Eduardo Habkost60032ac2012-09-06 10:05:37 +0000759 CPUID_MCA,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300760 .features[FEAT_8000_0001_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300761 (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) |
Eduardo Habkost60032ac2012-09-06 10:05:37 +0000762 CPUID_EXT2_MMXEXT | CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100763 .xlevel = 0x80000008,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100764 },
765 {
766 .name = "n270",
767 /* original is on level 10 */
768 .level = 5,
Igor Mammedov99b88a12013-01-21 15:06:36 +0100769 .vendor = CPUID_VENDOR_INTEL,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100770 .family = 6,
771 .model = 28,
772 .stepping = 2,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300773 .features[FEAT_1_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300774 PPRO_FEATURES |
Aurelien Jarno8560efe2010-03-13 16:43:15 +0100775 CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_VME | CPUID_DTS |
776 CPUID_ACPI | CPUID_SS | CPUID_HT | CPUID_TM | CPUID_PBE,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100777 /* Some CPUs got no CPUID_SEP */
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300778 .features[FEAT_1_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300779 CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_SSSE3 |
Borislav Petkov4458c232013-04-25 15:43:04 -0300780 CPUID_EXT_DSCPL | CPUID_EXT_EST | CPUID_EXT_TM2 | CPUID_EXT_XTPR |
781 CPUID_EXT_MOVBE,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300782 .features[FEAT_8000_0001_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300783 (PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) |
Eduardo Habkost60032ac2012-09-06 10:05:37 +0000784 CPUID_EXT2_NX,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300785 .features[FEAT_8000_0001_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300786 CPUID_EXT3_LAHF_LM,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100787 .xlevel = 0x8000000A,
788 .model_id = "Intel(R) Atom(TM) CPU N270 @ 1.60GHz",
789 },
Eduardo Habkost3eca4642012-09-05 17:41:10 -0300790 {
791 .name = "Conroe",
Eduardo Habkost6b113222013-05-27 17:23:55 -0300792 .level = 4,
Igor Mammedov99b88a12013-01-21 15:06:36 +0100793 .vendor = CPUID_VENDOR_INTEL,
Eduardo Habkost3eca4642012-09-05 17:41:10 -0300794 .family = 6,
Eduardo Habkostffce9eb2013-05-27 17:23:54 -0300795 .model = 15,
Eduardo Habkost3eca4642012-09-05 17:41:10 -0300796 .stepping = 3,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300797 .features[FEAT_1_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300798 CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
Eduardo Habkost3eca4642012-09-05 17:41:10 -0300799 CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
800 CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
801 CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
802 CPUID_DE | CPUID_FP87,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300803 .features[FEAT_1_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300804 CPUID_EXT_SSSE3 | CPUID_EXT_SSE3,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300805 .features[FEAT_8000_0001_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300806 CPUID_EXT2_LM | CPUID_EXT2_NX | CPUID_EXT2_SYSCALL,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300807 .features[FEAT_8000_0001_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300808 CPUID_EXT3_LAHF_LM,
Eduardo Habkost3eca4642012-09-05 17:41:10 -0300809 .xlevel = 0x8000000A,
810 .model_id = "Intel Celeron_4x0 (Conroe/Merom Class Core 2)",
811 },
812 {
813 .name = "Penryn",
Eduardo Habkost6b113222013-05-27 17:23:55 -0300814 .level = 4,
Igor Mammedov99b88a12013-01-21 15:06:36 +0100815 .vendor = CPUID_VENDOR_INTEL,
Eduardo Habkost3eca4642012-09-05 17:41:10 -0300816 .family = 6,
Eduardo Habkostffce9eb2013-05-27 17:23:54 -0300817 .model = 23,
Eduardo Habkost3eca4642012-09-05 17:41:10 -0300818 .stepping = 3,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300819 .features[FEAT_1_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300820 CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
Eduardo Habkost3eca4642012-09-05 17:41:10 -0300821 CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
822 CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
823 CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
824 CPUID_DE | CPUID_FP87,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300825 .features[FEAT_1_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300826 CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 |
Eduardo Habkost3eca4642012-09-05 17:41:10 -0300827 CPUID_EXT_SSE3,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300828 .features[FEAT_8000_0001_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300829 CPUID_EXT2_LM | CPUID_EXT2_NX | CPUID_EXT2_SYSCALL,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300830 .features[FEAT_8000_0001_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300831 CPUID_EXT3_LAHF_LM,
Eduardo Habkost3eca4642012-09-05 17:41:10 -0300832 .xlevel = 0x8000000A,
833 .model_id = "Intel Core 2 Duo P9xxx (Penryn Class Core 2)",
834 },
835 {
836 .name = "Nehalem",
Eduardo Habkost6b113222013-05-27 17:23:55 -0300837 .level = 4,
Igor Mammedov99b88a12013-01-21 15:06:36 +0100838 .vendor = CPUID_VENDOR_INTEL,
Eduardo Habkost3eca4642012-09-05 17:41:10 -0300839 .family = 6,
Eduardo Habkostffce9eb2013-05-27 17:23:54 -0300840 .model = 26,
Eduardo Habkost3eca4642012-09-05 17:41:10 -0300841 .stepping = 3,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300842 .features[FEAT_1_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300843 CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
Eduardo Habkost3eca4642012-09-05 17:41:10 -0300844 CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
845 CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
846 CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
847 CPUID_DE | CPUID_FP87,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300848 .features[FEAT_1_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300849 CPUID_EXT_POPCNT | CPUID_EXT_SSE42 | CPUID_EXT_SSE41 |
Eduardo Habkost3eca4642012-09-05 17:41:10 -0300850 CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | CPUID_EXT_SSE3,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300851 .features[FEAT_8000_0001_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300852 CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300853 .features[FEAT_8000_0001_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300854 CPUID_EXT3_LAHF_LM,
Eduardo Habkost3eca4642012-09-05 17:41:10 -0300855 .xlevel = 0x8000000A,
856 .model_id = "Intel Core i7 9xx (Nehalem Class Core i7)",
857 },
858 {
859 .name = "Westmere",
860 .level = 11,
Igor Mammedov99b88a12013-01-21 15:06:36 +0100861 .vendor = CPUID_VENDOR_INTEL,
Eduardo Habkost3eca4642012-09-05 17:41:10 -0300862 .family = 6,
863 .model = 44,
864 .stepping = 1,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300865 .features[FEAT_1_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300866 CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
Eduardo Habkost3eca4642012-09-05 17:41:10 -0300867 CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
868 CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
869 CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
870 CPUID_DE | CPUID_FP87,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300871 .features[FEAT_1_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300872 CPUID_EXT_AES | CPUID_EXT_POPCNT | CPUID_EXT_SSE42 |
Eduardo Habkost3eca4642012-09-05 17:41:10 -0300873 CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 |
Aurelien Jarno41cb3832013-03-31 12:58:30 +0200874 CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300875 .features[FEAT_8000_0001_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300876 CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300877 .features[FEAT_8000_0001_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300878 CPUID_EXT3_LAHF_LM,
Eduardo Habkost3eca4642012-09-05 17:41:10 -0300879 .xlevel = 0x8000000A,
880 .model_id = "Westmere E56xx/L56xx/X56xx (Nehalem-C)",
881 },
882 {
883 .name = "SandyBridge",
884 .level = 0xd,
Igor Mammedov99b88a12013-01-21 15:06:36 +0100885 .vendor = CPUID_VENDOR_INTEL,
Eduardo Habkost3eca4642012-09-05 17:41:10 -0300886 .family = 6,
887 .model = 42,
888 .stepping = 1,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300889 .features[FEAT_1_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300890 CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
Eduardo Habkost3eca4642012-09-05 17:41:10 -0300891 CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
892 CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
893 CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
894 CPUID_DE | CPUID_FP87,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300895 .features[FEAT_1_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300896 CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES |
Eduardo Habkost3eca4642012-09-05 17:41:10 -0300897 CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_POPCNT |
898 CPUID_EXT_X2APIC | CPUID_EXT_SSE42 | CPUID_EXT_SSE41 |
899 CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | CPUID_EXT_PCLMULQDQ |
900 CPUID_EXT_SSE3,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300901 .features[FEAT_8000_0001_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300902 CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX |
Eduardo Habkost3eca4642012-09-05 17:41:10 -0300903 CPUID_EXT2_SYSCALL,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300904 .features[FEAT_8000_0001_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300905 CPUID_EXT3_LAHF_LM,
Eduardo Habkost3eca4642012-09-05 17:41:10 -0300906 .xlevel = 0x8000000A,
907 .model_id = "Intel Xeon E312xx (Sandy Bridge)",
908 },
909 {
Eduardo Habkost37507092012-11-14 16:28:54 -0200910 .name = "Haswell",
911 .level = 0xd,
Igor Mammedov99b88a12013-01-21 15:06:36 +0100912 .vendor = CPUID_VENDOR_INTEL,
Eduardo Habkost37507092012-11-14 16:28:54 -0200913 .family = 6,
914 .model = 60,
915 .stepping = 1,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300916 .features[FEAT_1_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300917 CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
Eduardo Habkost37507092012-11-14 16:28:54 -0200918 CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
Eduardo Habkost80ae4162012-11-22 13:31:03 -0200919 CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
Eduardo Habkost37507092012-11-14 16:28:54 -0200920 CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
921 CPUID_DE | CPUID_FP87,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300922 .features[FEAT_1_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300923 CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES |
Eduardo Habkost37507092012-11-14 16:28:54 -0200924 CPUID_EXT_POPCNT | CPUID_EXT_X2APIC | CPUID_EXT_SSE42 |
925 CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 |
926 CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3 |
927 CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_FMA | CPUID_EXT_MOVBE |
928 CPUID_EXT_PCID,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300929 .features[FEAT_8000_0001_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300930 CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX |
Eduardo Habkost80ae4162012-11-22 13:31:03 -0200931 CPUID_EXT2_SYSCALL,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300932 .features[FEAT_8000_0001_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300933 CPUID_EXT3_LAHF_LM,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300934 .features[FEAT_7_0_EBX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300935 CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 |
Eduardo Habkost37507092012-11-14 16:28:54 -0200936 CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP |
937 CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID |
938 CPUID_7_0_EBX_RTM,
939 .xlevel = 0x8000000A,
940 .model_id = "Intel Core Processor (Haswell)",
941 },
942 {
Eduardo Habkost3eca4642012-09-05 17:41:10 -0300943 .name = "Opteron_G1",
944 .level = 5,
Igor Mammedov99b88a12013-01-21 15:06:36 +0100945 .vendor = CPUID_VENDOR_AMD,
Eduardo Habkost3eca4642012-09-05 17:41:10 -0300946 .family = 15,
947 .model = 6,
948 .stepping = 1,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300949 .features[FEAT_1_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300950 CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
Eduardo Habkost3eca4642012-09-05 17:41:10 -0300951 CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
952 CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
953 CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
954 CPUID_DE | CPUID_FP87,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300955 .features[FEAT_1_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300956 CPUID_EXT_SSE3,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300957 .features[FEAT_8000_0001_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300958 CPUID_EXT2_LM | CPUID_EXT2_FXSR | CPUID_EXT2_MMX |
Eduardo Habkost3eca4642012-09-05 17:41:10 -0300959 CPUID_EXT2_NX | CPUID_EXT2_PSE36 | CPUID_EXT2_PAT |
960 CPUID_EXT2_CMOV | CPUID_EXT2_MCA | CPUID_EXT2_PGE |
961 CPUID_EXT2_MTRR | CPUID_EXT2_SYSCALL | CPUID_EXT2_APIC |
962 CPUID_EXT2_CX8 | CPUID_EXT2_MCE | CPUID_EXT2_PAE | CPUID_EXT2_MSR |
963 CPUID_EXT2_TSC | CPUID_EXT2_PSE | CPUID_EXT2_DE | CPUID_EXT2_FPU,
964 .xlevel = 0x80000008,
965 .model_id = "AMD Opteron 240 (Gen 1 Class Opteron)",
966 },
967 {
968 .name = "Opteron_G2",
969 .level = 5,
Igor Mammedov99b88a12013-01-21 15:06:36 +0100970 .vendor = CPUID_VENDOR_AMD,
Eduardo Habkost3eca4642012-09-05 17:41:10 -0300971 .family = 15,
972 .model = 6,
973 .stepping = 1,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300974 .features[FEAT_1_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300975 CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
Eduardo Habkost3eca4642012-09-05 17:41:10 -0300976 CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
977 CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
978 CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
979 CPUID_DE | CPUID_FP87,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300980 .features[FEAT_1_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300981 CPUID_EXT_CX16 | CPUID_EXT_SSE3,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300982 .features[FEAT_8000_0001_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300983 CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_FXSR |
Eduardo Habkost3eca4642012-09-05 17:41:10 -0300984 CPUID_EXT2_MMX | CPUID_EXT2_NX | CPUID_EXT2_PSE36 |
985 CPUID_EXT2_PAT | CPUID_EXT2_CMOV | CPUID_EXT2_MCA |
986 CPUID_EXT2_PGE | CPUID_EXT2_MTRR | CPUID_EXT2_SYSCALL |
987 CPUID_EXT2_APIC | CPUID_EXT2_CX8 | CPUID_EXT2_MCE |
988 CPUID_EXT2_PAE | CPUID_EXT2_MSR | CPUID_EXT2_TSC | CPUID_EXT2_PSE |
989 CPUID_EXT2_DE | CPUID_EXT2_FPU,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300990 .features[FEAT_8000_0001_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300991 CPUID_EXT3_SVM | CPUID_EXT3_LAHF_LM,
Eduardo Habkost3eca4642012-09-05 17:41:10 -0300992 .xlevel = 0x80000008,
993 .model_id = "AMD Opteron 22xx (Gen 2 Class Opteron)",
994 },
995 {
996 .name = "Opteron_G3",
997 .level = 5,
Igor Mammedov99b88a12013-01-21 15:06:36 +0100998 .vendor = CPUID_VENDOR_AMD,
Eduardo Habkost3eca4642012-09-05 17:41:10 -0300999 .family = 15,
1000 .model = 6,
1001 .stepping = 1,
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001002 .features[FEAT_1_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -03001003 CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
Eduardo Habkost3eca4642012-09-05 17:41:10 -03001004 CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
1005 CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
1006 CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
1007 CPUID_DE | CPUID_FP87,
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001008 .features[FEAT_1_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -03001009 CPUID_EXT_POPCNT | CPUID_EXT_CX16 | CPUID_EXT_MONITOR |
Eduardo Habkost3eca4642012-09-05 17:41:10 -03001010 CPUID_EXT_SSE3,
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001011 .features[FEAT_8000_0001_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -03001012 CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_FXSR |
Eduardo Habkost3eca4642012-09-05 17:41:10 -03001013 CPUID_EXT2_MMX | CPUID_EXT2_NX | CPUID_EXT2_PSE36 |
1014 CPUID_EXT2_PAT | CPUID_EXT2_CMOV | CPUID_EXT2_MCA |
1015 CPUID_EXT2_PGE | CPUID_EXT2_MTRR | CPUID_EXT2_SYSCALL |
1016 CPUID_EXT2_APIC | CPUID_EXT2_CX8 | CPUID_EXT2_MCE |
1017 CPUID_EXT2_PAE | CPUID_EXT2_MSR | CPUID_EXT2_TSC | CPUID_EXT2_PSE |
1018 CPUID_EXT2_DE | CPUID_EXT2_FPU,
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001019 .features[FEAT_8000_0001_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -03001020 CPUID_EXT3_MISALIGNSSE | CPUID_EXT3_SSE4A |
Eduardo Habkost3eca4642012-09-05 17:41:10 -03001021 CPUID_EXT3_ABM | CPUID_EXT3_SVM | CPUID_EXT3_LAHF_LM,
1022 .xlevel = 0x80000008,
1023 .model_id = "AMD Opteron 23xx (Gen 3 Class Opteron)",
1024 },
1025 {
1026 .name = "Opteron_G4",
1027 .level = 0xd,
Igor Mammedov99b88a12013-01-21 15:06:36 +01001028 .vendor = CPUID_VENDOR_AMD,
Eduardo Habkost3eca4642012-09-05 17:41:10 -03001029 .family = 21,
1030 .model = 1,
1031 .stepping = 2,
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001032 .features[FEAT_1_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -03001033 CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
Eduardo Habkost3eca4642012-09-05 17:41:10 -03001034 CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
1035 CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
1036 CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
1037 CPUID_DE | CPUID_FP87,
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001038 .features[FEAT_1_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -03001039 CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES |
Eduardo Habkost3eca4642012-09-05 17:41:10 -03001040 CPUID_EXT_POPCNT | CPUID_EXT_SSE42 | CPUID_EXT_SSE41 |
1041 CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | CPUID_EXT_PCLMULQDQ |
1042 CPUID_EXT_SSE3,
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001043 .features[FEAT_8000_0001_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -03001044 CPUID_EXT2_LM | CPUID_EXT2_RDTSCP |
Eduardo Habkost3eca4642012-09-05 17:41:10 -03001045 CPUID_EXT2_PDPE1GB | CPUID_EXT2_FXSR | CPUID_EXT2_MMX |
1046 CPUID_EXT2_NX | CPUID_EXT2_PSE36 | CPUID_EXT2_PAT |
1047 CPUID_EXT2_CMOV | CPUID_EXT2_MCA | CPUID_EXT2_PGE |
1048 CPUID_EXT2_MTRR | CPUID_EXT2_SYSCALL | CPUID_EXT2_APIC |
1049 CPUID_EXT2_CX8 | CPUID_EXT2_MCE | CPUID_EXT2_PAE | CPUID_EXT2_MSR |
1050 CPUID_EXT2_TSC | CPUID_EXT2_PSE | CPUID_EXT2_DE | CPUID_EXT2_FPU,
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001051 .features[FEAT_8000_0001_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -03001052 CPUID_EXT3_FMA4 | CPUID_EXT3_XOP |
Eduardo Habkost3eca4642012-09-05 17:41:10 -03001053 CPUID_EXT3_3DNOWPREFETCH | CPUID_EXT3_MISALIGNSSE |
1054 CPUID_EXT3_SSE4A | CPUID_EXT3_ABM | CPUID_EXT3_SVM |
1055 CPUID_EXT3_LAHF_LM,
1056 .xlevel = 0x8000001A,
1057 .model_id = "AMD Opteron 62xx class CPU",
1058 },
Andre Przywara021941b2012-11-14 16:28:53 -02001059 {
1060 .name = "Opteron_G5",
1061 .level = 0xd,
Igor Mammedov99b88a12013-01-21 15:06:36 +01001062 .vendor = CPUID_VENDOR_AMD,
Andre Przywara021941b2012-11-14 16:28:53 -02001063 .family = 21,
1064 .model = 2,
1065 .stepping = 0,
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001066 .features[FEAT_1_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -03001067 CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
Andre Przywara021941b2012-11-14 16:28:53 -02001068 CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
1069 CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
1070 CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
1071 CPUID_DE | CPUID_FP87,
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001072 .features[FEAT_1_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -03001073 CPUID_EXT_F16C | CPUID_EXT_AVX | CPUID_EXT_XSAVE |
Andre Przywara021941b2012-11-14 16:28:53 -02001074 CPUID_EXT_AES | CPUID_EXT_POPCNT | CPUID_EXT_SSE42 |
1075 CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_FMA |
1076 CPUID_EXT_SSSE3 | CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3,
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001077 .features[FEAT_8000_0001_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -03001078 CPUID_EXT2_LM | CPUID_EXT2_RDTSCP |
Andre Przywara021941b2012-11-14 16:28:53 -02001079 CPUID_EXT2_PDPE1GB | CPUID_EXT2_FXSR | CPUID_EXT2_MMX |
1080 CPUID_EXT2_NX | CPUID_EXT2_PSE36 | CPUID_EXT2_PAT |
1081 CPUID_EXT2_CMOV | CPUID_EXT2_MCA | CPUID_EXT2_PGE |
1082 CPUID_EXT2_MTRR | CPUID_EXT2_SYSCALL | CPUID_EXT2_APIC |
1083 CPUID_EXT2_CX8 | CPUID_EXT2_MCE | CPUID_EXT2_PAE | CPUID_EXT2_MSR |
1084 CPUID_EXT2_TSC | CPUID_EXT2_PSE | CPUID_EXT2_DE | CPUID_EXT2_FPU,
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001085 .features[FEAT_8000_0001_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -03001086 CPUID_EXT3_TBM | CPUID_EXT3_FMA4 | CPUID_EXT3_XOP |
Andre Przywara021941b2012-11-14 16:28:53 -02001087 CPUID_EXT3_3DNOWPREFETCH | CPUID_EXT3_MISALIGNSSE |
1088 CPUID_EXT3_SSE4A | CPUID_EXT3_ABM | CPUID_EXT3_SVM |
1089 CPUID_EXT3_LAHF_LM,
1090 .xlevel = 0x8000001A,
1091 .model_id = "AMD Opteron 63xx class CPU",
1092 },
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001093};
1094
Eduardo Habkost0668af52013-04-25 15:43:00 -03001095/**
1096 * x86_cpu_compat_set_features:
1097 * @cpu_model: CPU model name to be changed. If NULL, all CPU models are changed
1098 * @w: Identifies the feature word to be changed.
1099 * @feat_add: Feature bits to be added to feature word
1100 * @feat_remove: Feature bits to be removed from feature word
1101 *
1102 * Change CPU model feature bits for compatibility.
1103 *
1104 * This function may be used by machine-type compatibility functions
1105 * to enable or disable feature bits on specific CPU models.
1106 */
1107void x86_cpu_compat_set_features(const char *cpu_model, FeatureWord w,
1108 uint32_t feat_add, uint32_t feat_remove)
1109{
1110 x86_def_t *def;
1111 int i;
1112 for (i = 0; i < ARRAY_SIZE(builtin_x86_defs); i++) {
1113 def = &builtin_x86_defs[i];
1114 if (!cpu_model || !strcmp(cpu_model, def->name)) {
1115 def->features[w] |= feat_add;
1116 def->features[w] &= ~feat_remove;
1117 }
1118 }
1119}
1120
Eduardo Habkoste4ab0d62012-11-02 14:25:15 -02001121#ifdef CONFIG_KVM
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001122static int cpu_x86_fill_model_id(char *str)
1123{
1124 uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
1125 int i;
1126
1127 for (i = 0; i < 3; i++) {
1128 host_cpuid(0x80000002 + i, 0, &eax, &ebx, &ecx, &edx);
1129 memcpy(str + i * 16 + 0, &eax, 4);
1130 memcpy(str + i * 16 + 4, &ebx, 4);
1131 memcpy(str + i * 16 + 8, &ecx, 4);
1132 memcpy(str + i * 16 + 12, &edx, 4);
1133 }
1134 return 0;
1135}
Eduardo Habkoste4ab0d62012-11-02 14:25:15 -02001136#endif
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001137
Eduardo Habkost6e746f32012-10-24 19:44:06 -02001138/* Fill a x86_def_t struct with information about the host CPU, and
1139 * the CPU features supported by the host hardware + host kernel
1140 *
1141 * This function may be called only if KVM is enabled.
1142 */
1143static void kvm_cpu_fill_host(x86_def_t *x86_cpu_def)
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001144{
Eduardo Habkoste4ab0d62012-11-02 14:25:15 -02001145#ifdef CONFIG_KVM
Eduardo Habkost12869992012-10-24 19:44:07 -02001146 KVMState *s = kvm_state;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001147 uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
1148
Eduardo Habkost6e746f32012-10-24 19:44:06 -02001149 assert(kvm_enabled());
1150
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001151 x86_cpu_def->name = "host";
Benoît Canet787aaf52013-09-02 17:06:37 +02001152 x86_cpu_def->cache_info_passthrough = true;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001153 host_cpuid(0x0, 0, &eax, &ebx, &ecx, &edx);
Igor Mammedov99b88a12013-01-21 15:06:36 +01001154 x86_cpu_vendor_words2str(x86_cpu_def->vendor, ebx, edx, ecx);
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001155
1156 host_cpuid(0x1, 0, &eax, &ebx, &ecx, &edx);
1157 x86_cpu_def->family = ((eax >> 8) & 0x0F) + ((eax >> 20) & 0xFF);
1158 x86_cpu_def->model = ((eax >> 4) & 0x0F) | ((eax & 0xF0000) >> 12);
1159 x86_cpu_def->stepping = eax & 0x0F;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001160
Eduardo Habkost12869992012-10-24 19:44:07 -02001161 x86_cpu_def->level = kvm_arch_get_supported_cpuid(s, 0x0, 0, R_EAX);
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001162 x86_cpu_def->features[FEAT_1_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -03001163 kvm_arch_get_supported_cpuid(s, 0x1, 0, R_EDX);
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001164 x86_cpu_def->features[FEAT_1_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -03001165 kvm_arch_get_supported_cpuid(s, 0x1, 0, R_ECX);
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001166
Eduardo Habkost6e746f32012-10-24 19:44:06 -02001167 if (x86_cpu_def->level >= 7) {
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001168 x86_cpu_def->features[FEAT_7_0_EBX] =
Eduardo Habkost12869992012-10-24 19:44:07 -02001169 kvm_arch_get_supported_cpuid(s, 0x7, 0, R_EBX);
Eduardo Habkost13526722012-05-21 11:27:02 -03001170 } else {
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001171 x86_cpu_def->features[FEAT_7_0_EBX] = 0;
Eduardo Habkost13526722012-05-21 11:27:02 -03001172 }
1173
Eduardo Habkost12869992012-10-24 19:44:07 -02001174 x86_cpu_def->xlevel = kvm_arch_get_supported_cpuid(s, 0x80000000, 0, R_EAX);
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001175 x86_cpu_def->features[FEAT_8000_0001_EDX] =
Eduardo Habkost12869992012-10-24 19:44:07 -02001176 kvm_arch_get_supported_cpuid(s, 0x80000001, 0, R_EDX);
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001177 x86_cpu_def->features[FEAT_8000_0001_ECX] =
Eduardo Habkost12869992012-10-24 19:44:07 -02001178 kvm_arch_get_supported_cpuid(s, 0x80000001, 0, R_ECX);
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001179
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001180 cpu_x86_fill_model_id(x86_cpu_def->model_id);
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001181
brillywu@viatech.com.cnb3baa152011-06-01 09:59:52 +08001182 /* Call Centaur's CPUID instruction. */
Igor Mammedov99b88a12013-01-21 15:06:36 +01001183 if (!strcmp(x86_cpu_def->vendor, CPUID_VENDOR_VIA)) {
brillywu@viatech.com.cnb3baa152011-06-01 09:59:52 +08001184 host_cpuid(0xC0000000, 0, &eax, &ebx, &ecx, &edx);
Eduardo Habkost12869992012-10-24 19:44:07 -02001185 eax = kvm_arch_get_supported_cpuid(s, 0xC0000000, 0, R_EAX);
brillywu@viatech.com.cnb3baa152011-06-01 09:59:52 +08001186 if (eax >= 0xC0000001) {
1187 /* Support VIA max extended level */
1188 x86_cpu_def->xlevel2 = eax;
1189 host_cpuid(0xC0000001, 0, &eax, &ebx, &ecx, &edx);
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001190 x86_cpu_def->features[FEAT_C000_0001_EDX] =
Eduardo Habkost12869992012-10-24 19:44:07 -02001191 kvm_arch_get_supported_cpuid(s, 0xC0000001, 0, R_EDX);
brillywu@viatech.com.cnb3baa152011-06-01 09:59:52 +08001192 }
1193 }
Joerg Roedel296acb62010-09-27 15:16:17 +02001194
Eduardo Habkostfcb93c02013-01-04 20:01:04 -02001195 /* Other KVM-specific feature fields: */
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001196 x86_cpu_def->features[FEAT_SVM] =
Eduardo Habkostfcb93c02013-01-04 20:01:04 -02001197 kvm_arch_get_supported_cpuid(s, 0x8000000A, 0, R_EDX);
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001198 x86_cpu_def->features[FEAT_KVM] =
Eduardo Habkostbd004be2013-01-04 20:01:05 -02001199 kvm_arch_get_supported_cpuid(s, KVM_CPUID_FEATURES, 0, R_EAX);
Eduardo Habkostfcb93c02013-01-04 20:01:04 -02001200
Eduardo Habkoste4ab0d62012-11-02 14:25:15 -02001201#endif /* CONFIG_KVM */
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001202}
1203
Eduardo Habkostbffd67b2013-01-07 16:20:46 -02001204static int unavailable_host_feature(FeatureWordInfo *f, uint32_t mask)
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001205{
1206 int i;
1207
1208 for (i = 0; i < 32; ++i)
1209 if (1 << i & mask) {
Eduardo Habkostbffd67b2013-01-07 16:20:46 -02001210 const char *reg = get_register_name_32(f->cpuid_reg);
Eduardo Habkost8b4bedd2013-01-04 20:01:06 -02001211 assert(reg);
1212 fprintf(stderr, "warning: host doesn't support requested feature: "
1213 "CPUID.%02XH:%s%s%s [bit %d]\n",
Eduardo Habkostbffd67b2013-01-07 16:20:46 -02001214 f->cpuid_eax, reg,
1215 f->feat_names[i] ? "." : "",
1216 f->feat_names[i] ? f->feat_names[i] : "", i);
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001217 break;
1218 }
1219 return 0;
1220}
1221
Eduardo Habkost07ca5942013-01-07 16:20:48 -02001222/* Check if all requested cpu flags are making their way to the guest
1223 *
1224 * Returns 0 if all flags are supported by the host, non-zero otherwise.
Eduardo Habkost6e746f32012-10-24 19:44:06 -02001225 *
1226 * This function may be called only if KVM is enabled.
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001227 */
Igor Mammedov5ec01c22013-01-11 03:10:17 +01001228static int kvm_check_features_against_host(X86CPU *cpu)
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001229{
Igor Mammedov5ec01c22013-01-11 03:10:17 +01001230 CPUX86State *env = &cpu->env;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001231 x86_def_t host_def;
1232 uint32_t mask;
1233 int rv, i;
1234 struct model_features_t ft[] = {
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001235 {&env->features[FEAT_1_EDX],
1236 &host_def.features[FEAT_1_EDX],
Eduardo Habkostbffd67b2013-01-07 16:20:46 -02001237 FEAT_1_EDX },
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001238 {&env->features[FEAT_1_ECX],
1239 &host_def.features[FEAT_1_ECX],
Eduardo Habkostbffd67b2013-01-07 16:20:46 -02001240 FEAT_1_ECX },
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001241 {&env->features[FEAT_8000_0001_EDX],
1242 &host_def.features[FEAT_8000_0001_EDX],
Eduardo Habkostbffd67b2013-01-07 16:20:46 -02001243 FEAT_8000_0001_EDX },
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001244 {&env->features[FEAT_8000_0001_ECX],
1245 &host_def.features[FEAT_8000_0001_ECX],
Eduardo Habkostbffd67b2013-01-07 16:20:46 -02001246 FEAT_8000_0001_ECX },
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001247 {&env->features[FEAT_C000_0001_EDX],
1248 &host_def.features[FEAT_C000_0001_EDX],
Eduardo Habkost07ca5942013-01-07 16:20:48 -02001249 FEAT_C000_0001_EDX },
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001250 {&env->features[FEAT_7_0_EBX],
1251 &host_def.features[FEAT_7_0_EBX],
Eduardo Habkost07ca5942013-01-07 16:20:48 -02001252 FEAT_7_0_EBX },
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001253 {&env->features[FEAT_SVM],
1254 &host_def.features[FEAT_SVM],
Eduardo Habkost07ca5942013-01-07 16:20:48 -02001255 FEAT_SVM },
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001256 {&env->features[FEAT_KVM],
1257 &host_def.features[FEAT_KVM],
Eduardo Habkost07ca5942013-01-07 16:20:48 -02001258 FEAT_KVM },
Eduardo Habkost8b4bedd2013-01-04 20:01:06 -02001259 };
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001260
Eduardo Habkost6e746f32012-10-24 19:44:06 -02001261 assert(kvm_enabled());
1262
1263 kvm_cpu_fill_host(&host_def);
Eduardo Habkostbffd67b2013-01-07 16:20:46 -02001264 for (rv = 0, i = 0; i < ARRAY_SIZE(ft); ++i) {
1265 FeatureWord w = ft[i].feat_word;
1266 FeatureWordInfo *wi = &feature_word_info[w];
1267 for (mask = 1; mask; mask <<= 1) {
Eduardo Habkoste8beac02013-01-04 20:01:10 -02001268 if (*ft[i].guest_feat & mask &&
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001269 !(*ft[i].host_feat & mask)) {
Eduardo Habkostbffd67b2013-01-07 16:20:46 -02001270 unavailable_host_feature(wi, mask);
1271 rv = 1;
1272 }
1273 }
1274 }
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001275 return rv;
1276}
1277
Andreas Färber95b85192012-04-17 14:42:22 +02001278static void x86_cpuid_version_get_family(Object *obj, Visitor *v, void *opaque,
1279 const char *name, Error **errp)
1280{
1281 X86CPU *cpu = X86_CPU(obj);
1282 CPUX86State *env = &cpu->env;
1283 int64_t value;
1284
1285 value = (env->cpuid_version >> 8) & 0xf;
1286 if (value == 0xf) {
1287 value += (env->cpuid_version >> 20) & 0xff;
1288 }
1289 visit_type_int(v, &value, name, errp);
1290}
1291
Andreas Färber71ad61d2012-04-17 12:10:29 +02001292static void x86_cpuid_version_set_family(Object *obj, Visitor *v, void *opaque,
1293 const char *name, Error **errp)
Andreas Färbered5e1ec2012-02-17 17:46:01 +01001294{
Andreas Färber71ad61d2012-04-17 12:10:29 +02001295 X86CPU *cpu = X86_CPU(obj);
1296 CPUX86State *env = &cpu->env;
1297 const int64_t min = 0;
1298 const int64_t max = 0xff + 0xf;
1299 int64_t value;
1300
1301 visit_type_int(v, &value, name, errp);
1302 if (error_is_set(errp)) {
1303 return;
1304 }
1305 if (value < min || value > max) {
1306 error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE, "",
1307 name ? name : "null", value, min, max);
1308 return;
1309 }
1310
Andreas Färbered5e1ec2012-02-17 17:46:01 +01001311 env->cpuid_version &= ~0xff00f00;
Andreas Färber71ad61d2012-04-17 12:10:29 +02001312 if (value > 0x0f) {
1313 env->cpuid_version |= 0xf00 | ((value - 0x0f) << 20);
Andreas Färbered5e1ec2012-02-17 17:46:01 +01001314 } else {
Andreas Färber71ad61d2012-04-17 12:10:29 +02001315 env->cpuid_version |= value << 8;
Andreas Färbered5e1ec2012-02-17 17:46:01 +01001316 }
1317}
1318
Andreas Färber67e30c82012-04-17 14:48:14 +02001319static void x86_cpuid_version_get_model(Object *obj, Visitor *v, void *opaque,
1320 const char *name, Error **errp)
1321{
1322 X86CPU *cpu = X86_CPU(obj);
1323 CPUX86State *env = &cpu->env;
1324 int64_t value;
1325
1326 value = (env->cpuid_version >> 4) & 0xf;
1327 value |= ((env->cpuid_version >> 16) & 0xf) << 4;
1328 visit_type_int(v, &value, name, errp);
1329}
1330
Andreas Färberc5291a42012-04-17 12:16:39 +02001331static void x86_cpuid_version_set_model(Object *obj, Visitor *v, void *opaque,
1332 const char *name, Error **errp)
Andreas Färberb0704cb2012-02-17 17:46:02 +01001333{
Andreas Färberc5291a42012-04-17 12:16:39 +02001334 X86CPU *cpu = X86_CPU(obj);
1335 CPUX86State *env = &cpu->env;
1336 const int64_t min = 0;
1337 const int64_t max = 0xff;
1338 int64_t value;
1339
1340 visit_type_int(v, &value, name, errp);
1341 if (error_is_set(errp)) {
1342 return;
1343 }
1344 if (value < min || value > max) {
1345 error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE, "",
1346 name ? name : "null", value, min, max);
1347 return;
1348 }
1349
Andreas Färberb0704cb2012-02-17 17:46:02 +01001350 env->cpuid_version &= ~0xf00f0;
Andreas Färberc5291a42012-04-17 12:16:39 +02001351 env->cpuid_version |= ((value & 0xf) << 4) | ((value >> 4) << 16);
Andreas Färberb0704cb2012-02-17 17:46:02 +01001352}
1353
Andreas Färber35112e42012-04-17 14:50:53 +02001354static void x86_cpuid_version_get_stepping(Object *obj, Visitor *v,
1355 void *opaque, const char *name,
1356 Error **errp)
1357{
1358 X86CPU *cpu = X86_CPU(obj);
1359 CPUX86State *env = &cpu->env;
1360 int64_t value;
1361
1362 value = env->cpuid_version & 0xf;
1363 visit_type_int(v, &value, name, errp);
1364}
1365
Andreas Färber036e2222012-04-17 14:14:18 +02001366static void x86_cpuid_version_set_stepping(Object *obj, Visitor *v,
1367 void *opaque, const char *name,
1368 Error **errp)
Andreas Färber38c3dc42012-02-17 17:46:03 +01001369{
Andreas Färber036e2222012-04-17 14:14:18 +02001370 X86CPU *cpu = X86_CPU(obj);
1371 CPUX86State *env = &cpu->env;
1372 const int64_t min = 0;
1373 const int64_t max = 0xf;
1374 int64_t value;
1375
1376 visit_type_int(v, &value, name, errp);
1377 if (error_is_set(errp)) {
1378 return;
1379 }
1380 if (value < min || value > max) {
1381 error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE, "",
1382 name ? name : "null", value, min, max);
1383 return;
1384 }
1385
Andreas Färber38c3dc42012-02-17 17:46:03 +01001386 env->cpuid_version &= ~0xf;
Andreas Färber036e2222012-04-17 14:14:18 +02001387 env->cpuid_version |= value & 0xf;
Andreas Färber38c3dc42012-02-17 17:46:03 +01001388}
1389
Andreas Färber8e1898b2012-04-17 18:41:40 +02001390static void x86_cpuid_get_level(Object *obj, Visitor *v, void *opaque,
1391 const char *name, Error **errp)
1392{
1393 X86CPU *cpu = X86_CPU(obj);
Andreas Färber8e1898b2012-04-17 18:41:40 +02001394
Andreas Färberfa029882012-05-01 23:33:13 +02001395 visit_type_uint32(v, &cpu->env.cpuid_level, name, errp);
Andreas Färber8e1898b2012-04-17 18:41:40 +02001396}
1397
1398static void x86_cpuid_set_level(Object *obj, Visitor *v, void *opaque,
1399 const char *name, Error **errp)
1400{
1401 X86CPU *cpu = X86_CPU(obj);
Andreas Färber8e1898b2012-04-17 18:41:40 +02001402
Andreas Färberfa029882012-05-01 23:33:13 +02001403 visit_type_uint32(v, &cpu->env.cpuid_level, name, errp);
Andreas Färber8e1898b2012-04-17 18:41:40 +02001404}
1405
Andreas Färber16b93aa2012-04-17 18:44:07 +02001406static void x86_cpuid_get_xlevel(Object *obj, Visitor *v, void *opaque,
1407 const char *name, Error **errp)
1408{
1409 X86CPU *cpu = X86_CPU(obj);
Andreas Färber16b93aa2012-04-17 18:44:07 +02001410
Andreas Färberfa029882012-05-01 23:33:13 +02001411 visit_type_uint32(v, &cpu->env.cpuid_xlevel, name, errp);
Andreas Färber16b93aa2012-04-17 18:44:07 +02001412}
1413
1414static void x86_cpuid_set_xlevel(Object *obj, Visitor *v, void *opaque,
1415 const char *name, Error **errp)
1416{
1417 X86CPU *cpu = X86_CPU(obj);
Andreas Färber16b93aa2012-04-17 18:44:07 +02001418
Andreas Färberfa029882012-05-01 23:33:13 +02001419 visit_type_uint32(v, &cpu->env.cpuid_xlevel, name, errp);
Andreas Färber16b93aa2012-04-17 18:44:07 +02001420}
1421
Andreas Färberd480e1a2012-04-17 19:22:58 +02001422static char *x86_cpuid_get_vendor(Object *obj, Error **errp)
1423{
1424 X86CPU *cpu = X86_CPU(obj);
1425 CPUX86State *env = &cpu->env;
1426 char *value;
Andreas Färberd480e1a2012-04-17 19:22:58 +02001427
Igor Mammedov9df694e2012-10-22 17:03:10 +02001428 value = (char *)g_malloc(CPUID_VENDOR_SZ + 1);
Igor Mammedov99b88a12013-01-21 15:06:36 +01001429 x86_cpu_vendor_words2str(value, env->cpuid_vendor1, env->cpuid_vendor2,
1430 env->cpuid_vendor3);
Andreas Färberd480e1a2012-04-17 19:22:58 +02001431 return value;
1432}
1433
1434static void x86_cpuid_set_vendor(Object *obj, const char *value,
1435 Error **errp)
1436{
1437 X86CPU *cpu = X86_CPU(obj);
1438 CPUX86State *env = &cpu->env;
1439 int i;
1440
Igor Mammedov9df694e2012-10-22 17:03:10 +02001441 if (strlen(value) != CPUID_VENDOR_SZ) {
Andreas Färberd480e1a2012-04-17 19:22:58 +02001442 error_set(errp, QERR_PROPERTY_VALUE_BAD, "",
1443 "vendor", value);
1444 return;
1445 }
1446
1447 env->cpuid_vendor1 = 0;
1448 env->cpuid_vendor2 = 0;
1449 env->cpuid_vendor3 = 0;
1450 for (i = 0; i < 4; i++) {
1451 env->cpuid_vendor1 |= ((uint8_t)value[i ]) << (8 * i);
1452 env->cpuid_vendor2 |= ((uint8_t)value[i + 4]) << (8 * i);
1453 env->cpuid_vendor3 |= ((uint8_t)value[i + 8]) << (8 * i);
1454 }
Andreas Färberd480e1a2012-04-17 19:22:58 +02001455}
1456
Andreas Färber63e886e2012-04-17 23:02:26 +02001457static char *x86_cpuid_get_model_id(Object *obj, Error **errp)
1458{
1459 X86CPU *cpu = X86_CPU(obj);
1460 CPUX86State *env = &cpu->env;
1461 char *value;
1462 int i;
1463
1464 value = g_malloc(48 + 1);
1465 for (i = 0; i < 48; i++) {
1466 value[i] = env->cpuid_model[i >> 2] >> (8 * (i & 3));
1467 }
1468 value[48] = '\0';
1469 return value;
1470}
1471
Andreas Färber938d4c22012-04-17 15:17:27 +02001472static void x86_cpuid_set_model_id(Object *obj, const char *model_id,
1473 Error **errp)
Andreas Färberdcce6672012-02-17 17:46:04 +01001474{
Andreas Färber938d4c22012-04-17 15:17:27 +02001475 X86CPU *cpu = X86_CPU(obj);
1476 CPUX86State *env = &cpu->env;
Andreas Färberdcce6672012-02-17 17:46:04 +01001477 int c, len, i;
1478
1479 if (model_id == NULL) {
1480 model_id = "";
1481 }
1482 len = strlen(model_id);
Andreas Färberd0a6acf2012-04-17 18:21:52 +02001483 memset(env->cpuid_model, 0, 48);
Andreas Färberdcce6672012-02-17 17:46:04 +01001484 for (i = 0; i < 48; i++) {
1485 if (i >= len) {
1486 c = '\0';
1487 } else {
1488 c = (uint8_t)model_id[i];
1489 }
1490 env->cpuid_model[i >> 2] |= c << (8 * (i & 3));
1491 }
1492}
1493
Andreas Färber89e48962012-04-18 00:12:23 +02001494static void x86_cpuid_get_tsc_freq(Object *obj, Visitor *v, void *opaque,
1495 const char *name, Error **errp)
1496{
1497 X86CPU *cpu = X86_CPU(obj);
1498 int64_t value;
1499
1500 value = cpu->env.tsc_khz * 1000;
1501 visit_type_int(v, &value, name, errp);
1502}
1503
1504static void x86_cpuid_set_tsc_freq(Object *obj, Visitor *v, void *opaque,
1505 const char *name, Error **errp)
1506{
1507 X86CPU *cpu = X86_CPU(obj);
1508 const int64_t min = 0;
Don Slutz2e848492012-09-21 20:13:13 -04001509 const int64_t max = INT64_MAX;
Andreas Färber89e48962012-04-18 00:12:23 +02001510 int64_t value;
1511
1512 visit_type_int(v, &value, name, errp);
1513 if (error_is_set(errp)) {
1514 return;
1515 }
1516 if (value < min || value > max) {
1517 error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE, "",
1518 name ? name : "null", value, min, max);
1519 return;
1520 }
1521
1522 cpu->env.tsc_khz = value / 1000;
1523}
1524
Igor Mammedov31050932013-04-25 16:05:26 +02001525static void x86_cpuid_get_apic_id(Object *obj, Visitor *v, void *opaque,
1526 const char *name, Error **errp)
1527{
1528 X86CPU *cpu = X86_CPU(obj);
1529 int64_t value = cpu->env.cpuid_apic_id;
1530
1531 visit_type_int(v, &value, name, errp);
1532}
1533
1534static void x86_cpuid_set_apic_id(Object *obj, Visitor *v, void *opaque,
1535 const char *name, Error **errp)
1536{
1537 X86CPU *cpu = X86_CPU(obj);
Igor Mammedov8d6d4982013-04-26 19:51:52 +02001538 DeviceState *dev = DEVICE(obj);
Igor Mammedov31050932013-04-25 16:05:26 +02001539 const int64_t min = 0;
1540 const int64_t max = UINT32_MAX;
1541 Error *error = NULL;
1542 int64_t value;
1543
Igor Mammedov8d6d4982013-04-26 19:51:52 +02001544 if (dev->realized) {
1545 error_setg(errp, "Attempt to set property '%s' on '%s' after "
1546 "it was realized", name, object_get_typename(obj));
1547 return;
1548 }
1549
Igor Mammedov31050932013-04-25 16:05:26 +02001550 visit_type_int(v, &value, name, &error);
1551 if (error) {
1552 error_propagate(errp, error);
1553 return;
1554 }
1555 if (value < min || value > max) {
1556 error_setg(errp, "Property %s.%s doesn't take value %" PRId64
1557 " (minimum: %" PRId64 ", maximum: %" PRId64 ")" ,
1558 object_get_typename(obj), name, value, min, max);
1559 return;
1560 }
1561
1562 if ((value != cpu->env.cpuid_apic_id) && cpu_exists(value)) {
1563 error_setg(errp, "CPU with APIC ID %" PRIi64 " exists", value);
1564 return;
1565 }
1566 cpu->env.cpuid_apic_id = value;
1567}
1568
Eduardo Habkost7e5292b2013-05-06 13:20:09 -03001569/* Generic getter for "feature-words" and "filtered-features" properties */
Eduardo Habkost8e8aba52013-05-06 13:20:07 -03001570static void x86_cpu_get_feature_words(Object *obj, Visitor *v, void *opaque,
1571 const char *name, Error **errp)
1572{
Eduardo Habkost7e5292b2013-05-06 13:20:09 -03001573 uint32_t *array = (uint32_t *)opaque;
Eduardo Habkost8e8aba52013-05-06 13:20:07 -03001574 FeatureWord w;
1575 Error *err = NULL;
1576 X86CPUFeatureWordInfo word_infos[FEATURE_WORDS] = { };
1577 X86CPUFeatureWordInfoList list_entries[FEATURE_WORDS] = { };
1578 X86CPUFeatureWordInfoList *list = NULL;
1579
1580 for (w = 0; w < FEATURE_WORDS; w++) {
1581 FeatureWordInfo *wi = &feature_word_info[w];
1582 X86CPUFeatureWordInfo *qwi = &word_infos[w];
1583 qwi->cpuid_input_eax = wi->cpuid_eax;
1584 qwi->has_cpuid_input_ecx = wi->cpuid_needs_ecx;
1585 qwi->cpuid_input_ecx = wi->cpuid_ecx;
1586 qwi->cpuid_register = x86_reg_info_32[wi->cpuid_reg].qapi_enum;
Eduardo Habkost7e5292b2013-05-06 13:20:09 -03001587 qwi->features = array[w];
Eduardo Habkost8e8aba52013-05-06 13:20:07 -03001588
1589 /* List will be in reverse order, but order shouldn't matter */
1590 list_entries[w].next = list;
1591 list_entries[w].value = &word_infos[w];
1592 list = &list_entries[w];
1593 }
1594
1595 visit_type_X86CPUFeatureWordInfoList(v, &list, "feature-words", &err);
1596 error_propagate(errp, err);
1597}
1598
Eduardo Habkostc1399112013-07-26 17:09:35 -03001599static int cpu_x86_find_by_name(X86CPU *cpu, x86_def_t *x86_cpu_def,
1600 const char *name)
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001601{
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001602 x86_def_t *def;
Eduardo Habkost9337e3b2013-07-26 17:09:36 -03001603 Error *err = NULL;
Andreas Färber7fc9b712013-01-21 01:02:28 +01001604 int i;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001605
Andreas Färber4bfe9102013-01-21 01:00:24 +01001606 if (name == NULL) {
Eduardo Habkost8f961352012-12-04 17:34:39 -02001607 return -1;
Andreas Färber4bfe9102013-01-21 01:00:24 +01001608 }
1609 if (kvm_enabled() && strcmp(name, "host") == 0) {
1610 kvm_cpu_fill_host(x86_cpu_def);
Eduardo Habkost9337e3b2013-07-26 17:09:36 -03001611 object_property_set_bool(OBJECT(cpu), true, "pmu", &err);
1612 assert_no_error(err);
Andreas Färber4bfe9102013-01-21 01:00:24 +01001613 return 0;
Eduardo Habkost8f961352012-12-04 17:34:39 -02001614 }
1615
Andreas Färber7fc9b712013-01-21 01:02:28 +01001616 for (i = 0; i < ARRAY_SIZE(builtin_x86_defs); i++) {
1617 def = &builtin_x86_defs[i];
Andreas Färber4bfe9102013-01-21 01:00:24 +01001618 if (strcmp(name, def->name) == 0) {
1619 memcpy(x86_cpu_def, def, sizeof(*def));
Igor Mammedov11acfdd2013-01-21 15:06:37 +01001620 /* sysenter isn't supported in compatibility mode on AMD,
1621 * syscall isn't supported in compatibility mode on Intel.
1622 * Normally we advertise the actual CPU vendor, but you can
1623 * override this using the 'vendor' property if you want to use
1624 * KVM's sysenter/syscall emulation in compatibility mode and
1625 * when doing cross vendor migration
1626 */
1627 if (kvm_enabled()) {
1628 uint32_t ebx = 0, ecx = 0, edx = 0;
1629 host_cpuid(0, 0, NULL, &ebx, &ecx, &edx);
1630 x86_cpu_vendor_words2str(x86_cpu_def->vendor, ebx, edx, ecx);
1631 }
Andreas Färber4bfe9102013-01-21 01:00:24 +01001632 return 0;
1633 }
1634 }
1635
1636 return -1;
Eduardo Habkost8f961352012-12-04 17:34:39 -02001637}
1638
Igor Mammedov72ac2e82013-04-26 18:04:32 +02001639/* Convert all '_' in a feature string option name to '-', to make feature
1640 * name conform to QOM property naming rule, which uses '-' instead of '_'.
1641 */
1642static inline void feat2prop(char *s)
1643{
1644 while ((s = strchr(s, '_'))) {
1645 *s = '-';
1646 }
1647}
1648
Eduardo Habkost8f961352012-12-04 17:34:39 -02001649/* Parse "+feature,-feature,feature=foo" CPU feature string
1650 */
Igor Mammedova91987c2013-01-21 15:06:38 +01001651static void cpu_x86_parse_featurestr(X86CPU *cpu, char *features, Error **errp)
Eduardo Habkost8f961352012-12-04 17:34:39 -02001652{
Eduardo Habkost8f961352012-12-04 17:34:39 -02001653 char *featurestr; /* Single 'key=value" string being parsed */
Eduardo Habkost9f3fb562012-12-04 17:34:38 -02001654 /* Features to be added */
Igor Mammedov077c68c2013-01-11 03:10:15 +01001655 FeatureWordArray plus_features = { 0 };
Joerg Roedel296acb62010-09-27 15:16:17 +02001656 /* Features to be removed */
Eduardo Habkost5ef57872013-01-07 16:20:45 -02001657 FeatureWordArray minus_features = { 0 };
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001658 uint32_t numvalue;
Igor Mammedova91987c2013-01-21 15:06:38 +01001659 CPUX86State *env = &cpu->env;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001660
Eduardo Habkost8f961352012-12-04 17:34:39 -02001661 featurestr = features ? strtok(features, ",") : NULL;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001662
1663 while (featurestr) {
1664 char *val;
1665 if (featurestr[0] == '+') {
Eduardo Habkost5ef57872013-01-07 16:20:45 -02001666 add_flagname_to_bitmaps(featurestr + 1, plus_features);
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001667 } else if (featurestr[0] == '-') {
Eduardo Habkost5ef57872013-01-07 16:20:45 -02001668 add_flagname_to_bitmaps(featurestr + 1, minus_features);
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001669 } else if ((val = strchr(featurestr, '='))) {
1670 *val = 0; val++;
Igor Mammedov72ac2e82013-04-26 18:04:32 +02001671 feat2prop(featurestr);
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001672 if (!strcmp(featurestr, "family")) {
Igor Mammedova91987c2013-01-21 15:06:38 +01001673 object_property_parse(OBJECT(cpu), val, featurestr, errp);
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001674 } else if (!strcmp(featurestr, "model")) {
Igor Mammedova91987c2013-01-21 15:06:38 +01001675 object_property_parse(OBJECT(cpu), val, featurestr, errp);
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001676 } else if (!strcmp(featurestr, "stepping")) {
Igor Mammedova91987c2013-01-21 15:06:38 +01001677 object_property_parse(OBJECT(cpu), val, featurestr, errp);
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001678 } else if (!strcmp(featurestr, "level")) {
Igor Mammedova91987c2013-01-21 15:06:38 +01001679 object_property_parse(OBJECT(cpu), val, featurestr, errp);
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001680 } else if (!strcmp(featurestr, "xlevel")) {
1681 char *err;
Igor Mammedova91987c2013-01-21 15:06:38 +01001682 char num[32];
1683
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001684 numvalue = strtoul(val, &err, 0);
1685 if (!*val || *err) {
Markus Armbruster312fd5f2013-02-08 21:22:16 +01001686 error_setg(errp, "bad numerical value %s", val);
Igor Mammedova91987c2013-01-21 15:06:38 +01001687 goto out;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001688 }
1689 if (numvalue < 0x80000000) {
Igor Mammedov8ba8a692013-01-21 15:06:35 +01001690 fprintf(stderr, "xlevel value shall always be >= 0x80000000"
1691 ", fixup will be removed in future versions\n");
Aurelien Jarno2f7a21c2010-03-13 16:46:33 +01001692 numvalue += 0x80000000;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001693 }
Igor Mammedova91987c2013-01-21 15:06:38 +01001694 snprintf(num, sizeof(num), "%" PRIu32, numvalue);
1695 object_property_parse(OBJECT(cpu), num, featurestr, errp);
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001696 } else if (!strcmp(featurestr, "vendor")) {
Igor Mammedova91987c2013-01-21 15:06:38 +01001697 object_property_parse(OBJECT(cpu), val, featurestr, errp);
Igor Mammedov72ac2e82013-04-26 18:04:32 +02001698 } else if (!strcmp(featurestr, "model-id")) {
1699 object_property_parse(OBJECT(cpu), val, featurestr, errp);
1700 } else if (!strcmp(featurestr, "tsc-freq")) {
Joerg Roedelb862d1f2011-07-07 16:13:12 +02001701 int64_t tsc_freq;
1702 char *err;
Igor Mammedova91987c2013-01-21 15:06:38 +01001703 char num[32];
Joerg Roedelb862d1f2011-07-07 16:13:12 +02001704
1705 tsc_freq = strtosz_suffix_unit(val, &err,
1706 STRTOSZ_DEFSUFFIX_B, 1000);
Markus Armbruster45009a32011-11-22 09:46:04 +01001707 if (tsc_freq < 0 || *err) {
Markus Armbruster312fd5f2013-02-08 21:22:16 +01001708 error_setg(errp, "bad numerical value %s", val);
Igor Mammedova91987c2013-01-21 15:06:38 +01001709 goto out;
Joerg Roedelb862d1f2011-07-07 16:13:12 +02001710 }
Igor Mammedova91987c2013-01-21 15:06:38 +01001711 snprintf(num, sizeof(num), "%" PRId64, tsc_freq);
1712 object_property_parse(OBJECT(cpu), num, "tsc-frequency", errp);
Igor Mammedov72ac2e82013-04-26 18:04:32 +02001713 } else if (!strcmp(featurestr, "hv-spinlocks")) {
Vadim Rozenfeld28f52cc2011-12-18 22:48:13 +02001714 char *err;
Igor Mammedov92067bf2013-06-05 15:18:40 +02001715 const int min = 0xFFF;
Vadim Rozenfeld28f52cc2011-12-18 22:48:13 +02001716 numvalue = strtoul(val, &err, 0);
1717 if (!*val || *err) {
Markus Armbruster312fd5f2013-02-08 21:22:16 +01001718 error_setg(errp, "bad numerical value %s", val);
Igor Mammedova91987c2013-01-21 15:06:38 +01001719 goto out;
Vadim Rozenfeld28f52cc2011-12-18 22:48:13 +02001720 }
Igor Mammedov92067bf2013-06-05 15:18:40 +02001721 if (numvalue < min) {
1722 fprintf(stderr, "hv-spinlocks value shall always be >= 0x%x"
1723 ", fixup will be removed in future versions\n",
1724 min);
1725 numvalue = min;
1726 }
1727 cpu->hyperv_spinlock_attempts = numvalue;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001728 } else {
Markus Armbruster312fd5f2013-02-08 21:22:16 +01001729 error_setg(errp, "unrecognized feature %s", featurestr);
Igor Mammedova91987c2013-01-21 15:06:38 +01001730 goto out;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001731 }
1732 } else if (!strcmp(featurestr, "check")) {
1733 check_cpuid = 1;
1734 } else if (!strcmp(featurestr, "enforce")) {
1735 check_cpuid = enforce_cpuid = 1;
Vadim Rozenfeld28f52cc2011-12-18 22:48:13 +02001736 } else if (!strcmp(featurestr, "hv_relaxed")) {
Igor Mammedov92067bf2013-06-05 15:18:40 +02001737 cpu->hyperv_relaxed_timing = true;
Vadim Rozenfeld28f52cc2011-12-18 22:48:13 +02001738 } else if (!strcmp(featurestr, "hv_vapic")) {
Igor Mammedov92067bf2013-06-05 15:18:40 +02001739 cpu->hyperv_vapic = true;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001740 } else {
Igor Mammedova91987c2013-01-21 15:06:38 +01001741 error_setg(errp, "feature string `%s' not in format (+feature|"
Markus Armbruster312fd5f2013-02-08 21:22:16 +01001742 "-feature|feature=xyz)", featurestr);
Igor Mammedova91987c2013-01-21 15:06:38 +01001743 goto out;
1744 }
1745 if (error_is_set(errp)) {
1746 goto out;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001747 }
1748 featurestr = strtok(NULL, ",");
1749 }
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001750 env->features[FEAT_1_EDX] |= plus_features[FEAT_1_EDX];
1751 env->features[FEAT_1_ECX] |= plus_features[FEAT_1_ECX];
1752 env->features[FEAT_8000_0001_EDX] |= plus_features[FEAT_8000_0001_EDX];
1753 env->features[FEAT_8000_0001_ECX] |= plus_features[FEAT_8000_0001_ECX];
1754 env->features[FEAT_C000_0001_EDX] |= plus_features[FEAT_C000_0001_EDX];
1755 env->features[FEAT_KVM] |= plus_features[FEAT_KVM];
1756 env->features[FEAT_SVM] |= plus_features[FEAT_SVM];
1757 env->features[FEAT_7_0_EBX] |= plus_features[FEAT_7_0_EBX];
1758 env->features[FEAT_1_EDX] &= ~minus_features[FEAT_1_EDX];
1759 env->features[FEAT_1_ECX] &= ~minus_features[FEAT_1_ECX];
1760 env->features[FEAT_8000_0001_EDX] &= ~minus_features[FEAT_8000_0001_EDX];
1761 env->features[FEAT_8000_0001_ECX] &= ~minus_features[FEAT_8000_0001_ECX];
1762 env->features[FEAT_C000_0001_EDX] &= ~minus_features[FEAT_C000_0001_EDX];
1763 env->features[FEAT_KVM] &= ~minus_features[FEAT_KVM];
1764 env->features[FEAT_SVM] &= ~minus_features[FEAT_SVM];
1765 env->features[FEAT_7_0_EBX] &= ~minus_features[FEAT_7_0_EBX];
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001766
Igor Mammedova91987c2013-01-21 15:06:38 +01001767out:
1768 return;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001769}
1770
1771/* generate a composite string into buf of all cpuid names in featureset
1772 * selected by fbits. indicate truncation at bufsize in the event of overflow.
1773 * if flags, suppress names undefined in featureset.
1774 */
1775static void listflags(char *buf, int bufsize, uint32_t fbits,
1776 const char **featureset, uint32_t flags)
1777{
1778 const char **p = &featureset[31];
1779 char *q, *b, bit;
1780 int nc;
1781
1782 b = 4 <= bufsize ? buf + (bufsize -= 3) - 1 : NULL;
1783 *buf = '\0';
1784 for (q = buf, bit = 31; fbits && bufsize; --p, fbits &= ~(1 << bit), --bit)
1785 if (fbits & 1 << bit && (*p || !flags)) {
1786 if (*p)
1787 nc = snprintf(q, bufsize, "%s%s", q == buf ? "" : " ", *p);
1788 else
1789 nc = snprintf(q, bufsize, "%s[%d]", q == buf ? "" : " ", bit);
1790 if (bufsize <= nc) {
1791 if (b) {
1792 memcpy(b, "...", sizeof("..."));
1793 }
1794 return;
1795 }
1796 q += nc;
1797 bufsize -= nc;
1798 }
1799}
1800
Peter Maydelle916cbf2012-09-05 17:41:08 -03001801/* generate CPU information. */
1802void x86_cpu_list(FILE *f, fprintf_function cpu_fprintf)
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001803{
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001804 x86_def_t *def;
1805 char buf[256];
Andreas Färber7fc9b712013-01-21 01:02:28 +01001806 int i;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001807
Andreas Färber7fc9b712013-01-21 01:02:28 +01001808 for (i = 0; i < ARRAY_SIZE(builtin_x86_defs); i++) {
1809 def = &builtin_x86_defs[i];
Eduardo Habkostc04321b2012-09-05 17:41:13 -03001810 snprintf(buf, sizeof(buf), "%s", def->name);
Peter Maydell6cdf8852012-09-05 17:41:07 -03001811 (*cpu_fprintf)(f, "x86 %16s %-48s\n", buf, def->model_id);
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001812 }
Jan Kiszka21ad7782013-03-24 17:01:02 +01001813#ifdef CONFIG_KVM
1814 (*cpu_fprintf)(f, "x86 %16s %-48s\n", "host",
1815 "KVM processor with all supported host features "
1816 "(only available in KVM mode)");
1817#endif
1818
Peter Maydell6cdf8852012-09-05 17:41:07 -03001819 (*cpu_fprintf)(f, "\nRecognized CPUID flags:\n");
Jan Kiszka3af60be2013-02-27 10:15:51 +01001820 for (i = 0; i < ARRAY_SIZE(feature_word_info); i++) {
1821 FeatureWordInfo *fw = &feature_word_info[i];
1822
1823 listflags(buf, sizeof(buf), (uint32_t)~0, fw->feat_names, 1);
1824 (*cpu_fprintf)(f, " %s\n", buf);
1825 }
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001826}
1827
Anthony Liguori76b64a72012-08-14 22:17:36 -05001828CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp)
Anthony Liguorie3966122012-08-10 11:04:14 -05001829{
1830 CpuDefinitionInfoList *cpu_list = NULL;
1831 x86_def_t *def;
Andreas Färber7fc9b712013-01-21 01:02:28 +01001832 int i;
Anthony Liguorie3966122012-08-10 11:04:14 -05001833
Andreas Färber7fc9b712013-01-21 01:02:28 +01001834 for (i = 0; i < ARRAY_SIZE(builtin_x86_defs); i++) {
Anthony Liguorie3966122012-08-10 11:04:14 -05001835 CpuDefinitionInfoList *entry;
1836 CpuDefinitionInfo *info;
1837
Andreas Färber7fc9b712013-01-21 01:02:28 +01001838 def = &builtin_x86_defs[i];
Anthony Liguorie3966122012-08-10 11:04:14 -05001839 info = g_malloc0(sizeof(*info));
1840 info->name = g_strdup(def->name);
1841
1842 entry = g_malloc0(sizeof(*entry));
1843 entry->value = info;
1844 entry->next = cpu_list;
1845 cpu_list = entry;
1846 }
1847
1848 return cpu_list;
1849}
1850
Eduardo Habkostbc74b7d2012-10-04 17:49:05 -03001851#ifdef CONFIG_KVM
1852static void filter_features_for_kvm(X86CPU *cpu)
1853{
1854 CPUX86State *env = &cpu->env;
1855 KVMState *s = kvm_state;
Eduardo Habkostbd87d2a2013-04-22 16:00:18 -03001856 FeatureWord w;
Eduardo Habkostbc74b7d2012-10-04 17:49:05 -03001857
Eduardo Habkostbd87d2a2013-04-22 16:00:18 -03001858 for (w = 0; w < FEATURE_WORDS; w++) {
1859 FeatureWordInfo *wi = &feature_word_info[w];
Eduardo Habkost034acf42013-05-06 13:20:08 -03001860 uint32_t host_feat = kvm_arch_get_supported_cpuid(s, wi->cpuid_eax,
1861 wi->cpuid_ecx,
1862 wi->cpuid_reg);
1863 uint32_t requested_features = env->features[w];
1864 env->features[w] &= host_feat;
1865 cpu->filtered_features[w] = requested_features & ~env->features[w];
Eduardo Habkostbd87d2a2013-04-22 16:00:18 -03001866 }
Eduardo Habkostbc74b7d2012-10-04 17:49:05 -03001867}
1868#endif
1869
Andreas Färber2d642552013-02-15 14:06:56 +01001870static void cpu_x86_register(X86CPU *cpu, const char *name, Error **errp)
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001871{
Andreas Färber61dcd772012-04-17 12:00:51 +02001872 CPUX86State *env = &cpu->env;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001873 x86_def_t def1, *def = &def1;
1874
Joerg Roedeldb0ad1b2010-09-27 15:16:16 +02001875 memset(def, 0, sizeof(*def));
1876
Eduardo Habkostc1399112013-07-26 17:09:35 -03001877 if (cpu_x86_find_by_name(cpu, def, name) < 0) {
Andreas Färber2d642552013-02-15 14:06:56 +01001878 error_setg(errp, "Unable to find CPU definition: %s", name);
1879 return;
1880 }
1881
1882 if (kvm_enabled()) {
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001883 def->features[FEAT_KVM] |= kvm_default_features;
Andreas Färber2d642552013-02-15 14:06:56 +01001884 }
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001885 def->features[FEAT_1_ECX] |= CPUID_EXT_HYPERVISOR;
Andreas Färber2d642552013-02-15 14:06:56 +01001886
1887 object_property_set_str(OBJECT(cpu), def->vendor, "vendor", errp);
1888 object_property_set_int(OBJECT(cpu), def->level, "level", errp);
1889 object_property_set_int(OBJECT(cpu), def->family, "family", errp);
1890 object_property_set_int(OBJECT(cpu), def->model, "model", errp);
1891 object_property_set_int(OBJECT(cpu), def->stepping, "stepping", errp);
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001892 env->features[FEAT_1_EDX] = def->features[FEAT_1_EDX];
1893 env->features[FEAT_1_ECX] = def->features[FEAT_1_ECX];
1894 env->features[FEAT_8000_0001_EDX] = def->features[FEAT_8000_0001_EDX];
1895 env->features[FEAT_8000_0001_ECX] = def->features[FEAT_8000_0001_ECX];
Andreas Färber2d642552013-02-15 14:06:56 +01001896 object_property_set_int(OBJECT(cpu), def->xlevel, "xlevel", errp);
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001897 env->features[FEAT_KVM] = def->features[FEAT_KVM];
1898 env->features[FEAT_SVM] = def->features[FEAT_SVM];
1899 env->features[FEAT_C000_0001_EDX] = def->features[FEAT_C000_0001_EDX];
1900 env->features[FEAT_7_0_EBX] = def->features[FEAT_7_0_EBX];
Andreas Färber2d642552013-02-15 14:06:56 +01001901 env->cpuid_xlevel2 = def->xlevel2;
Benoît Canet787aaf52013-09-02 17:06:37 +02001902 cpu->cache_info_passthrough = def->cache_info_passthrough;
Andreas Färber2d642552013-02-15 14:06:56 +01001903
1904 object_property_set_str(OBJECT(cpu), def->model_id, "model-id", errp);
1905}
1906
Igor Mammedov62fc4032013-04-29 18:54:13 +02001907X86CPU *cpu_x86_create(const char *cpu_model, DeviceState *icc_bridge,
1908 Error **errp)
Andreas Färber2d642552013-02-15 14:06:56 +01001909{
1910 X86CPU *cpu = NULL;
Andreas Färber2d642552013-02-15 14:06:56 +01001911 gchar **model_pieces;
1912 char *name, *features;
Andreas Färberba2bc7a2013-05-01 17:05:47 +02001913 char *typename;
Andreas Färber2d642552013-02-15 14:06:56 +01001914 Error *error = NULL;
1915
Eduardo Habkost8f961352012-12-04 17:34:39 -02001916 model_pieces = g_strsplit(cpu_model, ",", 2);
1917 if (!model_pieces[0]) {
Igor Mammedovfa2db3c2013-01-11 03:10:16 +01001918 error_setg(&error, "Invalid/empty CPU model name");
1919 goto out;
Eduardo Habkost8f961352012-12-04 17:34:39 -02001920 }
1921 name = model_pieces[0];
1922 features = model_pieces[1];
1923
Andreas Färber2d642552013-02-15 14:06:56 +01001924 cpu = X86_CPU(object_new(TYPE_X86_CPU));
Igor Mammedov62fc4032013-04-29 18:54:13 +02001925#ifndef CONFIG_USER_ONLY
1926 if (icc_bridge == NULL) {
1927 error_setg(&error, "Invalid icc-bridge value");
1928 goto out;
1929 }
1930 qdev_set_parent_bus(DEVICE(cpu), qdev_get_child_bus(icc_bridge, "icc"));
1931 object_unref(OBJECT(cpu));
1932#endif
Eduardo Habkost8f961352012-12-04 17:34:39 -02001933
Andreas Färber2d642552013-02-15 14:06:56 +01001934 cpu_x86_register(cpu, name, &error);
Igor Mammedova91987c2013-01-21 15:06:38 +01001935 if (error) {
1936 goto out;
1937 }
Igor Mammedovfa2db3c2013-01-11 03:10:16 +01001938
Andreas Färberba2bc7a2013-05-01 17:05:47 +02001939 /* Emulate per-model subclasses for global properties */
1940 typename = g_strdup_printf("%s-" TYPE_X86_CPU, name);
1941 qdev_prop_set_globals_for_type(DEVICE(cpu), typename, &error);
1942 g_free(typename);
1943 if (error) {
1944 goto out;
1945 }
1946
Igor Mammedova91987c2013-01-21 15:06:38 +01001947 cpu_x86_parse_featurestr(cpu, features, &error);
Andreas Färber2d642552013-02-15 14:06:56 +01001948 if (error) {
1949 goto out;
1950 }
1951
Igor Mammedov7f833242013-04-11 16:51:40 +02001952out:
Andreas Färbercd7b87f2013-08-02 18:56:05 +02001953 if (error != NULL) {
1954 error_propagate(errp, error);
1955 object_unref(OBJECT(cpu));
1956 cpu = NULL;
1957 }
Igor Mammedov7f833242013-04-11 16:51:40 +02001958 g_strfreev(model_pieces);
1959 return cpu;
1960}
1961
1962X86CPU *cpu_x86_init(const char *cpu_model)
1963{
1964 Error *error = NULL;
1965 X86CPU *cpu;
1966
Igor Mammedov62fc4032013-04-29 18:54:13 +02001967 cpu = cpu_x86_create(cpu_model, NULL, &error);
Andreas Färber2d642552013-02-15 14:06:56 +01001968 if (error) {
1969 goto out;
1970 }
1971
Igor Mammedov7f833242013-04-11 16:51:40 +02001972 object_property_set_bool(OBJECT(cpu), true, "realized", &error);
1973
Igor Mammedovfa2db3c2013-01-11 03:10:16 +01001974out:
Igor Mammedov18eb4732012-10-02 17:36:54 +02001975 if (error) {
Seiji Aguchi4a44d852013-08-05 15:40:44 -04001976 error_report("%s", error_get_pretty(error));
Andreas Färber71ad61d2012-04-17 12:10:29 +02001977 error_free(error);
Andreas Färber2d642552013-02-15 14:06:56 +01001978 if (cpu != NULL) {
1979 object_unref(OBJECT(cpu));
1980 cpu = NULL;
1981 }
Andreas Färber5c3c6a62013-02-01 15:12:13 +01001982 }
1983 return cpu;
1984}
1985
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001986#if !defined(CONFIG_USER_ONLY)
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001987
Blue Swirl0e26b7b2010-06-19 10:42:34 +03001988void cpu_clear_apic_feature(CPUX86State *env)
1989{
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001990 env->features[FEAT_1_EDX] &= ~CPUID_APIC;
Blue Swirl0e26b7b2010-06-19 10:42:34 +03001991}
1992
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001993#endif /* !CONFIG_USER_ONLY */
1994
Eduardo Habkostc04321b2012-09-05 17:41:13 -03001995/* Initialize list of CPU models, filling some non-static fields if necessary
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001996 */
1997void x86_cpudef_setup(void)
1998{
Crístian Viana93bfef42012-05-30 00:35:51 -03001999 int i, j;
2000 static const char *model_with_versions[] = { "qemu32", "qemu64", "athlon" };
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002001
2002 for (i = 0; i < ARRAY_SIZE(builtin_x86_defs); ++i) {
Eduardo Habkostbc3e1292012-09-05 17:41:12 -03002003 x86_def_t *def = &builtin_x86_defs[i];
Crístian Viana93bfef42012-05-30 00:35:51 -03002004
2005 /* Look for specific "cpudef" models that */
Stefan Weil09faecf2012-06-20 06:05:51 +02002006 /* have the QEMU version in .model_id */
Crístian Viana93bfef42012-05-30 00:35:51 -03002007 for (j = 0; j < ARRAY_SIZE(model_with_versions); j++) {
Eduardo Habkostbc3e1292012-09-05 17:41:12 -03002008 if (strcmp(model_with_versions[j], def->name) == 0) {
2009 pstrcpy(def->model_id, sizeof(def->model_id),
2010 "QEMU Virtual CPU version ");
2011 pstrcat(def->model_id, sizeof(def->model_id),
2012 qemu_get_version());
Crístian Viana93bfef42012-05-30 00:35:51 -03002013 break;
2014 }
2015 }
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002016 }
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002017}
2018
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002019static void get_cpuid_vendor(CPUX86State *env, uint32_t *ebx,
2020 uint32_t *ecx, uint32_t *edx)
2021{
2022 *ebx = env->cpuid_vendor1;
2023 *edx = env->cpuid_vendor2;
2024 *ecx = env->cpuid_vendor3;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002025}
2026
2027void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
2028 uint32_t *eax, uint32_t *ebx,
2029 uint32_t *ecx, uint32_t *edx)
2030{
Andreas Färbera60f24b2012-12-01 05:35:08 +01002031 X86CPU *cpu = x86_env_get_cpu(env);
2032 CPUState *cs = CPU(cpu);
2033
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002034 /* test if maximum index reached */
2035 if (index & 0x80000000) {
brillywu@viatech.com.cnb3baa152011-06-01 09:59:52 +08002036 if (index > env->cpuid_xlevel) {
2037 if (env->cpuid_xlevel2 > 0) {
2038 /* Handle the Centaur's CPUID instruction. */
2039 if (index > env->cpuid_xlevel2) {
2040 index = env->cpuid_xlevel2;
2041 } else if (index < 0xC0000000) {
2042 index = env->cpuid_xlevel;
2043 }
2044 } else {
Eduardo Habkost57f26ae2012-12-20 16:43:48 -02002045 /* Intel documentation states that invalid EAX input will
2046 * return the same information as EAX=cpuid_level
2047 * (Intel SDM Vol. 2A - Instruction Set Reference - CPUID)
2048 */
2049 index = env->cpuid_level;
brillywu@viatech.com.cnb3baa152011-06-01 09:59:52 +08002050 }
2051 }
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002052 } else {
2053 if (index > env->cpuid_level)
2054 index = env->cpuid_level;
2055 }
2056
2057 switch(index) {
2058 case 0:
2059 *eax = env->cpuid_level;
2060 get_cpuid_vendor(env, ebx, ecx, edx);
2061 break;
2062 case 1:
2063 *eax = env->cpuid_version;
2064 *ebx = (env->cpuid_apic_id << 24) | 8 << 8; /* CLFLUSH size in quad words, Linux wants it. */
Eduardo Habkost0514ef22013-04-22 16:00:15 -03002065 *ecx = env->features[FEAT_1_ECX];
2066 *edx = env->features[FEAT_1_EDX];
Andreas Färberce3960e2012-12-17 03:27:07 +01002067 if (cs->nr_cores * cs->nr_threads > 1) {
2068 *ebx |= (cs->nr_cores * cs->nr_threads) << 16;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002069 *edx |= 1 << 28; /* HTT bit */
2070 }
2071 break;
2072 case 2:
2073 /* cache info: needed for Pentium Pro compatibility */
Benoît Canet787aaf52013-09-02 17:06:37 +02002074 if (cpu->cache_info_passthrough) {
2075 host_cpuid(index, 0, eax, ebx, ecx, edx);
2076 break;
2077 }
Eduardo Habkost5e891bf2013-08-27 12:24:37 -03002078 *eax = 1; /* Number of CPUID[EAX=2] calls required */
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002079 *ebx = 0;
2080 *ecx = 0;
Eduardo Habkost5e891bf2013-08-27 12:24:37 -03002081 *edx = (L1D_DESCRIPTOR << 16) | \
2082 (L1I_DESCRIPTOR << 8) | \
2083 (L2_DESCRIPTOR);
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002084 break;
2085 case 4:
2086 /* cache info: needed for Core compatibility */
Benoît Canet787aaf52013-09-02 17:06:37 +02002087 if (cpu->cache_info_passthrough) {
2088 host_cpuid(index, count, eax, ebx, ecx, edx);
Paolo Bonzini76c29752013-11-19 17:49:46 +01002089 *eax &= ~0xFC000000;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002090 } else {
Aurelien Jarno2f7a21c2010-03-13 16:46:33 +01002091 *eax = 0;
Paolo Bonzini76c29752013-11-19 17:49:46 +01002092 switch (count) {
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002093 case 0: /* L1 dcache info */
Eduardo Habkost5e891bf2013-08-27 12:24:37 -03002094 *eax |= CPUID_4_TYPE_DCACHE | \
2095 CPUID_4_LEVEL(1) | \
2096 CPUID_4_SELF_INIT_LEVEL;
2097 *ebx = (L1D_LINE_SIZE - 1) | \
2098 ((L1D_PARTITIONS - 1) << 12) | \
2099 ((L1D_ASSOCIATIVITY - 1) << 22);
2100 *ecx = L1D_SETS - 1;
2101 *edx = CPUID_4_NO_INVD_SHARING;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002102 break;
2103 case 1: /* L1 icache info */
Eduardo Habkost5e891bf2013-08-27 12:24:37 -03002104 *eax |= CPUID_4_TYPE_ICACHE | \
2105 CPUID_4_LEVEL(1) | \
2106 CPUID_4_SELF_INIT_LEVEL;
2107 *ebx = (L1I_LINE_SIZE - 1) | \
2108 ((L1I_PARTITIONS - 1) << 12) | \
2109 ((L1I_ASSOCIATIVITY - 1) << 22);
2110 *ecx = L1I_SETS - 1;
2111 *edx = CPUID_4_NO_INVD_SHARING;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002112 break;
2113 case 2: /* L2 cache info */
Eduardo Habkost5e891bf2013-08-27 12:24:37 -03002114 *eax |= CPUID_4_TYPE_UNIFIED | \
2115 CPUID_4_LEVEL(2) | \
2116 CPUID_4_SELF_INIT_LEVEL;
Andreas Färberce3960e2012-12-17 03:27:07 +01002117 if (cs->nr_threads > 1) {
2118 *eax |= (cs->nr_threads - 1) << 14;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002119 }
Eduardo Habkost5e891bf2013-08-27 12:24:37 -03002120 *ebx = (L2_LINE_SIZE - 1) | \
2121 ((L2_PARTITIONS - 1) << 12) | \
2122 ((L2_ASSOCIATIVITY - 1) << 22);
2123 *ecx = L2_SETS - 1;
2124 *edx = CPUID_4_NO_INVD_SHARING;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002125 break;
2126 default: /* end of info */
2127 *eax = 0;
2128 *ebx = 0;
2129 *ecx = 0;
2130 *edx = 0;
2131 break;
Paolo Bonzini76c29752013-11-19 17:49:46 +01002132 }
2133 }
2134
2135 /* QEMU gives out its own APIC IDs, never pass down bits 31..26. */
2136 if ((*eax & 31) && cs->nr_cores > 1) {
2137 *eax |= (cs->nr_cores - 1) << 26;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002138 }
2139 break;
2140 case 5:
2141 /* mwait info: needed for Core compatibility */
2142 *eax = 0; /* Smallest monitor-line size in bytes */
2143 *ebx = 0; /* Largest monitor-line size in bytes */
2144 *ecx = CPUID_MWAIT_EMX | CPUID_MWAIT_IBE;
2145 *edx = 0;
2146 break;
2147 case 6:
2148 /* Thermal and Power Leaf */
2149 *eax = 0;
2150 *ebx = 0;
2151 *ecx = 0;
2152 *edx = 0;
2153 break;
Yang, Wei Yf7911682011-05-30 23:17:42 +08002154 case 7:
Eduardo Habkost13526722012-05-21 11:27:02 -03002155 /* Structured Extended Feature Flags Enumeration Leaf */
2156 if (count == 0) {
2157 *eax = 0; /* Maximum ECX value for sub-leaves */
Eduardo Habkost0514ef22013-04-22 16:00:15 -03002158 *ebx = env->features[FEAT_7_0_EBX]; /* Feature flags */
Eduardo Habkost13526722012-05-21 11:27:02 -03002159 *ecx = 0; /* Reserved */
2160 *edx = 0; /* Reserved */
Yang, Wei Yf7911682011-05-30 23:17:42 +08002161 } else {
2162 *eax = 0;
2163 *ebx = 0;
2164 *ecx = 0;
2165 *edx = 0;
2166 }
2167 break;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002168 case 9:
2169 /* Direct Cache Access Information Leaf */
2170 *eax = 0; /* Bits 0-31 in DCA_CAP MSR */
2171 *ebx = 0;
2172 *ecx = 0;
2173 *edx = 0;
2174 break;
2175 case 0xA:
2176 /* Architectural Performance Monitoring Leaf */
Eduardo Habkost9337e3b2013-07-26 17:09:36 -03002177 if (kvm_enabled() && cpu->enable_pmu) {
Andreas Färbera60f24b2012-12-01 05:35:08 +01002178 KVMState *s = cs->kvm_state;
Gleb Natapova0fa8202011-12-15 12:44:05 +02002179
2180 *eax = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EAX);
2181 *ebx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EBX);
2182 *ecx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_ECX);
2183 *edx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EDX);
2184 } else {
2185 *eax = 0;
2186 *ebx = 0;
2187 *ecx = 0;
2188 *edx = 0;
2189 }
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002190 break;
Paolo Bonzini2560f192013-10-02 17:54:57 +02002191 case 0xD: {
2192 KVMState *s = cs->kvm_state;
2193 uint64_t kvm_mask;
2194 int i;
2195
Sheng Yang51e49432010-06-17 15:18:14 +08002196 /* Processor Extended State */
Paolo Bonzini2560f192013-10-02 17:54:57 +02002197 *eax = 0;
2198 *ebx = 0;
2199 *ecx = 0;
2200 *edx = 0;
2201 if (!(env->features[FEAT_1_ECX] & CPUID_EXT_XSAVE) || !kvm_enabled()) {
Sheng Yang51e49432010-06-17 15:18:14 +08002202 break;
2203 }
Paolo Bonzini2560f192013-10-02 17:54:57 +02002204 kvm_mask =
2205 kvm_arch_get_supported_cpuid(s, 0xd, 0, R_EAX) |
2206 ((uint64_t)kvm_arch_get_supported_cpuid(s, 0xd, 0, R_EDX) << 32);
Jan Kiszkaba9bc592011-06-08 16:11:05 +02002207
Paolo Bonzini2560f192013-10-02 17:54:57 +02002208 if (count == 0) {
2209 *ecx = 0x240;
2210 for (i = 2; i < ARRAY_SIZE(ext_save_areas); i++) {
2211 const ExtSaveArea *esa = &ext_save_areas[i];
2212 if ((env->features[esa->feature] & esa->bits) == esa->bits &&
2213 (kvm_mask & (1 << i)) != 0) {
2214 if (i < 32) {
2215 *eax |= 1 << i;
2216 } else {
2217 *edx |= 1 << (i - 32);
2218 }
2219 *ecx = MAX(*ecx, esa->offset + esa->size);
2220 }
2221 }
2222 *eax |= kvm_mask & (XSTATE_FP | XSTATE_SSE);
2223 *ebx = *ecx;
2224 } else if (count == 1) {
2225 *eax = kvm_arch_get_supported_cpuid(s, 0xd, 1, R_EAX);
2226 } else if (count < ARRAY_SIZE(ext_save_areas)) {
2227 const ExtSaveArea *esa = &ext_save_areas[count];
2228 if ((env->features[esa->feature] & esa->bits) == esa->bits &&
2229 (kvm_mask & (1 << count)) != 0) {
Liu Jinsong33f373d2013-12-03 04:17:50 +08002230 *eax = esa->size;
2231 *ebx = esa->offset;
Paolo Bonzini2560f192013-10-02 17:54:57 +02002232 }
Sheng Yang51e49432010-06-17 15:18:14 +08002233 }
2234 break;
Paolo Bonzini2560f192013-10-02 17:54:57 +02002235 }
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002236 case 0x80000000:
2237 *eax = env->cpuid_xlevel;
2238 *ebx = env->cpuid_vendor1;
2239 *edx = env->cpuid_vendor2;
2240 *ecx = env->cpuid_vendor3;
2241 break;
2242 case 0x80000001:
2243 *eax = env->cpuid_version;
2244 *ebx = 0;
Eduardo Habkost0514ef22013-04-22 16:00:15 -03002245 *ecx = env->features[FEAT_8000_0001_ECX];
2246 *edx = env->features[FEAT_8000_0001_EDX];
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002247
2248 /* The Linux kernel checks for the CMPLegacy bit and
2249 * discards multiple thread information if it is set.
2250 * So dont set it here for Intel to make Linux guests happy.
2251 */
Andreas Färberce3960e2012-12-17 03:27:07 +01002252 if (cs->nr_cores * cs->nr_threads > 1) {
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002253 uint32_t tebx, tecx, tedx;
2254 get_cpuid_vendor(env, &tebx, &tecx, &tedx);
2255 if (tebx != CPUID_VENDOR_INTEL_1 ||
2256 tedx != CPUID_VENDOR_INTEL_2 ||
2257 tecx != CPUID_VENDOR_INTEL_3) {
2258 *ecx |= 1 << 1; /* CmpLegacy bit */
2259 }
2260 }
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002261 break;
2262 case 0x80000002:
2263 case 0x80000003:
2264 case 0x80000004:
2265 *eax = env->cpuid_model[(index - 0x80000002) * 4 + 0];
2266 *ebx = env->cpuid_model[(index - 0x80000002) * 4 + 1];
2267 *ecx = env->cpuid_model[(index - 0x80000002) * 4 + 2];
2268 *edx = env->cpuid_model[(index - 0x80000002) * 4 + 3];
2269 break;
2270 case 0x80000005:
2271 /* cache info (L1 cache) */
Benoît Canet787aaf52013-09-02 17:06:37 +02002272 if (cpu->cache_info_passthrough) {
2273 host_cpuid(index, 0, eax, ebx, ecx, edx);
2274 break;
2275 }
Eduardo Habkost5e891bf2013-08-27 12:24:37 -03002276 *eax = (L1_DTLB_2M_ASSOC << 24) | (L1_DTLB_2M_ENTRIES << 16) | \
2277 (L1_ITLB_2M_ASSOC << 8) | (L1_ITLB_2M_ENTRIES);
2278 *ebx = (L1_DTLB_4K_ASSOC << 24) | (L1_DTLB_4K_ENTRIES << 16) | \
2279 (L1_ITLB_4K_ASSOC << 8) | (L1_ITLB_4K_ENTRIES);
2280 *ecx = (L1D_SIZE_KB_AMD << 24) | (L1D_ASSOCIATIVITY_AMD << 16) | \
2281 (L1D_LINES_PER_TAG << 8) | (L1D_LINE_SIZE);
2282 *edx = (L1I_SIZE_KB_AMD << 24) | (L1I_ASSOCIATIVITY_AMD << 16) | \
2283 (L1I_LINES_PER_TAG << 8) | (L1I_LINE_SIZE);
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002284 break;
2285 case 0x80000006:
2286 /* cache info (L2 cache) */
Benoît Canet787aaf52013-09-02 17:06:37 +02002287 if (cpu->cache_info_passthrough) {
2288 host_cpuid(index, 0, eax, ebx, ecx, edx);
2289 break;
2290 }
Eduardo Habkost5e891bf2013-08-27 12:24:37 -03002291 *eax = (AMD_ENC_ASSOC(L2_DTLB_2M_ASSOC) << 28) | \
2292 (L2_DTLB_2M_ENTRIES << 16) | \
2293 (AMD_ENC_ASSOC(L2_ITLB_2M_ASSOC) << 12) | \
2294 (L2_ITLB_2M_ENTRIES);
2295 *ebx = (AMD_ENC_ASSOC(L2_DTLB_4K_ASSOC) << 28) | \
2296 (L2_DTLB_4K_ENTRIES << 16) | \
2297 (AMD_ENC_ASSOC(L2_ITLB_4K_ASSOC) << 12) | \
2298 (L2_ITLB_4K_ENTRIES);
2299 *ecx = (L2_SIZE_KB_AMD << 16) | \
2300 (AMD_ENC_ASSOC(L2_ASSOCIATIVITY) << 12) | \
2301 (L2_LINES_PER_TAG << 8) | (L2_LINE_SIZE);
2302 *edx = ((L3_SIZE_KB/512) << 18) | \
2303 (AMD_ENC_ASSOC(L3_ASSOCIATIVITY) << 12) | \
2304 (L3_LINES_PER_TAG << 8) | (L3_LINE_SIZE);
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002305 break;
2306 case 0x80000008:
2307 /* virtual & phys address size in low 2 bytes. */
2308/* XXX: This value must match the one used in the MMU code. */
Eduardo Habkost0514ef22013-04-22 16:00:15 -03002309 if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM) {
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002310 /* 64 bit processor */
2311/* XXX: The physical address space is limited to 42 bits in exec.c. */
Eduardo Habkostdd13e082013-04-11 17:07:23 -03002312 *eax = 0x00003028; /* 48 bits virtual, 40 bits physical */
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002313 } else {
Eduardo Habkost0514ef22013-04-22 16:00:15 -03002314 if (env->features[FEAT_1_EDX] & CPUID_PSE36) {
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002315 *eax = 0x00000024; /* 36 bits physical */
Eduardo Habkostdd13e082013-04-11 17:07:23 -03002316 } else {
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002317 *eax = 0x00000020; /* 32 bits physical */
Eduardo Habkostdd13e082013-04-11 17:07:23 -03002318 }
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002319 }
2320 *ebx = 0;
2321 *ecx = 0;
2322 *edx = 0;
Andreas Färberce3960e2012-12-17 03:27:07 +01002323 if (cs->nr_cores * cs->nr_threads > 1) {
2324 *ecx |= (cs->nr_cores * cs->nr_threads) - 1;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002325 }
2326 break;
2327 case 0x8000000A:
Eduardo Habkost0514ef22013-04-22 16:00:15 -03002328 if (env->features[FEAT_8000_0001_ECX] & CPUID_EXT3_SVM) {
Eduardo Habkost9f3fb562012-12-04 17:34:38 -02002329 *eax = 0x00000001; /* SVM Revision */
2330 *ebx = 0x00000010; /* nr of ASIDs */
2331 *ecx = 0;
Eduardo Habkost0514ef22013-04-22 16:00:15 -03002332 *edx = env->features[FEAT_SVM]; /* optional features */
Eduardo Habkost9f3fb562012-12-04 17:34:38 -02002333 } else {
2334 *eax = 0;
2335 *ebx = 0;
2336 *ecx = 0;
2337 *edx = 0;
2338 }
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002339 break;
brillywu@viatech.com.cnb3baa152011-06-01 09:59:52 +08002340 case 0xC0000000:
2341 *eax = env->cpuid_xlevel2;
2342 *ebx = 0;
2343 *ecx = 0;
2344 *edx = 0;
2345 break;
2346 case 0xC0000001:
2347 /* Support for VIA CPU's CPUID instruction */
2348 *eax = env->cpuid_version;
2349 *ebx = 0;
2350 *ecx = 0;
Eduardo Habkost0514ef22013-04-22 16:00:15 -03002351 *edx = env->features[FEAT_C000_0001_EDX];
brillywu@viatech.com.cnb3baa152011-06-01 09:59:52 +08002352 break;
2353 case 0xC0000002:
2354 case 0xC0000003:
2355 case 0xC0000004:
2356 /* Reserved for the future, and now filled with zero */
2357 *eax = 0;
2358 *ebx = 0;
2359 *ecx = 0;
2360 *edx = 0;
2361 break;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002362 default:
2363 /* reserved values: zero */
2364 *eax = 0;
2365 *ebx = 0;
2366 *ecx = 0;
2367 *edx = 0;
2368 break;
2369 }
2370}
Andreas Färber5fd20872012-04-02 23:20:08 +02002371
2372/* CPUClass::reset() */
2373static void x86_cpu_reset(CPUState *s)
2374{
2375 X86CPU *cpu = X86_CPU(s);
2376 X86CPUClass *xcc = X86_CPU_GET_CLASS(cpu);
2377 CPUX86State *env = &cpu->env;
Andreas Färberc1958ae2012-04-03 00:16:24 +02002378 int i;
2379
Andreas Färber5fd20872012-04-02 23:20:08 +02002380 xcc->parent_reset(s);
2381
Andreas Färberc1958ae2012-04-03 00:16:24 +02002382
2383 memset(env, 0, offsetof(CPUX86State, breakpoints));
2384
2385 tlb_flush(env, 1);
2386
2387 env->old_exception = -1;
2388
2389 /* init to reset state */
2390
2391#ifdef CONFIG_SOFTMMU
2392 env->hflags |= HF_SOFTMMU_MASK;
2393#endif
2394 env->hflags2 |= HF2_GIF_MASK;
2395
2396 cpu_x86_update_cr0(env, 0x60000010);
2397 env->a20_mask = ~0x0;
2398 env->smbase = 0x30000;
2399
2400 env->idt.limit = 0xffff;
2401 env->gdt.limit = 0xffff;
2402 env->ldt.limit = 0xffff;
2403 env->ldt.flags = DESC_P_MASK | (2 << DESC_TYPE_SHIFT);
2404 env->tr.limit = 0xffff;
2405 env->tr.flags = DESC_P_MASK | (11 << DESC_TYPE_SHIFT);
2406
2407 cpu_x86_load_seg_cache(env, R_CS, 0xf000, 0xffff0000, 0xffff,
2408 DESC_P_MASK | DESC_S_MASK | DESC_CS_MASK |
2409 DESC_R_MASK | DESC_A_MASK);
2410 cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0xffff,
2411 DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
2412 DESC_A_MASK);
2413 cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0xffff,
2414 DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
2415 DESC_A_MASK);
2416 cpu_x86_load_seg_cache(env, R_SS, 0, 0, 0xffff,
2417 DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
2418 DESC_A_MASK);
2419 cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0xffff,
2420 DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
2421 DESC_A_MASK);
2422 cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0xffff,
2423 DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
2424 DESC_A_MASK);
2425
2426 env->eip = 0xfff0;
2427 env->regs[R_EDX] = env->cpuid_version;
2428
2429 env->eflags = 0x2;
2430
2431 /* FPU init */
2432 for (i = 0; i < 8; i++) {
2433 env->fptags[i] = 1;
2434 }
2435 env->fpuc = 0x37f;
2436
2437 env->mxcsr = 0x1f80;
Paolo Bonzinic74f41b2013-09-13 15:55:57 +02002438 env->xstate_bv = XSTATE_FP | XSTATE_SSE;
Andreas Färberc1958ae2012-04-03 00:16:24 +02002439
2440 env->pat = 0x0007040600070406ULL;
2441 env->msr_ia32_misc_enable = MSR_IA32_MISC_ENABLE_DEFAULT;
2442
2443 memset(env->dr, 0, sizeof(env->dr));
2444 env->dr[6] = DR6_FIXED_1;
2445 env->dr[7] = DR7_FIXED_1;
2446 cpu_breakpoint_remove_all(env, BP_CPU);
2447 cpu_watchpoint_remove_all(env, BP_CPU);
Igor Mammedovdd673282012-07-23 15:22:27 +02002448
2449#if !defined(CONFIG_USER_ONLY)
2450 /* We hard-wire the BSP to the first CPU. */
Andreas Färber55e5c282012-12-17 06:18:02 +01002451 if (s->cpu_index == 0) {
Chen Fan02e51482013-12-23 17:04:02 +08002452 apic_designate_bsp(cpu->apic_state);
Igor Mammedovdd673282012-07-23 15:22:27 +02002453 }
2454
Andreas Färber259186a2013-01-17 18:51:17 +01002455 s->halted = !cpu_is_bsp(cpu);
Igor Mammedovdd673282012-07-23 15:22:27 +02002456#endif
Andreas Färber5fd20872012-04-02 23:20:08 +02002457}
2458
Igor Mammedovdd673282012-07-23 15:22:27 +02002459#ifndef CONFIG_USER_ONLY
2460bool cpu_is_bsp(X86CPU *cpu)
2461{
Chen Fan02e51482013-12-23 17:04:02 +08002462 return cpu_get_apic_base(cpu->apic_state) & MSR_IA32_APICBASE_BSP;
Igor Mammedovdd673282012-07-23 15:22:27 +02002463}
Igor Mammedov65dee382012-07-23 15:22:28 +02002464
2465/* TODO: remove me, when reset over QOM tree is implemented */
2466static void x86_cpu_machine_reset_cb(void *opaque)
2467{
2468 X86CPU *cpu = opaque;
2469 cpu_reset(CPU(cpu));
2470}
Igor Mammedovdd673282012-07-23 15:22:27 +02002471#endif
2472
Andreas Färberde024812012-04-03 00:00:17 +02002473static void mce_init(X86CPU *cpu)
2474{
2475 CPUX86State *cenv = &cpu->env;
2476 unsigned int bank;
2477
2478 if (((cenv->cpuid_version >> 8) & 0xf) >= 6
Eduardo Habkost0514ef22013-04-22 16:00:15 -03002479 && (cenv->features[FEAT_1_EDX] & (CPUID_MCE | CPUID_MCA)) ==
Andreas Färberde024812012-04-03 00:00:17 +02002480 (CPUID_MCE | CPUID_MCA)) {
2481 cenv->mcg_cap = MCE_CAP_DEF | MCE_BANKS_DEF;
2482 cenv->mcg_ctl = ~(uint64_t)0;
2483 for (bank = 0; bank < MCE_BANKS_DEF; bank++) {
2484 cenv->mce_banks[bank * 4] = ~(uint64_t)0;
2485 }
2486 }
2487}
2488
Igor Mammedovbdeec802012-10-13 22:35:39 +02002489#ifndef CONFIG_USER_ONLY
Igor Mammedovd3c64d62013-04-05 16:36:54 +02002490static void x86_cpu_apic_create(X86CPU *cpu, Error **errp)
Igor Mammedovbdeec802012-10-13 22:35:39 +02002491{
Igor Mammedovbdeec802012-10-13 22:35:39 +02002492 CPUX86State *env = &cpu->env;
Igor Mammedov53a89e22013-04-29 19:03:01 +02002493 DeviceState *dev = DEVICE(cpu);
Andreas Färber449994e2012-10-10 12:18:02 +02002494 APICCommonState *apic;
Igor Mammedovbdeec802012-10-13 22:35:39 +02002495 const char *apic_type = "apic";
2496
2497 if (kvm_irqchip_in_kernel()) {
2498 apic_type = "kvm-apic";
2499 } else if (xen_enabled()) {
2500 apic_type = "xen-apic";
2501 }
2502
Chen Fan02e51482013-12-23 17:04:02 +08002503 cpu->apic_state = qdev_try_create(qdev_get_parent_bus(dev), apic_type);
2504 if (cpu->apic_state == NULL) {
Igor Mammedovbdeec802012-10-13 22:35:39 +02002505 error_setg(errp, "APIC device '%s' could not be created", apic_type);
2506 return;
2507 }
2508
2509 object_property_add_child(OBJECT(cpu), "apic",
Chen Fan02e51482013-12-23 17:04:02 +08002510 OBJECT(cpu->apic_state), NULL);
2511 qdev_prop_set_uint8(cpu->apic_state, "id", env->cpuid_apic_id);
Igor Mammedovbdeec802012-10-13 22:35:39 +02002512 /* TODO: convert to link<> */
Chen Fan02e51482013-12-23 17:04:02 +08002513 apic = APIC_COMMON(cpu->apic_state);
Andreas Färber60671e52012-10-10 14:10:07 +02002514 apic->cpu = cpu;
Igor Mammedovd3c64d62013-04-05 16:36:54 +02002515}
2516
2517static void x86_cpu_apic_realize(X86CPU *cpu, Error **errp)
2518{
Chen Fan02e51482013-12-23 17:04:02 +08002519 if (cpu->apic_state == NULL) {
Igor Mammedovd3c64d62013-04-05 16:36:54 +02002520 return;
2521 }
Igor Mammedovbdeec802012-10-13 22:35:39 +02002522
Chen Fan02e51482013-12-23 17:04:02 +08002523 if (qdev_init(cpu->apic_state)) {
Igor Mammedovbdeec802012-10-13 22:35:39 +02002524 error_setg(errp, "APIC device '%s' could not be initialized",
Chen Fan02e51482013-12-23 17:04:02 +08002525 object_get_typename(OBJECT(cpu->apic_state)));
Igor Mammedovbdeec802012-10-13 22:35:39 +02002526 return;
2527 }
Igor Mammedovbdeec802012-10-13 22:35:39 +02002528}
Igor Mammedovd3c64d62013-04-05 16:36:54 +02002529#else
2530static void x86_cpu_apic_realize(X86CPU *cpu, Error **errp)
2531{
2532}
Igor Mammedovbdeec802012-10-13 22:35:39 +02002533#endif
2534
Andreas Färber2b6f2942013-01-16 03:41:47 +01002535static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
Andreas Färber7a059952012-05-09 23:15:32 +02002536{
Andreas Färber14a10fc2013-07-27 02:53:25 +02002537 CPUState *cs = CPU(dev);
Andreas Färber2b6f2942013-01-16 03:41:47 +01002538 X86CPU *cpu = X86_CPU(dev);
2539 X86CPUClass *xcc = X86_CPU_GET_CLASS(dev);
Igor Mammedovb34d12d2012-10-22 17:03:00 +02002540 CPUX86State *env = &cpu->env;
Andreas Färber2b6f2942013-01-16 03:41:47 +01002541 Error *local_err = NULL;
Igor Mammedovb34d12d2012-10-22 17:03:00 +02002542
Eduardo Habkost0514ef22013-04-22 16:00:15 -03002543 if (env->features[FEAT_7_0_EBX] && env->cpuid_level < 7) {
Igor Mammedovb34d12d2012-10-22 17:03:00 +02002544 env->cpuid_level = 7;
2545 }
Andreas Färber7a059952012-05-09 23:15:32 +02002546
Igor Mammedov9b15cd92012-12-28 21:01:17 +01002547 /* On AMD CPUs, some CPUID[8000_0001].EDX bits must match the bits on
2548 * CPUID[1].EDX.
2549 */
2550 if (env->cpuid_vendor1 == CPUID_VENDOR_AMD_1 &&
2551 env->cpuid_vendor2 == CPUID_VENDOR_AMD_2 &&
2552 env->cpuid_vendor3 == CPUID_VENDOR_AMD_3) {
Eduardo Habkost0514ef22013-04-22 16:00:15 -03002553 env->features[FEAT_8000_0001_EDX] &= ~CPUID_EXT2_AMD_ALIASES;
2554 env->features[FEAT_8000_0001_EDX] |= (env->features[FEAT_1_EDX]
Igor Mammedov9b15cd92012-12-28 21:01:17 +01002555 & CPUID_EXT2_AMD_ALIASES);
2556 }
2557
Igor Mammedov4586f152012-12-28 21:01:16 +01002558 if (!kvm_enabled()) {
Eduardo Habkost0514ef22013-04-22 16:00:15 -03002559 env->features[FEAT_1_EDX] &= TCG_FEATURES;
2560 env->features[FEAT_1_ECX] &= TCG_EXT_FEATURES;
2561 env->features[FEAT_8000_0001_EDX] &= (TCG_EXT2_FEATURES
Igor Mammedov4586f152012-12-28 21:01:16 +01002562#ifdef TARGET_X86_64
2563 | CPUID_EXT2_SYSCALL | CPUID_EXT2_LM
2564#endif
2565 );
Eduardo Habkost0514ef22013-04-22 16:00:15 -03002566 env->features[FEAT_8000_0001_ECX] &= TCG_EXT3_FEATURES;
2567 env->features[FEAT_SVM] &= TCG_SVM_FEATURES;
Igor Mammedov4586f152012-12-28 21:01:16 +01002568 } else {
Igor Mammedov5ec01c22013-01-11 03:10:17 +01002569 if (check_cpuid && kvm_check_features_against_host(cpu)
2570 && enforce_cpuid) {
Igor Mammedov4dc1f442013-04-05 16:36:53 +02002571 error_setg(&local_err,
2572 "Host's CPU doesn't support requested features");
2573 goto out;
Igor Mammedov5ec01c22013-01-11 03:10:17 +01002574 }
Eduardo Habkosta509d632013-04-02 17:48:12 -03002575#ifdef CONFIG_KVM
2576 filter_features_for_kvm(cpu);
2577#endif
Igor Mammedov4586f152012-12-28 21:01:16 +01002578 }
2579
Igor Mammedov65dee382012-07-23 15:22:28 +02002580#ifndef CONFIG_USER_ONLY
2581 qemu_register_reset(x86_cpu_machine_reset_cb, cpu);
Igor Mammedovbdeec802012-10-13 22:35:39 +02002582
Eduardo Habkost0514ef22013-04-22 16:00:15 -03002583 if (cpu->env.features[FEAT_1_EDX] & CPUID_APIC || smp_cpus > 1) {
Igor Mammedovd3c64d62013-04-05 16:36:54 +02002584 x86_cpu_apic_create(cpu, &local_err);
Andreas Färber2b6f2942013-01-16 03:41:47 +01002585 if (local_err != NULL) {
Igor Mammedov4dc1f442013-04-05 16:36:53 +02002586 goto out;
Igor Mammedovbdeec802012-10-13 22:35:39 +02002587 }
2588 }
Igor Mammedov65dee382012-07-23 15:22:28 +02002589#endif
2590
Andreas Färber7a059952012-05-09 23:15:32 +02002591 mce_init(cpu);
Andreas Färber14a10fc2013-07-27 02:53:25 +02002592 qemu_init_vcpu(cs);
Igor Mammedovd3c64d62013-04-05 16:36:54 +02002593
2594 x86_cpu_apic_realize(cpu, &local_err);
2595 if (local_err != NULL) {
2596 goto out;
2597 }
Andreas Färber14a10fc2013-07-27 02:53:25 +02002598 cpu_reset(cs);
Andreas Färber2b6f2942013-01-16 03:41:47 +01002599
Igor Mammedov4dc1f442013-04-05 16:36:53 +02002600 xcc->parent_realize(dev, &local_err);
2601out:
2602 if (local_err != NULL) {
2603 error_propagate(errp, local_err);
2604 return;
2605 }
Andreas Färber7a059952012-05-09 23:15:32 +02002606}
2607
Eduardo Habkost8932cfd2013-01-22 18:25:09 -02002608/* Enables contiguous-apic-ID mode, for compatibility */
2609static bool compat_apic_id_mode;
2610
2611void enable_compat_apic_id_mode(void)
2612{
2613 compat_apic_id_mode = true;
2614}
2615
Eduardo Habkostcb41bad2013-01-22 18:25:04 -02002616/* Calculates initial APIC ID for a specific CPU index
2617 *
2618 * Currently we need to be able to calculate the APIC ID from the CPU index
2619 * alone (without requiring a CPU object), as the QEMU<->Seabios interfaces have
2620 * no concept of "CPU index", and the NUMA tables on fw_cfg need the APIC ID of
2621 * all CPUs up to max_cpus.
2622 */
2623uint32_t x86_cpu_apic_id_from_index(unsigned int cpu_index)
2624{
Eduardo Habkost8932cfd2013-01-22 18:25:09 -02002625 uint32_t correct_id;
2626 static bool warned;
2627
2628 correct_id = x86_apicid_from_cpu_idx(smp_cores, smp_threads, cpu_index);
2629 if (compat_apic_id_mode) {
2630 if (cpu_index != correct_id && !warned) {
2631 error_report("APIC IDs set in compatibility mode, "
2632 "CPU topology won't match the configuration");
2633 warned = true;
2634 }
2635 return cpu_index;
2636 } else {
2637 return correct_id;
2638 }
Eduardo Habkostcb41bad2013-01-22 18:25:04 -02002639}
2640
Andreas Färberde024812012-04-03 00:00:17 +02002641static void x86_cpu_initfn(Object *obj)
2642{
Andreas Färber55e5c282012-12-17 06:18:02 +01002643 CPUState *cs = CPU(obj);
Andreas Färberde024812012-04-03 00:00:17 +02002644 X86CPU *cpu = X86_CPU(obj);
2645 CPUX86State *env = &cpu->env;
Igor Mammedovd65e9812012-06-19 15:39:46 +02002646 static int inited;
Andreas Färberde024812012-04-03 00:00:17 +02002647
Andreas Färberc05efcb2013-01-17 12:13:41 +01002648 cs->env_ptr = env;
Andreas Färberde024812012-04-03 00:00:17 +02002649 cpu_exec_init(env);
Andreas Färber71ad61d2012-04-17 12:10:29 +02002650
2651 object_property_add(obj, "family", "int",
Andreas Färber95b85192012-04-17 14:42:22 +02002652 x86_cpuid_version_get_family,
Andreas Färber71ad61d2012-04-17 12:10:29 +02002653 x86_cpuid_version_set_family, NULL, NULL, NULL);
Andreas Färberc5291a42012-04-17 12:16:39 +02002654 object_property_add(obj, "model", "int",
Andreas Färber67e30c82012-04-17 14:48:14 +02002655 x86_cpuid_version_get_model,
Andreas Färberc5291a42012-04-17 12:16:39 +02002656 x86_cpuid_version_set_model, NULL, NULL, NULL);
Andreas Färber036e2222012-04-17 14:14:18 +02002657 object_property_add(obj, "stepping", "int",
Andreas Färber35112e42012-04-17 14:50:53 +02002658 x86_cpuid_version_get_stepping,
Andreas Färber036e2222012-04-17 14:14:18 +02002659 x86_cpuid_version_set_stepping, NULL, NULL, NULL);
Andreas Färber8e1898b2012-04-17 18:41:40 +02002660 object_property_add(obj, "level", "int",
2661 x86_cpuid_get_level,
2662 x86_cpuid_set_level, NULL, NULL, NULL);
Andreas Färber16b93aa2012-04-17 18:44:07 +02002663 object_property_add(obj, "xlevel", "int",
2664 x86_cpuid_get_xlevel,
2665 x86_cpuid_set_xlevel, NULL, NULL, NULL);
Andreas Färberd480e1a2012-04-17 19:22:58 +02002666 object_property_add_str(obj, "vendor",
2667 x86_cpuid_get_vendor,
2668 x86_cpuid_set_vendor, NULL);
Andreas Färber938d4c22012-04-17 15:17:27 +02002669 object_property_add_str(obj, "model-id",
Andreas Färber63e886e2012-04-17 23:02:26 +02002670 x86_cpuid_get_model_id,
Andreas Färber938d4c22012-04-17 15:17:27 +02002671 x86_cpuid_set_model_id, NULL);
Andreas Färber89e48962012-04-18 00:12:23 +02002672 object_property_add(obj, "tsc-frequency", "int",
2673 x86_cpuid_get_tsc_freq,
2674 x86_cpuid_set_tsc_freq, NULL, NULL, NULL);
Igor Mammedov31050932013-04-25 16:05:26 +02002675 object_property_add(obj, "apic-id", "int",
2676 x86_cpuid_get_apic_id,
2677 x86_cpuid_set_apic_id, NULL, NULL, NULL);
Eduardo Habkost8e8aba52013-05-06 13:20:07 -03002678 object_property_add(obj, "feature-words", "X86CPUFeatureWordInfo",
2679 x86_cpu_get_feature_words,
Eduardo Habkost7e5292b2013-05-06 13:20:09 -03002680 NULL, NULL, (void *)env->features, NULL);
2681 object_property_add(obj, "filtered-features", "X86CPUFeatureWordInfo",
2682 x86_cpu_get_feature_words,
2683 NULL, NULL, (void *)cpu->filtered_features, NULL);
Andreas Färber71ad61d2012-04-17 12:10:29 +02002684
Igor Mammedov92067bf2013-06-05 15:18:40 +02002685 cpu->hyperv_spinlock_attempts = HYPERV_SPINLOCK_NEVER_RETRY;
Eduardo Habkostcb41bad2013-01-22 18:25:04 -02002686 env->cpuid_apic_id = x86_cpu_apic_id_from_index(cs->cpu_index);
Igor Mammedovd65e9812012-06-19 15:39:46 +02002687
2688 /* init various static tables used in TCG mode */
2689 if (tcg_enabled() && !inited) {
2690 inited = 1;
2691 optimize_flags_init();
2692#ifndef CONFIG_USER_ONLY
2693 cpu_set_debug_excp_handler(breakpoint_handler);
2694#endif
2695 }
Andreas Färberde024812012-04-03 00:00:17 +02002696}
2697
Igor Mammedov997395d2013-04-23 10:29:41 +02002698static int64_t x86_cpu_get_arch_id(CPUState *cs)
2699{
2700 X86CPU *cpu = X86_CPU(cs);
2701 CPUX86State *env = &cpu->env;
2702
2703 return env->cpuid_apic_id;
2704}
2705
Andreas Färber444d5592013-05-28 13:28:38 +02002706static bool x86_cpu_get_paging_enabled(const CPUState *cs)
2707{
2708 X86CPU *cpu = X86_CPU(cs);
2709
2710 return cpu->env.cr[0] & CR0_PG_MASK;
2711}
2712
Andreas Färberf45748f2013-06-21 19:09:18 +02002713static void x86_cpu_set_pc(CPUState *cs, vaddr value)
2714{
2715 X86CPU *cpu = X86_CPU(cs);
2716
2717 cpu->env.eip = value;
2718}
2719
Andreas Färberbdf7ae52013-06-28 19:31:32 +02002720static void x86_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
2721{
2722 X86CPU *cpu = X86_CPU(cs);
2723
2724 cpu->env.eip = tb->pc - tb->cs_base;
2725}
2726
Eduardo Habkost9337e3b2013-07-26 17:09:36 -03002727static Property x86_cpu_properties[] = {
2728 DEFINE_PROP_BOOL("pmu", X86CPU, enable_pmu, false),
2729 DEFINE_PROP_END_OF_LIST()
2730};
2731
Andreas Färber5fd20872012-04-02 23:20:08 +02002732static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
2733{
2734 X86CPUClass *xcc = X86_CPU_CLASS(oc);
2735 CPUClass *cc = CPU_CLASS(oc);
Andreas Färber2b6f2942013-01-16 03:41:47 +01002736 DeviceClass *dc = DEVICE_CLASS(oc);
2737
2738 xcc->parent_realize = dc->realize;
2739 dc->realize = x86_cpu_realizefn;
Igor Mammedov62fc4032013-04-29 18:54:13 +02002740 dc->bus_type = TYPE_ICC_BUS;
Eduardo Habkost9337e3b2013-07-26 17:09:36 -03002741 dc->props = x86_cpu_properties;
Andreas Färber5fd20872012-04-02 23:20:08 +02002742
2743 xcc->parent_reset = cc->reset;
2744 cc->reset = x86_cpu_reset;
Andreas Färber91b1df82013-06-16 07:49:48 +02002745 cc->reset_dump_flags = CPU_DUMP_FPU | CPU_DUMP_CCOP;
Andreas Färberf56e3a12013-02-02 13:38:08 +01002746
Andreas Färber97a8ea52013-02-02 10:57:51 +01002747 cc->do_interrupt = x86_cpu_do_interrupt;
Andreas Färber878096e2013-05-27 01:33:50 +02002748 cc->dump_state = x86_cpu_dump_state;
Andreas Färberf45748f2013-06-21 19:09:18 +02002749 cc->set_pc = x86_cpu_set_pc;
Andreas Färberbdf7ae52013-06-28 19:31:32 +02002750 cc->synchronize_from_tb = x86_cpu_synchronize_from_tb;
Andreas Färber5b50e792013-06-29 04:18:45 +02002751 cc->gdb_read_register = x86_cpu_gdb_read_register;
2752 cc->gdb_write_register = x86_cpu_gdb_write_register;
Andreas Färber444d5592013-05-28 13:28:38 +02002753 cc->get_arch_id = x86_cpu_get_arch_id;
2754 cc->get_paging_enabled = x86_cpu_get_paging_enabled;
Jens Freimannc72bf462013-04-19 16:45:06 +02002755#ifndef CONFIG_USER_ONLY
Andreas Färbera23bbfd2013-05-28 13:52:01 +02002756 cc->get_memory_mapping = x86_cpu_get_memory_mapping;
Andreas Färber00b941e2013-06-29 18:55:54 +02002757 cc->get_phys_page_debug = x86_cpu_get_phys_page_debug;
Jens Freimannc72bf462013-04-19 16:45:06 +02002758 cc->write_elf64_note = x86_cpu_write_elf64_note;
2759 cc->write_elf64_qemunote = x86_cpu_write_elf64_qemunote;
2760 cc->write_elf32_note = x86_cpu_write_elf32_note;
2761 cc->write_elf32_qemunote = x86_cpu_write_elf32_qemunote;
Andreas Färber00b941e2013-06-29 18:55:54 +02002762 cc->vmsd = &vmstate_x86_cpu;
Jens Freimannc72bf462013-04-19 16:45:06 +02002763#endif
Andreas Färbera0e372f2013-06-28 23:18:47 +02002764 cc->gdb_num_core_regs = CPU_NB_REGS * 2 + 25;
Andreas Färber5fd20872012-04-02 23:20:08 +02002765}
2766
2767static const TypeInfo x86_cpu_type_info = {
2768 .name = TYPE_X86_CPU,
2769 .parent = TYPE_CPU,
2770 .instance_size = sizeof(X86CPU),
Andreas Färberde024812012-04-03 00:00:17 +02002771 .instance_init = x86_cpu_initfn,
Andreas Färber5fd20872012-04-02 23:20:08 +02002772 .abstract = false,
2773 .class_size = sizeof(X86CPUClass),
2774 .class_init = x86_cpu_common_class_init,
2775};
2776
2777static void x86_cpu_register_types(void)
2778{
2779 type_register_static(&x86_cpu_type_info);
2780}
2781
2782type_init(x86_cpu_register_types)