aboutsummaryrefslogtreecommitdiff
path: root/hw/slw.c
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2020-08-04 23:02:18 +0530
committerOliver O'Halloran <oohall@gmail.com>2020-08-07 16:00:20 +1000
commit1629c851c57e5f86ce92516de778afa8aa12f712 (patch)
tree37dc09a1a8c12156b4196b3dcd549febaa59e387 /hw/slw.c
parenteb344bda04137c4bf694a711479c2d9a05fc277d (diff)
downloadskiboot-1629c851c57e5f86ce92516de778afa8aa12f712.zip
skiboot-1629c851c57e5f86ce92516de778afa8aa12f712.tar.gz
skiboot-1629c851c57e5f86ce92516de778afa8aa12f712.tar.bz2
slw: Limit fused cores P9 to STOP0/1/2
FROM: Benjamin Herrenschmidt <benh@kernel.crashing.org> 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> Signed-off-by: Michael Neuling <mikey@neuling.org> Signed-off-by: Vaidyanathan Srinivasan <svaidy@linux.vnet.ibm.com> Signed-off-by: Oliver O'Halloran <oohall@gmail.com>
Diffstat (limited to 'hw/slw.c')
-rw-r--r--hw/slw.c82
1 files changed, 81 insertions, 1 deletions
diff --git a/hw/slw.c b/hw/slw.c
index beb129a..625ee88 100644
--- a/hw/slw.c
+++ b/hw/slw.c
@@ -688,6 +688,83 @@ static struct cpu_idle_states power9_mambo_cpu_idle_states[] = {
};
+/*
+ * cpu_idle_states for fused core configuration
+ * These will be a subset of power9 idle states.
+ */
+static struct cpu_idle_states power9_fusedcore_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 },
+
+ /* stop1_lite has been removed since it adds no additional benefit over stop0_lite */
+
+ {
+ .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 },
+ /*
+ * stop2_lite has been removed since currently it adds minimal benefit over stop2.
+ * However, the benefit is eclipsed by the time required to ungate the clocks
+ */
+
+ {
+ .name = "stop2",
+ .latency_ns = 10000,
+ .residency_ns = 100000,
+ .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(2) \
+ | 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;
@@ -772,7 +849,10 @@ void add_cpu_idle_state_properties(void)
if (proc_chip_quirks & QUIRK_MAMBO_CALLOUTS) {
states = power9_mambo_cpu_idle_states;
nr_states = ARRAY_SIZE(power9_mambo_cpu_idle_states);
- } else {
+ } else if (this_cpu()->is_fused_core) {
+ states = power9_fusedcore_cpu_idle_states;
+ nr_states = ARRAY_SIZE(power9_fusedcore_cpu_idle_states);
+ } else {
states = power9_cpu_idle_states;
nr_states = ARRAY_SIZE(power9_cpu_idle_states);
}