mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Andi Kleen <ak@suse.de>
To: Joerg Roedel <joerg.roedel@amd.com>,
	linux-kernel@vger.kernel.org, patches@x86-64.org
Subject: [PATCH] [34/35] x86_64: fix cpu MHz reporting on constant_tsc cpus
Date: Sat, 28 Apr 2007 19:53:00 +0200 (CEST)	[thread overview]
Message-ID: <20070428175300.3EC6C151D1@wotan.suse.de> (raw)
In-Reply-To: <20070428752.712152000@suse.de>


From: Joerg Roedel <joerg.roedel@amd.com>

This patch fixes the reporting of cpu_mhz in /proc/cpuinfo on CPUs with
a constant TSC rate and a kernel with disabled cpufreq.

Signed-off-by: Mark Langsdorf <mark.langsdorf@amd.com>
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
Signed-off-by: Andi Kleen <ak@suse.de>

 arch/x86_64/kernel/apic.c     |    2 -
 arch/x86_64/kernel/time.c     |   58 +++++++++++++++++++++++++++++++++++++++---
 arch/x86_64/kernel/tsc.c      |   12 +++++---
 arch/x86_64/kernel/tsc_sync.c |    2 -
 include/asm-x86_64/proto.h    |    1 
 5 files changed, 65 insertions(+), 10 deletions(-)

Index: linux/arch/x86_64/kernel/apic.c
===================================================================
--- linux.orig/arch/x86_64/kernel/apic.c
+++ linux/arch/x86_64/kernel/apic.c
@@ -843,7 +843,7 @@ static int __init calibrate_APIC_clock(v
 		} while ((tsc - tsc_start) < TICK_COUNT &&
 				(apic - apic_start) < TICK_COUNT);
 
-		result = (apic_start - apic) * 1000L * cpu_khz /
+		result = (apic_start - apic) * 1000L * tsc_khz /
 					(tsc - tsc_start);
 	}
 	printk("result %d\n", result);
Index: linux/arch/x86_64/kernel/time.c
===================================================================
--- linux.orig/arch/x86_64/kernel/time.c
+++ linux/arch/x86_64/kernel/time.c
@@ -43,6 +43,7 @@
 #include <asm/apic.h>
 #include <asm/hpet.h>
 #include <asm/mpspec.h>
+#include <asm/nmi.h>
 
 static char *timename = NULL;
 
@@ -249,6 +250,51 @@ static unsigned long get_cmos_time(void)
 	return mktime(year, mon, day, hour, min, sec);
 }
 
+/* calibrate_cpu is used on systems with fixed rate TSCs to determine
+ * processor frequency */
+#define TICK_COUNT 100000000
+static unsigned int __init tsc_calibrate_cpu_khz(void)
+{
+       int tsc_start, tsc_now;
+       int i, no_ctr_free;
+       unsigned long evntsel3 = 0, pmc3 = 0, pmc_now = 0;
+       unsigned long flags;
+
+       for (i = 0; i < 4; i++)
+               if (avail_to_resrv_perfctr_nmi_bit(i))
+                       break;
+       no_ctr_free = (i == 4);
+       if (no_ctr_free) {
+               i = 3;
+               rdmsrl(MSR_K7_EVNTSEL3, evntsel3);
+               wrmsrl(MSR_K7_EVNTSEL3, 0);
+               rdmsrl(MSR_K7_PERFCTR3, pmc3);
+       } else {
+               reserve_perfctr_nmi(MSR_K7_PERFCTR0 + i);
+               reserve_evntsel_nmi(MSR_K7_EVNTSEL0 + i);
+       }
+       local_irq_save(flags);
+       /* start meauring cycles, incrementing from 0 */
+       wrmsrl(MSR_K7_PERFCTR0 + i, 0);
+       wrmsrl(MSR_K7_EVNTSEL0 + i, 1 << 22 | 3 << 16 | 0x76);
+       rdtscl(tsc_start);
+       do {
+               rdmsrl(MSR_K7_PERFCTR0 + i, pmc_now);
+               tsc_now = get_cycles_sync();
+       } while ((tsc_now - tsc_start) < TICK_COUNT);
+
+       local_irq_restore(flags);
+       if (no_ctr_free) {
+               wrmsrl(MSR_K7_EVNTSEL3, 0);
+               wrmsrl(MSR_K7_PERFCTR3, pmc3);
+               wrmsrl(MSR_K7_EVNTSEL3, evntsel3);
+       } else {
+               release_perfctr_nmi(MSR_K7_PERFCTR0 + i);
+               release_evntsel_nmi(MSR_K7_EVNTSEL0 + i);
+       }
+
+       return pmc_now * tsc_khz / (tsc_now - tsc_start);
+}
 
 /*
  * pit_calibrate_tsc() uses the speaker output (channel 2) of
@@ -336,14 +382,20 @@ void __init time_init(void)
 	if (hpet_use_timer) {
 		/* set tick_nsec to use the proper rate for HPET */
 	  	tick_nsec = TICK_NSEC_HPET;
-		cpu_khz = hpet_calibrate_tsc();
+		tsc_khz = hpet_calibrate_tsc();
 		timename = "HPET";
 	} else {
 		pit_init();
-		cpu_khz = pit_calibrate_tsc();
+		tsc_khz = pit_calibrate_tsc();
 		timename = "PIT";
 	}
 
+	cpu_khz = tsc_khz;
+	if (cpu_has(&boot_cpu_data, X86_FEATURE_CONSTANT_TSC) &&
+		boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
+		boot_cpu_data.x86 == 16)
+		cpu_khz = tsc_calibrate_cpu_khz();
+
 	if (unsynchronized_tsc())
 		mark_tsc_unstable();
 
@@ -352,7 +404,7 @@ void __init time_init(void)
 	else
 		vgetcpu_mode = VGETCPU_LSL;
 
-	set_cyc2ns_scale(cpu_khz);
+	set_cyc2ns_scale(tsc_khz);
 	printk(KERN_INFO "time.c: Detected %d.%03d MHz processor.\n",
 		cpu_khz / 1000, cpu_khz % 1000);
 	init_tsc_clocksource();
Index: linux/arch/x86_64/kernel/tsc.c
===================================================================
--- linux.orig/arch/x86_64/kernel/tsc.c
+++ linux/arch/x86_64/kernel/tsc.c
@@ -13,6 +13,8 @@ static int notsc __initdata = 0;
 
 unsigned int cpu_khz;		/* TSC clocks / usec, not used here */
 EXPORT_SYMBOL(cpu_khz);
+unsigned int tsc_khz;
+EXPORT_SYMBOL(tsc_khz);
 
 static unsigned int cyc2ns_scale __read_mostly;
 
@@ -77,7 +79,7 @@ static void handle_cpufreq_delayed_get(s
 static unsigned int  ref_freq = 0;
 static unsigned long loops_per_jiffy_ref = 0;
 
-static unsigned long cpu_khz_ref = 0;
+static unsigned long tsc_khz_ref = 0;
 
 static int time_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
 				 void *data)
@@ -99,7 +101,7 @@ static int time_cpufreq_notifier(struct 
 	if (!ref_freq) {
 		ref_freq = freq->old;
 		loops_per_jiffy_ref = *lpj;
-		cpu_khz_ref = cpu_khz;
+		tsc_khz_ref = tsc_khz;
 	}
 	if ((val == CPUFREQ_PRECHANGE  && freq->old < freq->new) ||
 		(val == CPUFREQ_POSTCHANGE && freq->old > freq->new) ||
@@ -107,12 +109,12 @@ static int time_cpufreq_notifier(struct 
 		*lpj =
 		cpufreq_scale(loops_per_jiffy_ref, ref_freq, freq->new);
 
-		cpu_khz = cpufreq_scale(cpu_khz_ref, ref_freq, freq->new);
+		tsc_khz = cpufreq_scale(tsc_khz_ref, ref_freq, freq->new);
 		if (!(freq->flags & CPUFREQ_CONST_LOOPS))
 			mark_tsc_unstable();
 	}
 
-	set_cyc2ns_scale(cpu_khz_ref);
+	set_cyc2ns_scale(tsc_khz_ref);
 
 	return 0;
 }
@@ -213,7 +215,7 @@ EXPORT_SYMBOL_GPL(mark_tsc_unstable);
 void __init init_tsc_clocksource(void)
 {
 	if (!notsc) {
-		clocksource_tsc.mult = clocksource_khz2mult(cpu_khz,
+		clocksource_tsc.mult = clocksource_khz2mult(tsc_khz,
 							clocksource_tsc.shift);
 		if (check_tsc_unstable())
 			clocksource_tsc.rating = 0;
Index: linux/arch/x86_64/kernel/tsc_sync.c
===================================================================
--- linux.orig/arch/x86_64/kernel/tsc_sync.c
+++ linux/arch/x86_64/kernel/tsc_sync.c
@@ -50,7 +50,7 @@ static __cpuinit void check_tsc_warp(voi
 	/*
 	 * The measurement runs for 20 msecs:
 	 */
-	end = start + cpu_khz * 20ULL;
+	end = start + tsc_khz * 20ULL;
 	now = start;
 
 	for (i = 0; ; i++) {
Index: linux/include/asm-x86_64/proto.h
===================================================================
--- linux.orig/include/asm-x86_64/proto.h
+++ linux/include/asm-x86_64/proto.h
@@ -92,6 +92,7 @@ extern unsigned long table_start, table_
 
 extern int exception_trace;
 extern unsigned cpu_khz;
+extern unsigned tsc_khz;
 
 extern void no_iommu_init(void);
 extern int force_iommu, no_iommu;

  parent reply	other threads:[~2007-04-28 17:53 UTC|newest]

Thread overview: 42+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-04-28 17:52 [PATCH] [0/35] Some x86 2.6.22 candidate patches for review Andi Kleen
2007-04-28 17:52 ` [PATCH] [1/35] i386: revert i386-fix-the-verify_quirk_intel_irqbalance Andi Kleen
2007-04-28 17:52 ` [PATCH] [2/35] x86_64: revert x86_64-mm-add-genapic_force Andi Kleen
2007-04-28 17:52 ` [PATCH] [3/35] x86: revert x86_64-mm-fix-the-irqbalance-quirk-for-e7320-e7520-e7525 Andi Kleen
2007-04-28 17:52 ` [PATCH] [4/35] x86_64: optimize & fix APIC mode setup Andi Kleen
2007-04-28 17:52 ` [PATCH] [5/35] x86_64: always use physical delivery mode on > 8 CPUs Andi Kleen
2007-04-28 17:52 ` [PATCH] [6/35] x86_64: remove clustered APIC mode Andi Kleen
2007-04-28 17:52 ` [PATCH] [7/35] x86: default to physical mode on hotplug CPU kernels Andi Kleen
2007-04-28 17:52 ` [PATCH] [8/35] x86_64: a memcpy that tries to reduce cache pressure Andi Kleen
2007-04-30  7:26   ` [patches] [PATCH] [8/35] x86_64: a memcpy that tries to reducecache pressure Jan Beulich
2007-04-30  9:04     ` Andi Kleen
2007-04-30 16:14       ` Bryan O'Sullivan
2007-04-30 16:25         ` Andi Kleen
2007-04-28 17:52 ` [PATCH] [9/35] i386: adjustments to page table dump during oops (v4) Andi Kleen
2007-04-28 17:52 ` [PATCH] [10/35] x86: adjust inclusion of asm/fixmap.h Andi Kleen
2007-04-28 17:52 ` [PATCH] [11/35] x86_64: adjust inclusion of asm/vsyscall32.h Andi Kleen
2007-04-28 17:52 ` [PATCH] [12/35] x86: consolidate smp_send_stop() Andi Kleen
2007-04-28 17:52 ` [PATCH] [13/35] i386: No need to use -traditional for processing asm in i386/kernel/ Andi Kleen
2007-04-28 17:52 ` [PATCH] [14/35] i386: mtrr range check correction Andi Kleen
2007-04-28 17:52 ` [PATCH] [15/35] i386: pit_latch_buggy has no effect Andi Kleen
2007-04-28 17:52 ` [PATCH] [16/35] i386: Add an option for the VIA C7 which sets appropriate L1 cache Andi Kleen
2007-04-28 18:08   ` Jeff Garzik
2007-04-28 18:28     ` Dave Jones
2007-04-28 17:52 ` [PATCH] [17/35] i386: probe_roms() cleanup Andi Kleen
2007-04-28 17:52 ` [PATCH] [18/35] x86_64: a few missing entry.S annotations Andi Kleen
2007-04-28 17:52 ` [PATCH] [19/35] i386: Add dwarf2 annotations to *_user and checksum functions Andi Kleen
2007-04-28 17:52 ` [PATCH] [20/35] x86: Fix i386 and x86_64 fault information pollution Andi Kleen
2007-04-28 17:52 ` [PATCH] [21/35] x86_64: Some cleanup in time.c Andi Kleen
2007-04-28 17:52 ` [PATCH] [22/35] i386: i386 make NMI use PERFCTR1 for architectural perfmon (take 2) Andi Kleen
2007-04-28 17:52 ` [PATCH] [23/35] x86_64: x86_64 " Andi Kleen
2007-04-28 17:52 ` [PATCH] [24/35] i386: Add __init to probe_bigsmp Andi Kleen
2007-04-28 17:52 ` [PATCH] [25/35] i386: Change sysenter_setup to __cpuinit & improve __INIT, __INITDATA Andi Kleen
2007-04-28 17:52 ` [PATCH] [26/35] x86_64: Correct max number of CPUs in Kconfig Andi Kleen
2007-04-28 17:52 ` [PATCH] [27/35] i386: Support Oprofile for AMD Family 10 CPUs Andi Kleen
2007-04-28 17:52 ` [PATCH] [28/35] x86: Drop cc-options call for all options supported in gcc 3.2+ Andi Kleen
2007-04-28 17:52 ` [PATCH] [29/35] i386: Update __copy_to_user_inatomic linuxdoc description Andi Kleen
2007-04-28 17:52 ` [PATCH] [30/35] i386: clean up mach_reboot_fixups Andi Kleen
2007-04-28 17:52 ` [PATCH] [31/35] i386: Fix usage of -mtune when X86_GENERIC=y or CONFIG_MCORE2=y Andi Kleen
2007-04-28 17:52 ` [PATCH] [32/35] x86_64: Remove unused set_seg_base Andi Kleen
2007-04-28 17:52 ` [PATCH] [33/35] x86_64: Remove duplicated code for reading control registers Andi Kleen
2007-04-28 17:53 ` Andi Kleen [this message]
2007-04-28 17:53 ` [PATCH] [35/35] i386: Simplify smp_call_function*() by using common implementation Andi Kleen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20070428175300.3EC6C151D1@wotan.suse.de \
    --to=ak@suse.de \
    --cc=joerg.roedel@amd.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=patches@x86-64.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®