@@ -519,6 +519,29 @@ static const struct cpufreq_driver __initconstrel hwp_cpufreq_driver =
.update = hwp_cpufreq_update,
};
+int get_hwp_para(unsigned int cpu,
+ struct xen_cppc_para *cppc_para)
+{
+ const struct hwp_drv_data *data = per_cpu(hwp_drv_data, cpu);
+
+ if ( data == NULL )
+ return -ENODATA;
+
+ cppc_para->features =
+ (feature_hwp_activity_window ? XEN_SYSCTL_CPPC_FEAT_ACT_WINDOW : 0);
+ cppc_para->lowest = data->hw.lowest;
+ cppc_para->lowest_nonlinear = data->hw.most_efficient;
+ cppc_para->nominal = data->hw.guaranteed;
+ cppc_para->highest = data->hw.highest;
+ cppc_para->minimum = data->minimum;
+ cppc_para->maximum = data->maximum;
+ cppc_para->desired = data->desired;
+ cppc_para->energy_perf = data->energy_perf;
+ cppc_para->activity_window = data->activity_window;
+
+ return 0;
+}
+
int __init hwp_register_driver(void)
{
int ret;
@@ -251,46 +251,52 @@ static int get_cpufreq_para(struct xen_sysctl_pm_op *op)
else
strlcpy(op->u.get_para.scaling_driver, "Unknown", CPUFREQ_NAME_LEN);
- if ( !(scaling_available_governors =
- xzalloc_array(char, gov_num * CPUFREQ_NAME_LEN)) )
- return -ENOMEM;
- if ( (ret = read_scaling_available_governors(scaling_available_governors,
- gov_num * CPUFREQ_NAME_LEN * sizeof(char))) )
+ if ( !strncmp(op->u.get_para.scaling_driver, XEN_HWP_DRIVER_NAME,
+ CPUFREQ_NAME_LEN) )
+ ret = get_hwp_para(policy->cpu, &op->u.get_para.u.cppc_para);
+ else
{
+ if ( !(scaling_available_governors =
+ xzalloc_array(char, gov_num * CPUFREQ_NAME_LEN)) )
+ return -ENOMEM;
+ if ( (ret = read_scaling_available_governors(
+ scaling_available_governors,
+ (gov_num * CPUFREQ_NAME_LEN *
+ sizeof(*scaling_available_governors)))) )
+ {
+ xfree(scaling_available_governors);
+ return ret;
+ }
+ ret = copy_to_guest(op->u.get_para.scaling_available_governors,
+ scaling_available_governors,
+ gov_num * CPUFREQ_NAME_LEN);
xfree(scaling_available_governors);
- return ret;
- }
- ret = copy_to_guest(op->u.get_para.scaling_available_governors,
- scaling_available_governors, gov_num * CPUFREQ_NAME_LEN);
- xfree(scaling_available_governors);
- if ( ret )
- return ret;
+ if ( ret )
+ return ret;
- op->u.get_para.u.s.scaling_cur_freq = policy->cur;
- op->u.get_para.u.s.scaling_max_freq = policy->max;
- op->u.get_para.u.s.scaling_min_freq = policy->min;
+ op->u.get_para.u.s.scaling_cur_freq = policy->cur;
+ op->u.get_para.u.s.scaling_max_freq = policy->max;
+ op->u.get_para.u.s.scaling_min_freq = policy->min;
- if ( policy->governor->name[0] )
- strlcpy(op->u.get_para.u.s.scaling_governor,
- policy->governor->name, CPUFREQ_NAME_LEN);
- else
- strlcpy(op->u.get_para.u.s.scaling_governor, "Unknown", CPUFREQ_NAME_LEN);
+ if ( policy->governor->name[0] )
+ strlcpy(op->u.get_para.u.s.scaling_governor,
+ policy->governor->name, CPUFREQ_NAME_LEN);
+ else
+ strlcpy(op->u.get_para.u.s.scaling_governor, "Unknown",
+ CPUFREQ_NAME_LEN);
- /* governor specific para */
- if ( !strncasecmp(op->u.get_para.u.s.scaling_governor,
- "userspace", CPUFREQ_NAME_LEN) )
- {
- op->u.get_para.u.s.u.userspace.scaling_setspeed = policy->cur;
- }
+ /* governor specific para */
+ if ( !strncasecmp(op->u.get_para.u.s.scaling_governor,
+ "userspace", CPUFREQ_NAME_LEN) )
+ op->u.get_para.u.s.u.userspace.scaling_setspeed = policy->cur;
- if ( !strncasecmp(op->u.get_para.u.s.scaling_governor,
- "ondemand", CPUFREQ_NAME_LEN) )
- {
- ret = get_cpufreq_ondemand_para(
- &op->u.get_para.u.s.u.ondemand.sampling_rate_max,
- &op->u.get_para.u.s.u.ondemand.sampling_rate_min,
- &op->u.get_para.u.s.u.ondemand.sampling_rate,
- &op->u.get_para.u.s.u.ondemand.up_threshold);
+ if ( !strncasecmp(op->u.get_para.u.s.scaling_governor,
+ "ondemand", CPUFREQ_NAME_LEN) )
+ ret = get_cpufreq_ondemand_para(
+ &op->u.get_para.u.s.u.ondemand.sampling_rate_max,
+ &op->u.get_para.u.s.u.ondemand.sampling_rate_min,
+ &op->u.get_para.u.s.u.ondemand.sampling_rate,
+ &op->u.get_para.u.s.u.ondemand.up_threshold);
}
return ret;
@@ -255,5 +255,7 @@ void intel_feature_detect(struct cpufreq_policy *policy);
int hwp_cmdline_parse(const char *s, const char *e);
int hwp_register_driver(void);
bool hwp_active(void);
+int get_hwp_para(unsigned int cpu,
+ struct xen_cppc_para *cppc_para);
#endif /* __XEN_CPUFREQ_PM_H__ */
@@ -296,6 +296,61 @@ struct xen_ondemand {
uint32_t up_threshold;
};
+struct xen_cppc_para {
+ /* OUT */
+ /* activity_window supported if set */
+#define XEN_SYSCTL_CPPC_FEAT_ACT_WINDOW (1 << 0)
+ uint32_t features; /* bit flags for features */
+ /*
+ * See Intel SDM: HWP Performance Range and Dynamic Capabilities
+ *
+ * These four are 0-255 hardware-provided values. They're "continuous,
+ * abstract unit-less, performance" values. Smaller numbers are slower
+ * and larger ones are faster.
+ */
+ uint32_t lowest;
+ uint32_t lowest_nonlinear; /* HWP: most_efficient */
+ uint32_t nominal; /* HWP: guaranteed */
+ uint32_t highest;
+ /*
+ * See Intel SDM: IA32_HWP_REQUEST MSR (Address: 774H Logical Processor
+ * Scope)
+ *
+ * These are all hints, and the processor may deviate outside of them.
+ * Values below are 0-255.
+ *
+ * minimum and maximum can be set to the above hardware values to constrain
+ * operation. The full range 0-255 is accepted and will be clipped by
+ * hardware.
+ */
+ uint32_t minimum;
+ uint32_t maximum;
+ /*
+ * An explicit performance hint, disabling hardware selection.
+ * 0 lets the hardware decide.
+ */
+ uint32_t desired;
+ /*
+ * Hint to hardware for energy/performance preference.
+ * 0: Performance
+ * 128: Balance (Default)
+ * 255: Powersaving
+ */
+ uint32_t energy_perf;
+ /*
+ * Activity Window is a moving history window for the processor's operation
+ * calculations, controlling responsiveness. Measured in microseconds
+ * encoded as:
+ *
+ * bits 6:0 - 7bit mantissa
+ * bits 9:7 - 3bit base-10 exponent
+ * btis 15:10 - Unused - must be 0
+ */
+#define XEN_CPPC_ACT_WINDOW_MANTISSA_MASK 0x07f
+#define XEN_CPPC_ACT_WINDOW_EXPONENT_MASK 0x380
+ uint32_t activity_window;
+};
+
#define XEN_HWP_DRIVER_NAME "hwp"
/*
@@ -333,6 +388,7 @@ struct xen_get_cpufreq_para {
struct xen_ondemand ondemand;
} u;
} s;
+ struct xen_cppc_para cppc_para;
} u;
int32_t turbo_enabled;