]> git.proxmox.com Git - pve-qemu.git/blame - debian/patches/extra/0011-target-i386-do-not-consult-nonexistent-host-leaves.patch
cherry-pick upstream fixes for 7.0.0
[pve-qemu.git] / debian / patches / extra / 0011-target-i386-do-not-consult-nonexistent-host-leaves.patch
CommitLineData
14ed5546
FE
1From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2From: Paolo Bonzini <pbonzini@redhat.com>
3Date: Fri, 29 Apr 2022 21:16:28 +0200
4Subject: [PATCH] target/i386: do not consult nonexistent host leaves
5
6When cache_info_passthrough is requested, QEMU passes the host values
7of the cache information CPUID leaves down to the guest. However,
8it blindly assumes that the CPUID leaf exists on the host, and this
9cannot be guaranteed: for example, KVM has recently started to
10synthesize AMD leaves up to 0x80000021 in order to provide accurate
11CPU bug information to guests.
12
13Querying a nonexistent host leaf fills the output arguments of
14host_cpuid with data that (albeit deterministic) is nonsensical
15as cache information, namely the data in the highest Intel CPUID
16leaf. If said highest leaf is not ECX-dependent, this can even
17cause an infinite loop when kvm_arch_init_vcpu prepares the input
18to KVM_SET_CPUID2. The infinite loop is only terminated by an
19abort() when the array gets full.
20
21Reported-by: Maxim Levitsky <mlevitsk@redhat.com>
22Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
23Cc: qemu-stable@nongnu.org
24Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
25(cherry-picked from commit 798d8ec0dacd4cc0034298d94f430c14f23e2919)
26Signed-off-by: Fabian Ebner <f.ebner@proxmox.com>
27---
28 target/i386/cpu.c | 41 ++++++++++++++++++++++++++++++++++++-----
29 1 file changed, 36 insertions(+), 5 deletions(-)
30
31diff --git a/target/i386/cpu.c b/target/i386/cpu.c
32index 6e6945139b..c79e151887 100644
33--- a/target/i386/cpu.c
34+++ b/target/i386/cpu.c
35@@ -5030,6 +5030,37 @@ uint64_t x86_cpu_get_supported_feature_word(FeatureWord w,
36 return r;
37 }
38
39+static void x86_cpu_get_cache_cpuid(uint32_t func, uint32_t index,
40+ uint32_t *eax, uint32_t *ebx,
41+ uint32_t *ecx, uint32_t *edx)
42+{
43+ uint32_t level, unused;
44+
45+ /* Only return valid host leaves. */
46+ switch (func) {
47+ case 2:
48+ case 4:
49+ host_cpuid(0, 0, &level, &unused, &unused, &unused);
50+ break;
51+ case 0x80000005:
52+ case 0x80000006:
53+ case 0x8000001d:
54+ host_cpuid(0x80000000, 0, &level, &unused, &unused, &unused);
55+ break;
56+ default:
57+ return;
58+ }
59+
60+ if (func > level) {
61+ *eax = 0;
62+ *ebx = 0;
63+ *ecx = 0;
64+ *edx = 0;
65+ } else {
66+ host_cpuid(func, index, eax, ebx, ecx, edx);
67+ }
68+}
69+
70 /*
71 * Only for builtin_x86_defs models initialized with x86_register_cpudef_types.
72 */
73@@ -5288,7 +5319,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
74 case 2:
75 /* cache info: needed for Pentium Pro compatibility */
76 if (cpu->cache_info_passthrough) {
77- host_cpuid(index, 0, eax, ebx, ecx, edx);
78+ x86_cpu_get_cache_cpuid(index, 0, eax, ebx, ecx, edx);
79 break;
80 } else if (cpu->vendor_cpuid_only && IS_AMD_CPU(env)) {
81 *eax = *ebx = *ecx = *edx = 0;
82@@ -5308,7 +5339,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
83 case 4:
84 /* cache info: needed for Core compatibility */
85 if (cpu->cache_info_passthrough) {
86- host_cpuid(index, count, eax, ebx, ecx, edx);
87+ x86_cpu_get_cache_cpuid(index, count, eax, ebx, ecx, edx);
88 /* QEMU gives out its own APIC IDs, never pass down bits 31..26. */
89 *eax &= ~0xFC000000;
90 if ((*eax & 31) && cs->nr_cores > 1) {
91@@ -5710,7 +5741,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
92 case 0x80000005:
93 /* cache info (L1 cache) */
94 if (cpu->cache_info_passthrough) {
95- host_cpuid(index, 0, eax, ebx, ecx, edx);
96+ x86_cpu_get_cache_cpuid(index, 0, eax, ebx, ecx, edx);
97 break;
98 }
99 *eax = (L1_DTLB_2M_ASSOC << 24) | (L1_DTLB_2M_ENTRIES << 16) |
100@@ -5723,7 +5754,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
101 case 0x80000006:
102 /* cache info (L2 cache) */
103 if (cpu->cache_info_passthrough) {
104- host_cpuid(index, 0, eax, ebx, ecx, edx);
105+ x86_cpu_get_cache_cpuid(index, 0, eax, ebx, ecx, edx);
106 break;
107 }
108 *eax = (AMD_ENC_ASSOC(L2_DTLB_2M_ASSOC) << 28) |
109@@ -5783,7 +5814,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
110 case 0x8000001D:
111 *eax = 0;
112 if (cpu->cache_info_passthrough) {
113- host_cpuid(index, count, eax, ebx, ecx, edx);
114+ x86_cpu_get_cache_cpuid(index, count, eax, ebx, ecx, edx);
115 break;
116 }
117 switch (count) {