[Skiboot] [PATCH v2 1/3] core/fast-reboot: verify mem regions before fast reboot

Nicholas Piggin npiggin at gmail.com
Mon Mar 26 16:05:59 AEDT 2018


Run the mem_region sanity checkers before proceeding with fast
reboot.

This is the beginning of proactive sanity checks on opal data
for fast reboot (with complements the reactive disable_fast_reboot
cases). This is encouraged to re-use and share any kind of debug
code and unit test code.

Signed-off-by: Nicholas Piggin <npiggin at gmail.com>
---
 core/fast-reboot.c   | 25 +++++++++++++++++++++++--
 core/init.c          |  2 --
 core/mem_region.c    | 15 ++++++++++++---
 include/mem_region.h |  4 ++++
 4 files changed, 39 insertions(+), 7 deletions(-)

diff --git a/core/fast-reboot.c b/core/fast-reboot.c
index d702044a..9f8c4d9a 100644
--- a/core/fast-reboot.c
+++ b/core/fast-reboot.c
@@ -19,6 +19,7 @@
 #include <fsp.h>
 #include <psi.h>
 #include <opal.h>
+#include <mem_region.h>
 #include <xscom.h>
 #include <interrupts.h>
 #include <cec.h>
@@ -71,6 +72,23 @@ void disable_fast_reboot(const char *reason)
 	fast_reboot_disabled = reason;
 }
 
+/*
+ * This is called by the reboot CPU after all other CPUs have been
+ * quiesced and stopped, to perform various sanity checks on firmware
+ * data (and potentially hardware), to determine whether the fast
+ * reboot should go ahead.
+ */
+static bool fast_reboot_sanity_check(void)
+{
+	if (!mem_check_all()) {
+		prlog(PR_NOTICE, "REST: Fast reboot failed due to inconsistent "
+				"firmware data\n");
+		return false;
+	}
+
+	return true;
+}
+
 void fast_reboot(void)
 {
 	struct cpu_thread *cpu;
@@ -104,8 +122,6 @@ void fast_reboot(void)
 		return;
 	}
 
-	/* Should mem_check() all regions before allowing fast reboot? */
-
 	prlog(PR_NOTICE, "RESET: Initiating fast reboot %d...\n", ++fast_reboot_count);
 	fast_boot_release = false;
 	sync();
@@ -118,6 +134,11 @@ void fast_reboot(void)
 		return;
 	}
 
+	if (!fast_reboot_sanity_check()) {
+		opal_quiesce(QUIESCE_RESUME, -1);
+		return;
+	}
+
 	/*
 	 * There is no point clearing special wakeup or un-quiesce due to
 	 * failure after this point, because we will be going to full IPL.
diff --git a/core/init.c b/core/init.c
index a60b7843..3de89a72 100644
--- a/core/init.c
+++ b/core/init.c
@@ -454,8 +454,6 @@ static void load_initramfs(void)
 			(uint64_t)INITRAMFS_LOAD_BASE + initramfs_size);
 }
 
-int64_t mem_dump_free(void);
-
 void *fdt;
 
 void __noreturn load_and_boot_kernel(bool is_reboot)
diff --git a/core/mem_region.c b/core/mem_region.c
index 4479a23a..aa0c850b 100644
--- a/core/mem_region.c
+++ b/core/mem_region.c
@@ -26,9 +26,6 @@
 #include <mem_region.h>
 #include <mem_region-malloc.h>
 
-int64_t mem_dump_free(void);
-void mem_dump_allocs(void);
-
 /* Memory poisoning on free (if POISON_MEM_REGION set to 1) */
 #ifdef DEBUG
 #define POISON_MEM_REGION	1
@@ -622,6 +619,18 @@ bool mem_check(const struct mem_region *region)
 	return true;
 }
 
+bool mem_check_all(void)
+{
+	struct mem_region *r;
+
+	list_for_each(&regions, r, list) {
+		if (!mem_check(r))
+			return false;
+	}
+
+	return true;
+}
+
 static struct mem_region *new_region(const char *name,
 				     uint64_t start, uint64_t len,
 				     struct dt_node *node,
diff --git a/include/mem_region.h b/include/mem_region.h
index 324e98e1..2a9453f5 100644
--- a/include/mem_region.h
+++ b/include/mem_region.h
@@ -63,7 +63,11 @@ bool mem_resize(struct mem_region *region, void *mem, size_t len,
 		const char *location);
 size_t mem_allocated_size(const void *ptr);
 bool mem_check(const struct mem_region *region);
+bool mem_check_all(void);
 void mem_region_release_unused(void);
+void mem_region_clear_unused(void);
+int64_t mem_dump_free(void);
+void mem_dump_allocs(void);
 
 /* Specifically for working on the heap. */
 extern struct mem_region skiboot_heap;
-- 
2.16.1



More information about the Skiboot mailing list