Hi Dave, Next patch... We will have ELF core dumps on s390x in the near future: 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 The mapping of a s390 CPU to the correct note number is done via the prefix register of the CPUs. This is implemented in s390x_get_note_nr(). The function gets the prefix register for the logical CPU number from the lowcore pointer array (global variable lowcore_ptr) and searches the matching prefix register note. If CPU information is found in the dump for a running task, it is converted into a generic s390x_cpu structure which is then attached to "bt->machdep". If "bt->machdep" is set, the s390x "machdep->get_stack_frame()" function uses that register information. --- defs.h | 66 ++++++++++++++++++++++++ netdump.c | 164 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ netdump.h | 6 ++ s390x.c | 34 ++++++++++-- symbols.c | 2 5 files changed, 264 insertions(+), 8 deletions(-) --- a/defs.h +++ b/defs.h @@ -2747,6 +2747,71 @@ 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 + +/* + * S390 floating point register ELF Note + */ +#ifndef NT_FPREGSET +#define NT_FPREGSET 0x2 +#endif + +struct nt_s390_fpregset_64 { + 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 +4261,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)) @@ -1858,6 +1863,72 @@ dump_Elf64_Nhdr(Elf64_Off offset, int st } } break; + case NT_FPREGSET: + netdump_print("(NT_FPREGSET)"); + if (store) { + for (i = 0; i < NR_CPUS; i++) { + if (nd->nt_fpregset_percpu[i]) + continue; + nd->nt_fpregset_percpu[i] = (void *)note; + break; + } + } + break; + case NT_S390_TIMER: + netdump_print("(NT_S390_TIMER)\n"); + if (store) { + for (i = 0; i < NR_CPUS; i++) { + if (nd->nt_s390_timer_percpu[i]) + continue; + nd->nt_s390_timer_percpu[i] = (void *)note; + break; + } + } + break; + case NT_S390_TODCMP: + netdump_print("(NT_S390_TODCMP)\n"); + if (store) { + for (i = 0; i < NR_CPUS; i++) { + if (nd->nt_s390_todcmp_percpu[i]) + continue; + nd->nt_s390_todcmp_percpu[i] = (void *)note; + break; + } + } + break; + case NT_S390_TODPREG: + netdump_print("(NT_S390_TODPREG)\n"); + if (store) { + for (i = 0; i < NR_CPUS; i++) { + if (nd->nt_s390_todpreg_percpu[i]) + continue; + nd->nt_s390_todpreg_percpu[i] = (void *)note; + break; + } + } + break; + case NT_S390_CTRS: + netdump_print("(NT_S390_CTRS)\n"); + if (store) { + for (i = 0; i < NR_CPUS; i++) { + if (nd->nt_s390_ctrs_percpu[i]) + continue; + nd->nt_s390_ctrs_percpu[i] = (void *)note; + break; + } + } + break; + case NT_S390_PREFIX: + netdump_print("(NT_S390_PREFIX)\n"); + if (store) { + for (i = 0; i < NR_CPUS; i++) { + if (nd->nt_s390_prefix_percpu[i]) + continue; + nd->nt_s390_prefix_percpu[i] = (void *)note; + break; + } + } + break; case NT_PRPSINFO: netdump_print("(NT_PRPSINFO)\n"); if (store) @@ -2082,6 +2153,9 @@ get_netdump_regs(struct bt_info *bt, ulo return get_netdump_regs_x86_64(bt, eip, esp); break; + case EM_S390: + get_netdump_regs_s390x(bt, eip, esp); + break; default: error(FATAL, "support for ELF machine type %d not available\n", @@ -2381,6 +2455,96 @@ get_netdump_regs_ppc64(struct bt_info *b machdep->get_stack_frame(bt, eip, esp); } +static void * +get_note_desc(Elf64_Nhdr *note) +{ + void *ptr = note; + + return ptr + roundup(sizeof(*note) + note->n_namesz, 4); +} + +static int +s390x_get_note_nr(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 < nd->num_prstatus_notes; i++) { + nt_prefix = get_note_desc(nd->nt_s390_prefix_percpu[i]); + if (*nt_prefix == prefix) + return i; + } + error(FATAL, "cannot determine NT_PRSTATUS ELF note for task: %lx\n", + bt->task); +} + +static void +s390x_note_to_s390x_cpu(struct s390x_cpu *s390x_cpu, int note_nr) +{ + struct nt_s390_fpregset_64 *nt_s390_fpregset; + Elf64_Nhdr *note; + char *ptr; + + /* Copy prstatus note */ + note = (Elf64_Nhdr *) nd->nt_prstatus_percpu[note_nr]; + ptr = get_note_desc(note) + MEMBER_OFFSET("elf_prstatus", "pr_reg"); + memcpy(&s390x_cpu->psw, ptr, sizeof(s390x_cpu->psw)); + memcpy(&s390x_cpu->gprs, ptr + 16, sizeof(s390x_cpu->gprs)); + memcpy(&s390x_cpu->acrs, ptr + 16 + 16 * 8, sizeof(s390x_cpu->acrs)); + + /* Copy s390 floating point register note */ + nt_s390_fpregset = get_note_desc(nd->nt_fpregset_percpu[note_nr]); + memcpy(&s390x_cpu->fpc, &nt_s390_fpregset->fpc, + sizeof(s390x_cpu->fpc)); + memcpy(&s390x_cpu->fprs, &nt_s390_fpregset->fprs, + sizeof(s390x_cpu->fprs)); + + /* Copy s390 additional notes */ + memcpy(&s390x_cpu->timer, + get_note_desc(nd->nt_s390_timer_percpu[note_nr]), + sizeof(s390x_cpu->timer)); + memcpy(&s390x_cpu->todcmp, + get_note_desc(nd->nt_s390_todcmp_percpu[note_nr]), + sizeof(s390x_cpu->todcmp)); + memcpy(&s390x_cpu->todpreg, + get_note_desc(nd->nt_s390_todpreg_percpu[note_nr]), + sizeof(s390x_cpu->todpreg)); + memcpy(&s390x_cpu->ctrs, + get_note_desc(nd->nt_s390_ctrs_percpu[note_nr]), + sizeof(s390x_cpu->ctrs)); + memcpy(&s390x_cpu->prefix, + get_note_desc(nd->nt_s390_prefix_percpu[note_nr]), + sizeof(s390x_cpu->prefix)); +} + +void +get_netdump_regs_s390x(struct bt_info *bt, ulong *eip, ulong *esp) +{ + static struct s390x_cpu s390x_cpu; + unsigned int note_nr; + Elf64_Nhdr *note; + + bt->machdep = NULL; + if (nd->num_prstatus_notes == 0) + goto out; + if (!(is_task_active(bt->task) && + (kt->cpu_flags[bt->tc->processor] & ONLINE))) + goto out; + note_nr = s390x_get_note_nr(bt); + if (!nd->nt_prstatus_percpu[note_nr]) + error(FATAL, "cannot determine NT_PRSTATUS ELF note for " + "task: %lx\n", bt->task); + s390x_note_to_s390x_cpu(&s390x_cpu, note_nr); + bt->machdep = &s390x_cpu; +out: + machdep->get_stack_frame(bt, eip, esp); +} + int is_partial_netdump(void) { --- a/netdump.h +++ b/netdump.h @@ -68,6 +68,12 @@ struct vmcore_data { ulong switch_stack; uint num_prstatus_notes; void *nt_prstatus_percpu[NR_CPUS]; + void *nt_fpregset_percpu[NR_CPUS]; + void *nt_s390_timer_percpu[NR_CPUS]; + void *nt_s390_todcmp_percpu[NR_CPUS]; + void *nt_s390_todpreg_percpu[NR_CPUS]; + void *nt_s390_ctrs_percpu[NR_CPUS]; + void *nt_s390_prefix_percpu[NR_CPUS]; struct xen_kdump_data *xen_kdump_data; void *vmcoreinfo; uint size_vmcoreinfo; --- 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,6 +63,7 @@ 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 *); /* @@ -571,15 +571,36 @@ 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 (!bt->machdep) + return; + + s390x_cpu = bt->machdep; + /* Copy ELF register information to defined places in lowcore */ + 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 +648,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 +929,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 +1160,4 @@ try_closest: } } } - #endif --- a/symbols.c +++ b/symbols.c @@ -2710,7 +2710,7 @@ is_shared_object(char *file) break; case EM_S390: - if (machine_type("S390")) + if (machine_type("S390X")) return TRUE; break; }
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 The mapping of a s390 CPU to the correct note number is done via the prefix register of the CPUs. This is implemented in s390x_get_note_nr(). The function gets the prefix register for the logical CPU number from the lowcore pointer array (global variable lowcore_ptr) and searches the matching prefix register note. If CPU information is found in the dump for a running task, it is converted into a generic s390x_cpu structure which is then attached to "bt->machdep". If "bt->machdep" is set, the s390x "machdep->get_stack_frame()" function uses that register information. --- defs.h | 66 ++++++++++++++++++++++++ netdump.c | 164 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ netdump.h | 6 ++ s390x.c | 34 ++++++++++-- symbols.c | 2 5 files changed, 264 insertions(+), 8 deletions(-) --- a/defs.h +++ b/defs.h @@ -2747,6 +2747,71 @@ 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 + +/* + * S390 floating point register ELF Note + */ +#ifndef NT_FPREGSET +#define NT_FPREGSET 0x2 +#endif + +struct nt_s390_fpregset_64 { + 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 +4261,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)) @@ -1858,6 +1863,72 @@ dump_Elf64_Nhdr(Elf64_Off offset, int st } } break; + case NT_FPREGSET: + netdump_print("(NT_FPREGSET)"); + if (store) { + for (i = 0; i < NR_CPUS; i++) { + if (nd->nt_fpregset_percpu[i]) + continue; + nd->nt_fpregset_percpu[i] = (void *)note; + break; + } + } + break; + case NT_S390_TIMER: + netdump_print("(NT_S390_TIMER)\n"); + if (store) { + for (i = 0; i < NR_CPUS; i++) { + if (nd->nt_s390_timer_percpu[i]) + continue; + nd->nt_s390_timer_percpu[i] = (void *)note; + break; + } + } + break; + case NT_S390_TODCMP: + netdump_print("(NT_S390_TODCMP)\n"); + if (store) { + for (i = 0; i < NR_CPUS; i++) { + if (nd->nt_s390_todcmp_percpu[i]) + continue; + nd->nt_s390_todcmp_percpu[i] = (void *)note; + break; + } + } + break; + case NT_S390_TODPREG: + netdump_print("(NT_S390_TODPREG)\n"); + if (store) { + for (i = 0; i < NR_CPUS; i++) { + if (nd->nt_s390_todpreg_percpu[i]) + continue; + nd->nt_s390_todpreg_percpu[i] = (void *)note; + break; + } + } + break; + case NT_S390_CTRS: + netdump_print("(NT_S390_CTRS)\n"); + if (store) { + for (i = 0; i < NR_CPUS; i++) { + if (nd->nt_s390_ctrs_percpu[i]) + continue; + nd->nt_s390_ctrs_percpu[i] = (void *)note; + break; + } + } + break; + case NT_S390_PREFIX: + netdump_print("(NT_S390_PREFIX)\n"); + if (store) { + for (i = 0; i < NR_CPUS; i++) { + if (nd->nt_s390_prefix_percpu[i]) + continue; + nd->nt_s390_prefix_percpu[i] = (void *)note; + break; + } + } + break; case NT_PRPSINFO: netdump_print("(NT_PRPSINFO)\n"); if (store) @@ -2082,6 +2153,9 @@ get_netdump_regs(struct bt_info *bt, ulo return get_netdump_regs_x86_64(bt, eip, esp); break; + case EM_S390: + get_netdump_regs_s390x(bt, eip, esp); + break; default: error(FATAL, "support for ELF machine type %d not available\n", @@ -2381,6 +2455,96 @@ get_netdump_regs_ppc64(struct bt_info *b machdep->get_stack_frame(bt, eip, esp); } +static void * +get_note_desc(Elf64_Nhdr *note) +{ + void *ptr = note; + + return ptr + roundup(sizeof(*note) + note->n_namesz, 4); +} + +static int +s390x_get_note_nr(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 < nd->num_prstatus_notes; i++) { + nt_prefix = get_note_desc(nd->nt_s390_prefix_percpu[i]); + if (*nt_prefix == prefix) + return i; + } + error(FATAL, "cannot determine NT_PRSTATUS ELF note for task: %lx\n", + bt->task); +} + +static void +s390x_note_to_s390x_cpu(struct s390x_cpu *s390x_cpu, int note_nr) +{ + struct nt_s390_fpregset_64 *nt_s390_fpregset; + Elf64_Nhdr *note; + char *ptr; + + /* Copy prstatus note */ + note = (Elf64_Nhdr *) nd->nt_prstatus_percpu[note_nr]; + ptr = get_note_desc(note) + MEMBER_OFFSET("elf_prstatus", "pr_reg"); + memcpy(&s390x_cpu->psw, ptr, sizeof(s390x_cpu->psw)); + memcpy(&s390x_cpu->gprs, ptr + 16, sizeof(s390x_cpu->gprs)); + memcpy(&s390x_cpu->acrs, ptr + 16 + 16 * 8, sizeof(s390x_cpu->acrs)); + + /* Copy s390 floating point register note */ + nt_s390_fpregset = get_note_desc(nd->nt_fpregset_percpu[note_nr]); + memcpy(&s390x_cpu->fpc, &nt_s390_fpregset->fpc, + sizeof(s390x_cpu->fpc)); + memcpy(&s390x_cpu->fprs, &nt_s390_fpregset->fprs, + sizeof(s390x_cpu->fprs)); + + /* Copy s390 additional notes */ + memcpy(&s390x_cpu->timer, + get_note_desc(nd->nt_s390_timer_percpu[note_nr]), + sizeof(s390x_cpu->timer)); + memcpy(&s390x_cpu->todcmp, + get_note_desc(nd->nt_s390_todcmp_percpu[note_nr]), + sizeof(s390x_cpu->todcmp)); + memcpy(&s390x_cpu->todpreg, + get_note_desc(nd->nt_s390_todpreg_percpu[note_nr]), + sizeof(s390x_cpu->todpreg)); + memcpy(&s390x_cpu->ctrs, + get_note_desc(nd->nt_s390_ctrs_percpu[note_nr]), + sizeof(s390x_cpu->ctrs)); + memcpy(&s390x_cpu->prefix, + get_note_desc(nd->nt_s390_prefix_percpu[note_nr]), + sizeof(s390x_cpu->prefix)); +} + +void +get_netdump_regs_s390x(struct bt_info *bt, ulong *eip, ulong *esp) +{ + static struct s390x_cpu s390x_cpu; + unsigned int note_nr; + Elf64_Nhdr *note; + + bt->machdep = NULL; + if (nd->num_prstatus_notes == 0) + goto out; + if (!(is_task_active(bt->task) && + (kt->cpu_flags[bt->tc->processor] & ONLINE))) + goto out; + note_nr = s390x_get_note_nr(bt); + if (!nd->nt_prstatus_percpu[note_nr]) + error(FATAL, "cannot determine NT_PRSTATUS ELF note for " + "task: %lx\n", bt->task); + s390x_note_to_s390x_cpu(&s390x_cpu, note_nr); + bt->machdep = &s390x_cpu; +out: + machdep->get_stack_frame(bt, eip, esp); +} + int is_partial_netdump(void) { --- a/netdump.h +++ b/netdump.h @@ -68,6 +68,12 @@ struct vmcore_data { ulong switch_stack; uint num_prstatus_notes; void *nt_prstatus_percpu[NR_CPUS]; + void *nt_fpregset_percpu[NR_CPUS]; + void *nt_s390_timer_percpu[NR_CPUS]; + void *nt_s390_todcmp_percpu[NR_CPUS]; + void *nt_s390_todpreg_percpu[NR_CPUS]; + void *nt_s390_ctrs_percpu[NR_CPUS]; + void *nt_s390_prefix_percpu[NR_CPUS]; struct xen_kdump_data *xen_kdump_data; void *vmcoreinfo; uint size_vmcoreinfo; --- 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,6 +63,7 @@ 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 *); /* @@ -571,15 +571,36 @@ 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 (!bt->machdep) + return; + + s390x_cpu = bt->machdep; + /* Copy ELF register information to defined places in lowcore */ + 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 +648,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 +929,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 +1160,4 @@ try_closest: } } } - #endif --- a/symbols.c +++ b/symbols.c @@ -2710,7 +2710,7 @@ is_shared_object(char *file) break; case EM_S390: - if (machine_type("S390")) + if (machine_type("S390X")) return TRUE; break; }
-- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility