[Skiboot] [PATCH 09/18] fast-reboot: add sreset timeout detection and handling

Nicholas Piggin npiggin at gmail.com
Sun Nov 19 20:14:59 AEDT 2017


Have the initiator wait for all its sreset targets to call in, and
time out after 200ms if they did not. Fail and revert to IPL reboot.

Signed-off-by: Nicholas Piggin <npiggin at gmail.com>
---
 core/fast-reboot.c | 80 ++++++++++++++++++++++++++++++------------------------
 1 file changed, 45 insertions(+), 35 deletions(-)

diff --git a/core/fast-reboot.c b/core/fast-reboot.c
index d156e536..e20a80bd 100644
--- a/core/fast-reboot.c
+++ b/core/fast-reboot.c
@@ -353,6 +353,35 @@ static bool fast_reset_p8(void)
 	return ret;
 }
 
+static bool cpu_state_wait_all_others(enum cpu_thread_state state,
+					unsigned long timeout_tb)
+{
+	struct cpu_thread *cpu;
+	unsigned long end = mftb() + timeout_tb;
+
+	sync();
+	for_each_ungarded_cpu(cpu) {
+		if (cpu == this_cpu())
+			continue;
+
+		if (cpu->state != state) {
+			smt_lowest();
+			while (cpu->state != state) {
+				barrier();
+
+				if (timeout_tb && (tb_compare(mftb(), end) == TB_AAFTERB)) {
+					smt_medium();
+					return false;
+				}
+			}
+			smt_medium();
+		}
+	}
+	sync();
+
+	return true;
+}
+
 extern void *fdt;
 extern struct lock capi_lock;
 
@@ -414,11 +443,16 @@ void fast_reboot(void)
 	/* Unlock, at this point we go away */
 	unlock(&reset_lock);
 
-	if (success) {
-		asm volatile("ba	0x100\n\t" : : : "memory");
-		for (;;)
-			;
-	}
+	if (!success)
+		return;
+
+	/* Ensure all the sresets get through */
+	if (!cpu_state_wait_all_others(cpu_state_present, msecs_to_tb(200)))
+		return;
+
+	asm volatile("ba	0x100\n\t" : : : "memory");
+	for (;;)
+		;
 }
 
 static void cleanup_cpu_state(void)
@@ -510,8 +544,6 @@ void __noreturn fast_reboot_entry(void);
 
 void __noreturn fast_reboot_entry(void)
 {
-	struct cpu_thread *cpu;
-
 	prlog(PR_DEBUG, "RESET: CPU 0x%04x reset in\n", this_cpu()->pir);
 	time_wait_ms(100);
 
@@ -525,13 +557,15 @@ void __noreturn fast_reboot_entry(void)
 	 */
 	check_split_core();
 
+	sync();
+	this_cpu()->state = cpu_state_present;
+	sync();
+
 	/* Are we the original boot CPU ? If not, we spin waiting
 	 * for a relase signal from CPU 1, then we clean ourselves
 	 * up and go processing jobs.
 	 */
 	if (this_cpu() != boot_cpu) {
-		this_cpu()->state = cpu_state_present;
-		sync();
 		if (!fast_boot_release) {
 			smt_lowest();
 			while (!fast_boot_release)
@@ -548,18 +582,7 @@ void __noreturn fast_reboot_entry(void)
 	/* We are the original boot CPU, wait for secondaries to
 	 * be captured.
 	 */
-	for_each_ungarded_cpu(cpu) {
-		if (cpu == this_cpu())
-			continue;
-
-		/* XXX Add a callin timeout ? */
-		if (cpu->state != cpu_state_present) {
-			smt_lowest();
-			while (cpu->state != cpu_state_present)
-				barrier();
-			smt_medium();
-		}
-	}
+	cpu_state_wait_all_others(cpu_state_present, 0);
 
 	prlog(PR_INFO, "RESET: Releasing secondaries...\n");
 
@@ -568,20 +591,7 @@ void __noreturn fast_reboot_entry(void)
 	sync();
 
 	/* Wait for them to respond */
-	for_each_ungarded_cpu(cpu) {
-		if (cpu == this_cpu())
-			continue;
-
-		/* XXX Add a callin timeout ? */
-		if (cpu->state == cpu_state_present) {
-			smt_lowest();
-			while (cpu->state == cpu_state_present)
-				barrier();
-			smt_medium();
-		}
-	}
-
-	sync();
+	cpu_state_wait_all_others(cpu_state_active, 0);
 
 	prlog(PR_INFO, "RESET: All done, cleaning up...\n");
 
-- 
2.15.0



More information about the Skiboot mailing list