[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] cpufreq: Update cpufreq aperf and mperf read, so that it can be used
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1237538897 0 # Node ID 532e25fda238b3ddba22d5c93e4b1bb36e2b4cb0 # Parent c657fc593306b8423b88c55e4dc4fe9617c40e7e cpufreq: Update cpufreq aperf and mperf read, so that it can be used by both ondemand gov and user program Current __get_measured_perf read aperf and mperf MSR and then clear them for the sake of ondemand governor. This solution block user program to get aperf and mperf on their purpose. In this patch, it no longer clear aperf and mperf MSR, so that it can be used by both ondemand gov and user program. Signed-off-by: Liu, Jinsong <jinsong.liu@xxxxxxxxx> --- xen/arch/x86/acpi/cpufreq/cpufreq.c | 135 +++++++++++++++++++++++---------- xen/drivers/cpufreq/cpufreq_ondemand.c | 4 xen/drivers/cpufreq/utility.c | 28 ++++-- xen/include/acpi/cpufreq/cpufreq.h | 7 + 4 files changed, 119 insertions(+), 55 deletions(-) diff -r c657fc593306 -r 532e25fda238 xen/arch/x86/acpi/cpufreq/cpufreq.c --- a/xen/arch/x86/acpi/cpufreq/cpufreq.c Fri Mar 20 08:44:54 2009 +0000 +++ b/xen/arch/x86/acpi/cpufreq/cpufreq.c Fri Mar 20 08:48:17 2009 +0000 @@ -232,6 +232,26 @@ static u32 get_cur_val(cpumask_t mask) return cmd.val; } +struct perf_pair { + union { + struct { + uint32_t lo; + uint32_t hi; + } split; + uint64_t whole; + } aperf, mperf; +}; +static DEFINE_PER_CPU(struct perf_pair, gov_perf_pair); +static DEFINE_PER_CPU(struct perf_pair, usr_perf_pair); + +static void read_measured_perf_ctrs(void *_readin) +{ + struct perf_pair *readin = _readin; + + rdmsr(MSR_IA32_APERF, readin->aperf.split.lo, readin->aperf.split.hi); + rdmsr(MSR_IA32_MPERF, readin->mperf.split.lo, readin->mperf.split.hi); +} + /* * Return the measured active (C0) frequency on this CPU since last call * to this function. @@ -245,40 +265,13 @@ static u32 get_cur_val(cpumask_t mask) * Only IA32_APERF/IA32_MPERF ratio is architecturally defined and * no meaning should be associated with absolute values of these MSRs. */ -static void __get_measured_perf(void *perf_percent) -{ - unsigned int *ratio = perf_percent; - union { - struct { - uint32_t lo; - uint32_t hi; - } split; - uint64_t whole; - } aperf_cur, mperf_cur; - - rdmsr(MSR_IA32_APERF, aperf_cur.split.lo, aperf_cur.split.hi); - rdmsr(MSR_IA32_MPERF, mperf_cur.split.lo, mperf_cur.split.hi); - - wrmsr(MSR_IA32_APERF, 0,0); - wrmsr(MSR_IA32_MPERF, 0,0); - - if (unlikely(((unsigned long)(-1) / 100) < aperf_cur.whole)) { - int shift_count = 7; - aperf_cur.whole >>= shift_count; - mperf_cur.whole >>= shift_count; - } - - if (aperf_cur.whole && mperf_cur.whole) - *ratio = (aperf_cur.whole * 100) / mperf_cur.whole; - else - *ratio = 0; -} - -static unsigned int get_measured_perf(unsigned int cpu) -{ - struct cpufreq_policy *policy; +static unsigned int get_measured_perf(unsigned int cpu, unsigned int flag) +{ + struct cpufreq_policy *policy; + struct perf_pair readin, cur, *saved; unsigned int perf_percent; cpumask_t cpumask; + unsigned int retval; if (!cpu_online(cpu)) return 0; @@ -287,16 +280,80 @@ static unsigned int get_measured_perf(un if (!policy) return 0; - /* Usually we take the short path (no IPI) for the sake of performance. */ + switch (flag) + { + case GOV_GETAVG: + { + saved = &per_cpu(gov_perf_pair, cpu); + break; + } + case USR_GETAVG: + { + saved = &per_cpu(usr_perf_pair, cpu); + break; + } + default: + return 0; + } + if (cpu == smp_processor_id()) { - __get_measured_perf((void *)&perf_percent); + read_measured_perf_ctrs((void *)&readin); } else { cpumask = cpumask_of_cpu(cpu); - on_selected_cpus(cpumask, __get_measured_perf, - (void *)&perf_percent,0,1); - } - - return drv_data[cpu]->max_freq * perf_percent / 100; + on_selected_cpus(cpumask, read_measured_perf_ctrs, + (void *)&readin, 0, 1); + } + + cur.aperf.whole = readin.aperf.whole - saved->aperf.whole; + cur.mperf.whole = readin.mperf.whole - saved->mperf.whole; + saved->aperf.whole = readin.aperf.whole; + saved->mperf.whole = readin.mperf.whole; + +#ifdef __i386__ + /* + * We dont want to do 64 bit divide with 32 bit kernel + * Get an approximate value. Return failure in case we cannot get + * an approximate value. + */ + if (unlikely(cur.aperf.split.hi || cur.mperf.split.hi)) { + int shift_count; + uint32_t h; + + h = max_t(uint32_t, cur.aperf.split.hi, cur.mperf.split.hi); + shift_count = fls(h); + + cur.aperf.whole >>= shift_count; + cur.mperf.whole >>= shift_count; + } + + if (((unsigned long)(-1) / 100) < cur.aperf.split.lo) { + int shift_count = 7; + cur.aperf.split.lo >>= shift_count; + cur.mperf.split.lo >>= shift_count; + } + + if (cur.aperf.split.lo && cur.mperf.split.lo) + perf_percent = (cur.aperf.split.lo * 100) / cur.mperf.split.lo; + else + perf_percent = 0; + +#else + if (unlikely(((unsigned long)(-1) / 100) < cur.aperf.whole)) { + int shift_count = 7; + cur.aperf.whole >>= shift_count; + cur.mperf.whole >>= shift_count; + } + + if (cur.aperf.whole && cur.mperf.whole) + perf_percent = (cur.aperf.whole * 100) / cur.mperf.whole; + else + perf_percent = 0; + +#endif + + retval = drv_data[policy->cpu]->max_freq * perf_percent / 100; + + return retval; } static unsigned int get_cur_freq_on_cpu(unsigned int cpu) diff -r c657fc593306 -r 532e25fda238 xen/drivers/cpufreq/cpufreq_ondemand.c --- a/xen/drivers/cpufreq/cpufreq_ondemand.c Fri Mar 20 08:44:54 2009 +0000 +++ b/xen/drivers/cpufreq/cpufreq_ondemand.c Fri Mar 20 08:48:17 2009 +0000 @@ -161,9 +161,7 @@ static void dbs_check_cpu(struct cpu_dbs if (load < (dbs_tuners_ins.up_threshold - 10)) { unsigned int freq_next, freq_cur; - freq_cur = __cpufreq_driver_getavg(policy); - if (!freq_cur) - freq_cur = policy->cur; + freq_cur = cpufreq_driver_getavg(policy->cpu, GOV_GETAVG); freq_next = (freq_cur * load) / (dbs_tuners_ins.up_threshold - 10); diff -r c657fc593306 -r 532e25fda238 xen/drivers/cpufreq/utility.c --- a/xen/drivers/cpufreq/utility.c Fri Mar 20 08:44:54 2009 +0000 +++ b/xen/drivers/cpufreq/utility.c Fri Mar 20 08:48:17 2009 +0000 @@ -357,17 +357,23 @@ int __cpufreq_driver_target(struct cpufr return retval; } -int __cpufreq_driver_getavg(struct cpufreq_policy *policy) -{ - int ret = 0; - - if (!policy) - return -EINVAL; - - if (cpu_online(policy->cpu) && cpufreq_driver->getavg) - ret = cpufreq_driver->getavg(policy->cpu); - - return ret; +int cpufreq_driver_getavg(unsigned int cpu, unsigned int flag) +{ + struct cpufreq_policy *policy; + int freq_avg; + + policy = cpufreq_cpu_policy[cpu]; + if (!cpu_online(cpu) || !policy) + return 0; + + if (cpufreq_driver->getavg) + { + freq_avg = cpufreq_driver->getavg(cpu, flag); + if (freq_avg > 0) + return freq_avg; + } + + return policy->cur; } diff -r c657fc593306 -r 532e25fda238 xen/include/acpi/cpufreq/cpufreq.h --- a/xen/include/acpi/cpufreq/cpufreq.h Fri Mar 20 08:44:54 2009 +0000 +++ b/xen/include/acpi/cpufreq/cpufreq.h Fri Mar 20 08:48:17 2009 +0000 @@ -106,7 +106,10 @@ extern int __cpufreq_driver_target(struc extern int __cpufreq_driver_target(struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation); -extern int __cpufreq_driver_getavg(struct cpufreq_policy *policy); + +#define GOV_GETAVG 1 +#define USR_GETAVG 2 +extern int cpufreq_driver_getavg(unsigned int cpu, unsigned int flag); static __inline__ int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event) @@ -130,7 +133,7 @@ struct cpufreq_driver { unsigned int target_freq, unsigned int relation); unsigned int (*get)(unsigned int cpu); - unsigned int (*getavg)(unsigned int cpu); + unsigned int (*getavg)(unsigned int cpu, unsigned int flag); int (*exit)(struct cpufreq_policy *policy); }; _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |