|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|