summaryrefslogtreecommitdiffstats
path: root/arch/s390/boot
diff options
context:
space:
mode:
authorVasily Gorbik <gor@linux.ibm.com>2018-07-19 10:51:25 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2018-10-09 05:21:02 -0400
commit369f91c374514f9491d52fec12f7ee9ef6d44b23 (patch)
tree5a505c3f47a36b8e71247278c9f95d844764d5e3 /arch/s390/boot
parent8f75582a2fb6e2c5afc5252b6d6932f61a79c939 (diff)
s390/decompressor: rework uncompressed image info collection
The kernel decompressor has to know several bits of information about uncompressed image. Currently this info is collected by running "nm" on uncompressed vmlinux + "sed" and producing sizes.h file. This method worked well, but it has several disadvantages. Obscure symbols name pattern matching is fragile. Adding new values makes pattern even longer. Logic is spread across code and make file. Limited ability to adjust symbols values (currently magic lma value of 0x100000 is always subtracted). Apart from that same pieces of information (and more) would be needed for early memory detection and features like KASLR outside of boot/compressed/ folder where sizes.h is generated. To overcome limitations new "struct vmlinux_info" has been introduced to include values needed for the decompressor and the rest of the boot code. The only static instance of vmlinux_info is produced during vmlinux link step by filling in struct fields by the linker (like it is done with input_data in boot/compressed/vmlinux.scr.lds.S). This way individual values could be adjusted with all the knowledge linker has and arithmetic it supports. Later .vmlinux.info section (which contains struct vmlinux_info) is transplanted into the decompressor image and dropped from uncompressed image altogether. While doing that replace "compressed/vmlinux.scr.lds.S" linker script (whose purpose is to rename .data section in piggy.o to .rodata.compressed) with plain objcopy command. And simplify decompressor's linker script. 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>
Diffstat (limited to 'arch/s390/boot')
-rw-r--r--arch/s390/boot/compressed/Makefile33
-rw-r--r--arch/s390/boot/compressed/decompressor.h13
-rw-r--r--arch/s390/boot/compressed/misc.c15
-rw-r--r--arch/s390/boot/compressed/vmlinux.lds.S21
-rw-r--r--arch/s390/boot/compressed/vmlinux.scr.lds.S15
-rw-r--r--arch/s390/boot/startup.c10
6 files changed, 51 insertions, 56 deletions
diff --git a/arch/s390/boot/compressed/Makefile b/arch/s390/boot/compressed/Makefile
index c16ded8a35be..8262984aa405 100644
--- a/arch/s390/boot/compressed/Makefile
+++ b/arch/s390/boot/compressed/Makefile
@@ -9,13 +9,14 @@ KCOV_INSTRUMENT := n
9GCOV_PROFILE := n 9GCOV_PROFILE := n
10UBSAN_SANITIZE := n 10UBSAN_SANITIZE := n
11 11
12obj-y := $(if $(CONFIG_KERNEL_UNCOMPRESSED),,misc.o) piggy.o 12obj-y := $(if $(CONFIG_KERNEL_UNCOMPRESSED),,misc.o) piggy.o info.o
13targets := vmlinux.lds vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 13targets := vmlinux.lds vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2
14targets += vmlinux.bin.xz vmlinux.bin.lzma vmlinux.bin.lzo vmlinux.bin.lz4 14targets += vmlinux.bin.xz vmlinux.bin.lzma vmlinux.bin.lzo vmlinux.bin.lz4
15targets += vmlinux.scr.lds $(obj-y) $(if $(CONFIG_KERNEL_UNCOMPRESSED),,sizes.h) 15targets += info.bin $(obj-y)
16 16
17KBUILD_AFLAGS := $(KBUILD_AFLAGS_DECOMPRESSOR) 17KBUILD_AFLAGS := $(KBUILD_AFLAGS_DECOMPRESSOR)
18KBUILD_CFLAGS := $(KBUILD_CFLAGS_DECOMPRESSOR) 18KBUILD_CFLAGS := $(KBUILD_CFLAGS_DECOMPRESSOR)
19OBJCOPYFLAGS :=
19 20
20OBJECTS := $(addprefix $(obj)/,$(obj-y)) 21OBJECTS := $(addprefix $(obj)/,$(obj-y))
21 22
@@ -23,20 +24,16 @@ LDFLAGS_vmlinux := --oformat $(LD_BFD) -e startup -T
23$(obj)/vmlinux: $(obj)/vmlinux.lds $(objtree)/arch/s390/boot/startup.a $(OBJECTS) 24$(obj)/vmlinux: $(obj)/vmlinux.lds $(objtree)/arch/s390/boot/startup.a $(OBJECTS)
24 $(call if_changed,ld) 25 $(call if_changed,ld)
25 26
26# extract required uncompressed vmlinux symbols and adjust them to reflect offsets inside vmlinux.bin 27OBJCOPYFLAGS_info.bin := -O binary --only-section=.vmlinux.info
27sed-sizes := -e 's/^\([0-9a-fA-F]*\) . \(__bss_start\|_end\)$$/\#define SZ\2 (0x\1 - 0x100000)/p' 28$(obj)/info.bin: vmlinux FORCE
28 29 $(call if_changed,objcopy)
29quiet_cmd_sizes = GEN $@
30 cmd_sizes = $(NM) $< | sed -n $(sed-sizes) > $@
31
32$(obj)/sizes.h: vmlinux
33 $(call if_changed,sizes)
34 30
35CFLAGS_misc.o += -I$(objtree)/$(obj) 31OBJCOPYFLAGS_info.o := -I binary -O elf64-s390 -B s390:64-bit --rename-section .data=.vmlinux.info
36$(obj)/misc.o: $(obj)/sizes.h 32$(obj)/info.o: $(obj)/info.bin FORCE
33 $(call if_changed,objcopy)
37 34
38OBJCOPYFLAGS_vmlinux.bin := -R .comment -S 35OBJCOPYFLAGS_vmlinux.bin := -O binary --remove-section=.comment --remove-section=.vmlinux.info -S
39$(obj)/vmlinux.bin: vmlinux 36$(obj)/vmlinux.bin: vmlinux FORCE
40 $(call if_changed,objcopy) 37 $(call if_changed,objcopy)
41 38
42vmlinux.bin.all-y := $(obj)/vmlinux.bin 39vmlinux.bin.all-y := $(obj)/vmlinux.bin
@@ -61,10 +58,10 @@ $(obj)/vmlinux.bin.lzo: $(vmlinux.bin.all-y)
61$(obj)/vmlinux.bin.xz: $(vmlinux.bin.all-y) 58$(obj)/vmlinux.bin.xz: $(vmlinux.bin.all-y)
62 $(call if_changed,xzkern) 59 $(call if_changed,xzkern)
63 60
64LDFLAGS_piggy.o := -r --format binary --oformat $(LD_BFD) -T 61OBJCOPYFLAGS_piggy.o := -I binary -O elf64-s390 -B s390:64-bit --rename-section .data=.vmlinux.bin.compressed
65$(obj)/piggy.o: $(obj)/vmlinux.scr.lds $(obj)/vmlinux.bin$(suffix-y) 62$(obj)/piggy.o: $(obj)/vmlinux.bin$(suffix-y) FORCE
66 $(call if_changed,ld) 63 $(call if_changed,objcopy)
67 64
68chkbss := $(filter-out $(obj)/misc.o $(obj)/piggy.o,$(OBJECTS)) 65chkbss := $(filter-out $(obj)/misc.o $(obj)/piggy.o $(obj)/info.o,$(OBJECTS))
69chkbss-target := $(obj)/vmlinux.bin 66chkbss-target := $(obj)/vmlinux.bin
70include $(srctree)/arch/s390/scripts/Makefile.chkbss 67include $(srctree)/arch/s390/scripts/Makefile.chkbss
diff --git a/arch/s390/boot/compressed/decompressor.h b/arch/s390/boot/compressed/decompressor.h
index 0dd0b84679c4..011cbb6e0e08 100644
--- a/arch/s390/boot/compressed/decompressor.h
+++ b/arch/s390/boot/compressed/decompressor.h
@@ -3,9 +3,18 @@
3#define BOOT_COMPRESSED_DECOMPRESSOR_H 3#define BOOT_COMPRESSED_DECOMPRESSOR_H
4 4
5#ifdef CONFIG_KERNEL_UNCOMPRESSED 5#ifdef CONFIG_KERNEL_UNCOMPRESSED
6static inline void *decompress_kernel(unsigned long *uncompressed_size) {} 6static inline void *decompress_kernel(void) {}
7#else 7#else
8void *decompress_kernel(unsigned long *uncompressed_size); 8void *decompress_kernel(void);
9#endif 9#endif
10 10
11struct vmlinux_info {
12 unsigned long default_lma;
13 void (*entry)(void);
14 unsigned long image_size; /* does not include .bss */
15};
16
17extern char _vmlinux_info[];
18#define vmlinux (*(struct vmlinux_info *)_vmlinux_info)
19
11#endif /* BOOT_COMPRESSED_DECOMPRESSOR_H */ 20#endif /* BOOT_COMPRESSED_DECOMPRESSOR_H */
diff --git a/arch/s390/boot/compressed/misc.c b/arch/s390/boot/compressed/misc.c
index 321f6151ded9..8b35af625aff 100644
--- a/arch/s390/boot/compressed/misc.c
+++ b/arch/s390/boot/compressed/misc.c
@@ -11,7 +11,6 @@
11#include <asm/page.h> 11#include <asm/page.h>
12#include <asm/sclp.h> 12#include <asm/sclp.h>
13#include <asm/ipl.h> 13#include <asm/ipl.h>
14#include "sizes.h"
15#include "decompressor.h" 14#include "decompressor.h"
16 15
17/* 16/*
@@ -26,10 +25,10 @@
26#define memzero(s, n) memset((s), 0, (n)) 25#define memzero(s, n) memset((s), 0, (n))
27 26
28/* Symbols defined by linker scripts */ 27/* Symbols defined by linker scripts */
29extern char input_data[];
30extern int input_len;
31extern char _end[]; 28extern char _end[];
32extern char _bss[], _ebss[]; 29extern char _bss[], _ebss[];
30extern unsigned char _compressed_start[];
31extern unsigned char _compressed_end[];
33 32
34static void error(char *m); 33static void error(char *m);
35 34
@@ -83,12 +82,12 @@ static void error(char *x)
83 asm volatile("lpsw %0" : : "Q" (psw)); 82 asm volatile("lpsw %0" : : "Q" (psw));
84} 83}
85 84
86void *decompress_kernel(unsigned long *uncompressed_size) 85void *decompress_kernel(void)
87{ 86{
88 void *output, *kernel_end; 87 void *output, *kernel_end;
89 88
90 output = (void *) ALIGN((unsigned long) _end + HEAP_SIZE, PAGE_SIZE); 89 output = (void *) ALIGN((unsigned long) _end + HEAP_SIZE, PAGE_SIZE);
91 kernel_end = output + SZ__bss_start; 90 kernel_end = output + vmlinux.image_size;
92 91
93#ifdef CONFIG_BLK_DEV_INITRD 92#ifdef CONFIG_BLK_DEV_INITRD
94 /* 93 /*
@@ -111,9 +110,7 @@ void *decompress_kernel(unsigned long *uncompressed_size)
111 free_mem_ptr = (unsigned long) _end; 110 free_mem_ptr = (unsigned long) _end;
112 free_mem_end_ptr = free_mem_ptr + HEAP_SIZE; 111 free_mem_end_ptr = free_mem_ptr + HEAP_SIZE;
113 112
114 __decompress(input_data, input_len, NULL, NULL, output, 0, NULL, error); 113 __decompress(_compressed_start, _compressed_end - _compressed_start,
115 if (uncompressed_size) 114 NULL, NULL, output, 0, NULL, error);
116 *uncompressed_size = SZ__bss_start;
117 return output; 115 return output;
118} 116}
119
diff --git a/arch/s390/boot/compressed/vmlinux.lds.S b/arch/s390/boot/compressed/vmlinux.lds.S
index b16ac8b3c439..3814810718ef 100644
--- a/arch/s390/boot/compressed/vmlinux.lds.S
+++ b/arch/s390/boot/compressed/vmlinux.lds.S
@@ -8,9 +8,6 @@ ENTRY(startup)
8 8
9SECTIONS 9SECTIONS
10{ 10{
11 /* Be careful parts of head_64.S assume startup_32 is at
12 * address 0.
13 */
14 . = 0; 11 . = 0;
15 .head.text : { 12 .head.text : {
16 _head = . ; 13 _head = . ;
@@ -26,7 +23,7 @@ SECTIONS
26 .rodata : { 23 .rodata : {
27 _rodata = . ; 24 _rodata = . ;
28 *(.rodata) /* read-only data */ 25 *(.rodata) /* read-only data */
29 *(EXCLUDE_FILE (*piggy.o) .rodata.compressed) 26 *(.rodata.*)
30 _erodata = . ; 27 _erodata = . ;
31 } 28 }
32 .data : { 29 .data : {
@@ -35,14 +32,26 @@ SECTIONS
35 *(.data.*) 32 *(.data.*)
36 _edata = . ; 33 _edata = . ;
37 } 34 }
38 startup_continue = 0x100000; 35 /*
36 * uncompressed image info used by the decompressor it should match
37 * struct vmlinux_info. It comes from .vmlinux.info section of
38 * uncompressed vmlinux in a form of info.o
39 */
40 . = ALIGN(8);
41 .vmlinux.info : {
42 _vmlinux_info = .;
43 *(.vmlinux.info)
44 }
45
39#ifdef CONFIG_KERNEL_UNCOMPRESSED 46#ifdef CONFIG_KERNEL_UNCOMPRESSED
40 . = 0x100000; 47 . = 0x100000;
41#else 48#else
42 . = ALIGN(8); 49 . = ALIGN(8);
43#endif 50#endif
44 .rodata.compressed : { 51 .rodata.compressed : {
45 *(.rodata.compressed) 52 _compressed_start = .;
53 *(.vmlinux.bin.compressed)
54 _compressed_end = .;
46 } 55 }
47 . = ALIGN(256); 56 . = ALIGN(256);
48 .bss : { 57 .bss : {
diff --git a/arch/s390/boot/compressed/vmlinux.scr.lds.S b/arch/s390/boot/compressed/vmlinux.scr.lds.S
deleted file mode 100644
index ff01d18c9222..000000000000
--- a/arch/s390/boot/compressed/vmlinux.scr.lds.S
+++ /dev/null
@@ -1,15 +0,0 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2SECTIONS
3{
4 .rodata.compressed : {
5#ifndef CONFIG_KERNEL_UNCOMPRESSED
6 input_len = .;
7 LONG(input_data_end - input_data) input_data = .;
8#endif
9 *(.data)
10#ifndef CONFIG_KERNEL_UNCOMPRESSED
11 output_len = . - 4;
12 input_data_end = .;
13#endif
14 }
15}
diff --git a/arch/s390/boot/startup.c b/arch/s390/boot/startup.c
index 2a9ce355f8e6..474dee84d8a8 100644
--- a/arch/s390/boot/startup.c
+++ b/arch/s390/boot/startup.c
@@ -5,13 +5,11 @@
5 5
6void startup_kernel(void) 6void startup_kernel(void)
7{ 7{
8 void (*startup_continue)(void) = (void *)0x100000; 8 void *img;
9 unsigned long uncompressed_size;
10 void *uncompressed_img;
11 9
12 if (!IS_ENABLED(CONFIG_KERNEL_UNCOMPRESSED)) { 10 if (!IS_ENABLED(CONFIG_KERNEL_UNCOMPRESSED)) {
13 uncompressed_img = decompress_kernel(&uncompressed_size); 11 img = decompress_kernel();
14 memmove(startup_continue, uncompressed_img, uncompressed_size); 12 memmove((void *)vmlinux.default_lma, img, vmlinux.image_size);
15 } 13 }
16 startup_continue(); 14 vmlinux.entry();
17} 15}