]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
x86/acpi: Do not attempt to bring up secondary CPUs in the kexec case
authorKirill A. Shutemov <kirill.shutemov@linux.intel.com>
Fri, 14 Jun 2024 09:59:00 +0000 (12:59 +0300)
committerBorislav Petkov (AMD) <bp@alien8.de>
Mon, 17 Jun 2024 15:46:17 +0000 (17:46 +0200)
ACPI MADT doesn't allow to offline a CPU after it was onlined. This limits
kexec: the second kernel won't be able to use more than one CPU.

To prevent a kexec kernel from onlining secondary CPUs, invalidate the mailbox
address in the ACPI MADT wakeup structure which prevents a kexec kernel to use
it.

This is safe as the booting kernel has the mailbox address cached already and
acpi_wakeup_cpu() uses the cached value to bring up the secondary CPUs.

Note: This is a Linux specific convention and not covered by the ACPI
specification.

Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
Reviewed-by: Kai Huang <kai.huang@intel.com>
Reviewed-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Tested-by: Tao Liu <ltao@redhat.com>
Link: https://lore.kernel.org/r/20240614095904.1345461-16-kirill.shutemov@linux.intel.com
arch/x86/kernel/acpi/madt_wakeup.c

index 004801b9b151516dd6094183863a5fb5e6bd77a5..30820f9de5afde5c15e4a16d02b79eaf633016c8 100644 (file)
@@ -14,6 +14,11 @@ static struct acpi_madt_multiproc_wakeup_mailbox *acpi_mp_wake_mailbox __ro_afte
 
 static int acpi_wakeup_cpu(u32 apicid, unsigned long start_ip)
 {
+       if (!acpi_mp_wake_mailbox_paddr) {
+               pr_warn_once("No MADT mailbox: cannot bringup secondary CPUs. Booting with kexec?\n");
+               return -EOPNOTSUPP;
+       }
+
        /*
         * Remap mailbox memory only for the first call to acpi_wakeup_cpu().
         *
@@ -64,6 +69,28 @@ static int acpi_wakeup_cpu(u32 apicid, unsigned long start_ip)
        return 0;
 }
 
+static void acpi_mp_disable_offlining(struct acpi_madt_multiproc_wakeup *mp_wake)
+{
+       cpu_hotplug_disable_offlining();
+
+       /*
+        * ACPI MADT doesn't allow to offline a CPU after it was onlined. This
+        * limits kexec: the second kernel won't be able to use more than one CPU.
+        *
+        * To prevent a kexec kernel from onlining secondary CPUs invalidate the
+        * mailbox address in the ACPI MADT wakeup structure which prevents a
+        * kexec kernel to use it.
+        *
+        * This is safe as the booting kernel has the mailbox address cached
+        * already and acpi_wakeup_cpu() uses the cached value to bring up the
+        * secondary CPUs.
+        *
+        * Note: This is a Linux specific convention and not covered by the
+        *       ACPI specification.
+        */
+       mp_wake->mailbox_address = 0;
+}
+
 int __init acpi_parse_mp_wake(union acpi_subtable_headers *header,
                              const unsigned long end)
 {
@@ -77,7 +104,7 @@ int __init acpi_parse_mp_wake(union acpi_subtable_headers *header,
 
        acpi_mp_wake_mailbox_paddr = mp_wake->mailbox_address;
 
-       cpu_hotplug_disable_offlining();
+       acpi_mp_disable_offlining(mp_wake);
 
        apic_update_callback(wakeup_secondary_cpu_64, acpi_wakeup_cpu);