[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v3 02/15] xen/x86: introduce new sub-hypercall to propagate 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 propagate required CPPC data from dom0 kernel. If the platform supports CPPC, the _CPC object must exist under all processor objects. That is, Xen is not expected to support mixed mode (CPPC & legacy PSS, _PCT, _PPC) operation, either advanced CPPC, or legacy P-states. This commit also introduces a new flag XEN_PM_CPPC to reflect processor initialised in CPPC mode. Signed-off-by: Penny Zheng <Penny.Zheng@xxxxxxx> --- v1 -> v2: - Remove unnecessary figure braces - Pointer-to-const for print_CPPC and set_cppc_pminfo - Structure allocation shall use xvzalloc() - Unnecessary memcpy(), and change it to a (type safe) structure assignment - Add comment for struct xen_processor_cppc, and keep the chosen fields in the order _CPC has them - Obey to alphabetic sorting, and prefix compat structures with ? instead of ! --- v2 -> v3: - Trim too long line - Re-place set_cppc_pminfo() past set_px_pminfo() - Fix Misra violations: Declaration and definition ought to agree in parameter names - Introduce a new flag XEN_PM_CPPC to reflect processor initialised in CPPC mode --- xen/arch/x86/platform_hypercall.c | 5 +++ xen/arch/x86/x86_64/cpufreq.c | 2 + xen/drivers/acpi/pmstat.c | 4 +- xen/drivers/cpufreq/cpufreq.c | 53 +++++++++++++++++++++-- xen/include/acpi/cpufreq/processor_perf.h | 8 ++-- xen/include/public/platform.h | 16 +++++++ xen/include/xen/pmstat.h | 2 + xen/include/xlat.lst | 1 + 8 files changed, 82 insertions(+), 9 deletions(-) diff --git a/xen/arch/x86/platform_hypercall.c b/xen/arch/x86/platform_hypercall.c index b0d98b5840..77390a0dbd 100644 --- a/xen/arch/x86/platform_hypercall.c +++ b/xen/arch/x86/platform_hypercall.c @@ -583,6 +583,11 @@ ret_t do_platform_op( &op->u.set_pminfo.u.domain_info); 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 d1b93b8eef..565e4f8652 100644 --- a/xen/arch/x86/x86_64/cpufreq.c +++ b/xen/arch/x86/x86_64/cpufreq.c @@ -26,6 +26,8 @@ #include <xen/pmstat.h> #include <compat/platform.h> +CHECK_processor_cppc; + CHECK_processor_px; CHECK_psd_package; diff --git a/xen/drivers/acpi/pmstat.c b/xen/drivers/acpi/pmstat.c index df309e27b4..c8e00766a6 100644 --- a/xen/drivers/acpi/pmstat.c +++ b/xen/drivers/acpi/pmstat.c @@ -68,7 +68,7 @@ int do_get_pm_info(struct xen_sysctl_get_pmstat *op) return -ENODEV; if ( hwp_active() ) return -EOPNOTSUPP; - if ( !pmpt || !(pmpt->perf.init & XEN_PX_INIT) ) + if ( !pmpt || !(pmpt->init & XEN_PX_INIT) ) return -EINVAL; break; default: @@ -467,7 +467,7 @@ int do_pm_op(struct xen_sysctl_pm_op *op) case CPUFREQ_PARA: if ( !(xen_processor_pmbits & XEN_PROCESSOR_PM_PX) ) return -ENODEV; - if ( !pmpt || !(pmpt->perf.init & XEN_PX_INIT) ) + if ( !pmpt || !(pmpt->init & (XEN_PX_INIT | XEN_CPPC_INIT)) ) return -EINVAL; break; } diff --git a/xen/drivers/cpufreq/cpufreq.c b/xen/drivers/cpufreq/cpufreq.c index 638476ca15..894bafebaa 100644 --- a/xen/drivers/cpufreq/cpufreq.c +++ b/xen/drivers/cpufreq/cpufreq.c @@ -210,7 +210,7 @@ int cpufreq_add_cpu(unsigned int cpu) pmpt = processor_pminfo[cpu]; - if ( !(pmpt->perf.init & XEN_PX_INIT) ) + if ( !(pmpt->init & (XEN_PX_INIT | XEN_CPPC_INIT)) ) return -EINVAL; if (!cpufreq_driver.init) @@ -368,7 +368,7 @@ int cpufreq_del_cpu(unsigned int cpu) pmpt = processor_pminfo[cpu]; - if ( !(pmpt->perf.init & XEN_PX_INIT) ) + if ( !(pmpt->init & (XEN_PX_INIT | XEN_CPPC_INIT)) ) return -EINVAL; if (!per_cpu(cpufreq_cpu_policy, cpu)) @@ -459,6 +459,16 @@ static void print_PPC(unsigned int platform_limit) printk("\t_PPC: %d\n", platform_limit); } +static void print_CPPC(const struct xen_processor_cppc *cppc_data) +{ + printk("\t_CPC: highest_perf=%u, lowest_perf=%u, " + "nominal_perf=%u, lowest_nonlinear_perf=%u, " + "nominal_mhz=%uMHz, lowest_mhz=%uMHz\n", + cppc_data->highest_perf, cppc_data->lowest_perf, + cppc_data->nominal_perf, cppc_data->lowest_nonlinear_perf, + cppc_data->nominal_mhz, cppc_data->lowest_mhz); +} + int set_px_pminfo(uint32_t acpi_id, struct xen_processor_performance *perf) { int ret = 0, cpu; @@ -539,7 +549,7 @@ int set_px_pminfo(uint32_t acpi_id, struct xen_processor_performance *perf) if ( cpufreq_verbose ) print_PPC(pxpt->platform_limit); - if ( pxpt->init == XEN_PX_INIT ) + if ( pmpt->init == XEN_PX_INIT ) { ret = cpufreq_limit_change(cpu); goto out; @@ -548,7 +558,7 @@ int set_px_pminfo(uint32_t acpi_id, struct xen_processor_performance *perf) if ( perf->flags == ( XEN_PX_PCT | XEN_PX_PSS | XEN_PX_PPC ) ) { - pxpt->init = XEN_PX_INIT; + pmpt->init = XEN_PX_INIT; ret = cpufreq_cpu_init(cpu); goto out; @@ -606,6 +616,41 @@ int set_psd_pminfo(uint32_t acpi_id, uint32_t shared_type, return ret; } +int set_cppc_pminfo(uint32_t acpi_id, + const 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]; + /* Must already allocated in set_psd_pminfo */ + if ( !pm_info ) + { + ret = -EINVAL; + goto out; + } + pm_info->cppc_data = *cppc_data; + + if ( cpufreq_verbose ) + print_CPPC(&pm_info->cppc_data); + + pm_info->init = XEN_CPPC_INIT; + ret = cpufreq_cpu_init(cpuid); + + out: + return ret; +} + static void cpufreq_cmdline_common_para(struct cpufreq_policy *new_policy) { if (usr_max_freq) diff --git a/xen/include/acpi/cpufreq/processor_perf.h b/xen/include/acpi/cpufreq/processor_perf.h index 19f5de6b08..12b6e6b826 100644 --- a/xen/include/acpi/cpufreq/processor_perf.h +++ b/xen/include/acpi/cpufreq/processor_perf.h @@ -5,7 +5,8 @@ #include <public/sysctl.h> #include <xen/acpi.h> -#define XEN_PX_INIT 0x80000000U +#define XEN_CPPC_INIT 0x40000000U +#define XEN_PX_INIT 0x80000000U unsigned int powernow_register_driver(void); unsigned int get_measured_perf(unsigned int cpu, unsigned int flag); @@ -27,8 +28,6 @@ struct processor_performance { struct xen_pct_register status_register; uint32_t state_count; struct xen_processor_px *states; - - uint32_t init; }; struct processor_pminfo { @@ -37,6 +36,9 @@ struct processor_pminfo { struct xen_psd_package domain_info; uint32_t shared_type; struct processor_performance perf; + struct xen_processor_cppc cppc_data; + + uint32_t init; }; extern struct processor_pminfo *processor_pminfo[NR_CPUS]; diff --git a/xen/include/public/platform.h b/xen/include/public/platform.h index f5c50380cb..07f4b72014 100644 --- a/xen/include/public/platform.h +++ b/xen/include/public/platform.h @@ -364,6 +364,7 @@ DEFINE_XEN_GUEST_HANDLE(xenpf_getidletime_t); #define XEN_PM_TX 2 #define XEN_PM_PDC 3 #define XEN_PM_PSD 4 +#define XEN_PM_CPPC 5 /* Px sub info type */ #define XEN_PX_PCT 1 @@ -432,6 +433,20 @@ struct xen_processor_px { typedef struct xen_processor_px xen_processor_px_t; DEFINE_XEN_GUEST_HANDLE(xen_processor_px_t); +/* + * Subset _CPC fields useful for CPPC-compatible cpufreq + * driver's initialization + */ +struct xen_processor_cppc { + uint32_t highest_perf; + uint32_t nominal_perf; + uint32_t lowest_nonlinear_perf; + uint32_t lowest_perf; + uint32_t lowest_mhz; + uint32_t nominal_mhz; +}; +typedef struct xen_processor_cppc xen_processor_cppc_t; + struct xen_psd_package { uint64_t num_entries; uint64_t revision; @@ -461,6 +476,7 @@ struct xenpf_set_processor_pminfo { xen_psd_package_t domain_info; /* _PSD */ struct xen_processor_performance perf; /* Px: _PPC/_PCT/_PSS/ */ XEN_GUEST_HANDLE(uint32) pdc; /* _PDC */ + xen_processor_cppc_t cppc_data; /*_CPC */ } u; /* Coordination type of this processor */ #define XEN_CPUPERF_SHARED_TYPE_HW 1 /* HW does needed coordination */ diff --git a/xen/include/xen/pmstat.h b/xen/include/xen/pmstat.h index fd02316ce9..c223f417fd 100644 --- a/xen/include/xen/pmstat.h +++ b/xen/include/xen/pmstat.h @@ -8,6 +8,8 @@ int set_psd_pminfo(uint32_t acpi_id, uint32_t shared_type, const struct xen_psd_package *psd_data); int set_px_pminfo(uint32_t acpi_id, struct xen_processor_performance *perf); +int set_cppc_pminfo(uint32_t acpi_id, + const struct xen_processor_cppc *cppc_data); long set_cx_pminfo(uint32_t acpi_id, struct xen_processor_power *power); #ifdef CONFIG_COMPAT diff --git a/xen/include/xlat.lst b/xen/include/xlat.lst index 0d964fe0ce..3f47552a22 100644 --- a/xen/include/xlat.lst +++ b/xen/include/xlat.lst @@ -162,6 +162,7 @@ ! pct_register platform.h ! power_register platform.h +? processor_cppc platform.h ? processor_csd platform.h ! processor_cx platform.h ! processor_flags platform.h -- 2.34.1
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |