Michal Suchanek b33ae5
From e4fc48fb4d34f7e7d42eb980a9c130bb93aba3b9 Mon Sep 17 00:00:00 2001
Michal Suchanek b33ae5
From: Hari Bathini <hbathini@linux.ibm.com>
Michal Suchanek b33ae5
Date: Wed, 11 Sep 2019 20:25:05 +0530
Michal Suchanek b33ae5
Subject: [PATCH] powerpc/fadump: make crash memory ranges array allocation
Michal Suchanek b33ae5
 generic
Michal Suchanek b33ae5
Michal Suchanek b33ae5
References: bsc#1103269 ltc#169948 git-fixes
Michal Suchanek b33ae5
Patch-mainline: v5.4-rc1
Michal Suchanek b33ae5
Git-commit: e4fc48fb4d34f7e7d42eb980a9c130bb93aba3b9
Michal Suchanek b33ae5
Michal Suchanek b33ae5
Make allocate_crash_memory_ranges() and free_crash_memory_ranges()
Michal Suchanek b33ae5
functions generic to reuse them for memory management of all types of
Michal Suchanek b33ae5
dynamic memory range arrays. This change helps in memory management
Michal Suchanek b33ae5
of reserved ranges array to be added later.
Michal Suchanek b33ae5
Michal Suchanek b33ae5
Signed-off-by: Hari Bathini <hbathini@linux.ibm.com>
Michal Suchanek b33ae5
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Michal Suchanek b33ae5
Link: https://lore.kernel.org/r/156821369863.5656.4375667005352155892.stgit@hbathini.in.ibm.com
Michal Suchanek b33ae5
Acked-by: Michal Suchanek <msuchanek@suse.de>
Michal Suchanek b33ae5
---
Michal Suchanek b33ae5
 arch/powerpc/include/asm/fadump-internal.h |  15 ++-
Michal Suchanek b33ae5
 arch/powerpc/kernel/fadump.c               | 113 +++++++++++----------
Michal Suchanek b33ae5
 2 files changed, 72 insertions(+), 56 deletions(-)
Michal Suchanek b33ae5
Michal Suchanek b33ae5
diff --git a/arch/powerpc/include/asm/fadump-internal.h b/arch/powerpc/include/asm/fadump-internal.h
Michal Suchanek b33ae5
--- a/arch/powerpc/include/asm/fadump.h
Michal Suchanek b33ae5
+++ b/arch/powerpc/include/asm/fadump.h
Michal Suchanek b33ae5
@@ -72,9 +72,18 @@ struct fadump_crash_info_header {
Michal Suchanek b33ae5
 	struct cpumask	online_mask;
Michal Suchanek b33ae5
 };
Michal Suchanek b33ae5
 
Michal Suchanek b33ae5
-struct fad_crash_memory_ranges {
Michal Suchanek b33ae5
-	unsigned long long	base;
Michal Suchanek b33ae5
-	unsigned long long	size;
Michal Suchanek b33ae5
+struct fadump_memory_range {
Michal Suchanek b33ae5
+	u64	base;
Michal Suchanek b33ae5
+	u64	size;
Michal Suchanek b33ae5
+};
Michal Suchanek b33ae5
+
Michal Suchanek b33ae5
+/* fadump memory ranges info */
Michal Suchanek b33ae5
+struct fadump_mrange_info {
Michal Suchanek b33ae5
+	char				name[16];
Michal Suchanek b33ae5
+	struct fadump_memory_range	*mem_ranges;
Michal Suchanek b33ae5
+	u32				mem_ranges_sz;
Michal Suchanek b33ae5
+	u32				mem_range_cnt;
Michal Suchanek b33ae5
+	u32				max_mem_ranges;
Michal Suchanek b33ae5
 };
Michal Suchanek b33ae5
 
Michal Suchanek b33ae5
 extern int is_fadump_memory_area(u64 addr, ulong size);
Michal Suchanek b33ae5
diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c
Michal Suchanek b33ae5
--- a/arch/powerpc/kernel/fadump.c
Michal Suchanek b33ae5
+++ b/arch/powerpc/kernel/fadump.c
Michal Suchanek b33ae5
@@ -35,10 +35,7 @@
Michal Suchanek b33ae5
 #endif
Michal Suchanek b33ae5
 
Michal Suchanek b33ae5
 static DEFINE_MUTEX(fadump_mutex);
Michal Suchanek b33ae5
-struct fad_crash_memory_ranges *crash_memory_ranges;
Michal Suchanek b33ae5
-int crash_memory_ranges_size;
Michal Suchanek b33ae5
-int crash_mem_ranges;
Michal Suchanek b33ae5
-int max_crash_mem_ranges;
Michal Suchanek b33ae5
+struct fadump_mrange_info crash_mrange_info = { "crash", NULL, 0, 0, 0 };
Michal Suchanek b33ae5
 
Michal Suchanek b33ae5
 #ifdef CONFIG_CMA
Michal Suchanek b33ae5
 /*
Michal Suchanek b33ae5
@@ -629,46 +626,48 @@ void fadump_free_cpu_notes_buf(void)
Michal Suchanek b33ae5
 	return 0;
Michal Suchanek b33ae5
 }
Michal Suchanek b33ae5
 
Michal Suchanek b33ae5
-static void free_crash_memory_ranges(void)
Michal Suchanek b33ae5
+static void fadump_free_mem_ranges(struct fadump_mrange_info *mrange_info)
Michal Suchanek b33ae5
 {
Michal Suchanek b33ae5
-	kfree(crash_memory_ranges);
Michal Suchanek b33ae5
-	crash_memory_ranges = NULL;
Michal Suchanek b33ae5
-	crash_memory_ranges_size = 0;
Michal Suchanek b33ae5
-	max_crash_mem_ranges = 0;
Michal Suchanek b33ae5
+	kfree(mrange_info->mem_ranges);
Michal Suchanek b33ae5
+	mrange_info->mem_ranges = NULL;
Michal Suchanek b33ae5
+	mrange_info->mem_ranges_sz = 0;
Michal Suchanek b33ae5
+	mrange_info->max_mem_ranges = 0;
Michal Suchanek b33ae5
 }
Michal Suchanek b33ae5
 
Michal Suchanek b33ae5
 /*
Michal Suchanek b33ae5
- * Allocate or reallocate crash memory ranges array in incremental units
Michal Suchanek b33ae5
+ * Allocate or reallocate mem_ranges array in incremental units
Michal Suchanek b33ae5
  * of PAGE_SIZE.
Michal Suchanek b33ae5
  */
Michal Suchanek b33ae5
-static int allocate_crash_memory_ranges(void)
Michal Suchanek b33ae5
+static int fadump_alloc_mem_ranges(struct fadump_mrange_info *mrange_info)
Michal Suchanek b33ae5
 {
Michal Suchanek b33ae5
-	struct fad_crash_memory_ranges *new_array;
Michal Suchanek b33ae5
+	struct fadump_memory_range *new_array;
Michal Suchanek b33ae5
 	u64 new_size;
Michal Suchanek b33ae5
 
Michal Suchanek b33ae5
-	new_size = crash_memory_ranges_size + PAGE_SIZE;
Michal Suchanek b33ae5
-	pr_debug("Allocating %llu bytes of memory for crash memory ranges\n",
Michal Suchanek b33ae5
-		 new_size);
Michal Suchanek b33ae5
+	new_size = mrange_info->mem_ranges_sz + PAGE_SIZE;
Michal Suchanek b33ae5
+	pr_debug("Allocating %llu bytes of memory for %s memory ranges\n",
Michal Suchanek b33ae5
+		 new_size, mrange_info->name);
Michal Suchanek b33ae5
 
Michal Suchanek b33ae5
-	new_array = krealloc(crash_memory_ranges, new_size, GFP_KERNEL);
Michal Suchanek b33ae5
+	new_array = krealloc(mrange_info->mem_ranges, new_size, GFP_KERNEL);
Michal Suchanek b33ae5
 	if (new_array == NULL) {
Michal Suchanek b33ae5
-		pr_err("Insufficient memory for setting up crash memory ranges\n");
Michal Suchanek b33ae5
-		free_crash_memory_ranges();
Michal Suchanek b33ae5
+		pr_err("Insufficient memory for setting up %s memory ranges\n",
Michal Suchanek b33ae5
+		       mrange_info->name);
Michal Suchanek b33ae5
+		fadump_free_mem_ranges(mrange_info);
Michal Suchanek b33ae5
 		return -ENOMEM;
Michal Suchanek b33ae5
 	}
Michal Suchanek b33ae5
 
Michal Suchanek b33ae5
-	crash_memory_ranges = new_array;
Michal Suchanek b33ae5
-	crash_memory_ranges_size = new_size;
Michal Suchanek b33ae5
-	max_crash_mem_ranges = (new_size /
Michal Suchanek b33ae5
-				sizeof(struct fad_crash_memory_ranges));
Michal Suchanek b33ae5
+	mrange_info->mem_ranges = new_array;
Michal Suchanek b33ae5
+	mrange_info->mem_ranges_sz = new_size;
Michal Suchanek b33ae5
+	mrange_info->max_mem_ranges = (new_size /
Michal Suchanek b33ae5
+				       sizeof(struct fadump_memory_range));
Michal Suchanek b33ae5
 	return 0;
Michal Suchanek b33ae5
 }
Michal Suchanek b33ae5
 
Michal Suchanek b33ae5
-static inline int fadump_add_crash_memory(unsigned long long base,
Michal Suchanek b33ae5
-					  unsigned long long end)
Michal Suchanek b33ae5
+static inline int fadump_add_mem_range(struct fadump_mrange_info *mrange_info,
Michal Suchanek b33ae5
+				       u64 base, u64 end)
Michal Suchanek b33ae5
 {
Michal Suchanek b33ae5
-	u64  start, size;
Michal Suchanek b33ae5
+	struct fadump_memory_range *mem_ranges = mrange_info->mem_ranges;
Michal Suchanek b33ae5
 	bool is_adjacent = false;
Michal Suchanek b33ae5
+	u64 start, size;
Michal Suchanek b33ae5
 
Michal Suchanek b33ae5
 	if (base == end)
Michal Suchanek b33ae5
 		return 0;
Michal Suchanek b33ae5
@@ -677,38 +676,41 @@ static inline int fadump_add_crash_memory(unsigned long long base,
Michal Suchanek b33ae5
 	 * Fold adjacent memory ranges to bring down the memory ranges/
Michal Suchanek b33ae5
 	 * PT_LOAD segments count.
Michal Suchanek b33ae5
 	 */
Michal Suchanek b33ae5
-	if (crash_mem_ranges) {
Michal Suchanek b33ae5
-		start = crash_memory_ranges[crash_mem_ranges - 1].base;
Michal Suchanek b33ae5
-		size = crash_memory_ranges[crash_mem_ranges - 1].size;
Michal Suchanek b33ae5
+	if (mrange_info->mem_range_cnt) {
Michal Suchanek b33ae5
+		start = mem_ranges[mrange_info->mem_range_cnt - 1].base;
Michal Suchanek b33ae5
+		size  = mem_ranges[mrange_info->mem_range_cnt - 1].size;
Michal Suchanek b33ae5
 
Michal Suchanek b33ae5
 		if ((start + size) == base)
Michal Suchanek b33ae5
 			is_adjacent = true;
Michal Suchanek b33ae5
 	}
Michal Suchanek b33ae5
 	if (!is_adjacent) {
Michal Suchanek b33ae5
 		/* resize the array on reaching the limit */
Michal Suchanek b33ae5
-		if (crash_mem_ranges == max_crash_mem_ranges) {
Michal Suchanek b33ae5
+		if (mrange_info->mem_range_cnt == mrange_info->max_mem_ranges) {
Michal Suchanek b33ae5
 			int ret;
Michal Suchanek b33ae5
 
Michal Suchanek b33ae5
-			ret = allocate_crash_memory_ranges();
Michal Suchanek b33ae5
+			ret = fadump_alloc_mem_ranges(mrange_info);
Michal Suchanek b33ae5
 			if (ret)
Michal Suchanek b33ae5
 				return ret;
Michal Suchanek b33ae5
+
Michal Suchanek b33ae5
+			/* Update to the new resized array */
Michal Suchanek b33ae5
+			mem_ranges = mrange_info->mem_ranges;
Michal Suchanek b33ae5
 		}
Michal Suchanek b33ae5
 
Michal Suchanek b33ae5
 		start = base;
Michal Suchanek b33ae5
-		crash_memory_ranges[crash_mem_ranges].base = start;
Michal Suchanek b33ae5
-		crash_mem_ranges++;
Michal Suchanek b33ae5
+		mem_ranges[mrange_info->mem_range_cnt].base = start;
Michal Suchanek b33ae5
+		mrange_info->mem_range_cnt++;
Michal Suchanek b33ae5
 	}
Michal Suchanek b33ae5
 
Michal Suchanek b33ae5
-	crash_memory_ranges[crash_mem_ranges - 1].size = (end - start);
Michal Suchanek b33ae5
-	pr_debug("crash_memory_range[%d] [%#016llx-%#016llx], %#llx bytes\n",
Michal Suchanek b33ae5
-		(crash_mem_ranges - 1), start, end - 1, (end - start));
Michal Suchanek b33ae5
+	mem_ranges[mrange_info->mem_range_cnt - 1].size = (end - start);
Michal Suchanek b33ae5
+	pr_debug("%s_memory_range[%d] [%#016llx-%#016llx], %#llx bytes\n",
Michal Suchanek b33ae5
+		 mrange_info->name, (mrange_info->mem_range_cnt - 1),
Michal Suchanek b33ae5
+		 start, end - 1, (end - start));
Michal Suchanek b33ae5
 	return 0;
Michal Suchanek b33ae5
 }
Michal Suchanek b33ae5
 
Michal Suchanek b33ae5
-static int fadump_exclude_reserved_area(unsigned long long start,
Michal Suchanek b33ae5
-					unsigned long long end)
Michal Suchanek b33ae5
+static int fadump_exclude_reserved_area(u64 start, u64 end)
Michal Suchanek b33ae5
 {
Michal Suchanek b33ae5
-	unsigned long long ra_start, ra_end;
Michal Suchanek b33ae5
+	u64 ra_start, ra_end;
Michal Suchanek b33ae5
 	int ret = 0;
Michal Suchanek b33ae5
 
Michal Suchanek b33ae5
 	ra_start = fw_dump.reserve_dump_area_start;
Michal Suchanek b33ae5
@@ -716,18 +718,22 @@ static int fadump_exclude_reserved_area(unsigned long long start,
Michal Suchanek b33ae5
 
Michal Suchanek b33ae5
 	if ((ra_start < end) && (ra_end > start)) {
Michal Suchanek b33ae5
 		if ((start < ra_start) && (end > ra_end)) {
Michal Suchanek b33ae5
-			ret = fadump_add_crash_memory(start, ra_start);
Michal Suchanek b33ae5
+			ret = fadump_add_mem_range(&crash_mrange_info,
Michal Suchanek b33ae5
+						   start, ra_start);
Michal Suchanek b33ae5
 			if (ret)
Michal Suchanek b33ae5
 				return ret;
Michal Suchanek b33ae5
 
Michal Suchanek b33ae5
-			ret = fadump_add_crash_memory(ra_end, end);
Michal Suchanek b33ae5
+			ret = fadump_add_mem_range(&crash_mrange_info,
Michal Suchanek b33ae5
+						   ra_end, end);
Michal Suchanek b33ae5
 		} else if (start < ra_start) {
Michal Suchanek b33ae5
-			ret = fadump_add_crash_memory(start, ra_start);
Michal Suchanek b33ae5
+			ret = fadump_add_mem_range(&crash_mrange_info,
Michal Suchanek b33ae5
+						   start, ra_start);
Michal Suchanek b33ae5
 		} else if (ra_end < end) {
Michal Suchanek b33ae5
-			ret = fadump_add_crash_memory(ra_end, end);
Michal Suchanek b33ae5
+			ret = fadump_add_mem_range(&crash_mrange_info,
Michal Suchanek b33ae5
+						   ra_end, end);
Michal Suchanek b33ae5
 		}
Michal Suchanek b33ae5
 	} else
Michal Suchanek b33ae5
-		ret = fadump_add_crash_memory(start, end);
Michal Suchanek b33ae5
+		ret = fadump_add_mem_range(&crash_mrange_info, start, end);
Michal Suchanek b33ae5
 
Michal Suchanek b33ae5
 	return ret;
Michal Suchanek b33ae5
 }
Michal Suchanek b33ae5
@@ -772,11 +778,11 @@ static int fadump_init_elfcore_header(char *bufp)
Michal Suchanek b33ae5
 static int fadump_setup_crash_memory_ranges(void)
Michal Suchanek b33ae5
 {
Michal Suchanek b33ae5
 	struct memblock_region *reg;
Michal Suchanek b33ae5
-	unsigned long long start, end;
Michal Suchanek b33ae5
+	u64 start, end;
Michal Suchanek b33ae5
 	int ret;
Michal Suchanek b33ae5
 
Michal Suchanek b33ae5
 	pr_debug("Setup crash memory ranges.\n");
Michal Suchanek b33ae5
-	crash_mem_ranges = 0;
Michal Suchanek b33ae5
+	crash_mrange_info.mem_range_cnt = 0;
Michal Suchanek b33ae5
 
Michal Suchanek b33ae5
 	/*
Michal Suchanek b33ae5
 	 * add the first memory chunk (RMA_START through boot_memory_size) as
Michal Suchanek b33ae5
@@ -785,13 +791,14 @@ static int fadump_setup_crash_memory_ranges(void)
Michal Suchanek b33ae5
 	 * specified during fadump registration. We need to create a separate
Michal Suchanek b33ae5
 	 * program header for this chunk with the correct offset.
Michal Suchanek b33ae5
 	 */
Michal Suchanek b33ae5
-	ret = fadump_add_crash_memory(RMA_START, fw_dump.boot_memory_size);
Michal Suchanek b33ae5
+	ret = fadump_add_mem_range(&crash_mrange_info,
Michal Suchanek b33ae5
+				   RMA_START, fw_dump.boot_memory_size);
Michal Suchanek b33ae5
 	if (ret)
Michal Suchanek b33ae5
 		return ret;
Michal Suchanek b33ae5
 
Michal Suchanek b33ae5
 	for_each_memblock(memory, reg) {
Michal Suchanek b33ae5
-		start = (unsigned long long)reg->base;
Michal Suchanek b33ae5
-		end = start + (unsigned long long)reg->size;
Michal Suchanek b33ae5
+		start = (u64)reg->base;
Michal Suchanek b33ae5
+		end = start + (u64)reg->size;
Michal Suchanek b33ae5
 
Michal Suchanek b33ae5
 		/*
Michal Suchanek b33ae5
 		 * skip the first memory chunk that is already added (RMA_START
Michal Suchanek b33ae5
@@ -876,11 +883,11 @@ static int fadump_create_elfcore_headers(char *bufp)
Michal Suchanek b33ae5
 
Michal Suchanek b33ae5
 	/* setup PT_LOAD sections. */
Michal Suchanek b33ae5
 
Michal Suchanek b33ae5
-	for (i = 0; i < crash_mem_ranges; i++) {
Michal Suchanek b33ae5
-		unsigned long long mbase, msize;
Michal Suchanek b33ae5
-		mbase = crash_memory_ranges[i].base;
Michal Suchanek b33ae5
-		msize = crash_memory_ranges[i].size;
Michal Suchanek b33ae5
+	for (i = 0; i < crash_mrange_info.mem_range_cnt; i++) {
Michal Suchanek b33ae5
+		u64 mbase, msize;
Michal Suchanek b33ae5
 
Michal Suchanek b33ae5
+		mbase = crash_mrange_info.mem_ranges[i].base;
Michal Suchanek b33ae5
+		msize = crash_mrange_info.mem_ranges[i].size;
Michal Suchanek b33ae5
 		if (!msize)
Michal Suchanek b33ae5
 			continue;
Michal Suchanek b33ae5
 
Michal Suchanek b33ae5
@@ -973,7 +980,7 @@ void fadump_cleanup(void)
Michal Suchanek b33ae5
 	} else if (fw_dump.dump_registered) {
Michal Suchanek b33ae5
 		/* Un-register Firmware-assisted dump if it was registered. */
Michal Suchanek b33ae5
 		fadump_unregister_dump(&fdm);
Michal Suchanek b33ae5
-		free_crash_memory_ranges();
Michal Suchanek b33ae5
+		fadump_free_mem_ranges(&crash_mrange_info);
Michal Suchanek b33ae5
 	}
Michal Suchanek b33ae5
 }
Michal Suchanek b33ae5
 
Michal Suchanek b33ae5
-- 
Michal Suchanek b33ae5
2.35.3
Michal Suchanek b33ae5