diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-09-17 14:04:43 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-09-17 14:04:43 -0700 |
commit | d590284419b1d7cc2dc646e9bdde4da19061cf0f (patch) | |
tree | 007a94945a82e3010c1847daeeb8f17d8e988929 /arch/s390/boot | |
parent | 1e24aaabdee9e07f19b09bd305ffc069b0b07371 (diff) | |
parent | 2735913c1079b7dd7ec1d746c13a84ec1b5ea276 (diff) |
Merge tag 's390-5.4-1' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux
Pull s390 updates from Vasily Gorbik:
- Add support for IBM z15 machines.
- Add SHA3 and CCA AES cipher key support in zcrypt and pkey
refactoring.
- Move to arch_stack_walk infrastructure for the stack unwinder.
- Various kasan fixes and improvements.
- Various command line parsing fixes.
- Improve decompressor phase debuggability.
- Lift no bss usage restriction for the early code.
- Use refcount_t for reference counters for couple of places in mm
code.
- Logging improvements and return code fix in vfio-ccw code.
- Couple of zpci fixes and minor refactoring.
- Remove some outdated documentation.
- Fix secure boot detection.
- Other various minor code clean ups.
* tag 's390-5.4-1' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux: (48 commits)
s390: remove pointless drivers-y in drivers/s390/Makefile
s390/cpum_sf: Fix line length and format string
s390/pci: fix MSI message data
s390: add support for IBM z15 machines
s390/crypto: Support for SHA3 via CPACF (MSA6)
s390/startup: add pgm check info printing
s390/crypto: xts-aes-s390 fix extra run-time crypto self tests finding
vfio-ccw: fix error return code in vfio_ccw_sch_init()
s390: vfio-ap: fix warning reset not completed
s390/base: remove unused s390_base_mcck_handler
s390/sclp: Fix bit checked for has_sipl
s390/zcrypt: fix wrong handling of cca cipher keygenflags
s390/kasan: add kdump support
s390/setup: avoid using strncmp with hardcoded length
s390/sclp: avoid using strncmp with hardcoded length
s390/module: avoid using strncmp with hardcoded length
s390/pci: avoid using strncmp with hardcoded length
s390/kaslr: reserve memory for kasan usage
s390/mem_detect: provide single get_mem_detect_end
s390/cmma: reuse kstrtobool for option value parsing
...
Diffstat (limited to 'arch/s390/boot')
-rw-r--r-- | arch/s390/boot/Makefile | 2 | ||||
-rw-r--r-- | arch/s390/boot/boot.h | 1 | ||||
-rw-r--r-- | arch/s390/boot/compressed/.gitignore | 3 | ||||
-rw-r--r-- | arch/s390/boot/compressed/vmlinux.lds.S | 3 | ||||
-rw-r--r-- | arch/s390/boot/head.S | 32 | ||||
-rw-r--r-- | arch/s390/boot/ipl_parm.c | 11 | ||||
-rw-r--r-- | arch/s390/boot/kaslr.c | 41 | ||||
-rw-r--r-- | arch/s390/boot/mem_detect.c | 7 | ||||
-rw-r--r-- | arch/s390/boot/pgm_check_info.c | 90 | ||||
-rw-r--r-- | arch/s390/boot/startup.c | 6 |
10 files changed, 172 insertions, 24 deletions
diff --git a/arch/s390/boot/Makefile b/arch/s390/boot/Makefile index 4cf0bddb7d92..e2c47d3a1c89 100644 --- a/arch/s390/boot/Makefile +++ b/arch/s390/boot/Makefile @@ -36,7 +36,7 @@ CFLAGS_sclp_early_core.o += -I$(srctree)/drivers/s390/char obj-y := head.o als.o startup.o mem_detect.o ipl_parm.o ipl_report.o obj-y += string.o ebcdic.o sclp_early_core.o mem.o ipl_vmparm.o cmdline.o -obj-y += version.o ctype.o text_dma.o +obj-y += version.o pgm_check_info.o ctype.o text_dma.o obj-$(CONFIG_PROTECTED_VIRTUALIZATION_GUEST) += uv.o obj-$(CONFIG_RELOCATABLE) += machine_kexec_reloc.o obj-$(CONFIG_RANDOMIZE_BASE) += kaslr.o diff --git a/arch/s390/boot/boot.h b/arch/s390/boot/boot.h index 1c3b2b257637..2ea603f70c3b 100644 --- a/arch/s390/boot/boot.h +++ b/arch/s390/boot/boot.h @@ -10,6 +10,7 @@ void parse_boot_command_line(void); void setup_memory_end(void); void verify_facilities(void); void print_missing_facilities(void); +void print_pgm_check_info(void); unsigned long get_random_base(unsigned long safe_addr); extern int kaslr_enabled; diff --git a/arch/s390/boot/compressed/.gitignore b/arch/s390/boot/compressed/.gitignore index 45aeb4f08752..e72fcd7ecebb 100644 --- a/arch/s390/boot/compressed/.gitignore +++ b/arch/s390/boot/compressed/.gitignore @@ -1,5 +1,2 @@ -sizes.h vmlinux vmlinux.lds -vmlinux.scr.lds -vmlinux.bin.full diff --git a/arch/s390/boot/compressed/vmlinux.lds.S b/arch/s390/boot/compressed/vmlinux.lds.S index 635217eb3d91..44561b2c3712 100644 --- a/arch/s390/boot/compressed/vmlinux.lds.S +++ b/arch/s390/boot/compressed/vmlinux.lds.S @@ -37,9 +37,9 @@ SECTIONS * .dma section for code, data, ex_table that need to stay below 2 GB, * even when the kernel is relocate: above 2 GB. */ + . = ALIGN(PAGE_SIZE); _sdma = .; .dma.text : { - . = ALIGN(PAGE_SIZE); _stext_dma = .; *(.dma.text) . = ALIGN(PAGE_SIZE); @@ -52,6 +52,7 @@ SECTIONS _stop_dma_ex_table = .; } .dma.data : { *(.dma.data) } + . = ALIGN(PAGE_SIZE); _edma = .; BOOT_DATA diff --git a/arch/s390/boot/head.S b/arch/s390/boot/head.S index 2087bed6e60f..4b86a8d3c121 100644 --- a/arch/s390/boot/head.S +++ b/arch/s390/boot/head.S @@ -60,8 +60,10 @@ __HEAD .long 0x02000690,0x60000050 .long 0x020006e0,0x20000050 - .org 0x1a0 + .org __LC_RST_NEW_PSW # 0x1a0 .quad 0,iplstart + .org __LC_PGM_NEW_PSW # 0x1d0 + .quad 0x0000000180000000,startup_pgm_check_handler .org 0x200 @@ -352,6 +354,34 @@ ENTRY(startup_kdump) #include "head_kdump.S" # +# This program check is active immediately after kernel start +# and until early_pgm_check_handler is set in kernel/early.c +# It simply saves general/control registers and psw in +# the save area and does disabled wait with a faulty address. +# +ENTRY(startup_pgm_check_handler) + stmg %r0,%r15,__LC_SAVE_AREA_SYNC + la %r1,4095 + stctg %c0,%c15,__LC_CREGS_SAVE_AREA-4095(%r1) + mvc __LC_GPREGS_SAVE_AREA-4095(128,%r1),__LC_SAVE_AREA_SYNC + mvc __LC_PSW_SAVE_AREA-4095(16,%r1),__LC_PGM_OLD_PSW + mvc __LC_RETURN_PSW(16),__LC_PGM_OLD_PSW + ni __LC_RETURN_PSW,0xfc # remove IO and EX bits + ni __LC_RETURN_PSW+1,0xfb # remove MCHK bit + oi __LC_RETURN_PSW+1,0x2 # set wait state bit + larl %r2,.Lold_psw_disabled_wait + stg %r2,__LC_PGM_NEW_PSW+8 + l %r15,.Ldump_info_stack-.Lold_psw_disabled_wait(%r2) + brasl %r14,print_pgm_check_info +.Lold_psw_disabled_wait: + la %r1,4095 + lmg %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1) + lpswe __LC_RETURN_PSW # disabled wait +.Ldump_info_stack: + .long 0x5000 + PAGE_SIZE - STACK_FRAME_OVERHEAD +ENDPROC(startup_pgm_check_handler) + +# # params at 10400 (setup.h) # Must be keept in sync with struct parmarea in setup.h # diff --git a/arch/s390/boot/ipl_parm.c b/arch/s390/boot/ipl_parm.c index b8aa6a9f937b..24ef67eb1cef 100644 --- a/arch/s390/boot/ipl_parm.c +++ b/arch/s390/boot/ipl_parm.c @@ -7,6 +7,7 @@ #include <asm/sections.h> #include <asm/boot_data.h> #include <asm/facility.h> +#include <asm/pgtable.h> #include <asm/uv.h> #include "boot.h" @@ -14,6 +15,7 @@ char __bootdata(early_command_line)[COMMAND_LINE_SIZE]; struct ipl_parameter_block __bootdata_preserved(ipl_block); int __bootdata_preserved(ipl_block_valid); +unsigned long __bootdata(vmalloc_size) = VMALLOC_DEFAULT_SIZE; unsigned long __bootdata(memory_end); int __bootdata(memory_end_set); int __bootdata(noexec_disabled); @@ -219,18 +221,21 @@ void parse_boot_command_line(void) while (*args) { args = next_arg(args, ¶m, &val); - if (!strcmp(param, "mem")) { - memory_end = memparse(val, NULL); + if (!strcmp(param, "mem") && val) { + memory_end = round_down(memparse(val, NULL), PAGE_SIZE); memory_end_set = 1; } + if (!strcmp(param, "vmalloc") && val) + vmalloc_size = round_up(memparse(val, NULL), PAGE_SIZE); + if (!strcmp(param, "noexec")) { rc = kstrtobool(val, &enabled); if (!rc && !enabled) noexec_disabled = 1; } - if (!strcmp(param, "facilities")) + if (!strcmp(param, "facilities") && val) modify_fac_list(val); if (!strcmp(param, "nokaslr")) diff --git a/arch/s390/boot/kaslr.c b/arch/s390/boot/kaslr.c index c34a6387ce38..5d12352545c5 100644 --- a/arch/s390/boot/kaslr.c +++ b/arch/s390/boot/kaslr.c @@ -3,6 +3,7 @@ * Copyright IBM Corp. 2019 */ #include <asm/mem_detect.h> +#include <asm/pgtable.h> #include <asm/cpacf.h> #include <asm/timex.h> #include <asm/sclp.h> @@ -90,8 +91,10 @@ static unsigned long get_random(unsigned long limit) unsigned long get_random_base(unsigned long safe_addr) { + unsigned long memory_limit = memory_end_set ? memory_end : 0; unsigned long base, start, end, kernel_size; unsigned long block_sum, offset; + unsigned long kasan_needs; int i; if (IS_ENABLED(CONFIG_BLK_DEV_INITRD) && INITRD_START && INITRD_SIZE) { @@ -100,14 +103,36 @@ unsigned long get_random_base(unsigned long safe_addr) } safe_addr = ALIGN(safe_addr, THREAD_SIZE); + if ((IS_ENABLED(CONFIG_KASAN))) { + /* + * Estimate kasan memory requirements, which it will reserve + * at the very end of available physical memory. To estimate + * that, we take into account that kasan would require + * 1/8 of available physical memory (for shadow memory) + + * creating page tables for the whole memory + shadow memory + * region (1 + 1/8). To keep page tables estimates simple take + * the double of combined ptes size. + */ + memory_limit = get_mem_detect_end(); + if (memory_end_set && memory_limit > memory_end) + memory_limit = memory_end; + + /* for shadow memory */ + kasan_needs = memory_limit / 8; + /* for paging structures */ + kasan_needs += (memory_limit + kasan_needs) / PAGE_SIZE / + _PAGE_ENTRIES * _PAGE_TABLE_SIZE * 2; + memory_limit -= kasan_needs; + } + kernel_size = vmlinux.image_size + vmlinux.bss_size; block_sum = 0; for_each_mem_detect_block(i, &start, &end) { - if (memory_end_set) { - if (start >= memory_end) + if (memory_limit) { + if (start >= memory_limit) break; - if (end > memory_end) - end = memory_end; + if (end > memory_limit) + end = memory_limit; } if (end - start < kernel_size) continue; @@ -125,11 +150,11 @@ unsigned long get_random_base(unsigned long safe_addr) base = safe_addr; block_sum = offset = 0; for_each_mem_detect_block(i, &start, &end) { - if (memory_end_set) { - if (start >= memory_end) + if (memory_limit) { + if (start >= memory_limit) break; - if (end > memory_end) - end = memory_end; + if (end > memory_limit) + end = memory_limit; } if (end - start < kernel_size) continue; diff --git a/arch/s390/boot/mem_detect.c b/arch/s390/boot/mem_detect.c index 5d316fe40480..62e7c13ce85c 100644 --- a/arch/s390/boot/mem_detect.c +++ b/arch/s390/boot/mem_detect.c @@ -63,13 +63,6 @@ void add_mem_detect_block(u64 start, u64 end) mem_detect.count++; } -static unsigned long get_mem_detect_end(void) -{ - if (mem_detect.count) - return __get_mem_detect_block_ptr(mem_detect.count - 1)->end; - return 0; -} - static int __diag260(unsigned long rx1, unsigned long rx2) { register unsigned long _rx1 asm("2") = rx1; diff --git a/arch/s390/boot/pgm_check_info.c b/arch/s390/boot/pgm_check_info.c new file mode 100644 index 000000000000..83b5b7915c32 --- /dev/null +++ b/arch/s390/boot/pgm_check_info.c @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: GPL-2.0 +#include <linux/kernel.h> +#include <linux/string.h> +#include <asm/lowcore.h> +#include <asm/sclp.h> +#include "boot.h" + +const char hex_asc[] = "0123456789abcdef"; + +#define add_val_as_hex(dst, val) \ + __add_val_as_hex(dst, (const unsigned char *)&val, sizeof(val)) + +static char *__add_val_as_hex(char *dst, const unsigned char *src, size_t count) +{ + while (count--) + dst = hex_byte_pack(dst, *src++); + return dst; +} + +static char *add_str(char *dst, char *src) +{ + strcpy(dst, src); + return dst + strlen(dst); +} + +void print_pgm_check_info(void) +{ + struct psw_bits *psw = &psw_bits(S390_lowcore.psw_save_area); + unsigned short ilc = S390_lowcore.pgm_ilc >> 1; + char buf[256]; + int row, col; + char *p; + + add_str(buf, "Linux version "); + strlcat(buf, kernel_version, sizeof(buf)); + sclp_early_printk(buf); + + p = add_str(buf, "Kernel fault: interruption code "); + p = add_val_as_hex(buf + strlen(buf), S390_lowcore.pgm_code); + p = add_str(p, " ilc:"); + *p++ = hex_asc_lo(ilc); + add_str(p, "\n"); + sclp_early_printk(buf); + + p = add_str(buf, "PSW : "); + p = add_val_as_hex(p, S390_lowcore.psw_save_area.mask); + p = add_str(p, " "); + p = add_val_as_hex(p, S390_lowcore.psw_save_area.addr); + add_str(p, "\n"); + sclp_early_printk(buf); + + p = add_str(buf, " R:"); + *p++ = hex_asc_lo(psw->per); + p = add_str(p, " T:"); + *p++ = hex_asc_lo(psw->dat); + p = add_str(p, " IO:"); + *p++ = hex_asc_lo(psw->io); + p = add_str(p, " EX:"); + *p++ = hex_asc_lo(psw->ext); + p = add_str(p, " Key:"); + *p++ = hex_asc_lo(psw->key); + p = add_str(p, " M:"); + *p++ = hex_asc_lo(psw->mcheck); + p = add_str(p, " W:"); + *p++ = hex_asc_lo(psw->wait); + p = add_str(p, " P:"); + *p++ = hex_asc_lo(psw->pstate); + p = add_str(p, " AS:"); + *p++ = hex_asc_lo(psw->as); + p = add_str(p, " CC:"); + *p++ = hex_asc_lo(psw->cc); + p = add_str(p, " PM:"); + *p++ = hex_asc_lo(psw->pm); + p = add_str(p, " RI:"); + *p++ = hex_asc_lo(psw->ri); + p = add_str(p, " EA:"); + *p++ = hex_asc_lo(psw->eaba); + add_str(p, "\n"); + sclp_early_printk(buf); + + for (row = 0; row < 4; row++) { + p = add_str(buf, row == 0 ? "GPRS:" : " "); + for (col = 0; col < 4; col++) { + p = add_str(p, " "); + p = add_val_as_hex(p, S390_lowcore.gpregs_save_area[row * 4 + col]); + } + add_str(p, "\n"); + sclp_early_printk(buf); + } +} diff --git a/arch/s390/boot/startup.c b/arch/s390/boot/startup.c index 7b0d05414618..596ca7cc4d7b 100644 --- a/arch/s390/boot/startup.c +++ b/arch/s390/boot/startup.c @@ -112,6 +112,11 @@ static void handle_relocs(unsigned long offset) } } +static void clear_bss_section(void) +{ + memset((void *)vmlinux.default_lma + vmlinux.image_size, 0, vmlinux.bss_size); +} + void startup_kernel(void) { unsigned long random_lma; @@ -151,6 +156,7 @@ void startup_kernel(void) } else if (__kaslr_offset) memcpy((void *)vmlinux.default_lma, img, vmlinux.image_size); + clear_bss_section(); copy_bootdata(); if (IS_ENABLED(CONFIG_RELOCATABLE)) handle_relocs(__kaslr_offset); |