@@ -793,6 +793,70 @@ static struct cpu_idle_states power9_ndd1_cpu_idle_states[] = {
| OPAL_PM_PSSCR_EC,
.pm_ctrl_reg_mask = OPAL_PM_PSSCR_MASK }
};
+
+static struct cpu_idle_states power9_bigcores_cpu_idle_states[] = {
+ {
+ .name = "stop0_lite", /* Enter stop0 with no state loss */
+ .latency_ns = 1000,
+ .residency_ns = 10000,
+ .flags = 0*OPAL_PM_DEC_STOP \
+ | 0*OPAL_PM_TIMEBASE_STOP \
+ | 0*OPAL_PM_LOSE_USER_CONTEXT \
+ | 0*OPAL_PM_LOSE_HYP_CONTEXT \
+ | 0*OPAL_PM_LOSE_FULL_CONTEXT \
+ | 1*OPAL_PM_STOP_INST_FAST,
+ .pm_ctrl_reg_val = OPAL_PM_PSSCR_RL(0) \
+ | OPAL_PM_PSSCR_MTL(3) \
+ | OPAL_PM_PSSCR_TR(3),
+ .pm_ctrl_reg_mask = OPAL_PM_PSSCR_MASK },
+ {
+ .name = "stop0",
+ .latency_ns = 2000,
+ .residency_ns = 20000,
+ .flags = 0*OPAL_PM_DEC_STOP \
+ | 0*OPAL_PM_TIMEBASE_STOP \
+ | 1*OPAL_PM_LOSE_USER_CONTEXT \
+ | 0*OPAL_PM_LOSE_HYP_CONTEXT \
+ | 0*OPAL_PM_LOSE_FULL_CONTEXT \
+ | 1*OPAL_PM_STOP_INST_FAST,
+ .pm_ctrl_reg_val = OPAL_PM_PSSCR_RL(0) \
+ | OPAL_PM_PSSCR_MTL(3) \
+ | OPAL_PM_PSSCR_TR(3) \
+ | OPAL_PM_PSSCR_ESL \
+ | OPAL_PM_PSSCR_EC,
+ .pm_ctrl_reg_mask = OPAL_PM_PSSCR_MASK },
+ {
+ .name = "stop1_lite", /* Enter stop1 with no state loss */
+ .latency_ns = 4900,
+ .residency_ns = 49000,
+ .flags = 0*OPAL_PM_DEC_STOP \
+ | 0*OPAL_PM_TIMEBASE_STOP \
+ | 0*OPAL_PM_LOSE_USER_CONTEXT \
+ | 0*OPAL_PM_LOSE_HYP_CONTEXT \
+ | 0*OPAL_PM_LOSE_FULL_CONTEXT \
+ | 1*OPAL_PM_STOP_INST_FAST,
+ .pm_ctrl_reg_val = OPAL_PM_PSSCR_RL(1) \
+ | OPAL_PM_PSSCR_MTL(3) \
+ | OPAL_PM_PSSCR_TR(3),
+ .pm_ctrl_reg_mask = OPAL_PM_PSSCR_MASK },
+ {
+ .name = "stop1",
+ .latency_ns = 5000,
+ .residency_ns = 50000,
+ .flags = 0*OPAL_PM_DEC_STOP \
+ | 0*OPAL_PM_TIMEBASE_STOP \
+ | 1*OPAL_PM_LOSE_USER_CONTEXT \
+ | 0*OPAL_PM_LOSE_HYP_CONTEXT \
+ | 0*OPAL_PM_LOSE_FULL_CONTEXT \
+ | 1*OPAL_PM_STOP_INST_FAST,
+ .pm_ctrl_reg_val = OPAL_PM_PSSCR_RL(1) \
+ | OPAL_PM_PSSCR_MTL(3) \
+ | OPAL_PM_PSSCR_TR(3) \
+ | OPAL_PM_PSSCR_ESL \
+ | OPAL_PM_PSSCR_EC,
+ .pm_ctrl_reg_mask = OPAL_PM_PSSCR_MASK },
+};
+
static void slw_late_init_p9(struct proc_chip *chip)
{
struct cpu_thread *c;
@@ -880,6 +944,9 @@ void add_cpu_idle_state_properties(void)
(chip->type == PROC_CHIP_P9_NIMBUS)) {
states = power9_ndd1_cpu_idle_states;
nr_states = ARRAY_SIZE(power9_ndd1_cpu_idle_states);
+ } else if (this_cpu()->is_fused_core) {
+ states = power9_bigcores_cpu_idle_states;
+ nr_states = ARRAY_SIZE(power9_bigcores_cpu_idle_states);
} else {
states = power9_cpu_idle_states;
nr_states = ARRAY_SIZE(power9_cpu_idle_states);
Linux doesn't know how to properly restore state on "both halves" of a fused core, so limit ourselves to STOP states that don't require HV state restore for bare metal kernels (KVM is still broken) until we add a new representation for STOP states. The new representation will have per-state versioning so that we can control their individual enablement based on whether the OS has the necessary workarounds to make them work. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> --- hw/slw.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+)