s390: move ipl block and cmd line handling to early boot phase
authorVasily Gorbik <gor@linux.ibm.com>
Tue, 15 May 2018 11:28:53 +0000 (13:28 +0200)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Tue, 9 Oct 2018 09:21:14 +0000 (11:21 +0200)
To distinguish zfcpdump case and to be able to parse some of the kernel
command line arguments early (e.g. mem=) ipl block retrieval and command
line construction code is moved to the early boot phase.

"memory_end" is set up correctly respecting "mem=" and hsa_size in case
of the zfcpdump.

arch/s390/boot/string.c is introduced to provide string handling and
command line parsing functions to early boot phase code for the compressed
kernel image case.

Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
15 files changed:
arch/s390/boot/Makefile
arch/s390/boot/boot.h
arch/s390/boot/cmdline.c [new file with mode: 0644]
arch/s390/boot/ctype.c [new file with mode: 0644]
arch/s390/boot/ipl_parm.c [new file with mode: 0644]
arch/s390/boot/ipl_vmparm.c [new file with mode: 0644]
arch/s390/boot/startup.c
arch/s390/boot/string.c [new file with mode: 0644]
arch/s390/include/asm/boot_data.h [new file with mode: 0644]
arch/s390/include/asm/ipl.h
arch/s390/kernel/Makefile
arch/s390/kernel/early.c
arch/s390/kernel/ipl.c
arch/s390/kernel/ipl_vmparm.c [new file with mode: 0644]
arch/s390/kernel/setup.c

index b6903c4..f58edd8 100644 (file)
@@ -27,7 +27,8 @@ endif
 
 CFLAGS_sclp_early_core.o += -I$(srctree)/drivers/s390/char
 
-obj-y  := head.o als.o startup.o mem_detect.o ebcdic.o sclp_early_core.o mem.o
+obj-y  := head.o als.o startup.o mem_detect.o ipl_parm.o string.o ebcdic.o
+obj-y  += sclp_early_core.o mem.o ipl_vmparm.o cmdline.o ctype.o
 targets        := bzImage startup.a section_cmp.boot.data $(obj-y)
 subdir-        := compressed
 
index 808154b..fc41e22 100644 (file)
@@ -4,5 +4,8 @@
 
 void startup_kernel(void);
 void detect_memory(void);
+void store_ipl_parmblock(void);
+void setup_boot_command_line(void);
+void setup_memory_end(void);
 
 #endif /* BOOT_BOOT_H */
diff --git a/arch/s390/boot/cmdline.c b/arch/s390/boot/cmdline.c
new file mode 100644 (file)
index 0000000..73d826c
--- /dev/null
@@ -0,0 +1,2 @@
+// SPDX-License-Identifier: GPL-2.0
+#include "../../../lib/cmdline.c"
diff --git a/arch/s390/boot/ctype.c b/arch/s390/boot/ctype.c
new file mode 100644 (file)
index 0000000..2495810
--- /dev/null
@@ -0,0 +1,2 @@
+// SPDX-License-Identifier: GPL-2.0
+#include "../../../lib/ctype.c"
diff --git a/arch/s390/boot/ipl_parm.c b/arch/s390/boot/ipl_parm.c
new file mode 100644 (file)
index 0000000..7f8e546
--- /dev/null
@@ -0,0 +1,173 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/init.h>
+#include <linux/ctype.h>
+#include <asm/ebcdic.h>
+#include <asm/sclp.h>
+#include <asm/sections.h>
+#include <asm/boot_data.h>
+#include "boot.h"
+
+char __bootdata(early_command_line)[COMMAND_LINE_SIZE];
+struct ipl_parameter_block __bootdata(early_ipl_block);
+int __bootdata(early_ipl_block_valid);
+
+unsigned long __bootdata(memory_end);
+int __bootdata(memory_end_set);
+
+static inline int __diag308(unsigned long subcode, void *addr)
+{
+       register unsigned long _addr asm("0") = (unsigned long)addr;
+       register unsigned long _rc asm("1") = 0;
+       unsigned long reg1, reg2;
+       psw_t old = S390_lowcore.program_new_psw;
+
+       asm volatile(
+               "       epsw    %0,%1\n"
+               "       st      %0,%[psw_pgm]\n"
+               "       st      %1,%[psw_pgm]+4\n"
+               "       larl    %0,1f\n"
+               "       stg     %0,%[psw_pgm]+8\n"
+               "       diag    %[addr],%[subcode],0x308\n"
+               "1:     nopr    %%r7\n"
+               : "=&d" (reg1), "=&a" (reg2),
+                 [psw_pgm] "=Q" (S390_lowcore.program_new_psw),
+                 [addr] "+d" (_addr), "+d" (_rc)
+               : [subcode] "d" (subcode)
+               : "cc", "memory");
+       S390_lowcore.program_new_psw = old;
+       return _rc;
+}
+
+void store_ipl_parmblock(void)
+{
+       int rc;
+
+       rc = __diag308(DIAG308_STORE, &early_ipl_block);
+       if (rc == DIAG308_RC_OK &&
+           early_ipl_block.hdr.version <= IPL_MAX_SUPPORTED_VERSION)
+               early_ipl_block_valid = 1;
+}
+
+static size_t scpdata_length(const char *buf, size_t count)
+{
+       while (count) {
+               if (buf[count - 1] != '\0' && buf[count - 1] != ' ')
+                       break;
+               count--;
+       }
+       return count;
+}
+
+static size_t ipl_block_get_ascii_scpdata(char *dest, size_t size,
+                                         const struct ipl_parameter_block *ipb)
+{
+       size_t count;
+       size_t i;
+       int has_lowercase;
+
+       count = min(size - 1, scpdata_length(ipb->ipl_info.fcp.scp_data,
+                                            ipb->ipl_info.fcp.scp_data_len));
+       if (!count)
+               goto out;
+
+       has_lowercase = 0;
+       for (i = 0; i < count; i++) {
+               if (!isascii(ipb->ipl_info.fcp.scp_data[i])) {
+                       count = 0;
+                       goto out;
+               }
+               if (!has_lowercase && islower(ipb->ipl_info.fcp.scp_data[i]))
+                       has_lowercase = 1;
+       }
+
+       if (has_lowercase)
+               memcpy(dest, ipb->ipl_info.fcp.scp_data, count);
+       else
+               for (i = 0; i < count; i++)
+                       dest[i] = tolower(ipb->ipl_info.fcp.scp_data[i]);
+out:
+       dest[count] = '\0';
+       return count;
+}
+
+static void append_ipl_block_parm(void)
+{
+       char *parm, *delim;
+       size_t len, rc = 0;
+
+       len = strlen(early_command_line);
+
+       delim = early_command_line + len;    /* '\0' character position */
+       parm = early_command_line + len + 1; /* append right after '\0' */
+
+       switch (early_ipl_block.hdr.pbt) {
+       case DIAG308_IPL_TYPE_CCW:
+               rc = ipl_block_get_ascii_vmparm(
+                       parm, COMMAND_LINE_SIZE - len - 1, &early_ipl_block);
+               break;
+       case DIAG308_IPL_TYPE_FCP:
+               rc = ipl_block_get_ascii_scpdata(
+                       parm, COMMAND_LINE_SIZE - len - 1, &early_ipl_block);
+               break;
+       }
+       if (rc) {
+               if (*parm == '=')
+                       memmove(early_command_line, parm + 1, rc);
+               else
+                       *delim = ' '; /* replace '\0' with space */
+       }
+}
+
+static inline int has_ebcdic_char(const char *str)
+{
+       int i;
+
+       for (i = 0; str[i]; i++)
+               if (str[i] & 0x80)
+                       return 1;
+       return 0;
+}
+
+void setup_boot_command_line(void)
+{
+       COMMAND_LINE[ARCH_COMMAND_LINE_SIZE - 1] = 0;
+       /* convert arch command line to ascii if necessary */
+       if (has_ebcdic_char(COMMAND_LINE))
+               EBCASC(COMMAND_LINE, ARCH_COMMAND_LINE_SIZE);
+       /* copy arch command line */
+       strcpy(early_command_line, strim(COMMAND_LINE));
+
+       /* append IPL PARM data to the boot command line */
+       if (early_ipl_block_valid)
+               append_ipl_block_parm();
+}
+
+static char command_line_buf[COMMAND_LINE_SIZE] __section(.data);
+static void parse_mem_opt(void)
+{
+       char *args;
+       char *param, *val;
+
+       args = strcpy(command_line_buf, early_command_line);
+       while (*args) {
+               args = next_arg(args, &param, &val);
+
+               if (!strcmp(param, "mem")) {
+                       memory_end = memparse(val, NULL);
+                       memory_end_set = 1;
+               }
+       }
+}
+
+void setup_memory_end(void)
+{
+       parse_mem_opt();
+#ifdef CONFIG_CRASH_DUMP
+       if (!OLDMEM_BASE && early_ipl_block_valid &&
+           early_ipl_block.hdr.pbt == DIAG308_IPL_TYPE_FCP &&
+           early_ipl_block.ipl_info.fcp.opt == DIAG308_IPL_OPT_DUMP) {
+               if (!sclp_early_get_hsa_size(&memory_end) && memory_end)
+                       memory_end_set = 1;
+       }
+#endif
+}
diff --git a/arch/s390/boot/ipl_vmparm.c b/arch/s390/boot/ipl_vmparm.c
new file mode 100644 (file)
index 0000000..8dacd5f
--- /dev/null
@@ -0,0 +1,2 @@
+// SPDX-License-Identifier: GPL-2.0
+#include "../kernel/ipl_vmparm.c"
index b0e9f46..4d44131 100644 (file)
@@ -51,6 +51,9 @@ void startup_kernel(void)
 
        rescue_initrd();
        sclp_early_read_info();
+       store_ipl_parmblock();
+       setup_boot_command_line();
+       setup_memory_end();
        detect_memory();
        if (!IS_ENABLED(CONFIG_KERNEL_UNCOMPRESSED)) {
                img = decompress_kernel();
diff --git a/arch/s390/boot/string.c b/arch/s390/boot/string.c
new file mode 100644 (file)
index 0000000..09ca913
--- /dev/null
@@ -0,0 +1,100 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/ctype.h>
+#include <linux/kernel.h>
+#include "../lib/string.c"
+
+int strncmp(const char *cs, const char *ct, size_t count)
+{
+       unsigned char c1, c2;
+
+       while (count) {
+               c1 = *cs++;
+               c2 = *ct++;
+               if (c1 != c2)
+                       return c1 < c2 ? -1 : 1;
+               if (!c1)
+                       break;
+               count--;
+       }
+       return 0;
+}
+
+char *skip_spaces(const char *str)
+{
+       while (isspace(*str))
+               ++str;
+       return (char *)str;
+}
+
+char *strim(char *s)
+{
+       size_t size;
+       char *end;
+
+       size = strlen(s);
+       if (!size)
+               return s;
+
+       end = s + size - 1;
+       while (end >= s && isspace(*end))
+               end--;
+       *(end + 1) = '\0';
+
+       return skip_spaces(s);
+}
+
+/* Works only for digits and letters, but small and fast */
+#define TOLOWER(x) ((x) | 0x20)
+
+static unsigned int simple_guess_base(const char *cp)
+{
+       if (cp[0] == '0') {
+               if (TOLOWER(cp[1]) == 'x' && isxdigit(cp[2]))
+                       return 16;
+               else
+                       return 8;
+       } else {
+               return 10;
+       }
+}
+
+/**
+ * simple_strtoull - convert a string to an unsigned long long
+ * @cp: The start of the string
+ * @endp: A pointer to the end of the parsed string will be placed here
+ * @base: The number base to use
+ */
+
+unsigned long long simple_strtoull(const char *cp, char **endp,
+                                  unsigned int base)
+{
+       unsigned long long result = 0;
+
+       if (!base)
+               base = simple_guess_base(cp);
+
+       if (base == 16 && cp[0] == '0' && TOLOWER(cp[1]) == 'x')
+               cp += 2;
+
+       while (isxdigit(*cp)) {
+               unsigned int value;
+
+               value = isdigit(*cp) ? *cp - '0' : TOLOWER(*cp) - 'a' + 10;
+               if (value >= base)
+                       break;
+               result = result * base + value;
+               cp++;
+       }
+       if (endp)
+               *endp = (char *)cp;
+
+       return result;
+}
+
+long simple_strtol(const char *cp, char **endp, unsigned int base)
+{
+       if (*cp == '-')
+               return -simple_strtoull(cp + 1, endp, base);
+
+       return simple_strtoull(cp, endp, base);
+}
diff --git a/arch/s390/include/asm/boot_data.h b/arch/s390/include/asm/boot_data.h
new file mode 100644 (file)
index 0000000..2d999cc
--- /dev/null
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_S390_BOOT_DATA_H
+
+#include <asm/setup.h>
+#include <asm/ipl.h>
+
+extern char early_command_line[COMMAND_LINE_SIZE];
+extern struct ipl_parameter_block early_ipl_block;
+extern int early_ipl_block_valid;
+
+#endif /* _ASM_S390_BOOT_DATA_H */
index ae51357..a8389e2 100644 (file)
@@ -89,8 +89,8 @@ void __init save_area_add_vxrs(struct save_area *, __vector128 *vxrs);
 
 extern void s390_reset_system(void);
 extern void ipl_store_parameters(void);
-extern size_t append_ipl_vmparm(char *, size_t);
-extern size_t append_ipl_scpdata(char *, size_t);
+extern size_t ipl_block_get_ascii_vmparm(char *dest, size_t size,
+                                        const struct ipl_parameter_block *ipb);
 
 enum ipl_type {
        IPL_TYPE_UNKNOWN        = 1,
index dbfd173..7ad6fa6 100644 (file)
@@ -47,7 +47,7 @@ obj-y += debug.o irq.o ipl.o dis.o diag.o vdso.o early_nobss.o
 obj-y  += sysinfo.o jump_label.o lgr.o os_info.o machine_kexec.o pgm_check.o
 obj-y  += runtime_instr.o cache.o fpu.o dumpstack.o guarded_storage.o sthyi.o
 obj-y  += entry.o reipl.o relocate_kernel.o kdebugfs.o alternative.o
-obj-y  += nospec-branch.o
+obj-y  += nospec-branch.o ipl_vmparm.o
 
 extra-y                                += head64.o vmlinux.lds
 
index 5b28b43..af5c2b3 100644 (file)
 #include <asm/cpcmd.h>
 #include <asm/sclp.h>
 #include <asm/facility.h>
+#include <asm/boot_data.h>
 #include "entry.h"
 
-static void __init setup_boot_command_line(void);
-
 /*
  * Initialize storage key for kernel pages
  */
@@ -284,51 +283,11 @@ static int __init cad_setup(char *str)
 }
 early_param("cad", cad_setup);
 
-/* Set up boot command line */
-static void __init append_to_cmdline(size_t (*ipl_data)(char *, size_t))
-{
-       char *parm, *delim;
-       size_t rc, len;
-
-       len = strlen(boot_command_line);
-
-       delim = boot_command_line + len;        /* '\0' character position */
-       parm  = boot_command_line + len + 1;    /* append right after '\0' */
-
-       rc = ipl_data(parm, COMMAND_LINE_SIZE - len - 1);
-       if (rc) {
-               if (*parm == '=')
-                       memmove(boot_command_line, parm + 1, rc);
-               else
-                       *delim = ' ';           /* replace '\0' with space */
-       }
-}
-
-static inline int has_ebcdic_char(const char *str)
-{
-       int i;
-
-       for (i = 0; str[i]; i++)
-               if (str[i] & 0x80)
-                       return 1;
-       return 0;
-}
-
+char __bootdata(early_command_line)[COMMAND_LINE_SIZE];
 static void __init setup_boot_command_line(void)
 {
-       COMMAND_LINE[ARCH_COMMAND_LINE_SIZE - 1] = 0;
-       /* convert arch command line to ascii if necessary */
-       if (has_ebcdic_char(COMMAND_LINE))
-               EBCASC(COMMAND_LINE, ARCH_COMMAND_LINE_SIZE);
        /* copy arch command line */
-       strlcpy(boot_command_line, strstrip(COMMAND_LINE),
-               ARCH_COMMAND_LINE_SIZE);
-
-       /* append IPL PARM data to the boot command line */
-       if (MACHINE_IS_VM)
-               append_to_cmdline(append_ipl_vmparm);
-
-       append_to_cmdline(append_ipl_scpdata);
+       strlcpy(boot_command_line, early_command_line, ARCH_COMMAND_LINE_SIZE);
 }
 
 static void __init check_image_bootable(void)
index 4296d7e..f1d69f7 100644 (file)
@@ -29,6 +29,8 @@
 #include <asm/checksum.h>
 #include <asm/debug.h>
 #include <asm/os_info.h>
+#include <asm/sections.h>
+#include <asm/boot_data.h>
 #include "entry.h"
 
 #define IPL_PARM_BLOCK_VERSION 0
@@ -117,6 +119,9 @@ static char *dump_type_str(enum dump_type type)
        }
 }
 
+struct ipl_parameter_block __bootdata(early_ipl_block);
+int __bootdata(early_ipl_block_valid);
+
 static int ipl_block_valid;
 static struct ipl_parameter_block ipl_block;
 
@@ -262,115 +267,16 @@ static ssize_t ipl_type_show(struct kobject *kobj, struct kobj_attribute *attr,
 
 static struct kobj_attribute sys_ipl_type_attr = __ATTR_RO(ipl_type);
 
-/* VM IPL PARM routines */
-static size_t reipl_get_ascii_vmparm(char *dest, size_t size,
-                                    const struct ipl_parameter_block *ipb)
-{
-       int i;
-       size_t len;
-       char has_lowercase = 0;
-
-       len = 0;
-       if ((ipb->ipl_info.ccw.vm_flags & DIAG308_VM_FLAGS_VP_VALID) &&
-           (ipb->ipl_info.ccw.vm_parm_len > 0)) {
-
-               len = min_t(size_t, size - 1, ipb->ipl_info.ccw.vm_parm_len);
-               memcpy(dest, ipb->ipl_info.ccw.vm_parm, len);
-               /* If at least one character is lowercase, we assume mixed
-                * case; otherwise we convert everything to lowercase.
-                */
-               for (i = 0; i < len; i++)
-                       if ((dest[i] > 0x80 && dest[i] < 0x8a) || /* a-i */
-                           (dest[i] > 0x90 && dest[i] < 0x9a) || /* j-r */
-                           (dest[i] > 0xa1 && dest[i] < 0xaa)) { /* s-z */
-                               has_lowercase = 1;
-                               break;
-                       }
-               if (!has_lowercase)
-                       EBC_TOLOWER(dest, len);
-               EBCASC(dest, len);
-       }
-       dest[len] = 0;
-
-       return len;
-}
-
-size_t append_ipl_vmparm(char *dest, size_t size)
-{
-       size_t rc;
-
-       rc = 0;
-       if (ipl_block_valid && ipl_block.hdr.pbt == DIAG308_IPL_TYPE_CCW)
-               rc = reipl_get_ascii_vmparm(dest, size, &ipl_block);
-       else
-               dest[0] = 0;
-       return rc;
-}
-
 static ssize_t ipl_vm_parm_show(struct kobject *kobj,
                                struct kobj_attribute *attr, char *page)
 {
        char parm[DIAG308_VMPARM_SIZE + 1] = {};
 
-       append_ipl_vmparm(parm, sizeof(parm));
+       if (ipl_block_valid && (ipl_block.hdr.pbt == DIAG308_IPL_TYPE_CCW))
+               ipl_block_get_ascii_vmparm(parm, sizeof(parm), &ipl_block);
        return sprintf(page, "%s\n", parm);
 }
 
-static size_t scpdata_length(const char* buf, size_t count)
-{
-       while (count) {
-               if (buf[count - 1] != '\0' && buf[count - 1] != ' ')
-                       break;
-               count--;
-       }
-       return count;
-}
-
-static size_t reipl_append_ascii_scpdata(char *dest, size_t size,
-                                        const struct ipl_parameter_block *ipb)
-{
-       size_t count;
-       size_t i;
-       int has_lowercase;
-
-       count = min(size - 1, scpdata_length(ipb->ipl_info.fcp.scp_data,
-                                            ipb->ipl_info.fcp.scp_data_len));
-       if (!count)
-               goto out;
-
-       has_lowercase = 0;
-       for (i = 0; i < count; i++) {
-               if (!isascii(ipb->ipl_info.fcp.scp_data[i])) {
-                       count = 0;
-                       goto out;
-               }
-               if (!has_lowercase && islower(ipb->ipl_info.fcp.scp_data[i]))
-                       has_lowercase = 1;
-       }
-
-       if (has_lowercase)
-               memcpy(dest, ipb->ipl_info.fcp.scp_data, count);
-       else
-               for (i = 0; i < count; i++)
-                       dest[i] = tolower(ipb->ipl_info.fcp.scp_data[i]);
-out:
-       dest[count] = '\0';
-       return count;
-}
-
-size_t append_ipl_scpdata(char *dest, size_t len)
-{
-       size_t rc;
-
-       rc = 0;
-       if (ipl_block_valid && ipl_block.hdr.pbt == DIAG308_IPL_TYPE_FCP)
-               rc = reipl_append_ascii_scpdata(dest, len, &ipl_block);
-       else
-               dest[0] = 0;
-       return rc;
-}
-
-
 static struct kobj_attribute sys_ipl_vm_parm_attr =
        __ATTR(parm, S_IRUGO, ipl_vm_parm_show, NULL);
 
@@ -564,7 +470,7 @@ static ssize_t reipl_generic_vmparm_show(struct ipl_parameter_block *ipb,
 {
        char vmparm[DIAG308_VMPARM_SIZE + 1] = {};
 
-       reipl_get_ascii_vmparm(vmparm, sizeof(vmparm), ipb);
+       ipl_block_get_ascii_vmparm(vmparm, sizeof(vmparm), ipb);
        return sprintf(page, "%s\n", vmparm);
 }
 
@@ -1769,11 +1675,10 @@ void __init setup_ipl(void)
 
 void __init ipl_store_parameters(void)
 {
-       int rc;
-
-       rc = diag308(DIAG308_STORE, &ipl_block);
-       if (rc == DIAG308_RC_OK && ipl_block.hdr.version <= IPL_MAX_SUPPORTED_VERSION)
+       if (early_ipl_block_valid) {
+               memcpy(&ipl_block, &early_ipl_block, sizeof(ipl_block));
                ipl_block_valid = 1;
+       }
 }
 
 void s390_reset_system(void)
diff --git a/arch/s390/kernel/ipl_vmparm.c b/arch/s390/kernel/ipl_vmparm.c
new file mode 100644 (file)
index 0000000..411838c
--- /dev/null
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <asm/ebcdic.h>
+#include <asm/ipl.h>
+
+/* VM IPL PARM routines */
+size_t ipl_block_get_ascii_vmparm(char *dest, size_t size,
+                                 const struct ipl_parameter_block *ipb)
+{
+       int i;
+       size_t len;
+       char has_lowercase = 0;
+
+       len = 0;
+       if ((ipb->ipl_info.ccw.vm_flags & DIAG308_VM_FLAGS_VP_VALID) &&
+           (ipb->ipl_info.ccw.vm_parm_len > 0)) {
+
+               len = min_t(size_t, size - 1, ipb->ipl_info.ccw.vm_parm_len);
+               memcpy(dest, ipb->ipl_info.ccw.vm_parm, len);
+               /* If at least one character is lowercase, we assume mixed
+                * case; otherwise we convert everything to lowercase.
+                */
+               for (i = 0; i < len; i++)
+                       if ((dest[i] > 0x80 && dest[i] < 0x8a) || /* a-i */
+                           (dest[i] > 0x90 && dest[i] < 0x9a) || /* j-r */
+                           (dest[i] > 0xa1 && dest[i] < 0xaa)) { /* s-z */
+                               has_lowercase = 1;
+                               break;
+                       }
+               if (!has_lowercase)
+                       EBC_TOLOWER(dest, len);
+               EBCASC(dest, len);
+       }
+       dest[len] = 0;
+
+       return len;
+}
index 36fb37d..ae3810c 100644 (file)
@@ -90,8 +90,8 @@ char elf_platform[ELF_PLATFORM_SIZE];
 
 unsigned long int_hwcap = 0;
 
-int __initdata memory_end_set;
-unsigned long __initdata memory_end;
+int __bootdata(memory_end_set);
+unsigned long __bootdata(memory_end);
 unsigned long __bootdata(max_physmem_end);
 struct mem_detect_info __bootdata(mem_detect);
 
@@ -286,15 +286,6 @@ void machine_power_off(void)
 void (*pm_power_off)(void) = machine_power_off;
 EXPORT_SYMBOL_GPL(pm_power_off);
 
-static int __init early_parse_mem(char *p)
-{
-       memory_end = memparse(p, &p);
-       memory_end &= PAGE_MASK;
-       memory_end_set = 1;
-       return 0;
-}
-early_param("mem", early_parse_mem);
-
 static int __init parse_vmalloc(char *arg)
 {
        if (!arg)
@@ -605,17 +596,8 @@ static struct notifier_block kdump_mem_nb = {
  */
 static void reserve_memory_end(void)
 {
-#ifdef CONFIG_CRASH_DUMP
-       if (ipl_info.type == IPL_TYPE_FCP_DUMP &&
-           !OLDMEM_BASE && sclp.hsa_size) {
-               memory_end = sclp.hsa_size;
-               memory_end &= PAGE_MASK;
-               memory_end_set = 1;
-       }
-#endif
-       if (!memory_end_set)
-               return;
-       memblock_reserve(memory_end, ULONG_MAX);
+       if (memory_end_set)
+               memblock_reserve(memory_end, ULONG_MAX);
 }
 
 /*