Patch "x86/i8259: Skip probing when ACPI/MADT advertises PCAT compatibility" has been added to the 5.4-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    x86/i8259: Skip probing when ACPI/MADT advertises PCAT compatibility

to the 5.4-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     x86-i8259-skip-probing-when-acpi-madt-advertises-pca.patch
and it can be found in the queue-5.4 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit 2807b3bc514e8032261b3af10559a668924e99be
Author: Thomas Gleixner <tglx@xxxxxxxxxxxxx>
Date:   Wed Oct 25 23:04:15 2023 +0200

    x86/i8259: Skip probing when ACPI/MADT advertises PCAT compatibility
    
    [ Upstream commit 128b0c9781c9f2651bea163cb85e52a6c7be0f9e ]
    
    David and a few others reported that on certain newer systems some legacy
    interrupts fail to work correctly.
    
    Debugging revealed that the BIOS of these systems leaves the legacy PIC in
    uninitialized state which makes the PIC detection fail and the kernel
    switches to a dummy implementation.
    
    Unfortunately this fallback causes quite some code to fail as it depends on
    checks for the number of legacy PIC interrupts or the availability of the
    real PIC.
    
    In theory there is no reason to use the PIC on any modern system when
    IO/APIC is available, but the dependencies on the related checks cannot be
    resolved trivially and on short notice. This needs lots of analysis and
    rework.
    
    The PIC detection has been added to avoid quirky checks and force selection
    of the dummy implementation all over the place, especially in VM guest
    scenarios. So it's not an option to revert the relevant commit as that
    would break a lot of other scenarios.
    
    One solution would be to try to initialize the PIC on detection fail and
    retry the detection, but that puts the burden on everything which does not
    have a PIC.
    
    Fortunately the ACPI/MADT table header has a flag field, which advertises
    in bit 0 that the system is PCAT compatible, which means it has a legacy
    8259 PIC.
    
    Evaluate that bit and if set avoid the detection routine and keep the real
    PIC installed, which then gets initialized (for nothing) and makes the rest
    of the code with all the dependencies work again.
    
    Fixes: e179f6914152 ("x86, irq, pic: Probe for legacy PIC and set legacy_pic appropriately")
    Reported-by: David Lazar <dlazar@xxxxxxxxx>
    Signed-off-by: Thomas Gleixner <tglx@xxxxxxxxxxxxx>
    Tested-by: David Lazar <dlazar@xxxxxxxxx>
    Reviewed-by: Hans de Goede <hdegoede@xxxxxxxxxx>
    Reviewed-by: Mario Limonciello <mario.limonciello@xxxxxxx>
    Cc: stable@xxxxxxxxxxxxxxx
    Closes: https://bugzilla.kernel.org/show_bug.cgi?id=218003
    Link: https://lore.kernel.org/r/875y2u5s8g.ffs@tglx
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/arch/x86/include/asm/i8259.h b/arch/x86/include/asm/i8259.h
index 89789e8c80f66..e16574c16e933 100644
--- a/arch/x86/include/asm/i8259.h
+++ b/arch/x86/include/asm/i8259.h
@@ -67,6 +67,8 @@ struct legacy_pic {
 	void (*make_irq)(unsigned int irq);
 };
 
+void legacy_pic_pcat_compat(void);
+
 extern struct legacy_pic *legacy_pic;
 extern struct legacy_pic null_legacy_pic;
 
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 2e4c8af36e8a5..11c0eab38369f 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -141,6 +141,9 @@ static int __init acpi_parse_madt(struct acpi_table_header *table)
 		       madt->address);
 	}
 
+	if (madt->flags & ACPI_MADT_PCAT_COMPAT)
+		legacy_pic_pcat_compat();
+
 	/* ACPI 6.3 and newer support the online capable bit. */
 	if (acpi_gbl_FADT.header.revision > 6 ||
 	    (acpi_gbl_FADT.header.revision == 6 &&
diff --git a/arch/x86/kernel/i8259.c b/arch/x86/kernel/i8259.c
index 8821d0ab0a08c..82753622f4890 100644
--- a/arch/x86/kernel/i8259.c
+++ b/arch/x86/kernel/i8259.c
@@ -32,6 +32,7 @@
  */
 static void init_8259A(int auto_eoi);
 
+static bool pcat_compat __ro_after_init;
 static int i8259A_auto_eoi;
 DEFINE_RAW_SPINLOCK(i8259A_lock);
 
@@ -301,15 +302,32 @@ static void unmask_8259A(void)
 
 static int probe_8259A(void)
 {
+	unsigned char new_val, probe_val = ~(1 << PIC_CASCADE_IR);
 	unsigned long flags;
-	unsigned char probe_val = ~(1 << PIC_CASCADE_IR);
-	unsigned char new_val;
+
+	/*
+	 * If MADT has the PCAT_COMPAT flag set, then do not bother probing
+	 * for the PIC. Some BIOSes leave the PIC uninitialized and probing
+	 * fails.
+	 *
+	 * Right now this causes problems as quite some code depends on
+	 * nr_legacy_irqs() > 0 or has_legacy_pic() == true. This is silly
+	 * when the system has an IO/APIC because then PIC is not required
+	 * at all, except for really old machines where the timer interrupt
+	 * must be routed through the PIC. So just pretend that the PIC is
+	 * there and let legacy_pic->init() initialize it for nothing.
+	 *
+	 * Alternatively this could just try to initialize the PIC and
+	 * repeat the probe, but for cases where there is no PIC that's
+	 * just pointless.
+	 */
+	if (pcat_compat)
+		return nr_legacy_irqs();
+
 	/*
-	 * Check to see if we have a PIC.
-	 * Mask all except the cascade and read
-	 * back the value we just wrote. If we don't
-	 * have a PIC, we will read 0xff as opposed to the
-	 * value we wrote.
+	 * Check to see if we have a PIC.  Mask all except the cascade and
+	 * read back the value we just wrote. If we don't have a PIC, we
+	 * will read 0xff as opposed to the value we wrote.
 	 */
 	raw_spin_lock_irqsave(&i8259A_lock, flags);
 
@@ -431,5 +449,9 @@ static int __init i8259A_init_ops(void)
 
 	return 0;
 }
-
 device_initcall(i8259A_init_ops);
+
+void __init legacy_pic_pcat_compat(void)
+{
+	pcat_compat = true;
+}



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux