Mark Langsdorf
2010-Mar-01 19:10 UTC
[Xen-devel] [PATCH] Add APERF/MPERF support for AMD processors
Starting with Family 0x10, model 10 processors, some AMD processors will have support for the APERF/MPERF MSRs. This patch adds the checks necessary to support those MSRs. It also makes the get_measured_perf function defined inside cpufreq.c driver independent. The max_freq is passed to the function by the caller instead of being taking from the acpi-cpufreq only drv_data structure. Signed-off-by: Mark Langsdorf <mark.langsdorf@amd.com> diff -r c4301c2c727d xen/arch/x86/acpi/cpufreq/cpufreq.c --- a/xen/arch/x86/acpi/cpufreq/cpufreq.c Fri Feb 26 17:09:50 2010 +0000 +++ b/xen/arch/x86/acpi/cpufreq/cpufreq.c Thu Feb 25 00:54:28 2010 -0600 @@ -269,7 +269,7 @@ * Only IA32_APERF/IA32_MPERF ratio is architecturally defined and * no meaning should be associated with absolute values of these MSRs. */ -static unsigned int get_measured_perf(unsigned int cpu, unsigned int flag) +unsigned int get_measured_perf(unsigned int cpu, unsigned int flag, unsigned int max_freq) { struct cpufreq_policy *policy; struct perf_pair readin, cur, *saved; @@ -353,7 +353,7 @@ #endif - retval = drv_data[policy->cpu]->max_freq * perf_percent / 100; + retval = max_freq * perf_percent / 100; return retval; } diff -r c4301c2c727d xen/arch/x86/acpi/cpufreq/powernow.c --- a/xen/arch/x86/acpi/cpufreq/powernow.c Fri Feb 26 17:09:50 2010 +0000 +++ b/xen/arch/x86/acpi/cpufreq/powernow.c Thu Feb 25 00:54:28 2010 -0600 @@ -38,6 +38,7 @@ #include <acpi/acpi.h> #include <acpi/cpufreq/cpufreq.h> +#define CPUID_6_ECX_APERFMPERF_CAPABILITY (0x1) #define CPUID_FREQ_VOLT_CAPABILITIES 0x80000007 #define USE_HW_PSTATE 0x00000080 #define HW_PSTATE_MASK 0x00000007 @@ -58,6 +59,8 @@ }; static struct powernow_cpufreq_data *drv_data[NR_CPUS]; + +static struct cpufreq_driver powernow_cpufreq_driver; struct drv_cmd { unsigned int type; @@ -159,6 +162,7 @@ unsigned int result = 0; struct processor_performance *perf; u32 max_hw_pstate, hi = 0, lo = 0; + struct cpuinfo_x86 *c = &cpu_data[policy->cpu]; data = xmalloc(struct powernow_cpufreq_data); if (!data) @@ -234,6 +238,14 @@ if (result) goto err_freqfree; + /* Check for APERF/MPERF support in hardware */ + if (c->cpuid_level >= 6) { + unsigned int ecx; + ecx = cpuid_ecx(6); + if (ecx & CPUID_6_ECX_APERFMPERF_CAPABILITY) + powernow_cpufreq_driver.getavg = get_measured_perf; + } + /* * the first call to ->target() should result in us actually * writing something to the appropriate registers. diff -r c4301c2c727d xen/drivers/cpufreq/cpufreq_ondemand.c --- a/xen/drivers/cpufreq/cpufreq_ondemand.c Fri Feb 26 17:09:50 2010 +0000 +++ b/xen/drivers/cpufreq/cpufreq_ondemand.c Thu Feb 25 00:54:28 2010 -0600 @@ -144,7 +144,7 @@ load = 100 * (total_ns - idle_ns) / total_ns; - freq_avg = cpufreq_driver_getavg(j, GOV_GETAVG); + freq_avg = cpufreq_driver_getavg(j, GOV_GETAVG); load_freq = load * freq_avg; if (load_freq > max_load_freq) diff -r c4301c2c727d xen/drivers/cpufreq/utility.c --- a/xen/drivers/cpufreq/utility.c Fri Feb 26 17:09:50 2010 +0000 +++ b/xen/drivers/cpufreq/utility.c Thu Feb 25 00:54:28 2010 -0600 @@ -381,7 +381,9 @@ if (cpufreq_driver->getavg) { - freq_avg = cpufreq_driver->getavg(cpu, flag); + freq_avg = cpufreq_driver->getavg(cpu, flag, + policy->cpuinfo.max_freq); + if (freq_avg > 0) return freq_avg; } diff -r c4301c2c727d xen/include/acpi/cpufreq/cpufreq.h --- a/xen/include/acpi/cpufreq/cpufreq.h Fri Feb 26 17:09:50 2010 +0000 +++ b/xen/include/acpi/cpufreq/cpufreq.h Thu Feb 25 00:54:28 2010 -0600 @@ -134,7 +134,8 @@ unsigned int target_freq, unsigned int relation); unsigned int (*get)(unsigned int cpu); - unsigned int (*getavg)(unsigned int cpu, unsigned int flag); + unsigned int (*getavg)(unsigned int cpu, unsigned int flag, + unsigned int max_freq); int (*exit)(struct cpufreq_policy *policy); }; diff -r c4301c2c727d xen/include/acpi/cpufreq/processor_perf.h --- a/xen/include/acpi/cpufreq/processor_perf.h Fri Feb 26 17:09:50 2010 +0000 +++ b/xen/include/acpi/cpufreq/processor_perf.h Thu Feb 25 00:54:28 2010 -0600 @@ -9,6 +9,8 @@ int get_cpu_id(u8); int powernow_cpufreq_init(void); unsigned int powernow_register_driver(void); +unsigned int get_measured_perf(unsigned int cpu, unsigned int flag, + unsigned int max_freq); void cpufreq_residency_update(unsigned int, uint8_t); void cpufreq_statistic_update(unsigned int, uint8_t, uint8_t); _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel