mirror of
https://github.com/adulau/aha.git
synced 2024-12-28 11:46:19 +00:00
x86: Skip verification by the watchdog for TSC clocksource.
Impact: Changes timekeeping on Vmware (or with tsc=reliable). This is achieved by resetting the CLOCKSOURCE_MUST_VERIFY flag. We add a tsc=reliable commandline option to enable this. This enables legacy hardware without HPET, LAPIC, or ACPI timers to enter high-resolution timer mode. Along with that have extended this to be used in virtualization environement too. Now we also set this flag if the X86_FEATURE_TSC_RELIABLE bit is set. This is important since there is a wrap-around problem with the acpi_pm timer. The acpi_pm counter is just 24bits and this can overflow in ~4 seconds. With the NO_HZ kernels in virtualized environment, there can be situations when the guest is descheduled for longer duration, as a result we may miss the wrap of the acpi counter. When TSC is used as a clocksource and acpi_pm timer is being used as the watchdog clocksource this error in acpi_pm results in TSC being marked as unstable, and essentially results in time dropping in chunks of 4 seconds whenever this wrap is missed. Since the virtualized TSC is reliable on VMware, we should always use the TSCs clocksource on VMware, so we skip the verfication at runtime, by checking for the feature bit. Since we reset the flag for mgeode systems too, i have combined the mgeode case with the feature bit check. Signed-off-by: Jeff Hansen <jhansen@cardaccess-inc.com> Signed-off-by: Alok N Kataria <akataria@vmware.com> Signed-off-by: Dan Hecht <dhecht@vmware.com> Signed-off-by: H. Peter Anvin <hpa@zytor.com>
This commit is contained in:
parent
eca0cd028b
commit
395628ef4e
2 changed files with 29 additions and 13 deletions
|
@ -2267,6 +2267,13 @@ and is between 256 and 4096 characters. It is defined in the file
|
||||||
Format:
|
Format:
|
||||||
<io>,<irq>,<dma>,<dma2>,<sb_io>,<sb_irq>,<sb_dma>,<mpu_io>,<mpu_irq>
|
<io>,<irq>,<dma>,<dma2>,<sb_io>,<sb_irq>,<sb_dma>,<mpu_io>,<mpu_irq>
|
||||||
|
|
||||||
|
tsc= Disable clocksource-must-verify flag for TSC.
|
||||||
|
Format: <string>
|
||||||
|
[x86] reliable: mark tsc clocksource as reliable, this
|
||||||
|
disables clocksource verification at runtime.
|
||||||
|
Used to enable high-resolution timer mode on older
|
||||||
|
hardware, and in virtualized environment.
|
||||||
|
|
||||||
turbografx.map[2|3]= [HW,JOY]
|
turbografx.map[2|3]= [HW,JOY]
|
||||||
TurboGraFX parallel port interface
|
TurboGraFX parallel port interface
|
||||||
Format:
|
Format:
|
||||||
|
|
|
@ -32,6 +32,7 @@ static int tsc_unstable;
|
||||||
erroneous rdtsc usage on !cpu_has_tsc processors */
|
erroneous rdtsc usage on !cpu_has_tsc processors */
|
||||||
static int tsc_disabled = -1;
|
static int tsc_disabled = -1;
|
||||||
|
|
||||||
|
static int tsc_clocksource_reliable;
|
||||||
/*
|
/*
|
||||||
* Scheduler clock - returns current time in nanosec units.
|
* Scheduler clock - returns current time in nanosec units.
|
||||||
*/
|
*/
|
||||||
|
@ -99,6 +100,15 @@ int __init notsc_setup(char *str)
|
||||||
|
|
||||||
__setup("notsc", notsc_setup);
|
__setup("notsc", notsc_setup);
|
||||||
|
|
||||||
|
static int __init tsc_setup(char *str)
|
||||||
|
{
|
||||||
|
if (!strcmp(str, "reliable"))
|
||||||
|
tsc_clocksource_reliable = 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
__setup("tsc=", tsc_setup);
|
||||||
|
|
||||||
#define MAX_RETRIES 5
|
#define MAX_RETRIES 5
|
||||||
#define SMI_TRESHOLD 50000
|
#define SMI_TRESHOLD 50000
|
||||||
|
|
||||||
|
@ -738,24 +748,21 @@ static struct dmi_system_id __initdata bad_tsc_dmi_table[] = {
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
static void __init check_system_tsc_reliable(void)
|
||||||
* Geode_LX - the OLPC CPU has a possibly a very reliable TSC
|
|
||||||
*/
|
|
||||||
#ifdef CONFIG_MGEODE_LX
|
|
||||||
/* RTSC counts during suspend */
|
|
||||||
#define RTSC_SUSP 0x100
|
|
||||||
|
|
||||||
static void __init check_geode_tsc_reliable(void)
|
|
||||||
{
|
{
|
||||||
|
#ifdef CONFIG_MGEODE_LX
|
||||||
|
/* RTSC counts during suspend */
|
||||||
|
#define RTSC_SUSP 0x100
|
||||||
unsigned long res_low, res_high;
|
unsigned long res_low, res_high;
|
||||||
|
|
||||||
rdmsr_safe(MSR_GEODE_BUSCONT_CONF0, &res_low, &res_high);
|
rdmsr_safe(MSR_GEODE_BUSCONT_CONF0, &res_low, &res_high);
|
||||||
|
/* Geode_LX - the OLPC CPU has a possibly a very reliable TSC */
|
||||||
if (res_low & RTSC_SUSP)
|
if (res_low & RTSC_SUSP)
|
||||||
clocksource_tsc.flags &= ~CLOCK_SOURCE_MUST_VERIFY;
|
tsc_clocksource_reliable = 1;
|
||||||
}
|
|
||||||
#else
|
|
||||||
static inline void check_geode_tsc_reliable(void) { }
|
|
||||||
#endif
|
#endif
|
||||||
|
if (boot_cpu_has(X86_FEATURE_TSC_RELIABLE))
|
||||||
|
tsc_clocksource_reliable = 1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Make an educated guess if the TSC is trustworthy and synchronized
|
* Make an educated guess if the TSC is trustworthy and synchronized
|
||||||
|
@ -790,6 +797,8 @@ static void __init init_tsc_clocksource(void)
|
||||||
{
|
{
|
||||||
clocksource_tsc.mult = clocksource_khz2mult(tsc_khz,
|
clocksource_tsc.mult = clocksource_khz2mult(tsc_khz,
|
||||||
clocksource_tsc.shift);
|
clocksource_tsc.shift);
|
||||||
|
if (tsc_clocksource_reliable)
|
||||||
|
clocksource_tsc.flags &= ~CLOCK_SOURCE_MUST_VERIFY;
|
||||||
/* lower the rating if we already know its unstable: */
|
/* lower the rating if we already know its unstable: */
|
||||||
if (check_tsc_unstable()) {
|
if (check_tsc_unstable()) {
|
||||||
clocksource_tsc.rating = 0;
|
clocksource_tsc.rating = 0;
|
||||||
|
@ -850,7 +859,7 @@ void __init tsc_init(void)
|
||||||
if (unsynchronized_tsc())
|
if (unsynchronized_tsc())
|
||||||
mark_tsc_unstable("TSCs unsynchronized");
|
mark_tsc_unstable("TSCs unsynchronized");
|
||||||
|
|
||||||
check_geode_tsc_reliable();
|
check_system_tsc_reliable();
|
||||||
init_tsc_clocksource();
|
init_tsc_clocksource();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue