[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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |