]>
Commit | Line | Data |
---|---|---|
321d628a FG |
1 | From 59011dc6f59cc32a499fb926d95dad0dabb75a8f Mon Sep 17 00:00:00 2001 |
2 | From: Juergen Gross <jgross@suse.com> | |
3 | Date: Thu, 9 Nov 2017 14:27:35 +0100 | |
633c5ed1 | 4 | Subject: [PATCH 118/242] x86/virt, x86/platform: Merge 'struct x86_hyper' into |
321d628a FG |
5 | 'struct x86_platform' and 'struct x86_init' |
6 | MIME-Version: 1.0 | |
7 | Content-Type: text/plain; charset=UTF-8 | |
8 | Content-Transfer-Encoding: 8bit | |
9 | ||
10 | CVE-2017-5754 | |
11 | ||
12 | Instead of x86_hyper being either NULL on bare metal or a pointer to a | |
13 | struct hypervisor_x86 in case of the kernel running as a guest merge | |
14 | the struct into x86_platform and x86_init. | |
15 | ||
16 | This will remove the need for wrappers making it hard to find out what | |
17 | is being called. With dummy functions added for all callbacks testing | |
18 | for a NULL function pointer can be removed, too. | |
19 | ||
20 | Suggested-by: Ingo Molnar <mingo@kernel.org> | |
21 | Signed-off-by: Juergen Gross <jgross@suse.com> | |
22 | Acked-by: Thomas Gleixner <tglx@linutronix.de> | |
23 | Cc: Linus Torvalds <torvalds@linux-foundation.org> | |
24 | Cc: Peter Zijlstra <peterz@infradead.org> | |
25 | Cc: akataria@vmware.com | |
26 | Cc: boris.ostrovsky@oracle.com | |
27 | Cc: devel@linuxdriverproject.org | |
28 | Cc: haiyangz@microsoft.com | |
29 | Cc: kvm@vger.kernel.org | |
30 | Cc: kys@microsoft.com | |
31 | Cc: pbonzini@redhat.com | |
32 | Cc: rkrcmar@redhat.com | |
33 | Cc: rusty@rustcorp.com.au | |
34 | Cc: sthemmin@microsoft.com | |
35 | Cc: virtualization@lists.linux-foundation.org | |
36 | Cc: xen-devel@lists.xenproject.org | |
37 | Link: http://lkml.kernel.org/r/20171109132739.23465-2-jgross@suse.com | |
38 | Signed-off-by: Ingo Molnar <mingo@kernel.org> | |
39 | (cherry picked from commit f72e38e8ec8869ac0ba5a75d7d2f897d98a1454e) | |
40 | Signed-off-by: Andy Whitcroft <apw@canonical.com> | |
41 | Signed-off-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com> | |
42 | (cherry picked from commit 2d0b017b38623bca666acbcb5ab251315845fa55) | |
43 | Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com> | |
44 | --- | |
45 | arch/x86/include/asm/hypervisor.h | 25 ++++-------------- | |
46 | arch/x86/include/asm/x86_init.h | 24 +++++++++++++++++ | |
47 | include/linux/hypervisor.h | 8 ++++-- | |
48 | arch/x86/kernel/apic/apic.c | 2 +- | |
49 | arch/x86/kernel/cpu/hypervisor.c | 54 +++++++++++++++++++-------------------- | |
50 | arch/x86/kernel/cpu/mshyperv.c | 2 +- | |
51 | arch/x86/kernel/cpu/vmware.c | 4 +-- | |
52 | arch/x86/kernel/kvm.c | 2 +- | |
53 | arch/x86/kernel/x86_init.c | 9 +++++++ | |
54 | arch/x86/mm/init.c | 2 +- | |
55 | arch/x86/xen/enlighten_hvm.c | 8 +++--- | |
56 | arch/x86/xen/enlighten_pv.c | 2 +- | |
57 | 12 files changed, 81 insertions(+), 61 deletions(-) | |
58 | ||
59 | diff --git a/arch/x86/include/asm/hypervisor.h b/arch/x86/include/asm/hypervisor.h | |
60 | index 0ead9dbb9130..0eca7239a7aa 100644 | |
61 | --- a/arch/x86/include/asm/hypervisor.h | |
62 | +++ b/arch/x86/include/asm/hypervisor.h | |
63 | @@ -23,6 +23,7 @@ | |
64 | #ifdef CONFIG_HYPERVISOR_GUEST | |
65 | ||
66 | #include <asm/kvm_para.h> | |
67 | +#include <asm/x86_init.h> | |
68 | #include <asm/xen/hypervisor.h> | |
69 | ||
70 | /* | |
71 | @@ -35,17 +36,11 @@ struct hypervisor_x86 { | |
72 | /* Detection routine */ | |
73 | uint32_t (*detect)(void); | |
74 | ||
75 | - /* Platform setup (run once per boot) */ | |
76 | - void (*init_platform)(void); | |
77 | + /* init time callbacks */ | |
78 | + struct x86_hyper_init init; | |
79 | ||
80 | - /* X2APIC detection (run once per boot) */ | |
81 | - bool (*x2apic_available)(void); | |
82 | - | |
83 | - /* pin current vcpu to specified physical cpu (run rarely) */ | |
84 | - void (*pin_vcpu)(int); | |
85 | - | |
86 | - /* called during init_mem_mapping() to setup early mappings. */ | |
87 | - void (*init_mem_mapping)(void); | |
88 | + /* runtime callbacks */ | |
89 | + struct x86_hyper_runtime runtime; | |
90 | }; | |
91 | ||
92 | extern const struct hypervisor_x86 *x86_hyper; | |
93 | @@ -58,17 +53,7 @@ extern const struct hypervisor_x86 x86_hyper_xen_hvm; | |
94 | extern const struct hypervisor_x86 x86_hyper_kvm; | |
95 | ||
96 | extern void init_hypervisor_platform(void); | |
97 | -extern bool hypervisor_x2apic_available(void); | |
98 | -extern void hypervisor_pin_vcpu(int cpu); | |
99 | - | |
100 | -static inline void hypervisor_init_mem_mapping(void) | |
101 | -{ | |
102 | - if (x86_hyper && x86_hyper->init_mem_mapping) | |
103 | - x86_hyper->init_mem_mapping(); | |
104 | -} | |
105 | #else | |
106 | static inline void init_hypervisor_platform(void) { } | |
107 | -static inline bool hypervisor_x2apic_available(void) { return false; } | |
108 | -static inline void hypervisor_init_mem_mapping(void) { } | |
109 | #endif /* CONFIG_HYPERVISOR_GUEST */ | |
110 | #endif /* _ASM_X86_HYPERVISOR_H */ | |
111 | diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h | |
112 | index 7ba7e90a9ad6..4d95e5a13c0b 100644 | |
113 | --- a/arch/x86/include/asm/x86_init.h | |
114 | +++ b/arch/x86/include/asm/x86_init.h | |
115 | @@ -113,6 +113,18 @@ struct x86_init_pci { | |
116 | void (*fixup_irqs)(void); | |
117 | }; | |
118 | ||
119 | +/** | |
120 | + * struct x86_hyper_init - x86 hypervisor init functions | |
121 | + * @init_platform: platform setup | |
122 | + * @x2apic_available: X2APIC detection | |
123 | + * @init_mem_mapping: setup early mappings during init_mem_mapping() | |
124 | + */ | |
125 | +struct x86_hyper_init { | |
126 | + void (*init_platform)(void); | |
127 | + bool (*x2apic_available)(void); | |
128 | + void (*init_mem_mapping)(void); | |
129 | +}; | |
130 | + | |
131 | /** | |
132 | * struct x86_init_ops - functions for platform specific setup | |
133 | * | |
134 | @@ -126,6 +138,7 @@ struct x86_init_ops { | |
135 | struct x86_init_timers timers; | |
136 | struct x86_init_iommu iommu; | |
137 | struct x86_init_pci pci; | |
138 | + struct x86_hyper_init hyper; | |
139 | }; | |
140 | ||
141 | /** | |
142 | @@ -198,6 +211,15 @@ struct x86_legacy_features { | |
143 | struct x86_legacy_devices devices; | |
144 | }; | |
145 | ||
146 | +/** | |
147 | + * struct x86_hyper_runtime - x86 hypervisor specific runtime callbacks | |
148 | + * | |
149 | + * @pin_vcpu: pin current vcpu to specified physical cpu (run rarely) | |
150 | + */ | |
151 | +struct x86_hyper_runtime { | |
152 | + void (*pin_vcpu)(int cpu); | |
153 | +}; | |
154 | + | |
155 | /** | |
156 | * struct x86_platform_ops - platform specific runtime functions | |
157 | * @calibrate_cpu: calibrate CPU | |
158 | @@ -217,6 +239,7 @@ struct x86_legacy_features { | |
159 | * possible in x86_early_init_platform_quirks() by | |
160 | * only using the current x86_hardware_subarch | |
161 | * semantics. | |
162 | + * @hyper: x86 hypervisor specific runtime callbacks | |
163 | */ | |
164 | struct x86_platform_ops { | |
165 | unsigned long (*calibrate_cpu)(void); | |
166 | @@ -232,6 +255,7 @@ struct x86_platform_ops { | |
167 | void (*apic_post_init)(void); | |
168 | struct x86_legacy_features legacy; | |
169 | void (*set_legacy_features)(void); | |
170 | + struct x86_hyper_runtime hyper; | |
171 | }; | |
172 | ||
173 | struct pci_dev; | |
174 | diff --git a/include/linux/hypervisor.h b/include/linux/hypervisor.h | |
175 | index 3fa5ef2b3759..35e170ca87a8 100644 | |
176 | --- a/include/linux/hypervisor.h | |
177 | +++ b/include/linux/hypervisor.h | |
178 | @@ -6,8 +6,12 @@ | |
179 | * Juergen Gross <jgross@suse.com> | |
180 | */ | |
181 | ||
182 | -#ifdef CONFIG_HYPERVISOR_GUEST | |
183 | -#include <asm/hypervisor.h> | |
184 | +#ifdef CONFIG_X86 | |
185 | +#include <asm/x86_init.h> | |
186 | +static inline void hypervisor_pin_vcpu(int cpu) | |
187 | +{ | |
188 | + x86_platform.hyper.pin_vcpu(cpu); | |
189 | +} | |
190 | #else | |
191 | static inline void hypervisor_pin_vcpu(int cpu) | |
192 | { | |
193 | diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c | |
194 | index 4a7f962b53ff..bb63c1350524 100644 | |
195 | --- a/arch/x86/kernel/apic/apic.c | |
196 | +++ b/arch/x86/kernel/apic/apic.c | |
197 | @@ -1666,7 +1666,7 @@ static __init void try_to_enable_x2apic(int remap_mode) | |
198 | * under KVM | |
199 | */ | |
200 | if (max_physical_apicid > 255 || | |
201 | - !hypervisor_x2apic_available()) { | |
202 | + !x86_init.hyper.x2apic_available()) { | |
203 | pr_info("x2apic: IRQ remapping doesn't support X2APIC mode\n"); | |
204 | x2apic_disable(); | |
205 | return; | |
206 | diff --git a/arch/x86/kernel/cpu/hypervisor.c b/arch/x86/kernel/cpu/hypervisor.c | |
207 | index 4fa90006ac68..22226c1bf092 100644 | |
208 | --- a/arch/x86/kernel/cpu/hypervisor.c | |
209 | +++ b/arch/x86/kernel/cpu/hypervisor.c | |
210 | @@ -44,51 +44,49 @@ static const __initconst struct hypervisor_x86 * const hypervisors[] = | |
211 | const struct hypervisor_x86 *x86_hyper; | |
212 | EXPORT_SYMBOL(x86_hyper); | |
213 | ||
214 | -static inline void __init | |
215 | +static inline const struct hypervisor_x86 * __init | |
216 | detect_hypervisor_vendor(void) | |
217 | { | |
218 | - const struct hypervisor_x86 *h, * const *p; | |
219 | + const struct hypervisor_x86 *h = NULL, * const *p; | |
220 | uint32_t pri, max_pri = 0; | |
221 | ||
222 | for (p = hypervisors; p < hypervisors + ARRAY_SIZE(hypervisors); p++) { | |
223 | - h = *p; | |
224 | - pri = h->detect(); | |
225 | - if (pri != 0 && pri > max_pri) { | |
226 | + pri = (*p)->detect(); | |
227 | + if (pri > max_pri) { | |
228 | max_pri = pri; | |
229 | - x86_hyper = h; | |
230 | + h = *p; | |
231 | } | |
232 | } | |
233 | ||
234 | - if (max_pri) | |
235 | - pr_info("Hypervisor detected: %s\n", x86_hyper->name); | |
236 | + if (h) | |
237 | + pr_info("Hypervisor detected: %s\n", h->name); | |
238 | + | |
239 | + return h; | |
240 | } | |
241 | ||
242 | -void __init init_hypervisor_platform(void) | |
243 | +static void __init copy_array(const void *src, void *target, unsigned int size) | |
244 | { | |
245 | + unsigned int i, n = size / sizeof(void *); | |
246 | + const void * const *from = (const void * const *)src; | |
247 | + const void **to = (const void **)target; | |
248 | ||
249 | - detect_hypervisor_vendor(); | |
250 | - | |
251 | - if (!x86_hyper) | |
252 | - return; | |
253 | - | |
254 | - if (x86_hyper->init_platform) | |
255 | - x86_hyper->init_platform(); | |
256 | + for (i = 0; i < n; i++) | |
257 | + if (from[i]) | |
258 | + to[i] = from[i]; | |
259 | } | |
260 | ||
261 | -bool __init hypervisor_x2apic_available(void) | |
262 | +void __init init_hypervisor_platform(void) | |
263 | { | |
264 | - return x86_hyper && | |
265 | - x86_hyper->x2apic_available && | |
266 | - x86_hyper->x2apic_available(); | |
267 | -} | |
268 | + const struct hypervisor_x86 *h; | |
269 | ||
270 | -void hypervisor_pin_vcpu(int cpu) | |
271 | -{ | |
272 | - if (!x86_hyper) | |
273 | + h = detect_hypervisor_vendor(); | |
274 | + | |
275 | + if (!h) | |
276 | return; | |
277 | ||
278 | - if (x86_hyper->pin_vcpu) | |
279 | - x86_hyper->pin_vcpu(cpu); | |
280 | - else | |
281 | - WARN_ONCE(1, "vcpu pinning requested but not supported!\n"); | |
282 | + copy_array(&h->init, &x86_init.hyper, sizeof(h->init)); | |
283 | + copy_array(&h->runtime, &x86_platform.hyper, sizeof(h->runtime)); | |
284 | + | |
285 | + x86_hyper = h; | |
286 | + x86_init.hyper.init_platform(); | |
287 | } | |
288 | diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c | |
289 | index 70e717fccdd6..9707e431da27 100644 | |
290 | --- a/arch/x86/kernel/cpu/mshyperv.c | |
291 | +++ b/arch/x86/kernel/cpu/mshyperv.c | |
292 | @@ -255,6 +255,6 @@ static void __init ms_hyperv_init_platform(void) | |
293 | const __refconst struct hypervisor_x86 x86_hyper_ms_hyperv = { | |
294 | .name = "Microsoft HyperV", | |
295 | .detect = ms_hyperv_platform, | |
296 | - .init_platform = ms_hyperv_init_platform, | |
297 | + .init.init_platform = ms_hyperv_init_platform, | |
298 | }; | |
299 | EXPORT_SYMBOL(x86_hyper_ms_hyperv); | |
300 | diff --git a/arch/x86/kernel/cpu/vmware.c b/arch/x86/kernel/cpu/vmware.c | |
301 | index 40ed26852ebd..4804c1d063c8 100644 | |
302 | --- a/arch/x86/kernel/cpu/vmware.c | |
303 | +++ b/arch/x86/kernel/cpu/vmware.c | |
304 | @@ -208,7 +208,7 @@ static bool __init vmware_legacy_x2apic_available(void) | |
305 | const __refconst struct hypervisor_x86 x86_hyper_vmware = { | |
306 | .name = "VMware", | |
307 | .detect = vmware_platform, | |
308 | - .init_platform = vmware_platform_setup, | |
309 | - .x2apic_available = vmware_legacy_x2apic_available, | |
310 | + .init.init_platform = vmware_platform_setup, | |
311 | + .init.x2apic_available = vmware_legacy_x2apic_available, | |
312 | }; | |
313 | EXPORT_SYMBOL(x86_hyper_vmware); | |
314 | diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c | |
315 | index 9e3798b00e40..54e373bfeab9 100644 | |
316 | --- a/arch/x86/kernel/kvm.c | |
317 | +++ b/arch/x86/kernel/kvm.c | |
318 | @@ -547,7 +547,7 @@ static uint32_t __init kvm_detect(void) | |
319 | const struct hypervisor_x86 x86_hyper_kvm __refconst = { | |
320 | .name = "KVM", | |
321 | .detect = kvm_detect, | |
322 | - .x2apic_available = kvm_para_available, | |
323 | + .init.x2apic_available = kvm_para_available, | |
324 | }; | |
325 | EXPORT_SYMBOL_GPL(x86_hyper_kvm); | |
326 | ||
327 | diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c | |
328 | index a088b2c47f73..5b2d10c1973a 100644 | |
329 | --- a/arch/x86/kernel/x86_init.c | |
330 | +++ b/arch/x86/kernel/x86_init.c | |
331 | @@ -28,6 +28,8 @@ void x86_init_noop(void) { } | |
332 | void __init x86_init_uint_noop(unsigned int unused) { } | |
333 | int __init iommu_init_noop(void) { return 0; } | |
334 | void iommu_shutdown_noop(void) { } | |
335 | +bool __init bool_x86_init_noop(void) { return false; } | |
336 | +void x86_op_int_noop(int cpu) { } | |
337 | ||
338 | /* | |
339 | * The platform setup functions are preset with the default functions | |
340 | @@ -81,6 +83,12 @@ struct x86_init_ops x86_init __initdata = { | |
341 | .init_irq = x86_default_pci_init_irq, | |
342 | .fixup_irqs = x86_default_pci_fixup_irqs, | |
343 | }, | |
344 | + | |
345 | + .hyper = { | |
346 | + .init_platform = x86_init_noop, | |
347 | + .x2apic_available = bool_x86_init_noop, | |
348 | + .init_mem_mapping = x86_init_noop, | |
349 | + }, | |
350 | }; | |
351 | ||
352 | struct x86_cpuinit_ops x86_cpuinit = { | |
353 | @@ -101,6 +109,7 @@ struct x86_platform_ops x86_platform __ro_after_init = { | |
354 | .get_nmi_reason = default_get_nmi_reason, | |
355 | .save_sched_clock_state = tsc_save_sched_clock_state, | |
356 | .restore_sched_clock_state = tsc_restore_sched_clock_state, | |
357 | + .hyper.pin_vcpu = x86_op_int_noop, | |
358 | }; | |
359 | ||
360 | EXPORT_SYMBOL_GPL(x86_platform); | |
361 | diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c | |
362 | index af5c1ed21d43..a22c2b95e513 100644 | |
363 | --- a/arch/x86/mm/init.c | |
364 | +++ b/arch/x86/mm/init.c | |
365 | @@ -671,7 +671,7 @@ void __init init_mem_mapping(void) | |
366 | load_cr3(swapper_pg_dir); | |
367 | __flush_tlb_all(); | |
368 | ||
369 | - hypervisor_init_mem_mapping(); | |
370 | + x86_init.hyper.init_mem_mapping(); | |
371 | ||
372 | early_memtest(0, max_pfn_mapped << PAGE_SHIFT); | |
373 | } | |
374 | diff --git a/arch/x86/xen/enlighten_hvm.c b/arch/x86/xen/enlighten_hvm.c | |
375 | index de503c225ae1..7b1622089f96 100644 | |
376 | --- a/arch/x86/xen/enlighten_hvm.c | |
377 | +++ b/arch/x86/xen/enlighten_hvm.c | |
378 | @@ -229,9 +229,9 @@ static uint32_t __init xen_platform_hvm(void) | |
379 | const struct hypervisor_x86 x86_hyper_xen_hvm = { | |
380 | .name = "Xen HVM", | |
381 | .detect = xen_platform_hvm, | |
382 | - .init_platform = xen_hvm_guest_init, | |
383 | - .pin_vcpu = xen_pin_vcpu, | |
384 | - .x2apic_available = xen_x2apic_para_available, | |
385 | - .init_mem_mapping = xen_hvm_init_mem_mapping, | |
386 | + .init.init_platform = xen_hvm_guest_init, | |
387 | + .init.x2apic_available = xen_x2apic_para_available, | |
388 | + .init.init_mem_mapping = xen_hvm_init_mem_mapping, | |
389 | + .runtime.pin_vcpu = xen_pin_vcpu, | |
390 | }; | |
391 | EXPORT_SYMBOL(x86_hyper_xen_hvm); | |
392 | diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c | |
393 | index e7b213047724..4110fc9e5ee9 100644 | |
394 | --- a/arch/x86/xen/enlighten_pv.c | |
395 | +++ b/arch/x86/xen/enlighten_pv.c | |
396 | @@ -1461,6 +1461,6 @@ static uint32_t __init xen_platform_pv(void) | |
397 | const struct hypervisor_x86 x86_hyper_xen_pv = { | |
398 | .name = "Xen PV", | |
399 | .detect = xen_platform_pv, | |
400 | - .pin_vcpu = xen_pin_vcpu, | |
401 | + .runtime.pin_vcpu = xen_pin_vcpu, | |
402 | }; | |
403 | EXPORT_SYMBOL(x86_hyper_xen_pv); | |
404 | -- | |
405 | 2.14.2 | |
406 |