From 2c5d4073a79fe4ea2fca9148c8775743be5fb75b Mon Sep 17 00:00:00 2001 From: Mikhail Zaslonko Date: Wed, 9 Oct 2024 18:13:27 +0200 Subject: [PATCH] zdump: Drop support of obsolete dumps and dumpers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drop support of obsolete dump and dump-tool versions (single-volume DASD, FBA and Tape) in order to simplify zgetdump logic: - CCW dumpers written in assembler instructions as well as stage2 dumpers of size less than 0x3000 (STAGE2_DUMPER_SIZE_V1 or STAGE2_DUMPER_SIZE_V2) haven't been used for years. Remove its traces completely as a cleanup. Keep the last version (version 5) of non-extended DASD dumper as well as newer extended DASD dumpers. - Rename STAGE2_DUMPER_SIZE_V3 and STAGE2_DUMPER_SIZE_ZLIB constants. - Drop support of non-extended s390 dumps of version < 5. Dump files of s390 format version 5 can be still produced by zgetdump (dfo_s390). - Drop excessive dump version checking in df_s390_cpu_info_add() and df_s390_hdr_add() considering that obsolete s390 dumps of version lower than 5 no longer supported. - Use cpu_cnt field in s390 dump header instead of the s390 dump version to indicate no cpu info available (DFI_CPU_CONTENT_NONE) for dfo_s390. - Make df_s390_dumper_read() return error code upon unknown dumper version/magic detection. Signed-off-by: Mikhail Zaslonko Reviewed-by: Alexander Egorenkov Signed-off-by: Jan Höppner --- include/boot/loaders_layout.h | 6 +-- include/dump/s390_dump.h | 4 -- zdump/df_s390.c | 60 +++++++++++----------- zdump/df_s390.h | 4 +- zdump/dfi_s390mv.c | 7 ++- zdump/dfo_s390.c | 7 ++- zdump/dt_s390sv.c | 93 ++++++++++++----------------------- zipl/boot/eckd2dump.lds.S | 2 +- zipl/src/install.c | 3 +- 9 files changed, 77 insertions(+), 109 deletions(-) diff --git a/include/boot/loaders_layout.h b/include/boot/loaders_layout.h index 61b94169..85e0deca 100644 --- a/include/boot/loaders_layout.h +++ b/include/boot/loaders_layout.h @@ -31,11 +31,9 @@ #define ECKD2DUMP_STACK_SIZE _AC(0x2000, UL) #define STAGE2_MAX_SIZE _AC(0x3000, UL) -#define STAGE2_DUMPER_SIZE_V1 _AC(0x1000, UL) -#define STAGE2_DUMPER_SIZE_V2 _AC(0x2000, UL) -#define STAGE2_DUMPER_SIZE_V3 _AC(0x3000, UL) +#define STAGE2_DUMPER_SIZE_SV _AC(0x3000, UL) #define STAGE2_DUMPER_SIZE_MV _AC(0x4000, UL) -#define STAGE2_DUMPER_SIZE_ZLIB _AC(0x8000, UL) +#define STAGE2_DUMPER_SIZE_SV_ZLIB _AC(0x8000, UL) #define STAGE3_ENTRY _AC(0xa000, UL) diff --git a/include/dump/s390_dump.h b/include/dump/s390_dump.h index ad5ac1a8..c38d8b71 100644 --- a/include/dump/s390_dump.h +++ b/include/dump/s390_dump.h @@ -27,16 +27,12 @@ #define DF_S390_CPU_MAX 512 #define DF_S390_MAGIC_BLK_ECKD 3 #define DF_S390_DUMPER_MAGIC_SIZE 7 -#define DF_S390_DUMPER_MAGIC32 "ZECKD31" #define DF_S390_DUMPER_MAGIC64 "ZECKD64" #define DF_S390_DUMPER_MAGIC_EXT "XECKD64" -#define DF_S390_DUMPER_MAGIC32_FBA "ZDFBA31" #define DF_S390_DUMPER_MAGIC64_FBA "ZDFBA64" #define DF_S390_DUMPER_MAGIC_FBA_EXT "XDFBA64" #define DF_S390_DUMPER_MAGIC_MV "ZMULT64" #define DF_S390_DUMPER_MAGIC_MV_EXT "XMULT64" -#define OLD_DUMPER_HEX_INSTR1 "\x0d\x10\x47\xf0" /* BASR + 1st halfword of BC */ -#define OLD_DUMPER_HEX_INSTR2 "\x0d\xd0" /* BASR 13,0 */ /* * Architecture of dumped system diff --git a/zdump/df_s390.c b/zdump/df_s390.c index 387381e2..48f683b4 100644 --- a/zdump/df_s390.c +++ b/zdump/df_s390.c @@ -44,11 +44,12 @@ int df_s390_cpu_info_add(struct df_s390_hdr *hdr, u64 addr_max) unsigned int i; int rc; - if (hdr->version < 5 && hdr->magic == DF_S390_MAGIC) { + if (hdr->cpu_cnt == 0) { /* No Prefix registers in header */ - hdr->cpu_cnt = 0; dfi_cpu_info_init(DFI_CPU_CONTENT_NONE); - } else if (check_addr_max(hdr, addr_max) != 0) { + return 0; + } + if (check_addr_max(hdr, addr_max) != 0) { /* Only lowcore pointers available */ dfi_cpu_info_init(DFI_CPU_CONTENT_LC); } else { @@ -93,14 +94,11 @@ void df_s390_hdr_add(struct df_s390_hdr *hdr) dfi_arch_set(df_s390_to_dfi_arch(hdr->arch)); if (hdr->cpu_id) dfi_attr_cpu_id_set(hdr->cpu_id); - if ((hdr->version >= 2 || hdr->magic == DF_S390_MAGIC_EXT) && - hdr->build_arch) + if (hdr->build_arch) dfi_attr_build_arch_set(df_s390_to_dfi_arch(hdr->build_arch)); - if ((hdr->version >= 3 || hdr->magic == DF_S390_MAGIC_EXT) && - hdr->mem_size_real) + if (hdr->mem_size_real) dfi_attr_mem_size_real_set(hdr->mem_size_real); - if ((hdr->version >= 5 || hdr->magic == DF_S390_MAGIC_EXT) && - hdr->real_cpu_cnt) + if (hdr->real_cpu_cnt) dfi_attr_real_cpu_cnt_set(hdr->real_cpu_cnt); if (!hdr->mvdump && hdr->zlib_version_s390 && hdr->zlib_entry_size) dfi_attr_zlib_info_set(hdr->zlib_version_s390, hdr->zlib_entry_size); @@ -134,50 +132,56 @@ int df_s390_em_verify(struct df_s390_em *em, struct df_s390_hdr *hdr) /* * Read s390 dump tool from DASD with given block size */ -void df_s390_dumper_read(struct zg_fh *fh, int blk_size, - struct df_s390_dumper *dumper) +int df_s390_dumper_read(struct zg_fh *fh, int blk_size, + struct df_s390_dumper *dumper) { int bytes_to_read, offset = DF_S390_MAGIC_BLK_ECKD * blk_size; /* - * First read 3 fields at the start of the dumper. The magic number, - * version and one extra field for the old dumper case (no magic - * number, checking for specific assembler instructions). + * First read 2 fields at the start of the dumper. The magic number + * and the version. */ - bytes_to_read = offsetof(struct df_s390_dumper, force); + bytes_to_read = offsetof(struct df_s390_dumper, size); zg_seek(fh, offset, ZG_CHECK); zg_read(fh, dumper, bytes_to_read, ZG_CHECK); - if (memcmp(dumper->magic, OLD_DUMPER_HEX_INSTR1, 4) == 0 && - memcmp(&dumper->size, OLD_DUMPER_HEX_INSTR2, 2) == 0) - /* We found basr r13,0 (old dumper) */ - dumper->version = 0; + dumper->size = 0; switch (dumper->version) { + /* + * Versions 1 and 2 refer to the newer extended DASD dumpers + * while version 5 refers to the old (non-extended) DASD dump-tools + * we still support (either single-volume or multi-volume). + * Magic numbers for SV and MV dumpers apply as well. + * Pick a dumper size based on the Version and Magic combination. + */ case 1: if (strncmp(dumper->magic, DF_S390_DUMPER_MAGIC_EXT, DF_S390_DUMPER_MAGIC_SIZE) == 0 || strncmp(dumper->magic, DF_S390_DUMPER_MAGIC_MV_EXT, DF_S390_DUMPER_MAGIC_SIZE) == 0) - dumper->size = STAGE2_DUMPER_SIZE_V3; - else - dumper->size = STAGE2_DUMPER_SIZE_V1; + dumper->size = STAGE2_DUMPER_SIZE_SV; break; case 2: if (strncmp(dumper->magic, DF_S390_DUMPER_MAGIC_EXT, DF_S390_DUMPER_MAGIC_SIZE) == 0) - dumper->size = STAGE2_DUMPER_SIZE_ZLIB; + dumper->size = STAGE2_DUMPER_SIZE_SV_ZLIB; else if (strncmp(dumper->magic, DF_S390_DUMPER_MAGIC_MV_EXT, DF_S390_DUMPER_MAGIC_SIZE) == 0) dumper->size = STAGE2_DUMPER_SIZE_MV; - else - dumper->size = STAGE2_DUMPER_SIZE_V2; break; - case 3: - default: - dumper->size = STAGE2_DUMPER_SIZE_V3; + case 5: + if (strncmp(dumper->magic, DF_S390_DUMPER_MAGIC64, + DF_S390_DUMPER_MAGIC_SIZE) == 0 || + strncmp(dumper->magic, DF_S390_DUMPER_MAGIC_MV, + DF_S390_DUMPER_MAGIC_SIZE) == 0) + dumper->size = STAGE2_DUMPER_SIZE_SV; + break; } + if (dumper->size == 0) + return -1; /* Read force and mem fields in the end of the dumper */ bytes_to_read = sizeof(dumper->force) + sizeof(dumper->mem); offset += dumper->size - bytes_to_read; zg_seek(fh, offset, ZG_CHECK); zg_read(fh, &dumper->force, bytes_to_read, ZG_CHECK); + return 0; } diff --git a/zdump/df_s390.h b/zdump/df_s390.h index 98d6ace6..4a49190f 100644 --- a/zdump/df_s390.h +++ b/zdump/df_s390.h @@ -53,8 +53,8 @@ extern void df_s390_hdr_add(struct df_s390_hdr *hdr); extern void df_s390_em_add(struct df_s390_em *em); extern int df_s390_cpu_info_add(struct df_s390_hdr *hdr, u64 addr_max); extern int df_s390_em_verify(struct df_s390_em *em, struct df_s390_hdr *hdr); -extern void df_s390_dumper_read(struct zg_fh *fh, int32_t blk_size, - struct df_s390_dumper *dumper); +extern int df_s390_dumper_read(struct zg_fh *fh, int32_t blk_size, + struct df_s390_dumper *dumper); /* * DASD dt and dfi functions diff --git a/zdump/dfi_s390mv.c b/zdump/dfi_s390mv.c index a6bcadf4..92c6e2f2 100644 --- a/zdump/dfi_s390mv.c +++ b/zdump/dfi_s390mv.c @@ -211,7 +211,9 @@ static void check_vol_table(struct vol *vol) static void vol_read(struct vol *vol) { zg_ioctl(vol->fh, BLKFLSBUF, NULL, "BLKFLSBUF", ZG_CHECK); - df_s390_dumper_read(vol->fh, vol->blk_size, &vol->dumper); + if (df_s390_dumper_read(vol->fh, vol->blk_size, &vol->dumper)) + ERR_EXIT("No dump tool found on the multi-volume dump device '%s'", + vol->bus_id); check_vol_table(vol); zg_seek(vol->fh, vol->part_off, ZG_CHECK); zg_read(vol->fh, &vol->hdr, DF_S390_HDR_SIZE, ZG_CHECK); @@ -506,7 +508,8 @@ static int mv_dumper_read(void) if (zg_ioctl(g.fh, BLKSSZGET, &l.blk_size, "BLKSSZGET", ZG_CHECK_NONE) == -1) return -ENODEV; - df_s390_dumper_read(g.fh, l.blk_size, &l.dumper); + if (df_s390_dumper_read(g.fh, l.blk_size, &l.dumper)) + return -ENODEV; if (strncmp(l.dumper.magic, l.dumper_magic, DF_S390_DUMPER_MAGIC_SIZE) != 0) return -ENODEV; table_read(g.fh, l.blk_size, &l.table); diff --git a/zdump/dfo_s390.c b/zdump/dfo_s390.c index fc1636c7..fcf117ab 100644 --- a/zdump/dfo_s390.c +++ b/zdump/dfo_s390.c @@ -234,10 +234,7 @@ static void df_s390_dump_init(void) dh->hdr_size = DF_S390_HDR_SIZE; dh->page_size = PAGE_SIZE; dh->dump_level = 4; - if (dfi_cpu_content() == DFI_CPU_CONTENT_NONE) - dh->version = 4; - else - dh->version = 5; + dh->version = 5; dh->mem_start = 0; dh->mem_end = dfi_mem_end(); dh->mem_size = dh->mem_end + 1; @@ -246,6 +243,8 @@ static void df_s390_dump_init(void) if (dfi_attr_build_arch()) dh->build_arch = df_s390_from_dfi_arch(*dfi_attr_build_arch()); dh->cpu_cnt = dfi_cpu_cnt(); + if (dfi_cpu_content() == DFI_CPU_CONTENT_NONE) + dh->cpu_cnt = 0; if (dfi_attr_real_cpu_cnt()) dh->real_cpu_cnt = *dfi_attr_real_cpu_cnt(); if (dfi_attr_cpu_id()) diff --git a/zdump/dt_s390sv.c b/zdump/dt_s390sv.c index 205480ea..478887bd 100644 --- a/zdump/dt_s390sv.c +++ b/zdump/dt_s390sv.c @@ -31,28 +31,18 @@ static struct { */ static int dumper_read_eckd(int blk_size) { - df_s390_dumper_read(g.fh, blk_size, &l.dumper); - + if (df_s390_dumper_read(g.fh, blk_size, &l.dumper)) + return -ENODEV; if (l.extended) { if (strncmp(l.dumper.magic, DF_S390_DUMPER_MAGIC_EXT, DF_S390_DUMPER_MAGIC_SIZE) != 0) return -ENODEV; - l.dumper_arch = DFI_ARCH_64; - return 0; - } - if (strncmp(l.dumper.magic, DF_S390_DUMPER_MAGIC64, - DF_S390_DUMPER_MAGIC_SIZE) == 0) { - l.dumper_arch = DFI_ARCH_64; - } else if (strncmp(l.dumper.magic, DF_S390_DUMPER_MAGIC32, - DF_S390_DUMPER_MAGIC_SIZE) == 0) { - l.dumper_arch = DFI_ARCH_32; - } else if (memcmp(l.dumper.magic, OLD_DUMPER_HEX_INSTR1, 4) == 0 && - l.dumper.version == 0) { - /* We found the old dumper */ - l.dumper_arch = DFI_ARCH_UNKNOWN; } else { - return -ENODEV; + if (strncmp(l.dumper.magic, DF_S390_DUMPER_MAGIC64, + DF_S390_DUMPER_MAGIC_SIZE) != 0) + return -ENODEV; } + l.dumper_arch = DFI_ARCH_64; return 0; } @@ -65,47 +55,12 @@ static int dumper_check_fba(struct df_s390_dumper *dumper) if (strncmp(dumper->magic, DF_S390_DUMPER_MAGIC_FBA_EXT, DF_S390_DUMPER_MAGIC_SIZE) != 0) return -ENODEV; - l.dumper_arch = DFI_ARCH_64; - return 0; - } - if (strncmp(dumper->magic, DF_S390_DUMPER_MAGIC64_FBA, - DF_S390_DUMPER_MAGIC_SIZE) == 0) { - l.dumper_arch = DFI_ARCH_64; - } else if (strncmp(dumper->magic, DF_S390_DUMPER_MAGIC32_FBA, - DF_S390_DUMPER_MAGIC_SIZE) == 0) { - l.dumper_arch = DFI_ARCH_32; - } else if (memcmp(dumper->magic, OLD_DUMPER_HEX_INSTR1, 4) == 0 && - memcmp(&dumper->size, OLD_DUMPER_HEX_INSTR2, 2) == 0) { - /* We found basr r13,0 (old dumper) */ - dumper->version = 0; - l.dumper_arch = DFI_ARCH_UNKNOWN; } else { - return -ENODEV; + if (strncmp(dumper->magic, DF_S390_DUMPER_MAGIC64_FBA, + DF_S390_DUMPER_MAGIC_SIZE) != 0) + return -ENODEV; } - return 0; -} - -/* - * Read dump tool from FBA device - */ -static int dumper_read_validate_fba(int size, struct df_s390_dumper *dumper) -{ - int bytes_to_read; - - /* - * On FBA device the dumper is written at the end of the volume because - * there is not enough space to place it at the beginning due to the - * linux disk layout - */ - zg_seek_end(g.fh, -size, ZG_CHECK); - bytes_to_read = offsetof(struct df_s390_dumper, force); - zg_read(g.fh, dumper, bytes_to_read, ZG_CHECK); - if (dumper_check_fba(dumper) != 0) - return -ENODEV; - dumper->size = size; - bytes_to_read = sizeof(dumper->force) + sizeof(dumper->mem); - zg_seek_end(g.fh, -bytes_to_read, ZG_CHECK); - zg_read(g.fh, &dumper->force, bytes_to_read, ZG_CHECK); + l.dumper_arch = DFI_ARCH_64; return 0; } @@ -114,13 +69,27 @@ static int dumper_read_validate_fba(int size, struct df_s390_dumper *dumper) */ static int dumper_read_fba(void) { - if (dumper_read_validate_fba(STAGE2_DUMPER_SIZE_V3, &l.dumper) == 0) - return 0; - if (dumper_read_validate_fba(STAGE2_DUMPER_SIZE_V2, &l.dumper) == 0) - return 0; - if (dumper_read_validate_fba(STAGE2_DUMPER_SIZE_V1, &l.dumper) == 0) - return 0; - return -ENODEV; + struct df_s390_dumper *dumper = &l.dumper; + int bytes_to_read; + + /* + * On FBA device the dumper is written at the end of the volume because + * there is not enough space to place it at the beginning due to the + * linux disk layout. + * First read 2 fields at the start of the dumper. The magic number + * and the version. + */ + zg_seek_end(g.fh, -STAGE2_DUMPER_SIZE_SV, ZG_CHECK); + bytes_to_read = offsetof(struct df_s390_dumper, size); + zg_read(g.fh, dumper, bytes_to_read, ZG_CHECK); + if (dumper_check_fba(dumper) != 0) + return -ENODEV; + dumper->size = STAGE2_DUMPER_SIZE_SV; + /* Read force and mem fields in the end of the dumper */ + bytes_to_read = sizeof(dumper->force) + sizeof(dumper->mem); + zg_seek_end(g.fh, -bytes_to_read, ZG_CHECK); + zg_read(g.fh, &dumper->force, bytes_to_read, ZG_CHECK); + return 0; } /* diff --git a/zipl/boot/eckd2dump.lds.S b/zipl/boot/eckd2dump.lds.S index a81cacd2..d0c9a1ed 100644 --- a/zipl/boot/eckd2dump.lds.S +++ b/zipl/boot/eckd2dump.lds.S @@ -49,7 +49,7 @@ SECTIONS ASSERT(__stage2dump_tail_end - __stage2_head == STAGE2_DUMPER_SIZE_MV, "MV dumper size doesn't conform to the described memory layout"); #else - ASSERT(__stage2dump_tail_end - __stage2_head == STAGE2_DUMPER_SIZE_ZLIB, + ASSERT(__stage2dump_tail_end - __stage2_head == STAGE2_DUMPER_SIZE_SV_ZLIB, "SV dumper size doesn't conform to the described memory layout"); #endif } diff --git a/zipl/src/install.c b/zipl/src/install.c index c88f0ddd..235ac17d 100644 --- a/zipl/src/install.c +++ b/zipl/src/install.c @@ -367,8 +367,7 @@ static int clear_ccw_dumper(const struct disk_info *info, int fd) /* * Check if the dump tool is present and clear its first block with zeroes. */ - if (strncmp(dumper_magic, DF_S390_DUMPER_MAGIC32, sizeof(dumper_magic)) == 0 || - strncmp(dumper_magic, DF_S390_DUMPER_MAGIC64, sizeof(dumper_magic)) == 0 || + if (strncmp(dumper_magic, DF_S390_DUMPER_MAGIC64, sizeof(dumper_magic)) == 0 || strncmp(dumper_magic, DF_S390_DUMPER_MAGIC_EXT, sizeof(dumper_magic)) == 0 || strncmp(dumper_magic, DF_S390_DUMPER_MAGIC_MV, sizeof(dumper_magic)) == 0 || strncmp(dumper_magic, DF_S390_DUMPER_MAGIC_MV_EXT, sizeof(dumper_magic)) == 0) {