[RFC,v2,6/6] core/flash.c: cache loaded resources

Message ID 20180628025501.20676-7-stewart@linux.ibm.com
State New
Headers show
Series
  • Faster fast reboot (2x!)
Related show

Commit Message

Stewart Smith June 28, 2018, 2:55 a.m.
The vast majority of fast-reboot time on BMC based systems is spent
waiting for the BOOTKERNEL to be loaded off flash. If we cache it
instead, we sacrifice 16MB of memory to cut 4seconds (from our previous
total of 9 seconds) off fast reboot time.

We don't need to do this on FSP systems as loading BOOTKERNEL and
INITRAMFS from the FSP doesn't take nearly this long (typically they're
around <1s).

Signed-off-by: Stewart Smith <stewart@linux.ibm.com>
---
 core/fast-reboot.c |  7 ++++++-
 core/flash.c       | 49 +++++++++++++++++++++++++++++++++++++++++-----
 core/init.c        | 24 +++++++++++------------
 include/skiboot.h  |  4 +++-
 4 files changed, 65 insertions(+), 19 deletions(-)

Patch

diff --git a/core/fast-reboot.c b/core/fast-reboot.c
index b7e518b1a492..3c920eac29b1 100644
--- a/core/fast-reboot.c
+++ b/core/fast-reboot.c
@@ -402,5 +402,10 @@  void __noreturn fast_reboot_entry(void)
 	wait_mem_region_clear_unused();
 
 	/* Load and boot payload */
-	load_and_boot_kernel(true);
+	if (!load_kernel()) {
+		op_display(OP_FATAL, OP_MOD_INIT, 1);
+		abort();
+	}
+	load_initramfs();
+	boot_kernel(true);
 }
diff --git a/core/flash.c b/core/flash.c
index e3be576137e3..c94635d4adc0 100644
--- a/core/flash.c
+++ b/core/flash.c
@@ -28,6 +28,7 @@ 
 #include <libstb/secureboot.h>
 #include <libstb/trustedboot.h>
 #include <elf.h>
+#include <chip.h>
 
 struct flash {
 	struct list_node	list;
@@ -549,12 +550,14 @@  static struct {
 	enum resource_id	id;
 	uint32_t		subid;
 	char			name[PART_NAME_MAX+1];
+	void* cache;
+	size_t len;
 } part_name_map[] = {
-	{ RESOURCE_ID_KERNEL,	RESOURCE_SUBID_NONE,		"BOOTKERNEL" },
-	{ RESOURCE_ID_INITRAMFS,RESOURCE_SUBID_NONE,		"ROOTFS" },
-	{ RESOURCE_ID_CAPP,	RESOURCE_SUBID_SUPPORTED,	"CAPP" },
-	{ RESOURCE_ID_IMA_CATALOG,  RESOURCE_SUBID_SUPPORTED,	"IMA_CATALOG" },
-	{ RESOURCE_ID_VERSION,	RESOURCE_SUBID_NONE,		"VERSION" },
+	{ RESOURCE_ID_KERNEL,	RESOURCE_SUBID_NONE,		"BOOTKERNEL", NULL, 0 },
+	{ RESOURCE_ID_INITRAMFS,RESOURCE_SUBID_NONE,		"ROOTFS", NULL, 0 },
+	{ RESOURCE_ID_CAPP,	RESOURCE_SUBID_SUPPORTED,	"CAPP", NULL, 0 },
+	{ RESOURCE_ID_IMA_CATALOG,  RESOURCE_SUBID_SUPPORTED,	"IMA_CATALOG", NULL, 0 },
+	{ RESOURCE_ID_VERSION,	RESOURCE_SUBID_NONE,		"VERSION", NULL, 0 },
 };
 
 const char *flash_map_resource_name(enum resource_id id)
@@ -855,8 +858,19 @@  int flash_resource_loaded(enum resource_id id, uint32_t subid)
 	struct flash_load_resource_item *resource = NULL;
 	struct flash_load_resource_item *r;
 	int rc = OPAL_BUSY;
+	int i;
 
 	lock(&flash_load_resource_lock);
+
+	for (i = 0; i < ARRAY_SIZE(part_name_map); i++) {
+		if (part_name_map[i].id == id &&
+		    subid == RESOURCE_SUBID_NONE &&
+		    part_name_map[i].cache) {
+			unlock(&flash_load_resource_lock);
+			return OPAL_SUCCESS;
+		}
+	}
+
 	list_for_each(&flash_loaded_resources, r, link) {
 		if (r->id == id && r->subid == subid) {
 			resource = r;
@@ -884,6 +898,7 @@  static void flash_load_resources(void *data __unused)
 {
 	struct flash_load_resource_item *r;
 	int result;
+	int i;
 
 	lock(&flash_load_resource_lock);
 	do {
@@ -901,6 +916,19 @@  static void flash_load_resources(void *data __unused)
 		result = flash_load_resource(r->id, r->subid, r->buf, r->len);
 
 		lock(&flash_load_resource_lock);
+
+		/* Cache the resource */
+		for (i = 0; i < ARRAY_SIZE(part_name_map); i++) {
+			if (part_name_map[i].id == r->id &&
+			    r->subid == RESOURCE_SUBID_NONE) {
+				part_name_map[i].cache = local_alloc(next_chip(NULL)->id, *r->len, 4);
+				if (!part_name_map[i].cache)
+					break;
+				memcpy(part_name_map[i].cache, r->buf, *r->len);
+				part_name_map[i].len = *r->len;
+			}
+		}
+
 		r = list_pop(&flash_load_resource_queue,
 			     struct flash_load_resource_item, link);
 		r->result = result;
@@ -925,6 +953,17 @@  int flash_start_preload_resource(enum resource_id id, uint32_t subid,
 {
 	struct flash_load_resource_item *r;
 	bool start_thread = false;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(part_name_map); i++) {
+		if (part_name_map[i].id == id &&
+		    subid == RESOURCE_SUBID_NONE &&
+		    part_name_map[i].cache) {
+			*len = part_name_map[i].len;
+			memcpy(buf, part_name_map[i].cache, *len);
+			return OPAL_SUCCESS;
+		}
+	}
 
 	r = malloc(sizeof(struct flash_load_resource_item));
 
diff --git a/core/init.c b/core/init.c
index b660af2d7824..d5a1c3c769a5 100644
--- a/core/init.c
+++ b/core/init.c
@@ -344,7 +344,7 @@  bool start_preload_kernel(void)
 	return true;
 }
 
-static bool load_kernel(void)
+bool load_kernel(void)
 {
 	void *stb_container = NULL;
 	struct elf_hdr *kh;
@@ -435,7 +435,7 @@  static bool load_kernel(void)
 	return true;
 }
 
-static void load_initramfs(void)
+void load_initramfs(void)
 {
 	uint64_t *initramfs_start;
 	void *stb_container = NULL;
@@ -476,7 +476,7 @@  static void load_initramfs(void)
 
 void *fdt;
 
-void __noreturn load_and_boot_kernel(bool is_reboot)
+void __noreturn boot_kernel(bool is_reboot)
 {
 	const struct dt_property *memprop;
 	const char *cmdline, *stdoutp;
@@ -494,14 +494,6 @@  void __noreturn load_and_boot_kernel(bool is_reboot)
 	if (platform.exit)
 		platform.exit();
 
-	/* Load kernel LID */
-	if (!load_kernel()) {
-		op_display(OP_FATAL, OP_MOD_INIT, 1);
-		abort();
-	}
-
-	load_initramfs();
-
 	trustedboot_exit_boot_services();
 
 	ipmi_set_fw_progress_sensor(IPMI_FW_OS_BOOT);
@@ -1146,6 +1138,14 @@  void __noreturn __nomcount main_cpu_entry(const void *fdt)
 	/* Add the list of interrupts going to OPAL */
 	add_opal_interrupts();
 
+	/* Load kernel LID */
+	if (!load_kernel()) {
+		op_display(OP_FATAL, OP_MOD_INIT, 1);
+		abort();
+	}
+
+	load_initramfs();
+
 	/* Now release parts of memory nodes we haven't used ourselves... */
 	mem_region_release_unused();
 
@@ -1164,7 +1164,7 @@  void __noreturn __nomcount main_cpu_entry(const void *fdt)
 	/* On P9, switch to radix mode by default */
 	cpu_set_radix_mode();
 
-	load_and_boot_kernel(false);
+	boot_kernel(false);
 }
 
 void __noreturn __secondary_cpu_entry(void)
diff --git a/include/skiboot.h b/include/skiboot.h
index bba76c12c39e..432008cf1d11 100644
--- a/include/skiboot.h
+++ b/include/skiboot.h
@@ -184,7 +184,9 @@  extern int64_t opal_signal_system_reset(int cpu_nr);
 extern void disable_fast_reboot(const char *reason);
 extern void fast_reboot(void);
 extern void __noreturn __secondary_cpu_entry(void);
-extern void __noreturn load_and_boot_kernel(bool is_reboot);
+extern bool load_kernel(void);
+extern void load_initramfs(void);
+extern void __noreturn boot_kernel(bool is_reboot);
 extern void cleanup_local_tlb(void);
 extern void cleanup_global_tlb(void);
 extern void init_shared_sprs(void);