.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
---|
| 2 | + |
---|
1 | 3 | #include <linux/acpi.h> |
---|
2 | 4 | #include <linux/cpu.h> |
---|
3 | 5 | #include <linux/kexec.h> |
---|
.. | .. |
---|
9 | 11 | |
---|
10 | 12 | #include <asm/cpu.h> |
---|
11 | 13 | #include <asm/smp.h> |
---|
| 14 | +#include <asm/io_apic.h> |
---|
12 | 15 | #include <asm/reboot.h> |
---|
13 | 16 | #include <asm/setup.h> |
---|
| 17 | +#include <asm/idtentry.h> |
---|
14 | 18 | #include <asm/hypervisor.h> |
---|
15 | 19 | #include <asm/e820/api.h> |
---|
16 | 20 | #include <asm/early_ioremap.h> |
---|
.. | .. |
---|
116 | 120 | this_cpu_write(xen_vcpu_id, smp_processor_id()); |
---|
117 | 121 | } |
---|
118 | 122 | |
---|
| 123 | +DEFINE_IDTENTRY_SYSVEC(sysvec_xen_hvm_callback) |
---|
| 124 | +{ |
---|
| 125 | + struct pt_regs *old_regs = set_irq_regs(regs); |
---|
| 126 | + |
---|
| 127 | + inc_irq_stat(irq_hv_callback_count); |
---|
| 128 | + |
---|
| 129 | + xen_hvm_evtchn_do_upcall(); |
---|
| 130 | + |
---|
| 131 | + set_irq_regs(old_regs); |
---|
| 132 | +} |
---|
| 133 | + |
---|
119 | 134 | #ifdef CONFIG_KEXEC_CORE |
---|
120 | 135 | static void xen_hvm_shutdown(void) |
---|
121 | 136 | { |
---|
.. | .. |
---|
173 | 188 | return 0; |
---|
174 | 189 | } |
---|
175 | 190 | |
---|
| 191 | +static bool no_vector_callback __initdata; |
---|
| 192 | + |
---|
176 | 193 | static void __init xen_hvm_guest_init(void) |
---|
177 | 194 | { |
---|
178 | 195 | if (xen_pv_domain()) |
---|
.. | .. |
---|
192 | 209 | |
---|
193 | 210 | xen_panic_handler_init(); |
---|
194 | 211 | |
---|
195 | | - if (xen_feature(XENFEAT_hvm_callback_vector)) |
---|
| 212 | + if (!no_vector_callback && xen_feature(XENFEAT_hvm_callback_vector)) |
---|
196 | 213 | xen_have_vector_callback = 1; |
---|
197 | 214 | |
---|
198 | 215 | xen_hvm_smp_init(); |
---|
.. | .. |
---|
208 | 225 | #endif |
---|
209 | 226 | } |
---|
210 | 227 | |
---|
211 | | -static bool xen_nopv; |
---|
212 | 228 | static __init int xen_parse_nopv(char *arg) |
---|
213 | 229 | { |
---|
214 | | - xen_nopv = true; |
---|
215 | | - return 0; |
---|
| 230 | + pr_notice("\"xen_nopv\" is deprecated, please use \"nopv\" instead\n"); |
---|
| 231 | + |
---|
| 232 | + if (xen_cpuid_base()) |
---|
| 233 | + nopv = true; |
---|
| 234 | + return 0; |
---|
216 | 235 | } |
---|
217 | 236 | early_param("xen_nopv", xen_parse_nopv); |
---|
218 | 237 | |
---|
219 | | -bool xen_hvm_need_lapic(void) |
---|
| 238 | +static __init int xen_parse_no_vector_callback(char *arg) |
---|
220 | 239 | { |
---|
221 | | - if (xen_nopv) |
---|
222 | | - return false; |
---|
| 240 | + no_vector_callback = true; |
---|
| 241 | + return 0; |
---|
| 242 | +} |
---|
| 243 | +early_param("xen_no_vector_callback", xen_parse_no_vector_callback); |
---|
| 244 | + |
---|
| 245 | +bool __init xen_hvm_need_lapic(void) |
---|
| 246 | +{ |
---|
223 | 247 | if (xen_pv_domain()) |
---|
224 | 248 | return false; |
---|
225 | 249 | if (!xen_hvm_domain()) |
---|
.. | .. |
---|
227 | 251 | if (xen_feature(XENFEAT_hvm_pirqs) && xen_have_vector_callback) |
---|
228 | 252 | return false; |
---|
229 | 253 | return true; |
---|
230 | | -} |
---|
231 | | -EXPORT_SYMBOL_GPL(xen_hvm_need_lapic); |
---|
232 | | - |
---|
233 | | -static uint32_t __init xen_platform_hvm(void) |
---|
234 | | -{ |
---|
235 | | - if (xen_pv_domain() || xen_nopv) |
---|
236 | | - return 0; |
---|
237 | | - |
---|
238 | | - return xen_cpuid_base(); |
---|
239 | 254 | } |
---|
240 | 255 | |
---|
241 | 256 | static __init void xen_hvm_guest_late_init(void) |
---|
.. | .. |
---|
249 | 264 | /* PVH detected. */ |
---|
250 | 265 | xen_pvh = true; |
---|
251 | 266 | |
---|
| 267 | + if (nopv) |
---|
| 268 | + panic("\"nopv\" and \"xen_nopv\" parameters are unsupported in PVH guest."); |
---|
| 269 | + |
---|
252 | 270 | /* Make sure we don't fall back to (default) ACPI_IRQ_MODEL_PIC. */ |
---|
253 | 271 | if (!nr_ioapics && acpi_irq_model == ACPI_IRQ_MODEL_PIC) |
---|
254 | 272 | acpi_irq_model = ACPI_IRQ_MODEL_PLATFORM; |
---|
.. | .. |
---|
258 | 276 | #endif |
---|
259 | 277 | } |
---|
260 | 278 | |
---|
261 | | -const __initconst struct hypervisor_x86 x86_hyper_xen_hvm = { |
---|
| 279 | +static uint32_t __init xen_platform_hvm(void) |
---|
| 280 | +{ |
---|
| 281 | + uint32_t xen_domain = xen_cpuid_base(); |
---|
| 282 | + struct x86_hyper_init *h = &x86_hyper_xen_hvm.init; |
---|
| 283 | + |
---|
| 284 | + if (xen_pv_domain()) |
---|
| 285 | + return 0; |
---|
| 286 | + |
---|
| 287 | + if (xen_pvh_domain() && nopv) { |
---|
| 288 | + /* Guest booting via the Xen-PVH boot entry goes here */ |
---|
| 289 | + pr_info("\"nopv\" parameter is ignored in PVH guest\n"); |
---|
| 290 | + nopv = false; |
---|
| 291 | + } else if (nopv && xen_domain) { |
---|
| 292 | + /* |
---|
| 293 | + * Guest booting via normal boot entry (like via grub2) goes |
---|
| 294 | + * here. |
---|
| 295 | + * |
---|
| 296 | + * Use interface functions for bare hardware if nopv, |
---|
| 297 | + * xen_hvm_guest_late_init is an exception as we need to |
---|
| 298 | + * detect PVH and panic there. |
---|
| 299 | + */ |
---|
| 300 | + h->init_platform = x86_init_noop; |
---|
| 301 | + h->x2apic_available = bool_x86_init_noop; |
---|
| 302 | + h->init_mem_mapping = x86_init_noop; |
---|
| 303 | + h->init_after_bootmem = x86_init_noop; |
---|
| 304 | + h->guest_late_init = xen_hvm_guest_late_init; |
---|
| 305 | + x86_hyper_xen_hvm.runtime.pin_vcpu = x86_op_int_noop; |
---|
| 306 | + } |
---|
| 307 | + return xen_domain; |
---|
| 308 | +} |
---|
| 309 | + |
---|
| 310 | +struct hypervisor_x86 x86_hyper_xen_hvm __initdata = { |
---|
262 | 311 | .name = "Xen HVM", |
---|
263 | 312 | .detect = xen_platform_hvm, |
---|
264 | 313 | .type = X86_HYPER_XEN_HVM, |
---|
.. | .. |
---|
267 | 316 | .init.init_mem_mapping = xen_hvm_init_mem_mapping, |
---|
268 | 317 | .init.guest_late_init = xen_hvm_guest_late_init, |
---|
269 | 318 | .runtime.pin_vcpu = xen_pin_vcpu, |
---|
| 319 | + .ignore_nopv = true, |
---|
270 | 320 | }; |
---|