[Skiboot] [PATCH 1/2] core/direct-controls: fix p9_cont_thread for stopped/inactive threads
Nicholas Piggin
npiggin at gmail.com
Thu May 3 18:38:08 AEST 2018
Firstly, p9_cont_thread should check that the thread actually was
quiesced before it tries to resume it. Anything could happen if we
try this from an arbitrary thread state.
Then when resuming a quiesced thread that is inactive or stopped (in
a stop idle state), we must not send a core_start direct control,
clear_maint must be used in these cases.
Signed-off-by: Nicholas Piggin <npiggin at gmail.com>
---
core/direct-controls.c | 87 +++++++++++++++++++++++++++++++++---------
1 file changed, 70 insertions(+), 17 deletions(-)
diff --git a/core/direct-controls.c b/core/direct-controls.c
index c7b9c9b7..4511a113 100644
--- a/core/direct-controls.c
+++ b/core/direct-controls.c
@@ -273,10 +273,14 @@ static int p8_sreset_thread(struct cpu_thread *cpu)
#define P9_QUIESCE_POLL_INTERVAL 100
#define P9_QUIESCE_TIMEOUT 100000
+#define P9_CORE_THREAD_STATE 0x10ab3
+#define P9_THREAD_INFO 0x10a9b
+
#define P9_EC_DIRECT_CONTROLS 0x10a9c
#define P9_THREAD_STOP(t) PPC_BIT(7 + 8*(t))
#define P9_THREAD_CONT(t) PPC_BIT(6 + 8*(t))
#define P9_THREAD_SRESET(t) PPC_BIT(4 + 8*(t))
+#define P9_THREAD_CLEAR_MAINT(t) PPC_BIT(3 + 8*(t))
#define P9_THREAD_PWR(t) PPC_BIT(32 + 8*(t))
/* EC_PPM_SPECIAL_WKUP_HYP */
@@ -412,6 +416,72 @@ static int p9_thread_quiesced(struct cpu_thread *cpu)
return 0;
}
+static int p9_cont_thread(struct cpu_thread *cpu)
+{
+ uint32_t chip_id = pir_to_chip_id(cpu->pir);
+ uint32_t core_id = pir_to_core_id(cpu->pir);
+ uint32_t thread_id = pir_to_thread_id(cpu->pir);
+ uint32_t cts_addr;
+ uint32_t ti_addr;
+ uint32_t dctl_addr;
+ uint64_t core_thread_state;
+ uint64_t thread_info;
+ bool active, stop;
+ int rc;
+
+ rc = p9_thread_quiesced(cpu);
+ if (rc < 0)
+ return rc;
+ if (!rc) {
+ prlog(PR_ERR, "Could not cont thread %u:%u:%u:"
+ " Thread is not quiesced.\n",
+ chip_id, core_id, thread_id);
+ return OPAL_BUSY;
+ }
+
+ cts_addr = XSCOM_ADDR_P9_EC(core_id, P9_CORE_THREAD_STATE);
+ ti_addr = XSCOM_ADDR_P9_EC(core_id, P9_THREAD_INFO);
+ dctl_addr = XSCOM_ADDR_P9_EC(core_id, P9_EC_DIRECT_CONTROLS);
+
+ if (xscom_read(chip_id, cts_addr, &core_thread_state)) {
+ prlog(PR_ERR, "Could not resume thread %u:%u:%u:"
+ " Unable to read CORE_THREAD_STATE.\n",
+ chip_id, core_id, thread_id);
+ return OPAL_HARDWARE;
+ }
+ if (core_thread_state & PPC_BIT(56 + thread_id))
+ stop = true;
+ else
+ stop = false;
+
+ if (xscom_read(chip_id, ti_addr, &thread_info)) {
+ prlog(PR_ERR, "Could not resume thread %u:%u:%u:"
+ " Unable to read THREAD_INFO.\n",
+ chip_id, core_id, thread_id);
+ return OPAL_HARDWARE;
+ }
+ if (thread_info & PPC_BIT(thread_id))
+ active = true;
+ else
+ active = false;
+
+ if (!active || stop) {
+ if (xscom_write(chip_id, dctl_addr, P9_THREAD_CLEAR_MAINT(thread_id))) {
+ prlog(PR_ERR, "Could not resume thread %u:%u:%u:"
+ " Unable to write EC_DIRECT_CONTROLS.\n",
+ chip_id, core_id, thread_id);
+ }
+ } else {
+ if (xscom_write(chip_id, dctl_addr, P9_THREAD_CONT(thread_id))) {
+ prlog(PR_ERR, "Could not resume thread %u:%u:%u:"
+ " Unable to write EC_DIRECT_CONTROLS.\n",
+ chip_id, core_id, thread_id);
+ }
+ }
+
+ return 0;
+}
+
static int p9_stop_thread(struct cpu_thread *cpu)
{
uint32_t chip_id = pir_to_chip_id(cpu->pir);
@@ -461,23 +531,6 @@ static int p9_stop_thread(struct cpu_thread *cpu)
return OPAL_HARDWARE;
}
-static int p9_cont_thread(struct cpu_thread *cpu)
-{
- uint32_t chip_id = pir_to_chip_id(cpu->pir);
- uint32_t core_id = pir_to_core_id(cpu->pir);
- uint32_t thread_id = pir_to_thread_id(cpu->pir);
- uint32_t dctl_addr;
-
- dctl_addr = XSCOM_ADDR_P9_EC(core_id, P9_EC_DIRECT_CONTROLS);
- if (xscom_write(chip_id, dctl_addr, P9_THREAD_CONT(thread_id))) {
- prlog(PR_ERR, "Could not resume thread %u:%u:%u:"
- " Unable to write EC_DIRECT_CONTROLS.\n",
- chip_id, core_id, thread_id);
- }
-
- return 0;
-}
-
static int p9_sreset_thread(struct cpu_thread *cpu)
{
uint32_t chip_id = pir_to_chip_id(cpu->pir);
--
2.17.0
More information about the Skiboot
mailing list