WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

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

> 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