parse_apic() allows the user to try a different apic driver than the default one that's automatically chosen. It works for x86_32, but doesn't work for x86_64 becauase it was removed in 2009 for x86_64 by: commit 7b38725318f4 ("x86: remove subarchitecture support code"), whose changelog doesn't explicitly describe the removal for x86_64. The patch adds back the functionality for x86_64. The intent is mainly to work around an APIC emulation bug in Hyper-V in the case of kdump: currently Hyper-V does not honor the disabled state of the local APICs, and all the IOAPIC-based interrupts may not be delivered to the correct virtual CPU, if the logical-mode APIC driver is used (the kdump kernel usually uses the logical-mode APIC driver, since typically only 1 CPU is active). Luckily the kdump issue can be worked around by forcing the kdump kernel to use physical mode, before the fix to Hyper-V becomes widely available. IMHO the patch is safe because the current default algorithm to choose the apic driver is unchanged; the patch makes a difference only when the user specifies the apic= kernel parameter, e.g. "apic=physical flat". Signed-off-by: Dexuan Cui <decui@xxxxxxxxxxxxx> --- arch/x86/kernel/apic/apic_flat_64.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/apic/apic_flat_64.c b/arch/x86/kernel/apic/apic_flat_64.c index 7862b152a052..efbec63bb01f 100644 --- a/arch/x86/kernel/apic/apic_flat_64.c +++ b/arch/x86/kernel/apic/apic_flat_64.c @@ -23,9 +23,34 @@ static struct apic apic_flat; struct apic *apic __ro_after_init = &apic_flat; EXPORT_SYMBOL_GPL(apic); +static int cmdline_apic __initdata; +static int __init parse_apic(char *arg) +{ + struct apic **drv; + + if (!arg) + return -EINVAL; + + for (drv = __apicdrivers; drv < __apicdrivers_end; drv++) { + if (!strcmp((*drv)->name, arg)) { + apic = *drv; + cmdline_apic = 1; + return 0; + } + } + + /* Parsed again by __setup for debug/verbose */ + return 0; +} +early_param("apic", parse_apic); + + static int flat_acpi_madt_oem_check(char *oem_id, char *oem_table_id) { - return 1; + if (!cmdline_apic) + return 1; + + return apic == &apic_flat; } /* -- 2.25.1