On 04.09.2025 08:35, Penny Zheng wrote: > @@ -50,10 +139,333 @@ int __init amd_cppc_cmdline_parse(const char *s, const > char *e) > return 0; > } > > +/* > + * If CPPC lowest_freq and nominal_freq registers are exposed then we can > + * use them to convert perf to freq and vice versa. The conversion is > + * extrapolated as an linear function passing by the 2 points: > + * - (Low perf, Low freq) > + * - (Nominal perf, Nominal freq) > + * Parameter freq is always in kHz. > + */ > +static int amd_cppc_khz_to_perf(const struct amd_cppc_drv_data *data, > + unsigned int freq, uint8_t *perf) > +{ > + const struct xen_processor_cppc *cppc_data = data->cppc_data; > + unsigned int mul, div; > + int offset = 0, res; > + > + if ( cppc_data->cpc.lowest_mhz && > + data->caps.nominal_perf > data->caps.lowest_perf && > + cppc_data->cpc.nominal_mhz > cppc_data->cpc.lowest_mhz ) > + { > + mul = data->caps.nominal_perf - data->caps.lowest_perf; > + div = cppc_data->cpc.nominal_mhz - cppc_data->cpc.lowest_mhz; > + > + /* > + * We don't need to convert to kHz for computing offset and can > + * directly use nominal_mhz and lowest_mhz as the division > + * will remove the frequency unit. > + */ > + offset = data->caps.nominal_perf - > + (mul * cppc_data->cpc.nominal_mhz) / div; > + } > + else > + { > + /* Read Processor Max Speed(MHz) as anchor point */ > + mul = data->caps.highest_perf; > + div = this_cpu(pxfreq_mhz);
How do you know you ever initialized this instance of the per-CPU variable? amd_cppc_init_msrs() may never have run for this particular CPU. > +static int cf_check amd_cppc_cpufreq_target(struct cpufreq_policy *policy, > + unsigned int target_freq, > + unsigned int relation) > +{ > + struct amd_cppc_drv_data *data = policy->u.amd_cppc; > + uint8_t des_perf; > + int res; > + > + if ( unlikely(!target_freq) ) > + return 0; > + > + res = amd_cppc_khz_to_perf(data, target_freq, &des_perf); > + if ( res ) > + return res; > + > + /* > + * Having a performance level lower than the lowest nonlinear > + * performance level, such as, lowest_perf <= perf <= > lowest_nonliner_perf, > + * may actually cause an efficiency penalty, So when deciding the > min_perf > + * value, we prefer lowest nonlinear performance over lowest performance. > + */ > + amd_cppc_write_request(policy->cpu, data, > data->caps.lowest_nonlinear_perf, > + des_perf, data->caps.highest_perf, > + /* Pre-defined BIOS value for passive mode */ > + per_cpu(epp_init, policy->cpu)); This may access per-CPU data of an offline CPU. Jan