FAQ Search Today's Posts Mark Forums Read
» Video Reviews

» Linux Archive

Linux-archive is a website aiming to archive linux email lists and to make them easily accessible for linux users/developers.


» Sponsor

» Partners

» Sponsor

Go Back   Linux Archive > Redhat > Crash Utility

 
 
LinkBack Thread Tools
 
Old 02-11-2010, 11:06 AM
Michael Holzheu
 
Default Add ELF core dump support for s390x

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)
");
+ 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)
");
+ 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)
");
+ 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)
");
+ 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)
");
+ 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)
");
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
",
@@ -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
",
+ 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
", 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)
");
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@redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility
 
Old 02-11-2010, 03:13 PM
Dave Anderson
 
Default Add ELF core dump support for s390x

----- "Michael Holzheu" <holzheu@linux.vnet.ibm.com> wrote:

> 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.

OK, first the simple stuff...

The change to is_shared_object() doesn't make sense to me.
That function is only used when loading extension modules.
You make the following change in the ELFCLASS32 section.
So if a 32-bit s390 crash session attempts to load a 32-bit
s390 extension module, your patch will cause it to fall
through and fail:

--- 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;

How can that work?

Anyway, on to the the bigger picture...

--- 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;

This is bit hard to swallow. A while back I went through and purged
several prior static declarations of data structures that used arrays
indexed with NR_CPUS -- replacing them with pointers that dynamically
allocated the arrays when the actual number of cpus was known.
I really don't want to ever *add* any new instances of static arrays
indexed with NR_CPUS. Now you could argue that the currently-existing
nt_prstatus_percpu[NR_CPUS] is there, but that should probably be changed
to malloc() NR_CPUS-worth during the dumpfile discovery phase, and then
do a realloc() later on when the actual number of cpus is determined.

Anyway, the x86_64 and ia64 arches are up to 4096 NR_CPUS, so your patch
adds ~200k of useless static data for those architectures. So I suggest
suggest that all of your new NR_CPU-indexed fields -- none of which are
of any interest to the other architectures -- should be moved into s390x.c,
and then just a single pointer to the collective data could be put into
the vmcore_data structure. (i.e., similar to the xen_kdump_data pointer).
Let's keep the vmcore_data structure as generic as possible.

Also BTW, there's a lot work d one reading/saving the new note data,
but once that's accomplished, I don't see where the data is ever
used? What's the point of saving it if it's not referred
to somewhere later on? You couldn't even look at it unless
you ran a gdb on the crash session. Or am I missing something?
I see the temporary bt->machdep reference to the static s390x_cpu
data structure in get_netdump_regs_s390x(). But I would think
that if you're going to the trouble to save all of that data,
that you might want to put the s390x_cpu structure in s390x,
and then maybe dump its data in s390x_dump_machdep_table()
via "help -m".

Now, the NT_S390_XXX defines -- were did they originate exactly?
If I google them -- all I get is a reference to your 2-hour old
crash-utility mailing list post! Anyway, I haven't tried compiling
it, but given that they are all #define'd in the "#ifdef S390X" section
of defs.h, then netdump.c couldn't possibly compile for any other arch.
Also, the NT_S390_XXX numerical values are probably safe and would never
be misconstrued, but the NT_FPREGSET note is the only new note section
that could conceivably show up in some other architecture, so that
should be restricted to s390x only.

What do you think?

Dave





>
> ---
> 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)
");
> + 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)
");
> + 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)
");
> + 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)
");
> + 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)
");
> + 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)
");
> 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
",
> @@ -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
",
> + 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
", 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)
");
> 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@redhat.com
> https://www.redhat.com/mailman/listinfo/crash-utility

--
Crash-utility mailing list
Crash-utility@redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility
 
Old 02-12-2010, 09:40 AM
Michael Holzheu
 
Default Add ELF core dump support for s390x

Hello Dave,

On Thu, 2010-02-11 at 11:13 -0500, Dave Anderson wrote:
> OK, first the simple stuff...
>
> The change to is_shared_object() doesn't make sense to me.
> That function is only used when loading extension modules.
> You make the following change in the ELFCLASS32 section.
> So if a 32-bit s390 crash session attempts to load a 32-bit
> s390 extension module, your patch will cause it to fall
> through and fail:
>
> --- 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;
>
> How can that work?

Ok, that was probably a left over from my former work on the snap
extension module. That chunk is not needed for the EFL core dump
support. Sorry for that.

> Anyway, on to the the bigger picture...
> --- 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;
>
> This is bit hard to swallow. A while back I went through and purged
> several prior static declarations of data structures that used arrays
> indexed with NR_CPUS -- replacing them with pointers that dynamically
> allocated the arrays when the actual number of cpus was known.
> I really don't want to ever *add* any new instances of static arrays
> indexed with NR_CPUS. Now you could argue that the currently-existing
> nt_prstatus_percpu[NR_CPUS] is there, but that should probably be changed
> to malloc() NR_CPUS-worth during the dumpfile discovery phase, and then
> do a realloc() later on when the actual number of cpus is determined.
>
> Anyway, the x86_64 and ia64 arches are up to 4096 NR_CPUS, so your patch
> adds ~200k of useless static data for those architectures. So I suggest
> suggest that all of your new NR_CPU-indexed fields -- none of which are
> of any interest to the other architectures -- should be moved into s390x.c,
> and then just a single pointer to the collective data could be put into
> the vmcore_data structure. (i.e., similar to the xen_kdump_data pointer).
> Let's keep the vmcore_data structure as generic as possible.

Ok, so I will try to replace the arrays with one **void nt_s390
pointer.

> Also BTW, there's a lot work d one reading/saving the new note data,
> but once that's accomplished, I don't see where the data is ever
> used? What's the point of saving it if it's not referred
> to somewhere later on? You couldn't even look at it unless
> you ran a gdb on the crash session. Or am I missing something?

You are missing something. The data is copied to the s390x_cpu structure
in case of a backtrace of an active CPU.

> I see the temporary bt->machdep reference to the static s390x_cpu
> data structure in get_netdump_regs_s390x(). But I would think
> that if you're going to the trouble to save all of that data,
> that you might want to put the s390x_cpu structure in s390x,
> and then maybe dump its data in s390x_dump_machdep_table()
> via "help -m".
>
> Now, the NT_S390_XXX defines -- were did they originate exactly?

We have already brought the new s390 note sections upstream in the
binutils package. This is the place where new note sections are defined
first. In the next merge window for the Linux kernel, we also will bring
the new defines upstream to the Linux kernel (include/linux/elf.h).

> If I google them -- all I get is a reference to your 2-hour old
> crash-utility mailing list post!

Be patient.

> Anyway, I haven't tried compiling
> it, but given that they are all #define'd in the "#ifdef S390X" section
> of defs.h, then netdump.c couldn't possibly compile for any other arch.

Yes, I noticed that 10 seconds after I hit the send button for that
patch. The defines have to be outside of #ifdef S390X or when I change
the patch regarding your wishes, I can probably move them to s390x.c

> Also, the NT_S390_XXX numerical values are probably safe and would never
> be misconstrued, but the NT_FPREGSET note is the only new note section
> that could conceivably show up in some other architecture, so that
> should be restricted to s390x only.

> What do you think?

Good points, I try to change my patch and move more stuff into s390x.c.

Michael

--
Crash-utility mailing list
Crash-utility@redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility
 
Old 02-12-2010, 12:19 PM
Michael Holzheu
 
Default Add ELF core dump support for s390x

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.
---
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)
");
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
",
--- 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
", i);
+ return &s390x_cpu_vec[i];
+ }
+ }
+ error(FATAL, "cannot determine CPU for task: %lx
", 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()
");
fprintf(fp, " init_kernel_pgd: NULL
");
fprintf(fp, " value_to_symbol: generic_machdep_value_to_symbol()
");
+ fprintf(fp, " elf_not_add: s390x_elf_note_add()
");
fprintf(fp, " line_number_hooks: s390x_line_number_hooks
");
fprintf(fp, " last_pgd_read: %lx
", machdep->last_pgd_read);
fprintf(fp, " last_pmd_read: %lx
", 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)
");
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@redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility
 
Old 02-12-2010, 01:53 PM
Dave Anderson
 
Default Add ELF core dump support for s390x

----- "Michael Holzheu" <holzheu@linux.vnet.ibm.com> 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()
") ;

to:

+ fprintf(fp, " elf_note_add: s390x_elf_note_add()
") ;

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)
");
> 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
",
> --- 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
", i);
> + return &s390x_cpu_vec[i];
> + }
> + }
> + error(FATAL, "cannot determine CPU for task: %lx
", 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()
");
> fprintf(fp, " init_kernel_pgd: NULL
");
> fprintf(fp, " value_to_symbol:
> generic_machdep_value_to_symbol()
");
> + fprintf(fp, " elf_not_add: s390x_elf_note_add()
");
> fprintf(fp, " line_number_hooks: s390x_line_number_hooks
");
> fprintf(fp, " last_pgd_read: %lx
", machdep->last_pgd_read);
> fprintf(fp, " last_pmd_read: %lx
", 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)
");
> 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@redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility
 
Old 02-12-2010, 02:41 PM
Dave Anderson
 
Default Add ELF core dump support for s390x

----- "Dave Anderson" <anderson@redhat.com> wrote:

> If you're happy with the changes above, I can do it here, make sure
> it compiles, and queue it for the next release.

Here's my proposed patch, along with cleanups for these compiler warnings:

s390x.c: In function 's390x_cpu_get':
s390x.c:91: warning: unused variable 'nt_prefix'
s390x.c: In function 's390x_back_trace_cmd':
s390x.c:762: warning: unused variable 'cpu'
s390x.c: In function 's390x_cpu_get'
s390x.c:104: warning: control reaches end of non-void function
s390x.c:650: warning: ‘s390x_cpu_of_task’ defined but not used

BTW, the second stanza in the patch to s390x.c may require hand-patching --
your original didn't apply on my current tree.

Anyway, does this work for you?

Dave
--
Crash-utility mailing list
Crash-utility@redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility
 
Old 02-12-2010, 02:51 PM
Michael Holzheu
 
Default Add ELF core dump support for s390x

On Fri, 2010-02-12 at 09:53 -0500, Dave Anderson wrote:
> > 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 *);

Makes sense!

>
> And remove this -- it doesn't exist anymore:
>
> +void get_netdump_regs_s390x(struct bt_info *, ulong *, ulong *);

Yes, I already removed that in my local patch.

> 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);

Why the check for s390x? All architectures that do not define
"elf_note_add" will not be affected.

> 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);

ok

>
> and fix this typo:
>
> + fprintf(fp, " elf_not_add: s390x_elf_note_add()
") ;
>
> to:
>
> + fprintf(fp, " elf_note_add: s390x_elf_note_add()
") ;

ok

> If you're happy with the changes above, I can do it here, make sure
> it compiles, and queue it for the next release.

I attached a new patch (without the s390x check in netdump.c). I also
moved all the definitions from defs.h into s390x.c. No need to have them
in the header file.

Thanks!

Michael
---

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.
---
defs.h | 1
netdump.c | 11 ++
s390x.c | 230 ++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++--
3 files changed, 235 insertions(+), 7 deletions(-)

--- a/defs.h
+++ b/defs.h
@@ -792,6 +792,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, void *);
};

/*
--- 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)
");
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
",
--- a/s390x.c
+++ b/s390x.c
@@ -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);
@@ -65,6 +146,8 @@ 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 struct s390x_cpu *s390x_cpu_vec;
+static int s390x_cpu_cnt;

/*
* Initialize member offsets
@@ -79,6 +162,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)
+ return &s390x_cpu_vec[i];
+ }
+ error(FATAL, "cannot determine CPU for task: %lx
", 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, 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 @@ 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 +398,7 @@ s390x_dump_machdep_table(ulong arg)
fprintf(fp, " verify_paddr: generic_verify_paddr()
");
fprintf(fp, " init_kernel_pgd: NULL
");
fprintf(fp, " value_to_symbol: generic_machdep_value_to_symbol()
");
+ fprintf(fp, " elf_note_add: s390x_elf_note_add()
");
fprintf(fp, " line_number_hooks: s390x_line_number_hooks
");
fprintf(fp, " last_pgd_read: %lx
", machdep->last_pgd_read);
fprintf(fp, " last_pmd_read: %lx
", machdep->last_pmd_read);
@@ -571,15 +767,38 @@ 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 +846,7 @@ s390x_back_trace_cmd(struct bt_info *bt)
fprintf(fp,"(active)
");
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 @@ 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 +1358,4 @@ try_closest:
}
}
}
-
#endif

--
Crash-utility mailing list
Crash-utility@redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility
 
Old 02-12-2010, 03:03 PM
Dave Anderson
 
Default Add ELF core dump support for s390x

Sorry -- our paths are crossing -- my proposed patch went out
before I received this one.

Anyway...

> Why the check for s390x? All architectures that do not define
> "elf_note_add" will not be affected.

But if they *do* define it in the future, they might *not* want to call it
from here. I wanted to make the new function as flexibly-usable as possible.

> I attached a new patch (without the s390x check in netdump.c). I also
> moved all the definitions from defs.h into s390x.c. No need to have them
> in the header file.

Good -- I had moved the "#include <elf.h>" down into the "#ifdef S390X"
section, but I like the wholesale movement too. Doing it that way will
make this patch absolutely incapable of changing any other architecture's
behavior.

The only other patch mis-matches would be for the compiler warnings...

Thanks,
Dave

>
> Thanks!
>
> Michael
> ---
>
> 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.
> ---
> defs.h | 1
> netdump.c | 11 ++
> s390x.c | 230
> ++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++--
> 3 files changed, 235 insertions(+), 7 deletions(-)
>
> --- a/defs.h
> +++ b/defs.h
> @@ -792,6 +792,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, void *);
> };
>
> /*
> --- 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)
");
> 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
",
> --- a/s390x.c
> +++ b/s390x.c
> @@ -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);
> @@ -65,6 +146,8 @@ 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 struct s390x_cpu *s390x_cpu_vec;
> +static int s390x_cpu_cnt;
>
> /*
> * Initialize member offsets
> @@ -79,6 +162,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)
> + return &s390x_cpu_vec[i];
> + }
> + error(FATAL, "cannot determine CPU for task: %lx
", 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, 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 @@ 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 +398,7 @@ s390x_dump_machdep_table(ulong arg)
> fprintf(fp, " verify_paddr: generic_verify_paddr()
");
> fprintf(fp, " init_kernel_pgd: NULL
");
> fprintf(fp, " value_to_symbol:
> generic_machdep_value_to_symbol()
");
> + fprintf(fp, " elf_note_add: s390x_elf_note_add()
");
> fprintf(fp, " line_number_hooks: s390x_line_number_hooks
");
> fprintf(fp, " last_pgd_read: %lx
", machdep->last_pgd_read);
> fprintf(fp, " last_pmd_read: %lx
", machdep->last_pmd_read);
> @@ -571,15 +767,38 @@ 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 +846,7 @@ s390x_back_trace_cmd(struct bt_info *bt)
> fprintf(fp,"(active)
");
> 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 @@ 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 +1358,4 @@ try_closest:
> }
> }
> }
> -
> #endif

--
Crash-utility mailing list
Crash-utility@redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility
 
Old 02-12-2010, 03:09 PM
Michael Holzheu
 
Default Add ELF core dump support for s390x

Hi Dave,

On Fri, 2010-02-12 at 10:41 -0500, Dave Anderson wrote:
> ----- "Dave Anderson" <anderson@redhat.com> wrote:
>
> > If you're happy with the changes above, I can do it here, make sure
> > it compiles, and queue it for the next release.
>
> Here's my proposed patch, along with cleanups for these compiler warnings:
>
> s390x.c: In function 's390x_cpu_get':
> s390x.c:91: warning: unused variable 'nt_prefix'
> s390x.c: In function 's390x_back_trace_cmd':
> s390x.c:762: warning: unused variable 'cpu'
> s390x.c: In function 's390x_cpu_get'
> s390x.c:104: warning: control reaches end of non-void function
> s390x.c:650: warning: ‘s390x_cpu_of_task’ defined but not used

Thanks, I forgot to switch on WARNING_OPTIONS in my Makefile.

> BTW, the second stanza in the patch to s390x.c may require hand-patching --
> your original didn't apply on my current tree.
> Anyway, does this work for you?

Works for me! I would put the definitions from defs.h to s390x.c.

One thing left: Please remove the following debug printf:

+.------.-------if (s390x_cpu_vec[i].prefix == prefix) {
+.------.-------.-------fprintf(fp, "GOT: %i
", i); <<<<<<<
+.------.-------.-------return &s390x_cpu_vec[i];
+.------.-------}

Michael



--
Crash-utility mailing list
Crash-utility@redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility
 
Old 02-12-2010, 07:02 PM
Dave Anderson
 
Default Add ELF core dump support for s390x

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




--
Crash-utility mailing list
Crash-utility@redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility
 

Thread Tools




All times are GMT. The time now is 09:29 AM.

VBulletin, Copyright ©2000 - 2014, Jelsoft Enterprises Ltd.
Content Relevant URLs by vBSEO ©2007, Crawlability, Inc.
Copyright 2007 - 2008, www.linux-archive.org