From: Gautham R. Shenoy <hidden> Date: 2020-07-07 11:12:07
From: "Gautham R. Shenoy" <redacted>
Hi,
On pseries Dedicated Linux LPARs, apart from the polling snooze idle
state, we currently have the CEDE idle state which cedes the CPU to
the hypervisor with latency-hint = 0.
However, the PowerVM hypervisor supports additional extended CEDE
states, which can be queried through the "ibm,get-systems-parameter"
rtas-call with the CEDE_LATENCY_TOKEN. The hypervisor maps these
extended CEDE states to appropriate platform idle-states in order to
provide energy-savings as well as shifting power to the active
units. On existing pseries LPARs today we have extended CEDE with
latency-hints {1,2} supported.
In Patches 1-3 of this patchset, we add the code to parse the CEDE
latency records provided by the hypervisor. We use this information to
determine the wakeup latency of the regular CEDE (which we have been
so far hardcoding to 10us while experimentally it is much lesser ~
1us), by looking at the wakeup latency provided by the hypervisor for
Extended CEDE states. Since the platform currently advertises Extended
CEDE 1 to have wakeup latency of 2us, we can be sure that the wakeup
latency of the regular CEDE is no more than this.
Patch 4 (currently marked as RFC), expose the extended CEDE states
parsed above to the cpuidle framework, provided that they can wakeup
on an interrupt. On current platforms only Extended CEDE 1 fits the
bill, but this is going to change in future platforms where even
Extended CEDE 2 may be responsive to external interrupts.
Patch 5 (currently marked as RFC), filters out Extended CEDE 1 since
it offers no added advantage over the normal CEDE.
With Patches 1-3, we see an improvement in the single-threaded
performance on ebizzy.
2 ebizzy threads bound to the same big-core. 25% improvement in the
avg records/s (higher the better) with patches 1-3.
x without_patches
* with_patches
N Min Max Median Avg Stddev
x 10 2491089 5834307 5398375 4244335 1596244.9
* 10 2893813 5834474 5832448 5327281.3 1055941.4
We do not observe any major regression in either the context_switch2
benchmark or the schbench benchmark
context_switch2 across CPU0 CPU1 (Both belong to same big-core, but different
small cores). We observe a minor 0.14% regression in the number of
context-switches (higher is better).
x without_patch
* with_patch
N Min Max Median Avg Stddev
x 500 348872 362236 354712 354745.69 2711.827
* 500 349422 361452 353942 354215.4 2576.9258
context_switch2 across CPU0 CPU8 (Different big-cores). We observe a 0.37%
improvement in the number of context-switches (higher is better).
x without_patch
* with_patch
N Min Max Median Avg Stddev
x 500 287956 294940 288896 288977.23 646.59295
* 500 288300 294646 289582 290064.76 1161.9992
schbench:
No major difference could be seen until the 99.9th percentile.
Without-patch
Latency percentiles (usec)
50.0th: 29
75.0th: 39
90.0th: 49
95.0th: 59
*99.0th: 13104
99.5th: 14672
99.9th: 15824
min=0, max=17993
With-patch:
Latency percentiles (usec)
50.0th: 29
75.0th: 40
90.0th: 50
95.0th: 61
*99.0th: 13648
99.5th: 14768
99.9th: 15664
min=0, max=29812
Gautham R. Shenoy (5):
cpuidle-pseries: Set the latency-hint before entering CEDE
cpuidle-pseries: Add function to parse extended CEDE records
cpuidle-pseries : Fixup exit latency for CEDE(0)
cpuidle-pseries : Include extended CEDE states in cpuidle framework
cpuidle-pseries: Block Extended CEDE(1) which adds no additional
value.
drivers/cpuidle/cpuidle-pseries.c | 268 +++++++++++++++++++++++++++++++++++++-
1 file changed, 266 insertions(+), 2 deletions(-)
--
1.9.4
From: Gautham R. Shenoy <hidden> Date: 2020-07-07 11:12:08
From: "Gautham R. Shenoy" <redacted>
This patch exposes those extended CEDE states to the cpuidle framework
which are responsive to external interrupts and do not need an H_PROD.
Since as per the PAPR, all the extended CEDE states are non-responsive
to timers, we indicate this to the cpuidle subsystem via the
CPUIDLE_FLAG_TIMER_STOP flag for all those extende CEDE states which
can wake up on external interrupts.
With the patch, we are able to see the extended CEDE state with
latency hint = 1 exposed via the cpuidle framework.
$ cpupower idle-info
CPUidle driver: pseries_idle
CPUidle governor: menu
analyzing CPU 0:
Number of idle states: 3
Available idle states: snooze CEDE XCEDE1
snooze:
Flags/Description: snooze
Latency: 0
Usage: 33429446
Duration: 27006062
CEDE:
Flags/Description: CEDE
Latency: 1
Usage: 10272
Duration: 110786770
XCEDE1:
Flags/Description: XCEDE1
Latency: 12
Usage: 26445
Duration: 1436433815
Benchmark results:
TLDR: Over all we do not see any additional benefit from having XCEDE1 over
CEDE.
ebizzy :
2 threads bound to a big-core. With this patch, we see a 3.39%
regression compared to with only CEDE0 latency fixup.
x With only CEDE0 latency fixup
* With CEDE0 latency fixup + CEDE1
N Min Max Median Avg Stddev
x 10 2893813 5834474 5832448 5327281.3 1055941.4
* 10 2907329 5834923 5831398 5146614.6 1193874.8
context_switch2:
With the context_switch2 there are no observable regressions in the
results.
context_switch2 CPU0 CPU1 (Same Big-core, different small-cores).
No difference with and without patch.
x without_patch
* with_patch
N Min Max Median Avg Stddev
x 500 343644 348778 345444 345584.02 1035.1658
* 500 344310 347646 345776 345877.22 802.19501
context_switch2 CPU0 CPU8 (different big-cores). Minor 0.05% improvement
with patch
x without_patch
* with_patch
N Min Max Median Avg Stddev
x 500 287562 288756 288162 288134.76 262.24328
* 500 287874 288960 288306 288274.66 187.57034
schbench:
No regressions observed with schbench
Without Patch:
Latency percentiles (usec)
50.0th: 29
75.0th: 40
90.0th: 50
95.0th: 61
*99.0th: 13648
99.5th: 14768
99.9th: 15664
min=0, max=29812
With Patch:
Latency percentiles (usec)
50.0th: 30
75.0th: 40
90.0th: 51
95.0th: 59
*99.0th: 13616
99.5th: 14512
99.9th: 15696
min=0, max=15996
Signed-off-by: Gautham R. Shenoy <redacted>
---
drivers/cpuidle/cpuidle-pseries.c | 50 +++++++++++++++++++++++++++++++++++++++
1 file changed, 50 insertions(+)
* Gautham R Shenoy [off-list ref] [2020-07-07 16:41:38]:
From: "Gautham R. Shenoy" <redacted>
This patch exposes those extended CEDE states to the cpuidle framework
which are responsive to external interrupts and do not need an H_PROD.
Since as per the PAPR, all the extended CEDE states are non-responsive
to timers, we indicate this to the cpuidle subsystem via the
CPUIDLE_FLAG_TIMER_STOP flag for all those extende CEDE states which
can wake up on external interrupts.
With the patch, we are able to see the extended CEDE state with
latency hint = 1 exposed via the cpuidle framework.
$ cpupower idle-info
CPUidle driver: pseries_idle
CPUidle governor: menu
analyzing CPU 0:
Number of idle states: 3
Available idle states: snooze CEDE XCEDE1
snooze:
Flags/Description: snooze
Latency: 0
Usage: 33429446
Duration: 27006062
CEDE:
Flags/Description: CEDE
Latency: 1
Usage: 10272
Duration: 110786770
XCEDE1:
Flags/Description: XCEDE1
Latency: 12
Usage: 26445
Duration: 1436433815
Benchmark results:
TLDR: Over all we do not see any additional benefit from having XCEDE1 over
CEDE.
ebizzy :
2 threads bound to a big-core. With this patch, we see a 3.39%
regression compared to with only CEDE0 latency fixup.
x With only CEDE0 latency fixup
* With CEDE0 latency fixup + CEDE1
N Min Max Median Avg Stddev
x 10 2893813 5834474 5832448 5327281.3 1055941.4
* 10 2907329 5834923 5831398 5146614.6 1193874.8
context_switch2:
With the context_switch2 there are no observable regressions in the
results.
context_switch2 CPU0 CPU1 (Same Big-core, different small-cores).
No difference with and without patch.
x without_patch
* with_patch
N Min Max Median Avg Stddev
x 500 343644 348778 345444 345584.02 1035.1658
* 500 344310 347646 345776 345877.22 802.19501
context_switch2 CPU0 CPU8 (different big-cores). Minor 0.05% improvement
with patch
x without_patch
* with_patch
N Min Max Median Avg Stddev
x 500 287562 288756 288162 288134.76 262.24328
* 500 287874 288960 288306 288274.66 187.57034
schbench:
No regressions observed with schbench
Without Patch:
Latency percentiles (usec)
50.0th: 29
75.0th: 40
90.0th: 50
95.0th: 61
*99.0th: 13648
99.5th: 14768
99.9th: 15664
min=0, max=29812
With Patch:
Latency percentiles (usec)
50.0th: 30
75.0th: 40
90.0th: 51
95.0th: 59
*99.0th: 13616
99.5th: 14512
99.9th: 15696
min=0, max=15996
Signed-off-by: Gautham R. Shenoy <redacted>
@@ -362,9 +362,59 @@ static int add_pseries_idle_states(void)for(i=0;i<nr_xcede_records;i++){u64latency_tb=xcede_records[i].wakeup_latency_tb_ticks;u64latency_us=tb_to_ns(latency_tb)/NSEC_PER_USEC;+charname[CPUIDLE_NAME_LEN];+unsignedintlatency_hint=xcede_records[i].latency_hint;+u64residency_us;++if(!xcede_records[i].responsive_to_irqs){+pr_info("cpuidle : Skipping XCEDE%d. Not responsive to IRQs\n",+latency_hint);+continue;+}if(latency_us<min_latency_us)min_latency_us=latency_us;+snprintf(name,CPUIDLE_NAME_LEN,"XCEDE%d",latency_hint);++/*+*Asperthesection14.14.1ofPAPRversion2.8.1+*saysthatallingH_CEDEwiththevalueofthecede+*latencyspecifiersetgreaterthanzeroallowsthe+*processortimerfacilitytobedisabled(soasnot+*tocausegratuitouswake-ups-theuseofH_PROD,+*orotherexternalinterruptisrequiredtowakethe+*processorinthiscase).+*+*So,informthecpuidle-subsystemthatthetimer+*willbestoppedforthesestates.+*+*Also,bumpupthelatencyby10us,sincecpuidle+*wouldusetimer-offloadframeworkwhichwillneed+*tosendanIPItowakeupaCPUwhosetimerhas+*expired.+*/+if(latency_hint>0){+dedicated_states[nr_states].flags=CPUIDLE_FLAG_TIMER_STOP;+latency_us+=10;+}++/*+*Thumbrule:ResideintheXCEDEstateforatleast+*10xthetimerequiredtoenterandexitthatstate.+*/+residency_us=latency_us*10;++strlcpy(dedicated_states[nr_states].name,(constchar*)name,+CPUIDLE_NAME_LEN);+strlcpy(dedicated_states[nr_states].desc,(constchar*)name,+CPUIDLE_NAME_LEN);+dedicated_states[nr_states].exit_latency=latency_us;+dedicated_states[nr_states].target_residency=residency_us;+dedicated_states[nr_states].enter=&dedicated_cede_loop;+cede_latency_hint[nr_states]=latency_hint;+pr_info("cpuidle : Added %s. latency-hint = %d\n",+name,latency_hint);+nr_states++;
This patch demonstrates the various use cases of the previous patches
in the series that helps interface with the platform firmware better.
On current platforms these benefits are very limited, but the
framework built by the previous patches helps Linux exploit new and
enhanced idle states that will be available on newer platform and
firmware.
--Vaidy
From: Gautham R. Shenoy <hidden> Date: 2020-07-07 11:12:10
From: "Gautham R. Shenoy" <redacted>
Currently we use CEDE with latency-hint 0 as the only other idle state
on a dedicated LPAR apart from the polling "snooze" state.
The platform might support additional extended CEDE idle states, which
can be discovered through the "ibm,get-system-parameter" rtas-call
made with CEDE_LATENCY_TOKEN.
This patch adds a function to obtain information about the extended
CEDE idle states from the platform and parse the contents to populate
an array of extended CEDE states. These idle states thus discovered
will be added to the cpuidle framework in the next patch.
dmesg on a POWER9 LPAR, demonstrating the output of parsing the
extended CEDE latency parameters.
[ 5.913180] xcede : xcede_record_size = 10
[ 5.913183] xcede : Record 0 : hint = 1, latency =0x400 tb-ticks, Wake-on-irq = 1
[ 5.913188] xcede : Record 1 : hint = 2, latency =0x3e8000 tb-ticks, Wake-on-irq = 0
[ 5.913193] cpuidle : Skipping the 2 Extended CEDE idle states
Signed-off-by: Gautham R. Shenoy <redacted>
---
drivers/cpuidle/cpuidle-pseries.c | 129 +++++++++++++++++++++++++++++++++++++-
1 file changed, 127 insertions(+), 2 deletions(-)
@@ -238,6 +350,19 @@ static int pseries_cpuidle_driver_init(void)return0;}+staticintadd_pseries_idle_states(void)+{+intnr_states=2;/* By default we have snooze, CEDE */++if(parse_cede_parameters())+returnnr_states;++pr_info("cpuidle : Skipping the %d Extended CEDE idle states\n",+nr_xcede_records);++returnnr_states;+}+/**pseries_idle_probe()*Choosestatetableforsharedversusdedicatedpartition
@@ -260,7 +385,7 @@ static int pseries_idle_probe(void)max_idle_state=ARRAY_SIZE(shared_states);}else{cpuidle_state_table=dedicated_states;-max_idle_state=ARRAY_SIZE(dedicated_states);+max_idle_state=add_pseries_idle_states();}}elsereturn-ENODEV;
* Gautham R Shenoy [off-list ref] [2020-07-07 16:41:36]:
From: "Gautham R. Shenoy" <redacted>
Currently we use CEDE with latency-hint 0 as the only other idle state
on a dedicated LPAR apart from the polling "snooze" state.
The platform might support additional extended CEDE idle states, which
can be discovered through the "ibm,get-system-parameter" rtas-call
made with CEDE_LATENCY_TOKEN.
This patch adds a function to obtain information about the extended
CEDE idle states from the platform and parse the contents to populate
an array of extended CEDE states. These idle states thus discovered
will be added to the cpuidle framework in the next patch.
dmesg on a POWER9 LPAR, demonstrating the output of parsing the
extended CEDE latency parameters.
[ 5.913180] xcede : xcede_record_size = 10
[ 5.913183] xcede : Record 0 : hint = 1, latency =0x400 tb-ticks, Wake-on-irq = 1
[ 5.913188] xcede : Record 1 : hint = 2, latency =0x3e8000 tb-ticks, Wake-on-irq = 0
[ 5.913193] cpuidle : Skipping the 2 Extended CEDE idle states
Signed-off-by: Gautham R. Shenoy <redacted>
This is standard PAPR interface that has been defined long time ago.
However, new H_CEDE hints that map to new platform features will
appear in the same interface and Linux needs to prepare and be ready
to check and exploit the new hints if they are useful for the given
setup.
quoted hunk
+
+ if (xcede_record_size != XCEDE_LATENCY_RECORD_SIZE) {
+ pr_err("xcede : Expected record-size %d. Observed size %d.\n",
+ XCEDE_LATENCY_RECORD_SIZE, xcede_record_size);
+ return -EINVAL;
+ }
+
+ pr_info("xcede : xcede_record_size = %d\n", xcede_record_size);
+
+ /*
+ * Since the payload_length includes the last NULL byte and
+ * the xcede_record_size, the remaining bytes correspond to
+ * array of all cede_latency settings.
+ */
+ total_xcede_records_size = payload_length - 2;
+ nr_xcede_records = total_xcede_records_size / xcede_record_size;
+
+ payload++;
+ for (i = 0; i < nr_xcede_records; i++) {
+ struct xcede_latency_records *record = &xcede_records[i];
+
+ record->latency_hint = (u8)payload[0];
+ record->wakeup_latency_tb_ticks =
+ be64_to_cpu(*(__be64 *)(&payload[1]));
+ record->responsive_to_irqs = (u8)payload[9];
+ payload += xcede_record_size;
+ pr_info("xcede : Record %d : hint = %u, latency =0x%llx tb-ticks, Wake-on-irq = %u\n",
+ i, record->latency_hint,
+ record->wakeup_latency_tb_ticks,
+ record->responsive_to_irqs);
+ }
+
+ return 0;
+}
+
u8 cede_latency_hint[NR_DEDICATED_STATES];
static int dedicated_cede_loop(struct cpuidle_device *dev,
struct cpuidle_driver *drv,
@@ -238,6 +350,19 @@ static int pseries_cpuidle_driver_init(void) return 0; }+static int add_pseries_idle_states(void)+{+ int nr_states = 2; /* By default we have snooze, CEDE */++ if (parse_cede_parameters())+ return nr_states;++ pr_info("cpuidle : Skipping the %d Extended CEDE idle states\n",+ nr_xcede_records);++ return nr_states;
More logic will be added to this function in the subsequent patches to
actually make use of the information that is obtained from the platform
firmware.
--Vaidy
From: Gautham R. Shenoy <hidden> Date: 2020-07-07 11:12:14
From: "Gautham R. Shenoy" <redacted>
We are currently assuming that CEDE(0) has exit latency 10us, since
there is no way for us to query from the platform. However, if the
wakeup latency of an Extended CEDE state is smaller than 10us, then we
can be sure that the exit latency of CEDE(0) cannot be more than that.
that.
In this patch, we fix the exit latency of CEDE(0) if we discover an
Extended CEDE state with wakeup latency smaller than 10us. The new
value is 1us lesser than the smallest wakeup latency among the
Extended CEDE states.
Benchmark results:
ebizzy:
2 ebizzy threads bound to the same big-core. 25% improvement in the
avg records/s with patch.
x without_patch
* with_patch
N Min Max Median Avg Stddev
x 10 2491089 5834307 5398375 4244335 1596244.9
* 10 2893813 5834474 5832448 5327281.3 1055941.4
context_switch2 :
There is no major regression observed with this patch as seen from the
context_switch2 benchmark.
context_switch2 across CPU0 CPU1 (Both belong to same big-core, but different
small cores). We observe a minor 0.14% regression in the number of
context-switches (higher is better).
x without_patch
* with_patch
N Min Max Median Avg Stddev
x 500 348872 362236 354712 354745.69 2711.827
* 500 349422 361452 353942 354215.4 2576.9258
context_switch2 across CPU0 CPU8 (Different big-cores). We observe a 0.37%
improvement in the number of context-switches (higher is better).
x without_patch
* with_patch
N Min Max Median Avg Stddev
x 500 287956 294940 288896 288977.23 646.59295
* 500 288300 294646 289582 290064.76 1161.9992
schbench:
No major difference could be seen until the 99.9th percentile.
Without-patch
Latency percentiles (usec)
50.0th: 29
75.0th: 39
90.0th: 49
95.0th: 59
*99.0th: 13104
99.5th: 14672
99.9th: 15824
min=0, max=17993
With-patch:
Latency percentiles (usec)
50.0th: 29
75.0th: 40
90.0th: 50
95.0th: 61
*99.0th: 13648
99.5th: 14768
99.9th: 15664
min=0, max=29812
Signed-off-by: Gautham R. Shenoy <redacted>
---
drivers/cpuidle/cpuidle-pseries.c | 34 ++++++++++++++++++++++++++++++++--
1 file changed, 32 insertions(+), 2 deletions(-)
@@ -353,12 +353,42 @@ static int pseries_cpuidle_driver_init(void)staticintadd_pseries_idle_states(void){intnr_states=2;/* By default we have snooze, CEDE */+inti;+u64min_latency_us=dedicated_states[1].exit_latency;/* CEDE latency */if(parse_cede_parameters())returnnr_states;-pr_info("cpuidle : Skipping the %d Extended CEDE idle states\n",-nr_xcede_records);+for(i=0;i<nr_xcede_records;i++){+u64latency_tb=xcede_records[i].wakeup_latency_tb_ticks;+u64latency_us=tb_to_ns(latency_tb)/NSEC_PER_USEC;++if(latency_us<min_latency_us)+min_latency_us=latency_us;+}++/*+*WearecurrentlyassumingthatCEDE(0)hasexitlatency+*10us,sincethereisnowayforustoqueryfromthe+*platform.+*+*However,ifthewakeuplatencyofanExtendedCEDEstateis+*smallerthan10us,thenwecanbesurethatCEDE(0)+*requiresnomorethanthat.+*+*Performthefix-up.+*/+if(min_latency_us<dedicated_states[1].exit_latency){+u64cede0_latency=min_latency_us-1;++if(cede0_latency<=0)+cede0_latency=min_latency_us;++dedicated_states[1].exit_latency=cede0_latency;+dedicated_states[1].target_residency=10*(cede0_latency);+pr_info("cpuidle : Fixed up CEDE exit latency to %llu us\n",+cede0_latency);+}returnnr_states;}
* Gautham R Shenoy [off-list ref] [2020-07-07 16:41:37]:
From: "Gautham R. Shenoy" <redacted>
We are currently assuming that CEDE(0) has exit latency 10us, since
there is no way for us to query from the platform. However, if the
wakeup latency of an Extended CEDE state is smaller than 10us, then we
can be sure that the exit latency of CEDE(0) cannot be more than that.
that.
In this patch, we fix the exit latency of CEDE(0) if we discover an
Extended CEDE state with wakeup latency smaller than 10us. The new
value is 1us lesser than the smallest wakeup latency among the
Extended CEDE states.
Benchmark results:
ebizzy:
2 ebizzy threads bound to the same big-core. 25% improvement in the
avg records/s with patch.
x without_patch
* with_patch
N Min Max Median Avg Stddev
x 10 2491089 5834307 5398375 4244335 1596244.9
* 10 2893813 5834474 5832448 5327281.3 1055941.4
context_switch2 :
There is no major regression observed with this patch as seen from the
context_switch2 benchmark.
context_switch2 across CPU0 CPU1 (Both belong to same big-core, but different
small cores). We observe a minor 0.14% regression in the number of
context-switches (higher is better).
x without_patch
* with_patch
N Min Max Median Avg Stddev
x 500 348872 362236 354712 354745.69 2711.827
* 500 349422 361452 353942 354215.4 2576.9258
context_switch2 across CPU0 CPU8 (Different big-cores). We observe a 0.37%
improvement in the number of context-switches (higher is better).
x without_patch
* with_patch
N Min Max Median Avg Stddev
x 500 287956 294940 288896 288977.23 646.59295
* 500 288300 294646 289582 290064.76 1161.9992
schbench:
No major difference could be seen until the 99.9th percentile.
Without-patch
Latency percentiles (usec)
50.0th: 29
75.0th: 39
90.0th: 49
95.0th: 59
*99.0th: 13104
99.5th: 14672
99.9th: 15824
min=0, max=17993
With-patch:
Latency percentiles (usec)
50.0th: 29
75.0th: 40
90.0th: 50
95.0th: 61
*99.0th: 13648
99.5th: 14768
99.9th: 15664
min=0, max=29812
Signed-off-by: Gautham R. Shenoy <redacted>
@@ -353,12 +353,42 @@ static int pseries_cpuidle_driver_init(void)staticintadd_pseries_idle_states(void){intnr_states=2;/* By default we have snooze, CEDE */+inti;+u64min_latency_us=dedicated_states[1].exit_latency;/* CEDE latency */if(parse_cede_parameters())returnnr_states;-pr_info("cpuidle : Skipping the %d Extended CEDE idle states\n",-nr_xcede_records);+for(i=0;i<nr_xcede_records;i++){+u64latency_tb=xcede_records[i].wakeup_latency_tb_ticks;+u64latency_us=tb_to_ns(latency_tb)/NSEC_PER_USEC;++if(latency_us<min_latency_us)+min_latency_us=latency_us;+}++/*+*WearecurrentlyassumingthatCEDE(0)hasexitlatency+*10us,sincethereisnowayforustoqueryfromthe+*platform.+*+*However,ifthewakeuplatencyofanExtendedCEDEstateis+*smallerthan10us,thenwecanbesurethatCEDE(0)+*requiresnomorethanthat.+*+*Performthefix-up.+*/+if(min_latency_us<dedicated_states[1].exit_latency){+u64cede0_latency=min_latency_us-1;++if(cede0_latency<=0)+cede0_latency=min_latency_us;++dedicated_states[1].exit_latency=cede0_latency;+dedicated_states[1].target_residency=10*(cede0_latency);+pr_info("cpuidle : Fixed up CEDE exit latency to %llu us\n",+cede0_latency);+}
As per PAPR spec the CEDE hints are in increasing order of exit
latency. Hence a given state's exit latency cannot exceed the one
following it. The quirk is such that the first one (hint 0) is
implicit and hence we have to use the above logic to extract its
characteristics.
--Vaidy
From: Gautham R. Shenoy <hidden> Date: 2020-07-07 11:12:16
From: "Gautham R. Shenoy" <redacted>
The Extended CEDE state with latency-hint = 1 is only different from
normal CEDE (with latency-hint = 0) in that a CPU in Extended CEDE(1)
does not wakeup on timer events. Both CEDE and Extended CEDE(1) map to
the same hardware idle state. Since we already get SMT folding from
the normal CEDE, the Extended CEDE(1) doesn't provide any additional
value. This patch blocks Extended CEDE(1).
Signed-off-by: Gautham R. Shenoy <redacted>
---
drivers/cpuidle/cpuidle-pseries.c | 57 ++++++++++++++++++++++++++++++++++++---
1 file changed, 54 insertions(+), 3 deletions(-)
@@ -350,6 +350,43 @@ static int pseries_cpuidle_driver_init(void)return0;}+#define XCEDE1_HINT 1+#define ERR_NO_VALUE_ADD (-1)+#define ERR_NO_EE_WAKEUP (-2)++/*+*Returns0iftheExtendeCEDEstatewith@hintisnotblockedin+*cpuidleframework.+*+*ReturnsERR_NO_EE_WAKEUPiftheExtendedCEDEstateisblockeddue+*tonotbeingresponsivetoexternalinterrupts.+*+*ReturnsERR_NO_VALUE_ADDiftheExtendedCEDEstatedoesnotprovide+*addedvalueadditionoverthenormalCEDE.+*/+staticintcpuidle_xcede_blocked(u8hint,u64latency_us,u8responsive_to_irqs)+{++/*+*WewillonlyallowextendedCEDEstatesthatareresponsive+*toirqsdonotrequireanH_PRODtobewokenup.+*/+if(!responsive_to_irqs)+returnERR_NO_EE_WAKEUP;++/*+*WealreadyobtainSMTfoldingbenefitsfromCEDE(whichis+*CEDEwithhint0).Furthermore,CEDEisalsoresponsiveto+*timer-events,whileXCEDE1requiresanexternal+*interrupt/H_PRODtobewokenup.Hence,blockXCEDE1since+*itaddsnofurthervalue.+*/+if(hint==XCEDE1_HINT)+returnERR_NO_VALUE_ADD;++return0;+}+staticintadd_pseries_idle_states(void){intnr_states=2;/* By default we have snooze, CEDE */
@@ -365,15 +402,29 @@ static int add_pseries_idle_states(void)charname[CPUIDLE_NAME_LEN];unsignedintlatency_hint=xcede_records[i].latency_hint;u64residency_us;+intrc;++if(latency_us<min_latency_us)+min_latency_us=latency_us;++rc=cpuidle_xcede_blocked(latency_hint,latency_us,+xcede_records[i].responsive_to_irqs);-if(!xcede_records[i].responsive_to_irqs){+if(rc){+switch(rc){+caseERR_NO_VALUE_ADD:+pr_info("cpuidle : Skipping XCEDE%d. No additional value-add\n",+latency_hint);+break;+caseERR_NO_EE_WAKEUP:pr_info("cpuidle : Skipping XCEDE%d. Not responsive to IRQs\n",latency_hint);+break;+}+continue;}-if(latency_us<min_latency_us)-min_latency_us=latency_us;snprintf(name,CPUIDLE_NAME_LEN,"XCEDE%d",latency_hint);/*
* Gautham R Shenoy [off-list ref] [2020-07-07 16:41:39]:
From: "Gautham R. Shenoy" <redacted>
The Extended CEDE state with latency-hint = 1 is only different from
normal CEDE (with latency-hint = 0) in that a CPU in Extended CEDE(1)
does not wakeup on timer events. Both CEDE and Extended CEDE(1) map to
the same hardware idle state. Since we already get SMT folding from
the normal CEDE, the Extended CEDE(1) doesn't provide any additional
value. This patch blocks Extended CEDE(1).
Signed-off-by: Gautham R. Shenoy <redacted>
@@ -350,6 +350,43 @@ static int pseries_cpuidle_driver_init(void)return0;}+#define XCEDE1_HINT 1+#define ERR_NO_VALUE_ADD (-1)+#define ERR_NO_EE_WAKEUP (-2)++/*+*Returns0iftheExtendeCEDEstatewith@hintisnotblockedin+*cpuidleframework.+*+*ReturnsERR_NO_EE_WAKEUPiftheExtendedCEDEstateisblockeddue+*tonotbeingresponsivetoexternalinterrupts.+*+*ReturnsERR_NO_VALUE_ADDiftheExtendedCEDEstatedoesnotprovide+*addedvalueadditionoverthenormalCEDE.+*/+staticintcpuidle_xcede_blocked(u8hint,u64latency_us,u8responsive_to_irqs)+{++/*+*WewillonlyallowextendedCEDEstatesthatareresponsive+*toirqsdonotrequireanH_PRODtobewokenup.+*/+if(!responsive_to_irqs)+returnERR_NO_EE_WAKEUP;++/*+*WealreadyobtainSMTfoldingbenefitsfromCEDE(whichis+*CEDEwithhint0).Furthermore,CEDEisalsoresponsiveto+*timer-events,whileXCEDE1requiresanexternal+*interrupt/H_PRODtobewokenup.Hence,blockXCEDE1since+*itaddsnofurthervalue.+*/+if(hint==XCEDE1_HINT)+returnERR_NO_VALUE_ADD;++return0;+}+staticintadd_pseries_idle_states(void){intnr_states=2;/* By default we have snooze, CEDE */
@@ -365,15 +402,29 @@ static int add_pseries_idle_states(void)charname[CPUIDLE_NAME_LEN];unsignedintlatency_hint=xcede_records[i].latency_hint;u64residency_us;+intrc;++if(latency_us<min_latency_us)+min_latency_us=latency_us;++rc=cpuidle_xcede_blocked(latency_hint,latency_us,+xcede_records[i].responsive_to_irqs);-if(!xcede_records[i].responsive_to_irqs){+if(rc){+switch(rc){+caseERR_NO_VALUE_ADD:+pr_info("cpuidle : Skipping XCEDE%d. No additional value-add\n",+latency_hint);+break;+caseERR_NO_EE_WAKEUP:pr_info("cpuidle : Skipping XCEDE%d. Not responsive to IRQs\n",latency_hint);+break;+}+continue;}-if(latency_us<min_latency_us)-min_latency_us=latency_us;snprintf(name,CPUIDLE_NAME_LEN,"XCEDE%d",latency_hint);/*
We need these heuristics to select/reject idle states exposed by
platform firmware to Linux primarily because not all states are really
useful to Linux on a given setup.
--Vaidy
From: Gautham R. Shenoy <hidden> Date: 2020-07-07 11:12:22
From: "Gautham R. Shenoy" <redacted>
As per the PAPR, each H_CEDE call is associated with a latency-hint to
be passed in the VPA field "cede_latency_hint". The CEDE states that
we were implicitly entering so far is CEDE with latency-hint = 0.
This patch explicitly sets the latency hint corresponding to the CEDE
state that we are currently entering. While at it, we save the
previous hint, to be restored once we wakeup from CEDE. This will be
required in the future when we expose extended-cede states through the
cpuidle framework, where each of them will have a different
cede-latency hint.
Signed-off-by: Gautham R. Shenoy <redacted>
---
drivers/cpuidle/cpuidle-pseries.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
* Gautham R Shenoy [off-list ref] [2020-07-07 16:41:35]:
From: "Gautham R. Shenoy" <redacted>
As per the PAPR, each H_CEDE call is associated with a latency-hint to
be passed in the VPA field "cede_latency_hint". The CEDE states that
we were implicitly entering so far is CEDE with latency-hint = 0.
This patch explicitly sets the latency hint corresponding to the CEDE
state that we are currently entering. While at it, we save the
previous hint, to be restored once we wakeup from CEDE. This will be
required in the future when we expose extended-cede states through the
cpuidle framework, where each of them will have a different
cede-latency hint.
Signed-off-by: Gautham R. Shenoy <redacted>
Saving and restoring the current cede hint value helps in maintaining
compatibility with other parts of the kernel. Over long term we can
make cpuidle driver deterministically set the CEDE hint at each
invocation of H_CEDE call so that we do not have to do multiple
redundant save-restore.
This is a reasonable start to cleanup this cupidle subsystem on PAPR
guests.
--Vaidy
From: Gautham R Shenoy <hidden> Date: 2020-07-07 11:32:49
Hi,
On Tue, Jul 07, 2020 at 04:41:34PM +0530, Gautham R. Shenoy wrote:
From: "Gautham R. Shenoy" <redacted>
Hi,
Gautham R. Shenoy (5):
cpuidle-pseries: Set the latency-hint before entering CEDE
cpuidle-pseries: Add function to parse extended CEDE records
cpuidle-pseries : Fixup exit latency for CEDE(0)
cpuidle-pseries : Include extended CEDE states in cpuidle framework
cpuidle-pseries: Block Extended CEDE(1) which adds no additional
value.
From: "Rafael J. Wysocki" <rafael@kernel.org> Date: 2020-07-27 14:36:01
On Tue, Jul 7, 2020 at 1:32 PM Gautham R Shenoy [off-list ref] wrote:
Hi,
On Tue, Jul 07, 2020 at 04:41:34PM +0530, Gautham R. Shenoy wrote:
quoted
From: "Gautham R. Shenoy" <redacted>
Hi,
Gautham R. Shenoy (5):
cpuidle-pseries: Set the latency-hint before entering CEDE
cpuidle-pseries: Add function to parse extended CEDE records
cpuidle-pseries : Fixup exit latency for CEDE(0)
cpuidle-pseries : Include extended CEDE states in cpuidle framework
cpuidle-pseries: Block Extended CEDE(1) which adds no additional
value.
From: Gautham R Shenoy <hidden> Date: 2020-07-27 18:55:39
Hello Rafael,
On Mon, Jul 27, 2020 at 04:14:12PM +0200, Rafael J. Wysocki wrote:
On Tue, Jul 7, 2020 at 1:32 PM Gautham R Shenoy [off-list ref] wrote:
quoted
Hi,
On Tue, Jul 07, 2020 at 04:41:34PM +0530, Gautham R. Shenoy wrote:
quoted
From: "Gautham R. Shenoy" <redacted>
Hi,
Gautham R. Shenoy (5):
cpuidle-pseries: Set the latency-hint before entering CEDE
cpuidle-pseries: Add function to parse extended CEDE records
cpuidle-pseries : Fixup exit latency for CEDE(0)
cpuidle-pseries : Include extended CEDE states in cpuidle framework
cpuidle-pseries: Block Extended CEDE(1) which adds no additional
value.
OK, so this is targeted at the powerpc maintainers, isn't it?
Yes, the code is powerpc specific.
Also, I noticed that Nathan's patches have been merged by Michael
Ellerman in the powerpc/merge tree. I will rebase and post a v2 of
this patch series.
--
Thanks and Regards
gautham.
* Gautham R Shenoy [off-list ref] [2020-07-07 16:41:34]:
From: "Gautham R. Shenoy" <redacted>
Hi,
On pseries Dedicated Linux LPARs, apart from the polling snooze idle
state, we currently have the CEDE idle state which cedes the CPU to
the hypervisor with latency-hint = 0.
However, the PowerVM hypervisor supports additional extended CEDE
states, which can be queried through the "ibm,get-systems-parameter"
rtas-call with the CEDE_LATENCY_TOKEN. The hypervisor maps these
extended CEDE states to appropriate platform idle-states in order to
provide energy-savings as well as shifting power to the active
units. On existing pseries LPARs today we have extended CEDE with
latency-hints {1,2} supported.
In Patches 1-3 of this patchset, we add the code to parse the CEDE
latency records provided by the hypervisor. We use this information to
determine the wakeup latency of the regular CEDE (which we have been
so far hardcoding to 10us while experimentally it is much lesser ~
1us), by looking at the wakeup latency provided by the hypervisor for
Extended CEDE states. Since the platform currently advertises Extended
CEDE 1 to have wakeup latency of 2us, we can be sure that the wakeup
latency of the regular CEDE is no more than this.
Patch 4 (currently marked as RFC), expose the extended CEDE states
parsed above to the cpuidle framework, provided that they can wakeup
on an interrupt. On current platforms only Extended CEDE 1 fits the
bill, but this is going to change in future platforms where even
Extended CEDE 2 may be responsive to external interrupts.
Patch 5 (currently marked as RFC), filters out Extended CEDE 1 since
it offers no added advantage over the normal CEDE.
With Patches 1-3, we see an improvement in the single-threaded
performance on ebizzy.
2 ebizzy threads bound to the same big-core. 25% improvement in the
avg records/s (higher the better) with patches 1-3.
x without_patches
* with_patches
N Min Max Median Avg Stddev
x 10 2491089 5834307 5398375 4244335 1596244.9
* 10 2893813 5834474 5832448 5327281.3 1055941.4
We do not observe any major regression in either the context_switch2
benchmark or the schbench benchmark
context_switch2 across CPU0 CPU1 (Both belong to same big-core, but different
small cores). We observe a minor 0.14% regression in the number of
context-switches (higher is better).
x without_patch
* with_patch
N Min Max Median Avg Stddev
x 500 348872 362236 354712 354745.69 2711.827
* 500 349422 361452 353942 354215.4 2576.9258
context_switch2 across CPU0 CPU8 (Different big-cores). We observe a 0.37%
improvement in the number of context-switches (higher is better).
x without_patch
* with_patch
N Min Max Median Avg Stddev
x 500 287956 294940 288896 288977.23 646.59295
* 500 288300 294646 289582 290064.76 1161.9992
schbench:
No major difference could be seen until the 99.9th percentile.
Without-patch
Latency percentiles (usec)
50.0th: 29
75.0th: 39
90.0th: 49
95.0th: 59
*99.0th: 13104
99.5th: 14672
99.9th: 15824
min=0, max=17993
With-patch:
Latency percentiles (usec)
50.0th: 29
75.0th: 40
90.0th: 50
95.0th: 61
*99.0th: 13648
99.5th: 14768
99.9th: 15664
min=0, max=29812
This patch series mainly cleans up the CEDE latency discovery and
prepares to add different cpuidle states in virtualised environment.
This helps in improving SMT folding speeds and also power savings and
power shifting with newer platform firmware.
The current benefit is primarily from faster SMT folding and resulting
single performance achieved by updating the platform firmware provided
heuristics in the cpuidle states.
--Vaidy