Re: [PATCH] Add ELF core dump support for s390x

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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)\n");
                 break;
 	}
-
+	if (store && machdep->elf_note_add)
+		machdep->elf_note_add(nd->num_prstatus_notes, note);
 	uptr = (ulonglong *)(ptr + note->n_namesz);
 
         /*
@@ -2082,6 +2088,9 @@ get_netdump_regs(struct bt_info *bt, ulo
 		return get_netdump_regs_x86_64(bt, eip, esp);
 		break;
 
+	case EM_S390:
+		machdep->get_stack_frame(bt, eip, esp);
+		break;
 	default:
 		error(FATAL, 
 		   "support for ELF machine type %d not available\n",
--- a/s390x.c
+++ b/s390x.c
@@ -56,7 +56,6 @@ static ulong s390x_processor_speed(void)
 static int s390x_eframe_search(struct bt_info *);
 static void s390x_back_trace_cmd(struct bt_info *);
 static void s390x_dump_irq(int);
-static void s390x_get_stack_frame(struct bt_info *, ulong *, ulong *);
 static int s390x_dis_filter(ulong, char *);
 static void s390x_cmd_mach(void);
 static int s390x_get_smp_cpus(void);
@@ -64,7 +63,10 @@ static void s390x_display_machine_stats(
 static void s390x_dump_line_number(ulong);
 static struct line_number_hook s390x_line_number_hooks[];
 static int s390x_is_uvaddr(ulong, struct task_context *);
+static void s390x_get_stack_frame(struct bt_info *, ulong *, ulong *);
 
+static struct s390x_cpu *s390x_cpu_vec;
+static int s390x_cpu_cnt;
 
 /*
  * Initialize member offsets
@@ -79,6 +81,115 @@ static void s390x_offsets_init(void)
 				   "psw_save_area");
 }
 
+/*
+ * Return s390x CPU data for backtrace
+ */
+static struct s390x_cpu *s390x_cpu_get(struct bt_info *bt)
+{
+	unsigned int cpu = bt->tc->processor;
+	unsigned long lowcore_ptr, prefix;
+	uint32_t *nt_prefix;
+	unsigned int i;
+
+	lowcore_ptr = symbol_value("lowcore_ptr");
+	readmem(lowcore_ptr + cpu * sizeof(long), KVADDR,
+		&prefix, sizeof(long), "lowcore_ptr", FAULT_ON_ERROR);
+	for (i = 0; i < s390x_cpu_cnt; i++) {
+		if (s390x_cpu_vec[i].prefix == prefix) {
+			fprintf(fp, "GOT: %i\n", i);
+			return &s390x_cpu_vec[i];
+		}
+	}
+	error(FATAL, "cannot determine CPU for task: %lx\n", bt->task);
+}
+
+/*
+ * ELF core dump fuctions for storing CPU data
+ */
+static void s390x_elf_nt_prstatus_add(struct s390x_cpu *cpu,
+				      struct s390x_nt_prstatus *prstatus)
+{
+	memcpy(&cpu->psw, &prstatus->psw, sizeof(cpu->psw));
+	memcpy(&cpu->gprs, &prstatus->gprs, sizeof(cpu->gprs));
+	memcpy(&cpu->acrs, &prstatus->acrs, sizeof(cpu->acrs));
+}
+
+static void s390x_elf_nt_fpregset_add(struct s390x_cpu *cpu,
+				      struct s390x_nt_fpregset *fpregset)
+{
+	memcpy(&cpu->fpc, &fpregset->fpc, sizeof(cpu->fpc));
+	memcpy(&cpu->fprs, &fpregset->fprs, sizeof(cpu->fprs));
+}
+
+static void s390x_elf_nt_timer_add(struct s390x_cpu *cpu, void *desc)
+{
+	memcpy(&cpu->timer, desc, sizeof(cpu->timer));
+}
+
+static void s390x_elf_nt_todcmp_add(struct s390x_cpu *cpu, void *desc)
+{
+	memcpy(&cpu->todcmp, desc, sizeof(cpu->todcmp));
+}
+
+static void s390x_elf_nt_todpreg_add(struct s390x_cpu *cpu, void *desc)
+{
+	memcpy(&cpu->todpreg, desc, sizeof(cpu->todpreg));
+}
+
+static void s390x_elf_nt_ctrs_add(struct s390x_cpu *cpu, void *desc)
+{
+	memcpy(&cpu->ctrs, desc, sizeof(cpu->ctrs));
+}
+
+static void s390x_elf_nt_prefix_add(struct s390x_cpu *cpu, void *desc)
+{
+	memcpy(&cpu->prefix, desc, sizeof(cpu->prefix));
+}
+
+static void *get_elf_note_desc(Elf64_Nhdr *note)
+{
+	void *ptr = note;
+
+	return ptr + roundup(sizeof(*note) + note->n_namesz, 4);
+}
+
+static void s390x_elf_note_add(int elf_cpu_nr, Elf64_Nhdr *note)
+{
+	void *desc = get_elf_note_desc(note);
+	struct s390x_cpu *cpu;
+
+	if (elf_cpu_nr != s390x_cpu_cnt) {
+		s390x_cpu_cnt++;
+		s390x_cpu_vec = realloc(s390x_cpu_vec,
+					s390x_cpu_cnt * sizeof(*s390x_cpu_vec));
+		if (!s390x_cpu_vec)
+			error(FATAL, "cannot malloc cpu space.");
+	}
+	cpu = &s390x_cpu_vec[s390x_cpu_cnt - 1];
+	switch (note->n_type) {
+	case NT_PRSTATUS:
+		s390x_elf_nt_prstatus_add(cpu, desc);
+		break;
+	case NT_FPREGSET:
+		s390x_elf_nt_fpregset_add(cpu, desc);
+		break;
+	case NT_S390_TIMER:
+		s390x_elf_nt_timer_add(cpu, desc);
+		break;
+	case NT_S390_TODCMP:
+		s390x_elf_nt_todcmp_add(cpu, desc);
+		break;
+	case NT_S390_TODPREG:
+		s390x_elf_nt_todpreg_add(cpu, desc);
+		break;
+	case NT_S390_CTRS:
+		s390x_elf_nt_ctrs_add(cpu, desc);
+		break;
+	case NT_S390_PREFIX:
+		s390x_elf_nt_prefix_add(cpu, desc);
+		break;
+	}
+}
 
 /*
  *  Do all necessary machine-specific setup here.  This is called several
@@ -89,6 +200,9 @@ s390x_init(int when)
 {
 	switch (when)
 	{
+	case SETUP_ENV:
+		machdep->elf_note_add = s390x_elf_note_add;
+		break;
 	case PRE_SYMTAB:
 		machdep->verify_symbol = s390x_verify_symbol;
 		if (pc->flags & KERNEL_DEBUG_QUERY)
@@ -203,6 +317,7 @@ s390x_dump_machdep_table(ulong arg)
 	fprintf(fp, "       verify_paddr: generic_verify_paddr()\n");
 	fprintf(fp, "    init_kernel_pgd: NULL\n");
 	fprintf(fp, "    value_to_symbol: generic_machdep_value_to_symbol()\n");
+	fprintf(fp, "        elf_not_add: s390x_elf_note_add()\n");
 	fprintf(fp, "  line_number_hooks: s390x_line_number_hooks\n");
 	fprintf(fp, "      last_pgd_read: %lx\n", machdep->last_pgd_read);
 	fprintf(fp, "      last_pmd_read: %lx\n", machdep->last_pmd_read);
@@ -571,15 +686,37 @@ s390x_has_cpu(struct bt_info *bt)
  * read lowcore for cpu
  */
 static void
-s390x_get_lowcore(int cpu, char* lowcore)
+s390x_get_lowcore(struct bt_info *bt, char* lowcore)
 {
 	unsigned long lowcore_array,lowcore_ptr;
+	struct s390x_cpu *s390x_cpu;
+	int cpu = bt->tc->processor;
 
 	lowcore_array = symbol_value("lowcore_ptr");
 	readmem(lowcore_array + cpu * S390X_WORD_SIZE,KVADDR,
-		&lowcore_ptr, sizeof(long), "lowcore_ptr", FAULT_ON_ERROR);
-	readmem(lowcore_ptr, KVADDR, lowcore, LOWCORE_SIZE, "lowcore", 
+		&lowcore_ptr, sizeof(long), "lowcore_ptr",
 		FAULT_ON_ERROR);
+	readmem(lowcore_ptr, KVADDR, lowcore, LOWCORE_SIZE, "lowcore", FAULT_ON_ERROR);
+
+	if (!s390x_cpu_vec)
+		return;
+
+	/* Copy register information to defined places in lowcore */
+	s390x_cpu = s390x_cpu_get(bt);
+
+	memcpy(lowcore + 4864, &s390x_cpu->psw, sizeof(s390x_cpu->psw));
+	memcpy(lowcore + 4736, &s390x_cpu->gprs, sizeof(s390x_cpu->gprs));
+	memcpy(lowcore + 4928, &s390x_cpu->acrs, sizeof(s390x_cpu->acrs));
+
+	memcpy(lowcore + 4892, &s390x_cpu->fpc, sizeof(s390x_cpu->fpc));
+	memcpy(lowcore + 4608, &s390x_cpu->fprs, sizeof(s390x_cpu->fprs));
+
+	memcpy(lowcore + 4888, &s390x_cpu->prefix, sizeof(s390x_cpu->prefix));
+	memcpy(lowcore + 4992, &s390x_cpu->ctrs, sizeof(s390x_cpu->ctrs));
+
+	memcpy(lowcore + 4900, &s390x_cpu->todpreg, sizeof(s390x_cpu->todpreg));
+	memcpy(lowcore + 4904, &s390x_cpu->timer, sizeof(s390x_cpu->timer));
+	memcpy(lowcore + 4912, &s390x_cpu->todcmp, sizeof(s390x_cpu->todcmp));
 }
 
 /*
@@ -627,7 +764,7 @@ s390x_back_trace_cmd(struct bt_info *bt)
 			fprintf(fp,"(active)\n");
 			return;
 		}
-		s390x_get_lowcore(cpu,lowcore);
+		s390x_get_lowcore(bt, lowcore);
 		psw_flags = ULONG(lowcore + OFFSET(s390_lowcore_psw_save_area));
 
 		if(psw_flags & 0x1000000000000ULL){
@@ -908,7 +1045,7 @@ s390x_get_stack_frame(struct bt_info *bt
 	char lowcore[LOWCORE_SIZE];
 
 	if(s390x_has_cpu(bt))
-		s390x_get_lowcore(s390x_cpu_of_task(bt->task),lowcore);
+		s390x_get_lowcore(bt, lowcore);
 
 	/* get the stack pointer */
 	if(esp){
@@ -1139,5 +1276,4 @@ try_closest:
 		}
 	}
 }
-
 #endif 

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)\n");
                 break;
 	}
-
+	if (store && machdep->elf_note_add)
+		machdep->elf_note_add(nd->num_prstatus_notes, note);
 	uptr = (ulonglong *)(ptr + note->n_namesz);
 
         /*
@@ -2082,6 +2088,9 @@ get_netdump_regs(struct bt_info *bt, ulo
 		return get_netdump_regs_x86_64(bt, eip, esp);
 		break;
 
+	case EM_S390:
+		machdep->get_stack_frame(bt, eip, esp);
+		break;
 	default:
 		error(FATAL, 
 		   "support for ELF machine type %d not available\n",
--- a/s390x.c
+++ b/s390x.c
@@ -56,7 +56,6 @@ static ulong s390x_processor_speed(void)
 static int s390x_eframe_search(struct bt_info *);
 static void s390x_back_trace_cmd(struct bt_info *);
 static void s390x_dump_irq(int);
-static void s390x_get_stack_frame(struct bt_info *, ulong *, ulong *);
 static int s390x_dis_filter(ulong, char *);
 static void s390x_cmd_mach(void);
 static int s390x_get_smp_cpus(void);
@@ -64,7 +63,10 @@ static void s390x_display_machine_stats(
 static void s390x_dump_line_number(ulong);
 static struct line_number_hook s390x_line_number_hooks[];
 static int s390x_is_uvaddr(ulong, struct task_context *);
+static void s390x_get_stack_frame(struct bt_info *, ulong *, ulong *);
 
+static struct s390x_cpu *s390x_cpu_vec;
+static int s390x_cpu_cnt;
 
 /*
  * Initialize member offsets
@@ -79,6 +81,115 @@ static void s390x_offsets_init(void)
 				   "psw_save_area");
 }
 
+/*
+ * Return s390x CPU data for backtrace
+ */
+static struct s390x_cpu *s390x_cpu_get(struct bt_info *bt)
+{
+	unsigned int cpu = bt->tc->processor;
+	unsigned long lowcore_ptr, prefix;
+	uint32_t *nt_prefix;
+	unsigned int i;
+
+	lowcore_ptr = symbol_value("lowcore_ptr");
+	readmem(lowcore_ptr + cpu * sizeof(long), KVADDR,
+		&prefix, sizeof(long), "lowcore_ptr", FAULT_ON_ERROR);
+	for (i = 0; i < s390x_cpu_cnt; i++) {
+		if (s390x_cpu_vec[i].prefix == prefix) {
+			fprintf(fp, "GOT: %i\n", i);
+			return &s390x_cpu_vec[i];
+		}
+	}
+	error(FATAL, "cannot determine CPU for task: %lx\n", bt->task);
+}
+
+/*
+ * ELF core dump fuctions for storing CPU data
+ */
+static void s390x_elf_nt_prstatus_add(struct s390x_cpu *cpu,
+				      struct s390x_nt_prstatus *prstatus)
+{
+	memcpy(&cpu->psw, &prstatus->psw, sizeof(cpu->psw));
+	memcpy(&cpu->gprs, &prstatus->gprs, sizeof(cpu->gprs));
+	memcpy(&cpu->acrs, &prstatus->acrs, sizeof(cpu->acrs));
+}
+
+static void s390x_elf_nt_fpregset_add(struct s390x_cpu *cpu,
+				      struct s390x_nt_fpregset *fpregset)
+{
+	memcpy(&cpu->fpc, &fpregset->fpc, sizeof(cpu->fpc));
+	memcpy(&cpu->fprs, &fpregset->fprs, sizeof(cpu->fprs));
+}
+
+static void s390x_elf_nt_timer_add(struct s390x_cpu *cpu, void *desc)
+{
+	memcpy(&cpu->timer, desc, sizeof(cpu->timer));
+}
+
+static void s390x_elf_nt_todcmp_add(struct s390x_cpu *cpu, void *desc)
+{
+	memcpy(&cpu->todcmp, desc, sizeof(cpu->todcmp));
+}
+
+static void s390x_elf_nt_todpreg_add(struct s390x_cpu *cpu, void *desc)
+{
+	memcpy(&cpu->todpreg, desc, sizeof(cpu->todpreg));
+}
+
+static void s390x_elf_nt_ctrs_add(struct s390x_cpu *cpu, void *desc)
+{
+	memcpy(&cpu->ctrs, desc, sizeof(cpu->ctrs));
+}
+
+static void s390x_elf_nt_prefix_add(struct s390x_cpu *cpu, void *desc)
+{
+	memcpy(&cpu->prefix, desc, sizeof(cpu->prefix));
+}
+
+static void *get_elf_note_desc(Elf64_Nhdr *note)
+{
+	void *ptr = note;
+
+	return ptr + roundup(sizeof(*note) + note->n_namesz, 4);
+}
+
+static void s390x_elf_note_add(int elf_cpu_nr, Elf64_Nhdr *note)
+{
+	void *desc = get_elf_note_desc(note);
+	struct s390x_cpu *cpu;
+
+	if (elf_cpu_nr != s390x_cpu_cnt) {
+		s390x_cpu_cnt++;
+		s390x_cpu_vec = realloc(s390x_cpu_vec,
+					s390x_cpu_cnt * sizeof(*s390x_cpu_vec));
+		if (!s390x_cpu_vec)
+			error(FATAL, "cannot malloc cpu space.");
+	}
+	cpu = &s390x_cpu_vec[s390x_cpu_cnt - 1];
+	switch (note->n_type) {
+	case NT_PRSTATUS:
+		s390x_elf_nt_prstatus_add(cpu, desc);
+		break;
+	case NT_FPREGSET:
+		s390x_elf_nt_fpregset_add(cpu, desc);
+		break;
+	case NT_S390_TIMER:
+		s390x_elf_nt_timer_add(cpu, desc);
+		break;
+	case NT_S390_TODCMP:
+		s390x_elf_nt_todcmp_add(cpu, desc);
+		break;
+	case NT_S390_TODPREG:
+		s390x_elf_nt_todpreg_add(cpu, desc);
+		break;
+	case NT_S390_CTRS:
+		s390x_elf_nt_ctrs_add(cpu, desc);
+		break;
+	case NT_S390_PREFIX:
+		s390x_elf_nt_prefix_add(cpu, desc);
+		break;
+	}
+}
 
 /*
  *  Do all necessary machine-specific setup here.  This is called several
@@ -89,6 +200,9 @@ s390x_init(int when)
 {
 	switch (when)
 	{
+	case SETUP_ENV:
+		machdep->elf_note_add = s390x_elf_note_add;
+		break;
 	case PRE_SYMTAB:
 		machdep->verify_symbol = s390x_verify_symbol;
 		if (pc->flags & KERNEL_DEBUG_QUERY)
@@ -203,6 +317,7 @@ s390x_dump_machdep_table(ulong arg)
 	fprintf(fp, "       verify_paddr: generic_verify_paddr()\n");
 	fprintf(fp, "    init_kernel_pgd: NULL\n");
 	fprintf(fp, "    value_to_symbol: generic_machdep_value_to_symbol()\n");
+	fprintf(fp, "        elf_not_add: s390x_elf_note_add()\n");
 	fprintf(fp, "  line_number_hooks: s390x_line_number_hooks\n");
 	fprintf(fp, "      last_pgd_read: %lx\n", machdep->last_pgd_read);
 	fprintf(fp, "      last_pmd_read: %lx\n", machdep->last_pmd_read);
@@ -571,15 +686,37 @@ s390x_has_cpu(struct bt_info *bt)
  * read lowcore for cpu
  */
 static void
-s390x_get_lowcore(int cpu, char* lowcore)
+s390x_get_lowcore(struct bt_info *bt, char* lowcore)
 {
 	unsigned long lowcore_array,lowcore_ptr;
+	struct s390x_cpu *s390x_cpu;
+	int cpu = bt->tc->processor;
 
 	lowcore_array = symbol_value("lowcore_ptr");
 	readmem(lowcore_array + cpu * S390X_WORD_SIZE,KVADDR,
-		&lowcore_ptr, sizeof(long), "lowcore_ptr", FAULT_ON_ERROR);
-	readmem(lowcore_ptr, KVADDR, lowcore, LOWCORE_SIZE, "lowcore", 
+		&lowcore_ptr, sizeof(long), "lowcore_ptr",
 		FAULT_ON_ERROR);
+	readmem(lowcore_ptr, KVADDR, lowcore, LOWCORE_SIZE, "lowcore", FAULT_ON_ERROR);
+
+	if (!s390x_cpu_vec)
+		return;
+
+	/* Copy register information to defined places in lowcore */
+	s390x_cpu = s390x_cpu_get(bt);
+
+	memcpy(lowcore + 4864, &s390x_cpu->psw, sizeof(s390x_cpu->psw));
+	memcpy(lowcore + 4736, &s390x_cpu->gprs, sizeof(s390x_cpu->gprs));
+	memcpy(lowcore + 4928, &s390x_cpu->acrs, sizeof(s390x_cpu->acrs));
+
+	memcpy(lowcore + 4892, &s390x_cpu->fpc, sizeof(s390x_cpu->fpc));
+	memcpy(lowcore + 4608, &s390x_cpu->fprs, sizeof(s390x_cpu->fprs));
+
+	memcpy(lowcore + 4888, &s390x_cpu->prefix, sizeof(s390x_cpu->prefix));
+	memcpy(lowcore + 4992, &s390x_cpu->ctrs, sizeof(s390x_cpu->ctrs));
+
+	memcpy(lowcore + 4900, &s390x_cpu->todpreg, sizeof(s390x_cpu->todpreg));
+	memcpy(lowcore + 4904, &s390x_cpu->timer, sizeof(s390x_cpu->timer));
+	memcpy(lowcore + 4912, &s390x_cpu->todcmp, sizeof(s390x_cpu->todcmp));
 }
 
 /*
@@ -627,7 +764,7 @@ s390x_back_trace_cmd(struct bt_info *bt)
 			fprintf(fp,"(active)\n");
 			return;
 		}
-		s390x_get_lowcore(cpu,lowcore);
+		s390x_get_lowcore(bt, lowcore);
 		psw_flags = ULONG(lowcore + OFFSET(s390_lowcore_psw_save_area));
 
 		if(psw_flags & 0x1000000000000ULL){
@@ -908,7 +1045,7 @@ s390x_get_stack_frame(struct bt_info *bt
 	char lowcore[LOWCORE_SIZE];
 
 	if(s390x_has_cpu(bt))
-		s390x_get_lowcore(s390x_cpu_of_task(bt->task),lowcore);
+		s390x_get_lowcore(bt, lowcore);
 
 	/* get the stack pointer */
 	if(esp){
@@ -1139,5 +1276,4 @@ try_closest:
 		}
 	}
 }
-
 #endif 
--
Crash-utility mailing list
Crash-utility@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/crash-utility

[Index of Archives]     [Fedora Development]     [Fedora Desktop]     [Fedora SELinux]     [Yosemite News]     [KDE Users]     [Fedora Tools]

 

Powered by Linux