diff --git a/zdump/df_s390.c b/zdump/df_s390.c index 4e9a52aa..834ec4d6 100644 --- a/zdump/df_s390.c +++ b/zdump/df_s390.c @@ -3,7 +3,7 @@ * * S390 dump format common functions * - * Copyright IBM Corp. 2001, 2017 + * Copyright IBM Corp. 2001, 2018 * * s390-tools is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. @@ -41,7 +41,7 @@ void df_s390_cpu_info_add(struct df_s390_hdr *hdr, u64 addr_max) { unsigned int i; - if (hdr->version < 5) { + if (hdr->version < 5 && hdr->magic == DF_S390_MAGIC) { /* No Prefix registers in header */ hdr->cpu_cnt = 0; dfi_cpu_info_init(DFI_CPU_CONTENT_NONE); @@ -85,11 +85,14 @@ 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 >= 3 && hdr->mem_size_real) - dfi_attr_mem_size_real_set(hdr->mem_size_real); - if (hdr->version >= 2 && hdr->build_arch) + if ((hdr->version >= 2 || hdr->magic == DF_S390_MAGIC_EXT) && + hdr->build_arch) dfi_attr_build_arch_set(df_s390_to_dfi_arch(hdr->build_arch)); - if (hdr->version >= 5 && hdr->real_cpu_cnt) + if ((hdr->version >= 3 || hdr->magic == DF_S390_MAGIC_EXT) && + 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) dfi_attr_real_cpu_cnt_set(hdr->real_cpu_cnt); } @@ -124,8 +127,38 @@ int df_s390_em_verify(struct df_s390_em *em, struct df_s390_hdr *hdr) void df_s390_dumper_read(struct zg_fh *fh, int blk_size, struct df_s390_dumper *dumper) { - int offset = DF_S390_MAGIC_BLK_ECKD * blk_size; + 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). + */ + bytes_to_read = offsetof(struct df_s390_dumper, force); zg_seek(fh, offset, ZG_CHECK); - zg_read(fh, dumper, sizeof(*dumper), 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; + switch (dumper->version) { + case 1: + if (strncmp(dumper->magic, DF_S390_DUMPER_MAGIC_EXT, 7) == 0 || + strncmp(dumper->magic, DF_S390_DUMPER_MAGIC_MV_EXT, 7) == 0) + dumper->size = DF_S390_DUMPER_SIZE_V3; + else + dumper->size = DF_S390_DUMPER_SIZE_V1; + break; + case 2: + dumper->size = DF_S390_DUMPER_SIZE_V2; + break; + case 3: + default: + dumper->size = DF_S390_DUMPER_SIZE_V3; + } + /* 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); } diff --git a/zdump/df_s390.h b/zdump/df_s390.h index 0abba494..ec979ec3 100644 --- a/zdump/df_s390.h +++ b/zdump/df_s390.h @@ -3,7 +3,7 @@ * * S390 dump format common functions * - * Copyright IBM Corp. 2001, 2017 + * Copyright IBM Corp. 2001, 2018 * * s390-tools is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. @@ -16,6 +16,7 @@ #include "zg.h" #define DF_S390_MAGIC 0xa8190173618f23fdULL +#define DF_S390_MAGIC_EXT 0xa8190173618f23feULL #define DF_S390_HDR_SIZE 0x1000 #define DF_S390_EM_SIZE 16 #define DF_S390_EM_STR "DUMP_END" @@ -68,6 +69,16 @@ struct df_s390_em { u64 tod; } __attribute__((packed)); +/* + * Segment header for s390 extended dump format + */ +struct df_s390_dump_segm_hdr { + u64 start; + u64 len; + u64 stop_marker; + u8 reserved[0x1000 - 24]; +} __attribute__((packed)); + /* * Convert DFI arch to s390 arch */ @@ -84,96 +95,31 @@ static inline enum dfi_arch df_s390_to_dfi_arch(enum df_s390_arch df_s390_arch) return df_s390_arch == DF_S390_ARCH_64 ? DFI_ARCH_64 : DFI_ARCH_32; } -/* - * Dump tool structure (version 1) - */ -struct df_s390_dumper_v1 { - char code[0xff7 - 0x8]; - u8 force; - u64 mem; -} __attribute__ ((packed)); - -#define DF_S390_DUMPER_SIZE_V1 0x1000 - -/* - * Dump tool structure (version 2) - */ -struct df_s390_dumper_v2 { - char code[0x1ff7 - 0x8]; - u8 force; - u64 mem; -} __attribute__ ((packed)); - -#define DF_S390_DUMPER_SIZE_V2 0x2000 - -/* - * Dump tool structure (version 3 and 4) - */ -struct df_s390_dumper_v3 { - char code[0x2ff7 - 0x8]; - u8 force; - u64 mem; -} __attribute__ ((packed)); - -#define DF_S390_DUMPER_SIZE_V3 0x3000 +#define DF_S390_DUMPER_SIZE_V1 0x1000 +#define DF_S390_DUMPER_SIZE_V2 0x2000 +#define DF_S390_DUMPER_SIZE_V3 0x3000 +#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 */ /* * Dump tool structure */ struct df_s390_dumper { - char magic[7]; - u8 version; - union { - struct df_s390_dumper_v1 v1; - struct df_s390_dumper_v2 v2; - struct df_s390_dumper_v3 v3; - } d; + char magic[7]; + u8 version; + u32 size; + u8 force; + u64 mem; } __attribute__ ((packed)); -/* - * Dumper member access helpers - */ -#define df_s390_dumper_magic(dumper) ((dumper).magic) -#define df_s390_dumper_version(dumper) ((dumper).version) -static inline u64 df_s390_dumper_mem(struct df_s390_dumper *dumper) -{ - switch (dumper->version) { - case 1: - return dumper->d.v1.mem; - case 2: - return dumper->d.v2.mem; - case 3: - default: - return dumper->d.v3.mem; - } -} - -static inline u8 df_s390_dumper_force(struct df_s390_dumper *dumper) -{ - switch (dumper->version) { - case 1: - return dumper->d.v1.force; - case 2: - return dumper->d.v2.force; - case 3: - default: - return dumper->d.v3.force; - } -} - -static inline unsigned long df_s390_dumper_size(struct df_s390_dumper *dumper) -{ - switch (dumper->version) { - case 1: - return 0x1000; - case 2: - return 0x2000; - case 3: - default: - return 0x3000; - } -} - /* * s390 dump helpers */ diff --git a/zdump/dfi_s390mv.c b/zdump/dfi_s390mv.c index a226b05e..f19d6c73 100644 --- a/zdump/dfi_s390mv.c +++ b/zdump/dfi_s390mv.c @@ -3,7 +3,7 @@ * * S390 multi-volume dump input format * - * Copyright IBM Corp. 2001, 2017 + * Copyright IBM Corp. 2001, 2018 * * s390-tools is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. @@ -109,8 +109,7 @@ static void table_read(struct zg_fh *fh, u16 blk_size, { int off; - off = DF_S390_MAGIC_BLK_ECKD * blk_size + - df_s390_dumper_size(&l.dumper); + off = DF_S390_MAGIC_BLK_ECKD * blk_size + l.dumper.size; zg_seek(fh, off, ZG_CHECK); zg_read(fh, table, sizeof(*table), ZG_CHECK); } @@ -263,7 +262,7 @@ static void vol_init(struct vol *vol, struct vol_parm *vol_parm, int ssid, l.dump_incomplete = 1; } - if (strncmp(df_s390_dumper_magic(vol->dumper), "ZMULT64", 7) != 0) { + if (strncmp(vol->dumper.magic, DF_S390_DUMPER_MAGIC_MV, 7) != 0) { vol->sign = SIGN_INVALID; l.dump_incomplete = 1; } @@ -445,7 +444,7 @@ static int mv_dumper_read(void) ZG_CHECK_NONE) == -1) return -ENODEV; df_s390_dumper_read(g.fh, l.blk_size, &l.dumper); - if (memcmp(df_s390_dumper_magic(l.dumper), "ZMULT64", 7) != 0) + if (memcmp(l.dumper.magic, DF_S390_DUMPER_MAGIC_MV, 7) != 0) return -ENODEV; table_read(g.fh, l.blk_size, &l.table); return 0; @@ -529,9 +528,9 @@ int dt_s390mv_init(void) return -ENODEV; volumes_init(); dt_arch_set(DFI_ARCH_64); - dt_version_set(df_s390_dumper_version(l.dumper)); - dt_attr_mem_limit_set(df_s390_dumper_mem(&l.dumper)); - dt_attr_force_set(df_s390_dumper_force(&l.dumper)); + dt_version_set(l.dumper.version); + dt_attr_mem_limit_set(l.dumper.mem); + dt_attr_force_set(l.dumper.force); return 0; } diff --git a/zdump/dt_s390sv.c b/zdump/dt_s390sv.c index 7e1b04a1..466388a7 100644 --- a/zdump/dt_s390sv.c +++ b/zdump/dt_s390sv.c @@ -3,7 +3,7 @@ * * S390 single-volume DASD dump tool * - * Copyright IBM Corp. 2001, 2017 + * Copyright IBM Corp. 2001, 2018 * * s390-tools is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. @@ -12,8 +12,6 @@ #include #include "zgetdump.h" -#define HEXINSTR "\x0d\x10\x47\xf0" /* BASR + 1st halfword of BC */ - /* * File local static data */ @@ -29,15 +27,13 @@ static int dumper_read_eckd(int blk_size) { df_s390_dumper_read(g.fh, blk_size, &l.dumper); - if (strncmp(l.dumper.magic, "ZECKD31", 7) == 0) { - l.dumper_arch = DFI_ARCH_32; - } else if (strncmp(l.dumper.magic, "ZECKD64", 7) == 0) { + if (strncmp(l.dumper.magic, DF_S390_DUMPER_MAGIC64, 7) == 0) { l.dumper_arch = DFI_ARCH_64; - } else if ((memcmp(l.dumper.magic, HEXINSTR, 4) == 0) && - (l.dumper.d.v1.code[0] == '\x0d') && - (l.dumper.d.v1.code[1] == '\xd0')) { - /* We found basr r13,0 (old dumper) */ - l.dumper.version = 0; + } else if (strncmp(l.dumper.magic, DF_S390_DUMPER_MAGIC32, 7) == 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; @@ -46,28 +42,18 @@ static int dumper_read_eckd(int blk_size) } /* - * Read dump tool from FBA DASD device + * Check FBA dump tool magic number and set architecture attribute */ -static void dumper_read_fba_gen(int size, void *buffer) +static int dumper_check_fba(struct df_s390_dumper *dumper) { - zg_seek_end(g.fh, -size, ZG_CHECK); - zg_read(g.fh, buffer, size, ZG_CHECK); -} - -/* - * Read dump tool on FBA disk and check its magic number - */ -static int dumper_check_fba(void) -{ - if (strncmp(l.dumper.magic, "ZDFBA31", 7) == 0) { - l.dumper_arch = DFI_ARCH_32; - } else if (strncmp(l.dumper.magic, "ZDFBA64", 7) == 0) { + if (strncmp(dumper->magic, DF_S390_DUMPER_MAGIC64_FBA, 7) == 0) { l.dumper_arch = DFI_ARCH_64; - } else if ((memcmp(l.dumper.magic, HEXINSTR, 4) == 0) && - (l.dumper.d.v1.code[0] == '\x0d') && - (l.dumper.d.v1.code[1] == '\xd0')) { + } else if (strncmp(dumper->magic, DF_S390_DUMPER_MAGIC32_FBA, 7) == 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) */ - l.dumper.version = 0; + dumper->version = 0; l.dumper_arch = DFI_ARCH_UNKNOWN; } else { return -ENODEV; @@ -75,19 +61,40 @@ static int dumper_check_fba(void) 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); + return 0; +} + /* * Read dump tool on FBA disk and check its magic number */ static int dumper_read_fba(void) { - dumper_read_fba_gen(DF_S390_DUMPER_SIZE_V1, &l.dumper); - if (dumper_check_fba() == 0) + if (dumper_read_validate_fba(DF_S390_DUMPER_SIZE_V3, &l.dumper) == 0) return 0; - dumper_read_fba_gen(DF_S390_DUMPER_SIZE_V2, &l.dumper); - if (dumper_check_fba() == 0) + if (dumper_read_validate_fba(DF_S390_DUMPER_SIZE_V2, &l.dumper) == 0) return 0; - dumper_read_fba_gen(DF_S390_DUMPER_SIZE_V3, &l.dumper); - if (dumper_check_fba() == 0) + if (dumper_read_validate_fba(DF_S390_DUMPER_SIZE_V1, &l.dumper) == 0) return 0; return -ENODEV; } @@ -121,8 +128,8 @@ static int dt_s390sv_init(void) if (sv_dumper_read() != 0) return -ENODEV; dt_arch_set(l.dumper_arch); - dt_version_set(df_s390_dumper_version(l.dumper)); - dt_attr_mem_limit_set(df_s390_dumper_mem(&l.dumper)); + dt_version_set(l.dumper.version); + dt_attr_mem_limit_set(l.dumper.mem); return 0; }