aboutsummaryrefslogtreecommitdiff
path: root/core/direct-controls.c
diff options
context:
space:
mode:
authorNicholas Piggin <npiggin@gmail.com>2017-11-29 15:36:54 +1000
committerStewart Smith <stewart@linux.vnet.ibm.com>2017-12-03 21:49:12 -0600
commit44687f84e44311fed40cb8520664907221be8298 (patch)
treebf12dd5fc0669b5295285ad31e008590d1b30e3b /core/direct-controls.c
parent1949c768eba6387d73ec5e21da1f90d1fde2047c (diff)
downloadskiboot-44687f84e44311fed40cb8520664907221be8298.zip
skiboot-44687f84e44311fed40cb8520664907221be8298.tar.gz
skiboot-44687f84e44311fed40cb8520664907221be8298.tar.bz2
direct-controls: p8 implementation of generic direct controls
This reworks the sreset functionality that was brought over from fast-reboot, and fits it under the generic direct controls APIs. The fast reboot APIs are implemented using generic direct controls, which also makes them available on p9. Signed-off-by: Nicholas Piggin <npiggin@gmail.com> Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'core/direct-controls.c')
-rw-r--r--core/direct-controls.c212
1 files changed, 119 insertions, 93 deletions
diff --git a/core/direct-controls.c b/core/direct-controls.c
index 658729f..7e0aea3 100644
--- a/core/direct-controls.c
+++ b/core/direct-controls.c
@@ -44,7 +44,7 @@ static void mambo_sreset_cpu(struct cpu_thread *cpu)
#define P8_DIRECT_CTL_PRENAP PPC_BIT(47)
#define P8_DIRECT_CTL_SRESET PPC_BIT(60)
-static int p8_set_special_wakeup(struct cpu_thread *cpu)
+static int p8_core_set_special_wakeup(struct cpu_thread *cpu)
{
uint64_t val, poll_target, stamp;
uint32_t core_id;
@@ -155,7 +155,7 @@ static int p8_set_special_wakeup(struct cpu_thread *cpu)
return OPAL_HARDWARE;
}
-static int p8_clr_special_wakeup(struct cpu_thread *cpu)
+static int p8_core_clear_special_wakeup(struct cpu_thread *cpu)
{
uint64_t val;
uint32_t core_id;
@@ -215,94 +215,19 @@ static void p8_set_direct_ctl(struct cpu_thread *cpu, uint64_t bits)
xscom_write(chip_id, xscom_addr, bits);
}
-static int p8_sreset_all_prepare(void)
+static int p8_stop_thread(struct cpu_thread *cpu)
{
- struct cpu_thread *cpu;
-
- prlog(PR_DEBUG, "RESET: Resetting from cpu: 0x%x (core 0x%x)\n",
- this_cpu()->pir, pir_to_core_id(this_cpu()->pir));
-
- /* Assert special wakup on all cores. Only on operational cores. */
- for_each_ungarded_primary(cpu) {
- if (p8_set_special_wakeup(cpu) != OPAL_SUCCESS)
- return OPAL_HARDWARE;
- }
-
- prlog(PR_DEBUG, "RESET: Stopping the world...\n");
-
- /* Put everybody in stop except myself */
- for_each_ungarded_cpu(cpu) {
- if (cpu != this_cpu())
- p8_set_direct_ctl(cpu, P8_DIRECT_CTL_STOP);
- }
+ p8_set_direct_ctl(cpu, P8_DIRECT_CTL_STOP);
return OPAL_SUCCESS;
}
-static void p8_sreset_all_finish(void)
-{
- struct cpu_thread *cpu;
-
- for_each_ungarded_primary(cpu)
- p8_clr_special_wakeup(cpu);
-}
-
-static void p8_sreset_all_others(void)
-{
- struct cpu_thread *cpu;
-
- prlog(PR_DEBUG, "RESET: Resetting all threads but one...\n");
-
- /* Reset everybody except my own core threads */
- for_each_ungarded_cpu(cpu) {
- if (cpu == this_cpu())
- continue;
-
- p8_set_direct_ctl(cpu, P8_DIRECT_CTL_PRENAP);
- p8_set_direct_ctl(cpu, P8_DIRECT_CTL_SRESET);
- }
-}
-
-int sreset_all_prepare(void)
+static int p8_sreset_thread(struct cpu_thread *cpu)
{
- if (chip_quirk(QUIRK_MAMBO_CALLOUTS))
- return OPAL_SUCCESS;
-
- if (proc_gen == proc_gen_p8)
- return p8_sreset_all_prepare();
+ p8_set_direct_ctl(cpu, P8_DIRECT_CTL_PRENAP);
+ p8_set_direct_ctl(cpu, P8_DIRECT_CTL_SRESET);
- return OPAL_UNSUPPORTED;
-}
-
-void sreset_all_finish(void)
-{
- if (chip_quirk(QUIRK_MAMBO_CALLOUTS))
- return;
-
- if (proc_gen == proc_gen_p8)
- return p8_sreset_all_finish();
-}
-
-int sreset_all_others(void)
-{
- if (chip_quirk(QUIRK_MAMBO_CALLOUTS)) {
- struct cpu_thread *cpu;
-
- for_each_ungarded_cpu(cpu) {
- if (cpu == this_cpu())
- continue;
- mambo_sreset_cpu(cpu);
- }
-
- return OPAL_SUCCESS;
- }
-
- if (proc_gen == proc_gen_p8) {
- p8_sreset_all_others();
- return OPAL_SUCCESS;
- }
-
- return OPAL_UNSUPPORTED;
+ return OPAL_SUCCESS;
}
@@ -529,17 +454,23 @@ static int p9_sreset_thread(struct cpu_thread *cpu)
return 0;
}
+/**************** generic direct controls ****************/
+
int dctl_set_special_wakeup(struct cpu_thread *t)
{
struct cpu_thread *c = t->primary;
int rc = OPAL_SUCCESS;
- if (proc_gen != proc_gen_p9)
+ if (proc_gen != proc_gen_p9 && proc_gen != proc_gen_p8)
return OPAL_UNSUPPORTED;
lock(&c->dctl_lock);
- if (c->special_wakeup_count == 0)
- rc = p9_core_set_special_wakeup(c);
+ if (c->special_wakeup_count == 0) {
+ if (proc_gen == proc_gen_p9)
+ rc = p9_core_set_special_wakeup(c);
+ else /* (proc_gen == proc_gen_p8) */
+ rc = p8_core_set_special_wakeup(c);
+ }
if (!rc)
c->special_wakeup_count++;
unlock(&c->dctl_lock);
@@ -552,14 +483,18 @@ int dctl_clear_special_wakeup(struct cpu_thread *t)
struct cpu_thread *c = t->primary;
int rc = OPAL_SUCCESS;
- if (proc_gen != proc_gen_p9)
+ if (proc_gen != proc_gen_p9 && proc_gen != proc_gen_p8)
return OPAL_UNSUPPORTED;
lock(&c->dctl_lock);
if (!c->special_wakeup_count)
goto out;
- if (c->special_wakeup_count == 1)
- rc = p9_core_clear_special_wakeup(c);
+ if (c->special_wakeup_count == 1) {
+ if (proc_gen == proc_gen_p9)
+ rc = p9_core_clear_special_wakeup(c);
+ else /* (proc_gen == proc_gen_p8) */
+ rc = p8_core_clear_special_wakeup(c);
+ }
if (!rc)
c->special_wakeup_count--;
out:
@@ -576,6 +511,9 @@ int dctl_core_is_gated(struct cpu_thread *t)
uint32_t sshhyp_addr;
uint64_t val;
+ if (proc_gen != proc_gen_p9)
+ return OPAL_UNSUPPORTED;
+
sshhyp_addr = XSCOM_ADDR_P9_EC_SLAVE(core_id, P9_EC_PPM_SSHHYP);
if (xscom_read(chip_id, sshhyp_addr, &val)) {
@@ -593,7 +531,7 @@ static int dctl_stop(struct cpu_thread *t)
struct cpu_thread *c = t->primary;
int rc;
- if (proc_gen != proc_gen_p9)
+ if (proc_gen != proc_gen_p9 && proc_gen != proc_gen_p8)
return OPAL_UNSUPPORTED;
lock(&c->dctl_lock);
@@ -601,7 +539,10 @@ static int dctl_stop(struct cpu_thread *t)
unlock(&c->dctl_lock);
return OPAL_BUSY;
}
- rc = p9_stop_thread(t);
+ if (proc_gen == proc_gen_p9)
+ rc = p9_stop_thread(t);
+ else /* (proc_gen == proc_gen_p8) */
+ rc = p8_stop_thread(t);
if (!rc)
t->dctl_stopped = true;
unlock(&c->dctl_lock);
@@ -630,12 +571,18 @@ static int dctl_cont(struct cpu_thread *t)
return rc;
}
+/*
+ * NOTE:
+ * The POWER8 sreset does not provide SRR registers, so it can be used
+ * for fast reboot, but not OPAL_SIGNAL_SYSTEM_RESET or anywhere that is
+ * expected to return. For now, callers beware.
+ */
static int dctl_sreset(struct cpu_thread *t)
{
struct cpu_thread *c = t->primary;
int rc;
- if (proc_gen != proc_gen_p9)
+ if (proc_gen != proc_gen_p9 && proc_gen != proc_gen_p8)
return OPAL_UNSUPPORTED;
lock(&c->dctl_lock);
@@ -643,7 +590,10 @@ static int dctl_sreset(struct cpu_thread *t)
unlock(&c->dctl_lock);
return OPAL_BUSY;
}
- rc = p9_sreset_thread(t);
+ if (proc_gen == proc_gen_p9)
+ rc = p9_sreset_thread(t);
+ else /* (proc_gen == proc_gen_p8) */
+ rc = p8_sreset_thread(t);
if (!rc)
t->dctl_stopped = false;
unlock(&c->dctl_lock);
@@ -651,6 +601,82 @@ static int dctl_sreset(struct cpu_thread *t)
return rc;
}
+
+/**************** fast reboot API ****************/
+
+int sreset_all_prepare(void)
+{
+ struct cpu_thread *cpu;
+
+ prlog(PR_DEBUG, "RESET: Resetting from cpu: 0x%x (core 0x%x)\n",
+ this_cpu()->pir, pir_to_core_id(this_cpu()->pir));
+
+ if (chip_quirk(QUIRK_MAMBO_CALLOUTS))
+ return OPAL_SUCCESS;
+
+ /* Assert special wakup on all cores. Only on operational cores. */
+ for_each_ungarded_primary(cpu) {
+ if (dctl_set_special_wakeup(cpu) != OPAL_SUCCESS)
+ return OPAL_HARDWARE;
+ }
+
+ prlog(PR_DEBUG, "RESET: Stopping the world...\n");
+
+ /* Put everybody in stop except myself */
+ for_each_ungarded_cpu(cpu) {
+ if (cpu == this_cpu())
+ continue;
+ if (dctl_stop(cpu) != OPAL_SUCCESS)
+ return OPAL_HARDWARE;
+
+ }
+
+ return OPAL_SUCCESS;
+}
+
+void sreset_all_finish(void)
+{
+ struct cpu_thread *cpu;
+
+ if (chip_quirk(QUIRK_MAMBO_CALLOUTS))
+ return;
+
+ for_each_ungarded_primary(cpu)
+ dctl_clear_special_wakeup(cpu);
+}
+
+int sreset_all_others(void)
+{
+ struct cpu_thread *cpu;
+
+ prlog(PR_DEBUG, "RESET: Resetting all threads but self...\n");
+
+ /*
+ * mambo should actually implement stop as well, and implement
+ * the dctl_ helpers properly. Currently it's racy just sresetting.
+ */
+ if (chip_quirk(QUIRK_MAMBO_CALLOUTS)) {
+ for_each_ungarded_cpu(cpu) {
+ if (cpu == this_cpu())
+ continue;
+ mambo_sreset_cpu(cpu);
+ }
+ return OPAL_SUCCESS;
+ }
+
+ for_each_ungarded_cpu(cpu) {
+ if (cpu == this_cpu())
+ continue;
+ if (dctl_sreset(cpu) != OPAL_SUCCESS)
+ return OPAL_HARDWARE;
+ }
+
+ return OPAL_SUCCESS;
+}
+
+
+/**************** OPAL_SIGNAL_SYSTEM_RESET API ****************/
+
/*
* This provides a way for the host to raise system reset exceptions
* on other threads using direct control scoms on POWER9.