From e2079c43861f71b2deb78ee20e247ad954fdd67e Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 8 Jul 2008 16:12:26 +0200 Subject: [PATCH] x86: fix C1E && nx6325 stability problem The problems are that, with the ACPI vs timer overring issue _fixed_, after using the box for some time (between several seconds and 1 hour, at random) processes get very high CPU loads (once I've got X using 107% of the CPU, for example) and the system becomes unresponsive, as though there were interrupts lost or something similar. Andreas Herrman reproduced similar problems: > Ok, now I've reproduced the stability problem. > - Using tip/master, > - reverting e38502eb8aa82314d5ab0eba45f50e6790dadd88 and > - applying your patch from this posting > http://marc.info/?l=linux-kernel&m=121539354224562&w=4 > > Starting X, firefox, gimp, tuxpaint and doing some drawing in tuxpaint > results in a slow system. Drawing is almost not possible anymore -- > Selections of new colors, cursors etc. is performed with huge delay > if it's performed at all. > > BTW, the code sets up timer IRQ as Virtual Wire IRQ: > > Jul 8 14:57:58 kodscha IO-APIC (apicid-pin) 2-22, 2-23 not connected. > Jul 8 14:57:58 kodscha ..TIMER: vector=0x30 apic1=0 pin1=2 apic2=-1 pin2=-1 > Jul 8 14:57:58 kodscha ...trying to set up timer as Virtual Wire IRQ... works. > > and both INT0 and INT2 of IOAPIC are masked: > > Jul 8 14:57:58 kodscha NR Dst Mask Trig IRR Pol Stat Dmod Deli Vect: > Jul 8 14:57:58 kodscha 00 000 1 0 0 0 0 0 0 00 > Jul 8 14:57:58 kodscha 01 003 0 0 0 0 0 1 1 31 > Jul 8 14:57:58 kodscha 02 003 1 0 0 0 0 0 0 30 > > I've also seen strange CPU utilization -- with syslog-ng: > > top - 15:33:06 up 35 min, 4 users, load average: 1.70, 0.68, 0.37 > Tasks: 64 total, 4 running, 60 sleeping, 0 stopped, 0 zombie > Cpu0 : 0.0%us,100.0%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st > Cpu1 : 6.4%us, 87.2%sy, 0.0%ni, 5.8%id, 0.0%wa, 0.6%hi, 0.0%si, 0.0%st > Mem: 895384k total, 283568k used, 611816k free, 35492k buffers > Swap: 1959920k total, 0k used, 1959920k free, 163044k cached > > PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND > 4632 root 20 0 17216 800 580 S 104 0.1 0:34.22 syslog-ng > 28505 root 20 0 205m 11m 4024 S 6 1.3 0:21.16 X > 28518 root 20 0 56292 5652 4492 S 1 0.6 0:01.80 fluxbox > 1 root 20 0 3724 608 508 S 0 0.1 0:00.36 init > > So far I have no clue why C1E-idle in conjunction with virtual wire > mode causes this strange behaviour. > > ... and I start to think about the root cause of all this. > > I've performed similar tests under X with the IRQ0/INT0 configuration and > I did not see above symptoms. So lets fall back to the IRQ0/INT0 configuration on this box. This basically restores the dont-use-the-lapic-timer exception mechanism that was unconditional on this box prior commit 8750bf5 ("x86: add C1E aware idle function"). Signed-off-by: Ingo Molnar --- arch/x86/kernel/acpi/boot.c | 43 +++++++++++++++++++++++++++++++----- arch/x86/kernel/io_apic_32.c | 10 +++++++++ arch/x86/kernel/io_apic_64.c | 10 +++++++++ include/asm-x86/genapic_32.h | 1 + include/asm-x86/genapic_64.h | 2 ++ 5 files changed, 60 insertions(+), 6 deletions(-) diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 5c0107602b6..e1f01394b68 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -1373,8 +1373,6 @@ static void __init acpi_process_madt(void) return; } -#ifdef __i386__ - static int __init disable_acpi_irq(const struct dmi_system_id *d) { if (!acpi_force) { @@ -1435,6 +1433,17 @@ dmi_disable_irq0_through_ioapic(const struct dmi_system_id *d) return 0; } +/* + * Force ignoring BIOS IRQ0 pin2 override + */ +static int __init dmi_ignore_irq0_timer_override(const struct dmi_system_id *d) +{ + pr_notice("%s detected: Ignoring BIOS IRQ0 pin2 override\n", d->ident); + acpi_skip_timer_override = 1; + force_mask_ioapic_irq_2(); + return 0; +} + /* * If your system is blacklisted here, but you find that acpi=force * works for you, please contact acpi-devel@sourceforge.net @@ -1628,11 +1637,35 @@ static struct dmi_system_id __initdata acpi_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6325"), }, }, + /* + * HP laptops which use a DSDT reporting as HP/SB400/10000, + * which includes some code which overrides all temperature + * trip points to 16C if the INTIN2 input of the I/O APIC + * is enabled. This input is incorrectly designated the + * ISA IRQ 0 via an interrupt source override even though + * it is wired to the output of the master 8259A and INTIN0 + * is not connected at all. Force ignoring BIOS IRQ0 pin2 + * override in that cases. + */ + { + .callback = dmi_ignore_irq0_timer_override, + .ident = "HP NX6125 laptop", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6125"), + }, + }, + { + .callback = dmi_ignore_irq0_timer_override, + .ident = "HP NX6325 laptop", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6325"), + }, + }, {} }; -#endif /* __i386__ */ - /* * acpi_boot_table_init() and acpi_boot_init() * called from setup_arch(), always. @@ -1660,9 +1693,7 @@ int __init acpi_boot_table_init(void) { int error; -#ifdef __i386__ dmi_check_system(acpi_dmi_table); -#endif /* * If acpi_disabled, bail out diff --git a/arch/x86/kernel/io_apic_32.c b/arch/x86/kernel/io_apic_32.c index 337ec3438a8..6b220b9dcbb 100644 --- a/arch/x86/kernel/io_apic_32.c +++ b/arch/x86/kernel/io_apic_32.c @@ -59,6 +59,13 @@ static struct { int pin, apic; } ioapic_i8259 = { -1, -1 }; static DEFINE_SPINLOCK(ioapic_lock); static DEFINE_SPINLOCK(vector_lock); +static bool mask_ioapic_irq_2 __initdata; + +void __init force_mask_ioapic_irq_2(void) +{ + mask_ioapic_irq_2 = true; +} + int timer_through_8259 __initdata; /* @@ -2172,6 +2179,9 @@ static inline void __init check_timer(void) printk(KERN_INFO "..TIMER: vector=0x%02X apic1=%d pin1=%d apic2=%d pin2=%d\n", vector, apic1, pin1, apic2, pin2); + if (mask_ioapic_irq_2) + mask_IO_APIC_irq(2); + /* * Some BIOS writers are clueless and report the ExtINTA * I/O APIC input from the cascaded 8259A as the timer diff --git a/arch/x86/kernel/io_apic_64.c b/arch/x86/kernel/io_apic_64.c index 2b4c40bc12c..0494cdb270c 100644 --- a/arch/x86/kernel/io_apic_64.c +++ b/arch/x86/kernel/io_apic_64.c @@ -94,6 +94,13 @@ static int no_timer_check; static int disable_timer_pin_1 __initdata; +static bool mask_ioapic_irq_2 __initdata; + +void __init force_mask_ioapic_irq_2(void) +{ + mask_ioapic_irq_2 = true; +} + int timer_through_8259 __initdata; /* Where if anywhere is the i8259 connect in external int mode */ @@ -1698,6 +1705,9 @@ static inline void __init check_timer(void) apic_printk(APIC_VERBOSE,KERN_INFO "..TIMER: vector=0x%02X apic1=%d pin1=%d apic2=%d pin2=%d\n", cfg->vector, apic1, pin1, apic2, pin2); + if (mask_ioapic_irq_2) + mask_IO_APIC_irq(2); + /* * Some BIOS writers are clueless and report the ExtINTA * I/O APIC input from the cascaded 8259A as the timer diff --git a/include/asm-x86/genapic_32.h b/include/asm-x86/genapic_32.h index b02ea6e17de..8d4c8bdb906 100644 --- a/include/asm-x86/genapic_32.h +++ b/include/asm-x86/genapic_32.h @@ -119,5 +119,6 @@ enum uv_system_type {UV_NONE, UV_LEGACY_APIC, UV_X2APIC, UV_NON_UNIQUE_APIC}; #define is_uv_system() 0 #define uv_wakeup_secondary(a, b) 1 +extern void force_mask_ioapic_irq_2(void); #endif diff --git a/include/asm-x86/genapic_64.h b/include/asm-x86/genapic_64.h index 0f8504627c4..082ad020e41 100644 --- a/include/asm-x86/genapic_64.h +++ b/include/asm-x86/genapic_64.h @@ -46,4 +46,6 @@ extern int uv_wakeup_secondary(int phys_apicid, unsigned int start_rip); extern void setup_apic_routing(void); +extern void force_mask_ioapic_irq_2(void); + #endif -- 2.41.0