Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > fc11cd6e1c513a17304da94a5390f3cd > files > 1582

kernel-2.6.18-194.11.1.el5.src.rpm

From: Prarit Bhargava <prarit@redhat.com>
Date: Mon, 8 Feb 2010 16:17:45 -0500
Subject: [misc] fix APIC and TSC reads for guests
Message-id: <20100208161745.6197.5679.sendpatchset@prarit.bos.redhat.com>
Patchwork-id: 23190
O-Subject: [RHEL5]: Fix APIC & TSC reads for guests
Bugzilla: 562006
RH-Acked-by: Zachary Amsden <zamsden@redhat.com>
RH-Acked-by: Rik van Riel <riel@redhat.com>

APIC and TSC reads do take longer than 1000 cycles when done from inside the
VM, due to the hypervisor exits that need to be taken.

Bump the calibration length to 5000 cycles, and add a kernel parameter to
allow a user to modify the length.

Successfully tested by me on a guest and baremetal.

Resolves BZ 562006.

Signed-off-by: Jarod Wilson <jarod@redhat.com>

diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index f9e5c88..5887dd0 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -271,6 +271,10 @@ running once the system is up.
 			[APIC,i386, x86_64] Number of iterations during APIC
 			calibration.  Default is 10.
 
+	apiccalibrationdiff=
+			[APIC,i386, x86_64] Length of APIC calibration window.
+			Default is 5000.
+
 	apm=		[APM] Advanced Power Management
 			See header of arch/i386/kernel/apm.c.
 
diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c
index 6e05f68..ed139fc 100644
--- a/arch/i386/kernel/apic.c
+++ b/arch/i386/kernel/apic.c
@@ -1008,7 +1008,7 @@ static void __devinit setup_APIC_timer(unsigned int clocks)
 }
 
 int apic_calibration_iters __initdata = 10;
-#define MAX_DIFFERENCE 1000ULL
+int apic_calibration_diff __initdata = 5000;
 
 static inline int __init
 __read_tsc_and_apic(unsigned long long *tsc, long *apic)
@@ -1023,10 +1023,10 @@ __read_tsc_and_apic(unsigned long long *tsc, long *apic)
 		rdtsc_barrier();
 		rdtscll(tsc1);
 		diff = tsc1 - tsc0;
-	} while (diff > MAX_DIFFERENCE && ++i < apic_calibration_iters);
+	} while (diff > apic_calibration_diff && ++i < apic_calibration_iters);
 
 	*tsc = tsc0 + (diff >> 1);
-	return diff > MAX_DIFFERENCE ? -EIO : 0;
+	return diff > apic_calibration_diff ? -EIO : 0;
 }
 
 /*
@@ -1139,6 +1139,14 @@ static __init int setup_apiccalibrationiters(char *str)
 }
 __setup("apiccalibrationiters=", setup_apiccalibrationiters);
 
+static __init int setup_apiccalibrationdiff(char *str)
+{
+	get_option(&str, &apic_calibration_diff);
+	return 1;
+}
+__setup("apiccalibrationdiff=", setup_apiccalibrationdiff);
+
+
 static unsigned int calibration_result;
 
 void __init setup_boot_APIC_clock(void)
diff --git a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c
index c518f62..3a22107 100644
--- a/arch/x86_64/kernel/apic.c
+++ b/arch/x86_64/kernel/apic.c
@@ -43,6 +43,7 @@ int apic_verbosity;
 int apic_runs_main_timer;
 int apic_calibrate_pmtmr __initdata;
 int apic_calibration_iters __initdata = 10;
+int apic_calibration_diff __initdata = 5000;
 
 int disable_apic_timer __initdata;
 
@@ -770,7 +771,6 @@ static void setup_APIC_timer(unsigned int clocks)
  * than a single retry, given that the rdtsc/apic_read/rdtsc
  * sequence won't take more than a few cycles.
  */
-#define MAX_DIFFERENCE 1000UL
 static inline int __init
 __read_tsc_and_apic(unsigned long *tsc, unsigned int *apic)
 {
@@ -784,10 +784,10 @@ __read_tsc_and_apic(unsigned long *tsc, unsigned int *apic)
 		rdtsc_barrier();
 		rdtscll(tsc1);
 		diff = tsc1 - tsc0;
-	} while (diff > MAX_DIFFERENCE && ++i < apic_calibration_iters);
+	} while (diff > apic_calibration_diff && ++i < apic_calibration_iters);
 
 	*tsc = tsc0 + (diff >> 1);
-	return diff > MAX_DIFFERENCE ? -EIO : 0;
+	return diff > apic_calibration_diff ? -EIO : 0;
 }
 
 /*
@@ -1285,6 +1285,14 @@ static __init int setup_apiccalibrationiters(char *str)
 }
 __setup("apiccalibrationiters=", setup_apiccalibrationiters);
 
+static __init int setup_apiccalibrationdiff(char *str)
+{
+	get_option(&str, &apic_calibration_diff);
+	return 1;
+}
+__setup("apiccalibrationdiff=", setup_apiccalibrationdiff);
+
+
 /* dummy parsing: see setup.c */
 
 __setup("disableapic", setup_disableapic);