Sophie

Sophie

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

kernel-2.6.18-194.11.1.el5.src.rpm

From: Chris Lalancette <clalance@redhat.com>
Date: Fri, 20 Mar 2009 10:23:53 +0100
Subject: [x86] vmware lazy timer emulation
Message-id: 49C360A9.3040404@redhat.com
O-Subject: [RHEL5.4 PATCH 12/14]: x86: vmware lazy timer emulation
Bugzilla: 463573
RH-Acked-by: Rik van Riel <riel@redhat.com>
RH-Acked-by: Justin M. Forbes <jforbes@redhat.com>

Make a call to the vmware magic port to enable lazy timer emulation.
Rather than holding back virtual time when timer interrupt delivery falls
behind and attempting to "catch up", in lazy mode, missed periodic
interrupts are skipped and virtual time always reflects real time.

Note that this is not needed upstream; the VMware hypervisor
detects no-HZ kernels and automatically enables this mode for them.

Fixes BZ 463573

diff --git a/arch/i386/kernel/cpu/vmware.c b/arch/i386/kernel/cpu/vmware.c
index 2d377f4..2ca3a3b 100644
--- a/arch/i386/kernel/cpu/vmware.c
+++ b/arch/i386/kernel/cpu/vmware.c
@@ -32,6 +32,7 @@
 
 #define VMWARE_PORT_CMD_GETVERSION	10
 #define VMWARE_PORT_CMD_GETHZ		45
+#define VMWARE_PORT_CMD_LAZYTIMEREMULATION 49
 
 #define VMWARE_PORT(cmd, eax, ebx, ecx, edx)				\
 	__asm__("inl (%%dx)" :						\
@@ -41,6 +42,13 @@
 			"2"(VMWARE_HYPERVISOR_PORT), "3"(UINT_MAX) :	\
 			"memory");
 
+static inline int vmware_enable_lazy_timer_emulation(void)
+{
+	uint32_t eax, ebx, ecx, edx;
+	VMWARE_PORT(LAZYTIMEREMULATION, eax, ebx, ecx, edx);
+	return ebx == VMWARE_HYPERVISOR_MAGIC;
+}
+
 static inline int __vmware_platform(void)
 {
 	uint32_t eax, ebx, ecx, edx;
@@ -90,8 +98,44 @@ int vmware_platform(void)
 
 unsigned long vmware_get_tsc_khz(void)
 {
+	unsigned long vm_tsc_khz;
+
 	BUG_ON(!vmware_platform());
-	return __vmware_get_tsc_khz();
+
+	/* Enable "lazy" timer emulation.  Rather than holding
+	 * back virtual time when timer interrupt delivery falls
+	 * behind and attempting to "catch up", in lazy mode,
+	 * missed periodic interrupts are skipped and virtual
+	 * time always reflects real time.
+	 */
+	vm_tsc_khz = __vmware_get_tsc_khz();
+
+#ifdef CONFIG_X86_64
+	{
+	extern int timekeeping_use_tsc;
+	if (vm_tsc_khz && timekeeping_use_tsc >= 0) {
+		if (vmware_enable_lazy_timer_emulation())
+			timekeeping_use_tsc = 1;
+		else {
+			printk(KERN_WARNING
+			       "time.c: failed to enable lazy timer "
+			       "emulation. Disabling tsc based "
+			       "timekeeping\n");
+			timekeeping_use_tsc = 0;
+		}
+	}
+	}
+#else
+	if (vm_tsc_khz) {
+		if (!vmware_enable_lazy_timer_emulation())
+			printk(KERN_WARNING
+			       "time.c: failed to enable lazy timer "
+			       "emulation. Disabling tsc based "
+			       "timekeeping\n");
+	}
+#endif
+
+	return vm_tsc_khz;
 }
 
 /*
diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c
index 4310ca9..7670151 100644
--- a/arch/x86_64/kernel/time.c
+++ b/arch/x86_64/kernel/time.c
@@ -99,7 +99,7 @@ struct timespec __xtime __section_xtime;
 struct timezone __sys_tz __section_sys_tz;
 
 /* -1=>disabled, 0=>autoconfigure, 1=>enabled */
-static int timekeeping_use_tsc;
+int timekeeping_use_tsc;
 static cycles_t cycles_per_tick, cycles_accounted_limit;
 
 /*