----- "Michael Holzheu" <holzheu@xxxxxxxxxxxxxxxxxx> wrote: > Hi Dave, > > Next try... I think this one is better: > > I added a new machdep function "elf_note_add()" and moved almost all > into s390x.c: > > Add ELF core dump support for s390x > > This patch enables crash for reading s390x (64 bit) ELF core dumps. The > following new ELF note sections are added by this patch: > > * NT_FPREGSET: Floating point registers - all architectures > * NT_S390_TIMER: S390 CPU timer > * NT_S390_TODCMP: S390 TOD clock comparator > * NT_S390_TODPREG: S390 TOD programmable register > * NT_S390_CTRS: S390 control registers > * NT_S390_PREFIX: S390 prefix register > > A new machdep member function "elf_note_add()" is added. In this function > we setup the s390x CPU information. OK, this looks good -- these are the changes I would make. Since a new entry-point is being made in the machdep_table, let's make it generic so that other arches in the future may use it for their own purposes, and allow it to be called from other locations with an int and a generic pointer argument. So in defs.h, remove this: +#include <elf.h> and move it to s390x.c. Then change this from: + void (*elf_note_add)(int, Elf64_Nhdr *); to: + void (*elf_note_add)(int, void *); And remove this -- it doesn't exist anymore: +void get_netdump_regs_s390x(struct bt_info *, ulong *, ulong *); In netdump.c, change this from: + if (store && machdep->elf_note_add) + machdep->elf_note_add(nd->num_prstatus_notes, note); to: + if (store && machine_type("S390X") && machdep->elf_note_add) + machdep->elf_note_add(nd->num_prstatus_notes, (void *)note); And in s390x.c, adjust for the generic pointer argument, changing this: +static void s390x_elf_note_add(int elf_cpu_nr, Elf64_Nhdr *note) +{ to: +static void s390x_elf_note_add(int elf_cpu_nr, void *noteptr) +{ + Elf64_Nhdr *note = (Elf64_Nhdr *)noteptr; void *desc = get_elf_note_desc(note); and fix this typo: + fprintf(fp, " elf_not_add: s390x_elf_note_add()\n") ; to: + fprintf(fp, " elf_note_add: s390x_elf_note_add()\n") ; If you're happy with the changes above, I can do it here, make sure it compiles, and queue it for the next release. Dave > --- > defs.h | 83 ++++++++++++++++++++++++++++++++++ > netdump.c | 11 ++++ > s390x.c | 150 > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- > 3 files changed, 236 insertions(+), 8 deletions(-) > > --- a/defs.h > +++ b/defs.h > @@ -41,6 +41,7 @@ > #include <dirent.h> > #include <time.h> > #include <zlib.h> > +#include <elf.h> > #include <sys/types.h> > #include <sys/stat.h> > #include <sys/param.h> > @@ -792,6 +793,7 @@ struct machdep_table { > void (*clear_machdep_cache)(void); > int (*xen_kdump_p2m_create)(struct xen_kdump_data *); > int (*in_alternate_stack)(int, ulong); > + void (*elf_note_add)(int, Elf64_Nhdr *); > }; > > /* > @@ -2747,6 +2749,86 @@ struct efi_memory_desc_t { > #define _SECTION_SIZE_BITS 28 > #define _MAX_PHYSMEM_BITS 42 > > +/* > + * S390 CPU timer ELF note > + */ > +#ifndef NT_S390_TIMER > +#define NT_S390_TIMER 0x301 > +#endif > + > +/* > + * S390 TOD clock comparator ELF note > + */ > +#ifndef NT_S390_TODCMP > +#define NT_S390_TODCMP 0x302 > +#endif > + > +/* > + * S390 TOD programmable register ELF note > + */ > +#ifndef NT_S390_TODPREG > +#define NT_S390_TODPREG 0x303 > +#endif > + > +/* > + * S390 control registers ELF note > + */ > +#ifndef NT_S390_CTRS > +#define NT_S390_CTRS 0x304 > +#endif > + > +/* > + * S390 prefix ELF note > + */ > +#ifndef NT_S390_PREFIX > +#define NT_S390_PREFIX 0x305 > +#endif > + > +/* > + * s390x prstatus ELF Note > + */ > +struct s390x_nt_prstatus { > + uint8_t pad1[32]; > + uint32_t pr_pid; > + uint8_t pad2[76]; > + uint64_t psw[2]; > + uint64_t gprs[16]; > + uint32_t acrs[16]; > + uint64_t orig_gpr2; > + uint32_t pr_fpvalid; > + uint8_t pad3[4]; > +} __attribute__ ((packed)); > + > +/* > + * S390x floating point register ELF Note > + */ > +#ifndef NT_FPREGSET > +#define NT_FPREGSET 0x2 > +#endif > + > +struct s390x_nt_fpregset { > + uint32_t fpc; > + uint32_t pad; > + uint64_t fprs[16]; > +} __attribute__ ((packed)); > + > +/* > + * s390x CPU info > + */ > +struct s390x_cpu > +{ > + uint64_t gprs[16]; > + uint64_t ctrs[16]; > + uint32_t acrs[16]; > + uint64_t fprs[16]; > + uint32_t fpc; > + uint64_t psw[2]; > + uint32_t prefix; > + uint64_t timer; > + uint64_t todcmp; > + uint32_t todpreg; > +}; > + > #endif /* S390X */ > > #ifdef PLATFORM > @@ -4196,6 +4278,7 @@ void get_netdump_regs(struct bt_info *, > int is_partial_netdump(void); > void get_netdump_regs_x86(struct bt_info *, ulong *, ulong *); > void get_netdump_regs_x86_64(struct bt_info *, ulong *, ulong *); > +void get_netdump_regs_s390x(struct bt_info *, ulong *, ulong *); > struct vmcore_data; > struct vmcore_data *get_kdump_vmcore_data(void); > int read_kdump(int, void *, int, ulong, physaddr_t); > --- a/netdump.c > +++ b/netdump.c > @@ -213,6 +213,11 @@ is_netdump(char *file, ulong source_quer > goto bailout; > break; > > + case EM_S390: > + if (machine_type_mismatch(file, "S390X", NULL, > + source_query)) > + goto bailout; > + break; > case EM_386: > if (machine_type_mismatch(file, "X86", NULL, > source_query)) > @@ -1989,7 +1994,8 @@ dump_Elf64_Nhdr(Elf64_Off offset, int st > netdump_print("(XEN_ELFNOTE_CRASH_REGS)\n"); > break; > } > - > + if (store && machdep->elf_note_add) > + machdep->elf_note_add(nd->num_prstatus_notes, note); > uptr = (ulonglong *)(ptr + note->n_namesz); > > /* > @@ -2082,6 +2088,9 @@ get_netdump_regs(struct bt_info *bt, ulo > return get_netdump_regs_x86_64(bt, eip, esp); > break; > > + case EM_S390: > + machdep->get_stack_frame(bt, eip, esp); > + break; > default: > error(FATAL, > "support for ELF machine type %d not available\n", > --- a/s390x.c > +++ b/s390x.c > @@ -56,7 +56,6 @@ static ulong s390x_processor_speed(void) > static int s390x_eframe_search(struct bt_info *); > static void s390x_back_trace_cmd(struct bt_info *); > static void s390x_dump_irq(int); > -static void s390x_get_stack_frame(struct bt_info *, ulong *, ulong > *); > static int s390x_dis_filter(ulong, char *); > static void s390x_cmd_mach(void); > static int s390x_get_smp_cpus(void); > @@ -64,7 +63,10 @@ static void s390x_display_machine_stats( > static void s390x_dump_line_number(ulong); > static struct line_number_hook s390x_line_number_hooks[]; > static int s390x_is_uvaddr(ulong, struct task_context *); > +static void s390x_get_stack_frame(struct bt_info *, ulong *, ulong > *); > > +static struct s390x_cpu *s390x_cpu_vec; > +static int s390x_cpu_cnt; > > /* > * Initialize member offsets > @@ -79,6 +81,115 @@ static void s390x_offsets_init(void) > "psw_save_area"); > } > > +/* > + * Return s390x CPU data for backtrace > + */ > +static struct s390x_cpu *s390x_cpu_get(struct bt_info *bt) > +{ > + unsigned int cpu = bt->tc->processor; > + unsigned long lowcore_ptr, prefix; > + uint32_t *nt_prefix; > + unsigned int i; > + > + lowcore_ptr = symbol_value("lowcore_ptr"); > + readmem(lowcore_ptr + cpu * sizeof(long), KVADDR, > + &prefix, sizeof(long), "lowcore_ptr", FAULT_ON_ERROR); > + for (i = 0; i < s390x_cpu_cnt; i++) { > + if (s390x_cpu_vec[i].prefix == prefix) { > + fprintf(fp, "GOT: %i\n", i); > + return &s390x_cpu_vec[i]; > + } > + } > + error(FATAL, "cannot determine CPU for task: %lx\n", bt->task); > +} > + > +/* > + * ELF core dump fuctions for storing CPU data > + */ > +static void s390x_elf_nt_prstatus_add(struct s390x_cpu *cpu, > + struct s390x_nt_prstatus *prstatus) > +{ > + memcpy(&cpu->psw, &prstatus->psw, sizeof(cpu->psw)); > + memcpy(&cpu->gprs, &prstatus->gprs, sizeof(cpu->gprs)); > + memcpy(&cpu->acrs, &prstatus->acrs, sizeof(cpu->acrs)); > +} > + > +static void s390x_elf_nt_fpregset_add(struct s390x_cpu *cpu, > + struct s390x_nt_fpregset *fpregset) > +{ > + memcpy(&cpu->fpc, &fpregset->fpc, sizeof(cpu->fpc)); > + memcpy(&cpu->fprs, &fpregset->fprs, sizeof(cpu->fprs)); > +} > + > +static void s390x_elf_nt_timer_add(struct s390x_cpu *cpu, void > *desc) > +{ > + memcpy(&cpu->timer, desc, sizeof(cpu->timer)); > +} > + > +static void s390x_elf_nt_todcmp_add(struct s390x_cpu *cpu, void > *desc) > +{ > + memcpy(&cpu->todcmp, desc, sizeof(cpu->todcmp)); > +} > + > +static void s390x_elf_nt_todpreg_add(struct s390x_cpu *cpu, void > *desc) > +{ > + memcpy(&cpu->todpreg, desc, sizeof(cpu->todpreg)); > +} > + > +static void s390x_elf_nt_ctrs_add(struct s390x_cpu *cpu, void *desc) > +{ > + memcpy(&cpu->ctrs, desc, sizeof(cpu->ctrs)); > +} > + > +static void s390x_elf_nt_prefix_add(struct s390x_cpu *cpu, void > *desc) > +{ > + memcpy(&cpu->prefix, desc, sizeof(cpu->prefix)); > +} > + > +static void *get_elf_note_desc(Elf64_Nhdr *note) > +{ > + void *ptr = note; > + > + return ptr + roundup(sizeof(*note) + note->n_namesz, 4); > +} > + > +static void s390x_elf_note_add(int elf_cpu_nr, Elf64_Nhdr *note) > +{ > + void *desc = get_elf_note_desc(note); > + struct s390x_cpu *cpu; > + > + if (elf_cpu_nr != s390x_cpu_cnt) { > + s390x_cpu_cnt++; > + s390x_cpu_vec = realloc(s390x_cpu_vec, > + s390x_cpu_cnt * sizeof(*s390x_cpu_vec)); > + if (!s390x_cpu_vec) > + error(FATAL, "cannot malloc cpu space."); > + } > + cpu = &s390x_cpu_vec[s390x_cpu_cnt - 1]; > + switch (note->n_type) { > + case NT_PRSTATUS: > + s390x_elf_nt_prstatus_add(cpu, desc); > + break; > + case NT_FPREGSET: > + s390x_elf_nt_fpregset_add(cpu, desc); > + break; > + case NT_S390_TIMER: > + s390x_elf_nt_timer_add(cpu, desc); > + break; > + case NT_S390_TODCMP: > + s390x_elf_nt_todcmp_add(cpu, desc); > + break; > + case NT_S390_TODPREG: > + s390x_elf_nt_todpreg_add(cpu, desc); > + break; > + case NT_S390_CTRS: > + s390x_elf_nt_ctrs_add(cpu, desc); > + break; > + case NT_S390_PREFIX: > + s390x_elf_nt_prefix_add(cpu, desc); > + break; > + } > +} > > /* > * Do all necessary machine-specific setup here. This is called > several > @@ -89,6 +200,9 @@ s390x_init(int when) > { > switch (when) > { > + case SETUP_ENV: > + machdep->elf_note_add = s390x_elf_note_add; > + break; > case PRE_SYMTAB: > machdep->verify_symbol = s390x_verify_symbol; > if (pc->flags & KERNEL_DEBUG_QUERY) > @@ -203,6 +317,7 @@ s390x_dump_machdep_table(ulong arg) > fprintf(fp, " verify_paddr: generic_verify_paddr()\n"); > fprintf(fp, " init_kernel_pgd: NULL\n"); > fprintf(fp, " value_to_symbol: > generic_machdep_value_to_symbol()\n"); > + fprintf(fp, " elf_not_add: s390x_elf_note_add()\n"); > fprintf(fp, " line_number_hooks: s390x_line_number_hooks\n"); > fprintf(fp, " last_pgd_read: %lx\n", machdep->last_pgd_read); > fprintf(fp, " last_pmd_read: %lx\n", machdep->last_pmd_read); > @@ -571,15 +686,37 @@ s390x_has_cpu(struct bt_info *bt) > * read lowcore for cpu > */ > static void > -s390x_get_lowcore(int cpu, char* lowcore) > +s390x_get_lowcore(struct bt_info *bt, char* lowcore) > { > unsigned long lowcore_array,lowcore_ptr; > + struct s390x_cpu *s390x_cpu; > + int cpu = bt->tc->processor; > > lowcore_array = symbol_value("lowcore_ptr"); > readmem(lowcore_array + cpu * S390X_WORD_SIZE,KVADDR, > - &lowcore_ptr, sizeof(long), "lowcore_ptr", FAULT_ON_ERROR); > - readmem(lowcore_ptr, KVADDR, lowcore, LOWCORE_SIZE, "lowcore", > + &lowcore_ptr, sizeof(long), "lowcore_ptr", > FAULT_ON_ERROR); > + readmem(lowcore_ptr, KVADDR, lowcore, LOWCORE_SIZE, "lowcore", > FAULT_ON_ERROR); > + > + if (!s390x_cpu_vec) > + return; > + > + /* Copy register information to defined places in lowcore */ > + s390x_cpu = s390x_cpu_get(bt); > + > + memcpy(lowcore + 4864, &s390x_cpu->psw, sizeof(s390x_cpu->psw)); > + memcpy(lowcore + 4736, &s390x_cpu->gprs, sizeof(s390x_cpu->gprs)); > + memcpy(lowcore + 4928, &s390x_cpu->acrs, sizeof(s390x_cpu->acrs)); > + > + memcpy(lowcore + 4892, &s390x_cpu->fpc, sizeof(s390x_cpu->fpc)); > + memcpy(lowcore + 4608, &s390x_cpu->fprs, sizeof(s390x_cpu->fprs)); > + > + memcpy(lowcore + 4888, &s390x_cpu->prefix, > sizeof(s390x_cpu->prefix)); > + memcpy(lowcore + 4992, &s390x_cpu->ctrs, sizeof(s390x_cpu->ctrs)); > + > + memcpy(lowcore + 4900, &s390x_cpu->todpreg, > sizeof(s390x_cpu->todpreg)); > + memcpy(lowcore + 4904, &s390x_cpu->timer, > sizeof(s390x_cpu->timer)); > + memcpy(lowcore + 4912, &s390x_cpu->todcmp, > sizeof(s390x_cpu->todcmp)); > } > > /* > @@ -627,7 +764,7 @@ s390x_back_trace_cmd(struct bt_info *bt) > fprintf(fp,"(active)\n"); > return; > } > - s390x_get_lowcore(cpu,lowcore); > + s390x_get_lowcore(bt, lowcore); > psw_flags = ULONG(lowcore + OFFSET(s390_lowcore_psw_save_area)); > > if(psw_flags & 0x1000000000000ULL){ > @@ -908,7 +1045,7 @@ s390x_get_stack_frame(struct bt_info *bt > char lowcore[LOWCORE_SIZE]; > > if(s390x_has_cpu(bt)) > - s390x_get_lowcore(s390x_cpu_of_task(bt->task),lowcore); > + s390x_get_lowcore(bt, lowcore); > > /* get the stack pointer */ > if(esp){ > @@ -1139,5 +1276,4 @@ try_closest: > } > } > } > - > #endif -- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility