111 lines
4.3 KiB
Diff
111 lines
4.3 KiB
Diff
Subject: [PATCH] cpu-misc: (CPU model plumbing)
|
|
|
|
Targets VMAware check: (CPU model plumbing)
|
|
|
|
CPU feature-word plumbing and an upstream backport; not aimed at a check.
|
|
|
|
Applies to QEMU v11.1.1. Apply from the source root with:
|
|
patch -p1 < 08-cpu-misc.patch
|
|
|
|
---
|
|
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
|
|
index 5805d33..1b0203e 100644
|
|
--- a/target/i386/cpu.c
|
|
+++ b/target/i386/cpu.c
|
|
@@ -1009,6 +1009,7 @@ void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1,
|
|
#define TCG_7_2_EDX_FEATURES 0
|
|
#define TCG_APM_FEATURES 0
|
|
#define TCG_6_EAX_FEATURES CPUID_6_EAX_ARAT
|
|
+#define TCG_6_ECX_FEATURES 0
|
|
#define TCG_XSAVE_FEATURES (CPUID_XSAVE_XSAVEOPT | CPUID_XSAVE_XGETBV1)
|
|
/* missing:
|
|
CPUID_XSAVE_XSAVEC, CPUID_XSAVE_XSAVES */
|
|
@@ -1545,6 +1546,21 @@ FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
|
|
.cpuid = { .eax = 6, .reg = R_EAX, },
|
|
.tcg_features = TCG_6_EAX_FEATURES,
|
|
},
|
|
+ [FEAT_6_ECX] = {
|
|
+ .type = CPUID_FEATURE_WORD,
|
|
+ .feat_names = {
|
|
+ "aperfmperf", NULL, NULL, NULL,
|
|
+ NULL, NULL, NULL, NULL,
|
|
+ NULL, NULL, NULL, NULL,
|
|
+ NULL, NULL, NULL, NULL,
|
|
+ NULL, NULL, NULL, NULL,
|
|
+ NULL, NULL, NULL, NULL,
|
|
+ NULL, NULL, NULL, NULL,
|
|
+ NULL, NULL, NULL, NULL,
|
|
+ },
|
|
+ .cpuid = { .eax = 6, .reg = R_ECX, },
|
|
+ .tcg_features = TCG_6_ECX_FEATURES,
|
|
+ },
|
|
[FEAT_XSAVE_XCR0_LO] = {
|
|
.type = CPUID_FEATURE_WORD,
|
|
.cpuid = {
|
|
@@ -8778,7 +8794,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
|
|
/* Thermal and Power Leaf */
|
|
*eax = env->features[FEAT_6_EAX];
|
|
*ebx = 0;
|
|
- *ecx = 0;
|
|
+ *ecx = env->features[FEAT_6_ECX];
|
|
*edx = 0;
|
|
break;
|
|
case 7:
|
|
@@ -9809,6 +9825,7 @@ void x86_cpu_expand_features(X86CPU *cpu, Error **errp)
|
|
x86_cpu_adjust_feat_level(cpu, FEAT_1_EDX);
|
|
x86_cpu_adjust_feat_level(cpu, FEAT_1_ECX);
|
|
x86_cpu_adjust_feat_level(cpu, FEAT_6_EAX);
|
|
+ x86_cpu_adjust_feat_level(cpu, FEAT_6_ECX);
|
|
x86_cpu_adjust_feat_level(cpu, FEAT_7_0_ECX);
|
|
x86_cpu_adjust_feat_level(cpu, FEAT_7_1_EAX);
|
|
x86_cpu_adjust_feat_level(cpu, FEAT_7_1_ECX);
|
|
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
|
|
index e6a1976..2a6dbbf 100644
|
|
--- a/target/i386/cpu.h
|
|
+++ b/target/i386/cpu.h
|
|
@@ -700,6 +700,7 @@ typedef enum FeatureWord {
|
|
FEAT_SVM, /* CPUID[8000_000A].EDX */
|
|
FEAT_XSAVE, /* CPUID[EAX=0xd,ECX=1].EAX */
|
|
FEAT_6_EAX, /* CPUID[6].EAX */
|
|
+ FEAT_6_ECX, /* CPUID[6].ECX */
|
|
FEAT_XSAVE_XCR0_LO, /* CPUID[EAX=0xd,ECX=0].EAX */
|
|
FEAT_XSAVE_XCR0_HI, /* CPUID[EAX=0xd,ECX=0].EDX */
|
|
FEAT_ARCH_CAPABILITIES,
|
|
@@ -1232,6 +1233,7 @@ uint64_t x86_cpu_get_supported_feature_word(X86CPU *cpu, FeatureWord w);
|
|
#define CPUID_XSAVE_XFD (1U << 4)
|
|
|
|
#define CPUID_6_EAX_ARAT (1U << 2)
|
|
+#define CPUID_6_ECX_APERFMPERF (1U << 0)
|
|
|
|
/* CPUID[0x80000007].EDX flags: */
|
|
#define CPUID_APM_INVTSC (1U << 8)
|
|
diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
|
|
index 644c45f..6f6862e 100644
|
|
--- a/target/i386/kvm/kvm.c
|
|
+++ b/target/i386/kvm/kvm.c
|
|
@@ -499,6 +499,14 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function,
|
|
}
|
|
} else if (function == 6 && reg == R_EAX) {
|
|
ret |= CPUID_6_EAX_ARAT; /* safe to allow because of emulated APIC */
|
|
+ } else if (function == 6 && reg == R_ECX) {
|
|
+ if (enable_cpu_pm) {
|
|
+ int disable_exits = kvm_check_extension(s,
|
|
+ KVM_CAP_X86_DISABLE_EXITS);
|
|
+ if (disable_exits & KVM_X86_DISABLE_EXITS_APERFMPERF) {
|
|
+ ret |= CPUID_6_ECX_APERFMPERF;
|
|
+ }
|
|
+ }
|
|
} else if (function == 7 && index == 0 && reg == R_EBX) {
|
|
/* Not new instructions, just an optimization. */
|
|
uint32_t ebx;
|
|
@@ -3292,7 +3300,8 @@ static int kvm_vm_enable_disable_exits(KVMState *s)
|
|
disable_exits &= (KVM_X86_DISABLE_EXITS_MWAIT |
|
|
KVM_X86_DISABLE_EXITS_HLT |
|
|
KVM_X86_DISABLE_EXITS_PAUSE |
|
|
- KVM_X86_DISABLE_EXITS_CSTATE);
|
|
+ KVM_X86_DISABLE_EXITS_CSTATE |
|
|
+ KVM_X86_DISABLE_EXITS_APERFMPERF);
|
|
}
|
|
|
|
return kvm_vm_enable_cap(s, KVM_CAP_X86_DISABLE_EXITS, 0,
|