Re: Increase of NR_CPUS on IA64

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

 



Bernhard Walle wrote:
* Bernhard Walle <bwalle@xxxxxxx> [2007-10-19 17:24]:

The solution for that problem is to calculate the number of CPUs for
IA64 at runtime. The 2nd patch implements this, and also reads the
registers from the LKCD dump header instead of guessing on the stack.
This fixes a problem here -- unfortunately, I don't still have that
dump to provide further details.


I forget to attach the 2nd patch ;)


Thanks,
   Bernhard



At this point I've lost most insights into the LKCD code.
The ia64 pt_regs hardwiring bothers me, mainly because there have
been changes to its definition over the years.  (There's a couple
different versions hardwired in unwind.h for example).
So my biggest worry would be if this somehow breaks
backwards-compatibility, but I'm presuming that you took
that into account.  But anyway, I leave this all up
to Troy.

A couple nits...

Please build with "make warn" before submitting any patch
and clean up the complaints.

Also I'd prefer to not tinker with the netdump.c file.
There is no /usr/include/stddef.h in the RHEL and FC8
environments, and the /usr/include/linux/stddef.h has
removed offsetof() in FC8 for some reason?  In any case,
I'd prefer leaving it alone.

Because of the builtin array sizes that I long ago
painted crash into a corner with, I'd also prefer keeping
NR_CPUS to its minimum.  I have no problem updating it if
necessary later, so 4096 is preferable to overkilling
it with 16384 at this time.  I don't see how that could
be a problem?  If it is, you can always release the SUSE
version with the larger value -- I'm sure that you're
almost never in sync with the upstream version anyway,
right?  (I can't even do that with RHEL errata...)

Thanks,
  Dave







------------------------------------------------------------------------

---
Makefile | 4 defs.h | 9 + kernel.c | 5 lkcd_dump_v8.h | 300 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 lkcd_fix_mem.c |   22 ----
 lkcd_fix_mem.h |  295 --------------------------------------------------------
 lkcd_v8.c      |  186 ++++++++++++++++++++++++++++++++++-
netdump.c | 1 8 files changed, 502 insertions(+), 320 deletions(-)

--- a/Makefile
+++ b/Makefile
@@ -66,7 +66,7 @@ GENERIC_HFILES=defs.h xen_hyper_defs.h
 MCORE_HFILES=va_server.h vas_crash.h
 REDHAT_HFILES=netdump.h diskdump.h xendump.h
 LKCD_DUMP_HFILES=lkcd_vmdump_v1.h lkcd_vmdump_v2_v3.h lkcd_dump_v5.h \
-        lkcd_dump_v7.h lkcd_dump_v8.h lkcd_fix_mem.h
+        lkcd_dump_v7.h lkcd_dump_v8.h
 LKCD_TRACE_HFILES=lkcd_x86_trace.h
 IBM_HFILES=ibm_common.h
 UNWIND_HFILES=unwind.h unwind_i.h rse.h unwind_x86.h unwind_x86_64.h
@@ -406,7 +406,7 @@ unwind_v3.o: ${GENERIC_HFILES} ${UNWIND_
 	cc -c ${CFLAGS} -DREDHAT -DUNWIND_V3 unwind.c -o unwind_v3.o ${WARNING_OPTIONS} ${WARNING_ERROR}
lkcd_fix_mem.o: ${GENERIC_HFILES} ${LKCD_HFILES} lkcd_fix_mem.c
-	cc -c ${CFLAGS} lkcd_fix_mem.c ${WARNING_OPTIONS} ${WARNING_ERROR}
+	cc -c ${CFLAGS} -DMCLX lkcd_fix_mem.c ${WARNING_OPTIONS} ${WARNING_ERROR}
xen_hyper.o: ${GENERIC_HFILES} xen_hyper.c
 	cc -c ${CFLAGS} xen_hyper.c ${WARNING_OPTIONS} ${WARNING_ERROR}
--- a/defs.h
+++ b/defs.h
@@ -19,6 +19,7 @@
 #ifndef GDB_COMMON
#include <stdio.h>
+#include <stddef.h>
 #include <stdarg.h>
 #include <stdint.h>
 #include <termios.h>
@@ -54,6 +55,7 @@
#define TRUE (1)
 #define FALSE (0)
+#define STR(x)	#x
#ifdef X86
 #define NR_CPUS  (256)
@@ -3826,10 +3828,15 @@ void ppc_dump_machdep_table(ulong);
  */
ulong get_lkcd_switch_stack(ulong);
-int fix_addr_v8(int);
+int fix_addr_v8();
 int fix_addr_v7(int);
/*
+ * lkcd_v8.c
+ */
+int get_lkcd_regs_for_cpu(struct bt_info *bt, ulong *eip, ulong *esp);
+
+/*
  *  ia64.c
  */
 #ifdef IA64
--- a/kernel.c
+++ b/kernel.c
@@ -2102,6 +2102,11 @@ get_lkcd_regs(struct bt_info *bt, ulong return;
 	}
+ /* try to get it from the header */
+	if (get_lkcd_regs_for_cpu(bt, eip, esp) == 0)
+		return;
+
+	/* if that fails: do guessing */
 	sysrq_eip = sysrq_esp = 0;
for (i = 0, up = (ulong *)bt->stackbuf; i < LONGS_PER_STACK; i++, up++){
--- a/lkcd_dump_v8.h
+++ b/lkcd_dump_v8.h
@@ -235,4 +235,304 @@ typedef struct lkcdinfo_s {
 	int             stack_offset;
 } lkcdinfo_t;
+/*
+ *
+ * machine specific dump headers
+ *
+ */
+
+/*
+ * IA64 ---------------------------------------------------------
+ */
+
+#if defined(IA64)
+
+#define DUMP_ASM_MAGIC_NUMBER     0xdeaddeadULL  /* magic number */
+#define DUMP_ASM_VERSION_NUMBER   0x5            /* version number          */
+
+
+struct pt_regs {
+	/* The following registers are saved by SAVE_MIN: */
+	unsigned long b6;		/* scratch */
+	unsigned long b7;		/* scratch */
+
+	unsigned long ar_csd;           /* used by cmp8xchg16 (scratch) */
+	unsigned long ar_ssd;           /* reserved for future use (scratch) */
+
+	unsigned long r8;		/* scratch (return value register 0) */
+	unsigned long r9;		/* scratch (return value register 1) */
+	unsigned long r10;		/* scratch (return value register 2) */
+	unsigned long r11;		/* scratch (return value register 3) */
+
+	unsigned long cr_ipsr;		/* interrupted task's psr */
+	unsigned long cr_iip;		/* interrupted task's instruction pointer */
+	unsigned long cr_ifs;		/* interrupted task's function state */
+
+	unsigned long ar_unat;		/* interrupted task's NaT register (preserved) */
+	unsigned long ar_pfs;		/* prev function state  */
+	unsigned long ar_rsc;		/* RSE configuration */
+	/* The following two are valid only if cr_ipsr.cpl > 0: */
+	unsigned long ar_rnat;		/* RSE NaT */
+	unsigned long ar_bspstore;	/* RSE bspstore */
+
+	unsigned long pr;		/* 64 predicate registers (1 bit each) */
+	unsigned long b0;		/* return pointer (bp) */
+	unsigned long loadrs;		/* size of dirty partition << 16 */
+
+	unsigned long r1;		/* the gp pointer */
+	unsigned long r12;		/* interrupted task's memory stack pointer */
+	unsigned long r13;		/* thread pointer */
+
+	unsigned long ar_fpsr;		/* floating point status (preserved) */
+	unsigned long r15;		/* scratch */
+
+	/* The remaining registers are NOT saved for system calls.  */
+
+	unsigned long r14;		/* scratch */
+	unsigned long r2;		/* scratch */
+	unsigned long r3;		/* scratch */
+
+	/* The following registers are saved by SAVE_REST: */
+	unsigned long r16;		/* scratch */
+	unsigned long r17;		/* scratch */
+	unsigned long r18;		/* scratch */
+	unsigned long r19;		/* scratch */
+	unsigned long r20;		/* scratch */
+	unsigned long r21;		/* scratch */
+	unsigned long r22;		/* scratch */
+	unsigned long r23;		/* scratch */
+	unsigned long r24;		/* scratch */
+	unsigned long r25;		/* scratch */
+	unsigned long r26;		/* scratch */
+	unsigned long r27;		/* scratch */
+	unsigned long r28;		/* scratch */
+	unsigned long r29;		/* scratch */
+	unsigned long r30;		/* scratch */
+	unsigned long r31;		/* scratch */
+
+	unsigned long ar_ccv;		/* compare/exchange value (scratch) */
+
+	/*
+	 * Floating point registers that the kernel considers scratch:
+	 */
+	struct ia64_fpreg f6;		/* scratch */
+	struct ia64_fpreg f7;		/* scratch */
+	struct ia64_fpreg f8;		/* scratch */
+	struct ia64_fpreg f9;		/* scratch */
+	struct ia64_fpreg f10;		/* scratch */
+	struct ia64_fpreg f11;		/* scratch */
+};
+
+
+
+/*
+ * Structure: dump_header_asm_t
+ *  Function: This is the header for architecture-specific stuff.  It
+ *            follows right after the dump header.
+ *
+ */
+typedef struct __dump_header_asm_ia64 {
+
+        /* the dump magic number -- unique to verify dump is valid */
+        uint64_t             dha_magic_number;
+
+        /* the version number of this dump */
+        uint32_t             dha_version;
+
+        /* the size of this header (in case we can't read it) */
+        uint32_t             dha_header_size;
+
+        /* pointer to pt_regs, (OLD: (struct pt_regs *, NEW: (uint64_t)) */
+	uint64_t             dha_pt_regs;
+
+	/* the dump registers */
+	struct pt_regs       dha_regs;
+
+        /* the rnat register saved after flushrs */
+        uint64_t             dha_rnat;
+
+	/* the pfs register saved after flushrs */
+	uint64_t             dha_pfs;
+
+	/* the bspstore register saved after flushrs */
+	uint64_t             dha_bspstore;
+
+	/* smp specific */
+	uint32_t	     dha_smp_num_cpus;
+	uint32_t	     dha_dumping_cpu;
+	struct pt_regs	     dha_smp_regs[NR_CPUS];
+	uint64_t	     dha_smp_current_task[NR_CPUS];
+	uint64_t	     dha_stack[NR_CPUS];
+	uint64_t	     dha_stack_ptr[NR_CPUS];
+
+	/* load address of kernel */
+        uint64_t             dha_kernel_addr;
+
+} __attribute__((packed)) dump_header_asm_ia64_t;
+
+struct dump_CPU_info_ia64 {
+	struct pt_regs	     dha_smp_regs;
+	uint64_t	     dha_smp_current_task;
+	uint64_t	     dha_stack;
+	uint64_t	     dha_stack_ptr;
+} __attribute__((packed)) dump_CPU_info_ia64_t;
+
+typedef struct dump_CPU_info_ia64 dump_CPU_info_t;
+typedef struct __dump_header_asm_ia64 dump_header_asm_t;
+
+#elif defined(X86)
+
+#define DUMP_ASM_MAGIC_NUMBER	0xdeaddeadULL	/* magic number            */
+#define DUMP_ASM_VERSION_NUMBER	0x5	/* version number          */
+
+
+struct pt_regs {
+	long ebx;
+	long ecx;
+	long edx;
+	long esi;
+	long edi;
+	long ebp;
+	long eax;
+	int  xds;
+	int  xes;
+	long orig_eax;
+	long eip;
+	int  xcs;
+	long eflags;
+	long esp;
+	int  xss;
+};
+
+/*
+ * Structure: __dump_header_asm
+ *  Function: This is the header for architecture-specific stuff.  It
+ *            follows right after the dump header.
+ */
+typedef struct __dump_header_asm_i386 {
+	/* the dump magic number -- unique to verify dump is valid */
+	uint64_t	dha_magic_number;
+
+	/* the version number of this dump */
+	uint32_t	dha_version;
+
+	/* the size of this header (in case we can't read it) */
+	uint32_t	dha_header_size;
+
+	/* the esp for i386 systems */
+	uint32_t	dha_esp;
+
+	/* the eip for i386 systems */
+	uint32_t	dha_eip;
+
+	/* the dump registers */
+	struct pt_regs	dha_regs;
+
+	/* smp specific */
+	uint32_t	dha_smp_num_cpus;
+	uint32_t	dha_dumping_cpu;
+	struct pt_regs	dha_smp_regs[NR_CPUS];
+	uint32_t	dha_smp_current_task[NR_CPUS];
+	uint32_t	dha_stack[NR_CPUS];
+	uint32_t	dha_stack_ptr[NR_CPUS];
+} __attribute__((packed)) dump_header_asm_i386_t;
+
+/*
+ * CPU specific part of dump_header_asm_t
+ */
+typedef struct dump_CPU_info_i386 {
+	struct pt_regs	dha_smp_regs;
+	uint64_t	dha_smp_current_task;
+	uint64_t	dha_stack;
+	uint64_t	dha_stack_ptr;
+} __attribute__ ((packed)) dump_CPU_info_i386_t;
+
+
+typedef struct __dump_header_asm_i386 dump_header_asm_t;
+typedef struct dump_CPU_info_i386 dump_CPU_info_t;
+
+#elif defined(X86_64)
+
+/* definitions */
+#define DUMP_ASM_MAGIC_NUMBER     0xdeaddeadULL  /* magic number            */
+#define DUMP_ASM_VERSION_NUMBER   0x2            /* version number          */
+
+
+struct pt_regs {
+	unsigned long r15;
+	unsigned long r14;
+	unsigned long r13;
+	unsigned long r12;
+	unsigned long rbp;
+	unsigned long rbx;
+/* arguments: non interrupts/non tracing syscalls only save upto here*/
+ 	unsigned long r11;
+	unsigned long r10;
+	unsigned long r9;
+	unsigned long r8;
+	unsigned long rax;
+	unsigned long rcx;
+	unsigned long rdx;
+	unsigned long rsi;
+	unsigned long rdi;
+	unsigned long orig_rax;
+/* end of arguments */
+/* cpu exception frame or undefined */
+	unsigned long rip;
+	unsigned long cs;
+	unsigned long eflags;
+	unsigned long rsp;
+	unsigned long ss;
+/* top of stack page */
+};
+
+/*
+ * Structure: dump_header_asm_t
+ *  Function: This is the header for architecture-specific stuff.  It
+ *            follows right after the dump header.
+ */
+typedef struct __dump_header_asm_x86_64 {
+
+        /* the dump magic number -- unique to verify dump is valid */
+        uint64_t             dha_magic_number;
+
+        /* the version number of this dump */
+        uint32_t             dha_version;
+
+        /* the size of this header (in case we can't read it) */
+        uint32_t             dha_header_size;
+
+	/* the dump registers */
+	struct pt_regs       dha_regs;
+
+	/* smp specific */
+	uint32_t	     dha_smp_num_cpus;
+	int		     dha_dumping_cpu;
+	struct pt_regs	     dha_smp_regs[NR_CPUS];
+	uint64_t	     dha_smp_current_task[NR_CPUS];
+	uint64_t	     dha_stack[NR_CPUS];
+	uint64_t	     dha_stack_ptr[NR_CPUS];
+} __attribute__((packed)) dump_header_asm_t_x86_64;
+
+
+/*
+ * CPU specific part of dump_header_asm_t
+ */
+typedef struct dump_CPU_info_x86_64 {
+	struct pt_regs	     dha_smp_regs;
+	uint64_t	     dha_smp_current_task;
+	uint64_t	     dha_stack;
+	uint64_t	     dha_stack_ptr;
+} __attribute__ ((packed)) dump_CPU_info_x86_64_t;
+
+typedef struct dump_CPU_info_x86_64 dump_CPU_info_t;
+typedef struct __dump_header_asm_x86_64 dump_header_asm_t;
+
+
+#else
+
+#define HAVE_NO_DUMP_HEADER_ASM 1
+
+#endif
+
 #endif /* _DUMP_H */
--- a/lkcd_fix_mem.c
+++ b/lkcd_fix_mem.c
@@ -20,21 +20,13 @@
#define LKCD_COMMON
 #include "defs.h"
-#include "lkcd_fix_mem.h"
+#include "lkcd_dump_v8.h"
static int fix_addr(dump_header_asm_t *); int
-fix_addr_v8(int fd)
+fix_addr_v8(dump_header_asm_t *dha)
 {
-    static dump_header_asm_t dump_header_asm_v8 = { 0 };
-    dump_header_asm_t *dha;
-    dha = &dump_header_asm_v8;
- - if (read(lkcd->fd, dha, sizeof(dump_header_asm_t)) !=
-	    sizeof(dump_header_asm_t))
-	return -1;
- fix_addr(dha); return 0;
@@ -59,14 +51,6 @@ fix_addr_v7(int fd)
 static int
fix_addr(dump_header_asm_t *dha) { - -
-    if (dha->dha_header_size != sizeof(dump_header_asm_t)) {
-	error(INFO, "LKCD machine specific dump header doesn't match crash version\n");
-	error(INFO, "traceback of currently executing threads may not work\n\n");
-    }
- -
     lkcd->dump_header_asm = dha;
@@ -83,7 +67,7 @@ fix_addr(dump_header_asm_t *dha) if (dha->dha_stack[i] && dha->dha_smp_current_task[i]) {
 		    lkcd->fix_addr[i].task = (ulong)dha->dha_smp_current_task[i];
lkcd->fix_addr[i].saddr = (ulong)dha->dha_stack[i]; - lkcd->fix_addr[i].sw = (ulong)dha->dha_switch_stack[i];
+		    lkcd->fix_addr[i].sw = (ulong)dha->dha_stack_ptr[i];
 		    /* remember the highest non-zero entry */
 		    lkcd->fix_addr_num = i + 1;
 		} else {
--- a/lkcd_fix_mem.h
+++ /dev/null
@@ -1,295 +0,0 @@
-#ifdef IA64
-
-#define UTSNAME_ENTRY_SZ 65
-
-/* necessary header definitions in all cases */
-#define DUMP_KIOBUF_NUMBER  0xdeadbeef  /* special number for kiobuf maps   */
-
-/* size of a dump header page */
-#define DUMP_PAGE_SZ        64 * 1024  /* size of dump page buffer          */
-
-/* header definitions for s390 dump */
-#define DUMP_MAGIC_S390     0xa8190173618f23fdULL  /* s390 magic number     */
-#define S390_DUMP_HEADER_SIZE     4096
-
-/* standard header definitions */
-#define DUMP_MAGIC_NUMBER   0xa8190173618f23edULL  /* dump magic number     */
-#define DUMP_MAGIC_LIVE     0xa8190173618f23cdULL  /* live magic number     */
-#define DUMP_VERSION_NUMBER   0x5       /* dump version number              */
-#define DUMP_PANIC_LEN        0x100     /* dump panic string length         */
-
-/* dump levels - type specific stuff added later -- add as necessary */
-#define DUMP_LEVEL_NONE        0x0      /* no dumping at all -- just bail   */
-#define DUMP_LEVEL_HEADER      0x1      /* kernel dump header only          */
-#define DUMP_LEVEL_KERN        0x2      /* dump header and kernel pages     */
-#define DUMP_LEVEL_USED        0x4      /* dump header, kernel/user pages   */
-#define DUMP_LEVEL_ALL         0x8      /* dump header, all memory pages    */
-
-/* dump compression options -- add as necessary */
-#define DUMP_COMPRESS_NONE     0x0      /* don't compress this dump         */
-#define DUMP_COMPRESS_RLE      0x1      /* use RLE compression              */
-#define DUMP_COMPRESS_GZIP     0x2      /* use GZIP compression             */
-
-/* dump flags - any dump-type specific flags -- add as necessary */
-#define DUMP_FLAGS_NONE        0x0      /* no flags are set for this dump   */
-#define DUMP_FLAGS_NONDISRUPT  0x1      /* try to keep running after dump   */
-
-/* dump header flags -- add as necessary */
-#define DUMP_DH_FLAGS_NONE     0x0      /* no flags set (error condition!)  */
-#define DUMP_DH_RAW            0x1      /* raw page (no compression)        */
-#define DUMP_DH_COMPRESSED     0x2      /* page is compressed               */
-#define DUMP_DH_END            0x4      /* end marker on a full dump        */
-
-/* names for various dump tunables (they are now all read-only) */
-#define DUMP_ROOT_NAME         "sys/dump"
-#define DUMP_DEVICE_NAME       "dump_device"
-#define DUMP_COMPRESS_NAME     "dump_compress"
-#define DUMP_LEVEL_NAME        "dump_level"
-#define DUMP_FLAGS_NAME        "dump_flags"
-
-/* page size for gzip compression -- buffered beyond PAGE_SIZE slightly */
-#define DUMP_DPC_PAGE_SIZE     (PAGE_SIZE + 512)
-
-/* dump ioctl() control options */
-#define DIOSDUMPDEV		1       /* set the dump device              */
-#define DIOGDUMPDEV		2       /* get the dump device              */
-#define DIOSDUMPLEVEL		3       /* set the dump level               */
-#define DIOGDUMPLEVEL		4       /* get the dump level               */
-#define DIOSDUMPFLAGS		5       /* set the dump flag parameters     */
-#define DIOGDUMPFLAGS		6       /* get the dump flag parameters     */
-#define DIOSDUMPCOMPRESS	7       /* set the dump compress level      */
-#define DIOGDUMPCOMPRESS	8       /* get the dump compress level      */
-
-/* the major number used for the dumping device */
-#ifndef DUMP_MAJOR
-#define DUMP_MAJOR              227
-#endif
-
-/*
- * Structure: dump_header_t
- *  Function: This is the header dumped at the top of every valid crash
- * dump. - * easy reassembly of each crash dump page. The address bits
- *            are split to make things easier for 64-bit/32-bit system
- *            conversions.
- */
-typedef struct _dump_header_s {
-	/* the dump magic number -- unique to verify dump is valid */
-	uint64_t             dh_magic_number;
-
-	/* the version number of this dump */
-	uint32_t             dh_version;
-
-	/* the size of this header (in case we can't read it) */
-	uint32_t             dh_header_size;
-
-	/* the level of this dump (just a header?) */
-	uint32_t             dh_dump_level;
-
-	/* the size of a Linux memory page (4K, 8K, 16K, etc.) */
-	uint32_t             dh_page_size;
-
-	/* the size of all physical memory */
-	uint64_t             dh_memory_size;
-
-	/* the start of physical memory */
-	uint64_t             dh_memory_start;
-
-	/* the end of physical memory */
-	uint64_t             dh_memory_end;
-
-	/* the number of pages in this dump specifically */
-	uint32_t             dh_num_pages;
-
-	/* the panic string, if available */
-	char                 dh_panic_string[DUMP_PANIC_LEN];
-
-	/* timeval depends on architecture, two long values */
-	struct {
-		uint64_t tv_sec;
-		uint64_t tv_usec;
-	} dh_time; /* the time of the system crash */
-
-	/* the NEW utsname (uname) information -- in character form */
-	/* we do this so we don't have to include utsname.h         */
-	/* plus it helps us be more architecture independent        */
-	/* now maybe one day soon they'll make the [65] a #define!  */
-	char                 dh_utsname_sysname[65];
-	char                 dh_utsname_nodename[65];
-	char                 dh_utsname_release[65];
-	char                 dh_utsname_version[65];
-	char                 dh_utsname_machine[65];
-	char                 dh_utsname_domainname[65];
-
-	/* the address of current task (OLD = task_struct *, NEW = void *) */
-	uint64_t             dh_current_task;
-
-	/* what type of compression we're using in this dump (if any) */
-	uint32_t             dh_dump_compress;
-
-	/* any additional flags */
-	uint32_t             dh_dump_flags;
-
-	/* any additional flags */
-	uint32_t             dh_dump_device;
-
-} __attribute__((packed)) dump_header_t;
-
-/*
- * Structure: dump_page_t
- *  Function: To act as the header associated to each physical page of
- *            memory saved in the system crash dump.  This allows for
- *            easy reassembly of each crash dump page.  The address bits
- *            are split to make things easier for 64-bit/32-bit system
- *            conversions.
- */
-typedef struct _dump_page_s {
- - /* the address of this dump page */
-	uint64_t             dp_address;
-
-	/* the size of this dump page */
-	uint32_t             dp_size;
-
-	/* flags (currently DUMP_COMPRESSED, DUMP_RAW or DUMP_END) */
-	uint32_t             dp_flags;
-} __attribute__((packed)) dump_page_t;
-
-/*
- * This structure contains information needed for the lkcdutils
- * package (particularly lcrash) to determine what information is
- * associated to this kernel, specifically.
- */
-typedef struct lkcdinfo_s {
-	int             arch;
-	int             ptrsz;
-	int             byte_order;
-	int             linux_release;
-	int             page_shift;
-	int             page_size;
-	uint64_t        page_mask;
-	uint64_t        page_offset;
-	int             stack_offset;
-} lkcdinfo_t;
-
-#define DUMP_ASM_MAGIC_NUMBER     0xdeaddeadULL  /* magic number */
-
-
-struct pt_regs {
-	/* The following registers are saved by SAVE_MIN: */
-	unsigned long b6;		/* scratch */
-	unsigned long b7;		/* scratch */
-
-	unsigned long ar_csd;           /* used by cmp8xchg16 (scratch) */
-	unsigned long ar_ssd;           /* reserved for future use (scratch) */
-
-	unsigned long r8;		/* scratch (return value register 0) */
-	unsigned long r9;		/* scratch (return value register 1) */
-	unsigned long r10;		/* scratch (return value register 2) */
-	unsigned long r11;		/* scratch (return value register 3) */
-
-	unsigned long cr_ipsr;		/* interrupted task's psr */
-	unsigned long cr_iip;		/* interrupted task's instruction pointer */
-	unsigned long cr_ifs;		/* interrupted task's function state */
-
-	unsigned long ar_unat;		/* interrupted task's NaT register (preserved) */
-	unsigned long ar_pfs;		/* prev function state  */
-	unsigned long ar_rsc;		/* RSE configuration */
-	/* The following two are valid only if cr_ipsr.cpl > 0: */
-	unsigned long ar_rnat;		/* RSE NaT */
-	unsigned long ar_bspstore;	/* RSE bspstore */
-
-	unsigned long pr;		/* 64 predicate registers (1 bit each) */
-	unsigned long b0;		/* return pointer (bp) */
-	unsigned long loadrs;		/* size of dirty partition << 16 */
-
-	unsigned long r1;		/* the gp pointer */
-	unsigned long r12;		/* interrupted task's memory stack pointer */
-	unsigned long r13;		/* thread pointer */
-
-	unsigned long ar_fpsr;		/* floating point status (preserved) */
-	unsigned long r15;		/* scratch */
-
-	/* The remaining registers are NOT saved for system calls.  */
-
-	unsigned long r14;		/* scratch */
-	unsigned long r2;		/* scratch */
-	unsigned long r3;		/* scratch */
-
-	/* The following registers are saved by SAVE_REST: */
-	unsigned long r16;		/* scratch */
-	unsigned long r17;		/* scratch */
-	unsigned long r18;		/* scratch */
-	unsigned long r19;		/* scratch */
-	unsigned long r20;		/* scratch */
-	unsigned long r21;		/* scratch */
-	unsigned long r22;		/* scratch */
-	unsigned long r23;		/* scratch */
-	unsigned long r24;		/* scratch */
-	unsigned long r25;		/* scratch */
-	unsigned long r26;		/* scratch */
-	unsigned long r27;		/* scratch */
-	unsigned long r28;		/* scratch */
-	unsigned long r29;		/* scratch */
-	unsigned long r30;		/* scratch */
-	unsigned long r31;		/* scratch */
-
-	unsigned long ar_ccv;		/* compare/exchange value (scratch) */
-
-	/*
-	 * Floating point registers that the kernel considers scratch:
-	 */
-	struct ia64_fpreg f6;		/* scratch */
-	struct ia64_fpreg f7;		/* scratch */
-	struct ia64_fpreg f8;		/* scratch */
-	struct ia64_fpreg f9;		/* scratch */
-	struct ia64_fpreg f10;		/* scratch */
-	struct ia64_fpreg f11;		/* scratch */
-};
-
-
-
-/*
- * Structure: dump_header_asm_t
- *  Function: This is the header for architecture-specific stuff.  It
- *            follows right after the dump header.
- *
- */
-typedef struct _dump_header_asm_s {
-
-        /* the dump magic number -- unique to verify dump is valid */
-        uint64_t             dha_magic_number;
-
-        /* the version number of this dump */
-        uint32_t             dha_version;
-
-        /* the size of this header (in case we can't read it) */
-        uint32_t             dha_header_size;
-
-        /* pointer to pt_regs */
-//	struct pt_regs      *dha_pt_regs; // version 4 changed this
-	uint64_t             dha_pt_regs;
-
-	/* the dump registers */
-	struct pt_regs       dha_regs;
-
-        /* the rnat register saved after flushrs */
-        uint64_t             dha_rnat;
-
-	/* the pfs register saved after flushrs */
-	uint64_t             dha_pfs;
-
-	/* the bspstore register saved after flushrs */
-	uint64_t             dha_bspstore;
-
-	/* smp specific */
-	uint32_t	     dha_smp_num_cpus;
-	uint32_t 	     dha_dumping_cpu;	// v4 changed this
-	struct pt_regs	     dha_smp_regs[NR_CPUS];
- uint64_t dha_smp_current_task[NR_CPUS]; // v4 changed this - uint64_t dha_stack[NR_CPUS]; // v4 changed this - uint64_t dha_switch_stack[NR_CPUS]; // v4 changed this -
-} __attribute__((packed)) dump_header_asm_t;
-
-#endif // IA64
--- a/lkcd_v8.c
+++ b/lkcd_v8.c
@@ -23,11 +23,187 @@
 #include "lkcd_dump_v8.h"				/* REMIND */
static dump_header_t dump_header_v8 = { 0 };
-// static dump_header_asm_t dump_header_asm_v8 = { 0 };
+#ifndef HAVE_NO_DUMP_HEADER_ASM
+static dump_header_asm_t dump_header_asm_v8 = { 0 };
+#endif
 static dump_page_t dump_page = { 0 };
 static void mclx_cache_page_headers_v8(void);
 static off_t lkcd_offset_to_first_page = LKCD_OFFSET_TO_FIRST_PAGE;
+#if defined(X86_64)
+
+int
+get_lkcd_regs_for_cpu_arch(int cpu, ulong *eip, ulong *esp)
+{
+	if (eip)
+		*eip = dump_header_asm_v8.dha_smp_regs[cpu].rip;
+	if (esp)
+		*esp = dump_header_asm_v8.dha_smp_regs[cpu].rsp;
+
+	return 0;
+}
+
+#elif defined(X86)
+
+int
+get_lkcd_regs_for_cpu_arch(int cpu, ulong *eip, ulong *esp)
+{
+	if (eip)
+		*eip = dump_header_asm_v8.dha_smp_regs[cpu].eip;
+	if (esp)
+		*esp = dump_header_asm_v8.dha_smp_regs[cpu].esp;
+
+	return 0;
+}
+
+#else
+
+int
+get_lkcd_regs_for_cpu_arch(int cpu, ulong *eip, ulong *esp)
+{
+	return -1;
+}
+
+#endif
+
+
+
+int
+get_lkcd_regs_for_cpu(struct bt_info *bt, ulong *eip, ulong *esp)
+{
+	int cpu;
+
+	if (!bt || !bt->tc) {
+		fprintf(stderr, "get_lkcd_regs_for_cpu: invalid tc\n", cpu);
+		return -EINVAL;
+	}
+
+	cpu = bt->tc->processor;
+
+	if (cpu >= NR_CPUS) {
+		fprintf(stderr, "get_lkcd_regs_for_cpu, cpu (%d) too high\n", cpu);
+		return -EINVAL;
+	}
+
+	return get_lkcd_regs_for_cpu_arch(cpu, eip, esp);
+}
+
+
+#ifndef HAVE_NO_DUMP_HEADER_ASM
+int
+lkcd_dump_init_v8_arch(dump_header_t *dh)
+{
+	off_t 			ret_of;
+	ssize_t 		ret_sz;
+	uint32_t 		hdr_size, offset, nr_cpus;
+	dump_header_asm_t 	arch_hdr;
+	char 			*hdr_buf = NULL;
+
+	ret_of = lseek(lkcd->fd, dh->dh_header_size +
+			offsetof(dump_header_asm_t, dha_header_size),
+			SEEK_SET);
+	if (ret_of < 0) {
+		perror("lseek failed in " __FILE__ ":" STR(__LINE__));
+		goto err;
+	}
+
+	ret_sz = read(lkcd->fd, (char *)&hdr_size, sizeof(hdr_size));
+	if (ret_sz != sizeof(hdr_size)) {
+		perror("Reading hdr_size failed in " __FILE__ ":" STR(__LINE__));
+		goto err;
+	}
+
+	ret_of = lseek(lkcd->fd, dh->dh_header_size, SEEK_SET);
+	if (ret_of < 0) {
+		perror("lseek failed in " __FILE__ ":" STR(__LINE__));
+		goto err;
+	}
+
+	hdr_buf = (char *)malloc(hdr_size);
+	if (!hdr_buf) {
+		perror("Could not allocate memory for dump header\n");
+		goto err;
+	}
+
+	ret_sz = read(lkcd->fd, (char *)hdr_buf, hdr_size);
+	if (ret_sz != hdr_size) {
+		perror("Could not read header " __FILE__ ":" STR(__LINE__));
+		goto err;
+	}
+
+
+	/*
+         * Though we have KL_NR_CPUS is 128, the header size is different
+         * CONFIG_NR_CPUS might be different in the kernel. Hence, need
+         * to find out how many CPUs are configured.
+         */
+        offset = offsetof(dump_header_asm_t, dha_smp_regs[0]);
+        nr_cpus = (hdr_size - offset) / sizeof(dump_CPU_info_t);
+
+	/* check for CPU overflow */
+	if (nr_cpus > NR_CPUS) {
+		fprintf(stderr, "CPU number too high %d (%s:%s)\n",
+				nr_cpus, __FILE__, __LINE__);
+		goto err;
+	}
+
+	/* parts that don't depend on the number of CPUs */
+	memcpy(&arch_hdr, (void *)hdr_buf, offset);
+
+	/* registers */
+	memcpy(&arch_hdr.dha_smp_regs, (void *)&hdr_buf[offset],
+			nr_cpus * sizeof(struct pt_regs));
+	offset += nr_cpus * sizeof(struct pt_regs);
+
+	/* current task */
+	memcpy(&arch_hdr.dha_smp_current_task, (void *)&hdr_buf[offset],
+			nr_cpus * sizeof(&arch_hdr.dha_smp_current_task[0]));
+	offset += nr_cpus * sizeof(&arch_hdr.dha_smp_current_task[0]);
+
+	/* stack */
+	memcpy(&arch_hdr.dha_stack, (void *)&hdr_buf[offset],
+			nr_cpus * sizeof(&arch_hdr.dha_stack[0]));
+	offset += nr_cpus * sizeof(&arch_hdr.dha_stack[0]);
+
+	/* stack_ptr */
+	memcpy(&arch_hdr.dha_stack_ptr, (void *)&hdr_buf[offset],
+			nr_cpus * sizeof(&arch_hdr.dha_stack_ptr[0]));
+	offset += nr_cpus * sizeof(&arch_hdr.dha_stack_ptr[0]);
+
+	if (arch_hdr.dha_magic_number != DUMP_ASM_MAGIC_NUMBER) {
+		fprintf(stderr, "Invalid magic number for x86_64\n");
+		goto err;
+	}
+
+	/*
+	 * read the kernel load address on IA64 -- other architectures have
+	 * no relocatable kernel at the lifetime of LKCD
+	 */
+#ifdef IA64
+	memcpy(&arch_hdr.dha_kernel_addr, (void *)&hdr_buf[offset], sizeof(uint64_t));
+#endif
+
+	memcpy(&dump_header_asm_v8, &arch_hdr, sizeof(dump_header_asm_t));
+
+	return 0;
+
+err:
+	free(hdr_buf);
+	return -1;
+}
+
+#else /* architecture that has no lkcd_dump_init_v8 */
+
+int
+lkcd_dump_init_v8_arch(dump_header_t *dh)
+{
+	return 0;
+}
+
+#endif
+
+
+
 /*
  *  Verify and initialize the LKCD environment, storing the common data
  *  in the global lkcd_environment structure.
@@ -69,8 +245,14 @@ lkcd_dump_init_v8(FILE *fp, int fd, char
         lkcd->dump_header = dh;
if (lkcd->debug) dump_lkcd_environment(LKCD_DUMP_HEADER_ONLY);
+
+	if (lkcd_dump_init_v8_arch(dh) != 0) {
+		fprintf(stderr, "Warning: Failed to initialise "
+				"arch specific dump code\n");
+	}
+
 #ifdef IA64
-	if ( (fix_addr_v8(fd) == -1) )
+	if ( (fix_addr_v8(&dump_header_asm_v8) == -1) )
 	    return FALSE;
 #endif
--- a/netdump.c
+++ b/netdump.c
@@ -1757,7 +1757,6 @@ struct x86_64_user_regs_struct {
         unsigned long fs_base, gs_base;
         unsigned long ds,es,fs,gs;
 };
-#define offsetof(TYPE, MEMBER) ((ulong)&((TYPE *)0)->MEMBER)
void get_netdump_regs_x86_64(struct bt_info *bt, ulong *ripp, ulong *rspp)


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