| .. | .. |
|---|
| 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 | }; |
|---|