mirror of
https://github.com/qemu/qemu.git
synced 2024-11-24 19:33:39 +08:00
X86CPU
* Filter out MONITOR for KVM * Fix filtering for TCG * -cpu foo,check and -cpu foo,enforce support for TCG * -cpu host migration support (-cpu host,migratable=no to disable) * Add invtsc feature support * New model: Broadwell -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQIcBAABAgAGBQJTq0U4AAoJEPou0S0+fgE/68AP/Amk6LYhiyhGXEbTNAZcf84k qwnU7bX/4KRt508ygjtySgjxkKnkw2xDIZLjdjI48z+81m76h/lv4+X9kAmsnCjT DUTNXeNb4QYylGXxKChkQ+KZNPb6HstUcnAUtiP+3tgDf58IVZRjJgtBSpBEv9y3 k0UbHhS9cHoksLOLG/8S435FnTpZg2vyVeANxGouC8Zt7T5Zu/WvstqmsVfF2+CR eEwlbtdwcaSbWFSesG6kEI06Ty/zX//VZpFbEZK36nyU6tZ78SrYO9v/QqXun/hA gJuANsthahvaZPWtYNGzsFkTuwD8WgVnrtsg33M82aCq0z3Zp2SJ0UXuQrFe5+qr xrZCMb51SyHsBna7X2w30JBgoEvS70g7WO2LdNUvZpmiTNWN5UEouT9c2o0tLoqP rsNpO1aMRJVeJt8FckWMUEgl19UYjEliLO7WqBD5a3AjjuvIiwQOLuA5ev7GpO9b sXPTnwqJLz3BNVIQlce5DNBezKmfq0ffnZdkxn0Y42DE7oSbU2/SO7+WGSc6exnx /vXN/wrHnfVp9nzt54ANnAs7RHCKvlkrmAdsuW82k4lP5Nkoe7bZu6PjefRO07uo XUgQ84RSHUn1b2qyC1uLN/c97F7mM5sYhVDIWB0DpO86/vgMGWgymSp4Md38ZNWm 4H8L34HuFLXan4vHuPuz =h6c5 -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/afaerber/tags/qom-cpu-for-2.1' into staging X86CPU * Filter out MONITOR for KVM * Fix filtering for TCG * -cpu foo,check and -cpu foo,enforce support for TCG * -cpu host migration support (-cpu host,migratable=no to disable) * Add invtsc feature support * New model: Broadwell # gpg: Signature made Wed 25 Jun 2014 22:55:04 BST using RSA key ID 3E7E013F # gpg: Good signature from "Andreas Färber <afaerber@suse.de>" # gpg: aka "Andreas Färber <afaerber@suse.com>" * remotes/afaerber/tags/qom-cpu-for-2.1: target-i386: Broadwell CPU model target-i386: Fix indentation of CPU model definitions target-i386: Support "invariant tsc" flag target-i386: block migration and savevm if invariant tsc is exposed savevm: check vmsd for migratability status target-i386: Set migratable=yes by default on "host" CPU mooel target-i386: Add "migratable" property to "host" CPU model target-i386: Support check/enforce flags in TCG mode, too target-i386: Loop-based feature word filtering in TCG mode target-i386: Loop-based copying and setting/unsetting of feature words target-i386: Define TCG_*_FEATURES earlier in cpu.c target-i386: Filter KVM and 0xC0000001 features on TCG target-i386: Filter FEAT_7_0_EBX TCG features too target-i386: Make TCG feature filtering more readable target-i386: Isolate KVM-specific code on CPU feature filtering logic target-i386: Pass FeatureWord argument to report_unavailable_features() target-i386: Merge feature filtering/checking functions target-i386: Simplify reporting of unavailable features target-i386: kvm: Don't enable MONITOR by default on any CPU model Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
8589744aaf
5
savevm.c
5
savevm.c
@ -232,7 +232,6 @@ typedef struct SaveStateEntry {
|
|||||||
const VMStateDescription *vmsd;
|
const VMStateDescription *vmsd;
|
||||||
void *opaque;
|
void *opaque;
|
||||||
CompatEntry *compat;
|
CompatEntry *compat;
|
||||||
int no_migrate;
|
|
||||||
int is_ram;
|
int is_ram;
|
||||||
} SaveStateEntry;
|
} SaveStateEntry;
|
||||||
|
|
||||||
@ -430,7 +429,6 @@ int register_savevm_live(DeviceState *dev,
|
|||||||
se->ops = ops;
|
se->ops = ops;
|
||||||
se->opaque = opaque;
|
se->opaque = opaque;
|
||||||
se->vmsd = NULL;
|
se->vmsd = NULL;
|
||||||
se->no_migrate = 0;
|
|
||||||
/* if this is a live_savem then set is_ram */
|
/* if this is a live_savem then set is_ram */
|
||||||
if (ops->save_live_setup != NULL) {
|
if (ops->save_live_setup != NULL) {
|
||||||
se->is_ram = 1;
|
se->is_ram = 1;
|
||||||
@ -521,7 +519,6 @@ int vmstate_register_with_alias_id(DeviceState *dev, int instance_id,
|
|||||||
se->opaque = opaque;
|
se->opaque = opaque;
|
||||||
se->vmsd = vmsd;
|
se->vmsd = vmsd;
|
||||||
se->alias_id = alias_id;
|
se->alias_id = alias_id;
|
||||||
se->no_migrate = vmsd->unmigratable;
|
|
||||||
|
|
||||||
if (dev) {
|
if (dev) {
|
||||||
char *id = qdev_get_dev_path(dev);
|
char *id = qdev_get_dev_path(dev);
|
||||||
@ -590,7 +587,7 @@ bool qemu_savevm_state_blocked(Error **errp)
|
|||||||
SaveStateEntry *se;
|
SaveStateEntry *se;
|
||||||
|
|
||||||
QTAILQ_FOREACH(se, &savevm_handlers, entry) {
|
QTAILQ_FOREACH(se, &savevm_handlers, entry) {
|
||||||
if (se->no_migrate) {
|
if (se->vmsd && se->vmsd->unmigratable) {
|
||||||
error_setg(errp, "State blocked by non-migratable device '%s'",
|
error_setg(errp, "State blocked by non-migratable device '%s'",
|
||||||
se->idstr);
|
se->idstr);
|
||||||
return true;
|
return true;
|
||||||
|
@ -71,6 +71,9 @@ typedef struct X86CPUClass {
|
|||||||
/**
|
/**
|
||||||
* X86CPU:
|
* X86CPU:
|
||||||
* @env: #CPUX86State
|
* @env: #CPUX86State
|
||||||
|
* @migratable: If set, only migratable flags will be accepted when "enforce"
|
||||||
|
* mode is used, and only migratable flags will be included in the "host"
|
||||||
|
* CPU model.
|
||||||
*
|
*
|
||||||
* An x86 CPU.
|
* An x86 CPU.
|
||||||
*/
|
*/
|
||||||
@ -88,6 +91,7 @@ typedef struct X86CPU {
|
|||||||
bool check_cpuid;
|
bool check_cpuid;
|
||||||
bool enforce_cpuid;
|
bool enforce_cpuid;
|
||||||
bool expose_kvm;
|
bool expose_kvm;
|
||||||
|
bool migratable;
|
||||||
|
|
||||||
/* if true the CPUID code directly forward host cache leaves to the guest */
|
/* if true the CPUID code directly forward host cache leaves to the guest */
|
||||||
bool cache_info_passthrough;
|
bool cache_info_passthrough;
|
||||||
@ -117,7 +121,7 @@ static inline X86CPU *x86_env_get_cpu(CPUX86State *env)
|
|||||||
#define ENV_OFFSET offsetof(X86CPU, env)
|
#define ENV_OFFSET offsetof(X86CPU, env)
|
||||||
|
|
||||||
#ifndef CONFIG_USER_ONLY
|
#ifndef CONFIG_USER_ONLY
|
||||||
extern const struct VMStateDescription vmstate_x86_cpu;
|
extern struct VMStateDescription vmstate_x86_cpu;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -263,48 +263,133 @@ static const char *cpuid_7_0_ebx_feature_name[] = {
|
|||||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const char *cpuid_apm_edx_feature_name[] = {
|
||||||
|
NULL, NULL, NULL, NULL,
|
||||||
|
NULL, NULL, NULL, NULL,
|
||||||
|
"invtsc", NULL, NULL, NULL,
|
||||||
|
NULL, NULL, NULL, NULL,
|
||||||
|
NULL, NULL, NULL, NULL,
|
||||||
|
NULL, NULL, NULL, NULL,
|
||||||
|
NULL, NULL, NULL, NULL,
|
||||||
|
NULL, NULL, NULL, NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define I486_FEATURES (CPUID_FP87 | CPUID_VME | CPUID_PSE)
|
||||||
|
#define PENTIUM_FEATURES (I486_FEATURES | CPUID_DE | CPUID_TSC | \
|
||||||
|
CPUID_MSR | CPUID_MCE | CPUID_CX8 | CPUID_MMX | CPUID_APIC)
|
||||||
|
#define PENTIUM2_FEATURES (PENTIUM_FEATURES | CPUID_PAE | CPUID_SEP | \
|
||||||
|
CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_CMOV | CPUID_PAT | \
|
||||||
|
CPUID_PSE36 | CPUID_FXSR)
|
||||||
|
#define PENTIUM3_FEATURES (PENTIUM2_FEATURES | CPUID_SSE)
|
||||||
|
#define PPRO_FEATURES (CPUID_FP87 | CPUID_DE | CPUID_PSE | CPUID_TSC | \
|
||||||
|
CPUID_MSR | CPUID_MCE | CPUID_CX8 | CPUID_PGE | CPUID_CMOV | \
|
||||||
|
CPUID_PAT | CPUID_FXSR | CPUID_MMX | CPUID_SSE | CPUID_SSE2 | \
|
||||||
|
CPUID_PAE | CPUID_SEP | CPUID_APIC)
|
||||||
|
|
||||||
|
#define TCG_FEATURES (CPUID_FP87 | CPUID_PSE | CPUID_TSC | CPUID_MSR | \
|
||||||
|
CPUID_PAE | CPUID_MCE | CPUID_CX8 | CPUID_APIC | CPUID_SEP | \
|
||||||
|
CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_CMOV | CPUID_PAT | \
|
||||||
|
CPUID_PSE36 | CPUID_CLFLUSH | CPUID_ACPI | CPUID_MMX | \
|
||||||
|
CPUID_FXSR | CPUID_SSE | CPUID_SSE2 | CPUID_SS)
|
||||||
|
/* partly implemented:
|
||||||
|
CPUID_MTRR, CPUID_MCA, CPUID_CLFLUSH (needed for Win64) */
|
||||||
|
/* missing:
|
||||||
|
CPUID_VME, CPUID_DTS, CPUID_SS, CPUID_HT, CPUID_TM, CPUID_PBE */
|
||||||
|
#define TCG_EXT_FEATURES (CPUID_EXT_SSE3 | CPUID_EXT_PCLMULQDQ | \
|
||||||
|
CPUID_EXT_MONITOR | CPUID_EXT_SSSE3 | CPUID_EXT_CX16 | \
|
||||||
|
CPUID_EXT_SSE41 | CPUID_EXT_SSE42 | CPUID_EXT_POPCNT | \
|
||||||
|
CPUID_EXT_MOVBE | CPUID_EXT_AES | CPUID_EXT_HYPERVISOR)
|
||||||
|
/* missing:
|
||||||
|
CPUID_EXT_DTES64, CPUID_EXT_DSCPL, CPUID_EXT_VMX, CPUID_EXT_SMX,
|
||||||
|
CPUID_EXT_EST, CPUID_EXT_TM2, CPUID_EXT_CID, CPUID_EXT_FMA,
|
||||||
|
CPUID_EXT_XTPR, CPUID_EXT_PDCM, CPUID_EXT_PCID, CPUID_EXT_DCA,
|
||||||
|
CPUID_EXT_X2APIC, CPUID_EXT_TSC_DEADLINE_TIMER, CPUID_EXT_XSAVE,
|
||||||
|
CPUID_EXT_OSXSAVE, CPUID_EXT_AVX, CPUID_EXT_F16C,
|
||||||
|
CPUID_EXT_RDRAND */
|
||||||
|
|
||||||
|
#ifdef TARGET_X86_64
|
||||||
|
#define TCG_EXT2_X86_64_FEATURES (CPUID_EXT2_SYSCALL | CPUID_EXT2_LM)
|
||||||
|
#else
|
||||||
|
#define TCG_EXT2_X86_64_FEATURES 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define TCG_EXT2_FEATURES ((TCG_FEATURES & CPUID_EXT2_AMD_ALIASES) | \
|
||||||
|
CPUID_EXT2_NX | CPUID_EXT2_MMXEXT | CPUID_EXT2_RDTSCP | \
|
||||||
|
CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT | CPUID_EXT2_PDPE1GB | \
|
||||||
|
TCG_EXT2_X86_64_FEATURES)
|
||||||
|
#define TCG_EXT3_FEATURES (CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM | \
|
||||||
|
CPUID_EXT3_CR8LEG | CPUID_EXT3_ABM | CPUID_EXT3_SSE4A)
|
||||||
|
#define TCG_EXT4_FEATURES 0
|
||||||
|
#define TCG_SVM_FEATURES 0
|
||||||
|
#define TCG_KVM_FEATURES 0
|
||||||
|
#define TCG_7_0_EBX_FEATURES (CPUID_7_0_EBX_SMEP | CPUID_7_0_EBX_SMAP | \
|
||||||
|
CPUID_7_0_EBX_BMI1 | CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ADX)
|
||||||
|
/* missing:
|
||||||
|
CPUID_7_0_EBX_FSGSBASE, CPUID_7_0_EBX_HLE, CPUID_7_0_EBX_AVX2,
|
||||||
|
CPUID_7_0_EBX_ERMS, CPUID_7_0_EBX_INVPCID, CPUID_7_0_EBX_RTM,
|
||||||
|
CPUID_7_0_EBX_RDSEED */
|
||||||
|
#define TCG_APM_FEATURES 0
|
||||||
|
|
||||||
|
|
||||||
typedef struct FeatureWordInfo {
|
typedef struct FeatureWordInfo {
|
||||||
const char **feat_names;
|
const char **feat_names;
|
||||||
uint32_t cpuid_eax; /* Input EAX for CPUID */
|
uint32_t cpuid_eax; /* Input EAX for CPUID */
|
||||||
bool cpuid_needs_ecx; /* CPUID instruction uses ECX as input */
|
bool cpuid_needs_ecx; /* CPUID instruction uses ECX as input */
|
||||||
uint32_t cpuid_ecx; /* Input ECX value for CPUID */
|
uint32_t cpuid_ecx; /* Input ECX value for CPUID */
|
||||||
int cpuid_reg; /* output register (R_* constant) */
|
int cpuid_reg; /* output register (R_* constant) */
|
||||||
|
uint32_t tcg_features; /* Feature flags supported by TCG */
|
||||||
|
uint32_t unmigratable_flags; /* Feature flags known to be unmigratable */
|
||||||
} FeatureWordInfo;
|
} FeatureWordInfo;
|
||||||
|
|
||||||
static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
|
static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
|
||||||
[FEAT_1_EDX] = {
|
[FEAT_1_EDX] = {
|
||||||
.feat_names = feature_name,
|
.feat_names = feature_name,
|
||||||
.cpuid_eax = 1, .cpuid_reg = R_EDX,
|
.cpuid_eax = 1, .cpuid_reg = R_EDX,
|
||||||
|
.tcg_features = TCG_FEATURES,
|
||||||
},
|
},
|
||||||
[FEAT_1_ECX] = {
|
[FEAT_1_ECX] = {
|
||||||
.feat_names = ext_feature_name,
|
.feat_names = ext_feature_name,
|
||||||
.cpuid_eax = 1, .cpuid_reg = R_ECX,
|
.cpuid_eax = 1, .cpuid_reg = R_ECX,
|
||||||
|
.tcg_features = TCG_EXT_FEATURES,
|
||||||
},
|
},
|
||||||
[FEAT_8000_0001_EDX] = {
|
[FEAT_8000_0001_EDX] = {
|
||||||
.feat_names = ext2_feature_name,
|
.feat_names = ext2_feature_name,
|
||||||
.cpuid_eax = 0x80000001, .cpuid_reg = R_EDX,
|
.cpuid_eax = 0x80000001, .cpuid_reg = R_EDX,
|
||||||
|
.tcg_features = TCG_EXT2_FEATURES,
|
||||||
},
|
},
|
||||||
[FEAT_8000_0001_ECX] = {
|
[FEAT_8000_0001_ECX] = {
|
||||||
.feat_names = ext3_feature_name,
|
.feat_names = ext3_feature_name,
|
||||||
.cpuid_eax = 0x80000001, .cpuid_reg = R_ECX,
|
.cpuid_eax = 0x80000001, .cpuid_reg = R_ECX,
|
||||||
|
.tcg_features = TCG_EXT3_FEATURES,
|
||||||
},
|
},
|
||||||
[FEAT_C000_0001_EDX] = {
|
[FEAT_C000_0001_EDX] = {
|
||||||
.feat_names = ext4_feature_name,
|
.feat_names = ext4_feature_name,
|
||||||
.cpuid_eax = 0xC0000001, .cpuid_reg = R_EDX,
|
.cpuid_eax = 0xC0000001, .cpuid_reg = R_EDX,
|
||||||
|
.tcg_features = TCG_EXT4_FEATURES,
|
||||||
},
|
},
|
||||||
[FEAT_KVM] = {
|
[FEAT_KVM] = {
|
||||||
.feat_names = kvm_feature_name,
|
.feat_names = kvm_feature_name,
|
||||||
.cpuid_eax = KVM_CPUID_FEATURES, .cpuid_reg = R_EAX,
|
.cpuid_eax = KVM_CPUID_FEATURES, .cpuid_reg = R_EAX,
|
||||||
|
.tcg_features = TCG_KVM_FEATURES,
|
||||||
},
|
},
|
||||||
[FEAT_SVM] = {
|
[FEAT_SVM] = {
|
||||||
.feat_names = svm_feature_name,
|
.feat_names = svm_feature_name,
|
||||||
.cpuid_eax = 0x8000000A, .cpuid_reg = R_EDX,
|
.cpuid_eax = 0x8000000A, .cpuid_reg = R_EDX,
|
||||||
|
.tcg_features = TCG_SVM_FEATURES,
|
||||||
},
|
},
|
||||||
[FEAT_7_0_EBX] = {
|
[FEAT_7_0_EBX] = {
|
||||||
.feat_names = cpuid_7_0_ebx_feature_name,
|
.feat_names = cpuid_7_0_ebx_feature_name,
|
||||||
.cpuid_eax = 7,
|
.cpuid_eax = 7,
|
||||||
.cpuid_needs_ecx = true, .cpuid_ecx = 0,
|
.cpuid_needs_ecx = true, .cpuid_ecx = 0,
|
||||||
.cpuid_reg = R_EBX,
|
.cpuid_reg = R_EBX,
|
||||||
|
.tcg_features = TCG_7_0_EBX_FEATURES,
|
||||||
|
},
|
||||||
|
[FEAT_8000_0007_EDX] = {
|
||||||
|
.feat_names = cpuid_apm_edx_feature_name,
|
||||||
|
.cpuid_eax = 0x80000007,
|
||||||
|
.cpuid_reg = R_EDX,
|
||||||
|
.tcg_features = TCG_APM_FEATURES,
|
||||||
|
.unmigratable_flags = CPUID_APM_INVTSC,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -373,11 +458,42 @@ static uint32_t kvm_default_features[FEATURE_WORDS] = {
|
|||||||
[FEAT_1_ECX] = CPUID_EXT_X2APIC,
|
[FEAT_1_ECX] = CPUID_EXT_X2APIC,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Features that are not added by default to any CPU model when KVM is enabled.
|
||||||
|
*/
|
||||||
|
static uint32_t kvm_default_unset_features[FEATURE_WORDS] = {
|
||||||
|
[FEAT_1_ECX] = CPUID_EXT_MONITOR,
|
||||||
|
};
|
||||||
|
|
||||||
void x86_cpu_compat_disable_kvm_features(FeatureWord w, uint32_t features)
|
void x86_cpu_compat_disable_kvm_features(FeatureWord w, uint32_t features)
|
||||||
{
|
{
|
||||||
kvm_default_features[w] &= ~features;
|
kvm_default_features[w] &= ~features;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns the set of feature flags that are supported and migratable by
|
||||||
|
* QEMU, for a given FeatureWord.
|
||||||
|
*/
|
||||||
|
static uint32_t x86_cpu_get_migratable_flags(FeatureWord w)
|
||||||
|
{
|
||||||
|
FeatureWordInfo *wi = &feature_word_info[w];
|
||||||
|
uint32_t r = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < 32; i++) {
|
||||||
|
uint32_t f = 1U << i;
|
||||||
|
/* If the feature name is unknown, it is not supported by QEMU yet */
|
||||||
|
if (!wi->feat_names[i]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* Skip features known to QEMU, but explicitly marked as unmigratable */
|
||||||
|
if (wi->unmigratable_flags & f) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
r |= f;
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
void host_cpuid(uint32_t function, uint32_t count,
|
void host_cpuid(uint32_t function, uint32_t count,
|
||||||
uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
|
uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
|
||||||
{
|
{
|
||||||
@ -534,51 +650,6 @@ struct X86CPUDefinition {
|
|||||||
bool cache_info_passthrough;
|
bool cache_info_passthrough;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define I486_FEATURES (CPUID_FP87 | CPUID_VME | CPUID_PSE)
|
|
||||||
#define PENTIUM_FEATURES (I486_FEATURES | CPUID_DE | CPUID_TSC | \
|
|
||||||
CPUID_MSR | CPUID_MCE | CPUID_CX8 | CPUID_MMX | CPUID_APIC)
|
|
||||||
#define PENTIUM2_FEATURES (PENTIUM_FEATURES | CPUID_PAE | CPUID_SEP | \
|
|
||||||
CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_CMOV | CPUID_PAT | \
|
|
||||||
CPUID_PSE36 | CPUID_FXSR)
|
|
||||||
#define PENTIUM3_FEATURES (PENTIUM2_FEATURES | CPUID_SSE)
|
|
||||||
#define PPRO_FEATURES (CPUID_FP87 | CPUID_DE | CPUID_PSE | CPUID_TSC | \
|
|
||||||
CPUID_MSR | CPUID_MCE | CPUID_CX8 | CPUID_PGE | CPUID_CMOV | \
|
|
||||||
CPUID_PAT | CPUID_FXSR | CPUID_MMX | CPUID_SSE | CPUID_SSE2 | \
|
|
||||||
CPUID_PAE | CPUID_SEP | CPUID_APIC)
|
|
||||||
|
|
||||||
#define TCG_FEATURES (CPUID_FP87 | CPUID_PSE | CPUID_TSC | CPUID_MSR | \
|
|
||||||
CPUID_PAE | CPUID_MCE | CPUID_CX8 | CPUID_APIC | CPUID_SEP | \
|
|
||||||
CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_CMOV | CPUID_PAT | \
|
|
||||||
CPUID_PSE36 | CPUID_CLFLUSH | CPUID_ACPI | CPUID_MMX | \
|
|
||||||
CPUID_FXSR | CPUID_SSE | CPUID_SSE2 | CPUID_SS)
|
|
||||||
/* partly implemented:
|
|
||||||
CPUID_MTRR, CPUID_MCA, CPUID_CLFLUSH (needed for Win64) */
|
|
||||||
/* missing:
|
|
||||||
CPUID_VME, CPUID_DTS, CPUID_SS, CPUID_HT, CPUID_TM, CPUID_PBE */
|
|
||||||
#define TCG_EXT_FEATURES (CPUID_EXT_SSE3 | CPUID_EXT_PCLMULQDQ | \
|
|
||||||
CPUID_EXT_MONITOR | CPUID_EXT_SSSE3 | CPUID_EXT_CX16 | \
|
|
||||||
CPUID_EXT_SSE41 | CPUID_EXT_SSE42 | CPUID_EXT_POPCNT | \
|
|
||||||
CPUID_EXT_MOVBE | CPUID_EXT_AES | CPUID_EXT_HYPERVISOR)
|
|
||||||
/* missing:
|
|
||||||
CPUID_EXT_DTES64, CPUID_EXT_DSCPL, CPUID_EXT_VMX, CPUID_EXT_SMX,
|
|
||||||
CPUID_EXT_EST, CPUID_EXT_TM2, CPUID_EXT_CID, CPUID_EXT_FMA,
|
|
||||||
CPUID_EXT_XTPR, CPUID_EXT_PDCM, CPUID_EXT_PCID, CPUID_EXT_DCA,
|
|
||||||
CPUID_EXT_X2APIC, CPUID_EXT_TSC_DEADLINE_TIMER, CPUID_EXT_XSAVE,
|
|
||||||
CPUID_EXT_OSXSAVE, CPUID_EXT_AVX, CPUID_EXT_F16C,
|
|
||||||
CPUID_EXT_RDRAND */
|
|
||||||
#define TCG_EXT2_FEATURES ((TCG_FEATURES & CPUID_EXT2_AMD_ALIASES) | \
|
|
||||||
CPUID_EXT2_NX | CPUID_EXT2_MMXEXT | CPUID_EXT2_RDTSCP | \
|
|
||||||
CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT | CPUID_EXT2_PDPE1GB)
|
|
||||||
#define TCG_EXT3_FEATURES (CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM | \
|
|
||||||
CPUID_EXT3_CR8LEG | CPUID_EXT3_ABM | CPUID_EXT3_SSE4A)
|
|
||||||
#define TCG_SVM_FEATURES 0
|
|
||||||
#define TCG_7_0_EBX_FEATURES (CPUID_7_0_EBX_SMEP | CPUID_7_0_EBX_SMAP \
|
|
||||||
CPUID_7_0_EBX_BMI1 | CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ADX)
|
|
||||||
/* missing:
|
|
||||||
CPUID_7_0_EBX_FSGSBASE, CPUID_7_0_EBX_HLE, CPUID_7_0_EBX_AVX2,
|
|
||||||
CPUID_7_0_EBX_ERMS, CPUID_7_0_EBX_INVPCID, CPUID_7_0_EBX_RTM,
|
|
||||||
CPUID_7_0_EBX_RDSEED */
|
|
||||||
|
|
||||||
static X86CPUDefinition builtin_x86_defs[] = {
|
static X86CPUDefinition builtin_x86_defs[] = {
|
||||||
{
|
{
|
||||||
.name = "qemu64",
|
.name = "qemu64",
|
||||||
@ -970,6 +1041,40 @@ static X86CPUDefinition builtin_x86_defs[] = {
|
|||||||
.xlevel = 0x8000000A,
|
.xlevel = 0x8000000A,
|
||||||
.model_id = "Intel Core Processor (Haswell)",
|
.model_id = "Intel Core Processor (Haswell)",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.name = "Broadwell",
|
||||||
|
.level = 0xd,
|
||||||
|
.vendor = CPUID_VENDOR_INTEL,
|
||||||
|
.family = 6,
|
||||||
|
.model = 61,
|
||||||
|
.stepping = 2,
|
||||||
|
.features[FEAT_1_EDX] =
|
||||||
|
CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX |
|
||||||
|
CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA |
|
||||||
|
CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 |
|
||||||
|
CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE |
|
||||||
|
CPUID_DE | CPUID_FP87,
|
||||||
|
.features[FEAT_1_ECX] =
|
||||||
|
CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES |
|
||||||
|
CPUID_EXT_POPCNT | CPUID_EXT_X2APIC | CPUID_EXT_SSE42 |
|
||||||
|
CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 |
|
||||||
|
CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3 |
|
||||||
|
CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_FMA | CPUID_EXT_MOVBE |
|
||||||
|
CPUID_EXT_PCID,
|
||||||
|
.features[FEAT_8000_0001_EDX] =
|
||||||
|
CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX |
|
||||||
|
CPUID_EXT2_SYSCALL,
|
||||||
|
.features[FEAT_8000_0001_ECX] =
|
||||||
|
CPUID_EXT3_LAHF_LM | CPUID_EXT3_3DNOWPREFETCH,
|
||||||
|
.features[FEAT_7_0_EBX] =
|
||||||
|
CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 |
|
||||||
|
CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP |
|
||||||
|
CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID |
|
||||||
|
CPUID_7_0_EBX_RTM | CPUID_7_0_EBX_RDSEED | CPUID_7_0_EBX_ADX |
|
||||||
|
CPUID_7_0_EBX_SMAP,
|
||||||
|
.xlevel = 0x8000000A,
|
||||||
|
.model_id = "Intel Core Processor (Broadwell)",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.name = "Opteron_G1",
|
.name = "Opteron_G1",
|
||||||
.level = 5,
|
.level = 5,
|
||||||
@ -1168,12 +1273,18 @@ static int cpu_x86_fill_model_id(char *str)
|
|||||||
|
|
||||||
static X86CPUDefinition host_cpudef;
|
static X86CPUDefinition host_cpudef;
|
||||||
|
|
||||||
|
static Property host_x86_cpu_properties[] = {
|
||||||
|
DEFINE_PROP_BOOL("migratable", X86CPU, migratable, true),
|
||||||
|
DEFINE_PROP_END_OF_LIST()
|
||||||
|
};
|
||||||
|
|
||||||
/* class_init for the "host" CPU model
|
/* class_init for the "host" CPU model
|
||||||
*
|
*
|
||||||
* This function may be called before KVM is initialized.
|
* This function may be called before KVM is initialized.
|
||||||
*/
|
*/
|
||||||
static void host_x86_cpu_class_init(ObjectClass *oc, void *data)
|
static void host_x86_cpu_class_init(ObjectClass *oc, void *data)
|
||||||
{
|
{
|
||||||
|
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||||
X86CPUClass *xcc = X86_CPU_CLASS(oc);
|
X86CPUClass *xcc = X86_CPU_CLASS(oc);
|
||||||
uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
|
uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
|
||||||
|
|
||||||
@ -1195,8 +1306,13 @@ static void host_x86_cpu_class_init(ObjectClass *oc, void *data)
|
|||||||
/* level, xlevel, xlevel2, and the feature words are initialized on
|
/* level, xlevel, xlevel2, and the feature words are initialized on
|
||||||
* instance_init, because they require KVM to be initialized.
|
* instance_init, because they require KVM to be initialized.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
dc->props = host_x86_cpu_properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t x86_cpu_get_supported_feature_word(FeatureWord w,
|
||||||
|
bool migratable_only);
|
||||||
|
|
||||||
static void host_x86_cpu_initfn(Object *obj)
|
static void host_x86_cpu_initfn(Object *obj)
|
||||||
{
|
{
|
||||||
X86CPU *cpu = X86_CPU(obj);
|
X86CPU *cpu = X86_CPU(obj);
|
||||||
@ -1211,10 +1327,8 @@ static void host_x86_cpu_initfn(Object *obj)
|
|||||||
env->cpuid_xlevel2 = kvm_arch_get_supported_cpuid(s, 0xC0000000, 0, R_EAX);
|
env->cpuid_xlevel2 = kvm_arch_get_supported_cpuid(s, 0xC0000000, 0, R_EAX);
|
||||||
|
|
||||||
for (w = 0; w < FEATURE_WORDS; w++) {
|
for (w = 0; w < FEATURE_WORDS; w++) {
|
||||||
FeatureWordInfo *wi = &feature_word_info[w];
|
|
||||||
env->features[w] =
|
env->features[w] =
|
||||||
kvm_arch_get_supported_cpuid(s, wi->cpuid_eax, wi->cpuid_ecx,
|
x86_cpu_get_supported_feature_word(w, cpu->migratable);
|
||||||
wi->cpuid_reg);
|
|
||||||
}
|
}
|
||||||
object_property_set_bool(OBJECT(cpu), true, "pmu", &error_abort);
|
object_property_set_bool(OBJECT(cpu), true, "pmu", &error_abort);
|
||||||
}
|
}
|
||||||
@ -1228,53 +1342,23 @@ static const TypeInfo host_x86_cpu_type_info = {
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int unavailable_host_feature(FeatureWordInfo *f, uint32_t mask)
|
static void report_unavailable_features(FeatureWord w, uint32_t mask)
|
||||||
{
|
{
|
||||||
|
FeatureWordInfo *f = &feature_word_info[w];
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < 32; ++i)
|
for (i = 0; i < 32; ++i) {
|
||||||
if (1 << i & mask) {
|
if (1 << i & mask) {
|
||||||
const char *reg = get_register_name_32(f->cpuid_reg);
|
const char *reg = get_register_name_32(f->cpuid_reg);
|
||||||
assert(reg);
|
assert(reg);
|
||||||
fprintf(stderr, "warning: host doesn't support requested feature: "
|
fprintf(stderr, "warning: %s doesn't support requested feature: "
|
||||||
"CPUID.%02XH:%s%s%s [bit %d]\n",
|
"CPUID.%02XH:%s%s%s [bit %d]\n",
|
||||||
|
kvm_enabled() ? "host" : "TCG",
|
||||||
f->cpuid_eax, reg,
|
f->cpuid_eax, reg,
|
||||||
f->feat_names[i] ? "." : "",
|
f->feat_names[i] ? "." : "",
|
||||||
f->feat_names[i] ? f->feat_names[i] : "", i);
|
f->feat_names[i] ? f->feat_names[i] : "", i);
|
||||||
break;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if all requested cpu flags are making their way to the guest
|
|
||||||
*
|
|
||||||
* Returns 0 if all flags are supported by the host, non-zero otherwise.
|
|
||||||
*
|
|
||||||
* This function may be called only if KVM is enabled.
|
|
||||||
*/
|
|
||||||
static int kvm_check_features_against_host(KVMState *s, X86CPU *cpu)
|
|
||||||
{
|
|
||||||
CPUX86State *env = &cpu->env;
|
|
||||||
int rv = 0;
|
|
||||||
FeatureWord w;
|
|
||||||
|
|
||||||
assert(kvm_enabled());
|
|
||||||
|
|
||||||
for (w = 0; w < FEATURE_WORDS; w++) {
|
|
||||||
FeatureWordInfo *wi = &feature_word_info[w];
|
|
||||||
uint32_t guest_feat = env->features[w];
|
|
||||||
uint32_t host_feat = kvm_arch_get_supported_cpuid(s, wi->cpuid_eax,
|
|
||||||
wi->cpuid_ecx,
|
|
||||||
wi->cpuid_reg);
|
|
||||||
uint32_t mask;
|
|
||||||
for (mask = 1; mask; mask <<= 1) {
|
|
||||||
if (guest_feat & mask && !(host_feat & mask)) {
|
|
||||||
unavailable_host_feature(wi, mask);
|
|
||||||
rv = 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return rv;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void x86_cpuid_version_get_family(Object *obj, Visitor *v, void *opaque,
|
static void x86_cpuid_version_get_family(Object *obj, Visitor *v, void *opaque,
|
||||||
@ -1663,6 +1747,7 @@ static void x86_cpu_parse_featurestr(CPUState *cs, char *features,
|
|||||||
{
|
{
|
||||||
X86CPU *cpu = X86_CPU(cs);
|
X86CPU *cpu = X86_CPU(cs);
|
||||||
char *featurestr; /* Single 'key=value" string being parsed */
|
char *featurestr; /* Single 'key=value" string being parsed */
|
||||||
|
FeatureWord w;
|
||||||
/* Features to be added */
|
/* Features to be added */
|
||||||
FeatureWordArray plus_features = { 0 };
|
FeatureWordArray plus_features = { 0 };
|
||||||
/* Features to be removed */
|
/* Features to be removed */
|
||||||
@ -1742,22 +1827,11 @@ static void x86_cpu_parse_featurestr(CPUState *cs, char *features,
|
|||||||
}
|
}
|
||||||
featurestr = strtok(NULL, ",");
|
featurestr = strtok(NULL, ",");
|
||||||
}
|
}
|
||||||
env->features[FEAT_1_EDX] |= plus_features[FEAT_1_EDX];
|
|
||||||
env->features[FEAT_1_ECX] |= plus_features[FEAT_1_ECX];
|
for (w = 0; w < FEATURE_WORDS; w++) {
|
||||||
env->features[FEAT_8000_0001_EDX] |= plus_features[FEAT_8000_0001_EDX];
|
env->features[w] |= plus_features[w];
|
||||||
env->features[FEAT_8000_0001_ECX] |= plus_features[FEAT_8000_0001_ECX];
|
env->features[w] &= ~minus_features[w];
|
||||||
env->features[FEAT_C000_0001_EDX] |= plus_features[FEAT_C000_0001_EDX];
|
}
|
||||||
env->features[FEAT_KVM] |= plus_features[FEAT_KVM];
|
|
||||||
env->features[FEAT_SVM] |= plus_features[FEAT_SVM];
|
|
||||||
env->features[FEAT_7_0_EBX] |= plus_features[FEAT_7_0_EBX];
|
|
||||||
env->features[FEAT_1_EDX] &= ~minus_features[FEAT_1_EDX];
|
|
||||||
env->features[FEAT_1_ECX] &= ~minus_features[FEAT_1_ECX];
|
|
||||||
env->features[FEAT_8000_0001_EDX] &= ~minus_features[FEAT_8000_0001_EDX];
|
|
||||||
env->features[FEAT_8000_0001_ECX] &= ~minus_features[FEAT_8000_0001_ECX];
|
|
||||||
env->features[FEAT_C000_0001_EDX] &= ~minus_features[FEAT_C000_0001_EDX];
|
|
||||||
env->features[FEAT_KVM] &= ~minus_features[FEAT_KVM];
|
|
||||||
env->features[FEAT_SVM] &= ~minus_features[FEAT_SVM];
|
|
||||||
env->features[FEAT_7_0_EBX] &= ~minus_features[FEAT_7_0_EBX];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* generate a composite string into buf of all cpuid names in featureset
|
/* generate a composite string into buf of all cpuid names in featureset
|
||||||
@ -1840,21 +1914,53 @@ CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp)
|
|||||||
return cpu_list;
|
return cpu_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void filter_features_for_kvm(X86CPU *cpu)
|
static uint32_t x86_cpu_get_supported_feature_word(FeatureWord w,
|
||||||
|
bool migratable_only)
|
||||||
{
|
{
|
||||||
CPUX86State *env = &cpu->env;
|
|
||||||
KVMState *s = kvm_state;
|
|
||||||
FeatureWord w;
|
|
||||||
|
|
||||||
for (w = 0; w < FEATURE_WORDS; w++) {
|
|
||||||
FeatureWordInfo *wi = &feature_word_info[w];
|
FeatureWordInfo *wi = &feature_word_info[w];
|
||||||
uint32_t host_feat = kvm_arch_get_supported_cpuid(s, wi->cpuid_eax,
|
uint32_t r;
|
||||||
|
|
||||||
|
if (kvm_enabled()) {
|
||||||
|
r = kvm_arch_get_supported_cpuid(kvm_state, wi->cpuid_eax,
|
||||||
wi->cpuid_ecx,
|
wi->cpuid_ecx,
|
||||||
wi->cpuid_reg);
|
wi->cpuid_reg);
|
||||||
|
} else if (tcg_enabled()) {
|
||||||
|
r = wi->tcg_features;
|
||||||
|
} else {
|
||||||
|
return ~0;
|
||||||
|
}
|
||||||
|
if (migratable_only) {
|
||||||
|
r &= x86_cpu_get_migratable_flags(w);
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Filters CPU feature words based on host availability of each feature.
|
||||||
|
*
|
||||||
|
* Returns: 0 if all flags are supported by the host, non-zero otherwise.
|
||||||
|
*/
|
||||||
|
static int x86_cpu_filter_features(X86CPU *cpu)
|
||||||
|
{
|
||||||
|
CPUX86State *env = &cpu->env;
|
||||||
|
FeatureWord w;
|
||||||
|
int rv = 0;
|
||||||
|
|
||||||
|
for (w = 0; w < FEATURE_WORDS; w++) {
|
||||||
|
uint32_t host_feat =
|
||||||
|
x86_cpu_get_supported_feature_word(w, cpu->migratable);
|
||||||
uint32_t requested_features = env->features[w];
|
uint32_t requested_features = env->features[w];
|
||||||
env->features[w] &= host_feat;
|
env->features[w] &= host_feat;
|
||||||
cpu->filtered_features[w] = requested_features & ~env->features[w];
|
cpu->filtered_features[w] = requested_features & ~env->features[w];
|
||||||
|
if (cpu->filtered_features[w]) {
|
||||||
|
if (cpu->check_cpuid || cpu->enforce_cpuid) {
|
||||||
|
report_unavailable_features(w, cpu->filtered_features[w]);
|
||||||
}
|
}
|
||||||
|
rv = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Load data from X86CPUDefinition
|
/* Load data from X86CPUDefinition
|
||||||
@ -1864,30 +1970,26 @@ static void x86_cpu_load_def(X86CPU *cpu, X86CPUDefinition *def, Error **errp)
|
|||||||
CPUX86State *env = &cpu->env;
|
CPUX86State *env = &cpu->env;
|
||||||
const char *vendor;
|
const char *vendor;
|
||||||
char host_vendor[CPUID_VENDOR_SZ + 1];
|
char host_vendor[CPUID_VENDOR_SZ + 1];
|
||||||
|
FeatureWord w;
|
||||||
|
|
||||||
object_property_set_int(OBJECT(cpu), def->level, "level", errp);
|
object_property_set_int(OBJECT(cpu), def->level, "level", errp);
|
||||||
object_property_set_int(OBJECT(cpu), def->family, "family", errp);
|
object_property_set_int(OBJECT(cpu), def->family, "family", errp);
|
||||||
object_property_set_int(OBJECT(cpu), def->model, "model", errp);
|
object_property_set_int(OBJECT(cpu), def->model, "model", errp);
|
||||||
object_property_set_int(OBJECT(cpu), def->stepping, "stepping", errp);
|
object_property_set_int(OBJECT(cpu), def->stepping, "stepping", errp);
|
||||||
env->features[FEAT_1_EDX] = def->features[FEAT_1_EDX];
|
|
||||||
env->features[FEAT_1_ECX] = def->features[FEAT_1_ECX];
|
|
||||||
env->features[FEAT_8000_0001_EDX] = def->features[FEAT_8000_0001_EDX];
|
|
||||||
env->features[FEAT_8000_0001_ECX] = def->features[FEAT_8000_0001_ECX];
|
|
||||||
object_property_set_int(OBJECT(cpu), def->xlevel, "xlevel", errp);
|
object_property_set_int(OBJECT(cpu), def->xlevel, "xlevel", errp);
|
||||||
env->features[FEAT_KVM] = def->features[FEAT_KVM];
|
|
||||||
env->features[FEAT_SVM] = def->features[FEAT_SVM];
|
|
||||||
env->features[FEAT_C000_0001_EDX] = def->features[FEAT_C000_0001_EDX];
|
|
||||||
env->features[FEAT_7_0_EBX] = def->features[FEAT_7_0_EBX];
|
|
||||||
env->cpuid_xlevel2 = def->xlevel2;
|
env->cpuid_xlevel2 = def->xlevel2;
|
||||||
cpu->cache_info_passthrough = def->cache_info_passthrough;
|
cpu->cache_info_passthrough = def->cache_info_passthrough;
|
||||||
|
|
||||||
object_property_set_str(OBJECT(cpu), def->model_id, "model-id", errp);
|
object_property_set_str(OBJECT(cpu), def->model_id, "model-id", errp);
|
||||||
|
for (w = 0; w < FEATURE_WORDS; w++) {
|
||||||
|
env->features[w] = def->features[w];
|
||||||
|
}
|
||||||
|
|
||||||
/* Special cases not set in the X86CPUDefinition structs: */
|
/* Special cases not set in the X86CPUDefinition structs: */
|
||||||
if (kvm_enabled()) {
|
if (kvm_enabled()) {
|
||||||
FeatureWord w;
|
FeatureWord w;
|
||||||
for (w = 0; w < FEATURE_WORDS; w++) {
|
for (w = 0; w < FEATURE_WORDS; w++) {
|
||||||
env->features[w] |= kvm_default_features[w];
|
env->features[w] |= kvm_default_features[w];
|
||||||
|
env->features[w] &= ~kvm_default_unset_features[w];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2336,6 +2438,12 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
|
|||||||
(AMD_ENC_ASSOC(L3_ASSOCIATIVITY) << 12) | \
|
(AMD_ENC_ASSOC(L3_ASSOCIATIVITY) << 12) | \
|
||||||
(L3_LINES_PER_TAG << 8) | (L3_LINE_SIZE);
|
(L3_LINES_PER_TAG << 8) | (L3_LINE_SIZE);
|
||||||
break;
|
break;
|
||||||
|
case 0x80000007:
|
||||||
|
*eax = 0;
|
||||||
|
*ebx = 0;
|
||||||
|
*ecx = 0;
|
||||||
|
*edx = env->features[FEAT_8000_0007_EDX];
|
||||||
|
break;
|
||||||
case 0x80000008:
|
case 0x80000008:
|
||||||
/* virtual & phys address size in low 2 bytes. */
|
/* virtual & phys address size in low 2 bytes. */
|
||||||
/* XXX: This value must match the one used in the MMU code. */
|
/* XXX: This value must match the one used in the MMU code. */
|
||||||
@ -2593,26 +2701,14 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
|
|||||||
& CPUID_EXT2_AMD_ALIASES);
|
& CPUID_EXT2_AMD_ALIASES);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!kvm_enabled()) {
|
|
||||||
env->features[FEAT_1_EDX] &= TCG_FEATURES;
|
if (x86_cpu_filter_features(cpu) && cpu->enforce_cpuid) {
|
||||||
env->features[FEAT_1_ECX] &= TCG_EXT_FEATURES;
|
|
||||||
env->features[FEAT_8000_0001_EDX] &= (TCG_EXT2_FEATURES
|
|
||||||
#ifdef TARGET_X86_64
|
|
||||||
| CPUID_EXT2_SYSCALL | CPUID_EXT2_LM
|
|
||||||
#endif
|
|
||||||
);
|
|
||||||
env->features[FEAT_8000_0001_ECX] &= TCG_EXT3_FEATURES;
|
|
||||||
env->features[FEAT_SVM] &= TCG_SVM_FEATURES;
|
|
||||||
} else {
|
|
||||||
KVMState *s = kvm_state;
|
|
||||||
if ((cpu->check_cpuid || cpu->enforce_cpuid)
|
|
||||||
&& kvm_check_features_against_host(s, cpu) && cpu->enforce_cpuid) {
|
|
||||||
error_setg(&local_err,
|
error_setg(&local_err,
|
||||||
"Host's CPU doesn't support requested features");
|
kvm_enabled() ?
|
||||||
|
"Host doesn't support requested features" :
|
||||||
|
"TCG doesn't support requested features");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
filter_features_for_kvm(cpu);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef CONFIG_USER_ONLY
|
#ifndef CONFIG_USER_ONLY
|
||||||
qemu_register_reset(x86_cpu_machine_reset_cb, cpu);
|
qemu_register_reset(x86_cpu_machine_reset_cb, cpu);
|
||||||
|
@ -402,6 +402,7 @@ typedef enum FeatureWord {
|
|||||||
FEAT_7_0_EBX, /* CPUID[EAX=7,ECX=0].EBX */
|
FEAT_7_0_EBX, /* CPUID[EAX=7,ECX=0].EBX */
|
||||||
FEAT_8000_0001_EDX, /* CPUID[8000_0001].EDX */
|
FEAT_8000_0001_EDX, /* CPUID[8000_0001].EDX */
|
||||||
FEAT_8000_0001_ECX, /* CPUID[8000_0001].ECX */
|
FEAT_8000_0001_ECX, /* CPUID[8000_0001].ECX */
|
||||||
|
FEAT_8000_0007_EDX, /* CPUID[8000_0007].EDX */
|
||||||
FEAT_C000_0001_EDX, /* CPUID[C000_0001].EDX */
|
FEAT_C000_0001_EDX, /* CPUID[C000_0001].EDX */
|
||||||
FEAT_KVM, /* CPUID[4000_0001].EAX (KVM_CPUID_FEATURES) */
|
FEAT_KVM, /* CPUID[4000_0001].EAX (KVM_CPUID_FEATURES) */
|
||||||
FEAT_SVM, /* CPUID[8000_000A].EDX */
|
FEAT_SVM, /* CPUID[8000_000A].EDX */
|
||||||
@ -561,6 +562,9 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS];
|
|||||||
#define CPUID_7_0_EBX_ADX (1U << 19)
|
#define CPUID_7_0_EBX_ADX (1U << 19)
|
||||||
#define CPUID_7_0_EBX_SMAP (1U << 20)
|
#define CPUID_7_0_EBX_SMAP (1U << 20)
|
||||||
|
|
||||||
|
/* CPUID[0x80000007].EDX flags: */
|
||||||
|
#define CPUID_APM_INVTSC (1U << 8)
|
||||||
|
|
||||||
#define CPUID_VENDOR_SZ 12
|
#define CPUID_VENDOR_SZ 12
|
||||||
|
|
||||||
#define CPUID_VENDOR_INTEL_1 0x756e6547 /* "Genu" */
|
#define CPUID_VENDOR_INTEL_1 0x756e6547 /* "Genu" */
|
||||||
|
@ -35,6 +35,8 @@
|
|||||||
#include "exec/ioport.h"
|
#include "exec/ioport.h"
|
||||||
#include <asm/hyperv.h>
|
#include <asm/hyperv.h>
|
||||||
#include "hw/pci/pci.h"
|
#include "hw/pci/pci.h"
|
||||||
|
#include "migration/migration.h"
|
||||||
|
#include "qapi/qmp/qerror.h"
|
||||||
|
|
||||||
//#define DEBUG_KVM
|
//#define DEBUG_KVM
|
||||||
|
|
||||||
@ -448,6 +450,8 @@ static bool hyperv_enabled(X86CPU *cpu)
|
|||||||
cpu->hyperv_relaxed_timing);
|
cpu->hyperv_relaxed_timing);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Error *invtsc_mig_blocker;
|
||||||
|
|
||||||
#define KVM_MAX_CPUID_ENTRIES 100
|
#define KVM_MAX_CPUID_ENTRIES 100
|
||||||
|
|
||||||
int kvm_arch_init_vcpu(CPUState *cs)
|
int kvm_arch_init_vcpu(CPUState *cs)
|
||||||
@ -705,6 +709,17 @@ int kvm_arch_init_vcpu(CPUState *cs)
|
|||||||
!!(c->ecx & CPUID_EXT_SMX);
|
!!(c->ecx & CPUID_EXT_SMX);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c = cpuid_find_entry(&cpuid_data.cpuid, 0x80000007, 0);
|
||||||
|
if (c && (c->edx & 1<<8) && invtsc_mig_blocker == NULL) {
|
||||||
|
/* for migration */
|
||||||
|
error_setg(&invtsc_mig_blocker,
|
||||||
|
"State blocked by non-migratable CPU device"
|
||||||
|
" (invtsc flag)");
|
||||||
|
migrate_add_blocker(invtsc_mig_blocker);
|
||||||
|
/* for savevm */
|
||||||
|
vmstate_x86_cpu.unmigratable = 1;
|
||||||
|
}
|
||||||
|
|
||||||
cpuid_data.cpuid.padding = 0;
|
cpuid_data.cpuid.padding = 0;
|
||||||
r = kvm_vcpu_ioctl(cs, KVM_SET_CPUID2, &cpuid_data);
|
r = kvm_vcpu_ioctl(cs, KVM_SET_CPUID2, &cpuid_data);
|
||||||
if (r) {
|
if (r) {
|
||||||
|
@ -603,7 +603,7 @@ static const VMStateDescription vmstate_msr_hyperv_time = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const VMStateDescription vmstate_x86_cpu = {
|
VMStateDescription vmstate_x86_cpu = {
|
||||||
.name = "cpu",
|
.name = "cpu",
|
||||||
.version_id = 12,
|
.version_id = 12,
|
||||||
.minimum_version_id = 3,
|
.minimum_version_id = 3,
|
||||||
|
Loading…
Reference in New Issue
Block a user