[PATCH] vmi: cpu cycles fix
authorZachary Amsden <zach@vmware.com>
Mon, 5 Mar 2007 08:30:36 +0000 (00:30 -0800)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Mon, 5 Mar 2007 15:57:52 +0000 (07:57 -0800)
In order to share the common code in tsc.c which does CPU Khz calibration, we
need to make an accurate value of CPU speed available to the tsc.c code.  This
value loses a lot of precision in a VM because of the timing differences with
real hardware, but we need it to be as precise as possible so the guest can
make accurate time calculations with the cycle counters.

Signed-off-by: Zachary Amsden <zach@vmware.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
arch/i386/kernel/paravirt.c
arch/i386/kernel/tsc.c
arch/i386/kernel/vmi.c
arch/i386/kernel/vmitime.c
include/asm-i386/paravirt.h
include/asm-i386/timer.h
include/asm-i386/vmi_time.h

index 31bbe70d1e021d8bcdfabb812a9c98f0e46b0e5f..8352394d5efbd7d85852893cce4660d26ba882e1 100644 (file)
@@ -522,6 +522,7 @@ struct paravirt_ops paravirt_ops = {
        .read_tsc = native_read_tsc,
        .read_pmc = native_read_pmc,
        .get_scheduled_cycles = native_read_tsc,
+       .get_cpu_khz = native_calculate_cpu_khz,
        .load_tr_desc = native_load_tr_desc,
        .set_ldt = native_set_ldt,
        .load_gdt = native_load_gdt,
index c9c9d54c91f6589e0f5ded11d7de863c2b2c76be..59222a04234b929cb98b086caaad46f021b259df 100644 (file)
@@ -117,7 +117,7 @@ unsigned long long sched_clock(void)
        return cycles_2_ns(this_offset);
 }
 
-static unsigned long calculate_cpu_khz(void)
+unsigned long native_calculate_cpu_khz(void)
 {
        unsigned long long start, end;
        unsigned long count;
index 556b9a6b7365a7e0acf6e9cb4631288c8098f8ec..acdfe69fb7ad18b4b6a146def8a54457dd91eb4b 100644 (file)
@@ -874,6 +874,7 @@ static inline int __init activate_vmi(void)
                paravirt_ops.setup_secondary_clock = vmi_timer_setup_secondary_alarm;
 #endif
                paravirt_ops.get_scheduled_cycles = vmi_get_sched_cycles;
+               paravirt_ops.get_cpu_khz = vmi_cpu_khz;
        }
        if (!disable_noidle)
                para_fill(safe_halt, Halt);
index f2aa8fab8c029dd649045649925301ec4940fbca..4bb218e2eb14a545cbee2432486a2a4533d0fa4f 100644 (file)
@@ -177,6 +177,15 @@ unsigned long long vmi_get_sched_cycles(void)
        return read_available_cycles();
 }
 
+unsigned long vmi_cpu_khz(void)
+{
+       unsigned long long khz;
+
+       khz = vmi_timer_ops.get_cycle_frequency();
+       (void)do_div(khz, 1000);
+       return khz;
+}
+
 void __init vmi_time_init(void)
 {
        unsigned long long cycles_per_sec, cycles_per_msec;
@@ -206,7 +215,6 @@ void __init vmi_time_init(void)
        (void)do_div(cycles_per_alarm, alarm_hz);
        cycles_per_msec = cycles_per_sec;
        (void)do_div(cycles_per_msec, 1000);
-       cpu_khz = cycles_per_msec;
 
        printk(KERN_WARNING "VMI timer cycles/sec = %llu ; cycles/jiffy = %llu ;"
               "cycles/alarm = %llu\n", cycles_per_sec, cycles_per_jiffy,
index a13230254f4f28f108eda7020e071c77a82e921f..a35c81480654926fdb8f4b297f6f8b1897c09e72 100644 (file)
@@ -95,6 +95,7 @@ struct paravirt_ops
        u64 (*read_tsc)(void);
        u64 (*read_pmc)(void);
        u64 (*get_scheduled_cycles)(void);
+       unsigned long (*get_cpu_khz)(void);
 
        void (*load_tr_desc)(void);
        void (*load_gdt)(const struct Xgt_desc_struct *);
@@ -275,6 +276,7 @@ static inline void halt(void)
 #define rdtscll(val) (val = paravirt_ops.read_tsc())
 
 #define get_scheduled_cycles(val) (val = paravirt_ops.get_scheduled_cycles())
+#define calculate_cpu_khz() (paravirt_ops.get_cpu_khz())
 
 #define write_tsc(val1,val2) wrmsr(0x10, val1, val2)
 
index d1f7b4f575b4abe20e9a703c5ec1d16016ab2a8a..12dd67bf760f8f270ef577b9675235aff5054283 100644 (file)
@@ -7,6 +7,7 @@
 
 void setup_pit_timer(void);
 unsigned long long native_sched_clock(void);
+unsigned long native_calculate_cpu_khz(void);
 
 /* Modifiers for buggy PIT handling */
 extern int pit_latch_buggy;
@@ -17,6 +18,7 @@ extern int recalibrate_cpu_khz(void);
 
 #ifndef CONFIG_PARAVIRT
 #define get_scheduled_cycles(val) rdtscll(val)
+#define calculate_cpu_khz() native_calculate_cpu_khz()
 #endif
 
 #endif
index f59c35d373524dcc4f2f162f23525a0fbd670e1c..1f971eb7f71eefd42cff195c3eb1baecc4ff6e5c 100644 (file)
@@ -50,6 +50,7 @@ extern void __init vmi_time_init(void);
 extern unsigned long vmi_get_wallclock(void);
 extern int vmi_set_wallclock(unsigned long now);
 extern unsigned long long vmi_get_sched_cycles(void);
+extern unsigned long vmi_cpu_khz(void);
 
 #ifdef CONFIG_X86_LOCAL_APIC
 extern void __init vmi_timer_setup_boot_alarm(void);