* [RFC/RFT] [PATCH v2 1/6] cpufreq: intel_pstate: Cache last HWP capability/request value
2018-05-24 1:47 [RFC/RFT] [PATCH v2 0/6] Intel_pstate: HWP Dynamic performance boost Srinivas Pandruvada
@ 2018-05-24 1:47 ` Srinivas Pandruvada
2018-05-24 1:47 ` [RFC/RFT] [PATCH v2 2/6] cpufreq: intel_pstate: Add HWP boost utility functions Srinivas Pandruvada
` (4 subsequent siblings)
5 siblings, 0 replies; 12+ messages in thread
From: Srinivas Pandruvada @ 2018-05-24 1:47 UTC (permalink / raw)
To: lenb, rjw, peterz, mgorman
Cc: linux-pm, linux-kernel, juri.lelli, viresh.kumar, Srinivas Pandruvada
Store the HWP request value last set using MSR_HWP_REQUEST. This will
allow us to save cycles used for reading last HWP request value for
dynamic update of MSR_HWP_REQUEST.
Also store HWP capability MSR value in local memory, to avoid reading
MSR later for calculating limits for dynamic update of MSR_HWP_REQUEST.
Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
---
drivers/cpufreq/intel_pstate.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index 17e566afbb41..baed29c768e7 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -221,6 +221,8 @@ struct global_params {
* preference/bias
* @epp_saved: Saved EPP/EPB during system suspend or CPU offline
* operation
+ * @hwp_req_cached: Cached value of the last HWP Request MSR
+ * @hwp_cap_cached: Cached value of the last HWP Capabilities MSR
*
* This structure stores per CPU instance data for all CPUs.
*/
@@ -253,6 +255,8 @@ struct cpudata {
s16 epp_policy;
s16 epp_default;
s16 epp_saved;
+ u64 hwp_req_cached;
+ u64 hwp_cap_cached;
};
static struct cpudata **all_cpu_data;
@@ -689,6 +693,7 @@ static void intel_pstate_get_hwp_max(unsigned int cpu, int *phy_max,
u64 cap;
rdmsrl_on_cpu(cpu, MSR_HWP_CAPABILITIES, &cap);
+ WRITE_ONCE(all_cpu_data[cpu]->hwp_cap_cached, cap);
if (global.no_turbo)
*current_max = HWP_GUARANTEED_PERF(cap);
else
@@ -763,6 +768,7 @@ static void intel_pstate_hwp_set(unsigned int cpu)
intel_pstate_set_epb(cpu, epp);
}
skip_epp:
+ WRITE_ONCE(cpu_data->hwp_req_cached, value);
wrmsrl_on_cpu(cpu, MSR_HWP_REQUEST, value);
}
--
2.13.6
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [RFC/RFT] [PATCH v2 2/6] cpufreq: intel_pstate: Add HWP boost utility functions
2018-05-24 1:47 [RFC/RFT] [PATCH v2 0/6] Intel_pstate: HWP Dynamic performance boost Srinivas Pandruvada
2018-05-24 1:47 ` [RFC/RFT] [PATCH v2 1/6] cpufreq: intel_pstate: Cache last HWP capability/request value Srinivas Pandruvada
@ 2018-05-24 1:47 ` Srinivas Pandruvada
2018-05-29 7:47 ` Rafael J. Wysocki
2018-05-24 1:47 ` [RFC/RFT] [PATCH v2 3/6] cpufreq: intel_pstate: Add update_util_hook for HWP Srinivas Pandruvada
` (3 subsequent siblings)
5 siblings, 1 reply; 12+ messages in thread
From: Srinivas Pandruvada @ 2018-05-24 1:47 UTC (permalink / raw)
To: lenb, rjw, peterz, mgorman
Cc: linux-pm, linux-kernel, juri.lelli, viresh.kumar, Srinivas Pandruvada
Added two utility functions to HWP boost up gradually and boost down to
the default cached HWP request values.
Boost up:
Boost up updates HWP request minimum value in steps. This minimum value
can reach upto at HWP request maximum values depends on how frequently,
the IOWAIT flag is set. At max, boost up will take three steps to reach
the maximum, depending on the current HWP request levels and HWP
capabilities. For example, if the current settings are:
If P0 (Turbo max) = P1 (Guaranteed max) = min
No boost at all.
If P0 (Turbo max) > P1 (Guaranteed max) = min
Should result in one level boost only for P0.
If P0 (Turbo max) = P1 (Guaranteed max) > min
Should result in two level boost:
(min + p1)/2 and P1.
If P0 (Turbo max) > P1 (Guaranteed max) > min
Should result in three level boost:
(min + p1)/2, P1 and P0.
We don't set any level between P0 and P1 as there is no guarantee that
they will be honored.
Boost down:
After the system is idle for hold time of 3ms, the HWP request is reset
to the default cached value from HWP init or user modified one via sysfs.
Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
---
drivers/cpufreq/intel_pstate.c | 74 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 74 insertions(+)
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index baed29c768e7..6ad46e07cad6 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -223,6 +223,7 @@ struct global_params {
* operation
* @hwp_req_cached: Cached value of the last HWP Request MSR
* @hwp_cap_cached: Cached value of the last HWP Capabilities MSR
+ * @hwp_boost_min: Last HWP boosted min performance
*
* This structure stores per CPU instance data for all CPUs.
*/
@@ -257,6 +258,7 @@ struct cpudata {
s16 epp_saved;
u64 hwp_req_cached;
u64 hwp_cap_cached;
+ int hwp_boost_min;
};
static struct cpudata **all_cpu_data;
@@ -1387,6 +1389,78 @@ static void intel_pstate_get_cpu_pstates(struct cpudata *cpu)
intel_pstate_set_min_pstate(cpu);
}
+/*
+ * Long hold time will keep high perf limits for long time,
+ * which negatively impacts perf/watt for some workloads,
+ * like specpower. 3ms is based on experiements on some
+ * workoads.
+ */
+static int hwp_boost_hold_time_ms = 3;
+
+static inline void intel_pstate_hwp_boost_up(struct cpudata *cpu)
+{
+ u64 hwp_req = READ_ONCE(cpu->hwp_req_cached);
+ int max_limit = (hwp_req & 0xff00) >> 8;
+ int min_limit = (hwp_req & 0xff);
+ int boost_level1;
+
+ /*
+ * Cases to consider (User changes via sysfs or boot time):
+ * If, P0 (Turbo max) = P1 (Guaranteed max) = min:
+ * No boost, return.
+ * If, P0 (Turbo max) > P1 (Guaranteed max) = min:
+ * Should result in one level boost only for P0.
+ * If, P0 (Turbo max) = P1 (Guaranteed max) > min:
+ * Should result in two level boost:
+ * (min + p1)/2 and P1.
+ * If, P0 (Turbo max) > P1 (Guaranteed max) > min:
+ * Should result in three level boost:
+ * (min + p1)/2, P1 and P0.
+ */
+
+ /* If max and min are equal or already at max, nothing to boost */
+ if (max_limit == min_limit || cpu->hwp_boost_min >= max_limit)
+ return;
+
+ if (!cpu->hwp_boost_min)
+ cpu->hwp_boost_min = min_limit;
+
+ /* level at half way mark between min and guranteed */
+ boost_level1 = (HWP_GUARANTEED_PERF(cpu->hwp_cap_cached) + min_limit) >> 1;
+
+ if (cpu->hwp_boost_min < boost_level1)
+ cpu->hwp_boost_min = boost_level1;
+ else if (cpu->hwp_boost_min < HWP_GUARANTEED_PERF(cpu->hwp_cap_cached))
+ cpu->hwp_boost_min = HWP_GUARANTEED_PERF(cpu->hwp_cap_cached);
+ else if (cpu->hwp_boost_min == HWP_GUARANTEED_PERF(cpu->hwp_cap_cached) &&
+ max_limit != HWP_GUARANTEED_PERF(cpu->hwp_cap_cached))
+ cpu->hwp_boost_min = max_limit;
+ else
+ return;
+
+ hwp_req = (hwp_req & ~GENMASK_ULL(7, 0)) | cpu->hwp_boost_min;
+ wrmsrl(MSR_HWP_REQUEST, hwp_req);
+ cpu->last_update = cpu->sample.time;
+}
+
+static inline bool intel_pstate_hwp_boost_down(struct cpudata *cpu)
+{
+ if (cpu->hwp_boost_min) {
+ bool expired;
+
+ /* Check if we are idle for hold time to boost down */
+ expired = time_after64(cpu->sample.time, cpu->last_update +
+ (hwp_boost_hold_time_ms * NSEC_PER_MSEC));
+ if (expired) {
+ wrmsrl(MSR_HWP_REQUEST, cpu->hwp_req_cached);
+ cpu->hwp_boost_min = 0;
+ return true;
+ }
+ }
+
+ return false;
+}
+
static inline void intel_pstate_calc_avg_perf(struct cpudata *cpu)
{
struct sample *sample = &cpu->sample;
--
2.13.6
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [RFC/RFT] [PATCH v2 2/6] cpufreq: intel_pstate: Add HWP boost utility functions
2018-05-24 1:47 ` [RFC/RFT] [PATCH v2 2/6] cpufreq: intel_pstate: Add HWP boost utility functions Srinivas Pandruvada
@ 2018-05-29 7:47 ` Rafael J. Wysocki
0 siblings, 0 replies; 12+ messages in thread
From: Rafael J. Wysocki @ 2018-05-29 7:47 UTC (permalink / raw)
To: Srinivas Pandruvada
Cc: Len Brown, Rafael J. Wysocki, Peter Zijlstra, Mel Gorman,
Linux PM, Linux Kernel Mailing List, Juri Lelli, Viresh Kumar
On Thu, May 24, 2018 at 3:47 AM, Srinivas Pandruvada
<srinivas.pandruvada@linux.intel.com> wrote:
> Added two utility functions to HWP boost up gradually and boost down to
> the default cached HWP request values.
>
> Boost up:
> Boost up updates HWP request minimum value in steps. This minimum value
> can reach upto at HWP request maximum values depends on how frequently,
> the IOWAIT flag is set. At max, boost up will take three steps to reach
> the maximum, depending on the current HWP request levels and HWP
> capabilities. For example, if the current settings are:
> If P0 (Turbo max) = P1 (Guaranteed max) = min
> No boost at all.
> If P0 (Turbo max) > P1 (Guaranteed max) = min
> Should result in one level boost only for P0.
> If P0 (Turbo max) = P1 (Guaranteed max) > min
> Should result in two level boost:
> (min + p1)/2 and P1.
> If P0 (Turbo max) > P1 (Guaranteed max) > min
> Should result in three level boost:
> (min + p1)/2, P1 and P0.
> We don't set any level between P0 and P1 as there is no guarantee that
> they will be honored.
>
> Boost down:
> After the system is idle for hold time of 3ms, the HWP request is reset
> to the default cached value from HWP init or user modified one via sysfs.
>
> Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
> ---
> drivers/cpufreq/intel_pstate.c | 74 ++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 74 insertions(+)
>
> diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
> index baed29c768e7..6ad46e07cad6 100644
> --- a/drivers/cpufreq/intel_pstate.c
> +++ b/drivers/cpufreq/intel_pstate.c
> @@ -223,6 +223,7 @@ struct global_params {
> * operation
> * @hwp_req_cached: Cached value of the last HWP Request MSR
> * @hwp_cap_cached: Cached value of the last HWP Capabilities MSR
> + * @hwp_boost_min: Last HWP boosted min performance
> *
> * This structure stores per CPU instance data for all CPUs.
> */
> @@ -257,6 +258,7 @@ struct cpudata {
> s16 epp_saved;
> u64 hwp_req_cached;
> u64 hwp_cap_cached;
> + int hwp_boost_min;
> };
>
> static struct cpudata **all_cpu_data;
> @@ -1387,6 +1389,78 @@ static void intel_pstate_get_cpu_pstates(struct cpudata *cpu)
> intel_pstate_set_min_pstate(cpu);
> }
>
> +/*
> + * Long hold time will keep high perf limits for long time,
> + * which negatively impacts perf/watt for some workloads,
> + * like specpower. 3ms is based on experiements on some
> + * workoads.
> + */
> +static int hwp_boost_hold_time_ms = 3;
> +
> +static inline void intel_pstate_hwp_boost_up(struct cpudata *cpu)
> +{
> + u64 hwp_req = READ_ONCE(cpu->hwp_req_cached);
If user space updates the limits after this read, our decision below
may be based on a stale value, may it not?
> + int max_limit = (hwp_req & 0xff00) >> 8;
> + int min_limit = (hwp_req & 0xff);
> + int boost_level1;
> +
> + /*
> + * Cases to consider (User changes via sysfs or boot time):
> + * If, P0 (Turbo max) = P1 (Guaranteed max) = min:
> + * No boost, return.
> + * If, P0 (Turbo max) > P1 (Guaranteed max) = min:
> + * Should result in one level boost only for P0.
> + * If, P0 (Turbo max) = P1 (Guaranteed max) > min:
> + * Should result in two level boost:
> + * (min + p1)/2 and P1.
> + * If, P0 (Turbo max) > P1 (Guaranteed max) > min:
> + * Should result in three level boost:
> + * (min + p1)/2, P1 and P0.
> + */
> +
> + /* If max and min are equal or already at max, nothing to boost */
> + if (max_limit == min_limit || cpu->hwp_boost_min >= max_limit)
> + return;
> +
> + if (!cpu->hwp_boost_min)
> + cpu->hwp_boost_min = min_limit;
> +
> + /* level at half way mark between min and guranteed */
> + boost_level1 = (HWP_GUARANTEED_PERF(cpu->hwp_cap_cached) + min_limit) >> 1;
> +
> + if (cpu->hwp_boost_min < boost_level1)
> + cpu->hwp_boost_min = boost_level1;
> + else if (cpu->hwp_boost_min < HWP_GUARANTEED_PERF(cpu->hwp_cap_cached))
> + cpu->hwp_boost_min = HWP_GUARANTEED_PERF(cpu->hwp_cap_cached);
> + else if (cpu->hwp_boost_min == HWP_GUARANTEED_PERF(cpu->hwp_cap_cached) &&
> + max_limit != HWP_GUARANTEED_PERF(cpu->hwp_cap_cached))
> + cpu->hwp_boost_min = max_limit;
> + else
> + return;
> +
> + hwp_req = (hwp_req & ~GENMASK_ULL(7, 0)) | cpu->hwp_boost_min;
> + wrmsrl(MSR_HWP_REQUEST, hwp_req);
> + cpu->last_update = cpu->sample.time;
> +}
> +
> +static inline bool intel_pstate_hwp_boost_down(struct cpudata *cpu)
> +{
> + if (cpu->hwp_boost_min) {
> + bool expired;
> +
> + /* Check if we are idle for hold time to boost down */
> + expired = time_after64(cpu->sample.time, cpu->last_update +
> + (hwp_boost_hold_time_ms * NSEC_PER_MSEC));
> + if (expired) {
> + wrmsrl(MSR_HWP_REQUEST, cpu->hwp_req_cached);
> + cpu->hwp_boost_min = 0;
> + return true;
> + }
> + }
> +
> + return false;
> +}
> +
> static inline void intel_pstate_calc_avg_perf(struct cpudata *cpu)
> {
> struct sample *sample = &cpu->sample;
> --
> 2.13.6
>
^ permalink raw reply [flat|nested] 12+ messages in thread
* [RFC/RFT] [PATCH v2 3/6] cpufreq: intel_pstate: Add update_util_hook for HWP
2018-05-24 1:47 [RFC/RFT] [PATCH v2 0/6] Intel_pstate: HWP Dynamic performance boost Srinivas Pandruvada
2018-05-24 1:47 ` [RFC/RFT] [PATCH v2 1/6] cpufreq: intel_pstate: Cache last HWP capability/request value Srinivas Pandruvada
2018-05-24 1:47 ` [RFC/RFT] [PATCH v2 2/6] cpufreq: intel_pstate: Add HWP boost utility functions Srinivas Pandruvada
@ 2018-05-24 1:47 ` Srinivas Pandruvada
2018-05-29 7:37 ` Rafael J. Wysocki
2018-05-24 1:47 ` [RFC/RFT] [PATCH v2 4/6] cpufreq: intel_pstate: HWP boost performance on IO wakeup Srinivas Pandruvada
` (2 subsequent siblings)
5 siblings, 1 reply; 12+ messages in thread
From: Srinivas Pandruvada @ 2018-05-24 1:47 UTC (permalink / raw)
To: lenb, rjw, peterz, mgorman
Cc: linux-pm, linux-kernel, juri.lelli, viresh.kumar, Srinivas Pandruvada
When HWP dynamic boost is active then set the HWP specific update util
hook.
Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
---
drivers/cpufreq/intel_pstate.c | 21 +++++++++++++++++----
1 file changed, 17 insertions(+), 4 deletions(-)
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index 6ad46e07cad6..382160570b5f 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -291,6 +291,7 @@ static struct pstate_funcs pstate_funcs __read_mostly;
static int hwp_active __read_mostly;
static bool per_cpu_limits __read_mostly;
+static bool hwp_boost __read_mostly;
static struct cpufreq_driver *intel_pstate_driver __read_mostly;
@@ -1461,6 +1462,11 @@ static inline bool intel_pstate_hwp_boost_down(struct cpudata *cpu)
return false;
}
+static inline void intel_pstate_update_util_hwp(struct update_util_data *data,
+ u64 time, unsigned int flags)
+{
+}
+
static inline void intel_pstate_calc_avg_perf(struct cpudata *cpu)
{
struct sample *sample = &cpu->sample;
@@ -1764,7 +1770,7 @@ static void intel_pstate_set_update_util_hook(unsigned int cpu_num)
{
struct cpudata *cpu = all_cpu_data[cpu_num];
- if (hwp_active)
+ if (hwp_active && !hwp_boost)
return;
if (cpu->update_util_set)
@@ -1772,8 +1778,12 @@ static void intel_pstate_set_update_util_hook(unsigned int cpu_num)
/* Prevent intel_pstate_update_util() from using stale data. */
cpu->sample.time = 0;
- cpufreq_add_update_util_hook(cpu_num, &cpu->update_util,
- intel_pstate_update_util);
+ if (hwp_active)
+ cpufreq_add_update_util_hook(cpu_num, &cpu->update_util,
+ intel_pstate_update_util_hwp);
+ else
+ cpufreq_add_update_util_hook(cpu_num, &cpu->update_util,
+ intel_pstate_update_util);
cpu->update_util_set = true;
}
@@ -1885,8 +1895,11 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy)
intel_pstate_set_update_util_hook(policy->cpu);
}
- if (hwp_active)
+ if (hwp_active) {
+ if (!hwp_boost)
+ intel_pstate_clear_update_util_hook(policy->cpu);
intel_pstate_hwp_set(policy->cpu);
+ }
mutex_unlock(&intel_pstate_limits_lock);
--
2.13.6
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [RFC/RFT] [PATCH v2 3/6] cpufreq: intel_pstate: Add update_util_hook for HWP
2018-05-24 1:47 ` [RFC/RFT] [PATCH v2 3/6] cpufreq: intel_pstate: Add update_util_hook for HWP Srinivas Pandruvada
@ 2018-05-29 7:37 ` Rafael J. Wysocki
2018-05-29 22:17 ` Srinivas Pandruvada
0 siblings, 1 reply; 12+ messages in thread
From: Rafael J. Wysocki @ 2018-05-29 7:37 UTC (permalink / raw)
To: Srinivas Pandruvada
Cc: Len Brown, Rafael J. Wysocki, Peter Zijlstra, Mel Gorman,
Linux PM, Linux Kernel Mailing List, Juri Lelli, Viresh Kumar
On Thu, May 24, 2018 at 3:47 AM, Srinivas Pandruvada
<srinivas.pandruvada@linux.intel.com> wrote:
> When HWP dynamic boost is active then set the HWP specific update util
> hook.
>
> Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
Splitting this patch out of the next one is sort of artificial.
> ---
> drivers/cpufreq/intel_pstate.c | 21 +++++++++++++++++----
> 1 file changed, 17 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
> index 6ad46e07cad6..382160570b5f 100644
> --- a/drivers/cpufreq/intel_pstate.c
> +++ b/drivers/cpufreq/intel_pstate.c
> @@ -291,6 +291,7 @@ static struct pstate_funcs pstate_funcs __read_mostly;
>
> static int hwp_active __read_mostly;
> static bool per_cpu_limits __read_mostly;
> +static bool hwp_boost __read_mostly;
Because of this, among other things.
>
> static struct cpufreq_driver *intel_pstate_driver __read_mostly;
>
> @@ -1461,6 +1462,11 @@ static inline bool intel_pstate_hwp_boost_down(struct cpudata *cpu)
> return false;
> }
>
> +static inline void intel_pstate_update_util_hwp(struct update_util_data *data,
> + u64 time, unsigned int flags)
> +{
> +}
> +
> static inline void intel_pstate_calc_avg_perf(struct cpudata *cpu)
> {
> struct sample *sample = &cpu->sample;
> @@ -1764,7 +1770,7 @@ static void intel_pstate_set_update_util_hook(unsigned int cpu_num)
> {
> struct cpudata *cpu = all_cpu_data[cpu_num];
>
> - if (hwp_active)
> + if (hwp_active && !hwp_boost)
> return;
>
> if (cpu->update_util_set)
> @@ -1772,8 +1778,12 @@ static void intel_pstate_set_update_util_hook(unsigned int cpu_num)
>
> /* Prevent intel_pstate_update_util() from using stale data. */
> cpu->sample.time = 0;
> - cpufreq_add_update_util_hook(cpu_num, &cpu->update_util,
> - intel_pstate_update_util);
> + if (hwp_active)
> + cpufreq_add_update_util_hook(cpu_num, &cpu->update_util,
> + intel_pstate_update_util_hwp);
> + else
> + cpufreq_add_update_util_hook(cpu_num, &cpu->update_util,
> + intel_pstate_update_util);
> cpu->update_util_set = true;
> }
>
> @@ -1885,8 +1895,11 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy)
> intel_pstate_set_update_util_hook(policy->cpu);
> }
>
> - if (hwp_active)
> + if (hwp_active) {
> + if (!hwp_boost)
> + intel_pstate_clear_update_util_hook(policy->cpu);
> intel_pstate_hwp_set(policy->cpu);
> + }
>
> mutex_unlock(&intel_pstate_limits_lock);
>
> --
> 2.13.6
>
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [RFC/RFT] [PATCH v2 3/6] cpufreq: intel_pstate: Add update_util_hook for HWP
2018-05-29 7:37 ` Rafael J. Wysocki
@ 2018-05-29 22:17 ` Srinivas Pandruvada
0 siblings, 0 replies; 12+ messages in thread
From: Srinivas Pandruvada @ 2018-05-29 22:17 UTC (permalink / raw)
To: Rafael J. Wysocki
Cc: Len Brown, Rafael J. Wysocki, Peter Zijlstra, Mel Gorman,
Linux PM, Linux Kernel Mailing List, Juri Lelli, Viresh Kumar
On Tue, 2018-05-29 at 09:37 +0200, Rafael J. Wysocki wrote:
> On Thu, May 24, 2018 at 3:47 AM, Srinivas Pandruvada
> <srinivas.pandruvada@linux.intel.com> wrote:
> > When HWP dynamic boost is active then set the HWP specific update
> > util
> > hook.
> >
> > Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel
> > .com>
>
> Splitting this patch out of the next one is sort of artificial.
I will merge to the patch where the hwp_boost is getting used.
Thanks,
Srinivas
>
> > ---
> > drivers/cpufreq/intel_pstate.c | 21 +++++++++++++++++----
> > 1 file changed, 17 insertions(+), 4 deletions(-)
> >
> > diff --git a/drivers/cpufreq/intel_pstate.c
> > b/drivers/cpufreq/intel_pstate.c
> > index 6ad46e07cad6..382160570b5f 100644
> > --- a/drivers/cpufreq/intel_pstate.c
> > +++ b/drivers/cpufreq/intel_pstate.c
> > @@ -291,6 +291,7 @@ static struct pstate_funcs pstate_funcs
> > __read_mostly;
> >
> > static int hwp_active __read_mostly;
> > static bool per_cpu_limits __read_mostly;
> > +static bool hwp_boost __read_mostly;
>
> Because of this, among other things.
>
> >
> > static struct cpufreq_driver *intel_pstate_driver __read_mostly;
> >
> > @@ -1461,6 +1462,11 @@ static inline bool
> > intel_pstate_hwp_boost_down(struct cpudata *cpu)
> > return false;
> > }
> >
> > +static inline void intel_pstate_update_util_hwp(struct
> > update_util_data *data,
> > + u64 time, unsigned
> > int flags)
> > +{
> > +}
> > +
> > static inline void intel_pstate_calc_avg_perf(struct cpudata *cpu)
> > {
> > struct sample *sample = &cpu->sample;
> > @@ -1764,7 +1770,7 @@ static void
> > intel_pstate_set_update_util_hook(unsigned int cpu_num)
> > {
> > struct cpudata *cpu = all_cpu_data[cpu_num];
> >
> > - if (hwp_active)
> > + if (hwp_active && !hwp_boost)
> > return;
> >
> > if (cpu->update_util_set)
> > @@ -1772,8 +1778,12 @@ static void
> > intel_pstate_set_update_util_hook(unsigned int cpu_num)
> >
> > /* Prevent intel_pstate_update_util() from using stale
> > data. */
> > cpu->sample.time = 0;
> > - cpufreq_add_update_util_hook(cpu_num, &cpu->update_util,
> > - intel_pstate_update_util);
> > + if (hwp_active)
> > + cpufreq_add_update_util_hook(cpu_num, &cpu-
> > >update_util,
> > + intel_pstate_update_ut
> > il_hwp);
> > + else
> > + cpufreq_add_update_util_hook(cpu_num, &cpu-
> > >update_util,
> > + intel_pstate_update_ut
> > il);
> > cpu->update_util_set = true;
> > }
> >
> > @@ -1885,8 +1895,11 @@ static int intel_pstate_set_policy(struct
> > cpufreq_policy *policy)
> > intel_pstate_set_update_util_hook(policy->cpu);
> > }
> >
> > - if (hwp_active)
> > + if (hwp_active) {
> > + if (!hwp_boost)
> > + intel_pstate_clear_update_util_hook(policy-
> > >cpu);
> > intel_pstate_hwp_set(policy->cpu);
> > + }
> >
> > mutex_unlock(&intel_pstate_limits_lock);
> >
> > --
> > 2.13.6
> >
^ permalink raw reply [flat|nested] 12+ messages in thread
* [RFC/RFT] [PATCH v2 4/6] cpufreq: intel_pstate: HWP boost performance on IO wakeup
2018-05-24 1:47 [RFC/RFT] [PATCH v2 0/6] Intel_pstate: HWP Dynamic performance boost Srinivas Pandruvada
` (2 preceding siblings ...)
2018-05-24 1:47 ` [RFC/RFT] [PATCH v2 3/6] cpufreq: intel_pstate: Add update_util_hook for HWP Srinivas Pandruvada
@ 2018-05-24 1:47 ` Srinivas Pandruvada
2018-05-29 7:44 ` Rafael J. Wysocki
2018-05-24 1:47 ` [RFC/RFT] [PATCH v2 5/6] cpufreq: intel_pstate: New sysfs entry to control HWP boost Srinivas Pandruvada
2018-05-24 1:47 ` [RFC/RFT] [PATCH v2 6/6] cpufreq: intel_pstate: enable boost for SKX Srinivas Pandruvada
5 siblings, 1 reply; 12+ messages in thread
From: Srinivas Pandruvada @ 2018-05-24 1:47 UTC (permalink / raw)
To: lenb, rjw, peterz, mgorman
Cc: linux-pm, linux-kernel, juri.lelli, viresh.kumar, Srinivas Pandruvada
This change uses SCHED_CPUFREQ_IOWAIT flag to boost HWP performance.
Since SCHED_CPUFREQ_IOWAIT flag is set frequently, we don't start
boosting steps unless we see two consecutive flags in two ticks. This
avoids boosting due to IO because of regular system activities.
To avoid synchronization issues, the actual processing of the flag is
done on the local CPU callback.
Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
---
drivers/cpufreq/intel_pstate.c | 44 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 44 insertions(+)
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index 382160570b5f..6d0ebe4fe1c7 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -223,6 +223,8 @@ struct global_params {
* operation
* @hwp_req_cached: Cached value of the last HWP Request MSR
* @hwp_cap_cached: Cached value of the last HWP Capabilities MSR
+ * @last_io_update: Last time when IO wake flag was set
+ * @sched_flags: Store scheduler flags for possible cross CPU update
* @hwp_boost_min: Last HWP boosted min performance
*
* This structure stores per CPU instance data for all CPUs.
@@ -258,6 +260,8 @@ struct cpudata {
s16 epp_saved;
u64 hwp_req_cached;
u64 hwp_cap_cached;
+ u64 last_io_update;
+ unsigned long sched_flags;
int hwp_boost_min;
};
@@ -1462,9 +1466,49 @@ static inline bool intel_pstate_hwp_boost_down(struct cpudata *cpu)
return false;
}
+static inline void intel_pstate_update_util_hwp_local(struct cpudata *cpu,
+ u64 time)
+{
+ bool io_flag;
+
+ cpu->sample.time = time;
+ io_flag = test_and_clear_bit(SCHED_CPUFREQ_IOWAIT, &cpu->sched_flags);
+ if (io_flag) {
+ bool do_io = false;
+
+ /*
+ * Set iowait_boost flag and update time. Since IO WAIT flag
+ * is set all the time, we can't just conclude that there is
+ * some IO bound activity is scheduled on this CPU with just
+ * one occurrence. If we receive at least two in two
+ * consecutive ticks, then we treat as boost candidate.
+ */
+ if (time_before64(time, cpu->last_io_update + 2 * TICK_NSEC))
+ do_io = true;
+
+ cpu->last_io_update = time;
+
+ if (do_io)
+ intel_pstate_hwp_boost_up(cpu);
+
+ } else {
+ if (intel_pstate_hwp_boost_down(cpu))
+ return;
+ }
+
+ cpu->last_update = time;
+}
+
static inline void intel_pstate_update_util_hwp(struct update_util_data *data,
u64 time, unsigned int flags)
{
+ struct cpudata *cpu = container_of(data, struct cpudata, update_util);
+
+ if (flags & SCHED_CPUFREQ_IOWAIT)
+ set_bit(SCHED_CPUFREQ_IOWAIT, &cpu->sched_flags);
+
+ if (smp_processor_id() == cpu->cpu)
+ intel_pstate_update_util_hwp_local(cpu, time);
}
static inline void intel_pstate_calc_avg_perf(struct cpudata *cpu)
--
2.13.6
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [RFC/RFT] [PATCH v2 4/6] cpufreq: intel_pstate: HWP boost performance on IO wakeup
2018-05-24 1:47 ` [RFC/RFT] [PATCH v2 4/6] cpufreq: intel_pstate: HWP boost performance on IO wakeup Srinivas Pandruvada
@ 2018-05-29 7:44 ` Rafael J. Wysocki
2018-05-29 22:24 ` Pandruvada, Srinivas
0 siblings, 1 reply; 12+ messages in thread
From: Rafael J. Wysocki @ 2018-05-29 7:44 UTC (permalink / raw)
To: Srinivas Pandruvada
Cc: Len Brown, Rafael J. Wysocki, Peter Zijlstra, Mel Gorman,
Linux PM, Linux Kernel Mailing List, Juri Lelli, Viresh Kumar
On Thu, May 24, 2018 at 3:47 AM, Srinivas Pandruvada
<srinivas.pandruvada@linux.intel.com> wrote:
> This change uses SCHED_CPUFREQ_IOWAIT flag to boost HWP performance.
> Since SCHED_CPUFREQ_IOWAIT flag is set frequently, we don't start
> boosting steps unless we see two consecutive flags in two ticks. This
> avoids boosting due to IO because of regular system activities.
>
> To avoid synchronization issues, the actual processing of the flag is
> done on the local CPU callback.
>
> Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
> ---
> drivers/cpufreq/intel_pstate.c | 44 ++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 44 insertions(+)
>
> diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
> index 382160570b5f..6d0ebe4fe1c7 100644
> --- a/drivers/cpufreq/intel_pstate.c
> +++ b/drivers/cpufreq/intel_pstate.c
> @@ -223,6 +223,8 @@ struct global_params {
> * operation
> * @hwp_req_cached: Cached value of the last HWP Request MSR
> * @hwp_cap_cached: Cached value of the last HWP Capabilities MSR
> + * @last_io_update: Last time when IO wake flag was set
> + * @sched_flags: Store scheduler flags for possible cross CPU update
> * @hwp_boost_min: Last HWP boosted min performance
> *
> * This structure stores per CPU instance data for all CPUs.
> @@ -258,6 +260,8 @@ struct cpudata {
> s16 epp_saved;
> u64 hwp_req_cached;
> u64 hwp_cap_cached;
> + u64 last_io_update;
> + unsigned long sched_flags;
> int hwp_boost_min;
> };
>
> @@ -1462,9 +1466,49 @@ static inline bool intel_pstate_hwp_boost_down(struct cpudata *cpu)
> return false;
> }
>
> +static inline void intel_pstate_update_util_hwp_local(struct cpudata *cpu,
> + u64 time)
> +{
> + bool io_flag;
> +
> + cpu->sample.time = time;
> + io_flag = test_and_clear_bit(SCHED_CPUFREQ_IOWAIT, &cpu->sched_flags);
I don't think you need to use bit ops here.
_update_util() runs under rq->lock for the target CPU, so it will not
run concurrently on two different CPUs for the same target anyway.
> + if (io_flag) {
> + bool do_io = false;
> +
> + /*
> + * Set iowait_boost flag and update time. Since IO WAIT flag
> + * is set all the time, we can't just conclude that there is
> + * some IO bound activity is scheduled on this CPU with just
> + * one occurrence. If we receive at least two in two
> + * consecutive ticks, then we treat as boost candidate.
> + */
> + if (time_before64(time, cpu->last_io_update + 2 * TICK_NSEC))
> + do_io = true;
> +
> + cpu->last_io_update = time;
> +
> + if (do_io)
> + intel_pstate_hwp_boost_up(cpu);
But what happens if user space wants to update the limits while
boosting is in effect? Shouldn't it take hwp_boost_min into account
then?
> +
> + } else {
> + if (intel_pstate_hwp_boost_down(cpu))
> + return;
> + }
> +
> + cpu->last_update = time;
> +}
> +
> static inline void intel_pstate_update_util_hwp(struct update_util_data *data,
> u64 time, unsigned int flags)
> {
> + struct cpudata *cpu = container_of(data, struct cpudata, update_util);
> +
> + if (flags & SCHED_CPUFREQ_IOWAIT)
> + set_bit(SCHED_CPUFREQ_IOWAIT, &cpu->sched_flags);
> +
> + if (smp_processor_id() == cpu->cpu)
> + intel_pstate_update_util_hwp_local(cpu, time);
> }
>
> static inline void intel_pstate_calc_avg_perf(struct cpudata *cpu)
> --
> 2.13.6
>
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [RFC/RFT] [PATCH v2 4/6] cpufreq: intel_pstate: HWP boost performance on IO wakeup
2018-05-29 7:44 ` Rafael J. Wysocki
@ 2018-05-29 22:24 ` Pandruvada, Srinivas
0 siblings, 0 replies; 12+ messages in thread
From: Pandruvada, Srinivas @ 2018-05-29 22:24 UTC (permalink / raw)
To: rafael
Cc: linux-kernel, peterz, linux-pm, juri.lelli, rjw, viresh.kumar,
mgorman, lenb
[-- Attachment #1: Type: text/plain, Size: 1936 bytes --]
On Tue, 2018-05-29 at 09:44 +0200, Rafael J. Wysocki wrote:
> On Thu, May 24, 2018 at 3:47 AM, Srinivas Pandruvada
> <srinivas.pandruvada@linux.intel.com> wrote:
[...]
> >
> > + cpu->sample.time = time;
> > + io_flag = test_and_clear_bit(SCHED_CPUFREQ_IOWAIT, &cpu-
> > >sched_flags);
>
> I don't think you need to use bit ops here.
Agree. This is not required here for just IO boost support.
>
> _update_util() runs under rq->lock for the target CPU, so it will not
> run concurrently on two different CPUs for the same target anyway.
>
> > + if (io_flag) {
> > + bool do_io = false;
> > +
> > + /*
> > + * Set iowait_boost flag and update time. Since IO
> > WAIT flag
> > + * is set all the time, we can't just conclude that
> > there is
> > + * some IO bound activity is scheduled on this CPU
> > with just
> > + * one occurrence. If we receive at least two in
> > two
> > + * consecutive ticks, then we treat as boost
> > candidate.
> > + */
> > + if (time_before64(time, cpu->last_io_update + 2 *
> > TICK_NSEC))
> > + do_io = true;
> > +
> > + cpu->last_io_update = time;
> > +
> > + if (do_io)
> > + intel_pstate_hwp_boost_up(cpu);
>
> But what happens if user space wants to update the limits while
> boosting is in effect? Shouldn't it take hwp_boost_min into account
> then?
User request has always higher priority. User min will be taken into
account as the boost min is updated under the the update util call
back, not just one time.
Thanks,
Srinivas
[-- Attachment #2: smime.p7s --]
[-- Type: application/x-pkcs7-signature, Size: 3290 bytes --]
^ permalink raw reply [flat|nested] 12+ messages in thread
* [RFC/RFT] [PATCH v2 5/6] cpufreq: intel_pstate: New sysfs entry to control HWP boost
2018-05-24 1:47 [RFC/RFT] [PATCH v2 0/6] Intel_pstate: HWP Dynamic performance boost Srinivas Pandruvada
` (3 preceding siblings ...)
2018-05-24 1:47 ` [RFC/RFT] [PATCH v2 4/6] cpufreq: intel_pstate: HWP boost performance on IO wakeup Srinivas Pandruvada
@ 2018-05-24 1:47 ` Srinivas Pandruvada
2018-05-24 1:47 ` [RFC/RFT] [PATCH v2 6/6] cpufreq: intel_pstate: enable boost for SKX Srinivas Pandruvada
5 siblings, 0 replies; 12+ messages in thread
From: Srinivas Pandruvada @ 2018-05-24 1:47 UTC (permalink / raw)
To: lenb, rjw, peterz, mgorman
Cc: linux-pm, linux-kernel, juri.lelli, viresh.kumar, Srinivas Pandruvada
A new attribute is added to intel_pstate sysfs to enable/disable
HWP dynamic performance boost.
Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
---
drivers/cpufreq/intel_pstate.c | 30 ++++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index 6d0ebe4fe1c7..b2613c9775d5 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -1033,6 +1033,30 @@ static ssize_t store_min_perf_pct(struct kobject *a, struct attribute *b,
return count;
}
+static ssize_t show_hwp_dynamic_boost(struct kobject *kobj,
+ struct attribute *attr, char *buf)
+{
+ return sprintf(buf, "%u\n", hwp_boost);
+}
+
+static ssize_t store_hwp_dynamic_boost(struct kobject *a, struct attribute *b,
+ const char *buf, size_t count)
+{
+ unsigned int input;
+ int ret;
+
+ ret = kstrtouint(buf, 10, &input);
+ if (ret)
+ return ret;
+
+ mutex_lock(&intel_pstate_driver_lock);
+ hwp_boost = !!input;
+ intel_pstate_update_policies();
+ mutex_unlock(&intel_pstate_driver_lock);
+
+ return count;
+}
+
show_one(max_perf_pct, max_perf_pct);
show_one(min_perf_pct, min_perf_pct);
@@ -1042,6 +1066,7 @@ define_one_global_rw(max_perf_pct);
define_one_global_rw(min_perf_pct);
define_one_global_ro(turbo_pct);
define_one_global_ro(num_pstates);
+define_one_global_rw(hwp_dynamic_boost);
static struct attribute *intel_pstate_attributes[] = {
&status.attr,
@@ -1082,6 +1107,11 @@ static void __init intel_pstate_sysfs_expose_params(void)
rc = sysfs_create_file(intel_pstate_kobject, &min_perf_pct.attr);
WARN_ON(rc);
+ if (hwp_active) {
+ rc = sysfs_create_file(intel_pstate_kobject,
+ &hwp_dynamic_boost.attr);
+ WARN_ON(rc);
+ }
}
/************************** sysfs end ************************/
--
2.13.6
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [RFC/RFT] [PATCH v2 6/6] cpufreq: intel_pstate: enable boost for SKX
2018-05-24 1:47 [RFC/RFT] [PATCH v2 0/6] Intel_pstate: HWP Dynamic performance boost Srinivas Pandruvada
` (4 preceding siblings ...)
2018-05-24 1:47 ` [RFC/RFT] [PATCH v2 5/6] cpufreq: intel_pstate: New sysfs entry to control HWP boost Srinivas Pandruvada
@ 2018-05-24 1:47 ` Srinivas Pandruvada
5 siblings, 0 replies; 12+ messages in thread
From: Srinivas Pandruvada @ 2018-05-24 1:47 UTC (permalink / raw)
To: lenb, rjw, peterz, mgorman
Cc: linux-pm, linux-kernel, juri.lelli, viresh.kumar, Srinivas Pandruvada
Enable HWP boost on Skylake server platform.
Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
---
drivers/cpufreq/intel_pstate.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index b2613c9775d5..6f8214a40764 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -1801,6 +1801,11 @@ static const struct x86_cpu_id intel_pstate_cpu_ee_disable_ids[] = {
{}
};
+static const struct x86_cpu_id intel_pstate_hwp_boost_ids[] __initconst = {
+ ICPU(INTEL_FAM6_SKYLAKE_X, core_funcs),
+ {}
+};
+
static int intel_pstate_init_cpu(unsigned int cpunum)
{
struct cpudata *cpu;
@@ -1831,6 +1836,10 @@ static int intel_pstate_init_cpu(unsigned int cpunum)
intel_pstate_disable_ee(cpunum);
intel_pstate_hwp_enable(cpu);
+
+ id = x86_match_cpu(intel_pstate_hwp_boost_ids);
+ if (id)
+ hwp_boost = true;
}
intel_pstate_get_cpu_pstates(cpu);
--
2.13.6
^ permalink raw reply related [flat|nested] 12+ messages in thread