[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v1 02/11] xen/x86: introduce new sub-hypercall to get CPPC data
In order to provide backward compatibility with existing governors that represent performance as frequencies, like ondemand, the _CPC table can optionally provide processor frequency range values, Lowest frequency and Norminal frequency, to let OS use Lowest Frequency/ Performance and Nominal Frequency/Performance as anchor points to create linear mapping of CPPC abstract performance to CPU frequency. As Xen is uncapable of parsing the ACPI dynamic table, this commit introduces a new sub-hypercall to get required CPPC data from dom0 kernel. Signed-off-by: Penny Zheng <Penny.Zheng@xxxxxxx> --- xen/arch/x86/platform_hypercall.c | 6 +++ xen/arch/x86/x86_64/cpufreq.c | 18 ++++++++ xen/arch/x86/x86_64/platform_hypercall.c | 3 ++ xen/drivers/cpufreq/cpufreq.c | 50 +++++++++++++++++++++++ xen/include/acpi/cpufreq/processor_perf.h | 1 + xen/include/public/platform.h | 11 +++++ xen/include/xen/pmstat.h | 3 ++ xen/include/xlat.lst | 1 + 8 files changed, 93 insertions(+) diff --git a/xen/arch/x86/platform_hypercall.c b/xen/arch/x86/platform_hypercall.c index 67f851237d..917c395f58 100644 --- a/xen/arch/x86/platform_hypercall.c +++ b/xen/arch/x86/platform_hypercall.c @@ -572,6 +572,12 @@ ret_t do_platform_op( break; } + case XEN_PM_CPPC: + { + ret = set_cppc_pminfo(op->u.set_pminfo.id, &op->u.set_pminfo.u.cppc_data); + } + break; + default: ret = -EINVAL; break; diff --git a/xen/arch/x86/x86_64/cpufreq.c b/xen/arch/x86/x86_64/cpufreq.c index e4f3d5b436..1aa10a5dbd 100644 --- a/xen/arch/x86/x86_64/cpufreq.c +++ b/xen/arch/x86/x86_64/cpufreq.c @@ -54,3 +54,21 @@ int compat_set_px_pminfo(uint32_t acpi_id, return set_px_pminfo(acpi_id, xen_perf); } + +int compat_set_cppc_pminfo(uint32_t acpi_id, + struct compat_processor_cppc *cppc_data) +{ + struct xen_processor_cppc *xen_cppc; + unsigned long xlat_page_current; + + xlat_malloc_init(xlat_page_current); + + xen_cppc = xlat_malloc_array(xlat_page_current, + struct xen_processor_cppc, 1); + if ( unlikely(xen_cppc == NULL) ) + return -EFAULT; + + XLAT_processor_cppc(xen_cppc, cppc_data); + + return set_cppc_pminfo(acpi_id, xen_cppc); +} diff --git a/xen/arch/x86/x86_64/platform_hypercall.c b/xen/arch/x86/x86_64/platform_hypercall.c index 9ab631c17f..8c28465b8e 100644 --- a/xen/arch/x86/x86_64/platform_hypercall.c +++ b/xen/arch/x86/x86_64/platform_hypercall.c @@ -20,6 +20,9 @@ EMIT_FILE; #define xen_processor_power compat_processor_power #define set_cx_pminfo compat_set_cx_pminfo +#define xen_processor_cppc compat_processor_cppc +#define set_cppc_pminfo compat_set_cppc_pminfo + #define xen_pf_pcpuinfo xenpf_pcpuinfo CHECK_pf_pcpuinfo; #undef xen_pf_pcpuinfo diff --git a/xen/drivers/cpufreq/cpufreq.c b/xen/drivers/cpufreq/cpufreq.c index 4a103c6de9..3e3392da1b 100644 --- a/xen/drivers/cpufreq/cpufreq.c +++ b/xen/drivers/cpufreq/cpufreq.c @@ -458,6 +458,56 @@ static void print_PPC(unsigned int platform_limit) printk("\t_PPC: %d\n", platform_limit); } +static void print_CPPC(struct xen_processor_cppc *cppc_data) +{ + printk("\t_CPC: highest_perf=%u, lowest_perf=%u, " + "nominal_perf=%u, lowest_nonlinear_perf=%u, " + "nominal_freq=%uMhz, lowest_freq=%uMhz\n", + cppc_data->highest_perf, cppc_data->lowest_perf, + cppc_data->nominal_perf, cppc_data->lowest_nonlinear_perf, + cppc_data->nominal_freq, cppc_data->lowest_freq); +} + +int set_cppc_pminfo(uint32_t acpi_id, struct xen_processor_cppc *cppc_data) +{ + int ret = 0, cpuid; + struct processor_pminfo *pm_info; + + cpuid = get_cpu_id(acpi_id); + if ( cpuid < 0 || !cppc_data ) + { + ret = -EINVAL; + goto out; + } + if ( cpufreq_verbose ) + printk("Set CPU acpi_id(%d) cpuid(%d) CPPC State info:\n", + acpi_id, cpuid); + + pm_info = processor_pminfo[cpuid]; + if ( !pm_info ) + { + pm_info = xzalloc(struct processor_pminfo); + if ( !pm_info ) + { + ret = -ENOMEM; + goto out; + } + processor_pminfo[cpuid] = pm_info; + } + pm_info->acpi_id = acpi_id; + pm_info->id = cpuid; + + memcpy ((void *)&pm_info->cppc_data, + (void *)cppc_data, + sizeof(struct xen_processor_cppc)); + + if ( cpufreq_verbose ) + print_CPPC(&pm_info->cppc_data); + + out: + return ret; +} + int set_px_pminfo(uint32_t acpi_id, struct xen_processor_performance *perf) { int ret = 0, cpu; diff --git a/xen/include/acpi/cpufreq/processor_perf.h b/xen/include/acpi/cpufreq/processor_perf.h index 301104e16f..cfa0fed647 100644 --- a/xen/include/acpi/cpufreq/processor_perf.h +++ b/xen/include/acpi/cpufreq/processor_perf.h @@ -37,6 +37,7 @@ struct processor_pminfo { uint32_t acpi_id; uint32_t id; struct processor_performance perf; + struct xen_processor_cppc cppc_data; }; extern struct processor_pminfo *processor_pminfo[NR_CPUS]; diff --git a/xen/include/public/platform.h b/xen/include/public/platform.h index 2725b8d104..be1cf9a12f 100644 --- a/xen/include/public/platform.h +++ b/xen/include/public/platform.h @@ -363,6 +363,7 @@ DEFINE_XEN_GUEST_HANDLE(xenpf_getidletime_t); #define XEN_PM_PX 1 #define XEN_PM_TX 2 #define XEN_PM_PDC 3 +#define XEN_PM_CPPC 4 /* Px sub info type */ #define XEN_PX_PCT 1 @@ -432,6 +433,15 @@ struct xen_processor_px { typedef struct xen_processor_px xen_processor_px_t; DEFINE_XEN_GUEST_HANDLE(xen_processor_px_t); +struct xen_processor_cppc { + uint32_t highest_perf; + uint32_t nominal_perf; + uint32_t lowest_perf; + uint32_t lowest_nonlinear_perf; + uint32_t lowest_freq; + uint32_t nominal_freq; +}; + struct xen_psd_package { uint64_t num_entries; uint64_t revision; @@ -465,6 +475,7 @@ struct xenpf_set_processor_pminfo { struct xen_processor_power power;/* Cx: _CST/_CSD */ struct xen_processor_performance perf; /* Px: _PPC/_PCT/_PSS/_PSD */ XEN_GUEST_HANDLE(uint32) pdc; /* _PDC */ + struct xen_processor_cppc cppc_data; /*_CPC */ } u; }; typedef struct xenpf_set_processor_pminfo xenpf_set_processor_pminfo_t; diff --git a/xen/include/xen/pmstat.h b/xen/include/xen/pmstat.h index 8350403e95..7b73b123aa 100644 --- a/xen/include/xen/pmstat.h +++ b/xen/include/xen/pmstat.h @@ -5,6 +5,7 @@ #include <public/platform.h> /* for struct xen_processor_power */ #include <public/sysctl.h> /* for struct pm_cx_stat */ +int set_cppc_pminfo(uint32_t cpu, struct xen_processor_cppc *cppc_data); int set_px_pminfo(uint32_t acpi_id, struct xen_processor_performance *perf); long set_cx_pminfo(uint32_t acpi_id, struct xen_processor_power *power); @@ -13,6 +14,8 @@ struct compat_processor_performance; int compat_set_px_pminfo(uint32_t acpi_id, struct compat_processor_performance *perf); struct compat_processor_power; long compat_set_cx_pminfo(uint32_t acpi_id, struct compat_processor_power *power); +struct compat_processor_cppc; +int compat_set_cppc_pminfo(uint32_t acpi_id, struct compat_processor_cppc *cppc); #endif uint32_t pmstat_get_cx_nr(unsigned int cpu); diff --git a/xen/include/xlat.lst b/xen/include/xlat.lst index 2046b36c04..cdd0340c5e 100644 --- a/xen/include/xlat.lst +++ b/xen/include/xlat.lst @@ -166,6 +166,7 @@ ! processor_cx platform.h ! processor_flags platform.h ! processor_performance platform.h +! processor_cppc platform.h ! processor_power platform.h ? processor_px platform.h ! psd_package platform.h -- 2.34.1
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |