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

Re: [Crash-utility] [PATCH] 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()\n") ;
> 
> to:
> 
> +       fprintf(fp, "       elf_note_add: s390x_elf_note_add()\n") ;

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)\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
@@ -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\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, 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()\n");
 	fprintf(fp, "    init_kernel_pgd: NULL\n");
 	fprintf(fp, "    value_to_symbol: generic_machdep_value_to_symbol()\n");
+	fprintf(fp, "       elf_note_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 +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)\n");
 			return;
 		}
-		s390x_get_lowcore(cpu,lowcore);
+		s390x_get_lowcore(bt, lowcore);
 		psw_flags = ULONG(lowcore + OFFSET(s390_lowcore_psw_save_area));
 
 		if(psw_flags & 0x1000000000000ULL){
@@ -908,7 +1127,7 @@ 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 

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)\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
@@ -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\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, 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()\n");
 	fprintf(fp, "    init_kernel_pgd: NULL\n");
 	fprintf(fp, "    value_to_symbol: generic_machdep_value_to_symbol()\n");
+	fprintf(fp, "       elf_note_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 +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)\n");
 			return;
 		}
-		s390x_get_lowcore(cpu,lowcore);
+		s390x_get_lowcore(bt, lowcore);
 		psw_flags = ULONG(lowcore + OFFSET(s390_lowcore_psw_save_area));
 
 		if(psw_flags & 0x1000000000000ULL){
@@ -908,7 +1127,7 @@ 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 

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