[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



----- "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
Index: defs.h
===================================================================
RCS file: /nfs/projects/cvs/crash/defs.h,v
retrieving revision 1.410
diff -u -r1.410 defs.h
--- defs.h	4 Feb 2010 21:04:36 -0000	1.410
+++ defs.h	12 Feb 2010 15:31:27 -0000
@@ -792,6 +792,7 @@
 	void (*clear_machdep_cache)(void);
 	int (*xen_kdump_p2m_create)(struct xen_kdump_data *);
 	int (*in_alternate_stack)(int, ulong);
+	void (*elf_note_add)(int, void *);
 };
 
 /*
@@ -2728,6 +2729,8 @@
 #endif  /* S390 */
 
 #ifdef S390X
+#include "elf.h"
+
 #define _64BIT_
 #define MACHINE_TYPE       "S390X"
 
@@ -2750,6 +2753,86 @@
 #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
Index: netdump.c
===================================================================
RCS file: /nfs/projects/cvs/crash/netdump.c,v
retrieving revision 1.95
diff -u -r1.95 netdump.c
--- netdump.c	3 Dec 2009 15:36:42 -0000	1.95
+++ netdump.c	12 Feb 2010 15:32:07 -0000
@@ -213,6 +213,11 @@
 				goto bailout;
 			break;
 
+		case EM_S390:
+			if (machine_type_mismatch(file, "S390X", NULL,
+			    source_query))
+				goto bailout;
+			break;
 		case EM_386:
 			if (machine_type_mismatch(file, "X86", NULL,
 			    source_query))
@@ -1990,6 +1995,9 @@
                 break;
 	}
 
+	if (store && machine_type("S390X") && machdep->elf_note_add)
+		machdep->elf_note_add(nd->num_prstatus_notes, (void *)note);
+
 	uptr = (ulonglong *)(ptr + note->n_namesz);
 
         /*
@@ -2082,6 +2090,9 @@
 		return get_netdump_regs_x86_64(bt, eip, esp);
 		break;
 
+	case EM_S390:
+		machdep->get_stack_frame(bt, eip, esp);
+		break;
 	default:
 		error(FATAL, 
 		   "support for ELF machine type %d not available\n",
Index: s390x.c
===================================================================
RCS file: /nfs/projects/cvs/crash/s390x.c,v
retrieving revision 1.41
diff -u -r1.41 s390x.c
--- s390x.c	10 Feb 2010 20:07:38 -0000	1.41
+++ s390x.c	12 Feb 2010 15:30:58 -0000
@@ -56,7 +56,6 @@
 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_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,116 @@
 				   "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;
+	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);
+	return NULL;
+}
+
+/*
+ * ELF core dump fuctions for storing CPU data
+ */
+static void s390x_elf_nt_prstatus_add(struct s390x_cpu *cpu,
+				      struct s390x_nt_prstatus *prstatus)
+{
+	memcpy(&cpu->psw, &prstatus->psw, sizeof(cpu->psw));
+	memcpy(&cpu->gprs, &prstatus->gprs, sizeof(cpu->gprs));
+	memcpy(&cpu->acrs, &prstatus->acrs, sizeof(cpu->acrs));
+}
+
+static void s390x_elf_nt_fpregset_add(struct s390x_cpu *cpu,
+				      struct s390x_nt_fpregset *fpregset)
+{
+	memcpy(&cpu->fpc, &fpregset->fpc, sizeof(cpu->fpc));
+	memcpy(&cpu->fprs, &fpregset->fprs, sizeof(cpu->fprs));
+}
+
+static void s390x_elf_nt_timer_add(struct s390x_cpu *cpu, void *desc)
+{
+	memcpy(&cpu->timer, desc, sizeof(cpu->timer));
+}
+
+static void s390x_elf_nt_todcmp_add(struct s390x_cpu *cpu, void *desc)
+{
+	memcpy(&cpu->todcmp, desc, sizeof(cpu->todcmp));
+}
+
+static void s390x_elf_nt_todpreg_add(struct s390x_cpu *cpu, void *desc)
+{
+	memcpy(&cpu->todpreg, desc, sizeof(cpu->todpreg));
+}
+
+static void s390x_elf_nt_ctrs_add(struct s390x_cpu *cpu, void *desc)
+{
+	memcpy(&cpu->ctrs, desc, sizeof(cpu->ctrs));
+}
+
+static void s390x_elf_nt_prefix_add(struct s390x_cpu *cpu, void *desc)
+{
+	memcpy(&cpu->prefix, desc, sizeof(cpu->prefix));
+}
+
+static void *get_elf_note_desc(Elf64_Nhdr *note)
+{
+	void *ptr = note;
+
+	return ptr + roundup(sizeof(*note) + note->n_namesz, 4);
+}
+
+static void s390x_elf_note_add(int elf_cpu_nr, void *noteptr)
+{
+	Elf64_Nhdr *note = (Elf64_Nhdr *)noteptr;
+	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 +201,9 @@
 {
 	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 +318,7 @@
 	fprintf(fp, "       verify_paddr: generic_verify_paddr()\n");
 	fprintf(fp, "    init_kernel_pgd: NULL\n");
 	fprintf(fp, "    value_to_symbol: generic_machdep_value_to_symbol()\n");
+	fprintf(fp, "       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);
@@ -526,6 +642,7 @@
 		    "Option '-e' is not implemented for this architecture\n"));
 }
 
+#ifdef NOT_USED
 /*
  * returns cpu number of task
  */ 
@@ -552,6 +669,7 @@
 	}
 	return cpu;
 }
+#endif
 
 /*
  * returns true, if task of bt currently is executed by a cpu
@@ -571,15 +689,37 @@
  * read lowcore for cpu
  */
 static void
-s390x_get_lowcore(int cpu, char* lowcore)
+s390x_get_lowcore(struct bt_info *bt, char* lowcore)
 {
 	unsigned long lowcore_array,lowcore_ptr;
+	struct s390x_cpu *s390x_cpu;
+	int cpu = bt->tc->processor;
 
 	lowcore_array = symbol_value("lowcore_ptr");
 	readmem(lowcore_array + cpu * S390X_WORD_SIZE,KVADDR,
-		&lowcore_ptr, sizeof(long), "lowcore_ptr", FAULT_ON_ERROR);
-	readmem(lowcore_ptr, KVADDR, lowcore, LOWCORE_SIZE, "lowcore", 
+		&lowcore_ptr, sizeof(long), "lowcore_ptr",
 		FAULT_ON_ERROR);
+	readmem(lowcore_ptr, KVADDR, lowcore, LOWCORE_SIZE, "lowcore", FAULT_ON_ERROR);
+
+	if (!s390x_cpu_vec)
+		return;
+
+	/* Copy register information to defined places in lowcore */
+	s390x_cpu = s390x_cpu_get(bt);
+
+	memcpy(lowcore + 4864, &s390x_cpu->psw, sizeof(s390x_cpu->psw));
+	memcpy(lowcore + 4736, &s390x_cpu->gprs, sizeof(s390x_cpu->gprs));
+	memcpy(lowcore + 4928, &s390x_cpu->acrs, sizeof(s390x_cpu->acrs));
+
+	memcpy(lowcore + 4892, &s390x_cpu->fpc, sizeof(s390x_cpu->fpc));
+	memcpy(lowcore + 4608, &s390x_cpu->fprs, sizeof(s390x_cpu->fprs));
+
+	memcpy(lowcore + 4888, &s390x_cpu->prefix, sizeof(s390x_cpu->prefix));
+	memcpy(lowcore + 4992, &s390x_cpu->ctrs, sizeof(s390x_cpu->ctrs));
+
+	memcpy(lowcore + 4900, &s390x_cpu->todpreg, sizeof(s390x_cpu->todpreg));
+	memcpy(lowcore + 4904, &s390x_cpu->timer, sizeof(s390x_cpu->timer));
+	memcpy(lowcore + 4912, &s390x_cpu->todcmp, sizeof(s390x_cpu->todcmp));
 }
 
 /*
@@ -621,13 +761,12 @@
 	if(s390x_has_cpu(bt)){
 		char lowcore[LOWCORE_SIZE];
 		unsigned long psw_flags;
-		int cpu = s390x_cpu_of_task(bt->task);
 
 		if (ACTIVE()) {
 			fprintf(fp,"(active)\n");
 			return;
 		}
-		s390x_get_lowcore(cpu,lowcore);
+		s390x_get_lowcore(bt, lowcore);
 		psw_flags = ULONG(lowcore + OFFSET(s390_lowcore_psw_save_area));
 
 		if(psw_flags & 0x1000000000000ULL){
@@ -908,7 +1047,7 @@
 	char lowcore[LOWCORE_SIZE];
 
 	if(s390x_has_cpu(bt))
-		s390x_get_lowcore(s390x_cpu_of_task(bt->task),lowcore);
+		s390x_get_lowcore(bt, lowcore);
 
 	/* get the stack pointer */
 	if(esp){
@@ -1139,5 +1278,4 @@
 		}
 	}
 }
-
 #endif 

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