mirror of
https://github.com/torvalds/linux.git
synced 2024-12-18 09:02:17 +00:00
c8c4076723
Recent Intel chipsets including Skylake and ApolloLake have a special ITSSPRC register which allows the 8254 PIT to be gated. When gated, the 8254 registers can still be programmed as normal, but there are no IRQ0 timer interrupts. Some products such as the Connex L1430 and exone go Rugged E11 use this register to ship with the PIT gated by default. This causes Linux to fail to boot: Kernel panic - not syncing: IO-APIC + timer doesn't work! Boot with apic=debug and send a report. The panic happens before the framebuffer is initialized, so to the user, it appears as an early boot hang on a black screen. Affected products typically have a BIOS option that can be used to enable the 8254 and make Linux work (Chipset -> South Cluster Configuration -> Miscellaneous Configuration -> 8254 Clock Gating), however it would be best to make Linux support the no-8254 case. Modern sytems allow to discover the TSC and local APIC timer frequencies, so the calibration against the PIT is not required. These systems have always running timers and the local APIC timer works also in deep power states. So the setup of the PIT including the IO-APIC timer interrupt delivery checks are a pointless exercise. Skip the PIT setup and the IO-APIC timer interrupt checks on these systems, which avoids the panic caused by non ticking PITs and also speeds up the boot process. Thanks to Daniel for providing the changelog, initial analysis of the problem and testing against a variety of machines. Reported-by: Daniel Drake <drake@endlessm.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Tested-by: Daniel Drake <drake@endlessm.com> Cc: bp@alien8.de Cc: hpa@zytor.com Cc: linux@endlessm.com Cc: rafael.j.wysocki@intel.com Cc: hdegoede@redhat.com Link: https://lkml.kernel.org/r/20190628072307.24678-1-drake@endlessm.com
68 lines
1.6 KiB
C
68 lines
1.6 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* 8253/PIT functions
|
|
*
|
|
*/
|
|
#include <linux/clockchips.h>
|
|
#include <linux/init.h>
|
|
#include <linux/timex.h>
|
|
#include <linux/i8253.h>
|
|
|
|
#include <asm/apic.h>
|
|
#include <asm/hpet.h>
|
|
#include <asm/time.h>
|
|
#include <asm/smp.h>
|
|
|
|
/*
|
|
* HPET replaces the PIT, when enabled. So we need to know, which of
|
|
* the two timers is used
|
|
*/
|
|
struct clock_event_device *global_clock_event;
|
|
|
|
/*
|
|
* Modern chipsets can disable the PIT clock which makes it unusable. It
|
|
* would be possible to enable the clock but the registers are chipset
|
|
* specific and not discoverable. Avoid the whack a mole game.
|
|
*
|
|
* These platforms have discoverable TSC/CPU frequencies but this also
|
|
* requires to know the local APIC timer frequency as it normally is
|
|
* calibrated against the PIT interrupt.
|
|
*/
|
|
static bool __init use_pit(void)
|
|
{
|
|
if (!IS_ENABLED(CONFIG_X86_TSC) || !boot_cpu_has(X86_FEATURE_TSC))
|
|
return true;
|
|
|
|
/* This also returns true when APIC is disabled */
|
|
return apic_needs_pit();
|
|
}
|
|
|
|
bool __init pit_timer_init(void)
|
|
{
|
|
if (!use_pit())
|
|
return false;
|
|
|
|
clockevent_i8253_init(true);
|
|
global_clock_event = &i8253_clockevent;
|
|
return true;
|
|
}
|
|
|
|
#ifndef CONFIG_X86_64
|
|
static int __init init_pit_clocksource(void)
|
|
{
|
|
/*
|
|
* Several reasons not to register PIT as a clocksource:
|
|
*
|
|
* - On SMP PIT does not scale due to i8253_lock
|
|
* - when HPET is enabled
|
|
* - when local APIC timer is active (PIT is switched off)
|
|
*/
|
|
if (num_possible_cpus() > 1 || is_hpet_enabled() ||
|
|
!clockevent_state_periodic(&i8253_clockevent))
|
|
return 0;
|
|
|
|
return clocksource_i8253_init();
|
|
}
|
|
arch_initcall(init_pit_clocksource);
|
|
#endif /* !CONFIG_X86_64 */
|