14ed554660
coming in via qemu-stable (except for the vdmk fix, which was tagged for-7.0 on the qemu-devel list, but didn't make it into the release). Also took the chance to switch the gluster fix to the version that made it into upstream. Signed-off-by: Fabian Ebner <f.ebner@proxmox.com> Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
118 lines
4.6 KiB
Diff
118 lines
4.6 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Paolo Bonzini <pbonzini@redhat.com>
|
|
Date: Fri, 29 Apr 2022 21:16:28 +0200
|
|
Subject: [PATCH] target/i386: do not consult nonexistent host leaves
|
|
|
|
When cache_info_passthrough is requested, QEMU passes the host values
|
|
of the cache information CPUID leaves down to the guest. However,
|
|
it blindly assumes that the CPUID leaf exists on the host, and this
|
|
cannot be guaranteed: for example, KVM has recently started to
|
|
synthesize AMD leaves up to 0x80000021 in order to provide accurate
|
|
CPU bug information to guests.
|
|
|
|
Querying a nonexistent host leaf fills the output arguments of
|
|
host_cpuid with data that (albeit deterministic) is nonsensical
|
|
as cache information, namely the data in the highest Intel CPUID
|
|
leaf. If said highest leaf is not ECX-dependent, this can even
|
|
cause an infinite loop when kvm_arch_init_vcpu prepares the input
|
|
to KVM_SET_CPUID2. The infinite loop is only terminated by an
|
|
abort() when the array gets full.
|
|
|
|
Reported-by: Maxim Levitsky <mlevitsk@redhat.com>
|
|
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
|
|
Cc: qemu-stable@nongnu.org
|
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
(cherry-picked from commit 798d8ec0dacd4cc0034298d94f430c14f23e2919)
|
|
Signed-off-by: Fabian Ebner <f.ebner@proxmox.com>
|
|
---
|
|
target/i386/cpu.c | 41 ++++++++++++++++++++++++++++++++++++-----
|
|
1 file changed, 36 insertions(+), 5 deletions(-)
|
|
|
|
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
|
|
index 6e6945139b..c79e151887 100644
|
|
--- a/target/i386/cpu.c
|
|
+++ b/target/i386/cpu.c
|
|
@@ -5030,6 +5030,37 @@ uint64_t x86_cpu_get_supported_feature_word(FeatureWord w,
|
|
return r;
|
|
}
|
|
|
|
+static void x86_cpu_get_cache_cpuid(uint32_t func, uint32_t index,
|
|
+ uint32_t *eax, uint32_t *ebx,
|
|
+ uint32_t *ecx, uint32_t *edx)
|
|
+{
|
|
+ uint32_t level, unused;
|
|
+
|
|
+ /* Only return valid host leaves. */
|
|
+ switch (func) {
|
|
+ case 2:
|
|
+ case 4:
|
|
+ host_cpuid(0, 0, &level, &unused, &unused, &unused);
|
|
+ break;
|
|
+ case 0x80000005:
|
|
+ case 0x80000006:
|
|
+ case 0x8000001d:
|
|
+ host_cpuid(0x80000000, 0, &level, &unused, &unused, &unused);
|
|
+ break;
|
|
+ default:
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ if (func > level) {
|
|
+ *eax = 0;
|
|
+ *ebx = 0;
|
|
+ *ecx = 0;
|
|
+ *edx = 0;
|
|
+ } else {
|
|
+ host_cpuid(func, index, eax, ebx, ecx, edx);
|
|
+ }
|
|
+}
|
|
+
|
|
/*
|
|
* Only for builtin_x86_defs models initialized with x86_register_cpudef_types.
|
|
*/
|
|
@@ -5288,7 +5319,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
|
|
case 2:
|
|
/* cache info: needed for Pentium Pro compatibility */
|
|
if (cpu->cache_info_passthrough) {
|
|
- host_cpuid(index, 0, eax, ebx, ecx, edx);
|
|
+ x86_cpu_get_cache_cpuid(index, 0, eax, ebx, ecx, edx);
|
|
break;
|
|
} else if (cpu->vendor_cpuid_only && IS_AMD_CPU(env)) {
|
|
*eax = *ebx = *ecx = *edx = 0;
|
|
@@ -5308,7 +5339,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
|
|
case 4:
|
|
/* cache info: needed for Core compatibility */
|
|
if (cpu->cache_info_passthrough) {
|
|
- host_cpuid(index, count, eax, ebx, ecx, edx);
|
|
+ x86_cpu_get_cache_cpuid(index, count, eax, ebx, ecx, edx);
|
|
/* QEMU gives out its own APIC IDs, never pass down bits 31..26. */
|
|
*eax &= ~0xFC000000;
|
|
if ((*eax & 31) && cs->nr_cores > 1) {
|
|
@@ -5710,7 +5741,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
|
|
case 0x80000005:
|
|
/* cache info (L1 cache) */
|
|
if (cpu->cache_info_passthrough) {
|
|
- host_cpuid(index, 0, eax, ebx, ecx, edx);
|
|
+ x86_cpu_get_cache_cpuid(index, 0, eax, ebx, ecx, edx);
|
|
break;
|
|
}
|
|
*eax = (L1_DTLB_2M_ASSOC << 24) | (L1_DTLB_2M_ENTRIES << 16) |
|
|
@@ -5723,7 +5754,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
|
|
case 0x80000006:
|
|
/* cache info (L2 cache) */
|
|
if (cpu->cache_info_passthrough) {
|
|
- host_cpuid(index, 0, eax, ebx, ecx, edx);
|
|
+ x86_cpu_get_cache_cpuid(index, 0, eax, ebx, ecx, edx);
|
|
break;
|
|
}
|
|
*eax = (AMD_ENC_ASSOC(L2_DTLB_2M_ASSOC) << 28) |
|
|
@@ -5783,7 +5814,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
|
|
case 0x8000001D:
|
|
*eax = 0;
|
|
if (cpu->cache_info_passthrough) {
|
|
- host_cpuid(index, count, eax, ebx, ecx, edx);
|
|
+ x86_cpu_get_cache_cpuid(index, count, eax, ebx, ecx, edx);
|
|
break;
|
|
}
|
|
switch (count) {
|