[Skiboot] [PATCH v3 02/29] fast-reboot: factor out direct control loops for sreset
Nicholas Piggin
npiggin at gmail.com
Wed Nov 29 16:36:40 AEDT 2017
This provides a simple API that is amenable to be implemented
by the direct-controls subsystem in a future change.
Signed-off-by: Nicholas Piggin <npiggin at gmail.com>
---
core/fast-reboot.c | 79 +++++++++++++++++++++++++++++++++++++++---------------
1 file changed, 58 insertions(+), 21 deletions(-)
diff --git a/core/fast-reboot.c b/core/fast-reboot.c
index f63a6454b..62c7216b2 100644
--- a/core/fast-reboot.c
+++ b/core/fast-reboot.c
@@ -226,13 +226,10 @@ static void set_direct_ctl(struct cpu_thread *cpu, uint64_t bits)
xscom_write(chip_id, xscom_addr, bits);
}
-static bool fast_reset_p8(void)
+static int sreset_all_prepare(void)
{
struct cpu_thread *cpu;
- /* Mark ourselves as last man standing in need of a reset */
- last_man_standing = this_cpu();
-
prlog(PR_DEBUG, "RESET: Resetting from cpu: 0x%x (core 0x%x)\n",
this_cpu()->pir, pir_to_core_id(this_cpu()->pir));
@@ -257,16 +254,28 @@ static bool fast_reset_p8(void)
if (cpu != this_cpu())
set_direct_ctl(cpu, P8_DIRECT_CTL_STOP);
+ }
- /* Also make sure that saved_r1 is 0 ! That's what will
- * make our reset vector jump to fast_reboot_entry
- */
- cpu->save_r1 = 0;
+ return true;
+}
+
+static void sreset_all_finish(void)
+{
+ struct cpu_thread *cpu;
+
+ for_each_cpu(cpu) {
+ /* GARDed CPUs are marked unavailable. Skip them. */
+ if (cpu->state == cpu_state_unavailable)
+ continue;
+
+ if (cpu->primary == cpu)
+ clr_special_wakeup(cpu);
}
+}
- /* Restore skiboot vectors */
- copy_exception_vectors();
- setup_reset_vector();
+static void sreset_all_others(void)
+{
+ struct cpu_thread *cpu;
prlog(PR_DEBUG, "RESET: Pre-napping all threads but one...\n");
@@ -291,6 +300,42 @@ static bool fast_reset_p8(void)
if (cpu != this_cpu())
set_direct_ctl(cpu, P8_DIRECT_CTL_SRESET);
}
+}
+
+static void sreset_cpu(struct cpu_thread *cpu)
+{
+ set_direct_ctl(cpu, P8_DIRECT_CTL_PRENAP);
+ set_direct_ctl(cpu, P8_DIRECT_CTL_SRESET);
+}
+
+static bool fast_reset_p8(void)
+{
+ struct cpu_thread *cpu;
+
+ /* Mark ourselves as last man standing in need of a reset */
+ last_man_standing = this_cpu();
+
+ if (!sreset_all_prepare())
+ return false;
+
+ /* Put everybody in stop except myself */
+ for_each_cpu(cpu) {
+ /* GARDed CPUs are marked unavailable. Skip them. */
+ if (cpu->state == cpu_state_unavailable)
+ continue;
+
+ /* Also make sure that saved_r1 is 0 ! That's what will
+ * make our reset vector jump to fast_reboot_entry
+ */
+ cpu->save_r1 = 0;
+ }
+
+ /* Restore skiboot vectors */
+ copy_exception_vectors();
+ setup_reset_vector();
+
+ /* Send everyone else to 0x100 */
+ sreset_all_others();
return true;
}
@@ -463,8 +508,7 @@ void __noreturn fast_reboot_entry(void)
lock(&reset_lock);
if (last_man_standing && next_cpu(first_cpu())) {
prlog(PR_DEBUG, "RESET: last man standing fixup...\n");
- set_direct_ctl(last_man_standing, P8_DIRECT_CTL_PRENAP);
- set_direct_ctl(last_man_standing, P8_DIRECT_CTL_SRESET);
+ sreset_cpu(last_man_standing);
}
last_man_standing = NULL;
unlock(&reset_lock);
@@ -540,14 +584,7 @@ void __noreturn fast_reboot_entry(void)
prlog(PR_DEBUG, "RESET: Releasing special wakeups...\n");
- for_each_cpu(cpu) {
- /* GARDed CPUs are marked unavailable. Skip them. */
- if (cpu->state == cpu_state_unavailable)
- continue;
-
- if (cpu->primary == cpu)
- clr_special_wakeup(cpu);
- }
+ sreset_all_finish();
prlog(PR_INFO, "RESET: All done, cleaning up...\n");
--
2.15.0
More information about the Skiboot
mailing list