OK, the patch as queued is attached. No major changes other than to rename the machdep->elf_note_add() function to machdep->dumpfile_init(). The idea is that, in the future, if there is ever *anything* in *any* type of dumpfile header that should be transmitted to the architecture code during the dumpfile discovery phase, then that function can be used. (For example, I could collaborate all of those machdep->xen_xxx() functions into using it, but I'm not going to bother changing them all at this point...) Thanks, Dave
Index: defs.h =================================================================== RCS file: /nfs/projects/cvs/crash/defs.h,v retrieving revision 1.410 retrieving revision 1.411 diff -u -r1.410 -r1.411 --- defs.h 4 Feb 2010 21:04:36 -0000 1.410 +++ defs.h 12 Feb 2010 19:44:47 -0000 1.411 @@ -792,6 +792,7 @@ void (*clear_machdep_cache)(void); int (*xen_kdump_p2m_create)(struct xen_kdump_data *); int (*in_alternate_stack)(int, ulong); + void (*dumpfile_init)(int, void *); }; /* Index: netdump.c =================================================================== RCS file: /nfs/projects/cvs/crash/netdump.c,v retrieving revision 1.95 retrieving revision 1.96 diff -u -r1.95 -r1.96 --- netdump.c 3 Dec 2009 15:36:42 -0000 1.95 +++ netdump.c 12 Feb 2010 19:44:48 -0000 1.96 @@ -213,6 +213,11 @@ 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)) @@ -1990,6 +1995,9 @@ break; } + if (store && machine_type("S390X")) + machdep->dumpfile_init(nd->num_prstatus_notes, note); + uptr = (ulonglong *)(ptr + note->n_namesz); /* @@ -2082,6 +2090,9 @@ 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", Index: s390x.c =================================================================== RCS file: /nfs/projects/cvs/crash/s390x.c,v retrieving revision 1.41 retrieving revision 1.42 diff -u -r1.41 -r1.42 --- s390x.c 10 Feb 2010 20:07:38 -0000 1.41 +++ s390x.c 12 Feb 2010 19:44:48 -0000 1.42 @@ -16,6 +16,7 @@ * GNU General Public License for more details. */ #ifdef S390X +#include <elf.h> #include "defs.h" #define S390X_WORD_SIZE 8 @@ -41,6 +42,86 @@ #define LOWCORE_SIZE 8192 /* + * 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; +}; + +/* * declarations of static functions */ static void s390x_print_lowcore(char*, struct bt_info*,int); @@ -79,6 +160,117 @@ "psw_save_area"); } +static struct s390x_cpu *s390x_cpu_vec; +static int s390x_cpu_cnt; +/* + * 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; + 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) + return &s390x_cpu_vec[i]; + } + error(FATAL, "cannot determine CPU for task: %lx\n", bt->task); + return NULL; +} + +/* + * 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, void *note_ptr) +{ + Elf64_Nhdr *note = note_ptr; + struct s390x_cpu *cpu; + void *desc; + + desc = get_elf_note_desc(note); + 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 +281,9 @@ { switch (when) { + case SETUP_ENV: + machdep->dumpfile_init = s390x_elf_note_add; + break; case PRE_SYMTAB: machdep->verify_symbol = s390x_verify_symbol; if (pc->flags & KERNEL_DEBUG_QUERY) @@ -203,6 +398,7 @@ 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, " dumpfile_init: 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); @@ -526,6 +722,7 @@ "Option '-e' is not implemented for this architecture\n")); } +#ifdef DEPRECATED /* * returns cpu number of task */ @@ -552,6 +749,7 @@ } return cpu; } +#endif /* * returns true, if task of bt currently is executed by a cpu @@ -571,15 +769,37 @@ * 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", 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)); } /* @@ -621,13 +841,12 @@ if(s390x_has_cpu(bt)){ char lowcore[LOWCORE_SIZE]; unsigned long psw_flags; - int cpu = s390x_cpu_of_task(bt->task); if (ACTIVE()) { 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 +1127,7 @@ 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){
-- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility