[PATCH 2/3] powerpc/fadump: add support to specify memory range based size

Hari Bathini hbathini at linux.vnet.ibm.com
Fri May 6 21:50:37 AEST 2016


Currently, memory for fadump can be specified with fadump_reserve_mem=size,
where only a fixed size can be specified. This patch tries to extend this
syntax to support conditional reservation based on memory size, with the
below syntax:

	fadump_reserve_mem=<range1>:<size1>[,<range2>:<size2>,...]

This syntax helps using the same commandline parameter for different system
memory sizes.

Signed-off-by: Hari Bathini <hbathini at linux.vnet.ibm.com>
---
 arch/powerpc/kernel/fadump.c |  127 +++++++++++++++++++++++++++++++++++++++---
 1 file changed, 118 insertions(+), 9 deletions(-)

diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c
index d0af58b..a7fef3e 100644
--- a/arch/powerpc/kernel/fadump.c
+++ b/arch/powerpc/kernel/fadump.c
@@ -193,6 +193,121 @@ static unsigned long init_fadump_mem_struct(struct fadump_mem_struct *fdm,
 	return addr;
 }
 
+#define FADUMP_MEM_CMDLINE_PREFIX		"fadump_reserve_mem="
+
+static __init char *get_last_fadump_reserve_mem(void)
+{
+	char *p = boot_command_line, *fadump_cmdline = NULL;
+
+	/* find fadump_reserve_mem and use the last one if there are more */
+	p = strstr(p, FADUMP_MEM_CMDLINE_PREFIX);
+	while (p) {
+		fadump_cmdline = p;
+		p = strstr(p+1, FADUMP_MEM_CMDLINE_PREFIX);
+	}
+
+	return fadump_cmdline;
+}
+
+#define parse_fadump_print(fmt, arg...) \
+	printk(KERN_INFO "fadump_reserve_mem: "	fmt, ##arg)
+
+/*
+ * This function parses command line for fadump_reserve_mem=
+ *
+ * Supports the below two syntaxes:
+ *    1. fadump_reserve_mem=size
+ *    2. fadump_reserve_mem=ramsize-range:size[,...]
+ *
+ * Sets fw_dump.reserve_bootvar with the memory size
+ * provided, 0 otherwise
+ *
+ * The function returns -EINVAL on failure, 0 otherwise.
+ */
+static int __init parse_fadump_reserve_mem(void)
+{
+	char *cur, *tmp;
+	char *first_colon, *first_space;
+	char *fadump_cmdline;
+	unsigned long long system_ram;
+
+	fw_dump.reserve_bootvar = 0;
+	fadump_cmdline = get_last_fadump_reserve_mem();
+
+	/* when no fadump_reserve_mem= cmdline option is provided */
+	if (!fadump_cmdline)
+		return 0;
+
+	first_colon = strchr(fadump_cmdline, ':');
+	first_space = strchr(fadump_cmdline, ' ');
+	cur = fadump_cmdline + strlen(FADUMP_MEM_CMDLINE_PREFIX);
+
+	/* for fadump_reserve_mem=size cmdline syntax */
+	if (!first_colon || (first_space && (first_colon > first_space))) {
+		fw_dump.reserve_bootvar = memparse(cur, &cur);
+		return 0;
+	}
+
+	/* for fadump_reserve_mem=ramsize-range:size[,...] cmdline syntax */
+	system_ram = memblock_phys_mem_size();
+	/* for each entry of the comma-separated list */
+	do {
+		unsigned long long start, end = ULLONG_MAX, size;
+
+		/* get the start of the range */
+		start = memparse(cur, &tmp);
+		if (cur == tmp) {
+			parse_fadump_print("Memory value expected\n");
+			return -EINVAL;
+		}
+		cur = tmp;
+		if (*cur != '-') {
+			parse_fadump_print("'-' expected\n");
+			return -EINVAL;
+		}
+		cur++;
+
+		/* if no ':' is here, than we read the end */
+		if (*cur != ':') {
+			end = memparse(cur, &tmp);
+			if (cur == tmp) {
+				parse_fadump_print("Memory value expected\n");
+				return -EINVAL;
+			}
+			cur = tmp;
+			if (end <= start) {
+				parse_fadump_print("end <= start\n");
+				return -EINVAL;
+			}
+		}
+
+		if (*cur != ':') {
+			parse_fadump_print("':' expected\n");
+			return -EINVAL;
+		}
+		cur++;
+
+		size = memparse(cur, &tmp);
+		if (cur == tmp) {
+			parse_fadump_print("Memory value expected\n");
+			return -EINVAL;
+		}
+		cur = tmp;
+		if (size >= system_ram) {
+			parse_fadump_print("invalid size\n");
+			return -EINVAL;
+		}
+
+		/* match ? */
+		if (system_ram >= start && system_ram < end) {
+			fw_dump.reserve_bootvar = size;
+			break;
+		}
+	} while (*cur++ == ',');
+
+	return 0;
+}
+
 /**
  * fadump_calculate_reserve_size(): reserve variable boot area 5% of System RAM
  *
@@ -212,6 +327,9 @@ static inline unsigned long fadump_calculate_reserve_size(void)
 {
 	unsigned long size;
 
+	/* sets fw_dump.reserve_bootvar */
+	parse_fadump_reserve_mem();
+
 	/*
 	 * Check if the size is specified through fadump_reserve_mem= cmdline
 	 * option. If yes, then use that.
@@ -352,15 +470,6 @@ static int __init early_fadump_param(char *p)
 }
 early_param("fadump", early_fadump_param);
 
-/* Look for fadump_reserve_mem= cmdline option */
-static int __init early_fadump_reserve_mem(char *p)
-{
-	if (p)
-		fw_dump.reserve_bootvar = memparse(p, &p);
-	return 0;
-}
-early_param("fadump_reserve_mem", early_fadump_reserve_mem);
-
 static void register_fw_dump(struct fadump_mem_struct *fdm)
 {
 	int rc;



More information about the Linuxppc-dev mailing list