Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752485AbYGYPjs (ORCPT ); Fri, 25 Jul 2008 11:39:48 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1751394AbYGYPjk (ORCPT ); Fri, 25 Jul 2008 11:39:40 -0400 Received: from nf-out-0910.google.com ([64.233.182.188]:47980 "EHLO nf-out-0910.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751287AbYGYPjj (ORCPT ); Fri, 25 Jul 2008 11:39:39 -0400 DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=date:from:to:cc:subject:message-id:references:mime-version :content-type:content-disposition:in-reply-to:user-agent; b=PHcleH6VW/bamghJIC6rWnvowISPOIEttU3F3YnZiVYE3cC6JH6Fv8bqMf0hMUId/A RWVGCdEWA7bcbqeZlN6ttP8Web3CCmpnp+nOX4IRDjyQuZDgnHzL8PWvWDMGOoQL5w3f Nl4PUcrM5iR7E6GoUEqzWBZWQ9GIJK6ZGPEK4= Date: Fri, 25 Jul 2008 19:39:34 +0400 From: Cyrill Gorcunov To: Martin Wilck Cc: Thomas Gleixner , "linux-kernel@vger.kernel.org" , "H. Peter Anvin" , "Wichert, Gerhard" , "Maciej W. Rozycki" Subject: Re: [PATCH] x86 (64): make calibrate_APIC_clock() SMI-safe (take 3) Message-ID: <20080725153934.GE28466@lenovo> References: <48889C14.4070408@fujitsu-siemens.com> <4889968E.6020000@fujitsu-siemens.com> <20080725100844.GA16698@lenovo> <4889C723.7050402@fujitsu-siemens.com> <20080725125950.GA28466@lenovo> <4889D767.5050709@fujitsu-siemens.com> <20080725134831.GB28466@lenovo> <4889DCA4.4010800@fujitsu-siemens.com> <20080725150104.GD28466@lenovo> <4889ED91.7050800@fujitsu-siemens.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <4889ED91.7050800@fujitsu-siemens.com> User-Agent: Mutt/1.5.17+20080114 (2008-01-14) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 4183 Lines: 127 [Martin Wilck - Fri, Jul 25, 2008 at 05:13:21PM +0200] > Cyrill Gorcunov wrote: >> Martin, it seems you forgot to attach the patch :) > > I am sorry, here it is. Thanks :) > > Martin > > -- > Martin Wilck > PRIMERGY System Software Engineer > FSC IP ESP DEV 6 > > Fujitsu Siemens Computers GmbH > Heinz-Nixdorf-Ring 1 > 33106 Paderborn > Germany > > Tel: ++49 5251 8 15113 > Fax: ++49 5251 8 20209 > Email: mailto:martin.wilck@fujitsu-siemens.com > Internet: http://www.fujitsu-siemens.com > Company Details: http://www.fujitsu-siemens.com/imprint.html | [PATCH] x86 (64): make calibrate_APIC_clock() SMI-safe (take 3) | | Non-maskable asynchronous events (e.g. SMIs) which occur during the APIC | timer calibration can cause timer miscalibrations, sometimes by large amounts. | This patch fixes this by making sure that no significant interruption occurs | between APIC and TSC reads. SMIs may still occur at some stage in the | calibration loop, causing the loop to last longer than intended. This | doesn't matter though, as long as the start and end values are both | taken simultaneously. | | Changed wrt take 2: Use max. possible start value for the APIC timer | to avoid underflow. | | Signed-off-by: Martin Wilck | Signed-off-by: Gerhard Wichert | | --- arch/x86/kernel/apic_64.c 2008-07-25 15:39:51.000000000 +0200 | +++ arch/x86/kernel/apic_64.c.new 2008-07-25 15:55:08.000000000 +0200 | @@ -300,6 +300,31 @@ static void setup_APIC_timer(void) | } | | /* | + * Helper function for calibrate_APIC_clock(): Make sure that | + * APIC TMCTT and TSC are read at the same time, to reasonable | + * accuracy. On any sane system, the retry loop won't need more | + * than a single retry, given that the rdtsc/apic_read/rdtsc | + * sequence won't take more than a few cycles. | + */ | + | +#define MAX_DIFFERENCE 1000UL | +#define MAX_ITER 10 | +static inline int | +__read_tsc_and_apic(unsigned long *tsc, unsigned *apic) | +{ | + unsigned long tsc0, tsc1, diff; | + int i = 0; | + do { | + rdtscll(tsc0); | + *apic = apic_read(APIC_TMCCT); | + rdtscll(tsc1); | + diff = tsc1 - tsc0; | + } while (diff > MAX_DIFFERENCE && ++i < MAX_ITER); | + *tsc = tsc0 + (diff >> 1); | + return diff > MAX_DIFFERENCE ? -EIO : 0; | +} | + | +/* | * In this function we calibrate APIC bus clocks to the external | * timer. Unfortunately we cannot use jiffies and the timer irq | * to calibrate, since some later bootup code depends on getting | @@ -318,7 +343,7 @@ static void __init calibrate_APIC_clock( | { | unsigned apic, apic_start; | unsigned long tsc, tsc_start; | - int result; | + int result, err_start, err; | | local_irq_disable(); | | @@ -329,25 +354,27 @@ static void __init calibrate_APIC_clock( | * | * No interrupt enable ! | */ | - __setup_APIC_LVTT(250000000, 0, 0); | + __setup_APIC_LVTT(0xffffffff, 0, 0); | | - apic_start = apic_read(APIC_TMCCT); | #ifdef CONFIG_X86_PM_TIMER | if (apic_calibrate_pmtmr && pmtmr_ioport) { | + apic_start = apic_read(APIC_TMCCT); | pmtimer_wait(5000); /* 5ms wait */ | apic = apic_read(APIC_TMCCT); | result = (apic_start - apic) * 1000L / 5; | } else | #endif | { | - rdtscll(tsc_start); | + err_start = __read_tsc_and_apic(&tsc_start, &apic_start); | | do { | - apic = apic_read(APIC_TMCCT); | - rdtscll(tsc); | + err = __read_tsc_and_apic(&tsc, &apic); | } while ((tsc - tsc_start) < TICK_COUNT && | (apic_start - apic) < TICK_COUNT); | | + if (err_start || err) | + printk(KERN_CRIT "calibrate_APIC_clock: SMI flood - " | + "the APIC timer calibration may be wrong!\n"); | result = (apic_start - apic) * 1000L * tsc_khz / | (tsc - tsc_start); | } Thanks, Martin! Patch looks good for me (actually I would better wait for Maciej opinion since I'm not that specialist in this area). Thanks! - Cyrill - -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/