s390: introduce .boot.data section
authorVasily Gorbik <gor@linux.ibm.com>
Tue, 10 Apr 2018 12:14:02 +0000 (14:14 +0200)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Tue, 9 Oct 2018 09:21:06 +0000 (11:21 +0200)
Introduce .boot.data section which is "shared" between the decompressor
code and the decompressed kernel. The decompressor will store values in
it, and copy over to the decompressed image before starting it. This
method allows to avoid using pre-defined addresses and other hacks to
pass values between those boot phases.

.boot.data section is a part of init data, and will be freed after kernel
initialization is complete.

For uncompressed kernel image, .boot.data section is basically the same
as .init.data

Reviewed-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
arch/s390/boot/compressed/decompressor.h
arch/s390/boot/compressed/vmlinux.lds.S
arch/s390/boot/startup.c
arch/s390/include/asm/sections.h
arch/s390/include/asm/vmlinux.lds.h [new file with mode: 0644]
arch/s390/kernel/vmlinux.lds.S

index b774425dcb5f879feabef631786f5b418cc39260..e1c1f2ec60f4a88d14d0c4b28732df790e2ff6bd 100644 (file)
@@ -15,6 +15,8 @@ struct vmlinux_info {
        void (*entry)(void);
        unsigned long image_size;       /* does not include .bss */
        unsigned long bss_size;         /* uncompressed image .bss size */
+       unsigned long bootdata_off;
+       unsigned long bootdata_size;
 };
 
 extern char _vmlinux_info[];
index 3814810718efc638c805e42eb463a9401e3b62aa..7efc3938f5955dae79720d5323636def4138d9df 100644 (file)
@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 #include <asm-generic/vmlinux.lds.h>
+#include <asm/vmlinux.lds.h>
 
 OUTPUT_FORMAT("elf64-s390", "elf64-s390", "elf64-s390")
 OUTPUT_ARCH(s390:64-bit)
@@ -32,6 +33,8 @@ SECTIONS
                *(.data.*)
                _edata = . ;
        }
+       BOOT_DATA
+
        /*
         * uncompressed image info used by the decompressor it should match
         * struct vmlinux_info. It comes from .vmlinux.info section of
index 81199ca4a51332936d5a6c0a80f98e0a9bff269d..e9eea37894b304baddf1028bd9a6319d77c86001 100644 (file)
@@ -5,6 +5,8 @@
 #include "compressed/decompressor.h"
 #include "boot.h"
 
+extern char __boot_data_start[], __boot_data_end[];
+
 void error(char *x)
 {
        sclp_early_printk("\n\n");
@@ -36,6 +38,13 @@ static void rescue_initrd(void)
        INITRD_START = min_initrd_addr;
 }
 
+static void copy_bootdata(void)
+{
+       if (__boot_data_end - __boot_data_start != vmlinux.bootdata_size)
+               error(".boot.data section size mismatch");
+       memcpy((void *)vmlinux.bootdata_off, __boot_data_start, vmlinux.bootdata_size);
+}
+
 void startup_kernel(void)
 {
        void *img;
@@ -45,5 +54,6 @@ void startup_kernel(void)
                img = decompress_kernel();
                memmove((void *)vmlinux.default_lma, img, vmlinux.image_size);
        }
+       copy_bootdata();
        vmlinux.entry();
 }
index 724faede8ac52d565db7b4f4d5dd40391030e9d6..7afe4620685c93aac9b4bb9efaf196aacd4b055c 100644 (file)
@@ -4,4 +4,16 @@
 
 #include <asm-generic/sections.h>
 
+/*
+ * .boot.data section contains variables "shared" between the decompressor and
+ * the decompressed kernel. The decompressor will store values in them, and
+ * copy over to the decompressed image before starting it.
+ *
+ * Each variable end up in its own intermediate section .boot.data.<var name>,
+ * those sections are later sorted by alignment + name and merged together into
+ * final .boot.data section, which should be identical in the decompressor and
+ * the decompressed kernel (that is checked during the build).
+ */
+#define __bootdata(var) __section(.boot.data.var) var
+
 #endif
diff --git a/arch/s390/include/asm/vmlinux.lds.h b/arch/s390/include/asm/vmlinux.lds.h
new file mode 100644 (file)
index 0000000..2d127f9
--- /dev/null
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#include <asm/page.h>
+
+/*
+ * .boot.data section is shared between the decompressor code and the
+ * decompressed kernel. The decompressor will store values in it, and copy
+ * over to the decompressed image before starting it.
+ *
+ * .boot.data variables are kept in separate .boot.data.<var name> sections,
+ * which are sorted by alignment first, then by name before being merged
+ * into single .boot.data section. This way big holes cased by page aligned
+ * structs are avoided and linker produces consistent result.
+ */
+#define BOOT_DATA                                                      \
+       . = ALIGN(PAGE_SIZE);                                           \
+       .boot.data : {                                                  \
+               __boot_data_start = .;                                  \
+               *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.boot.data*)))         \
+               __boot_data_end = .;                                    \
+       }
index 4c5358ff9e0598bb78b5bf63783fed1e0f23dd3b..cc3cbdc93d35b4ef21e728977a380eba82693562 100644 (file)
@@ -16,6 +16,7 @@
 #define RO_AFTER_INIT_DATA
 
 #include <asm-generic/vmlinux.lds.h>
+#include <asm/vmlinux.lds.h>
 
 OUTPUT_FORMAT("elf64-s390", "elf64-s390", "elf64-s390")
 OUTPUT_ARCH(s390:64-bit)
@@ -134,6 +135,8 @@ SECTIONS
                __nospec_return_end = . ;
        }
 
+       BOOT_DATA
+
        /* early.c uses stsi, which requires page aligned data. */
        . = ALIGN(PAGE_SIZE);
        INIT_DATA_SECTION(0x100)
@@ -151,10 +154,12 @@ SECTIONS
         * it should match struct vmlinux_info
         */
        .vmlinux.info 0 : {
-               QUAD(_stext)                    /* default_lma */
-               QUAD(startup_continue)          /* entry */
-               QUAD(__bss_start - _stext)      /* image_size */
-               QUAD(__bss_stop - __bss_start)  /* bss_size */
+               QUAD(_stext)                                    /* default_lma */
+               QUAD(startup_continue)                          /* entry */
+               QUAD(__bss_start - _stext)                      /* image_size */
+               QUAD(__bss_stop - __bss_start)                  /* bss_size */
+               QUAD(__boot_data_start)                         /* bootdata_off */
+               QUAD(__boot_data_end - __boot_data_start)       /* bootdata_size */
        }
 
        /* Debugging sections.  */