blob: f4b420f9667365844900d067c73a1f6091f15f04 [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"
Paolo Bonzini50a2c6e2013-03-20 13:11:56 +010027#include "kvm_i386.h"
Andre Przywarac6dc6f62010-03-11 14:38:55 +010028
Markus Armbrusterd49b6832015-03-17 18:29:20 +010029#include "qemu/error-report.h"
Paolo Bonzini1de7afc2012-12-17 18:20:00 +010030#include "qemu/option.h"
31#include "qemu/config-file.h"
Paolo Bonzini7b1b5d12012-12-17 18:19:43 +010032#include "qapi/qmp/qerror.h"
Andre Przywarac6dc6f62010-03-11 14:38:55 +010033
Eduardo Habkost8e8aba52013-05-06 13:20:07 -030034#include "qapi-types.h"
35#include "qapi-visit.h"
Paolo Bonzini7b1b5d12012-12-17 18:19:43 +010036#include "qapi/visitor.h"
Paolo Bonzini9c17d612012-12-17 18:20:04 +010037#include "sysemu/arch_init.h"
Andreas Färber71ad61d2012-04-17 12:10:29 +020038
Igor Mammedov65dee382012-07-23 15:22:28 +020039#include "hw/hw.h"
Stefan Weilb834b502012-08-30 22:28:31 +020040#if defined(CONFIG_KVM)
Anthony Liguorief8621b2012-08-29 09:32:41 -050041#include <linux/kvm_para.h>
Stefan Weilb834b502012-08-30 22:28:31 +020042#endif
Igor Mammedov65dee382012-07-23 15:22:28 +020043
Paolo Bonzini9c17d612012-12-17 18:20:04 +010044#include "sysemu/sysemu.h"
Igor Mammedov53a89e22013-04-29 19:03:01 +020045#include "hw/qdev-properties.h"
Igor Mammedovbdeec802012-10-13 22:35:39 +020046#ifndef CONFIG_USER_ONLY
Paolo Bonzini2001d0c2015-03-31 14:11:09 +020047#include "exec/address-spaces.h"
Paolo Bonzini0d09e412013-02-05 17:06:20 +010048#include "hw/xen/xen.h"
Paolo Bonzini0d09e412013-02-05 17:06:20 +010049#include "hw/i386/apic_internal.h"
Igor Mammedovbdeec802012-10-13 22:35:39 +020050#endif
51
Eduardo Habkost5e891bf2013-08-27 12:24:37 -030052
53/* Cache topology CPUID constants: */
54
55/* CPUID Leaf 2 Descriptors */
56
57#define CPUID_2_L1D_32KB_8WAY_64B 0x2c
58#define CPUID_2_L1I_32KB_8WAY_64B 0x30
59#define CPUID_2_L2_2MB_8WAY_64B 0x7d
60
61
62/* CPUID Leaf 4 constants: */
63
64/* EAX: */
65#define CPUID_4_TYPE_DCACHE 1
66#define CPUID_4_TYPE_ICACHE 2
67#define CPUID_4_TYPE_UNIFIED 3
68
69#define CPUID_4_LEVEL(l) ((l) << 5)
70
71#define CPUID_4_SELF_INIT_LEVEL (1 << 8)
72#define CPUID_4_FULLY_ASSOC (1 << 9)
73
74/* EDX: */
75#define CPUID_4_NO_INVD_SHARING (1 << 0)
76#define CPUID_4_INCLUSIVE (1 << 1)
77#define CPUID_4_COMPLEX_IDX (1 << 2)
78
79#define ASSOC_FULL 0xFF
80
81/* AMD associativity encoding used on CPUID Leaf 0x80000006: */
82#define AMD_ENC_ASSOC(a) (a <= 1 ? a : \
83 a == 2 ? 0x2 : \
84 a == 4 ? 0x4 : \
85 a == 8 ? 0x6 : \
86 a == 16 ? 0x8 : \
87 a == 32 ? 0xA : \
88 a == 48 ? 0xB : \
89 a == 64 ? 0xC : \
90 a == 96 ? 0xD : \
91 a == 128 ? 0xE : \
92 a == ASSOC_FULL ? 0xF : \
93 0 /* invalid value */)
94
95
96/* Definitions of the hardcoded cache entries we expose: */
97
98/* L1 data cache: */
99#define L1D_LINE_SIZE 64
100#define L1D_ASSOCIATIVITY 8
101#define L1D_SETS 64
102#define L1D_PARTITIONS 1
103/* Size = LINE_SIZE*ASSOCIATIVITY*SETS*PARTITIONS = 32KiB */
104#define L1D_DESCRIPTOR CPUID_2_L1D_32KB_8WAY_64B
105/*FIXME: CPUID leaf 0x80000005 is inconsistent with leaves 2 & 4 */
106#define L1D_LINES_PER_TAG 1
107#define L1D_SIZE_KB_AMD 64
108#define L1D_ASSOCIATIVITY_AMD 2
109
110/* L1 instruction cache: */
111#define L1I_LINE_SIZE 64
112#define L1I_ASSOCIATIVITY 8
113#define L1I_SETS 64
114#define L1I_PARTITIONS 1
115/* Size = LINE_SIZE*ASSOCIATIVITY*SETS*PARTITIONS = 32KiB */
116#define L1I_DESCRIPTOR CPUID_2_L1I_32KB_8WAY_64B
117/*FIXME: CPUID leaf 0x80000005 is inconsistent with leaves 2 & 4 */
118#define L1I_LINES_PER_TAG 1
119#define L1I_SIZE_KB_AMD 64
120#define L1I_ASSOCIATIVITY_AMD 2
121
122/* Level 2 unified cache: */
123#define L2_LINE_SIZE 64
124#define L2_ASSOCIATIVITY 16
125#define L2_SETS 4096
126#define L2_PARTITIONS 1
127/* Size = LINE_SIZE*ASSOCIATIVITY*SETS*PARTITIONS = 4MiB */
128/*FIXME: CPUID leaf 2 descriptor is inconsistent with CPUID leaf 4 */
129#define L2_DESCRIPTOR CPUID_2_L2_2MB_8WAY_64B
130/*FIXME: CPUID leaf 0x80000006 is inconsistent with leaves 2 & 4 */
131#define L2_LINES_PER_TAG 1
132#define L2_SIZE_KB_AMD 512
133
134/* No L3 cache: */
135#define L3_SIZE_KB 0 /* disabled */
136#define L3_ASSOCIATIVITY 0 /* disabled */
137#define L3_LINES_PER_TAG 0 /* disabled */
138#define L3_LINE_SIZE 0 /* disabled */
139
140/* TLB definitions: */
141
142#define L1_DTLB_2M_ASSOC 1
143#define L1_DTLB_2M_ENTRIES 255
144#define L1_DTLB_4K_ASSOC 1
145#define L1_DTLB_4K_ENTRIES 255
146
147#define L1_ITLB_2M_ASSOC 1
148#define L1_ITLB_2M_ENTRIES 255
149#define L1_ITLB_4K_ASSOC 1
150#define L1_ITLB_4K_ENTRIES 255
151
152#define L2_DTLB_2M_ASSOC 0 /* disabled */
153#define L2_DTLB_2M_ENTRIES 0 /* disabled */
154#define L2_DTLB_4K_ASSOC 4
155#define L2_DTLB_4K_ENTRIES 512
156
157#define L2_ITLB_2M_ASSOC 0 /* disabled */
158#define L2_ITLB_2M_ENTRIES 0 /* disabled */
159#define L2_ITLB_4K_ASSOC 4
160#define L2_ITLB_4K_ENTRIES 512
161
162
163
Igor Mammedov99b88a12013-01-21 15:06:36 +0100164static void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1,
165 uint32_t vendor2, uint32_t vendor3)
166{
167 int i;
168 for (i = 0; i < 4; i++) {
169 dst[i] = vendor1 >> (8 * i);
170 dst[i + 4] = vendor2 >> (8 * i);
171 dst[i + 8] = vendor3 >> (8 * i);
172 }
173 dst[CPUID_VENDOR_SZ] = '\0';
174}
175
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100176/* feature flags taken from "Intel Processor Identification and the CPUID
177 * Instruction" and AMD's "CPUID Specification". In cases of disagreement
178 * between feature naming conventions, aliases may be added.
179 */
180static const char *feature_name[] = {
181 "fpu", "vme", "de", "pse",
182 "tsc", "msr", "pae", "mce",
183 "cx8", "apic", NULL, "sep",
184 "mtrr", "pge", "mca", "cmov",
185 "pat", "pse36", "pn" /* Intel psn */, "clflush" /* Intel clfsh */,
186 NULL, "ds" /* Intel dts */, "acpi", "mmx",
187 "fxsr", "sse", "sse2", "ss",
188 "ht" /* Intel htt */, "tm", "ia64", "pbe",
189};
190static const char *ext_feature_name[] = {
Eduardo Habkostf370be32012-02-17 14:41:20 -0200191 "pni|sse3" /* Intel,AMD sse3 */, "pclmulqdq|pclmuldq", "dtes64", "monitor",
Andre Przywarae117f772010-03-11 14:38:59 +0100192 "ds_cpl", "vmx", "smx", "est",
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100193 "tm2", "ssse3", "cid", NULL,
Andre Przywarae117f772010-03-11 14:38:59 +0100194 "fma", "cx16", "xtpr", "pdcm",
Mao, Junjie434acb82012-07-20 07:08:21 +0000195 NULL, "pcid", "dca", "sse4.1|sse4_1",
Andre Przywarae117f772010-03-11 14:38:59 +0100196 "sse4.2|sse4_2", "x2apic", "movbe", "popcnt",
Eduardo Habkosteaf3f092012-03-06 15:11:30 -0300197 "tsc-deadline", "aes", "xsave", "osxsave",
Andre Przywarac8acc382012-11-14 16:28:52 -0200198 "avx", "f16c", "rdrand", "hypervisor",
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100199};
Eduardo Habkost3b671a42012-09-06 10:05:38 +0000200/* Feature names that are already defined on feature_name[] but are set on
201 * CPUID[8000_0001].EDX on AMD CPUs don't have their names on
202 * ext2_feature_name[]. They are copied automatically to cpuid_ext2_features
203 * if and only if CPU vendor is AMD.
204 */
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100205static const char *ext2_feature_name[] = {
Eduardo Habkost3b671a42012-09-06 10:05:38 +0000206 NULL /* fpu */, NULL /* vme */, NULL /* de */, NULL /* pse */,
207 NULL /* tsc */, NULL /* msr */, NULL /* pae */, NULL /* mce */,
208 NULL /* cx8 */ /* AMD CMPXCHG8B */, NULL /* apic */, NULL, "syscall",
209 NULL /* mtrr */, NULL /* pge */, NULL /* mca */, NULL /* cmov */,
210 NULL /* pat */, NULL /* pse36 */, NULL, NULL /* Linux mp */,
211 "nx|xd", NULL, "mmxext", NULL /* mmx */,
212 NULL /* fxsr */, "fxsr_opt|ffxsr", "pdpe1gb" /* AMD Page1GB */, "rdtscp",
Eduardo Habkost01f590d2012-10-24 12:10:33 -0200213 NULL, "lm|i64", "3dnowext", "3dnow",
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100214};
215static const char *ext3_feature_name[] = {
216 "lahf_lm" /* AMD LahfSahf */, "cmp_legacy", "svm", "extapic" /* AMD ExtApicSpace */,
217 "cr8legacy" /* AMD AltMovCr8 */, "abm", "sse4a", "misalignsse",
Andre Przywarae117f772010-03-11 14:38:59 +0100218 "3dnowprefetch", "osvw", "ibs", "xop",
Andre Przywarac8acc382012-11-14 16:28:52 -0200219 "skinit", "wdt", NULL, "lwp",
220 "fma4", "tce", NULL, "nodeid_msr",
221 NULL, "tbm", "topoext", "perfctr_core",
222 "perfctr_nb", NULL, NULL, NULL,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100223 NULL, NULL, NULL, NULL,
224};
225
Eduardo Habkost89e49c82013-01-07 16:20:47 -0200226static const char *ext4_feature_name[] = {
227 NULL, NULL, "xstore", "xstore-en",
228 NULL, NULL, "xcrypt", "xcrypt-en",
229 "ace2", "ace2-en", "phe", "phe-en",
230 "pmm", "pmm-en", NULL, NULL,
231 NULL, NULL, NULL, NULL,
232 NULL, NULL, NULL, NULL,
233 NULL, NULL, NULL, NULL,
234 NULL, NULL, NULL, NULL,
235};
236
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100237static const char *kvm_feature_name[] = {
Don Slutzc3d39802012-10-12 15:43:23 -0400238 "kvmclock", "kvm_nopiodelay", "kvm_mmu", "kvmclock",
Andrew Jonesf010bc62013-09-18 16:41:45 +0200239 "kvm_asyncpf", "kvm_steal_time", "kvm_pv_eoi", "kvm_pv_unhalt",
Don Slutzc3d39802012-10-12 15:43:23 -0400240 NULL, NULL, NULL, NULL,
241 NULL, NULL, NULL, NULL,
242 NULL, NULL, NULL, NULL,
243 NULL, NULL, NULL, NULL,
Eduardo Habkost8248c362014-07-04 16:44:34 -0300244 "kvmclock-stable-bit", NULL, NULL, NULL,
Don Slutzc3d39802012-10-12 15:43:23 -0400245 NULL, NULL, NULL, NULL,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100246};
247
Joerg Roedel296acb62010-09-27 15:16:17 +0200248static const char *svm_feature_name[] = {
249 "npt", "lbrv", "svm_lock", "nrip_save",
250 "tsc_scale", "vmcb_clean", "flushbyasid", "decodeassists",
251 NULL, NULL, "pause_filter", NULL,
252 "pfthreshold", NULL, NULL, NULL,
253 NULL, NULL, NULL, NULL,
254 NULL, NULL, NULL, NULL,
255 NULL, NULL, NULL, NULL,
256 NULL, NULL, NULL, NULL,
257};
258
H. Peter Anvina9321a42012-09-26 13:18:43 -0700259static const char *cpuid_7_0_ebx_feature_name[] = {
Eduardo Habkost7b458bf2014-08-25 17:02:13 -0300260 "fsgsbase", "tsc_adjust", NULL, "bmi1", "hle", "avx2", NULL, "smep",
Eduardo Habkost5bd8ff02014-08-25 17:02:12 -0300261 "bmi2", "erms", "invpcid", "rtm", NULL, NULL, "mpx", NULL,
Xiao Guangrongf7fda282015-10-29 15:31:39 +0800262 "avx512f", NULL, "rdseed", "adx", "smap", NULL, "pcommit", "clflushopt",
263 "clwb", NULL, "avx512pf", "avx512er", "avx512cd", NULL, NULL, NULL,
H. Peter Anvina9321a42012-09-26 13:18:43 -0700264};
265
Huaitong Hanf74eefe2015-11-18 10:20:15 +0800266static const char *cpuid_7_0_ecx_feature_name[] = {
267 NULL, NULL, NULL, "pku",
268 "ospke", NULL, NULL, NULL,
269 NULL, NULL, NULL, NULL,
270 NULL, NULL, NULL, NULL,
271 NULL, NULL, NULL, NULL,
272 NULL, NULL, NULL, NULL,
273 NULL, NULL, NULL, NULL,
274 NULL, NULL, NULL, NULL,
275};
276
Marcelo Tosatti303752a2014-04-30 13:48:45 -0300277static const char *cpuid_apm_edx_feature_name[] = {
278 NULL, NULL, NULL, NULL,
279 NULL, NULL, NULL, NULL,
280 "invtsc", NULL, NULL, NULL,
281 NULL, NULL, NULL, NULL,
282 NULL, NULL, NULL, NULL,
283 NULL, NULL, NULL, NULL,
284 NULL, NULL, NULL, NULL,
285 NULL, NULL, NULL, NULL,
286};
287
Paolo Bonzini0bb0b2d2014-11-24 15:54:43 +0100288static const char *cpuid_xsave_feature_name[] = {
289 "xsaveopt", "xsavec", "xgetbv1", "xsaves",
290 NULL, NULL, NULL, NULL,
291 NULL, NULL, NULL, NULL,
292 NULL, NULL, NULL, NULL,
293 NULL, NULL, NULL, NULL,
294 NULL, NULL, NULL, NULL,
295 NULL, NULL, NULL, NULL,
296 NULL, NULL, NULL, NULL,
297};
298
Jan Kiszka28b8e4d2015-06-07 11:15:08 +0200299static const char *cpuid_6_feature_name[] = {
300 NULL, NULL, "arat", NULL,
301 NULL, NULL, NULL, NULL,
302 NULL, NULL, NULL, NULL,
303 NULL, NULL, NULL, NULL,
304 NULL, NULL, NULL, NULL,
305 NULL, NULL, NULL, NULL,
306 NULL, NULL, NULL, NULL,
307 NULL, NULL, NULL, NULL,
308};
309
Eduardo Habkost621626c2014-04-30 13:48:36 -0300310#define I486_FEATURES (CPUID_FP87 | CPUID_VME | CPUID_PSE)
311#define PENTIUM_FEATURES (I486_FEATURES | CPUID_DE | CPUID_TSC | \
312 CPUID_MSR | CPUID_MCE | CPUID_CX8 | CPUID_MMX | CPUID_APIC)
313#define PENTIUM2_FEATURES (PENTIUM_FEATURES | CPUID_PAE | CPUID_SEP | \
314 CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_CMOV | CPUID_PAT | \
315 CPUID_PSE36 | CPUID_FXSR)
316#define PENTIUM3_FEATURES (PENTIUM2_FEATURES | CPUID_SSE)
317#define PPRO_FEATURES (CPUID_FP87 | CPUID_DE | CPUID_PSE | CPUID_TSC | \
318 CPUID_MSR | CPUID_MCE | CPUID_CX8 | CPUID_PGE | CPUID_CMOV | \
319 CPUID_PAT | CPUID_FXSR | CPUID_MMX | CPUID_SSE | CPUID_SSE2 | \
320 CPUID_PAE | CPUID_SEP | CPUID_APIC)
321
322#define TCG_FEATURES (CPUID_FP87 | CPUID_PSE | CPUID_TSC | CPUID_MSR | \
323 CPUID_PAE | CPUID_MCE | CPUID_CX8 | CPUID_APIC | CPUID_SEP | \
324 CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_CMOV | CPUID_PAT | \
325 CPUID_PSE36 | CPUID_CLFLUSH | CPUID_ACPI | CPUID_MMX | \
Eduardo Habkostb6c5a6f2015-10-07 16:39:43 -0300326 CPUID_FXSR | CPUID_SSE | CPUID_SSE2 | CPUID_SS | CPUID_DE)
Eduardo Habkost621626c2014-04-30 13:48:36 -0300327 /* partly implemented:
328 CPUID_MTRR, CPUID_MCA, CPUID_CLFLUSH (needed for Win64) */
329 /* missing:
330 CPUID_VME, CPUID_DTS, CPUID_SS, CPUID_HT, CPUID_TM, CPUID_PBE */
331#define TCG_EXT_FEATURES (CPUID_EXT_SSE3 | CPUID_EXT_PCLMULQDQ | \
332 CPUID_EXT_MONITOR | CPUID_EXT_SSSE3 | CPUID_EXT_CX16 | \
333 CPUID_EXT_SSE41 | CPUID_EXT_SSE42 | CPUID_EXT_POPCNT | \
334 CPUID_EXT_MOVBE | CPUID_EXT_AES | CPUID_EXT_HYPERVISOR)
335 /* missing:
336 CPUID_EXT_DTES64, CPUID_EXT_DSCPL, CPUID_EXT_VMX, CPUID_EXT_SMX,
337 CPUID_EXT_EST, CPUID_EXT_TM2, CPUID_EXT_CID, CPUID_EXT_FMA,
338 CPUID_EXT_XTPR, CPUID_EXT_PDCM, CPUID_EXT_PCID, CPUID_EXT_DCA,
339 CPUID_EXT_X2APIC, CPUID_EXT_TSC_DEADLINE_TIMER, CPUID_EXT_XSAVE,
340 CPUID_EXT_OSXSAVE, CPUID_EXT_AVX, CPUID_EXT_F16C,
341 CPUID_EXT_RDRAND */
342
343#ifdef TARGET_X86_64
344#define TCG_EXT2_X86_64_FEATURES (CPUID_EXT2_SYSCALL | CPUID_EXT2_LM)
345#else
346#define TCG_EXT2_X86_64_FEATURES 0
347#endif
348
349#define TCG_EXT2_FEATURES ((TCG_FEATURES & CPUID_EXT2_AMD_ALIASES) | \
350 CPUID_EXT2_NX | CPUID_EXT2_MMXEXT | CPUID_EXT2_RDTSCP | \
351 CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT | CPUID_EXT2_PDPE1GB | \
352 TCG_EXT2_X86_64_FEATURES)
353#define TCG_EXT3_FEATURES (CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM | \
354 CPUID_EXT3_CR8LEG | CPUID_EXT3_ABM | CPUID_EXT3_SSE4A)
355#define TCG_EXT4_FEATURES 0
356#define TCG_SVM_FEATURES 0
357#define TCG_KVM_FEATURES 0
358#define TCG_7_0_EBX_FEATURES (CPUID_7_0_EBX_SMEP | CPUID_7_0_EBX_SMAP | \
Xiao Guangrong0c472422015-10-29 15:31:39 +0800359 CPUID_7_0_EBX_BMI1 | CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ADX | \
360 CPUID_7_0_EBX_PCOMMIT | CPUID_7_0_EBX_CLFLUSHOPT | \
361 CPUID_7_0_EBX_CLWB)
Eduardo Habkost621626c2014-04-30 13:48:36 -0300362 /* missing:
363 CPUID_7_0_EBX_FSGSBASE, CPUID_7_0_EBX_HLE, CPUID_7_0_EBX_AVX2,
364 CPUID_7_0_EBX_ERMS, CPUID_7_0_EBX_INVPCID, CPUID_7_0_EBX_RTM,
365 CPUID_7_0_EBX_RDSEED */
Huaitong Hanf74eefe2015-11-18 10:20:15 +0800366#define TCG_7_0_ECX_FEATURES 0
Marcelo Tosatti303752a2014-04-30 13:48:45 -0300367#define TCG_APM_FEATURES 0
Jan Kiszka28b8e4d2015-06-07 11:15:08 +0200368#define TCG_6_EAX_FEATURES CPUID_6_EAX_ARAT
Eduardo Habkost621626c2014-04-30 13:48:36 -0300369
370
Eduardo Habkost5ef57872013-01-07 16:20:45 -0200371typedef struct FeatureWordInfo {
372 const char **feat_names;
Eduardo Habkost04d104b2013-04-22 16:00:16 -0300373 uint32_t cpuid_eax; /* Input EAX for CPUID */
374 bool cpuid_needs_ecx; /* CPUID instruction uses ECX as input */
375 uint32_t cpuid_ecx; /* Input ECX value for CPUID */
376 int cpuid_reg; /* output register (R_* constant) */
Eduardo Habkost37ce3522014-04-30 13:48:38 -0300377 uint32_t tcg_features; /* Feature flags supported by TCG */
Eduardo Habkost84f1b922014-04-30 13:48:41 -0300378 uint32_t unmigratable_flags; /* Feature flags known to be unmigratable */
Eduardo Habkost5ef57872013-01-07 16:20:45 -0200379} FeatureWordInfo;
380
381static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
Eduardo Habkostbffd67b2013-01-07 16:20:46 -0200382 [FEAT_1_EDX] = {
383 .feat_names = feature_name,
384 .cpuid_eax = 1, .cpuid_reg = R_EDX,
Eduardo Habkost37ce3522014-04-30 13:48:38 -0300385 .tcg_features = TCG_FEATURES,
Eduardo Habkostbffd67b2013-01-07 16:20:46 -0200386 },
387 [FEAT_1_ECX] = {
388 .feat_names = ext_feature_name,
389 .cpuid_eax = 1, .cpuid_reg = R_ECX,
Eduardo Habkost37ce3522014-04-30 13:48:38 -0300390 .tcg_features = TCG_EXT_FEATURES,
Eduardo Habkostbffd67b2013-01-07 16:20:46 -0200391 },
392 [FEAT_8000_0001_EDX] = {
393 .feat_names = ext2_feature_name,
394 .cpuid_eax = 0x80000001, .cpuid_reg = R_EDX,
Eduardo Habkost37ce3522014-04-30 13:48:38 -0300395 .tcg_features = TCG_EXT2_FEATURES,
Eduardo Habkostbffd67b2013-01-07 16:20:46 -0200396 },
397 [FEAT_8000_0001_ECX] = {
398 .feat_names = ext3_feature_name,
399 .cpuid_eax = 0x80000001, .cpuid_reg = R_ECX,
Eduardo Habkost37ce3522014-04-30 13:48:38 -0300400 .tcg_features = TCG_EXT3_FEATURES,
Eduardo Habkostbffd67b2013-01-07 16:20:46 -0200401 },
Eduardo Habkost89e49c82013-01-07 16:20:47 -0200402 [FEAT_C000_0001_EDX] = {
403 .feat_names = ext4_feature_name,
404 .cpuid_eax = 0xC0000001, .cpuid_reg = R_EDX,
Eduardo Habkost37ce3522014-04-30 13:48:38 -0300405 .tcg_features = TCG_EXT4_FEATURES,
Eduardo Habkost89e49c82013-01-07 16:20:47 -0200406 },
Eduardo Habkostbffd67b2013-01-07 16:20:46 -0200407 [FEAT_KVM] = {
408 .feat_names = kvm_feature_name,
409 .cpuid_eax = KVM_CPUID_FEATURES, .cpuid_reg = R_EAX,
Eduardo Habkost37ce3522014-04-30 13:48:38 -0300410 .tcg_features = TCG_KVM_FEATURES,
Eduardo Habkostbffd67b2013-01-07 16:20:46 -0200411 },
412 [FEAT_SVM] = {
413 .feat_names = svm_feature_name,
414 .cpuid_eax = 0x8000000A, .cpuid_reg = R_EDX,
Eduardo Habkost37ce3522014-04-30 13:48:38 -0300415 .tcg_features = TCG_SVM_FEATURES,
Eduardo Habkostbffd67b2013-01-07 16:20:46 -0200416 },
417 [FEAT_7_0_EBX] = {
418 .feat_names = cpuid_7_0_ebx_feature_name,
Eduardo Habkost04d104b2013-04-22 16:00:16 -0300419 .cpuid_eax = 7,
420 .cpuid_needs_ecx = true, .cpuid_ecx = 0,
421 .cpuid_reg = R_EBX,
Eduardo Habkost37ce3522014-04-30 13:48:38 -0300422 .tcg_features = TCG_7_0_EBX_FEATURES,
Eduardo Habkostbffd67b2013-01-07 16:20:46 -0200423 },
Huaitong Hanf74eefe2015-11-18 10:20:15 +0800424 [FEAT_7_0_ECX] = {
425 .feat_names = cpuid_7_0_ecx_feature_name,
426 .cpuid_eax = 7,
427 .cpuid_needs_ecx = true, .cpuid_ecx = 0,
428 .cpuid_reg = R_ECX,
429 .tcg_features = TCG_7_0_ECX_FEATURES,
430 },
Marcelo Tosatti303752a2014-04-30 13:48:45 -0300431 [FEAT_8000_0007_EDX] = {
432 .feat_names = cpuid_apm_edx_feature_name,
433 .cpuid_eax = 0x80000007,
434 .cpuid_reg = R_EDX,
435 .tcg_features = TCG_APM_FEATURES,
436 .unmigratable_flags = CPUID_APM_INVTSC,
437 },
Paolo Bonzini0bb0b2d2014-11-24 15:54:43 +0100438 [FEAT_XSAVE] = {
439 .feat_names = cpuid_xsave_feature_name,
440 .cpuid_eax = 0xd,
441 .cpuid_needs_ecx = true, .cpuid_ecx = 1,
442 .cpuid_reg = R_EAX,
443 .tcg_features = 0,
Paolo Bonzini0bb0b2d2014-11-24 15:54:43 +0100444 },
Jan Kiszka28b8e4d2015-06-07 11:15:08 +0200445 [FEAT_6_EAX] = {
446 .feat_names = cpuid_6_feature_name,
447 .cpuid_eax = 6, .cpuid_reg = R_EAX,
448 .tcg_features = TCG_6_EAX_FEATURES,
449 },
Eduardo Habkost5ef57872013-01-07 16:20:45 -0200450};
451
Eduardo Habkost8e8aba52013-05-06 13:20:07 -0300452typedef struct X86RegisterInfo32 {
453 /* Name of register */
454 const char *name;
455 /* QAPI enum value register */
456 X86CPURegister32 qapi_enum;
457} X86RegisterInfo32;
458
459#define REGISTER(reg) \
Wenchao Xia5d371f42014-03-04 18:44:40 -0800460 [R_##reg] = { .name = #reg, .qapi_enum = X86_CPU_REGISTER32_##reg }
Stefan Weila443bc32014-03-16 15:03:41 +0100461static const X86RegisterInfo32 x86_reg_info_32[CPU_NB_REGS32] = {
Eduardo Habkost8e8aba52013-05-06 13:20:07 -0300462 REGISTER(EAX),
463 REGISTER(ECX),
464 REGISTER(EDX),
465 REGISTER(EBX),
466 REGISTER(ESP),
467 REGISTER(EBP),
468 REGISTER(ESI),
469 REGISTER(EDI),
470};
471#undef REGISTER
472
Paolo Bonzini2560f192013-10-02 17:54:57 +0200473typedef struct ExtSaveArea {
474 uint32_t feature, bits;
475 uint32_t offset, size;
476} ExtSaveArea;
477
478static const ExtSaveArea ext_save_areas[] = {
479 [2] = { .feature = FEAT_1_ECX, .bits = CPUID_EXT_AVX,
Liu Jinsong33f373d2013-12-03 04:17:50 +0800480 .offset = 0x240, .size = 0x100 },
Liu Jinsong79e9ebe2013-12-05 08:32:12 +0800481 [3] = { .feature = FEAT_7_0_EBX, .bits = CPUID_7_0_EBX_MPX,
482 .offset = 0x3c0, .size = 0x40 },
483 [4] = { .feature = FEAT_7_0_EBX, .bits = CPUID_7_0_EBX_MPX,
Liu, Jinsongb0f15a52014-03-03 05:24:14 +0000484 .offset = 0x400, .size = 0x40 },
Chao Peng9aecd6f2014-10-23 11:02:43 +0800485 [5] = { .feature = FEAT_7_0_EBX, .bits = CPUID_7_0_EBX_AVX512F,
486 .offset = 0x440, .size = 0x40 },
487 [6] = { .feature = FEAT_7_0_EBX, .bits = CPUID_7_0_EBX_AVX512F,
488 .offset = 0x480, .size = 0x200 },
489 [7] = { .feature = FEAT_7_0_EBX, .bits = CPUID_7_0_EBX_AVX512F,
490 .offset = 0x680, .size = 0x400 },
Huaitong Hanf74eefe2015-11-18 10:20:15 +0800491 [9] = { .feature = FEAT_7_0_ECX, .bits = CPUID_7_0_ECX_PKU,
492 .offset = 0xA80, .size = 0x8 },
Paolo Bonzini2560f192013-10-02 17:54:57 +0200493};
Eduardo Habkost8e8aba52013-05-06 13:20:07 -0300494
Eduardo Habkost8b4bedd2013-01-04 20:01:06 -0200495const char *get_register_name_32(unsigned int reg)
496{
Igor Mammedov31ccdde2013-06-03 18:23:27 +0200497 if (reg >= CPU_NB_REGS32) {
Eduardo Habkost8b4bedd2013-01-04 20:01:06 -0200498 return NULL;
499 }
Eduardo Habkost8e8aba52013-05-06 13:20:07 -0300500 return x86_reg_info_32[reg].name;
Eduardo Habkost8b4bedd2013-01-04 20:01:06 -0200501}
502
Eduardo Habkost84f1b922014-04-30 13:48:41 -0300503/*
504 * Returns the set of feature flags that are supported and migratable by
505 * QEMU, for a given FeatureWord.
506 */
507static uint32_t x86_cpu_get_migratable_flags(FeatureWord w)
508{
509 FeatureWordInfo *wi = &feature_word_info[w];
510 uint32_t r = 0;
511 int i;
512
513 for (i = 0; i < 32; i++) {
514 uint32_t f = 1U << i;
515 /* If the feature name is unknown, it is not supported by QEMU yet */
516 if (!wi->feat_names[i]) {
517 continue;
518 }
519 /* Skip features known to QEMU, but explicitly marked as unmigratable */
520 if (wi->unmigratable_flags & f) {
521 continue;
522 }
523 r |= f;
524 }
525 return r;
526}
527
Jan Kiszkabb44e0d2011-01-21 21:48:07 +0100528void host_cpuid(uint32_t function, uint32_t count,
529 uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
Andre Przywarabdde4762010-03-11 14:38:58 +0100530{
Anthony Liguoria1fd24a2011-11-27 11:13:01 -0600531 uint32_t vec[4];
532
533#ifdef __x86_64__
534 asm volatile("cpuid"
535 : "=a"(vec[0]), "=b"(vec[1]),
536 "=c"(vec[2]), "=d"(vec[3])
537 : "0"(function), "c"(count) : "cc");
Eduardo Habkostc1f41222014-01-30 17:48:53 -0200538#elif defined(__i386__)
Anthony Liguoria1fd24a2011-11-27 11:13:01 -0600539 asm volatile("pusha \n\t"
540 "cpuid \n\t"
541 "mov %%eax, 0(%2) \n\t"
542 "mov %%ebx, 4(%2) \n\t"
543 "mov %%ecx, 8(%2) \n\t"
544 "mov %%edx, 12(%2) \n\t"
545 "popa"
546 : : "a"(function), "c"(count), "S"(vec)
547 : "memory", "cc");
Eduardo Habkostc1f41222014-01-30 17:48:53 -0200548#else
549 abort();
Anthony Liguoria1fd24a2011-11-27 11:13:01 -0600550#endif
551
Andre Przywarabdde4762010-03-11 14:38:58 +0100552 if (eax)
Anthony Liguoria1fd24a2011-11-27 11:13:01 -0600553 *eax = vec[0];
Andre Przywarabdde4762010-03-11 14:38:58 +0100554 if (ebx)
Anthony Liguoria1fd24a2011-11-27 11:13:01 -0600555 *ebx = vec[1];
Andre Przywarabdde4762010-03-11 14:38:58 +0100556 if (ecx)
Anthony Liguoria1fd24a2011-11-27 11:13:01 -0600557 *ecx = vec[2];
Andre Przywarabdde4762010-03-11 14:38:58 +0100558 if (edx)
Anthony Liguoria1fd24a2011-11-27 11:13:01 -0600559 *edx = vec[3];
Andre Przywarabdde4762010-03-11 14:38:58 +0100560}
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100561
562#define iswhite(c) ((c) && ((c) <= ' ' || '~' < (c)))
563
564/* general substring compare of *[s1..e1) and *[s2..e2). sx is start of
565 * a substring. ex if !NULL points to the first char after a substring,
566 * otherwise the string is assumed to sized by a terminating nul.
567 * Return lexical ordering of *s1:*s2.
568 */
Chen Fan8f9d9892014-11-05 16:40:33 +0800569static int sstrcmp(const char *s1, const char *e1,
570 const char *s2, const char *e2)
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100571{
572 for (;;) {
573 if (!*s1 || !*s2 || *s1 != *s2)
574 return (*s1 - *s2);
575 ++s1, ++s2;
576 if (s1 == e1 && s2 == e2)
577 return (0);
578 else if (s1 == e1)
579 return (*s2);
580 else if (s2 == e2)
581 return (*s1);
582 }
583}
584
585/* compare *[s..e) to *altstr. *altstr may be a simple string or multiple
586 * '|' delimited (possibly empty) strings in which case search for a match
587 * within the alternatives proceeds left to right. Return 0 for success,
588 * non-zero otherwise.
589 */
590static int altcmp(const char *s, const char *e, const char *altstr)
591{
592 const char *p, *q;
593
594 for (q = p = altstr; ; ) {
595 while (*p && *p != '|')
596 ++p;
597 if ((q == p && !*s) || (q != p && !sstrcmp(s, e, q, p)))
598 return (0);
599 if (!*p)
600 return (1);
601 else
602 q = ++p;
603 }
604}
605
606/* search featureset for flag *[s..e), if found set corresponding bit in
Jan Kiszkae41e0fc2011-04-19 13:06:06 +0200607 * *pval and return true, otherwise return false
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100608 */
Jan Kiszkae41e0fc2011-04-19 13:06:06 +0200609static bool lookup_feature(uint32_t *pval, const char *s, const char *e,
610 const char **featureset)
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100611{
612 uint32_t mask;
613 const char **ppc;
Jan Kiszkae41e0fc2011-04-19 13:06:06 +0200614 bool found = false;
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100615
Jan Kiszkae41e0fc2011-04-19 13:06:06 +0200616 for (mask = 1, ppc = featureset; mask; mask <<= 1, ++ppc) {
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100617 if (*ppc && !altcmp(s, e, *ppc)) {
618 *pval |= mask;
Jan Kiszkae41e0fc2011-04-19 13:06:06 +0200619 found = true;
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100620 }
Jan Kiszkae41e0fc2011-04-19 13:06:06 +0200621 }
622 return found;
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100623}
624
Eduardo Habkost5ef57872013-01-07 16:20:45 -0200625static void add_flagname_to_bitmaps(const char *flagname,
Eduardo Habkostc00c94a2014-08-21 17:22:56 -0300626 FeatureWordArray words,
627 Error **errp)
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100628{
Eduardo Habkost5ef57872013-01-07 16:20:45 -0200629 FeatureWord w;
630 for (w = 0; w < FEATURE_WORDS; w++) {
631 FeatureWordInfo *wi = &feature_word_info[w];
632 if (wi->feat_names &&
633 lookup_feature(&words[w], flagname, NULL, wi->feat_names)) {
634 break;
635 }
636 }
637 if (w == FEATURE_WORDS) {
Eduardo Habkostc00c94a2014-08-21 17:22:56 -0300638 error_setg(errp, "CPU feature %s not found", flagname);
Eduardo Habkost5ef57872013-01-07 16:20:45 -0200639 }
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100640}
641
Eduardo Habkostd940ee92014-02-10 08:21:30 -0200642/* CPU class name definitions: */
643
644#define X86_CPU_TYPE_SUFFIX "-" TYPE_X86_CPU
645#define X86_CPU_TYPE_NAME(name) (name X86_CPU_TYPE_SUFFIX)
646
647/* Return type name for a given CPU model name
648 * Caller is responsible for freeing the returned string.
649 */
650static char *x86_cpu_type_name(const char *model_name)
651{
652 return g_strdup_printf(X86_CPU_TYPE_NAME("%s"), model_name);
653}
654
Andreas Färber500050d2014-02-10 22:02:44 +0100655static ObjectClass *x86_cpu_class_by_name(const char *cpu_model)
656{
Eduardo Habkostd940ee92014-02-10 08:21:30 -0200657 ObjectClass *oc;
658 char *typename;
659
Andreas Färber500050d2014-02-10 22:02:44 +0100660 if (cpu_model == NULL) {
661 return NULL;
662 }
663
Eduardo Habkostd940ee92014-02-10 08:21:30 -0200664 typename = x86_cpu_type_name(cpu_model);
665 oc = object_class_by_name(typename);
666 g_free(typename);
667 return oc;
Andreas Färber500050d2014-02-10 22:02:44 +0100668}
669
Eduardo Habkostd940ee92014-02-10 08:21:30 -0200670struct X86CPUDefinition {
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100671 const char *name;
672 uint32_t level;
Eduardo Habkost90e4b0c2013-04-22 16:00:12 -0300673 uint32_t xlevel;
674 uint32_t xlevel2;
Igor Mammedov99b88a12013-01-21 15:06:36 +0100675 /* vendor is zero-terminated, 12 character ASCII string */
676 char vendor[CPUID_VENDOR_SZ + 1];
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100677 int family;
678 int model;
679 int stepping;
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300680 FeatureWordArray features;
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100681 char model_id[48];
Eduardo Habkostd940ee92014-02-10 08:21:30 -0200682};
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100683
Eduardo Habkost9576de72014-01-30 17:48:58 -0200684static X86CPUDefinition builtin_x86_defs[] = {
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100685 {
686 .name = "qemu64",
Radim Krčmář3046bb52015-07-09 21:07:39 +0200687 .level = 0xd,
Igor Mammedov99b88a12013-01-21 15:06:36 +0100688 .vendor = CPUID_VENDOR_AMD,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100689 .family = 6,
Eduardo Habkostf8e6a112013-09-10 17:48:59 -0300690 .model = 6,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100691 .stepping = 3,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300692 .features[FEAT_1_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300693 PPRO_FEATURES |
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100694 CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100695 CPUID_PSE36,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300696 .features[FEAT_1_ECX] =
Eduardo Habkost6aa91e42015-11-03 17:24:18 -0200697 CPUID_EXT_SSE3 | CPUID_EXT_CX16,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300698 .features[FEAT_8000_0001_EDX] =
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100699 CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300700 .features[FEAT_8000_0001_ECX] =
Eduardo Habkost71195672015-11-03 17:24:18 -0200701 CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100702 .xlevel = 0x8000000A,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100703 },
704 {
705 .name = "phenom",
706 .level = 5,
Igor Mammedov99b88a12013-01-21 15:06:36 +0100707 .vendor = CPUID_VENDOR_AMD,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100708 .family = 16,
709 .model = 2,
710 .stepping = 3,
Eduardo Habkostb9fc20b2014-10-03 16:39:49 -0300711 /* Missing: CPUID_HT */
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300712 .features[FEAT_1_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300713 PPRO_FEATURES |
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100714 CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
Eduardo Habkostb9fc20b2014-10-03 16:39:49 -0300715 CPUID_PSE36 | CPUID_VME,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300716 .features[FEAT_1_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300717 CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_CX16 |
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100718 CPUID_EXT_POPCNT,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300719 .features[FEAT_8000_0001_EDX] =
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100720 CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX |
721 CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT | CPUID_EXT2_MMXEXT |
Aurelien Jarno8560efe2010-03-13 16:43:15 +0100722 CPUID_EXT2_FFXSR | CPUID_EXT2_PDPE1GB | CPUID_EXT2_RDTSCP,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100723 /* Missing: CPUID_EXT3_CMP_LEG, CPUID_EXT3_EXTAPIC,
724 CPUID_EXT3_CR8LEG,
725 CPUID_EXT3_MISALIGNSSE, CPUID_EXT3_3DNOWPREFETCH,
726 CPUID_EXT3_OSVW, CPUID_EXT3_IBS */
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300727 .features[FEAT_8000_0001_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300728 CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM |
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100729 CPUID_EXT3_ABM | CPUID_EXT3_SSE4A,
Eduardo Habkostb9fc20b2014-10-03 16:39:49 -0300730 /* Missing: CPUID_SVM_LBRV */
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300731 .features[FEAT_SVM] =
Eduardo Habkostb9fc20b2014-10-03 16:39:49 -0300732 CPUID_SVM_NPT,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100733 .xlevel = 0x8000001A,
734 .model_id = "AMD Phenom(tm) 9550 Quad-Core Processor"
735 },
736 {
737 .name = "core2duo",
738 .level = 10,
Igor Mammedov99b88a12013-01-21 15:06:36 +0100739 .vendor = CPUID_VENDOR_INTEL,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100740 .family = 6,
741 .model = 15,
742 .stepping = 11,
Eduardo Habkostb9fc20b2014-10-03 16:39:49 -0300743 /* Missing: CPUID_DTS, CPUID_HT, CPUID_TM, CPUID_PBE */
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300744 .features[FEAT_1_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300745 PPRO_FEATURES |
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100746 CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
Eduardo Habkostb9fc20b2014-10-03 16:39:49 -0300747 CPUID_PSE36 | CPUID_VME | CPUID_ACPI | CPUID_SS,
748 /* Missing: CPUID_EXT_DTES64, CPUID_EXT_DSCPL, CPUID_EXT_EST,
Eduardo Habkoste93abc12014-10-03 16:39:50 -0300749 * CPUID_EXT_TM2, CPUID_EXT_XTPR, CPUID_EXT_PDCM, CPUID_EXT_VMX */
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300750 .features[FEAT_1_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300751 CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_SSSE3 |
Eduardo Habkoste93abc12014-10-03 16:39:50 -0300752 CPUID_EXT_CX16,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300753 .features[FEAT_8000_0001_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300754 CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300755 .features[FEAT_8000_0001_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300756 CPUID_EXT3_LAHF_LM,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100757 .xlevel = 0x80000008,
758 .model_id = "Intel(R) Core(TM)2 Duo CPU T7700 @ 2.40GHz",
759 },
760 {
761 .name = "kvm64",
Radim Krčmář3046bb52015-07-09 21:07:39 +0200762 .level = 0xd,
Igor Mammedov99b88a12013-01-21 15:06:36 +0100763 .vendor = CPUID_VENDOR_INTEL,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100764 .family = 15,
765 .model = 6,
766 .stepping = 1,
Paolo Bonzinib3a4f0b2014-12-10 14:12:41 -0200767 /* Missing: CPUID_HT */
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300768 .features[FEAT_1_EDX] =
Paolo Bonzinib3a4f0b2014-12-10 14:12:41 -0200769 PPRO_FEATURES | CPUID_VME |
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100770 CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
771 CPUID_PSE36,
772 /* Missing: CPUID_EXT_POPCNT, CPUID_EXT_MONITOR */
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300773 .features[FEAT_1_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300774 CPUID_EXT_SSE3 | CPUID_EXT_CX16,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100775 /* Missing: CPUID_EXT2_PDPE1GB, CPUID_EXT2_RDTSCP */
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300776 .features[FEAT_8000_0001_EDX] =
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100777 CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
778 /* Missing: CPUID_EXT3_LAHF_LM, CPUID_EXT3_CMP_LEG, CPUID_EXT3_EXTAPIC,
779 CPUID_EXT3_CR8LEG, CPUID_EXT3_ABM, CPUID_EXT3_SSE4A,
780 CPUID_EXT3_MISALIGNSSE, CPUID_EXT3_3DNOWPREFETCH,
781 CPUID_EXT3_OSVW, CPUID_EXT3_IBS, CPUID_EXT3_SVM */
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300782 .features[FEAT_8000_0001_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300783 0,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100784 .xlevel = 0x80000008,
785 .model_id = "Common KVM processor"
786 },
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100787 {
788 .name = "qemu32",
789 .level = 4,
Igor Mammedov99b88a12013-01-21 15:06:36 +0100790 .vendor = CPUID_VENDOR_INTEL,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100791 .family = 6,
Eduardo Habkostf8e6a112013-09-10 17:48:59 -0300792 .model = 6,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100793 .stepping = 3,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300794 .features[FEAT_1_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300795 PPRO_FEATURES,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300796 .features[FEAT_1_ECX] =
Eduardo Habkost6aa91e42015-11-03 17:24:18 -0200797 CPUID_EXT_SSE3,
Andre Przywara58012d62010-03-11 14:39:06 +0100798 .xlevel = 0x80000004,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100799 },
800 {
Andre Przywaraeafaf1e2010-05-21 09:50:51 +0200801 .name = "kvm32",
802 .level = 5,
Igor Mammedov99b88a12013-01-21 15:06:36 +0100803 .vendor = CPUID_VENDOR_INTEL,
Andre Przywaraeafaf1e2010-05-21 09:50:51 +0200804 .family = 15,
805 .model = 6,
806 .stepping = 1,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300807 .features[FEAT_1_EDX] =
Paolo Bonzinib3a4f0b2014-12-10 14:12:41 -0200808 PPRO_FEATURES | CPUID_VME |
Andre Przywaraeafaf1e2010-05-21 09:50:51 +0200809 CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_PSE36,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300810 .features[FEAT_1_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300811 CPUID_EXT_SSE3,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300812 .features[FEAT_8000_0001_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300813 0,
Andre Przywaraeafaf1e2010-05-21 09:50:51 +0200814 .xlevel = 0x80000008,
815 .model_id = "Common 32-bit KVM processor"
816 },
817 {
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100818 .name = "coreduo",
819 .level = 10,
Igor Mammedov99b88a12013-01-21 15:06:36 +0100820 .vendor = CPUID_VENDOR_INTEL,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100821 .family = 6,
822 .model = 14,
823 .stepping = 8,
Eduardo Habkostb9fc20b2014-10-03 16:39:49 -0300824 /* Missing: CPUID_DTS, CPUID_HT, CPUID_TM, CPUID_PBE */
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300825 .features[FEAT_1_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300826 PPRO_FEATURES | CPUID_VME |
Eduardo Habkostb9fc20b2014-10-03 16:39:49 -0300827 CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_ACPI |
828 CPUID_SS,
829 /* Missing: CPUID_EXT_EST, CPUID_EXT_TM2 , CPUID_EXT_XTPR,
Eduardo Habkoste93abc12014-10-03 16:39:50 -0300830 * CPUID_EXT_PDCM, CPUID_EXT_VMX */
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300831 .features[FEAT_1_ECX] =
Eduardo Habkoste93abc12014-10-03 16:39:50 -0300832 CPUID_EXT_SSE3 | CPUID_EXT_MONITOR,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300833 .features[FEAT_8000_0001_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300834 CPUID_EXT2_NX,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100835 .xlevel = 0x80000008,
836 .model_id = "Genuine Intel(R) CPU T2600 @ 2.16GHz",
837 },
838 {
839 .name = "486",
Andre Przywara58012d62010-03-11 14:39:06 +0100840 .level = 1,
Igor Mammedov99b88a12013-01-21 15:06:36 +0100841 .vendor = CPUID_VENDOR_INTEL,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100842 .family = 4,
Andreas Färberb2a856d2013-05-01 17:30:51 +0200843 .model = 8,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100844 .stepping = 0,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300845 .features[FEAT_1_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300846 I486_FEATURES,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100847 .xlevel = 0,
848 },
849 {
850 .name = "pentium",
851 .level = 1,
Igor Mammedov99b88a12013-01-21 15:06:36 +0100852 .vendor = CPUID_VENDOR_INTEL,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100853 .family = 5,
854 .model = 4,
855 .stepping = 3,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300856 .features[FEAT_1_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300857 PENTIUM_FEATURES,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100858 .xlevel = 0,
859 },
860 {
861 .name = "pentium2",
862 .level = 2,
Igor Mammedov99b88a12013-01-21 15:06:36 +0100863 .vendor = CPUID_VENDOR_INTEL,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100864 .family = 6,
865 .model = 5,
866 .stepping = 2,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300867 .features[FEAT_1_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300868 PENTIUM2_FEATURES,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100869 .xlevel = 0,
870 },
871 {
872 .name = "pentium3",
Radim Krčmář3046bb52015-07-09 21:07:39 +0200873 .level = 3,
Igor Mammedov99b88a12013-01-21 15:06:36 +0100874 .vendor = CPUID_VENDOR_INTEL,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100875 .family = 6,
876 .model = 7,
877 .stepping = 3,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300878 .features[FEAT_1_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300879 PENTIUM3_FEATURES,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100880 .xlevel = 0,
881 },
882 {
883 .name = "athlon",
884 .level = 2,
Igor Mammedov99b88a12013-01-21 15:06:36 +0100885 .vendor = CPUID_VENDOR_AMD,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100886 .family = 6,
887 .model = 2,
888 .stepping = 3,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300889 .features[FEAT_1_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300890 PPRO_FEATURES | CPUID_PSE36 | CPUID_VME | CPUID_MTRR |
Eduardo Habkost60032ac2012-09-06 10:05:37 +0000891 CPUID_MCA,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300892 .features[FEAT_8000_0001_EDX] =
Eduardo Habkost60032ac2012-09-06 10:05:37 +0000893 CPUID_EXT2_MMXEXT | CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100894 .xlevel = 0x80000008,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100895 },
896 {
897 .name = "n270",
Radim Krčmář3046bb52015-07-09 21:07:39 +0200898 .level = 10,
Igor Mammedov99b88a12013-01-21 15:06:36 +0100899 .vendor = CPUID_VENDOR_INTEL,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100900 .family = 6,
901 .model = 28,
902 .stepping = 2,
Eduardo Habkostb9fc20b2014-10-03 16:39:49 -0300903 /* Missing: CPUID_DTS, CPUID_HT, CPUID_TM, CPUID_PBE */
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300904 .features[FEAT_1_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300905 PPRO_FEATURES |
Eduardo Habkostb9fc20b2014-10-03 16:39:49 -0300906 CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_VME |
907 CPUID_ACPI | CPUID_SS,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100908 /* Some CPUs got no CPUID_SEP */
Eduardo Habkostb9fc20b2014-10-03 16:39:49 -0300909 /* Missing: CPUID_EXT_DSCPL, CPUID_EXT_EST, CPUID_EXT_TM2,
910 * CPUID_EXT_XTPR */
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300911 .features[FEAT_1_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300912 CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_SSSE3 |
Borislav Petkov4458c232013-04-25 15:43:04 -0300913 CPUID_EXT_MOVBE,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300914 .features[FEAT_8000_0001_EDX] =
Eduardo Habkost60032ac2012-09-06 10:05:37 +0000915 CPUID_EXT2_NX,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300916 .features[FEAT_8000_0001_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300917 CPUID_EXT3_LAHF_LM,
Radim Krčmář3046bb52015-07-09 21:07:39 +0200918 .xlevel = 0x80000008,
Andre Przywarac6dc6f62010-03-11 14:38:55 +0100919 .model_id = "Intel(R) Atom(TM) CPU N270 @ 1.60GHz",
920 },
Eduardo Habkost3eca4642012-09-05 17:41:10 -0300921 {
922 .name = "Conroe",
Radim Krčmář3046bb52015-07-09 21:07:39 +0200923 .level = 10,
Igor Mammedov99b88a12013-01-21 15:06:36 +0100924 .vendor = CPUID_VENDOR_INTEL,
Eduardo Habkost3eca4642012-09-05 17:41:10 -0300925 .family = 6,
Eduardo Habkostffce9eb2013-05-27 17:23:54 -0300926 .model = 15,
Eduardo Habkost3eca4642012-09-05 17:41:10 -0300927 .stepping = 3,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300928 .features[FEAT_1_EDX] =
Paolo Bonzinib3a4f0b2014-12-10 14:12:41 -0200929 CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
Eduardo Habkostb3fb3a22014-06-17 20:05:29 -0300930 CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
931 CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
932 CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
933 CPUID_DE | CPUID_FP87,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300934 .features[FEAT_1_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300935 CPUID_EXT_SSSE3 | CPUID_EXT_SSE3,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300936 .features[FEAT_8000_0001_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300937 CPUID_EXT2_LM | CPUID_EXT2_NX | CPUID_EXT2_SYSCALL,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300938 .features[FEAT_8000_0001_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300939 CPUID_EXT3_LAHF_LM,
Radim Krčmář3046bb52015-07-09 21:07:39 +0200940 .xlevel = 0x80000008,
Eduardo Habkost3eca4642012-09-05 17:41:10 -0300941 .model_id = "Intel Celeron_4x0 (Conroe/Merom Class Core 2)",
942 },
943 {
944 .name = "Penryn",
Radim Krčmář3046bb52015-07-09 21:07:39 +0200945 .level = 10,
Igor Mammedov99b88a12013-01-21 15:06:36 +0100946 .vendor = CPUID_VENDOR_INTEL,
Eduardo Habkost3eca4642012-09-05 17:41:10 -0300947 .family = 6,
Eduardo Habkostffce9eb2013-05-27 17:23:54 -0300948 .model = 23,
Eduardo Habkost3eca4642012-09-05 17:41:10 -0300949 .stepping = 3,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300950 .features[FEAT_1_EDX] =
Paolo Bonzinib3a4f0b2014-12-10 14:12:41 -0200951 CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
Eduardo Habkostb3fb3a22014-06-17 20:05:29 -0300952 CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
953 CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
954 CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
955 CPUID_DE | CPUID_FP87,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300956 .features[FEAT_1_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300957 CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 |
Eduardo Habkostb3fb3a22014-06-17 20:05:29 -0300958 CPUID_EXT_SSE3,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300959 .features[FEAT_8000_0001_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300960 CPUID_EXT2_LM | CPUID_EXT2_NX | CPUID_EXT2_SYSCALL,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300961 .features[FEAT_8000_0001_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300962 CPUID_EXT3_LAHF_LM,
Radim Krčmář3046bb52015-07-09 21:07:39 +0200963 .xlevel = 0x80000008,
Eduardo Habkost3eca4642012-09-05 17:41:10 -0300964 .model_id = "Intel Core 2 Duo P9xxx (Penryn Class Core 2)",
965 },
966 {
967 .name = "Nehalem",
Radim Krčmář3046bb52015-07-09 21:07:39 +0200968 .level = 11,
Igor Mammedov99b88a12013-01-21 15:06:36 +0100969 .vendor = CPUID_VENDOR_INTEL,
Eduardo Habkost3eca4642012-09-05 17:41:10 -0300970 .family = 6,
Eduardo Habkostffce9eb2013-05-27 17:23:54 -0300971 .model = 26,
Eduardo Habkost3eca4642012-09-05 17:41:10 -0300972 .stepping = 3,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300973 .features[FEAT_1_EDX] =
Paolo Bonzinib3a4f0b2014-12-10 14:12:41 -0200974 CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
Eduardo Habkostb3fb3a22014-06-17 20:05:29 -0300975 CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
976 CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
977 CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
978 CPUID_DE | CPUID_FP87,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300979 .features[FEAT_1_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300980 CPUID_EXT_POPCNT | CPUID_EXT_SSE42 | CPUID_EXT_SSE41 |
Eduardo Habkostb3fb3a22014-06-17 20:05:29 -0300981 CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | 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_SYSCALL | CPUID_EXT2_NX,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300984 .features[FEAT_8000_0001_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -0300985 CPUID_EXT3_LAHF_LM,
Radim Krčmář3046bb52015-07-09 21:07:39 +0200986 .xlevel = 0x80000008,
Eduardo Habkost3eca4642012-09-05 17:41:10 -0300987 .model_id = "Intel Core i7 9xx (Nehalem Class Core i7)",
988 },
989 {
990 .name = "Westmere",
991 .level = 11,
Igor Mammedov99b88a12013-01-21 15:06:36 +0100992 .vendor = CPUID_VENDOR_INTEL,
Eduardo Habkost3eca4642012-09-05 17:41:10 -0300993 .family = 6,
994 .model = 44,
995 .stepping = 1,
Eduardo Habkost0514ef22013-04-22 16:00:15 -0300996 .features[FEAT_1_EDX] =
Paolo Bonzinib3a4f0b2014-12-10 14:12:41 -0200997 CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
Eduardo Habkostb3fb3a22014-06-17 20:05:29 -0300998 CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
999 CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
1000 CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
1001 CPUID_DE | CPUID_FP87,
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001002 .features[FEAT_1_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -03001003 CPUID_EXT_AES | CPUID_EXT_POPCNT | CPUID_EXT_SSE42 |
Eduardo Habkostb3fb3a22014-06-17 20:05:29 -03001004 CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 |
1005 CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3,
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001006 .features[FEAT_8000_0001_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -03001007 CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001008 .features[FEAT_8000_0001_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -03001009 CPUID_EXT3_LAHF_LM,
Jan Kiszka28b8e4d2015-06-07 11:15:08 +02001010 .features[FEAT_6_EAX] =
1011 CPUID_6_EAX_ARAT,
Radim Krčmář3046bb52015-07-09 21:07:39 +02001012 .xlevel = 0x80000008,
Eduardo Habkost3eca4642012-09-05 17:41:10 -03001013 .model_id = "Westmere E56xx/L56xx/X56xx (Nehalem-C)",
1014 },
1015 {
1016 .name = "SandyBridge",
1017 .level = 0xd,
Igor Mammedov99b88a12013-01-21 15:06:36 +01001018 .vendor = CPUID_VENDOR_INTEL,
Eduardo Habkost3eca4642012-09-05 17:41:10 -03001019 .family = 6,
1020 .model = 42,
1021 .stepping = 1,
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001022 .features[FEAT_1_EDX] =
Paolo Bonzinib3a4f0b2014-12-10 14:12:41 -02001023 CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
Eduardo Habkostb3fb3a22014-06-17 20:05:29 -03001024 CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
1025 CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
1026 CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
1027 CPUID_DE | CPUID_FP87,
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001028 .features[FEAT_1_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -03001029 CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES |
Eduardo Habkostb3fb3a22014-06-17 20:05:29 -03001030 CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_POPCNT |
1031 CPUID_EXT_X2APIC | CPUID_EXT_SSE42 | CPUID_EXT_SSE41 |
1032 CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | CPUID_EXT_PCLMULQDQ |
1033 CPUID_EXT_SSE3,
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001034 .features[FEAT_8000_0001_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -03001035 CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX |
Eduardo Habkostb3fb3a22014-06-17 20:05:29 -03001036 CPUID_EXT2_SYSCALL,
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001037 .features[FEAT_8000_0001_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -03001038 CPUID_EXT3_LAHF_LM,
Paolo Bonzini0bb0b2d2014-11-24 15:54:43 +01001039 .features[FEAT_XSAVE] =
1040 CPUID_XSAVE_XSAVEOPT,
Jan Kiszka28b8e4d2015-06-07 11:15:08 +02001041 .features[FEAT_6_EAX] =
1042 CPUID_6_EAX_ARAT,
Radim Krčmář3046bb52015-07-09 21:07:39 +02001043 .xlevel = 0x80000008,
Eduardo Habkost3eca4642012-09-05 17:41:10 -03001044 .model_id = "Intel Xeon E312xx (Sandy Bridge)",
1045 },
1046 {
Paolo Bonzini2f9ac422014-12-05 10:55:23 +01001047 .name = "IvyBridge",
1048 .level = 0xd,
1049 .vendor = CPUID_VENDOR_INTEL,
1050 .family = 6,
1051 .model = 58,
1052 .stepping = 9,
1053 .features[FEAT_1_EDX] =
1054 CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
1055 CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
1056 CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
1057 CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
1058 CPUID_DE | CPUID_FP87,
1059 .features[FEAT_1_ECX] =
1060 CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES |
1061 CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_POPCNT |
1062 CPUID_EXT_X2APIC | CPUID_EXT_SSE42 | CPUID_EXT_SSE41 |
1063 CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | CPUID_EXT_PCLMULQDQ |
1064 CPUID_EXT_SSE3 | CPUID_EXT_F16C | CPUID_EXT_RDRAND,
1065 .features[FEAT_7_0_EBX] =
1066 CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_SMEP |
1067 CPUID_7_0_EBX_ERMS,
1068 .features[FEAT_8000_0001_EDX] =
1069 CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX |
1070 CPUID_EXT2_SYSCALL,
1071 .features[FEAT_8000_0001_ECX] =
1072 CPUID_EXT3_LAHF_LM,
1073 .features[FEAT_XSAVE] =
1074 CPUID_XSAVE_XSAVEOPT,
Jan Kiszka28b8e4d2015-06-07 11:15:08 +02001075 .features[FEAT_6_EAX] =
1076 CPUID_6_EAX_ARAT,
Radim Krčmář3046bb52015-07-09 21:07:39 +02001077 .xlevel = 0x80000008,
Paolo Bonzini2f9ac422014-12-05 10:55:23 +01001078 .model_id = "Intel Xeon E3-12xx v2 (Ivy Bridge)",
1079 },
1080 {
Eduardo Habkosta3568502015-03-13 15:58:09 -03001081 .name = "Haswell-noTSX",
1082 .level = 0xd,
1083 .vendor = CPUID_VENDOR_INTEL,
1084 .family = 6,
1085 .model = 60,
1086 .stepping = 1,
1087 .features[FEAT_1_EDX] =
1088 CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
1089 CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
1090 CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
1091 CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
1092 CPUID_DE | CPUID_FP87,
1093 .features[FEAT_1_ECX] =
1094 CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES |
1095 CPUID_EXT_POPCNT | CPUID_EXT_X2APIC | CPUID_EXT_SSE42 |
1096 CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 |
1097 CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3 |
1098 CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_FMA | CPUID_EXT_MOVBE |
1099 CPUID_EXT_PCID | CPUID_EXT_F16C | CPUID_EXT_RDRAND,
1100 .features[FEAT_8000_0001_EDX] =
1101 CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX |
1102 CPUID_EXT2_SYSCALL,
1103 .features[FEAT_8000_0001_ECX] =
Paolo Bonzinibecb6662015-09-28 14:00:18 +02001104 CPUID_EXT3_ABM | CPUID_EXT3_LAHF_LM,
Eduardo Habkosta3568502015-03-13 15:58:09 -03001105 .features[FEAT_7_0_EBX] =
1106 CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 |
1107 CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP |
1108 CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID,
1109 .features[FEAT_XSAVE] =
1110 CPUID_XSAVE_XSAVEOPT,
Jan Kiszka28b8e4d2015-06-07 11:15:08 +02001111 .features[FEAT_6_EAX] =
1112 CPUID_6_EAX_ARAT,
Radim Krčmář3046bb52015-07-09 21:07:39 +02001113 .xlevel = 0x80000008,
Eduardo Habkosta3568502015-03-13 15:58:09 -03001114 .model_id = "Intel Core Processor (Haswell, no TSX)",
1115 }, {
Eduardo Habkost37507092012-11-14 16:28:54 -02001116 .name = "Haswell",
1117 .level = 0xd,
Igor Mammedov99b88a12013-01-21 15:06:36 +01001118 .vendor = CPUID_VENDOR_INTEL,
Eduardo Habkost37507092012-11-14 16:28:54 -02001119 .family = 6,
1120 .model = 60,
1121 .stepping = 1,
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001122 .features[FEAT_1_EDX] =
Paolo Bonzinib3a4f0b2014-12-10 14:12:41 -02001123 CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
Eduardo Habkostb3fb3a22014-06-17 20:05:29 -03001124 CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
1125 CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
1126 CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
1127 CPUID_DE | CPUID_FP87,
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001128 .features[FEAT_1_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -03001129 CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES |
Eduardo Habkostb3fb3a22014-06-17 20:05:29 -03001130 CPUID_EXT_POPCNT | CPUID_EXT_X2APIC | CPUID_EXT_SSE42 |
1131 CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 |
1132 CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3 |
1133 CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_FMA | CPUID_EXT_MOVBE |
Paolo Bonzini78a611f2014-12-05 10:52:46 +01001134 CPUID_EXT_PCID | CPUID_EXT_F16C | CPUID_EXT_RDRAND,
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001135 .features[FEAT_8000_0001_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -03001136 CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX |
Eduardo Habkostb3fb3a22014-06-17 20:05:29 -03001137 CPUID_EXT2_SYSCALL,
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001138 .features[FEAT_8000_0001_ECX] =
Paolo Bonzinibecb6662015-09-28 14:00:18 +02001139 CPUID_EXT3_ABM | CPUID_EXT3_LAHF_LM,
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001140 .features[FEAT_7_0_EBX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -03001141 CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 |
Eduardo Habkost1ee91592015-03-13 15:39:43 -03001142 CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP |
1143 CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID |
1144 CPUID_7_0_EBX_RTM,
Paolo Bonzini0bb0b2d2014-11-24 15:54:43 +01001145 .features[FEAT_XSAVE] =
1146 CPUID_XSAVE_XSAVEOPT,
Jan Kiszka28b8e4d2015-06-07 11:15:08 +02001147 .features[FEAT_6_EAX] =
1148 CPUID_6_EAX_ARAT,
Radim Krčmář3046bb52015-07-09 21:07:39 +02001149 .xlevel = 0x80000008,
Eduardo Habkost37507092012-11-14 16:28:54 -02001150 .model_id = "Intel Core Processor (Haswell)",
1151 },
1152 {
Eduardo Habkosta3568502015-03-13 15:58:09 -03001153 .name = "Broadwell-noTSX",
1154 .level = 0xd,
1155 .vendor = CPUID_VENDOR_INTEL,
1156 .family = 6,
1157 .model = 61,
1158 .stepping = 2,
1159 .features[FEAT_1_EDX] =
1160 CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
1161 CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
1162 CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
1163 CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
1164 CPUID_DE | CPUID_FP87,
1165 .features[FEAT_1_ECX] =
1166 CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES |
1167 CPUID_EXT_POPCNT | CPUID_EXT_X2APIC | CPUID_EXT_SSE42 |
1168 CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 |
1169 CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3 |
1170 CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_FMA | CPUID_EXT_MOVBE |
1171 CPUID_EXT_PCID | CPUID_EXT_F16C | CPUID_EXT_RDRAND,
1172 .features[FEAT_8000_0001_EDX] =
1173 CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX |
1174 CPUID_EXT2_SYSCALL,
1175 .features[FEAT_8000_0001_ECX] =
Paolo Bonzinibecb6662015-09-28 14:00:18 +02001176 CPUID_EXT3_ABM | CPUID_EXT3_LAHF_LM | CPUID_EXT3_3DNOWPREFETCH,
Eduardo Habkosta3568502015-03-13 15:58:09 -03001177 .features[FEAT_7_0_EBX] =
1178 CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 |
1179 CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP |
1180 CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID |
1181 CPUID_7_0_EBX_RDSEED | CPUID_7_0_EBX_ADX |
1182 CPUID_7_0_EBX_SMAP,
1183 .features[FEAT_XSAVE] =
1184 CPUID_XSAVE_XSAVEOPT,
Jan Kiszka28b8e4d2015-06-07 11:15:08 +02001185 .features[FEAT_6_EAX] =
1186 CPUID_6_EAX_ARAT,
Radim Krčmář3046bb52015-07-09 21:07:39 +02001187 .xlevel = 0x80000008,
Eduardo Habkosta3568502015-03-13 15:58:09 -03001188 .model_id = "Intel Core Processor (Broadwell, no TSX)",
1189 },
1190 {
Eduardo Habkostece01352014-06-17 17:11:40 -03001191 .name = "Broadwell",
1192 .level = 0xd,
1193 .vendor = CPUID_VENDOR_INTEL,
1194 .family = 6,
1195 .model = 61,
1196 .stepping = 2,
1197 .features[FEAT_1_EDX] =
Paolo Bonzinib3a4f0b2014-12-10 14:12:41 -02001198 CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
Eduardo Habkostece01352014-06-17 17:11:40 -03001199 CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
1200 CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
1201 CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
1202 CPUID_DE | CPUID_FP87,
1203 .features[FEAT_1_ECX] =
1204 CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES |
1205 CPUID_EXT_POPCNT | CPUID_EXT_X2APIC | CPUID_EXT_SSE42 |
1206 CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 |
1207 CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3 |
1208 CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_FMA | CPUID_EXT_MOVBE |
Paolo Bonzini78a611f2014-12-05 10:52:46 +01001209 CPUID_EXT_PCID | CPUID_EXT_F16C | CPUID_EXT_RDRAND,
Eduardo Habkostece01352014-06-17 17:11:40 -03001210 .features[FEAT_8000_0001_EDX] =
1211 CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX |
1212 CPUID_EXT2_SYSCALL,
1213 .features[FEAT_8000_0001_ECX] =
Paolo Bonzinibecb6662015-09-28 14:00:18 +02001214 CPUID_EXT3_ABM | CPUID_EXT3_LAHF_LM | CPUID_EXT3_3DNOWPREFETCH,
Eduardo Habkostece01352014-06-17 17:11:40 -03001215 .features[FEAT_7_0_EBX] =
1216 CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 |
Eduardo Habkost1ee91592015-03-13 15:39:43 -03001217 CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP |
Eduardo Habkostece01352014-06-17 17:11:40 -03001218 CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID |
Eduardo Habkost1ee91592015-03-13 15:39:43 -03001219 CPUID_7_0_EBX_RTM | CPUID_7_0_EBX_RDSEED | CPUID_7_0_EBX_ADX |
Eduardo Habkostece01352014-06-17 17:11:40 -03001220 CPUID_7_0_EBX_SMAP,
Paolo Bonzini0bb0b2d2014-11-24 15:54:43 +01001221 .features[FEAT_XSAVE] =
1222 CPUID_XSAVE_XSAVEOPT,
Jan Kiszka28b8e4d2015-06-07 11:15:08 +02001223 .features[FEAT_6_EAX] =
1224 CPUID_6_EAX_ARAT,
Radim Krčmář3046bb52015-07-09 21:07:39 +02001225 .xlevel = 0x80000008,
Eduardo Habkostece01352014-06-17 17:11:40 -03001226 .model_id = "Intel Core Processor (Broadwell)",
1227 },
1228 {
Eduardo Habkost3eca4642012-09-05 17:41:10 -03001229 .name = "Opteron_G1",
1230 .level = 5,
Igor Mammedov99b88a12013-01-21 15:06:36 +01001231 .vendor = CPUID_VENDOR_AMD,
Eduardo Habkost3eca4642012-09-05 17:41:10 -03001232 .family = 15,
1233 .model = 6,
1234 .stepping = 1,
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001235 .features[FEAT_1_EDX] =
Paolo Bonzinib3a4f0b2014-12-10 14:12:41 -02001236 CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
Eduardo Habkostb3fb3a22014-06-17 20:05:29 -03001237 CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
1238 CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
1239 CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
1240 CPUID_DE | CPUID_FP87,
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001241 .features[FEAT_1_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -03001242 CPUID_EXT_SSE3,
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001243 .features[FEAT_8000_0001_EDX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -03001244 CPUID_EXT2_LM | CPUID_EXT2_FXSR | CPUID_EXT2_MMX |
Eduardo Habkostb3fb3a22014-06-17 20:05:29 -03001245 CPUID_EXT2_NX | CPUID_EXT2_PSE36 | CPUID_EXT2_PAT |
1246 CPUID_EXT2_CMOV | CPUID_EXT2_MCA | CPUID_EXT2_PGE |
1247 CPUID_EXT2_MTRR | CPUID_EXT2_SYSCALL | CPUID_EXT2_APIC |
1248 CPUID_EXT2_CX8 | CPUID_EXT2_MCE | CPUID_EXT2_PAE | CPUID_EXT2_MSR |
1249 CPUID_EXT2_TSC | CPUID_EXT2_PSE | CPUID_EXT2_DE | CPUID_EXT2_FPU,
Eduardo Habkost3eca4642012-09-05 17:41:10 -03001250 .xlevel = 0x80000008,
1251 .model_id = "AMD Opteron 240 (Gen 1 Class Opteron)",
1252 },
1253 {
1254 .name = "Opteron_G2",
1255 .level = 5,
Igor Mammedov99b88a12013-01-21 15:06:36 +01001256 .vendor = CPUID_VENDOR_AMD,
Eduardo Habkost3eca4642012-09-05 17:41:10 -03001257 .family = 15,
1258 .model = 6,
1259 .stepping = 1,
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001260 .features[FEAT_1_EDX] =
Paolo Bonzinib3a4f0b2014-12-10 14:12:41 -02001261 CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
Eduardo Habkostb3fb3a22014-06-17 20:05:29 -03001262 CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
1263 CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
1264 CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
1265 CPUID_DE | CPUID_FP87,
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001266 .features[FEAT_1_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -03001267 CPUID_EXT_CX16 | CPUID_EXT_SSE3,
Eduardo Habkost33b5e8c2015-11-13 17:07:13 -02001268 /* Missing: CPUID_EXT2_RDTSCP */
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001269 .features[FEAT_8000_0001_EDX] =
Eduardo Habkost33b5e8c2015-11-13 17:07:13 -02001270 CPUID_EXT2_LM | CPUID_EXT2_FXSR |
Eduardo Habkostb3fb3a22014-06-17 20:05:29 -03001271 CPUID_EXT2_MMX | CPUID_EXT2_NX | CPUID_EXT2_PSE36 |
1272 CPUID_EXT2_PAT | CPUID_EXT2_CMOV | CPUID_EXT2_MCA |
1273 CPUID_EXT2_PGE | CPUID_EXT2_MTRR | CPUID_EXT2_SYSCALL |
1274 CPUID_EXT2_APIC | CPUID_EXT2_CX8 | CPUID_EXT2_MCE |
1275 CPUID_EXT2_PAE | CPUID_EXT2_MSR | CPUID_EXT2_TSC | CPUID_EXT2_PSE |
1276 CPUID_EXT2_DE | CPUID_EXT2_FPU,
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001277 .features[FEAT_8000_0001_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -03001278 CPUID_EXT3_SVM | CPUID_EXT3_LAHF_LM,
Eduardo Habkost3eca4642012-09-05 17:41:10 -03001279 .xlevel = 0x80000008,
1280 .model_id = "AMD Opteron 22xx (Gen 2 Class Opteron)",
1281 },
1282 {
1283 .name = "Opteron_G3",
1284 .level = 5,
Igor Mammedov99b88a12013-01-21 15:06:36 +01001285 .vendor = CPUID_VENDOR_AMD,
Eduardo Habkost3eca4642012-09-05 17:41:10 -03001286 .family = 15,
1287 .model = 6,
1288 .stepping = 1,
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001289 .features[FEAT_1_EDX] =
Paolo Bonzinib3a4f0b2014-12-10 14:12:41 -02001290 CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
Eduardo Habkostb3fb3a22014-06-17 20:05:29 -03001291 CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
1292 CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
1293 CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
1294 CPUID_DE | CPUID_FP87,
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001295 .features[FEAT_1_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -03001296 CPUID_EXT_POPCNT | CPUID_EXT_CX16 | CPUID_EXT_MONITOR |
Eduardo Habkostb3fb3a22014-06-17 20:05:29 -03001297 CPUID_EXT_SSE3,
Eduardo Habkost33b5e8c2015-11-13 17:07:13 -02001298 /* Missing: CPUID_EXT2_RDTSCP */
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001299 .features[FEAT_8000_0001_EDX] =
Eduardo Habkost33b5e8c2015-11-13 17:07:13 -02001300 CPUID_EXT2_LM | CPUID_EXT2_FXSR |
Eduardo Habkostb3fb3a22014-06-17 20:05:29 -03001301 CPUID_EXT2_MMX | CPUID_EXT2_NX | CPUID_EXT2_PSE36 |
1302 CPUID_EXT2_PAT | CPUID_EXT2_CMOV | CPUID_EXT2_MCA |
1303 CPUID_EXT2_PGE | CPUID_EXT2_MTRR | CPUID_EXT2_SYSCALL |
1304 CPUID_EXT2_APIC | CPUID_EXT2_CX8 | CPUID_EXT2_MCE |
1305 CPUID_EXT2_PAE | CPUID_EXT2_MSR | CPUID_EXT2_TSC | CPUID_EXT2_PSE |
1306 CPUID_EXT2_DE | CPUID_EXT2_FPU,
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001307 .features[FEAT_8000_0001_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -03001308 CPUID_EXT3_MISALIGNSSE | CPUID_EXT3_SSE4A |
Eduardo Habkostb3fb3a22014-06-17 20:05:29 -03001309 CPUID_EXT3_ABM | CPUID_EXT3_SVM | CPUID_EXT3_LAHF_LM,
Eduardo Habkost3eca4642012-09-05 17:41:10 -03001310 .xlevel = 0x80000008,
1311 .model_id = "AMD Opteron 23xx (Gen 3 Class Opteron)",
1312 },
1313 {
1314 .name = "Opteron_G4",
1315 .level = 0xd,
Igor Mammedov99b88a12013-01-21 15:06:36 +01001316 .vendor = CPUID_VENDOR_AMD,
Eduardo Habkost3eca4642012-09-05 17:41:10 -03001317 .family = 21,
1318 .model = 1,
1319 .stepping = 2,
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001320 .features[FEAT_1_EDX] =
Paolo Bonzinib3a4f0b2014-12-10 14:12:41 -02001321 CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
Eduardo Habkostb3fb3a22014-06-17 20:05:29 -03001322 CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
1323 CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
1324 CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
1325 CPUID_DE | CPUID_FP87,
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001326 .features[FEAT_1_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -03001327 CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES |
Eduardo Habkostb3fb3a22014-06-17 20:05:29 -03001328 CPUID_EXT_POPCNT | CPUID_EXT_SSE42 | CPUID_EXT_SSE41 |
1329 CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | CPUID_EXT_PCLMULQDQ |
1330 CPUID_EXT_SSE3,
Eduardo Habkost33b5e8c2015-11-13 17:07:13 -02001331 /* Missing: CPUID_EXT2_RDTSCP */
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001332 .features[FEAT_8000_0001_EDX] =
Eduardo Habkost33b5e8c2015-11-13 17:07:13 -02001333 CPUID_EXT2_LM |
Eduardo Habkostb3fb3a22014-06-17 20:05:29 -03001334 CPUID_EXT2_PDPE1GB | CPUID_EXT2_FXSR | CPUID_EXT2_MMX |
1335 CPUID_EXT2_NX | CPUID_EXT2_PSE36 | CPUID_EXT2_PAT |
1336 CPUID_EXT2_CMOV | CPUID_EXT2_MCA | CPUID_EXT2_PGE |
1337 CPUID_EXT2_MTRR | CPUID_EXT2_SYSCALL | CPUID_EXT2_APIC |
1338 CPUID_EXT2_CX8 | CPUID_EXT2_MCE | CPUID_EXT2_PAE | CPUID_EXT2_MSR |
1339 CPUID_EXT2_TSC | CPUID_EXT2_PSE | CPUID_EXT2_DE | CPUID_EXT2_FPU,
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001340 .features[FEAT_8000_0001_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -03001341 CPUID_EXT3_FMA4 | CPUID_EXT3_XOP |
Eduardo Habkostb3fb3a22014-06-17 20:05:29 -03001342 CPUID_EXT3_3DNOWPREFETCH | CPUID_EXT3_MISALIGNSSE |
1343 CPUID_EXT3_SSE4A | CPUID_EXT3_ABM | CPUID_EXT3_SVM |
1344 CPUID_EXT3_LAHF_LM,
Paolo Bonzini0bb0b2d2014-11-24 15:54:43 +01001345 /* no xsaveopt! */
Eduardo Habkost3eca4642012-09-05 17:41:10 -03001346 .xlevel = 0x8000001A,
1347 .model_id = "AMD Opteron 62xx class CPU",
1348 },
Andre Przywara021941b2012-11-14 16:28:53 -02001349 {
1350 .name = "Opteron_G5",
1351 .level = 0xd,
Igor Mammedov99b88a12013-01-21 15:06:36 +01001352 .vendor = CPUID_VENDOR_AMD,
Andre Przywara021941b2012-11-14 16:28:53 -02001353 .family = 21,
1354 .model = 2,
1355 .stepping = 0,
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001356 .features[FEAT_1_EDX] =
Paolo Bonzinib3a4f0b2014-12-10 14:12:41 -02001357 CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
Eduardo Habkostb3fb3a22014-06-17 20:05:29 -03001358 CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
1359 CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
1360 CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
1361 CPUID_DE | CPUID_FP87,
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001362 .features[FEAT_1_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -03001363 CPUID_EXT_F16C | CPUID_EXT_AVX | CPUID_EXT_XSAVE |
Eduardo Habkostb3fb3a22014-06-17 20:05:29 -03001364 CPUID_EXT_AES | CPUID_EXT_POPCNT | CPUID_EXT_SSE42 |
1365 CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_FMA |
1366 CPUID_EXT_SSSE3 | CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3,
Eduardo Habkost33b5e8c2015-11-13 17:07:13 -02001367 /* Missing: CPUID_EXT2_RDTSCP */
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001368 .features[FEAT_8000_0001_EDX] =
Eduardo Habkost33b5e8c2015-11-13 17:07:13 -02001369 CPUID_EXT2_LM |
Eduardo Habkostb3fb3a22014-06-17 20:05:29 -03001370 CPUID_EXT2_PDPE1GB | CPUID_EXT2_FXSR | CPUID_EXT2_MMX |
1371 CPUID_EXT2_NX | CPUID_EXT2_PSE36 | CPUID_EXT2_PAT |
1372 CPUID_EXT2_CMOV | CPUID_EXT2_MCA | CPUID_EXT2_PGE |
1373 CPUID_EXT2_MTRR | CPUID_EXT2_SYSCALL | CPUID_EXT2_APIC |
1374 CPUID_EXT2_CX8 | CPUID_EXT2_MCE | CPUID_EXT2_PAE | CPUID_EXT2_MSR |
1375 CPUID_EXT2_TSC | CPUID_EXT2_PSE | CPUID_EXT2_DE | CPUID_EXT2_FPU,
Eduardo Habkost0514ef22013-04-22 16:00:15 -03001376 .features[FEAT_8000_0001_ECX] =
Eduardo Habkost27861ec2013-04-22 16:00:14 -03001377 CPUID_EXT3_TBM | CPUID_EXT3_FMA4 | CPUID_EXT3_XOP |
Eduardo Habkostb3fb3a22014-06-17 20:05:29 -03001378 CPUID_EXT3_3DNOWPREFETCH | CPUID_EXT3_MISALIGNSSE |
1379 CPUID_EXT3_SSE4A | CPUID_EXT3_ABM | CPUID_EXT3_SVM |
1380 CPUID_EXT3_LAHF_LM,
Paolo Bonzini0bb0b2d2014-11-24 15:54:43 +01001381 /* no xsaveopt! */
Andre Przywara021941b2012-11-14 16:28:53 -02001382 .xlevel = 0x8000001A,
1383 .model_id = "AMD Opteron 63xx class CPU",
1384 },
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001385};
1386
Eduardo Habkost5114e842015-09-11 12:40:27 -03001387typedef struct PropValue {
1388 const char *prop, *value;
1389} PropValue;
1390
1391/* KVM-specific features that are automatically added/removed
1392 * from all CPU models when KVM is enabled.
1393 */
1394static PropValue kvm_default_props[] = {
1395 { "kvmclock", "on" },
1396 { "kvm-nopiodelay", "on" },
1397 { "kvm-asyncpf", "on" },
1398 { "kvm-steal-time", "on" },
1399 { "kvm-pv-eoi", "on" },
1400 { "kvmclock-stable-bit", "on" },
1401 { "x2apic", "on" },
1402 { "acpi", "off" },
1403 { "monitor", "off" },
1404 { "svm", "off" },
1405 { NULL, NULL },
1406};
1407
1408void x86_cpu_change_kvm_default(const char *prop, const char *value)
1409{
1410 PropValue *pv;
1411 for (pv = kvm_default_props; pv->prop; pv++) {
1412 if (!strcmp(pv->prop, prop)) {
1413 pv->value = value;
1414 break;
1415 }
1416 }
1417
1418 /* It is valid to call this function only for properties that
1419 * are already present in the kvm_default_props table.
1420 */
1421 assert(pv->prop);
1422}
1423
Eduardo Habkost4d1b2792014-08-20 17:30:12 -03001424static uint32_t x86_cpu_get_supported_feature_word(FeatureWord w,
1425 bool migratable_only);
1426
Eduardo Habkostd940ee92014-02-10 08:21:30 -02001427#ifdef CONFIG_KVM
1428
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001429static int cpu_x86_fill_model_id(char *str)
1430{
1431 uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
1432 int i;
1433
1434 for (i = 0; i < 3; i++) {
1435 host_cpuid(0x80000002 + i, 0, &eax, &ebx, &ecx, &edx);
1436 memcpy(str + i * 16 + 0, &eax, 4);
1437 memcpy(str + i * 16 + 4, &ebx, 4);
1438 memcpy(str + i * 16 + 8, &ecx, 4);
1439 memcpy(str + i * 16 + 12, &edx, 4);
1440 }
1441 return 0;
1442}
1443
Eduardo Habkostd940ee92014-02-10 08:21:30 -02001444static X86CPUDefinition host_cpudef;
1445
Eduardo Habkost84f1b922014-04-30 13:48:41 -03001446static Property host_x86_cpu_properties[] = {
Eduardo Habkost120eee72014-06-17 17:31:53 -03001447 DEFINE_PROP_BOOL("migratable", X86CPU, migratable, true),
Eduardo Habkoste265e3e2015-09-02 11:19:11 -03001448 DEFINE_PROP_BOOL("host-cache-info", X86CPU, cache_info_passthrough, false),
Eduardo Habkost84f1b922014-04-30 13:48:41 -03001449 DEFINE_PROP_END_OF_LIST()
1450};
1451
Eduardo Habkostd940ee92014-02-10 08:21:30 -02001452/* class_init for the "host" CPU model
Eduardo Habkost6e746f32012-10-24 19:44:06 -02001453 *
Eduardo Habkostd940ee92014-02-10 08:21:30 -02001454 * This function may be called before KVM is initialized.
Eduardo Habkost6e746f32012-10-24 19:44:06 -02001455 */
Eduardo Habkostd940ee92014-02-10 08:21:30 -02001456static void host_x86_cpu_class_init(ObjectClass *oc, void *data)
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001457{
Eduardo Habkost84f1b922014-04-30 13:48:41 -03001458 DeviceClass *dc = DEVICE_CLASS(oc);
Eduardo Habkostd940ee92014-02-10 08:21:30 -02001459 X86CPUClass *xcc = X86_CPU_CLASS(oc);
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001460 uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
Eduardo Habkostd940ee92014-02-10 08:21:30 -02001461
1462 xcc->kvm_required = true;
1463
1464 host_cpuid(0x0, 0, &eax, &ebx, &ecx, &edx);
1465 x86_cpu_vendor_words2str(host_cpudef.vendor, ebx, edx, ecx);
1466
1467 host_cpuid(0x1, 0, &eax, &ebx, &ecx, &edx);
1468 host_cpudef.family = ((eax >> 8) & 0x0F) + ((eax >> 20) & 0xFF);
1469 host_cpudef.model = ((eax >> 4) & 0x0F) | ((eax & 0xF0000) >> 12);
1470 host_cpudef.stepping = eax & 0x0F;
1471
1472 cpu_x86_fill_model_id(host_cpudef.model_id);
1473
1474 xcc->cpu_def = &host_cpudef;
Eduardo Habkostd940ee92014-02-10 08:21:30 -02001475
1476 /* level, xlevel, xlevel2, and the feature words are initialized on
1477 * instance_init, because they require KVM to be initialized.
1478 */
Eduardo Habkost84f1b922014-04-30 13:48:41 -03001479
1480 dc->props = host_x86_cpu_properties;
Markus Armbruster4c315c22015-10-01 10:59:58 +02001481 /* Reason: host_x86_cpu_initfn() dies when !kvm_enabled() */
1482 dc->cannot_destroy_with_object_finalize_yet = true;
Eduardo Habkostd940ee92014-02-10 08:21:30 -02001483}
1484
1485static void host_x86_cpu_initfn(Object *obj)
1486{
1487 X86CPU *cpu = X86_CPU(obj);
1488 CPUX86State *env = &cpu->env;
1489 KVMState *s = kvm_state;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001490
Eduardo Habkost6e746f32012-10-24 19:44:06 -02001491 assert(kvm_enabled());
1492
Eduardo Habkost4d1b2792014-08-20 17:30:12 -03001493 /* We can't fill the features array here because we don't know yet if
1494 * "migratable" is true or false.
1495 */
1496 cpu->host_features = true;
1497
Eduardo Habkostd940ee92014-02-10 08:21:30 -02001498 env->cpuid_level = kvm_arch_get_supported_cpuid(s, 0x0, 0, R_EAX);
1499 env->cpuid_xlevel = kvm_arch_get_supported_cpuid(s, 0x80000000, 0, R_EAX);
1500 env->cpuid_xlevel2 = kvm_arch_get_supported_cpuid(s, 0xC0000000, 0, R_EAX);
Eduardo Habkost2a573252014-01-20 14:41:12 -02001501
Eduardo Habkostd940ee92014-02-10 08:21:30 -02001502 object_property_set_bool(OBJECT(cpu), true, "pmu", &error_abort);
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001503}
1504
Eduardo Habkostd940ee92014-02-10 08:21:30 -02001505static const TypeInfo host_x86_cpu_type_info = {
1506 .name = X86_CPU_TYPE_NAME("host"),
1507 .parent = TYPE_X86_CPU,
1508 .instance_init = host_x86_cpu_initfn,
1509 .class_init = host_x86_cpu_class_init,
1510};
1511
1512#endif
1513
Eduardo Habkost8459e392014-04-30 13:48:31 -03001514static void report_unavailable_features(FeatureWord w, uint32_t mask)
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001515{
Eduardo Habkost8459e392014-04-30 13:48:31 -03001516 FeatureWordInfo *f = &feature_word_info[w];
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001517 int i;
1518
Eduardo Habkost857aee32014-04-30 13:48:29 -03001519 for (i = 0; i < 32; ++i) {
Eduardo Habkost72370dc2015-09-29 17:34:22 -03001520 if ((1UL << i) & mask) {
Eduardo Habkostbffd67b2013-01-07 16:20:46 -02001521 const char *reg = get_register_name_32(f->cpuid_reg);
Eduardo Habkost8b4bedd2013-01-04 20:01:06 -02001522 assert(reg);
Eduardo Habkostfefb41b2014-04-30 13:48:39 -03001523 fprintf(stderr, "warning: %s doesn't support requested feature: "
Eduardo Habkost8b4bedd2013-01-04 20:01:06 -02001524 "CPUID.%02XH:%s%s%s [bit %d]\n",
Eduardo Habkostfefb41b2014-04-30 13:48:39 -03001525 kvm_enabled() ? "host" : "TCG",
Eduardo Habkostbffd67b2013-01-07 16:20:46 -02001526 f->cpuid_eax, reg,
1527 f->feat_names[i] ? "." : "",
1528 f->feat_names[i] ? f->feat_names[i] : "", i);
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001529 }
Eduardo Habkost857aee32014-04-30 13:48:29 -03001530 }
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001531}
1532
Andreas Färber95b85192012-04-17 14:42:22 +02001533static void x86_cpuid_version_get_family(Object *obj, Visitor *v, void *opaque,
1534 const char *name, Error **errp)
1535{
1536 X86CPU *cpu = X86_CPU(obj);
1537 CPUX86State *env = &cpu->env;
1538 int64_t value;
1539
1540 value = (env->cpuid_version >> 8) & 0xf;
1541 if (value == 0xf) {
1542 value += (env->cpuid_version >> 20) & 0xff;
1543 }
1544 visit_type_int(v, &value, name, errp);
1545}
1546
Andreas Färber71ad61d2012-04-17 12:10:29 +02001547static void x86_cpuid_version_set_family(Object *obj, Visitor *v, void *opaque,
1548 const char *name, Error **errp)
Andreas Färbered5e1ec2012-02-17 17:46:01 +01001549{
Andreas Färber71ad61d2012-04-17 12:10:29 +02001550 X86CPU *cpu = X86_CPU(obj);
1551 CPUX86State *env = &cpu->env;
1552 const int64_t min = 0;
1553 const int64_t max = 0xff + 0xf;
Markus Armbruster65cd9062014-04-25 12:44:22 +02001554 Error *local_err = NULL;
Andreas Färber71ad61d2012-04-17 12:10:29 +02001555 int64_t value;
1556
Markus Armbruster65cd9062014-04-25 12:44:22 +02001557 visit_type_int(v, &value, name, &local_err);
1558 if (local_err) {
1559 error_propagate(errp, local_err);
Andreas Färber71ad61d2012-04-17 12:10:29 +02001560 return;
1561 }
1562 if (value < min || value > max) {
Markus Armbrusterc6bd8c72015-03-17 11:54:50 +01001563 error_setg(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE, "",
1564 name ? name : "null", value, min, max);
Andreas Färber71ad61d2012-04-17 12:10:29 +02001565 return;
1566 }
1567
Andreas Färbered5e1ec2012-02-17 17:46:01 +01001568 env->cpuid_version &= ~0xff00f00;
Andreas Färber71ad61d2012-04-17 12:10:29 +02001569 if (value > 0x0f) {
1570 env->cpuid_version |= 0xf00 | ((value - 0x0f) << 20);
Andreas Färbered5e1ec2012-02-17 17:46:01 +01001571 } else {
Andreas Färber71ad61d2012-04-17 12:10:29 +02001572 env->cpuid_version |= value << 8;
Andreas Färbered5e1ec2012-02-17 17:46:01 +01001573 }
1574}
1575
Andreas Färber67e30c82012-04-17 14:48:14 +02001576static void x86_cpuid_version_get_model(Object *obj, Visitor *v, void *opaque,
1577 const char *name, Error **errp)
1578{
1579 X86CPU *cpu = X86_CPU(obj);
1580 CPUX86State *env = &cpu->env;
1581 int64_t value;
1582
1583 value = (env->cpuid_version >> 4) & 0xf;
1584 value |= ((env->cpuid_version >> 16) & 0xf) << 4;
1585 visit_type_int(v, &value, name, errp);
1586}
1587
Andreas Färberc5291a42012-04-17 12:16:39 +02001588static void x86_cpuid_version_set_model(Object *obj, Visitor *v, void *opaque,
1589 const char *name, Error **errp)
Andreas Färberb0704cb2012-02-17 17:46:02 +01001590{
Andreas Färberc5291a42012-04-17 12:16:39 +02001591 X86CPU *cpu = X86_CPU(obj);
1592 CPUX86State *env = &cpu->env;
1593 const int64_t min = 0;
1594 const int64_t max = 0xff;
Markus Armbruster65cd9062014-04-25 12:44:22 +02001595 Error *local_err = NULL;
Andreas Färberc5291a42012-04-17 12:16:39 +02001596 int64_t value;
1597
Markus Armbruster65cd9062014-04-25 12:44:22 +02001598 visit_type_int(v, &value, name, &local_err);
1599 if (local_err) {
1600 error_propagate(errp, local_err);
Andreas Färberc5291a42012-04-17 12:16:39 +02001601 return;
1602 }
1603 if (value < min || value > max) {
Markus Armbrusterc6bd8c72015-03-17 11:54:50 +01001604 error_setg(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE, "",
1605 name ? name : "null", value, min, max);
Andreas Färberc5291a42012-04-17 12:16:39 +02001606 return;
1607 }
1608
Andreas Färberb0704cb2012-02-17 17:46:02 +01001609 env->cpuid_version &= ~0xf00f0;
Andreas Färberc5291a42012-04-17 12:16:39 +02001610 env->cpuid_version |= ((value & 0xf) << 4) | ((value >> 4) << 16);
Andreas Färberb0704cb2012-02-17 17:46:02 +01001611}
1612
Andreas Färber35112e42012-04-17 14:50:53 +02001613static void x86_cpuid_version_get_stepping(Object *obj, Visitor *v,
1614 void *opaque, const char *name,
1615 Error **errp)
1616{
1617 X86CPU *cpu = X86_CPU(obj);
1618 CPUX86State *env = &cpu->env;
1619 int64_t value;
1620
1621 value = env->cpuid_version & 0xf;
1622 visit_type_int(v, &value, name, errp);
1623}
1624
Andreas Färber036e2222012-04-17 14:14:18 +02001625static void x86_cpuid_version_set_stepping(Object *obj, Visitor *v,
1626 void *opaque, const char *name,
1627 Error **errp)
Andreas Färber38c3dc42012-02-17 17:46:03 +01001628{
Andreas Färber036e2222012-04-17 14:14:18 +02001629 X86CPU *cpu = X86_CPU(obj);
1630 CPUX86State *env = &cpu->env;
1631 const int64_t min = 0;
1632 const int64_t max = 0xf;
Markus Armbruster65cd9062014-04-25 12:44:22 +02001633 Error *local_err = NULL;
Andreas Färber036e2222012-04-17 14:14:18 +02001634 int64_t value;
1635
Markus Armbruster65cd9062014-04-25 12:44:22 +02001636 visit_type_int(v, &value, name, &local_err);
1637 if (local_err) {
1638 error_propagate(errp, local_err);
Andreas Färber036e2222012-04-17 14:14:18 +02001639 return;
1640 }
1641 if (value < min || value > max) {
Markus Armbrusterc6bd8c72015-03-17 11:54:50 +01001642 error_setg(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE, "",
1643 name ? name : "null", value, min, max);
Andreas Färber036e2222012-04-17 14:14:18 +02001644 return;
1645 }
1646
Andreas Färber38c3dc42012-02-17 17:46:03 +01001647 env->cpuid_version &= ~0xf;
Andreas Färber036e2222012-04-17 14:14:18 +02001648 env->cpuid_version |= value & 0xf;
Andreas Färber38c3dc42012-02-17 17:46:03 +01001649}
1650
Andreas Färberd480e1a2012-04-17 19:22:58 +02001651static char *x86_cpuid_get_vendor(Object *obj, Error **errp)
1652{
1653 X86CPU *cpu = X86_CPU(obj);
1654 CPUX86State *env = &cpu->env;
1655 char *value;
Andreas Färberd480e1a2012-04-17 19:22:58 +02001656
Markus Armbrustere42a92a2014-12-04 14:46:46 +01001657 value = g_malloc(CPUID_VENDOR_SZ + 1);
Igor Mammedov99b88a12013-01-21 15:06:36 +01001658 x86_cpu_vendor_words2str(value, env->cpuid_vendor1, env->cpuid_vendor2,
1659 env->cpuid_vendor3);
Andreas Färberd480e1a2012-04-17 19:22:58 +02001660 return value;
1661}
1662
1663static void x86_cpuid_set_vendor(Object *obj, const char *value,
1664 Error **errp)
1665{
1666 X86CPU *cpu = X86_CPU(obj);
1667 CPUX86State *env = &cpu->env;
1668 int i;
1669
Igor Mammedov9df694e2012-10-22 17:03:10 +02001670 if (strlen(value) != CPUID_VENDOR_SZ) {
Markus Armbrusterc6bd8c72015-03-17 11:54:50 +01001671 error_setg(errp, QERR_PROPERTY_VALUE_BAD, "", "vendor", value);
Andreas Färberd480e1a2012-04-17 19:22:58 +02001672 return;
1673 }
1674
1675 env->cpuid_vendor1 = 0;
1676 env->cpuid_vendor2 = 0;
1677 env->cpuid_vendor3 = 0;
1678 for (i = 0; i < 4; i++) {
1679 env->cpuid_vendor1 |= ((uint8_t)value[i ]) << (8 * i);
1680 env->cpuid_vendor2 |= ((uint8_t)value[i + 4]) << (8 * i);
1681 env->cpuid_vendor3 |= ((uint8_t)value[i + 8]) << (8 * i);
1682 }
Andreas Färberd480e1a2012-04-17 19:22:58 +02001683}
1684
Andreas Färber63e886e2012-04-17 23:02:26 +02001685static char *x86_cpuid_get_model_id(Object *obj, Error **errp)
1686{
1687 X86CPU *cpu = X86_CPU(obj);
1688 CPUX86State *env = &cpu->env;
1689 char *value;
1690 int i;
1691
1692 value = g_malloc(48 + 1);
1693 for (i = 0; i < 48; i++) {
1694 value[i] = env->cpuid_model[i >> 2] >> (8 * (i & 3));
1695 }
1696 value[48] = '\0';
1697 return value;
1698}
1699
Andreas Färber938d4c22012-04-17 15:17:27 +02001700static void x86_cpuid_set_model_id(Object *obj, const char *model_id,
1701 Error **errp)
Andreas Färberdcce6672012-02-17 17:46:04 +01001702{
Andreas Färber938d4c22012-04-17 15:17:27 +02001703 X86CPU *cpu = X86_CPU(obj);
1704 CPUX86State *env = &cpu->env;
Andreas Färberdcce6672012-02-17 17:46:04 +01001705 int c, len, i;
1706
1707 if (model_id == NULL) {
1708 model_id = "";
1709 }
1710 len = strlen(model_id);
Andreas Färberd0a6acf2012-04-17 18:21:52 +02001711 memset(env->cpuid_model, 0, 48);
Andreas Färberdcce6672012-02-17 17:46:04 +01001712 for (i = 0; i < 48; i++) {
1713 if (i >= len) {
1714 c = '\0';
1715 } else {
1716 c = (uint8_t)model_id[i];
1717 }
1718 env->cpuid_model[i >> 2] |= c << (8 * (i & 3));
1719 }
1720}
1721
Andreas Färber89e48962012-04-18 00:12:23 +02001722static void x86_cpuid_get_tsc_freq(Object *obj, Visitor *v, void *opaque,
1723 const char *name, Error **errp)
1724{
1725 X86CPU *cpu = X86_CPU(obj);
1726 int64_t value;
1727
1728 value = cpu->env.tsc_khz * 1000;
1729 visit_type_int(v, &value, name, errp);
1730}
1731
1732static void x86_cpuid_set_tsc_freq(Object *obj, Visitor *v, void *opaque,
1733 const char *name, Error **errp)
1734{
1735 X86CPU *cpu = X86_CPU(obj);
1736 const int64_t min = 0;
Don Slutz2e848492012-09-21 20:13:13 -04001737 const int64_t max = INT64_MAX;
Markus Armbruster65cd9062014-04-25 12:44:22 +02001738 Error *local_err = NULL;
Andreas Färber89e48962012-04-18 00:12:23 +02001739 int64_t value;
1740
Markus Armbruster65cd9062014-04-25 12:44:22 +02001741 visit_type_int(v, &value, name, &local_err);
1742 if (local_err) {
1743 error_propagate(errp, local_err);
Andreas Färber89e48962012-04-18 00:12:23 +02001744 return;
1745 }
1746 if (value < min || value > max) {
Markus Armbrusterc6bd8c72015-03-17 11:54:50 +01001747 error_setg(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE, "",
1748 name ? name : "null", value, min, max);
Andreas Färber89e48962012-04-18 00:12:23 +02001749 return;
1750 }
1751
Haozhong Zhang36f96c42015-11-24 11:33:57 +08001752 cpu->env.tsc_khz = cpu->env.user_tsc_khz = value / 1000;
Andreas Färber89e48962012-04-18 00:12:23 +02001753}
1754
Igor Mammedov31050932013-04-25 16:05:26 +02001755static void x86_cpuid_get_apic_id(Object *obj, Visitor *v, void *opaque,
1756 const char *name, Error **errp)
1757{
1758 X86CPU *cpu = X86_CPU(obj);
Eduardo Habkost7e72a452014-12-18 23:20:10 -02001759 int64_t value = cpu->apic_id;
Igor Mammedov31050932013-04-25 16:05:26 +02001760
1761 visit_type_int(v, &value, name, errp);
1762}
1763
1764static void x86_cpuid_set_apic_id(Object *obj, Visitor *v, void *opaque,
1765 const char *name, Error **errp)
1766{
1767 X86CPU *cpu = X86_CPU(obj);
Igor Mammedov8d6d4982013-04-26 19:51:52 +02001768 DeviceState *dev = DEVICE(obj);
Igor Mammedov31050932013-04-25 16:05:26 +02001769 const int64_t min = 0;
1770 const int64_t max = UINT32_MAX;
1771 Error *error = NULL;
1772 int64_t value;
1773
Igor Mammedov8d6d4982013-04-26 19:51:52 +02001774 if (dev->realized) {
1775 error_setg(errp, "Attempt to set property '%s' on '%s' after "
1776 "it was realized", name, object_get_typename(obj));
1777 return;
1778 }
1779
Igor Mammedov31050932013-04-25 16:05:26 +02001780 visit_type_int(v, &value, name, &error);
1781 if (error) {
1782 error_propagate(errp, error);
1783 return;
1784 }
1785 if (value < min || value > max) {
1786 error_setg(errp, "Property %s.%s doesn't take value %" PRId64
1787 " (minimum: %" PRId64 ", maximum: %" PRId64 ")" ,
1788 object_get_typename(obj), name, value, min, max);
1789 return;
1790 }
1791
Eduardo Habkost7e72a452014-12-18 23:20:10 -02001792 if ((value != cpu->apic_id) && cpu_exists(value)) {
Igor Mammedov31050932013-04-25 16:05:26 +02001793 error_setg(errp, "CPU with APIC ID %" PRIi64 " exists", value);
1794 return;
1795 }
Eduardo Habkost7e72a452014-12-18 23:20:10 -02001796 cpu->apic_id = value;
Igor Mammedov31050932013-04-25 16:05:26 +02001797}
1798
Eduardo Habkost7e5292b2013-05-06 13:20:09 -03001799/* Generic getter for "feature-words" and "filtered-features" properties */
Eduardo Habkost8e8aba52013-05-06 13:20:07 -03001800static void x86_cpu_get_feature_words(Object *obj, Visitor *v, void *opaque,
1801 const char *name, Error **errp)
1802{
Eduardo Habkost7e5292b2013-05-06 13:20:09 -03001803 uint32_t *array = (uint32_t *)opaque;
Eduardo Habkost8e8aba52013-05-06 13:20:07 -03001804 FeatureWord w;
1805 Error *err = NULL;
1806 X86CPUFeatureWordInfo word_infos[FEATURE_WORDS] = { };
1807 X86CPUFeatureWordInfoList list_entries[FEATURE_WORDS] = { };
1808 X86CPUFeatureWordInfoList *list = NULL;
1809
1810 for (w = 0; w < FEATURE_WORDS; w++) {
1811 FeatureWordInfo *wi = &feature_word_info[w];
1812 X86CPUFeatureWordInfo *qwi = &word_infos[w];
1813 qwi->cpuid_input_eax = wi->cpuid_eax;
1814 qwi->has_cpuid_input_ecx = wi->cpuid_needs_ecx;
1815 qwi->cpuid_input_ecx = wi->cpuid_ecx;
1816 qwi->cpuid_register = x86_reg_info_32[wi->cpuid_reg].qapi_enum;
Eduardo Habkost7e5292b2013-05-06 13:20:09 -03001817 qwi->features = array[w];
Eduardo Habkost8e8aba52013-05-06 13:20:07 -03001818
1819 /* List will be in reverse order, but order shouldn't matter */
1820 list_entries[w].next = list;
1821 list_entries[w].value = &word_infos[w];
1822 list = &list_entries[w];
1823 }
1824
1825 visit_type_X86CPUFeatureWordInfoList(v, &list, "feature-words", &err);
1826 error_propagate(errp, err);
1827}
1828
Igor Mammedovc8f0f882013-06-04 15:05:25 +02001829static void x86_get_hv_spinlocks(Object *obj, Visitor *v, void *opaque,
1830 const char *name, Error **errp)
1831{
1832 X86CPU *cpu = X86_CPU(obj);
1833 int64_t value = cpu->hyperv_spinlock_attempts;
1834
1835 visit_type_int(v, &value, name, errp);
1836}
1837
1838static void x86_set_hv_spinlocks(Object *obj, Visitor *v, void *opaque,
1839 const char *name, Error **errp)
1840{
1841 const int64_t min = 0xFFF;
1842 const int64_t max = UINT_MAX;
1843 X86CPU *cpu = X86_CPU(obj);
1844 Error *err = NULL;
1845 int64_t value;
1846
1847 visit_type_int(v, &value, name, &err);
1848 if (err) {
1849 error_propagate(errp, err);
1850 return;
1851 }
1852
1853 if (value < min || value > max) {
1854 error_setg(errp, "Property %s.%s doesn't take value %" PRId64
chenfan5bb4c352014-07-28 15:13:06 +08001855 " (minimum: %" PRId64 ", maximum: %" PRId64 ")",
1856 object_get_typename(obj), name ? name : "null",
1857 value, min, max);
Igor Mammedovc8f0f882013-06-04 15:05:25 +02001858 return;
1859 }
1860 cpu->hyperv_spinlock_attempts = value;
1861}
1862
1863static PropertyInfo qdev_prop_spinlocks = {
1864 .name = "int",
1865 .get = x86_get_hv_spinlocks,
1866 .set = x86_set_hv_spinlocks,
1867};
1868
Igor Mammedov72ac2e82013-04-26 18:04:32 +02001869/* Convert all '_' in a feature string option name to '-', to make feature
1870 * name conform to QOM property naming rule, which uses '-' instead of '_'.
1871 */
1872static inline void feat2prop(char *s)
1873{
1874 while ((s = strchr(s, '_'))) {
1875 *s = '-';
1876 }
1877}
1878
Eduardo Habkost8f961352012-12-04 17:34:39 -02001879/* Parse "+feature,-feature,feature=foo" CPU feature string
1880 */
Andreas Färber94a444b2014-03-03 23:19:19 +01001881static void x86_cpu_parse_featurestr(CPUState *cs, char *features,
1882 Error **errp)
Eduardo Habkost8f961352012-12-04 17:34:39 -02001883{
Andreas Färber94a444b2014-03-03 23:19:19 +01001884 X86CPU *cpu = X86_CPU(cs);
Eduardo Habkost8f961352012-12-04 17:34:39 -02001885 char *featurestr; /* Single 'key=value" string being parsed */
Eduardo Habkoste1c224b2014-04-30 13:48:37 -03001886 FeatureWord w;
Eduardo Habkost9f3fb562012-12-04 17:34:38 -02001887 /* Features to be added */
Igor Mammedov077c68c2013-01-11 03:10:15 +01001888 FeatureWordArray plus_features = { 0 };
Joerg Roedel296acb62010-09-27 15:16:17 +02001889 /* Features to be removed */
Eduardo Habkost5ef57872013-01-07 16:20:45 -02001890 FeatureWordArray minus_features = { 0 };
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001891 uint32_t numvalue;
Igor Mammedova91987c2013-01-21 15:06:38 +01001892 CPUX86State *env = &cpu->env;
Andreas Färber94a444b2014-03-03 23:19:19 +01001893 Error *local_err = NULL;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001894
Eduardo Habkost8f961352012-12-04 17:34:39 -02001895 featurestr = features ? strtok(features, ",") : NULL;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001896
1897 while (featurestr) {
1898 char *val;
1899 if (featurestr[0] == '+') {
Eduardo Habkostc00c94a2014-08-21 17:22:56 -03001900 add_flagname_to_bitmaps(featurestr + 1, plus_features, &local_err);
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001901 } else if (featurestr[0] == '-') {
Eduardo Habkostc00c94a2014-08-21 17:22:56 -03001902 add_flagname_to_bitmaps(featurestr + 1, minus_features, &local_err);
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001903 } else if ((val = strchr(featurestr, '='))) {
1904 *val = 0; val++;
Igor Mammedov72ac2e82013-04-26 18:04:32 +02001905 feat2prop(featurestr);
Igor Mammedovd024d202012-12-14 01:29:56 +01001906 if (!strcmp(featurestr, "xlevel")) {
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001907 char *err;
Igor Mammedova91987c2013-01-21 15:06:38 +01001908 char num[32];
1909
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001910 numvalue = strtoul(val, &err, 0);
1911 if (!*val || *err) {
Paolo Bonzini6b1dd542014-06-06 15:21:25 +02001912 error_setg(errp, "bad numerical value %s", val);
1913 return;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001914 }
1915 if (numvalue < 0x80000000) {
Andreas Färber94a444b2014-03-03 23:19:19 +01001916 error_report("xlevel value shall always be >= 0x80000000"
1917 ", fixup will be removed in future versions");
Aurelien Jarno2f7a21c2010-03-13 16:46:33 +01001918 numvalue += 0x80000000;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001919 }
Igor Mammedova91987c2013-01-21 15:06:38 +01001920 snprintf(num, sizeof(num), "%" PRIu32, numvalue);
Andreas Färber94a444b2014-03-03 23:19:19 +01001921 object_property_parse(OBJECT(cpu), num, featurestr, &local_err);
Igor Mammedov72ac2e82013-04-26 18:04:32 +02001922 } else if (!strcmp(featurestr, "tsc-freq")) {
Joerg Roedelb862d1f2011-07-07 16:13:12 +02001923 int64_t tsc_freq;
1924 char *err;
Igor Mammedova91987c2013-01-21 15:06:38 +01001925 char num[32];
Joerg Roedelb862d1f2011-07-07 16:13:12 +02001926
Marc-André Lureau4677bb42015-09-16 18:02:56 +02001927 tsc_freq = qemu_strtosz_suffix_unit(val, &err,
1928 QEMU_STRTOSZ_DEFSUFFIX_B, 1000);
Markus Armbruster45009a32011-11-22 09:46:04 +01001929 if (tsc_freq < 0 || *err) {
Paolo Bonzini6b1dd542014-06-06 15:21:25 +02001930 error_setg(errp, "bad numerical value %s", val);
1931 return;
Joerg Roedelb862d1f2011-07-07 16:13:12 +02001932 }
Igor Mammedova91987c2013-01-21 15:06:38 +01001933 snprintf(num, sizeof(num), "%" PRId64, tsc_freq);
Andreas Färber94a444b2014-03-03 23:19:19 +01001934 object_property_parse(OBJECT(cpu), num, "tsc-frequency",
1935 &local_err);
Igor Mammedov72ac2e82013-04-26 18:04:32 +02001936 } else if (!strcmp(featurestr, "hv-spinlocks")) {
Vadim Rozenfeld28f52cc2011-12-18 22:48:13 +02001937 char *err;
Igor Mammedov92067bf2013-06-05 15:18:40 +02001938 const int min = 0xFFF;
Igor Mammedovc8f0f882013-06-04 15:05:25 +02001939 char num[32];
Vadim Rozenfeld28f52cc2011-12-18 22:48:13 +02001940 numvalue = strtoul(val, &err, 0);
1941 if (!*val || *err) {
Paolo Bonzini6b1dd542014-06-06 15:21:25 +02001942 error_setg(errp, "bad numerical value %s", val);
1943 return;
Vadim Rozenfeld28f52cc2011-12-18 22:48:13 +02001944 }
Igor Mammedov92067bf2013-06-05 15:18:40 +02001945 if (numvalue < min) {
Andreas Färber94a444b2014-03-03 23:19:19 +01001946 error_report("hv-spinlocks value shall always be >= 0x%x"
chenfan5bb4c352014-07-28 15:13:06 +08001947 ", fixup will be removed in future versions",
1948 min);
Igor Mammedov92067bf2013-06-05 15:18:40 +02001949 numvalue = min;
1950 }
Igor Mammedovc8f0f882013-06-04 15:05:25 +02001951 snprintf(num, sizeof(num), "%" PRId32, numvalue);
Andreas Färber94a444b2014-03-03 23:19:19 +01001952 object_property_parse(OBJECT(cpu), num, featurestr, &local_err);
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001953 } else {
Andreas Färber94a444b2014-03-03 23:19:19 +01001954 object_property_parse(OBJECT(cpu), val, featurestr, &local_err);
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001955 }
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001956 } else {
Igor Mammedov258f5ab2012-12-14 01:16:00 +01001957 feat2prop(featurestr);
Andreas Färber94a444b2014-03-03 23:19:19 +01001958 object_property_parse(OBJECT(cpu), "on", featurestr, &local_err);
Igor Mammedova91987c2013-01-21 15:06:38 +01001959 }
Andreas Färber94a444b2014-03-03 23:19:19 +01001960 if (local_err) {
1961 error_propagate(errp, local_err);
Paolo Bonzini6b1dd542014-06-06 15:21:25 +02001962 return;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001963 }
1964 featurestr = strtok(NULL, ",");
1965 }
Eduardo Habkoste1c224b2014-04-30 13:48:37 -03001966
Eduardo Habkost4d1b2792014-08-20 17:30:12 -03001967 if (cpu->host_features) {
1968 for (w = 0; w < FEATURE_WORDS; w++) {
1969 env->features[w] =
1970 x86_cpu_get_supported_feature_word(w, cpu->migratable);
1971 }
1972 }
1973
Eduardo Habkoste1c224b2014-04-30 13:48:37 -03001974 for (w = 0; w < FEATURE_WORDS; w++) {
1975 env->features[w] |= plus_features[w];
1976 env->features[w] &= ~minus_features[w];
1977 }
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001978}
1979
Eduardo Habkost8c3329e2015-02-03 15:48:55 -02001980/* Print all cpuid feature names in featureset
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001981 */
Eduardo Habkost8c3329e2015-02-03 15:48:55 -02001982static void listflags(FILE *f, fprintf_function print, const char **featureset)
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001983{
Eduardo Habkost8c3329e2015-02-03 15:48:55 -02001984 int bit;
1985 bool first = true;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001986
Eduardo Habkost8c3329e2015-02-03 15:48:55 -02001987 for (bit = 0; bit < 32; bit++) {
1988 if (featureset[bit]) {
1989 print(f, "%s%s", first ? "" : " ", featureset[bit]);
1990 first = false;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001991 }
Eduardo Habkost8c3329e2015-02-03 15:48:55 -02001992 }
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001993}
1994
Peter Maydelle916cbf2012-09-05 17:41:08 -03001995/* generate CPU information. */
1996void x86_cpu_list(FILE *f, fprintf_function cpu_fprintf)
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001997{
Eduardo Habkost9576de72014-01-30 17:48:58 -02001998 X86CPUDefinition *def;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01001999 char buf[256];
Andreas Färber7fc9b712013-01-21 01:02:28 +01002000 int i;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002001
Andreas Färber7fc9b712013-01-21 01:02:28 +01002002 for (i = 0; i < ARRAY_SIZE(builtin_x86_defs); i++) {
2003 def = &builtin_x86_defs[i];
Eduardo Habkostc04321b2012-09-05 17:41:13 -03002004 snprintf(buf, sizeof(buf), "%s", def->name);
Peter Maydell6cdf8852012-09-05 17:41:07 -03002005 (*cpu_fprintf)(f, "x86 %16s %-48s\n", buf, def->model_id);
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002006 }
Jan Kiszka21ad7782013-03-24 17:01:02 +01002007#ifdef CONFIG_KVM
2008 (*cpu_fprintf)(f, "x86 %16s %-48s\n", "host",
2009 "KVM processor with all supported host features "
2010 "(only available in KVM mode)");
2011#endif
2012
Peter Maydell6cdf8852012-09-05 17:41:07 -03002013 (*cpu_fprintf)(f, "\nRecognized CPUID flags:\n");
Jan Kiszka3af60be2013-02-27 10:15:51 +01002014 for (i = 0; i < ARRAY_SIZE(feature_word_info); i++) {
2015 FeatureWordInfo *fw = &feature_word_info[i];
2016
Eduardo Habkost8c3329e2015-02-03 15:48:55 -02002017 (*cpu_fprintf)(f, " ");
2018 listflags(f, cpu_fprintf, fw->feat_names);
2019 (*cpu_fprintf)(f, "\n");
Jan Kiszka3af60be2013-02-27 10:15:51 +01002020 }
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002021}
2022
Anthony Liguori76b64a72012-08-14 22:17:36 -05002023CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp)
Anthony Liguorie3966122012-08-10 11:04:14 -05002024{
2025 CpuDefinitionInfoList *cpu_list = NULL;
Eduardo Habkost9576de72014-01-30 17:48:58 -02002026 X86CPUDefinition *def;
Andreas Färber7fc9b712013-01-21 01:02:28 +01002027 int i;
Anthony Liguorie3966122012-08-10 11:04:14 -05002028
Andreas Färber7fc9b712013-01-21 01:02:28 +01002029 for (i = 0; i < ARRAY_SIZE(builtin_x86_defs); i++) {
Anthony Liguorie3966122012-08-10 11:04:14 -05002030 CpuDefinitionInfoList *entry;
2031 CpuDefinitionInfo *info;
2032
Andreas Färber7fc9b712013-01-21 01:02:28 +01002033 def = &builtin_x86_defs[i];
Anthony Liguorie3966122012-08-10 11:04:14 -05002034 info = g_malloc0(sizeof(*info));
2035 info->name = g_strdup(def->name);
2036
2037 entry = g_malloc0(sizeof(*entry));
2038 entry->value = info;
2039 entry->next = cpu_list;
2040 cpu_list = entry;
2041 }
2042
2043 return cpu_list;
2044}
2045
Eduardo Habkost84f1b922014-04-30 13:48:41 -03002046static uint32_t x86_cpu_get_supported_feature_word(FeatureWord w,
2047 bool migratable_only)
Eduardo Habkost27418ad2014-04-30 13:48:32 -03002048{
2049 FeatureWordInfo *wi = &feature_word_info[w];
Eduardo Habkost84f1b922014-04-30 13:48:41 -03002050 uint32_t r;
Eduardo Habkost27418ad2014-04-30 13:48:32 -03002051
Eduardo Habkostfefb41b2014-04-30 13:48:39 -03002052 if (kvm_enabled()) {
Eduardo Habkost84f1b922014-04-30 13:48:41 -03002053 r = kvm_arch_get_supported_cpuid(kvm_state, wi->cpuid_eax,
2054 wi->cpuid_ecx,
2055 wi->cpuid_reg);
Eduardo Habkostfefb41b2014-04-30 13:48:39 -03002056 } else if (tcg_enabled()) {
Eduardo Habkost84f1b922014-04-30 13:48:41 -03002057 r = wi->tcg_features;
Eduardo Habkostfefb41b2014-04-30 13:48:39 -03002058 } else {
2059 return ~0;
2060 }
Eduardo Habkost84f1b922014-04-30 13:48:41 -03002061 if (migratable_only) {
2062 r &= x86_cpu_get_migratable_flags(w);
2063 }
2064 return r;
Eduardo Habkost27418ad2014-04-30 13:48:32 -03002065}
2066
Eduardo Habkost51f63ae2014-04-30 13:48:30 -03002067/*
2068 * Filters CPU feature words based on host availability of each feature.
2069 *
Eduardo Habkost51f63ae2014-04-30 13:48:30 -03002070 * Returns: 0 if all flags are supported by the host, non-zero otherwise.
2071 */
Eduardo Habkost27418ad2014-04-30 13:48:32 -03002072static int x86_cpu_filter_features(X86CPU *cpu)
Eduardo Habkostbc74b7d2012-10-04 17:49:05 -03002073{
2074 CPUX86State *env = &cpu->env;
Eduardo Habkostbd87d2a2013-04-22 16:00:18 -03002075 FeatureWord w;
Eduardo Habkost51f63ae2014-04-30 13:48:30 -03002076 int rv = 0;
2077
Eduardo Habkostbd87d2a2013-04-22 16:00:18 -03002078 for (w = 0; w < FEATURE_WORDS; w++) {
Eduardo Habkost84f1b922014-04-30 13:48:41 -03002079 uint32_t host_feat =
2080 x86_cpu_get_supported_feature_word(w, cpu->migratable);
Eduardo Habkost034acf42013-05-06 13:20:08 -03002081 uint32_t requested_features = env->features[w];
2082 env->features[w] &= host_feat;
2083 cpu->filtered_features[w] = requested_features & ~env->features[w];
Eduardo Habkost51f63ae2014-04-30 13:48:30 -03002084 if (cpu->filtered_features[w]) {
2085 if (cpu->check_cpuid || cpu->enforce_cpuid) {
Eduardo Habkost8459e392014-04-30 13:48:31 -03002086 report_unavailable_features(w, cpu->filtered_features[w]);
Eduardo Habkost51f63ae2014-04-30 13:48:30 -03002087 }
2088 rv = 1;
2089 }
Eduardo Habkostbd87d2a2013-04-22 16:00:18 -03002090 }
Eduardo Habkost51f63ae2014-04-30 13:48:30 -03002091
2092 return rv;
Eduardo Habkostbc74b7d2012-10-04 17:49:05 -03002093}
Eduardo Habkostbc74b7d2012-10-04 17:49:05 -03002094
Eduardo Habkost5114e842015-09-11 12:40:27 -03002095static void x86_cpu_apply_props(X86CPU *cpu, PropValue *props)
2096{
2097 PropValue *pv;
2098 for (pv = props; pv->prop; pv++) {
2099 if (!pv->value) {
2100 continue;
2101 }
2102 object_property_parse(OBJECT(cpu), pv->value, pv->prop,
2103 &error_abort);
2104 }
2105}
2106
Eduardo Habkostd940ee92014-02-10 08:21:30 -02002107/* Load data from X86CPUDefinition
Eduardo Habkostc080e302014-01-30 17:48:56 -02002108 */
Eduardo Habkostd940ee92014-02-10 08:21:30 -02002109static void x86_cpu_load_def(X86CPU *cpu, X86CPUDefinition *def, Error **errp)
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002110{
Andreas Färber61dcd772012-04-17 12:00:51 +02002111 CPUX86State *env = &cpu->env;
Eduardo Habkost74f54bc2014-02-19 16:39:21 -03002112 const char *vendor;
2113 char host_vendor[CPUID_VENDOR_SZ + 1];
Eduardo Habkoste1c224b2014-04-30 13:48:37 -03002114 FeatureWord w;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002115
Andreas Färber2d642552013-02-15 14:06:56 +01002116 object_property_set_int(OBJECT(cpu), def->level, "level", errp);
2117 object_property_set_int(OBJECT(cpu), def->family, "family", errp);
2118 object_property_set_int(OBJECT(cpu), def->model, "model", errp);
2119 object_property_set_int(OBJECT(cpu), def->stepping, "stepping", errp);
Andreas Färber2d642552013-02-15 14:06:56 +01002120 object_property_set_int(OBJECT(cpu), def->xlevel, "xlevel", errp);
Eduardo Habkost01431f32015-04-02 17:22:27 -03002121 object_property_set_int(OBJECT(cpu), def->xlevel2, "xlevel2", errp);
Andreas Färber2d642552013-02-15 14:06:56 +01002122 object_property_set_str(OBJECT(cpu), def->model_id, "model-id", errp);
Eduardo Habkoste1c224b2014-04-30 13:48:37 -03002123 for (w = 0; w < FEATURE_WORDS; w++) {
2124 env->features[w] = def->features[w];
2125 }
Eduardo Habkost82beb532014-01-30 17:48:54 -02002126
Eduardo Habkost9576de72014-01-30 17:48:58 -02002127 /* Special cases not set in the X86CPUDefinition structs: */
Eduardo Habkost82beb532014-01-30 17:48:54 -02002128 if (kvm_enabled()) {
Eduardo Habkost5114e842015-09-11 12:40:27 -03002129 x86_cpu_apply_props(cpu, kvm_default_props);
Eduardo Habkost82beb532014-01-30 17:48:54 -02002130 }
Eduardo Habkost5fcca9f2014-02-19 11:58:10 -03002131
Eduardo Habkost82beb532014-01-30 17:48:54 -02002132 env->features[FEAT_1_ECX] |= CPUID_EXT_HYPERVISOR;
Eduardo Habkost7c08db32014-01-30 17:48:55 -02002133
2134 /* sysenter isn't supported in compatibility mode on AMD,
2135 * syscall isn't supported in compatibility mode on Intel.
2136 * Normally we advertise the actual CPU vendor, but you can
2137 * override this using the 'vendor' property if you want to use
2138 * KVM's sysenter/syscall emulation in compatibility mode and
2139 * when doing cross vendor migration
2140 */
Eduardo Habkost74f54bc2014-02-19 16:39:21 -03002141 vendor = def->vendor;
Eduardo Habkost7c08db32014-01-30 17:48:55 -02002142 if (kvm_enabled()) {
2143 uint32_t ebx = 0, ecx = 0, edx = 0;
2144 host_cpuid(0, 0, NULL, &ebx, &ecx, &edx);
2145 x86_cpu_vendor_words2str(host_vendor, ebx, edx, ecx);
2146 vendor = host_vendor;
2147 }
2148
2149 object_property_set_str(OBJECT(cpu), vendor, "vendor", errp);
2150
Andreas Färber2d642552013-02-15 14:06:56 +01002151}
2152
Eduardo Habkoste1570d02015-03-05 14:26:51 -03002153X86CPU *cpu_x86_create(const char *cpu_model, Error **errp)
Andreas Färber2d642552013-02-15 14:06:56 +01002154{
2155 X86CPU *cpu = NULL;
Eduardo Habkostd940ee92014-02-10 08:21:30 -02002156 X86CPUClass *xcc;
Andreas Färber500050d2014-02-10 22:02:44 +01002157 ObjectClass *oc;
Andreas Färber2d642552013-02-15 14:06:56 +01002158 gchar **model_pieces;
2159 char *name, *features;
2160 Error *error = NULL;
2161
Eduardo Habkost8f961352012-12-04 17:34:39 -02002162 model_pieces = g_strsplit(cpu_model, ",", 2);
2163 if (!model_pieces[0]) {
Igor Mammedovfa2db3c2013-01-11 03:10:16 +01002164 error_setg(&error, "Invalid/empty CPU model name");
2165 goto out;
Eduardo Habkost8f961352012-12-04 17:34:39 -02002166 }
2167 name = model_pieces[0];
2168 features = model_pieces[1];
2169
Andreas Färber500050d2014-02-10 22:02:44 +01002170 oc = x86_cpu_class_by_name(name);
2171 if (oc == NULL) {
2172 error_setg(&error, "Unable to find CPU definition: %s", name);
2173 goto out;
2174 }
Eduardo Habkostd940ee92014-02-10 08:21:30 -02002175 xcc = X86_CPU_CLASS(oc);
2176
2177 if (xcc->kvm_required && !kvm_enabled()) {
2178 error_setg(&error, "CPU model '%s' requires KVM", name);
Eduardo Habkost285f0252014-01-30 17:48:57 -02002179 goto out;
2180 }
2181
Eduardo Habkostd940ee92014-02-10 08:21:30 -02002182 cpu = X86_CPU(object_new(object_class_get_name(oc)));
2183
Andreas Färber94a444b2014-03-03 23:19:19 +01002184 x86_cpu_parse_featurestr(CPU(cpu), features, &error);
Andreas Färber2d642552013-02-15 14:06:56 +01002185 if (error) {
2186 goto out;
2187 }
2188
Igor Mammedov7f833242013-04-11 16:51:40 +02002189out:
Andreas Färbercd7b87f2013-08-02 18:56:05 +02002190 if (error != NULL) {
2191 error_propagate(errp, error);
Andreas Färber500050d2014-02-10 22:02:44 +01002192 if (cpu) {
2193 object_unref(OBJECT(cpu));
2194 cpu = NULL;
2195 }
Andreas Färbercd7b87f2013-08-02 18:56:05 +02002196 }
Igor Mammedov7f833242013-04-11 16:51:40 +02002197 g_strfreev(model_pieces);
2198 return cpu;
2199}
2200
Peter Maydell08565792015-03-03 00:29:17 +00002201X86CPU *cpu_x86_init(const char *cpu_model)
Igor Mammedov7f833242013-04-11 16:51:40 +02002202{
2203 Error *error = NULL;
2204 X86CPU *cpu;
2205
Eduardo Habkoste1570d02015-03-05 14:26:51 -03002206 cpu = cpu_x86_create(cpu_model, &error);
Andreas Färber2d642552013-02-15 14:06:56 +01002207 if (error) {
Peter Maydell08565792015-03-03 00:29:17 +00002208 goto out;
Andreas Färber2d642552013-02-15 14:06:56 +01002209 }
2210
Igor Mammedov7f833242013-04-11 16:51:40 +02002211 object_property_set_bool(OBJECT(cpu), true, "realized", &error);
Peter Maydell08565792015-03-03 00:29:17 +00002212
2213out:
Igor Mammedov18eb4732012-10-02 17:36:54 +02002214 if (error) {
Peter Maydell08565792015-03-03 00:29:17 +00002215 error_report_err(error);
2216 if (cpu != NULL) {
2217 object_unref(OBJECT(cpu));
2218 cpu = NULL;
2219 }
Andreas Färber5c3c6a62013-02-01 15:12:13 +01002220 }
Peter Maydell08565792015-03-03 00:29:17 +00002221 return cpu;
Andreas Färber5c3c6a62013-02-01 15:12:13 +01002222}
2223
Eduardo Habkostd940ee92014-02-10 08:21:30 -02002224static void x86_cpu_cpudef_class_init(ObjectClass *oc, void *data)
2225{
2226 X86CPUDefinition *cpudef = data;
2227 X86CPUClass *xcc = X86_CPU_CLASS(oc);
2228
2229 xcc->cpu_def = cpudef;
2230}
2231
2232static void x86_register_cpudef_type(X86CPUDefinition *def)
2233{
2234 char *typename = x86_cpu_type_name(def->name);
2235 TypeInfo ti = {
2236 .name = typename,
2237 .parent = TYPE_X86_CPU,
2238 .class_init = x86_cpu_cpudef_class_init,
2239 .class_data = def,
2240 };
2241
2242 type_register(&ti);
2243 g_free(typename);
2244}
2245
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002246#if !defined(CONFIG_USER_ONLY)
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002247
Blue Swirl0e26b7b2010-06-19 10:42:34 +03002248void cpu_clear_apic_feature(CPUX86State *env)
2249{
Eduardo Habkost0514ef22013-04-22 16:00:15 -03002250 env->features[FEAT_1_EDX] &= ~CPUID_APIC;
Blue Swirl0e26b7b2010-06-19 10:42:34 +03002251}
2252
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002253#endif /* !CONFIG_USER_ONLY */
2254
Eduardo Habkostc04321b2012-09-05 17:41:13 -03002255/* Initialize list of CPU models, filling some non-static fields if necessary
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002256 */
2257void x86_cpudef_setup(void)
2258{
Crístian Viana93bfef42012-05-30 00:35:51 -03002259 int i, j;
2260 static const char *model_with_versions[] = { "qemu32", "qemu64", "athlon" };
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002261
2262 for (i = 0; i < ARRAY_SIZE(builtin_x86_defs); ++i) {
Eduardo Habkost9576de72014-01-30 17:48:58 -02002263 X86CPUDefinition *def = &builtin_x86_defs[i];
Crístian Viana93bfef42012-05-30 00:35:51 -03002264
2265 /* Look for specific "cpudef" models that */
Stefan Weil09faecf2012-06-20 06:05:51 +02002266 /* have the QEMU version in .model_id */
Crístian Viana93bfef42012-05-30 00:35:51 -03002267 for (j = 0; j < ARRAY_SIZE(model_with_versions); j++) {
Eduardo Habkostbc3e1292012-09-05 17:41:12 -03002268 if (strcmp(model_with_versions[j], def->name) == 0) {
2269 pstrcpy(def->model_id, sizeof(def->model_id),
2270 "QEMU Virtual CPU version ");
2271 pstrcat(def->model_id, sizeof(def->model_id),
Eduardo Habkost35c2c8d2015-10-30 17:36:08 -02002272 qemu_hw_version());
Crístian Viana93bfef42012-05-30 00:35:51 -03002273 break;
2274 }
2275 }
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002276 }
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002277}
2278
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002279void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
2280 uint32_t *eax, uint32_t *ebx,
2281 uint32_t *ecx, uint32_t *edx)
2282{
Andreas Färbera60f24b2012-12-01 05:35:08 +01002283 X86CPU *cpu = x86_env_get_cpu(env);
2284 CPUState *cs = CPU(cpu);
2285
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002286 /* test if maximum index reached */
2287 if (index & 0x80000000) {
brillywu@viatech.com.cnb3baa152011-06-01 09:59:52 +08002288 if (index > env->cpuid_xlevel) {
2289 if (env->cpuid_xlevel2 > 0) {
2290 /* Handle the Centaur's CPUID instruction. */
2291 if (index > env->cpuid_xlevel2) {
2292 index = env->cpuid_xlevel2;
2293 } else if (index < 0xC0000000) {
2294 index = env->cpuid_xlevel;
2295 }
2296 } else {
Eduardo Habkost57f26ae2012-12-20 16:43:48 -02002297 /* Intel documentation states that invalid EAX input will
2298 * return the same information as EAX=cpuid_level
2299 * (Intel SDM Vol. 2A - Instruction Set Reference - CPUID)
2300 */
2301 index = env->cpuid_level;
brillywu@viatech.com.cnb3baa152011-06-01 09:59:52 +08002302 }
2303 }
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002304 } else {
2305 if (index > env->cpuid_level)
2306 index = env->cpuid_level;
2307 }
2308
2309 switch(index) {
2310 case 0:
2311 *eax = env->cpuid_level;
Eduardo Habkost5eb2f7a2015-02-03 15:57:50 -02002312 *ebx = env->cpuid_vendor1;
2313 *edx = env->cpuid_vendor2;
2314 *ecx = env->cpuid_vendor3;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002315 break;
2316 case 1:
2317 *eax = env->cpuid_version;
Eduardo Habkost7e72a452014-12-18 23:20:10 -02002318 *ebx = (cpu->apic_id << 24) |
2319 8 << 8; /* CLFLUSH size in quad words, Linux wants it. */
Eduardo Habkost0514ef22013-04-22 16:00:15 -03002320 *ecx = env->features[FEAT_1_ECX];
2321 *edx = env->features[FEAT_1_EDX];
Andreas Färberce3960e2012-12-17 03:27:07 +01002322 if (cs->nr_cores * cs->nr_threads > 1) {
2323 *ebx |= (cs->nr_cores * cs->nr_threads) << 16;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002324 *edx |= 1 << 28; /* HTT bit */
2325 }
2326 break;
2327 case 2:
2328 /* cache info: needed for Pentium Pro compatibility */
Benoît Canet787aaf52013-09-02 17:06:37 +02002329 if (cpu->cache_info_passthrough) {
2330 host_cpuid(index, 0, eax, ebx, ecx, edx);
2331 break;
2332 }
Eduardo Habkost5e891bf2013-08-27 12:24:37 -03002333 *eax = 1; /* Number of CPUID[EAX=2] calls required */
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002334 *ebx = 0;
2335 *ecx = 0;
Eduardo Habkost5e891bf2013-08-27 12:24:37 -03002336 *edx = (L1D_DESCRIPTOR << 16) | \
2337 (L1I_DESCRIPTOR << 8) | \
2338 (L2_DESCRIPTOR);
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002339 break;
2340 case 4:
2341 /* cache info: needed for Core compatibility */
Benoît Canet787aaf52013-09-02 17:06:37 +02002342 if (cpu->cache_info_passthrough) {
2343 host_cpuid(index, count, eax, ebx, ecx, edx);
Paolo Bonzini76c29752013-11-19 17:49:46 +01002344 *eax &= ~0xFC000000;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002345 } else {
Aurelien Jarno2f7a21c2010-03-13 16:46:33 +01002346 *eax = 0;
Paolo Bonzini76c29752013-11-19 17:49:46 +01002347 switch (count) {
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002348 case 0: /* L1 dcache info */
Eduardo Habkost5e891bf2013-08-27 12:24:37 -03002349 *eax |= CPUID_4_TYPE_DCACHE | \
2350 CPUID_4_LEVEL(1) | \
2351 CPUID_4_SELF_INIT_LEVEL;
2352 *ebx = (L1D_LINE_SIZE - 1) | \
2353 ((L1D_PARTITIONS - 1) << 12) | \
2354 ((L1D_ASSOCIATIVITY - 1) << 22);
2355 *ecx = L1D_SETS - 1;
2356 *edx = CPUID_4_NO_INVD_SHARING;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002357 break;
2358 case 1: /* L1 icache info */
Eduardo Habkost5e891bf2013-08-27 12:24:37 -03002359 *eax |= CPUID_4_TYPE_ICACHE | \
2360 CPUID_4_LEVEL(1) | \
2361 CPUID_4_SELF_INIT_LEVEL;
2362 *ebx = (L1I_LINE_SIZE - 1) | \
2363 ((L1I_PARTITIONS - 1) << 12) | \
2364 ((L1I_ASSOCIATIVITY - 1) << 22);
2365 *ecx = L1I_SETS - 1;
2366 *edx = CPUID_4_NO_INVD_SHARING;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002367 break;
2368 case 2: /* L2 cache info */
Eduardo Habkost5e891bf2013-08-27 12:24:37 -03002369 *eax |= CPUID_4_TYPE_UNIFIED | \
2370 CPUID_4_LEVEL(2) | \
2371 CPUID_4_SELF_INIT_LEVEL;
Andreas Färberce3960e2012-12-17 03:27:07 +01002372 if (cs->nr_threads > 1) {
2373 *eax |= (cs->nr_threads - 1) << 14;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002374 }
Eduardo Habkost5e891bf2013-08-27 12:24:37 -03002375 *ebx = (L2_LINE_SIZE - 1) | \
2376 ((L2_PARTITIONS - 1) << 12) | \
2377 ((L2_ASSOCIATIVITY - 1) << 22);
2378 *ecx = L2_SETS - 1;
2379 *edx = CPUID_4_NO_INVD_SHARING;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002380 break;
2381 default: /* end of info */
2382 *eax = 0;
2383 *ebx = 0;
2384 *ecx = 0;
2385 *edx = 0;
2386 break;
Paolo Bonzini76c29752013-11-19 17:49:46 +01002387 }
2388 }
2389
2390 /* QEMU gives out its own APIC IDs, never pass down bits 31..26. */
2391 if ((*eax & 31) && cs->nr_cores > 1) {
2392 *eax |= (cs->nr_cores - 1) << 26;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002393 }
2394 break;
2395 case 5:
2396 /* mwait info: needed for Core compatibility */
2397 *eax = 0; /* Smallest monitor-line size in bytes */
2398 *ebx = 0; /* Largest monitor-line size in bytes */
2399 *ecx = CPUID_MWAIT_EMX | CPUID_MWAIT_IBE;
2400 *edx = 0;
2401 break;
2402 case 6:
2403 /* Thermal and Power Leaf */
Jan Kiszka28b8e4d2015-06-07 11:15:08 +02002404 *eax = env->features[FEAT_6_EAX];
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002405 *ebx = 0;
2406 *ecx = 0;
2407 *edx = 0;
2408 break;
Yang, Wei Yf7911682011-05-30 23:17:42 +08002409 case 7:
Eduardo Habkost13526722012-05-21 11:27:02 -03002410 /* Structured Extended Feature Flags Enumeration Leaf */
2411 if (count == 0) {
2412 *eax = 0; /* Maximum ECX value for sub-leaves */
Eduardo Habkost0514ef22013-04-22 16:00:15 -03002413 *ebx = env->features[FEAT_7_0_EBX]; /* Feature flags */
Huaitong Hanf74eefe2015-11-18 10:20:15 +08002414 *ecx = env->features[FEAT_7_0_ECX]; /* Feature flags */
Eduardo Habkost13526722012-05-21 11:27:02 -03002415 *edx = 0; /* Reserved */
Yang, Wei Yf7911682011-05-30 23:17:42 +08002416 } else {
2417 *eax = 0;
2418 *ebx = 0;
2419 *ecx = 0;
2420 *edx = 0;
2421 }
2422 break;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002423 case 9:
2424 /* Direct Cache Access Information Leaf */
2425 *eax = 0; /* Bits 0-31 in DCA_CAP MSR */
2426 *ebx = 0;
2427 *ecx = 0;
2428 *edx = 0;
2429 break;
2430 case 0xA:
2431 /* Architectural Performance Monitoring Leaf */
Eduardo Habkost9337e3b2013-07-26 17:09:36 -03002432 if (kvm_enabled() && cpu->enable_pmu) {
Andreas Färbera60f24b2012-12-01 05:35:08 +01002433 KVMState *s = cs->kvm_state;
Gleb Natapova0fa8202011-12-15 12:44:05 +02002434
2435 *eax = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EAX);
2436 *ebx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EBX);
2437 *ecx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_ECX);
2438 *edx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EDX);
2439 } else {
2440 *eax = 0;
2441 *ebx = 0;
2442 *ecx = 0;
2443 *edx = 0;
2444 }
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002445 break;
Paolo Bonzini2560f192013-10-02 17:54:57 +02002446 case 0xD: {
2447 KVMState *s = cs->kvm_state;
2448 uint64_t kvm_mask;
2449 int i;
2450
Sheng Yang51e49432010-06-17 15:18:14 +08002451 /* Processor Extended State */
Paolo Bonzini2560f192013-10-02 17:54:57 +02002452 *eax = 0;
2453 *ebx = 0;
2454 *ecx = 0;
2455 *edx = 0;
2456 if (!(env->features[FEAT_1_ECX] & CPUID_EXT_XSAVE) || !kvm_enabled()) {
Sheng Yang51e49432010-06-17 15:18:14 +08002457 break;
2458 }
Paolo Bonzini2560f192013-10-02 17:54:57 +02002459 kvm_mask =
2460 kvm_arch_get_supported_cpuid(s, 0xd, 0, R_EAX) |
2461 ((uint64_t)kvm_arch_get_supported_cpuid(s, 0xd, 0, R_EDX) << 32);
Jan Kiszkaba9bc592011-06-08 16:11:05 +02002462
Paolo Bonzini2560f192013-10-02 17:54:57 +02002463 if (count == 0) {
2464 *ecx = 0x240;
2465 for (i = 2; i < ARRAY_SIZE(ext_save_areas); i++) {
2466 const ExtSaveArea *esa = &ext_save_areas[i];
2467 if ((env->features[esa->feature] & esa->bits) == esa->bits &&
2468 (kvm_mask & (1 << i)) != 0) {
2469 if (i < 32) {
2470 *eax |= 1 << i;
2471 } else {
2472 *edx |= 1 << (i - 32);
2473 }
2474 *ecx = MAX(*ecx, esa->offset + esa->size);
2475 }
2476 }
2477 *eax |= kvm_mask & (XSTATE_FP | XSTATE_SSE);
2478 *ebx = *ecx;
2479 } else if (count == 1) {
Paolo Bonzini0bb0b2d2014-11-24 15:54:43 +01002480 *eax = env->features[FEAT_XSAVE];
Paolo Bonzini2560f192013-10-02 17:54:57 +02002481 } else if (count < ARRAY_SIZE(ext_save_areas)) {
2482 const ExtSaveArea *esa = &ext_save_areas[count];
2483 if ((env->features[esa->feature] & esa->bits) == esa->bits &&
2484 (kvm_mask & (1 << count)) != 0) {
Liu Jinsong33f373d2013-12-03 04:17:50 +08002485 *eax = esa->size;
2486 *ebx = esa->offset;
Paolo Bonzini2560f192013-10-02 17:54:57 +02002487 }
Sheng Yang51e49432010-06-17 15:18:14 +08002488 }
2489 break;
Paolo Bonzini2560f192013-10-02 17:54:57 +02002490 }
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002491 case 0x80000000:
2492 *eax = env->cpuid_xlevel;
2493 *ebx = env->cpuid_vendor1;
2494 *edx = env->cpuid_vendor2;
2495 *ecx = env->cpuid_vendor3;
2496 break;
2497 case 0x80000001:
2498 *eax = env->cpuid_version;
2499 *ebx = 0;
Eduardo Habkost0514ef22013-04-22 16:00:15 -03002500 *ecx = env->features[FEAT_8000_0001_ECX];
2501 *edx = env->features[FEAT_8000_0001_EDX];
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002502
2503 /* The Linux kernel checks for the CMPLegacy bit and
2504 * discards multiple thread information if it is set.
2505 * So dont set it here for Intel to make Linux guests happy.
2506 */
Andreas Färberce3960e2012-12-17 03:27:07 +01002507 if (cs->nr_cores * cs->nr_threads > 1) {
Eduardo Habkost5eb2f7a2015-02-03 15:57:50 -02002508 if (env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1 ||
2509 env->cpuid_vendor2 != CPUID_VENDOR_INTEL_2 ||
2510 env->cpuid_vendor3 != CPUID_VENDOR_INTEL_3) {
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002511 *ecx |= 1 << 1; /* CmpLegacy bit */
2512 }
2513 }
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002514 break;
2515 case 0x80000002:
2516 case 0x80000003:
2517 case 0x80000004:
2518 *eax = env->cpuid_model[(index - 0x80000002) * 4 + 0];
2519 *ebx = env->cpuid_model[(index - 0x80000002) * 4 + 1];
2520 *ecx = env->cpuid_model[(index - 0x80000002) * 4 + 2];
2521 *edx = env->cpuid_model[(index - 0x80000002) * 4 + 3];
2522 break;
2523 case 0x80000005:
2524 /* cache info (L1 cache) */
Benoît Canet787aaf52013-09-02 17:06:37 +02002525 if (cpu->cache_info_passthrough) {
2526 host_cpuid(index, 0, eax, ebx, ecx, edx);
2527 break;
2528 }
Eduardo Habkost5e891bf2013-08-27 12:24:37 -03002529 *eax = (L1_DTLB_2M_ASSOC << 24) | (L1_DTLB_2M_ENTRIES << 16) | \
2530 (L1_ITLB_2M_ASSOC << 8) | (L1_ITLB_2M_ENTRIES);
2531 *ebx = (L1_DTLB_4K_ASSOC << 24) | (L1_DTLB_4K_ENTRIES << 16) | \
2532 (L1_ITLB_4K_ASSOC << 8) | (L1_ITLB_4K_ENTRIES);
2533 *ecx = (L1D_SIZE_KB_AMD << 24) | (L1D_ASSOCIATIVITY_AMD << 16) | \
2534 (L1D_LINES_PER_TAG << 8) | (L1D_LINE_SIZE);
2535 *edx = (L1I_SIZE_KB_AMD << 24) | (L1I_ASSOCIATIVITY_AMD << 16) | \
2536 (L1I_LINES_PER_TAG << 8) | (L1I_LINE_SIZE);
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002537 break;
2538 case 0x80000006:
2539 /* cache info (L2 cache) */
Benoît Canet787aaf52013-09-02 17:06:37 +02002540 if (cpu->cache_info_passthrough) {
2541 host_cpuid(index, 0, eax, ebx, ecx, edx);
2542 break;
2543 }
Eduardo Habkost5e891bf2013-08-27 12:24:37 -03002544 *eax = (AMD_ENC_ASSOC(L2_DTLB_2M_ASSOC) << 28) | \
2545 (L2_DTLB_2M_ENTRIES << 16) | \
2546 (AMD_ENC_ASSOC(L2_ITLB_2M_ASSOC) << 12) | \
2547 (L2_ITLB_2M_ENTRIES);
2548 *ebx = (AMD_ENC_ASSOC(L2_DTLB_4K_ASSOC) << 28) | \
2549 (L2_DTLB_4K_ENTRIES << 16) | \
2550 (AMD_ENC_ASSOC(L2_ITLB_4K_ASSOC) << 12) | \
2551 (L2_ITLB_4K_ENTRIES);
2552 *ecx = (L2_SIZE_KB_AMD << 16) | \
2553 (AMD_ENC_ASSOC(L2_ASSOCIATIVITY) << 12) | \
2554 (L2_LINES_PER_TAG << 8) | (L2_LINE_SIZE);
2555 *edx = ((L3_SIZE_KB/512) << 18) | \
2556 (AMD_ENC_ASSOC(L3_ASSOCIATIVITY) << 12) | \
2557 (L3_LINES_PER_TAG << 8) | (L3_LINE_SIZE);
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002558 break;
Marcelo Tosatti303752a2014-04-30 13:48:45 -03002559 case 0x80000007:
2560 *eax = 0;
2561 *ebx = 0;
2562 *ecx = 0;
2563 *edx = env->features[FEAT_8000_0007_EDX];
2564 break;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002565 case 0x80000008:
2566 /* virtual & phys address size in low 2 bytes. */
2567/* XXX: This value must match the one used in the MMU code. */
Eduardo Habkost0514ef22013-04-22 16:00:15 -03002568 if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM) {
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002569 /* 64 bit processor */
2570/* XXX: The physical address space is limited to 42 bits in exec.c. */
Eduardo Habkostdd13e082013-04-11 17:07:23 -03002571 *eax = 0x00003028; /* 48 bits virtual, 40 bits physical */
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002572 } else {
Eduardo Habkost0514ef22013-04-22 16:00:15 -03002573 if (env->features[FEAT_1_EDX] & CPUID_PSE36) {
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002574 *eax = 0x00000024; /* 36 bits physical */
Eduardo Habkostdd13e082013-04-11 17:07:23 -03002575 } else {
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002576 *eax = 0x00000020; /* 32 bits physical */
Eduardo Habkostdd13e082013-04-11 17:07:23 -03002577 }
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002578 }
2579 *ebx = 0;
2580 *ecx = 0;
2581 *edx = 0;
Andreas Färberce3960e2012-12-17 03:27:07 +01002582 if (cs->nr_cores * cs->nr_threads > 1) {
2583 *ecx |= (cs->nr_cores * cs->nr_threads) - 1;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002584 }
2585 break;
2586 case 0x8000000A:
Eduardo Habkost0514ef22013-04-22 16:00:15 -03002587 if (env->features[FEAT_8000_0001_ECX] & CPUID_EXT3_SVM) {
Eduardo Habkost9f3fb562012-12-04 17:34:38 -02002588 *eax = 0x00000001; /* SVM Revision */
2589 *ebx = 0x00000010; /* nr of ASIDs */
2590 *ecx = 0;
Eduardo Habkost0514ef22013-04-22 16:00:15 -03002591 *edx = env->features[FEAT_SVM]; /* optional features */
Eduardo Habkost9f3fb562012-12-04 17:34:38 -02002592 } else {
2593 *eax = 0;
2594 *ebx = 0;
2595 *ecx = 0;
2596 *edx = 0;
2597 }
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002598 break;
brillywu@viatech.com.cnb3baa152011-06-01 09:59:52 +08002599 case 0xC0000000:
2600 *eax = env->cpuid_xlevel2;
2601 *ebx = 0;
2602 *ecx = 0;
2603 *edx = 0;
2604 break;
2605 case 0xC0000001:
2606 /* Support for VIA CPU's CPUID instruction */
2607 *eax = env->cpuid_version;
2608 *ebx = 0;
2609 *ecx = 0;
Eduardo Habkost0514ef22013-04-22 16:00:15 -03002610 *edx = env->features[FEAT_C000_0001_EDX];
brillywu@viatech.com.cnb3baa152011-06-01 09:59:52 +08002611 break;
2612 case 0xC0000002:
2613 case 0xC0000003:
2614 case 0xC0000004:
2615 /* Reserved for the future, and now filled with zero */
2616 *eax = 0;
2617 *ebx = 0;
2618 *ecx = 0;
2619 *edx = 0;
2620 break;
Andre Przywarac6dc6f62010-03-11 14:38:55 +01002621 default:
2622 /* reserved values: zero */
2623 *eax = 0;
2624 *ebx = 0;
2625 *ecx = 0;
2626 *edx = 0;
2627 break;
2628 }
2629}
Andreas Färber5fd20872012-04-02 23:20:08 +02002630
2631/* CPUClass::reset() */
2632static void x86_cpu_reset(CPUState *s)
2633{
2634 X86CPU *cpu = X86_CPU(s);
2635 X86CPUClass *xcc = X86_CPU_GET_CLASS(cpu);
2636 CPUX86State *env = &cpu->env;
Andreas Färberc1958ae2012-04-03 00:16:24 +02002637 int i;
2638
Andreas Färber5fd20872012-04-02 23:20:08 +02002639 xcc->parent_reset(s);
2640
Paolo Bonzini43175fa2013-03-12 13:16:28 +01002641 memset(env, 0, offsetof(CPUX86State, cpuid_level));
Andreas Färberc1958ae2012-04-03 00:16:24 +02002642
Andreas Färber00c8cb02013-09-04 02:19:44 +02002643 tlb_flush(s, 1);
Andreas Färberc1958ae2012-04-03 00:16:24 +02002644
2645 env->old_exception = -1;
2646
2647 /* init to reset state */
2648
2649#ifdef CONFIG_SOFTMMU
2650 env->hflags |= HF_SOFTMMU_MASK;
2651#endif
2652 env->hflags2 |= HF2_GIF_MASK;
2653
2654 cpu_x86_update_cr0(env, 0x60000010);
2655 env->a20_mask = ~0x0;
2656 env->smbase = 0x30000;
2657
2658 env->idt.limit = 0xffff;
2659 env->gdt.limit = 0xffff;
2660 env->ldt.limit = 0xffff;
2661 env->ldt.flags = DESC_P_MASK | (2 << DESC_TYPE_SHIFT);
2662 env->tr.limit = 0xffff;
2663 env->tr.flags = DESC_P_MASK | (11 << DESC_TYPE_SHIFT);
2664
2665 cpu_x86_load_seg_cache(env, R_CS, 0xf000, 0xffff0000, 0xffff,
2666 DESC_P_MASK | DESC_S_MASK | DESC_CS_MASK |
2667 DESC_R_MASK | DESC_A_MASK);
2668 cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0xffff,
2669 DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
2670 DESC_A_MASK);
2671 cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0xffff,
2672 DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
2673 DESC_A_MASK);
2674 cpu_x86_load_seg_cache(env, R_SS, 0, 0, 0xffff,
2675 DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
2676 DESC_A_MASK);
2677 cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0xffff,
2678 DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
2679 DESC_A_MASK);
2680 cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0xffff,
2681 DESC_P_MASK | DESC_S_MASK | DESC_W_MASK |
2682 DESC_A_MASK);
2683
2684 env->eip = 0xfff0;
2685 env->regs[R_EDX] = env->cpuid_version;
2686
2687 env->eflags = 0x2;
2688
2689 /* FPU init */
2690 for (i = 0; i < 8; i++) {
2691 env->fptags[i] = 1;
2692 }
Pavel Dovgalyuk5bde1402014-09-17 12:05:19 +04002693 cpu_set_fpuc(env, 0x37f);
Andreas Färberc1958ae2012-04-03 00:16:24 +02002694
2695 env->mxcsr = 0x1f80;
Paolo Bonzinic74f41b2013-09-13 15:55:57 +02002696 env->xstate_bv = XSTATE_FP | XSTATE_SSE;
Andreas Färberc1958ae2012-04-03 00:16:24 +02002697
2698 env->pat = 0x0007040600070406ULL;
2699 env->msr_ia32_misc_enable = MSR_IA32_MISC_ENABLE_DEFAULT;
2700
2701 memset(env->dr, 0, sizeof(env->dr));
2702 env->dr[6] = DR6_FIXED_1;
2703 env->dr[7] = DR7_FIXED_1;
Andreas Färberb3310ab2013-09-02 17:26:20 +02002704 cpu_breakpoint_remove_all(s, BP_CPU);
Andreas Färber75a34032013-09-02 16:57:02 +02002705 cpu_watchpoint_remove_all(s, BP_CPU);
Igor Mammedovdd673282012-07-23 15:22:27 +02002706
Paolo Bonzini05e7e812014-04-29 13:10:05 +02002707 env->xcr0 = 1;
Fernando Luis Vázquez Cao05226042013-12-06 17:33:01 +09002708
Alex Williamson9db2efd2014-08-14 15:39:39 -06002709 /*
2710 * SDM 11.11.5 requires:
2711 * - IA32_MTRR_DEF_TYPE MSR.E = 0
2712 * - IA32_MTRR_PHYSMASKn.V = 0
2713 * All other bits are undefined. For simplification, zero it all.
2714 */
2715 env->mtrr_deftype = 0;
2716 memset(env->mtrr_var, 0, sizeof(env->mtrr_var));
2717 memset(env->mtrr_fixed, 0, sizeof(env->mtrr_fixed));
2718
Igor Mammedovdd673282012-07-23 15:22:27 +02002719#if !defined(CONFIG_USER_ONLY)
2720 /* We hard-wire the BSP to the first CPU. */
Nadav Amit9cb11fd2015-04-02 02:58:36 +03002721 apic_designate_bsp(cpu->apic_state, s->cpu_index == 0);
Igor Mammedovdd673282012-07-23 15:22:27 +02002722
Andreas Färber259186a2013-01-17 18:51:17 +01002723 s->halted = !cpu_is_bsp(cpu);
Paolo Bonzini50a2c6e2013-03-20 13:11:56 +01002724
2725 if (kvm_enabled()) {
2726 kvm_arch_reset_vcpu(cpu);
2727 }
Igor Mammedovdd673282012-07-23 15:22:27 +02002728#endif
Andreas Färber5fd20872012-04-02 23:20:08 +02002729}
2730
Igor Mammedovdd673282012-07-23 15:22:27 +02002731#ifndef CONFIG_USER_ONLY
2732bool cpu_is_bsp(X86CPU *cpu)
2733{
Chen Fan02e51482013-12-23 17:04:02 +08002734 return cpu_get_apic_base(cpu->apic_state) & MSR_IA32_APICBASE_BSP;
Igor Mammedovdd673282012-07-23 15:22:27 +02002735}
Igor Mammedov65dee382012-07-23 15:22:28 +02002736
2737/* TODO: remove me, when reset over QOM tree is implemented */
2738static void x86_cpu_machine_reset_cb(void *opaque)
2739{
2740 X86CPU *cpu = opaque;
2741 cpu_reset(CPU(cpu));
2742}
Igor Mammedovdd673282012-07-23 15:22:27 +02002743#endif
2744
Andreas Färberde024812012-04-03 00:00:17 +02002745static void mce_init(X86CPU *cpu)
2746{
2747 CPUX86State *cenv = &cpu->env;
2748 unsigned int bank;
2749
2750 if (((cenv->cpuid_version >> 8) & 0xf) >= 6
Eduardo Habkost0514ef22013-04-22 16:00:15 -03002751 && (cenv->features[FEAT_1_EDX] & (CPUID_MCE | CPUID_MCA)) ==
Andreas Färberde024812012-04-03 00:00:17 +02002752 (CPUID_MCE | CPUID_MCA)) {
2753 cenv->mcg_cap = MCE_CAP_DEF | MCE_BANKS_DEF;
2754 cenv->mcg_ctl = ~(uint64_t)0;
2755 for (bank = 0; bank < MCE_BANKS_DEF; bank++) {
2756 cenv->mce_banks[bank * 4] = ~(uint64_t)0;
2757 }
2758 }
2759}
2760
Igor Mammedovbdeec802012-10-13 22:35:39 +02002761#ifndef CONFIG_USER_ONLY
Igor Mammedovd3c64d62013-04-05 16:36:54 +02002762static void x86_cpu_apic_create(X86CPU *cpu, Error **errp)
Igor Mammedovbdeec802012-10-13 22:35:39 +02002763{
Andreas Färber449994e2012-10-10 12:18:02 +02002764 APICCommonState *apic;
Igor Mammedovbdeec802012-10-13 22:35:39 +02002765 const char *apic_type = "apic";
2766
Paolo Bonzini15eafc22015-12-17 17:16:08 +01002767 if (kvm_apic_in_kernel()) {
Igor Mammedovbdeec802012-10-13 22:35:39 +02002768 apic_type = "kvm-apic";
2769 } else if (xen_enabled()) {
2770 apic_type = "xen-apic";
2771 }
2772
Chen Fan46232aa2015-09-16 17:19:14 +08002773 cpu->apic_state = DEVICE(object_new(apic_type));
Igor Mammedovbdeec802012-10-13 22:35:39 +02002774
2775 object_property_add_child(OBJECT(cpu), "apic",
Chen Fan02e51482013-12-23 17:04:02 +08002776 OBJECT(cpu->apic_state), NULL);
Eduardo Habkost7e72a452014-12-18 23:20:10 -02002777 qdev_prop_set_uint8(cpu->apic_state, "id", cpu->apic_id);
Igor Mammedovbdeec802012-10-13 22:35:39 +02002778 /* TODO: convert to link<> */
Chen Fan02e51482013-12-23 17:04:02 +08002779 apic = APIC_COMMON(cpu->apic_state);
Andreas Färber60671e52012-10-10 14:10:07 +02002780 apic->cpu = cpu;
Chen Fan8d42d2d2015-09-16 17:19:11 +08002781 apic->apicbase = APIC_DEFAULT_ADDRESS | MSR_IA32_APICBASE_ENABLE;
Igor Mammedovd3c64d62013-04-05 16:36:54 +02002782}
2783
2784static void x86_cpu_apic_realize(X86CPU *cpu, Error **errp)
2785{
Chen Fan8d42d2d2015-09-16 17:19:11 +08002786 APICCommonState *apic;
2787 static bool apic_mmio_map_once;
2788
Chen Fan02e51482013-12-23 17:04:02 +08002789 if (cpu->apic_state == NULL) {
Igor Mammedovd3c64d62013-04-05 16:36:54 +02002790 return;
2791 }
Markus Armbruster6e8e2652015-02-05 10:29:15 +01002792 object_property_set_bool(OBJECT(cpu->apic_state), true, "realized",
2793 errp);
Chen Fan8d42d2d2015-09-16 17:19:11 +08002794
2795 /* Map APIC MMIO area */
2796 apic = APIC_COMMON(cpu->apic_state);
2797 if (!apic_mmio_map_once) {
2798 memory_region_add_subregion_overlap(get_system_memory(),
2799 apic->apicbase &
2800 MSR_IA32_APICBASE_BASE,
2801 &apic->io_memory,
2802 0x1000);
2803 apic_mmio_map_once = true;
2804 }
Igor Mammedovbdeec802012-10-13 22:35:39 +02002805}
Paolo Bonzinif809c602015-03-31 14:12:25 +02002806
2807static void x86_cpu_machine_done(Notifier *n, void *unused)
2808{
2809 X86CPU *cpu = container_of(n, X86CPU, machine_done);
2810 MemoryRegion *smram =
2811 (MemoryRegion *) object_resolve_path("/machine/smram", NULL);
2812
2813 if (smram) {
2814 cpu->smram = g_new(MemoryRegion, 1);
2815 memory_region_init_alias(cpu->smram, OBJECT(cpu), "smram",
2816 smram, 0, 1ull << 32);
2817 memory_region_set_enabled(cpu->smram, false);
2818 memory_region_add_subregion_overlap(cpu->cpu_as_root, 0, cpu->smram, 1);
2819 }
2820}
Igor Mammedovd3c64d62013-04-05 16:36:54 +02002821#else
2822static void x86_cpu_apic_realize(X86CPU *cpu, Error **errp)
2823{
2824}
Igor Mammedovbdeec802012-10-13 22:35:39 +02002825#endif
2826
Wei Huange48638f2014-10-21 11:00:45 -04002827
2828#define IS_INTEL_CPU(env) ((env)->cpuid_vendor1 == CPUID_VENDOR_INTEL_1 && \
2829 (env)->cpuid_vendor2 == CPUID_VENDOR_INTEL_2 && \
2830 (env)->cpuid_vendor3 == CPUID_VENDOR_INTEL_3)
2831#define IS_AMD_CPU(env) ((env)->cpuid_vendor1 == CPUID_VENDOR_AMD_1 && \
2832 (env)->cpuid_vendor2 == CPUID_VENDOR_AMD_2 && \
2833 (env)->cpuid_vendor3 == CPUID_VENDOR_AMD_3)
Andreas Färber2b6f2942013-01-16 03:41:47 +01002834static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
Andreas Färber7a059952012-05-09 23:15:32 +02002835{
Andreas Färber14a10fc2013-07-27 02:53:25 +02002836 CPUState *cs = CPU(dev);
Andreas Färber2b6f2942013-01-16 03:41:47 +01002837 X86CPU *cpu = X86_CPU(dev);
2838 X86CPUClass *xcc = X86_CPU_GET_CLASS(dev);
Igor Mammedovb34d12d2012-10-22 17:03:00 +02002839 CPUX86State *env = &cpu->env;
Andreas Färber2b6f2942013-01-16 03:41:47 +01002840 Error *local_err = NULL;
Wei Huange48638f2014-10-21 11:00:45 -04002841 static bool ht_warned;
Igor Mammedovb34d12d2012-10-22 17:03:00 +02002842
Eduardo Habkost9886e832014-12-18 23:31:11 -02002843 if (cpu->apic_id < 0) {
2844 error_setg(errp, "apic-id property was not initialized properly");
2845 return;
2846 }
2847
Eduardo Habkost0514ef22013-04-22 16:00:15 -03002848 if (env->features[FEAT_7_0_EBX] && env->cpuid_level < 7) {
Igor Mammedovb34d12d2012-10-22 17:03:00 +02002849 env->cpuid_level = 7;
2850 }
Andreas Färber7a059952012-05-09 23:15:32 +02002851
Igor Mammedov9b15cd92012-12-28 21:01:17 +01002852 /* On AMD CPUs, some CPUID[8000_0001].EDX bits must match the bits on
2853 * CPUID[1].EDX.
2854 */
Wei Huange48638f2014-10-21 11:00:45 -04002855 if (IS_AMD_CPU(env)) {
Eduardo Habkost0514ef22013-04-22 16:00:15 -03002856 env->features[FEAT_8000_0001_EDX] &= ~CPUID_EXT2_AMD_ALIASES;
2857 env->features[FEAT_8000_0001_EDX] |= (env->features[FEAT_1_EDX]
Igor Mammedov9b15cd92012-12-28 21:01:17 +01002858 & CPUID_EXT2_AMD_ALIASES);
2859 }
2860
Eduardo Habkostfefb41b2014-04-30 13:48:39 -03002861
2862 if (x86_cpu_filter_features(cpu) && cpu->enforce_cpuid) {
2863 error_setg(&local_err,
2864 kvm_enabled() ?
2865 "Host doesn't support requested features" :
2866 "TCG doesn't support requested features");
2867 goto out;
Igor Mammedov4586f152012-12-28 21:01:16 +01002868 }
2869
Igor Mammedov65dee382012-07-23 15:22:28 +02002870#ifndef CONFIG_USER_ONLY
2871 qemu_register_reset(x86_cpu_machine_reset_cb, cpu);
Igor Mammedovbdeec802012-10-13 22:35:39 +02002872
Eduardo Habkost0514ef22013-04-22 16:00:15 -03002873 if (cpu->env.features[FEAT_1_EDX] & CPUID_APIC || smp_cpus > 1) {
Igor Mammedovd3c64d62013-04-05 16:36:54 +02002874 x86_cpu_apic_create(cpu, &local_err);
Andreas Färber2b6f2942013-01-16 03:41:47 +01002875 if (local_err != NULL) {
Igor Mammedov4dc1f442013-04-05 16:36:53 +02002876 goto out;
Igor Mammedovbdeec802012-10-13 22:35:39 +02002877 }
2878 }
Igor Mammedov65dee382012-07-23 15:22:28 +02002879#endif
2880
Andreas Färber7a059952012-05-09 23:15:32 +02002881 mce_init(cpu);
Paolo Bonzini2001d0c2015-03-31 14:11:09 +02002882
2883#ifndef CONFIG_USER_ONLY
2884 if (tcg_enabled()) {
Paolo Bonzinif809c602015-03-31 14:12:25 +02002885 cpu->cpu_as_mem = g_new(MemoryRegion, 1);
Paolo Bonzini2001d0c2015-03-31 14:11:09 +02002886 cpu->cpu_as_root = g_new(MemoryRegion, 1);
2887 cs->as = g_new(AddressSpace, 1);
Paolo Bonzinif809c602015-03-31 14:12:25 +02002888
2889 /* Outer container... */
2890 memory_region_init(cpu->cpu_as_root, OBJECT(cpu), "memory", ~0ull);
Paolo Bonzini2001d0c2015-03-31 14:11:09 +02002891 memory_region_set_enabled(cpu->cpu_as_root, true);
Paolo Bonzinif809c602015-03-31 14:12:25 +02002892
2893 /* ... with two regions inside: normal system memory with low
2894 * priority, and...
2895 */
2896 memory_region_init_alias(cpu->cpu_as_mem, OBJECT(cpu), "memory",
2897 get_system_memory(), 0, ~0ull);
2898 memory_region_add_subregion_overlap(cpu->cpu_as_root, 0, cpu->cpu_as_mem, 0);
2899 memory_region_set_enabled(cpu->cpu_as_mem, true);
Paolo Bonzini2001d0c2015-03-31 14:11:09 +02002900 address_space_init(cs->as, cpu->cpu_as_root, "CPU");
Paolo Bonzinif809c602015-03-31 14:12:25 +02002901
2902 /* ... SMRAM with higher priority, linked from /machine/smram. */
2903 cpu->machine_done.notify = x86_cpu_machine_done;
2904 qemu_add_machine_init_done_notifier(&cpu->machine_done);
Paolo Bonzini2001d0c2015-03-31 14:11:09 +02002905 }
2906#endif
2907
Andreas Färber14a10fc2013-07-27 02:53:25 +02002908 qemu_init_vcpu(cs);
Igor Mammedovd3c64d62013-04-05 16:36:54 +02002909
Wei Huange48638f2014-10-21 11:00:45 -04002910 /* Only Intel CPUs support hyperthreading. Even though QEMU fixes this
2911 * issue by adjusting CPUID_0000_0001_EBX and CPUID_8000_0008_ECX
2912 * based on inputs (sockets,cores,threads), it is still better to gives
2913 * users a warning.
2914 *
2915 * NOTE: the following code has to follow qemu_init_vcpu(). Otherwise
2916 * cs->nr_threads hasn't be populated yet and the checking is incorrect.
2917 */
2918 if (!IS_INTEL_CPU(env) && cs->nr_threads > 1 && !ht_warned) {
2919 error_report("AMD CPU doesn't support hyperthreading. Please configure"
2920 " -smp options properly.");
2921 ht_warned = true;
2922 }
2923
Igor Mammedovd3c64d62013-04-05 16:36:54 +02002924 x86_cpu_apic_realize(cpu, &local_err);
2925 if (local_err != NULL) {
2926 goto out;
2927 }
Andreas Färber14a10fc2013-07-27 02:53:25 +02002928 cpu_reset(cs);
Andreas Färber2b6f2942013-01-16 03:41:47 +01002929
Igor Mammedov4dc1f442013-04-05 16:36:53 +02002930 xcc->parent_realize(dev, &local_err);
Paolo Bonzini2001d0c2015-03-31 14:11:09 +02002931
Igor Mammedov4dc1f442013-04-05 16:36:53 +02002932out:
2933 if (local_err != NULL) {
2934 error_propagate(errp, local_err);
2935 return;
2936 }
Andreas Färber7a059952012-05-09 23:15:32 +02002937}
2938
Eduardo Habkost38e5c112015-03-23 17:29:32 -03002939typedef struct BitProperty {
2940 uint32_t *ptr;
2941 uint32_t mask;
2942} BitProperty;
2943
2944static void x86_cpu_get_bit_prop(Object *obj,
2945 struct Visitor *v,
2946 void *opaque,
2947 const char *name,
2948 Error **errp)
2949{
2950 BitProperty *fp = opaque;
2951 bool value = (*fp->ptr & fp->mask) == fp->mask;
2952 visit_type_bool(v, &value, name, errp);
2953}
2954
2955static void x86_cpu_set_bit_prop(Object *obj,
2956 struct Visitor *v,
2957 void *opaque,
2958 const char *name,
2959 Error **errp)
2960{
2961 DeviceState *dev = DEVICE(obj);
2962 BitProperty *fp = opaque;
2963 Error *local_err = NULL;
2964 bool value;
2965
2966 if (dev->realized) {
2967 qdev_prop_set_after_realize(dev, name, errp);
2968 return;
2969 }
2970
2971 visit_type_bool(v, &value, name, &local_err);
2972 if (local_err) {
2973 error_propagate(errp, local_err);
2974 return;
2975 }
2976
2977 if (value) {
2978 *fp->ptr |= fp->mask;
2979 } else {
2980 *fp->ptr &= ~fp->mask;
2981 }
2982}
2983
2984static void x86_cpu_release_bit_prop(Object *obj, const char *name,
2985 void *opaque)
2986{
2987 BitProperty *prop = opaque;
2988 g_free(prop);
2989}
2990
2991/* Register a boolean property to get/set a single bit in a uint32_t field.
2992 *
2993 * The same property name can be registered multiple times to make it affect
2994 * multiple bits in the same FeatureWord. In that case, the getter will return
2995 * true only if all bits are set.
2996 */
2997static void x86_cpu_register_bit_prop(X86CPU *cpu,
2998 const char *prop_name,
2999 uint32_t *field,
3000 int bitnr)
3001{
3002 BitProperty *fp;
3003 ObjectProperty *op;
3004 uint32_t mask = (1UL << bitnr);
3005
3006 op = object_property_find(OBJECT(cpu), prop_name, NULL);
3007 if (op) {
3008 fp = op->opaque;
3009 assert(fp->ptr == field);
3010 fp->mask |= mask;
3011 } else {
3012 fp = g_new0(BitProperty, 1);
3013 fp->ptr = field;
3014 fp->mask = mask;
3015 object_property_add(OBJECT(cpu), prop_name, "bool",
3016 x86_cpu_get_bit_prop,
3017 x86_cpu_set_bit_prop,
3018 x86_cpu_release_bit_prop, fp, &error_abort);
3019 }
3020}
3021
3022static void x86_cpu_register_feature_bit_props(X86CPU *cpu,
3023 FeatureWord w,
3024 int bitnr)
3025{
3026 Object *obj = OBJECT(cpu);
3027 int i;
3028 char **names;
3029 FeatureWordInfo *fi = &feature_word_info[w];
3030
3031 if (!fi->feat_names) {
3032 return;
3033 }
3034 if (!fi->feat_names[bitnr]) {
3035 return;
3036 }
3037
3038 names = g_strsplit(fi->feat_names[bitnr], "|", 0);
3039
3040 feat2prop(names[0]);
3041 x86_cpu_register_bit_prop(cpu, names[0], &cpu->env.features[w], bitnr);
3042
3043 for (i = 1; names[i]; i++) {
3044 feat2prop(names[i]);
Eduardo Habkostd461a442015-07-09 12:24:43 -03003045 object_property_add_alias(obj, names[i], obj, names[0],
Eduardo Habkost38e5c112015-03-23 17:29:32 -03003046 &error_abort);
3047 }
3048
3049 g_strfreev(names);
3050}
3051
Andreas Färberde024812012-04-03 00:00:17 +02003052static void x86_cpu_initfn(Object *obj)
3053{
Andreas Färber55e5c282012-12-17 06:18:02 +01003054 CPUState *cs = CPU(obj);
Andreas Färberde024812012-04-03 00:00:17 +02003055 X86CPU *cpu = X86_CPU(obj);
Eduardo Habkostd940ee92014-02-10 08:21:30 -02003056 X86CPUClass *xcc = X86_CPU_GET_CLASS(obj);
Andreas Färberde024812012-04-03 00:00:17 +02003057 CPUX86State *env = &cpu->env;
Eduardo Habkost38e5c112015-03-23 17:29:32 -03003058 FeatureWord w;
Igor Mammedovd65e9812012-06-19 15:39:46 +02003059 static int inited;
Andreas Färberde024812012-04-03 00:00:17 +02003060
Andreas Färberc05efcb2013-01-17 12:13:41 +01003061 cs->env_ptr = env;
Peter Crosthwaite4bad9e32015-06-23 19:31:18 -07003062 cpu_exec_init(cs, &error_abort);
Andreas Färber71ad61d2012-04-17 12:10:29 +02003063
3064 object_property_add(obj, "family", "int",
Andreas Färber95b85192012-04-17 14:42:22 +02003065 x86_cpuid_version_get_family,
Andreas Färber71ad61d2012-04-17 12:10:29 +02003066 x86_cpuid_version_set_family, NULL, NULL, NULL);
Andreas Färberc5291a42012-04-17 12:16:39 +02003067 object_property_add(obj, "model", "int",
Andreas Färber67e30c82012-04-17 14:48:14 +02003068 x86_cpuid_version_get_model,
Andreas Färberc5291a42012-04-17 12:16:39 +02003069 x86_cpuid_version_set_model, NULL, NULL, NULL);
Andreas Färber036e2222012-04-17 14:14:18 +02003070 object_property_add(obj, "stepping", "int",
Andreas Färber35112e42012-04-17 14:50:53 +02003071 x86_cpuid_version_get_stepping,
Andreas Färber036e2222012-04-17 14:14:18 +02003072 x86_cpuid_version_set_stepping, NULL, NULL, NULL);
Andreas Färberd480e1a2012-04-17 19:22:58 +02003073 object_property_add_str(obj, "vendor",
3074 x86_cpuid_get_vendor,
3075 x86_cpuid_set_vendor, NULL);
Andreas Färber938d4c22012-04-17 15:17:27 +02003076 object_property_add_str(obj, "model-id",
Andreas Färber63e886e2012-04-17 23:02:26 +02003077 x86_cpuid_get_model_id,
Andreas Färber938d4c22012-04-17 15:17:27 +02003078 x86_cpuid_set_model_id, NULL);
Andreas Färber89e48962012-04-18 00:12:23 +02003079 object_property_add(obj, "tsc-frequency", "int",
3080 x86_cpuid_get_tsc_freq,
3081 x86_cpuid_set_tsc_freq, NULL, NULL, NULL);
Igor Mammedov31050932013-04-25 16:05:26 +02003082 object_property_add(obj, "apic-id", "int",
3083 x86_cpuid_get_apic_id,
3084 x86_cpuid_set_apic_id, NULL, NULL, NULL);
Eduardo Habkost8e8aba52013-05-06 13:20:07 -03003085 object_property_add(obj, "feature-words", "X86CPUFeatureWordInfo",
3086 x86_cpu_get_feature_words,
Eduardo Habkost7e5292b2013-05-06 13:20:09 -03003087 NULL, NULL, (void *)env->features, NULL);
3088 object_property_add(obj, "filtered-features", "X86CPUFeatureWordInfo",
3089 x86_cpu_get_feature_words,
3090 NULL, NULL, (void *)cpu->filtered_features, NULL);
Andreas Färber71ad61d2012-04-17 12:10:29 +02003091
Igor Mammedov92067bf2013-06-05 15:18:40 +02003092 cpu->hyperv_spinlock_attempts = HYPERV_SPINLOCK_NEVER_RETRY;
Igor Mammedovd65e9812012-06-19 15:39:46 +02003093
Eduardo Habkost9886e832014-12-18 23:31:11 -02003094#ifndef CONFIG_USER_ONLY
3095 /* Any code creating new X86CPU objects have to set apic-id explicitly */
3096 cpu->apic_id = -1;
3097#endif
3098
Eduardo Habkost38e5c112015-03-23 17:29:32 -03003099 for (w = 0; w < FEATURE_WORDS; w++) {
3100 int bitnr;
3101
3102 for (bitnr = 0; bitnr < 32; bitnr++) {
3103 x86_cpu_register_feature_bit_props(cpu, w, bitnr);
3104 }
3105 }
3106
Eduardo Habkostd940ee92014-02-10 08:21:30 -02003107 x86_cpu_load_def(cpu, xcc->cpu_def, &error_abort);
3108
Igor Mammedovd65e9812012-06-19 15:39:46 +02003109 /* init various static tables used in TCG mode */
3110 if (tcg_enabled() && !inited) {
3111 inited = 1;
Eduardo Habkost63618b42015-03-05 12:38:48 -03003112 tcg_x86_init();
Igor Mammedovd65e9812012-06-19 15:39:46 +02003113 }
Andreas Färberde024812012-04-03 00:00:17 +02003114}
3115
Igor Mammedov997395d2013-04-23 10:29:41 +02003116static int64_t x86_cpu_get_arch_id(CPUState *cs)
3117{
3118 X86CPU *cpu = X86_CPU(cs);
Igor Mammedov997395d2013-04-23 10:29:41 +02003119
Eduardo Habkost7e72a452014-12-18 23:20:10 -02003120 return cpu->apic_id;
Igor Mammedov997395d2013-04-23 10:29:41 +02003121}
3122
Andreas Färber444d5592013-05-28 13:28:38 +02003123static bool x86_cpu_get_paging_enabled(const CPUState *cs)
3124{
3125 X86CPU *cpu = X86_CPU(cs);
3126
3127 return cpu->env.cr[0] & CR0_PG_MASK;
3128}
3129
Andreas Färberf45748f2013-06-21 19:09:18 +02003130static void x86_cpu_set_pc(CPUState *cs, vaddr value)
3131{
3132 X86CPU *cpu = X86_CPU(cs);
3133
3134 cpu->env.eip = value;
3135}
3136
Andreas Färberbdf7ae52013-06-28 19:31:32 +02003137static void x86_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
3138{
3139 X86CPU *cpu = X86_CPU(cs);
3140
3141 cpu->env.eip = tb->pc - tb->cs_base;
3142}
3143
Andreas Färber8c2e1b02013-08-25 18:53:55 +02003144static bool x86_cpu_has_work(CPUState *cs)
3145{
3146 X86CPU *cpu = X86_CPU(cs);
3147 CPUX86State *env = &cpu->env;
3148
Pavel Dovgalyuk6220e902015-09-17 19:23:31 +03003149 return ((cs->interrupt_request & (CPU_INTERRUPT_HARD |
3150 CPU_INTERRUPT_POLL)) &&
Andreas Färber8c2e1b02013-08-25 18:53:55 +02003151 (env->eflags & IF_MASK)) ||
3152 (cs->interrupt_request & (CPU_INTERRUPT_NMI |
3153 CPU_INTERRUPT_INIT |
3154 CPU_INTERRUPT_SIPI |
Paolo Bonzinia9bad652015-05-19 13:46:47 +02003155 CPU_INTERRUPT_MCE)) ||
3156 ((cs->interrupt_request & CPU_INTERRUPT_SMI) &&
3157 !(env->hflags & HF_SMM_MASK));
Andreas Färber8c2e1b02013-08-25 18:53:55 +02003158}
3159
Eduardo Habkost9337e3b2013-07-26 17:09:36 -03003160static Property x86_cpu_properties[] = {
3161 DEFINE_PROP_BOOL("pmu", X86CPU, enable_pmu, false),
Igor Mammedovc8f0f882013-06-04 15:05:25 +02003162 { .name = "hv-spinlocks", .info = &qdev_prop_spinlocks },
Igor Mammedov89314502012-08-08 13:52:51 +02003163 DEFINE_PROP_BOOL("hv-relaxed", X86CPU, hyperv_relaxed_timing, false),
Igor Mammedov0f466852012-08-08 13:54:27 +02003164 DEFINE_PROP_BOOL("hv-vapic", X86CPU, hyperv_vapic, false),
Vadim Rozenfeld48a5f3b2014-01-24 00:40:49 +11003165 DEFINE_PROP_BOOL("hv-time", X86CPU, hyperv_time, false),
Andrey Smetaninf2a53c92015-09-09 14:41:30 +02003166 DEFINE_PROP_BOOL("hv-crash", X86CPU, hyperv_crash, false),
Andrey Smetanin744b8a92015-09-16 12:59:42 +03003167 DEFINE_PROP_BOOL("hv-reset", X86CPU, hyperv_reset, false),
Andrey Smetanin8c145d72015-09-16 12:59:43 +03003168 DEFINE_PROP_BOOL("hv-vpindex", X86CPU, hyperv_vpindex, false),
Andrey Smetanin46eb8f92015-09-16 12:59:44 +03003169 DEFINE_PROP_BOOL("hv-runtime", X86CPU, hyperv_runtime, false),
Andrey Smetanin866eea92015-11-11 13:18:38 +03003170 DEFINE_PROP_BOOL("hv-synic", X86CPU, hyperv_synic, false),
Andrey Smetaninff99aa62015-11-25 18:21:25 +03003171 DEFINE_PROP_BOOL("hv-stimer", X86CPU, hyperv_stimer, false),
Eduardo Habkost15e41342015-08-26 13:25:44 -03003172 DEFINE_PROP_BOOL("check", X86CPU, check_cpuid, true),
Igor Mammedov912ffc42013-06-04 15:13:14 +02003173 DEFINE_PROP_BOOL("enforce", X86CPU, enforce_cpuid, false),
Alex Williamsonf522d2a2014-06-02 11:28:50 -06003174 DEFINE_PROP_BOOL("kvm", X86CPU, expose_kvm, true),
Eduardo Habkostb9472b72015-04-02 17:21:53 -03003175 DEFINE_PROP_UINT32("level", X86CPU, env.cpuid_level, 0),
3176 DEFINE_PROP_UINT32("xlevel", X86CPU, env.cpuid_xlevel, 0),
Eduardo Habkost01431f32015-04-02 17:22:27 -03003177 DEFINE_PROP_UINT32("xlevel2", X86CPU, env.cpuid_xlevel2, 0),
Alex Williamson1c4a55d2015-10-16 09:38:22 -06003178 DEFINE_PROP_STRING("hv-vendor-id", X86CPU, hyperv_vendor_id),
Eduardo Habkost9337e3b2013-07-26 17:09:36 -03003179 DEFINE_PROP_END_OF_LIST()
3180};
3181
Andreas Färber5fd20872012-04-02 23:20:08 +02003182static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
3183{
3184 X86CPUClass *xcc = X86_CPU_CLASS(oc);
3185 CPUClass *cc = CPU_CLASS(oc);
Andreas Färber2b6f2942013-01-16 03:41:47 +01003186 DeviceClass *dc = DEVICE_CLASS(oc);
3187
3188 xcc->parent_realize = dc->realize;
3189 dc->realize = x86_cpu_realizefn;
Eduardo Habkost9337e3b2013-07-26 17:09:36 -03003190 dc->props = x86_cpu_properties;
Andreas Färber5fd20872012-04-02 23:20:08 +02003191
3192 xcc->parent_reset = cc->reset;
3193 cc->reset = x86_cpu_reset;
Andreas Färber91b1df82013-06-16 07:49:48 +02003194 cc->reset_dump_flags = CPU_DUMP_FPU | CPU_DUMP_CCOP;
Andreas Färberf56e3a12013-02-02 13:38:08 +01003195
Andreas Färber500050d2014-02-10 22:02:44 +01003196 cc->class_by_name = x86_cpu_class_by_name;
Andreas Färber94a444b2014-03-03 23:19:19 +01003197 cc->parse_features = x86_cpu_parse_featurestr;
Andreas Färber8c2e1b02013-08-25 18:53:55 +02003198 cc->has_work = x86_cpu_has_work;
Andreas Färber97a8ea52013-02-02 10:57:51 +01003199 cc->do_interrupt = x86_cpu_do_interrupt;
Richard Henderson42f53fe2014-09-13 09:45:33 -07003200 cc->cpu_exec_interrupt = x86_cpu_exec_interrupt;
Andreas Färber878096e2013-05-27 01:33:50 +02003201 cc->dump_state = x86_cpu_dump_state;
Andreas Färberf45748f2013-06-21 19:09:18 +02003202 cc->set_pc = x86_cpu_set_pc;
Andreas Färberbdf7ae52013-06-28 19:31:32 +02003203 cc->synchronize_from_tb = x86_cpu_synchronize_from_tb;
Andreas Färber5b50e792013-06-29 04:18:45 +02003204 cc->gdb_read_register = x86_cpu_gdb_read_register;
3205 cc->gdb_write_register = x86_cpu_gdb_write_register;
Andreas Färber444d5592013-05-28 13:28:38 +02003206 cc->get_arch_id = x86_cpu_get_arch_id;
3207 cc->get_paging_enabled = x86_cpu_get_paging_enabled;
Andreas Färber75104542013-08-26 03:01:33 +02003208#ifdef CONFIG_USER_ONLY
3209 cc->handle_mmu_fault = x86_cpu_handle_mmu_fault;
3210#else
Andreas Färbera23bbfd2013-05-28 13:52:01 +02003211 cc->get_memory_mapping = x86_cpu_get_memory_mapping;
Andreas Färber00b941e2013-06-29 18:55:54 +02003212 cc->get_phys_page_debug = x86_cpu_get_phys_page_debug;
Jens Freimannc72bf462013-04-19 16:45:06 +02003213 cc->write_elf64_note = x86_cpu_write_elf64_note;
3214 cc->write_elf64_qemunote = x86_cpu_write_elf64_qemunote;
3215 cc->write_elf32_note = x86_cpu_write_elf32_note;
3216 cc->write_elf32_qemunote = x86_cpu_write_elf32_qemunote;
Andreas Färber00b941e2013-06-29 18:55:54 +02003217 cc->vmsd = &vmstate_x86_cpu;
Jens Freimannc72bf462013-04-19 16:45:06 +02003218#endif
Andreas Färbera0e372f2013-06-28 23:18:47 +02003219 cc->gdb_num_core_regs = CPU_NB_REGS * 2 + 25;
Peter Maydell86025ee2014-09-12 14:06:48 +01003220#ifndef CONFIG_USER_ONLY
3221 cc->debug_excp_handler = breakpoint_handler;
3222#endif
Richard Henderson374e0cd2014-09-13 09:45:14 -07003223 cc->cpu_exec_enter = x86_cpu_exec_enter;
3224 cc->cpu_exec_exit = x86_cpu_exec_exit;
Markus Armbruster4c315c22015-10-01 10:59:58 +02003225
3226 /*
3227 * Reason: x86_cpu_initfn() calls cpu_exec_init(), which saves the
3228 * object in cpus -> dangling pointer after final object_unref().
3229 */
3230 dc->cannot_destroy_with_object_finalize_yet = true;
Andreas Färber5fd20872012-04-02 23:20:08 +02003231}
3232
3233static const TypeInfo x86_cpu_type_info = {
3234 .name = TYPE_X86_CPU,
3235 .parent = TYPE_CPU,
3236 .instance_size = sizeof(X86CPU),
Andreas Färberde024812012-04-03 00:00:17 +02003237 .instance_init = x86_cpu_initfn,
Eduardo Habkostd940ee92014-02-10 08:21:30 -02003238 .abstract = true,
Andreas Färber5fd20872012-04-02 23:20:08 +02003239 .class_size = sizeof(X86CPUClass),
3240 .class_init = x86_cpu_common_class_init,
3241};
3242
3243static void x86_cpu_register_types(void)
3244{
Eduardo Habkostd940ee92014-02-10 08:21:30 -02003245 int i;
3246
Andreas Färber5fd20872012-04-02 23:20:08 +02003247 type_register_static(&x86_cpu_type_info);
Eduardo Habkostd940ee92014-02-10 08:21:30 -02003248 for (i = 0; i < ARRAY_SIZE(builtin_x86_defs); i++) {
3249 x86_register_cpudef_type(&builtin_x86_defs[i]);
3250 }
3251#ifdef CONFIG_KVM
3252 type_register_static(&host_x86_cpu_type_info);
3253#endif
Andreas Färber5fd20872012-04-02 23:20:08 +02003254}
3255
3256type_init(x86_cpu_register_types)