[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] x86 Physical CPUs at different frequencies - timer error messages



> Xen *is* able to cope with TSCs running at different frequencies. It
> calibrates each CPU every few seconds on the assumption that the
> frequencies are basically stable but different. 
> 
> To integrate with PowerNow, after you've changed the 
> frequency you need to run the code to generate a new
> time record and propagate it to the VCPU of the guest
> currently using the CPU. For the frequency field, you
> are best off scaling the frequency measured in the last
> calibration period rather than assuming the new target
> frequency is precise.

Is something like this what you meant?  I'm still
getting a half dozen Time error messages every time
I increase frequency.

diff -r a70de77dd8d3 arch/i386/kernel/time-xen.c
--- a/arch/i386/kernel/time-xen.c       Tue Jul 10 10:18:24 2007 +0100
+++ b/arch/i386/kernel/time-xen.c       Thu Jul 26 15:21:38 2007 -0500
@@ -50,6 +50,7 @@
 #include <linux/percpu.h>
 #include <linux/kernel_stat.h>
 #include <linux/posix-timers.h>
+#include <linux/cpufreq.h>
 
 #include <asm/io.h>
 #include <asm/smp.h>
@@ -1118,6 +1119,95 @@ void local_teardown_timer(unsigned int c
        BUG_ON(cpu == 0);
        unbind_from_irqhandler(per_cpu(timer_irq, cpu), NULL);
 }
+#endif
+
+#if CONFIG_CPU_FREQ
+/* 
+ * cpufreq scaling handling
+ */
+static int time_cpufreq_notifier(struct notifier_block *nb, unsigned long val, 
+                               void *data)
+{
+       struct cpufreq_freqs *freq = data;
+        struct vcpu_time_info *info = &vcpu_info(freq->cpu)->time;
+       u64 new_mult;
+       char new_shift;
+
+       if (cpu_has(&cpu_data[freq->cpu], X86_FEATURE_CONSTANT_TSC))
+               return 0;
+
+       if (val == CPUFREQ_PRECHANGE)
+               return 0;
+
+       /* re order time per Ian's instructions */
+       {
+               u64 __cpu_khz = info->tsc_to_system_mul;
+               do_div(__cpu_khz, freq->new / 1000);
+               new_mult = __cpu_khz * freq->old / 1000;        
+               new_shift = info->tsc_shift;
+               while (new_mult > (1LL <<32))  {
+                       new_shift += 1;
+                       new_mult = new_mult >> 1;
+               }
+               while (new_mult < (1LL << 31)) {
+                       new_shift -= 1;
+                       new_mult = new_mult << 1;
+               }
+       }
+       do {
+               rmb();
+               info->tsc_to_system_mul = new_mult;
+               info->tsc_shift = new_shift;
+               rmb();
+       } while (info->version & 1);
+       get_time_values_from_xen(freq->cpu);
+
+       return 0;
+}
+
+static struct notifier_block time_cpufreq_notifier_block = {
+       .notifier_call = time_cpufreq_notifier
+};
+
+static int __init cpufreq_time_setup(void)
+{
+       if (!cpufreq_register_notifier(&time_cpufreq_notifier_block,
+                       CPUFREQ_TRANSITION_NOTIFIER)) {
+               printk(KERN_ERR "failed to set up cpufreq notifier\n");
+               return -ENODEV;
+       }
+       return 0;
+}
+
+core_initcall(cpufreq_time_setup);
 #endif
 
 /*



_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.