tsc-disable_B7
PATCH 1/1 tsc-disable_B7
Marcelo,
This patch enables a workaround for multi-node NUMA systems that are
experiencing gettimeofday returning "old" time values. Because these systems are frequently driven by different crystals, the CPUs vary slightly in frequency causing the TSCs to drift apart. Thus it is possible for gettimeofday to return time values behind time values already seen on another cpu. This patch allows people compiling w/ 'Multi-node NUMA support' to pass "notsc" or "bad-tsc" as boot parameters. "notsc" disables rdtsc calls, and forces the kernel to use the PIT for gettimeofday calucluations (as normally expected w/ i386 compiled kernels). While "bad-tsc" forces the kernel to use the PIT for gettimeofday, but does not disable TSC access.
Thanks to Matt Wilson for suggestions on this revision.
Comments, suggestions and flames welcome.
thanks
-john
Documentation/Configure.help +15 -1
@@ -233,7 +233,21 @@ network and embedded applications. For more information see the Axis Communication site, <http://developer.axis.com/>. -Multiquad support for NUMA systems +Multi-node support for NUMA systems +CONFIG_X86_NUMA + This option is used for getting Linux to run on a NUMA multi-node box. + Because multi-node systems suffer from unsynced TSCs, as well as TSC + drift, which can cause gettimeofday to return non-monotonic values, + this option will turn off the CONFIG_X86_TSC optimization. This + allows you to then specify "bad-tsc" as a boot option to force all nodes + to use the PIT for gettimeofday. + + Note: This does not disable access to the unsynced TSCs from userspace, + thus applications using the rdtsc instruction for timing may have + issues. To disable userspace access, instead of "bad-tsc" use the + "notsc" boot option. + +Multiquad support for NUMAQ systems CONFIG_MULTIQUAD This option is used for getting Linux to run on a (IBM/Sequent) NUMA multiquad box. This changes the way that processors are bootstrapped,
arch/i386/config.in +24 -12
@@ -80,20 +80,20 @@ define_int CONFIG_X86_L1_CACHE_SHIFT 5 define_bool CONFIG_X86_USE_STRING_486 y define_bool CONFIG_X86_ALIGNMENT_16 y - define_bool CONFIG_X86_TSC y + define_bool CONFIG_X86_HAS_TSC y define_bool CONFIG_X86_PPRO_FENCE y fi if [ "$CONFIG_M586MMX" = "y" ]; then define_int CONFIG_X86_L1_CACHE_SHIFT 5 define_bool CONFIG_X86_USE_STRING_486 y define_bool CONFIG_X86_ALIGNMENT_16 y - define_bool CONFIG_X86_TSC y + define_bool CONFIG_X86_HAS_TSC y define_bool CONFIG_X86_GOOD_APIC y define_bool CONFIG_X86_PPRO_FENCE y fi if [ "$CONFIG_M686" = "y" ]; then define_int CONFIG_X86_L1_CACHE_SHIFT 5 - define_bool CONFIG_X86_TSC y + define_bool CONFIG_X86_HAS_TSC y define_bool CONFIG_X86_GOOD_APIC y define_bool CONFIG_X86_PGE y define_bool CONFIG_X86_USE_PPRO_CHECKSUM y
@@ -101,14 +101,14 @@ fi if [ "$CONFIG_MPENTIUMIII" = "y" ]; then define_int CONFIG_X86_L1_CACHE_SHIFT 5 - define_bool CONFIG_X86_TSC y + define_bool CONFIG_X86_HAS_TSC y define_bool CONFIG_X86_GOOD_APIC y define_bool CONFIG_X86_PGE y define_bool CONFIG_X86_USE_PPRO_CHECKSUM y fi if [ "$CONFIG_MPENTIUM4" = "y" ]; then define_int CONFIG_X86_L1_CACHE_SHIFT 7 - define_bool CONFIG_X86_TSC y + define_bool CONFIG_X86_HAS_TSC y define_bool CONFIG_X86_GOOD_APIC y define_bool CONFIG_X86_PGE y define_bool CONFIG_X86_USE_PPRO_CHECKSUM y
@@ -116,12 +116,12 @@ if [ "$CONFIG_MK6" = "y" ]; then define_int CONFIG_X86_L1_CACHE_SHIFT 5 define_bool CONFIG_X86_ALIGNMENT_16 y - define_bool CONFIG_X86_TSC y + define_bool CONFIG_X86_HAS_TSC y define_bool CONFIG_X86_USE_PPRO_CHECKSUM y fi if [ "$CONFIG_MK7" = "y" ]; then define_int CONFIG_X86_L1_CACHE_SHIFT 6 - define_bool CONFIG_X86_TSC y + define_bool CONFIG_X86_HAS_TSC y define_bool CONFIG_X86_GOOD_APIC y define_bool CONFIG_X86_USE_3DNOW y define_bool CONFIG_X86_PGE y
@@ -134,14 +134,14 @@ fi if [ "$CONFIG_MCYRIXIII" = "y" ]; then define_int CONFIG_X86_L1_CACHE_SHIFT 5 - define_bool CONFIG_X86_TSC y + define_bool CONFIG_X86_HAS_TSC y define_bool CONFIG_X86_ALIGNMENT_16 y define_bool CONFIG_X86_USE_3DNOW y define_bool CONFIG_X86_USE_PPRO_CHECKSUM y fi if [ "$CONFIG_MCRUSOE" = "y" ]; then define_int CONFIG_X86_L1_CACHE_SHIFT 5 - define_bool CONFIG_X86_TSC y + define_bool CONFIG_X86_HAS_TSC y fi if [ "$CONFIG_MWINCHIPC6" = "y" ]; then define_int CONFIG_X86_L1_CACHE_SHIFT 5
@@ -152,14 +152,14 @@ if [ "$CONFIG_MWINCHIP2" = "y" ]; then define_int CONFIG_X86_L1_CACHE_SHIFT 5 define_bool CONFIG_X86_ALIGNMENT_16 y - define_bool CONFIG_X86_TSC y + define_bool CONFIG_X86_HAS_TSC y define_bool CONFIG_X86_USE_PPRO_CHECKSUM y define_bool CONFIG_X86_OOSTORE y fi if [ "$CONFIG_MWINCHIP3D" = "y" ]; then define_int CONFIG_X86_L1_CACHE_SHIFT 5 define_bool CONFIG_X86_ALIGNMENT_16 y - define_bool CONFIG_X86_TSC y + define_bool CONFIG_X86_HAS_TSC y define_bool CONFIG_X86_USE_PPRO_CHECKSUM y define_bool CONFIG_X86_OOSTORE y fi
@@ -198,8 +198,20 @@ define_bool CONFIG_X86_IO_APIC y fi else - bool 'Multiquad NUMA system' CONFIG_MULTIQUAD + bool 'Multi-node NUMA system support' CONFIG_X86_NUMA + if [ "$CONFIG_X86_NUMA" = "y" ]; then + bool 'Multiquad (IBM/Sequent) NUMAQ support' CONFIG_MULTIQUAD + fi fi + +if [ "$CONFIG_X86_HAS_TSC" = "y" ]; then + if [ "$CONFIG_X86_NUMA" = "y" ]; then + define_bool CONFIG_X86_TSC n + else + define_bool CONFIG_X86_TSC y + fi +fi + if [ "$CONFIG_SMP" = "y" -a "$CONFIG_X86_CMPXCHG" = "y" ]; then define_bool CONFIG_HAVE_DEC_LOCK y
arch/i386/kernel/time.c +16 -6
@@ -569,6 +569,15 @@#define CALIBRATE_LATCH (5 * LATCH)#define CALIBRATE_TIME (5 * 1000020/HZ) +static int bad_tsc__initdata =0 ; +static int __init bad_tsc_setup (char *str) +{ + bad_tsc =1 ; +return 1 ; +} +__setup ("bad-tsc" , bad_tsc_setup); + +static unsigned long __init calibrate_tsc (void ) {/* Set the Gate high, disable speaker */
@@ -672,16 +681,17 @@unsigned long tsc_quotient =calibrate_tsc ();if (tsc_quotient) { fast_gettimeoffset_quotient = tsc_quotient; - use_tsc =1 ;/* * We could be more selective here I suspect * and just enable this for the next intel chips ? */ - x86_udelay_tsc =1 ; -#ifndef do_gettimeoffset - do_gettimeoffset = do_fast_gettimeoffset; -#endif - +if (!bad_tsc){ + use_tsc =1 ; + x86_udelay_tsc =1 ; +#ifndef do_gettimeoffset + do_gettimeoffset = do_fast_gettimeoffset; +#endif + }/* report CPU clock rate in Hz. * The formula is (10^6 * 2^32) / (2^32 * 1 / (clocks/us)) = * clock/second. Our precision is about 100 ppm.
Documentation/Configure.help +1 -1
@@ -233,7 +233,21 @@ network and embedded applications. For more information see the Axis Communication site, <http://developer.axis.com/>. -Multiquad support for NUMA systems +Multi-node support for NUMA systems
What's the difference between CONFIG_X86_NUMA and CONFIG_MULTIQUAD?
If CONFIG_X86_NUMA is for numaq boxens please use CONFIG_X86_NUMAQ as in pat's patch.
else
- bool 'Multiquad NUMA system' CONFIG_MULTIQUAD
+ bool 'Multi-node NUMA system support' CONFIG_X86_NUMA
+ if [ "$CONFIG_X86_NUMA" = "y" ]; then
+ bool 'Multiquad (IBM/Sequent) NUMAQ support' CONFIG_MULTIQUAD
+ fi
fi
config.in files have three-space indents.
+
+if [ "$CONFIG_X86_HAS_TSC" = "y" ]; then
+ if [ "$CONFIG_X86_NUMA" = "y" ]; then
+ define_bool CONFIG_X86_TSC n
+ else
+ define_bool CONFIG_X86_TSC y
+ fi
+fi
+
+ if(!bad_tsc){
+ use_tsc = 1;
+ x86_udelay_tsc = 1;
+ #ifndef do_gettimeoffset
+ do_gettimeoffset = do_fast_gettimeoffset;
+ #endif
+ }
you want to read Documentation/CodingStyle, don't you?
Quoted 7 lines · Christoph Hellwig
(quoted diff) +1
-1-Multiquad support for NUMA systems +Multi-node support for NUMA systemsWhat's the difference between
CONFIG_X86_NUMAandCONFIG_MULTIQUAD?If
CONFIG_X86_NUMAis for numaq boxens please useCONFIG_X86_NUMAQas in pat's patch.
Well, at the moment CONFIG_MULTIQUAD ~= numaq specific stuff + generic x86 numa stuff, so James and Martin are starting to break out the generic stuff out of MULTIQUAD and put the NUMAQ specific stuff under X86_NUMAQ.
We're trying to all move to something close to:
bool 'Multi-node NUMA system support' CONFIG_X86_NUMA
if [ "$CONFIG_X86_NUMA" = "y" ]; then
#Platform Choices
bool 'Multiquad (IBM/Sequent) NUMAQ support' CONFIG_X86_NUMAQ if [ "$CONFIG_X86_NUMAQ" = "y" ]; then
define_bool CONFIG_MULTIQUAD y
define_bool CONFIG_X86_TSC_DISABLE y
fi
bool 'IBM x440 Summit support' CONFIG_X86_SUMMIT_NUMA
if [ "$CONFIG_X86_SUMMIT_NUMA" = "y" ]; then
define_bool CONFIG_X86_TSC_DISABLE y
fi
# Common NUMA Features
if [ "$CONFIG_X86_NUMAQ" = "y" -o "$CONFIG_X86_SUMMIT_NUMA" = "y" ]; then
bool 'Numa Memory Allocation Support' CONFIG_NUMA
if [ "$CONFIG_NUMA" = "y" ]; then
define_bool CONFIG_DISCONTIGMEM y
define_bool CONFIG_HAVE_ARCH_BOOTMEM_NODE y
fi
#[XXX - future]
#bool 'NUMA API support' CONFIG_WHATEVER
#bool 'Enable NUMA Scheduler' CONFIG_WHATEVER
fi
fi
Quoted 9 lines
else
(quoted diff) +4
-1- bool 'Multiquad NUMA system' CONFIG_MULTIQUAD + bool 'Multi-node NUMA system support' CONFIG_X86_NUMA + if [ "$CONFIG_X86_NUMA" = "y" ]; then + bool 'Multiquad (IBM/Sequent) NUMAQ support' CONFIG_MULTIQUAD + fi ficonfig.in files have three-space indents.
ah, thanks. fixed and attached.
Quoted 9 lines
(quoted diff) +7
-0+ if(!bad_tsc){ + use_tsc = 1; + x86_udelay_tsc = 1; + #ifndef do_gettimeoffset + do_gettimeoffset = do_fast_gettimeoffset; + #endif + }you want to read
Documentation/CodingStyle, don't you?
Always a good read :) Although outside the #ifndef inside a function (which I'm really just moving, not adding to the code), I'm not sure I see the violation in the above (although enlightenment is welcome, in whatever form it might take :).
thanks for the feedback
-john
Documentation/Configure.help +15 -1
@@ -233,7 +233,21 @@ network and embedded applications. For more information see the Axis Communication site, <http://developer.axis.com/>. -Multiquad support for NUMA systems +Multi-node support for NUMA systems +CONFIG_X86_NUMA + This option is used for getting Linux to run on a NUMA multi-node box. + Because multi-node systems suffer from unsynced TSCs, as well as TSC + drift, which can cause gettimeofday to return non-monotonic values, + this option will turn off the CONFIG_X86_TSC optimization. This + allows you to then specify "bad-tsc" as a boot option to force all nodes + to use the PIT for gettimeofday. + + Note: This does not disable access to the unsynced TSCs from userspace, + thus applications using the rdtsc instruction for timing may have + issues. To disable userspace access, instead of "bad-tsc" use the + "notsc" boot option. + +Multiquad support for NUMAQ systems CONFIG_MULTIQUAD This option is used for getting Linux to run on a (IBM/Sequent) NUMA multiquad box. This changes the way that processors are bootstrapped,
arch/i386/config.in +20 -12
@@ -80,20 +80,20 @@ define_int CONFIG_X86_L1_CACHE_SHIFT 5 define_bool CONFIG_X86_USE_STRING_486 y define_bool CONFIG_X86_ALIGNMENT_16 y - define_bool CONFIG_X86_TSC y + define_bool CONFIG_X86_HAS_TSC y define_bool CONFIG_X86_PPRO_FENCE y fi if [ "$CONFIG_M586MMX" = "y" ]; then define_int CONFIG_X86_L1_CACHE_SHIFT 5 define_bool CONFIG_X86_USE_STRING_486 y define_bool CONFIG_X86_ALIGNMENT_16 y - define_bool CONFIG_X86_TSC y + define_bool CONFIG_X86_HAS_TSC y define_bool CONFIG_X86_GOOD_APIC y define_bool CONFIG_X86_PPRO_FENCE y fi if [ "$CONFIG_M686" = "y" ]; then define_int CONFIG_X86_L1_CACHE_SHIFT 5 - define_bool CONFIG_X86_TSC y + define_bool CONFIG_X86_HAS_TSC y define_bool CONFIG_X86_GOOD_APIC y define_bool CONFIG_X86_PGE y define_bool CONFIG_X86_USE_PPRO_CHECKSUM y
@@ -101,14 +101,14 @@ fi if [ "$CONFIG_MPENTIUMIII" = "y" ]; then define_int CONFIG_X86_L1_CACHE_SHIFT 5 - define_bool CONFIG_X86_TSC y + define_bool CONFIG_X86_HAS_TSC y define_bool CONFIG_X86_GOOD_APIC y define_bool CONFIG_X86_PGE y define_bool CONFIG_X86_USE_PPRO_CHECKSUM y fi if [ "$CONFIG_MPENTIUM4" = "y" ]; then define_int CONFIG_X86_L1_CACHE_SHIFT 7 - define_bool CONFIG_X86_TSC y + define_bool CONFIG_X86_HAS_TSC y define_bool CONFIG_X86_GOOD_APIC y define_bool CONFIG_X86_PGE y define_bool CONFIG_X86_USE_PPRO_CHECKSUM y
@@ -116,12 +116,12 @@ if [ "$CONFIG_MK6" = "y" ]; then define_int CONFIG_X86_L1_CACHE_SHIFT 5 define_bool CONFIG_X86_ALIGNMENT_16 y - define_bool CONFIG_X86_TSC y + define_bool CONFIG_X86_HAS_TSC y define_bool CONFIG_X86_USE_PPRO_CHECKSUM y fi if [ "$CONFIG_MK7" = "y" ]; then define_int CONFIG_X86_L1_CACHE_SHIFT 6 - define_bool CONFIG_X86_TSC y + define_bool CONFIG_X86_HAS_TSC y define_bool CONFIG_X86_GOOD_APIC y define_bool CONFIG_X86_USE_3DNOW y define_bool CONFIG_X86_PGE y
@@ -134,14 +134,14 @@ fi if [ "$CONFIG_MCYRIXIII" = "y" ]; then define_int CONFIG_X86_L1_CACHE_SHIFT 5 - define_bool CONFIG_X86_TSC y + define_bool CONFIG_X86_HAS_TSC y define_bool CONFIG_X86_ALIGNMENT_16 y define_bool CONFIG_X86_USE_3DNOW y define_bool CONFIG_X86_USE_PPRO_CHECKSUM y fi if [ "$CONFIG_MCRUSOE" = "y" ]; then define_int CONFIG_X86_L1_CACHE_SHIFT 5 - define_bool CONFIG_X86_TSC y + define_bool CONFIG_X86_HAS_TSC y fi if [ "$CONFIG_MWINCHIPC6" = "y" ]; then define_int CONFIG_X86_L1_CACHE_SHIFT 5
@@ -152,14 +152,14 @@ if [ "$CONFIG_MWINCHIP2" = "y" ]; then define_int CONFIG_X86_L1_CACHE_SHIFT 5 define_bool CONFIG_X86_ALIGNMENT_16 y - define_bool CONFIG_X86_TSC y + define_bool CONFIG_X86_HAS_TSC y define_bool CONFIG_X86_USE_PPRO_CHECKSUM y define_bool CONFIG_X86_OOSTORE y fi if [ "$CONFIG_MWINCHIP3D" = "y" ]; then define_int CONFIG_X86_L1_CACHE_SHIFT 5 define_bool CONFIG_X86_ALIGNMENT_16 y - define_bool CONFIG_X86_TSC y + define_bool CONFIG_X86_HAS_TSC y define_bool CONFIG_X86_USE_PPRO_CHECKSUM y define_bool CONFIG_X86_OOSTORE y fi
@@ -198,8 +198,16 @@ define_bool CONFIG_X86_IO_APIC y fi else - bool 'Multiquad NUMA system' CONFIG_MULTIQUAD + bool 'Multi-node NUMA system support' CONFIG_X86_NUMA + if [ "$CONFIG_X86_NUMA" = "y" ]; then + bool 'Multiquad (IBM/Sequent) NUMAQ support' CONFIG_MULTIQUAD + fi fi + +if [ "$CONFIG_X86_NUMA" != "y" -a "$CONFIG_X86_HAS_TSC" = "y" ]; then + define_bool CONFIG_X86_TSC y +fi + if [ "$CONFIG_SMP" = "y" -a "$CONFIG_X86_CMPXCHG" = "y" ]; then define_bool CONFIG_HAVE_DEC_LOCK y
arch/i386/kernel/time.c +16 -6
@@ -569,6 +569,15 @@#define CALIBRATE_LATCH (5 * LATCH)#define CALIBRATE_TIME (5 * 1000020/HZ) +static int bad_tsc__initdata =0 ; +static int __init bad_tsc_setup (char *str) +{ + bad_tsc =1 ; +return 1 ; +} +__setup ("bad-tsc" , bad_tsc_setup); + +static unsigned long __init calibrate_tsc (void ) {/* Set the Gate high, disable speaker */
@@ -672,16 +681,17 @@unsigned long tsc_quotient =calibrate_tsc ();if (tsc_quotient) { fast_gettimeoffset_quotient = tsc_quotient; - use_tsc =1 ;/* * We could be more selective here I suspect * and just enable this for the next intel chips ? */ - x86_udelay_tsc =1 ; -#ifndef do_gettimeoffset - do_gettimeoffset = do_fast_gettimeoffset; -#endif - +if (!bad_tsc){ + use_tsc =1 ; + x86_udelay_tsc =1 ; +#ifndef do_gettimeoffset + do_gettimeoffset = do_fast_gettimeoffset; +#endif + }/* report CPU clock rate in Hz. * The formula is (10^6 * 2^32) / (2^32 * 1 / (clocks/us)) = * clock/second. Our precision is about 100 ppm.
Quoted 9 lines
Quoted 4 lines
What's the difference between
CONFIG_X86_NUMAandCONFIG_MULTIQUAD?If
CONFIG_X86_NUMAis for numaq boxens please useCONFIG_X86_NUMAQas in pat's patch.Well, at the moment
CONFIG_MULTIQUAD~= numaq specific stuff + generic x86 numa stuff, so James and Martin are starting to break out the generic stuff out of MULTIQUAD and put the NUMAQ specific stuff underX86_NUMAQ.
The current differentiation is a mess, which is my fault. CONFIG_MULTIQUAD started off life as clustered apic mode, and grew from there to be a catchall for the NUMA-Q machine. I can't help but think this is a bad idea, with the benefit of hindsight. So we'll try to convert everything to more meaningful config options, where the top level "machine type" config option turns on the support features that machine needs.
I know the following looks a little verbose, but it's fairly straightforward, and is a lot more logical than the current, errm ... mess.
I'll submit a patch to convert the existing code over unless someone screams pretty loudly (and suggests a better idea ;-))
M.
PS. Looking at the below again, we probably ought to rename the remaining CONFIG_MULTIQUAD to CONFIG_CLUSTERED_APIC or something ... but I'm sure I'll get lynched in the morning for that one.
Quoted 34 lines
We're trying to all move to something close to:
bool 'Multi-node NUMA system support'
CONFIG_X86_NUMA
if [ "$CONFIG_X86_NUMA" = "y" ]; then
#Platform Choices
bool 'Multiquad (IBM/Sequent) NUMAQ support'CONFIG_X86_NUMAQif [ "$CONFIG_X86_NUMAQ" = "y" ]; then
define_boolCONFIG_MULTIQUADy
define_boolCONFIG_X86_TSC_DISABLEy
fi
bool 'IBM x440 Summit support'CONFIG_X86_SUMMIT_NUMA
if [ "$CONFIG_X86_SUMMIT_NUMA" = "y" ]; then
define_boolCONFIG_X86_TSC_DISABLEy
fi
# Common NUMA Features
if [ "$CONFIG_X86_NUMAQ" = "y" -o "$CONFIG_X86_SUMMIT_NUMA" = "y" ]; then
bool 'Numa Memory Allocation Support'CONFIG_NUMA
if [ "$CONFIG_NUMA" = "y" ]; then
define_boolCONFIG_DISCONTIGMEMy
define_boolCONFIG_HAVE_ARCH_BOOTMEM_NODEy
fi
#[XXX - future]
#bool 'NUMA API support'CONFIG_WHATEVER
#bool 'Enable NUMA Scheduler'CONFIG_WHATEVER
fi
fiQuoted 7 lines
else
arch/i386/config.in +4
-1- bool 'Multiquad NUMA system' CONFIG_MULTIQUAD + bool 'Multi-node NUMA system support' CONFIG_X86_NUMA + if [ "$CONFIG_X86_NUMA" = "y" ]; then + bool 'Multiquad (IBM/Sequent) NUMAQ support' CONFIG_MULTIQUAD + fi fi