Sophie

Sophie

distrib > CentOS > 5 > x86_64 > by-pkgid > ea32411352494358b8d75a78402a4713 > files > 4873

kernel-2.6.18-238.19.1.el5.centos.plus.src.rpm

From: Glauber Costa <glommer@redhat.com>
Date: Thu, 1 Jul 2010 19:45:35 -0400
Subject: [time] fix softlockups in RHEL5 virt guests
Message-id: <1278013535-12710-3-git-send-email-glommer@redhat.com>
Patchwork-id: 26668
O-Subject: [RHEL5.6 PATCH 2/2] fix softlockups with RHEL5 guests
Bugzilla: 607443
RH-Acked-by: Rik van Riel <riel@redhat.com>
RH-Acked-by: Jes Sorensen <Jes.Sorensen@redhat.com>
RH-Acked-by: Marcelo Tosatti <mtosatti@redhat.com>
RH-Acked-by: Jarod Wilson <jarod@redhat.com>
RH-Acked-by: Prarit Bhargava <prarit@redhat.com>

RH-Author: Glauber Costa <glommer@redhat.com>
RH-Bugzilla: 607443
RH-Upstream-status: N/A.

Because we may account many jiffies at once with the tick divider code,
the watchdog may be fooled, and fire.

We can't touch the watchdog at the end of ticks accounting, since the
code in do_timer_jiffy() has an implicit watchdog poking that can trigger
it while we're still accounting lost ticks.

So everytime we reach a certain amount of iterations, this patch touches
the watchdog.

Signed-off-by: Glauber Costa <glommer@redhat.com>

diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c
index dfe9ec6..ed86e23 100644
--- a/arch/x86_64/kernel/time.c
+++ b/arch/x86_64/kernel/time.c
@@ -493,7 +493,7 @@ static void do_timer_account_lost_ticks(struct pt_regs *regs)
 static void do_timer_tsc_timekeeping(struct pt_regs *regs)
 {
 	int i;
-	cycles_t tsc, tsc_accounted, tsc_not_accounted;
+	cycles_t tsc, tsc_accounted, tsc_not_accounted, tsc_wd;
 	unsigned long *last = NULL;
 
 
@@ -512,11 +512,17 @@ static void do_timer_tsc_timekeeping(struct pt_regs *regs)
 
 	tsc_not_accounted = tsc - tsc_accounted;
 
+	tsc_wd = 0;
 	while (tsc_not_accounted >= cycles_per_tick) {
+		if (tsc_wd > cycles_per_tick) {
+			touch_all_softlockup_watchdogs();
+			tsc_wd = 0;
+		}
 		for (i = 0; i < tick_divider; i++)
 			do_timer_jiffy(regs);
 		tsc_not_accounted -= cycles_per_tick;
 		tsc_accounted += cycles_per_tick;
+		tsc_wd += cycles_per_tick;
 	}
 
 	if (use_kvm_time) {
@@ -1449,9 +1455,9 @@ void __init time_init(void)
 			cycles_per_tick = get_hypervisor_cycles_per_tick();
 		/*
 		 * The maximum cycles we will account per
-		 * timer interrupt is 10 minutes.
+		 * timer interrupt is 10 seconds.
 		 */
-		cycles_accounted_limit = cycles_per_tick * REAL_HZ * 60 * 10;
+		cycles_accounted_limit = cycles_per_tick * REAL_HZ * 10;
 		tick_nsec = NSEC_PER_SEC / HZ;
 		printk(KERN_INFO
 			"time.c: Using tsc for timekeeping HZ %d\n", HZ);