public inbox for kexec@lists.infradead.org
 help / color / mirror / Atom feed
From: Petr Tesarik <ptesarik@suse.cz>
To: kexec@lists.infradead.org
Cc: Norbert Trapp <Norbert.Trapp@ts.fujitsu.com>
Subject: [PATCHv3 3/9] Read the Xen crash ELF note into memory at startup
Date: Fri, 24 Aug 2012 17:42:07 +0200	[thread overview]
Message-ID: <201208241742.07480.ptesarik@suse.cz> (raw)

Instead of seeking individual fields inside the ELF note, copy the
corresponding struct type from the Xen sources, so people can understand
why the code does what it does.

This is mainly a cleanup patch to improve maintainability, but it also
simplifies reusing the crash note data from other places.

Signed-off-by: Petr Tesarik <ptesarik@suse.cz>

---
 arch/x86_64.c  |   24 ++++++++++++++--
 elf_info.c     |   25 -----------------
 elf_info.h     |    2 -
 makedumpfile.c |   82 
++++++++++++++++++++++++++++++++++++++++++---------------
 makedumpfile.h |   49 ++++++++++++++++++++++++++++++++--
 5 files changed, 130 insertions(+), 52 deletions(-)

--- a/elf_info.c
+++ b/elf_info.c
@@ -88,7 +88,6 @@ static unsigned long		size_eraseinfo;
  */
 static off_t			offset_xen_crash_info;
 static unsigned long		size_xen_crash_info;
-static unsigned long		xen_p2m_mfn;
 
 
 /*
@@ -292,8 +291,7 @@ static int
 get_pt_note_info(void)
 {
 	int n_type, size_desc;
-	unsigned long p2m_mfn;
-	off_t offset, offset_desc, off_p2m = 0;
+	off_t offset, offset_desc;
 	char buf[VMCOREINFO_XEN_NOTE_NAME_BYTES];
 	char note[MAX_SIZE_NHDR];
 
@@ -349,21 +347,6 @@ get_pt_note_info(void)
 			offset_xen_crash_info = offset_desc;
 			size_xen_crash_info   = size_desc;
 
-			off_p2m = offset + offset_next_note(note)
-					 - sizeof(p2m_mfn);
-			if (lseek(fd_memory, off_p2m, SEEK_SET) < 0){
-				ERRMSG("Can't seek the dump memory(%s). %s\n",
-				    name_memory, strerror(errno));
-				return FALSE;
-			}
-			if (read(fd_memory, &p2m_mfn, sizeof(p2m_mfn))
-			     != sizeof(p2m_mfn)) {
-				ERRMSG("Can't read the dump memory(%s). %s\n",
-				    name_memory, strerror(errno));
-				return FALSE;
-			}
-			xen_p2m_mfn = p2m_mfn;
-
 		/*
 		 * Check whether a source dumpfile contains eraseinfo.
 		 *   /proc/vmcore does not contain eraseinfo, because eraseinfo
@@ -859,9 +842,3 @@ set_eraseinfo(off_t offset, unsigned lon
 	size_eraseinfo   = size;
 }
 
-unsigned long
-get_xen_p2m_mfn(void)
-{
-	return xen_p2m_mfn;
-}
-
--- a/elf_info.h
+++ b/elf_info.h
@@ -68,8 +68,6 @@ int has_eraseinfo(void);
 void get_eraseinfo(off_t *offset, unsigned long *size);
 void set_eraseinfo(off_t offset, unsigned long size);
 
-unsigned long get_xen_p2m_mfn(void);
-
 #endif  /* ELF_INFO_H */
 
 
--- a/makedumpfile.c
+++ b/makedumpfile.c
@@ -5316,32 +5316,64 @@ get_structure_info_xen(void)
 }
 
 int
-get_xen_phys_start(void)
+init_xen_crash_info(void)
 {
-	off_t offset, offset_xen_crash_info;
-	unsigned long xen_phys_start, size_xen_crash_info;
-	const off_t failed = (off_t)-1;
+	off_t		offset_xen_crash_info;
+	unsigned long	size_xen_crash_info;
+	void		*buf;
+
+	get_xen_crash_info(&offset_xen_crash_info, &size_xen_crash_info);
+	if (!size_xen_crash_info) {
+		info->xen_crash_info_v = -1;
+		return TRUE;		/* missing info is non-fatal */
+	}
+
+	if (size_xen_crash_info < sizeof(xen_crash_info_com_t)) {
+		ERRMSG("Xen crash info too small (%lu bytes).\n",
+		       size_xen_crash_info);
+		return FALSE;
+	}
+
+	buf = malloc(size_xen_crash_info);
+	if (!buf) {
+		ERRMSG("Can't allocate note (%lu bytes). %s\n",
+		       size_xen_crash_info, strerror(errno));
+		return FALSE;
+	}
+
+	if (lseek(info->fd_memory, offset_xen_crash_info, SEEK_SET) < 0) {
+		ERRMSG("Can't seek the dump memory(%s). %s\n",
+		       info->name_memory, strerror(errno));
+		return FALSE;
+	}
+	if (read(info->fd_memory, buf, size_xen_crash_info)
+	    != size_xen_crash_info) {
+		ERRMSG("Can't read the dump memory(%s). %s\n",
+		       info->name_memory, strerror(errno));
+		return FALSE;
+	}
+
+	info->xen_crash_info.com = buf;
+	if (size_xen_crash_info >= sizeof(xen_crash_info_v2_t))
+		info->xen_crash_info_v = 2;
+	else if (size_xen_crash_info >= sizeof(xen_crash_info_t))
+		info->xen_crash_info_v = 1;
+	else
+		info->xen_crash_info_v = 0;
 
+	return TRUE;
+}
+
+int
+get_xen_phys_start(void)
+{
 	if (info->xen_phys_start)
 		return TRUE;
 
-	get_xen_crash_info(&offset_xen_crash_info, &size_xen_crash_info);
-	if (size_xen_crash_info >= SIZE_XEN_CRASH_INFO_V2) {
-		offset = offset_xen_crash_info + size_xen_crash_info
-			 - sizeof(unsigned long) * 2;
-		if (lseek(info->fd_memory, offset, SEEK_SET) == failed) {
-			ERRMSG("Can't seek the dump memory(%s). %s\n",
-			    info->name_memory, strerror(errno));
-			return FALSE;
-		}
-		if (read(info->fd_memory, &xen_phys_start, sizeof(unsigned long))
-		    != sizeof(unsigned long)) {
-			ERRMSG("Can't read the dump memory(%s). %s\n",
-			    info->name_memory, strerror(errno));
-			return FALSE;
-		}
-		info->xen_phys_start = xen_phys_start;
-	}
+#if defined(__x86__) || defined(__x86_64__)
+	if (info->xen_crash_info_v >= 2)
+		info->xen_phys_start = info->xen_crash_info.v2->xen_phys_start;
+#endif
 
 	return TRUE;
 }
@@ -5506,6 +5538,12 @@ show_data_xen(void)
 	MSG("OFFSET(domain.next_in_list): %ld\n", OFFSET(domain.next_in_list));
 
 	MSG("\n");
+	if (info->xen_crash_info.com) {
+		MSG("xen_major_version: %lx\n",
+		    info->xen_crash_info.com->xen_major_version);
+		MSG("xen_minor_version: %lx\n",
+		    info->xen_crash_info.com->xen_minor_version);
+	}
 	MSG("xen_phys_start: %lx\n", info->xen_phys_start);
 	MSG("frame_table_vaddr: %lx\n", info->frame_table_vaddr);
 	MSG("xen_heap_start: %lx\n", info->xen_heap_start);
@@ -5785,6 +5823,8 @@ initial_xen(void)
 		return FALSE;
 	}
 #endif
+	if (!init_xen_crash_info())
+		return FALSE;
 	if (!fallback_to_current_page_size())
 		return FALSE;
 	/*
--- a/makedumpfile.h
+++ b/makedumpfile.h
@@ -416,8 +416,6 @@ do { \
 #define SIZE_BUF_STDIN	(4096)
 #define STRLEN_OSRELEASE (65)	/* same length as diskdump.h */
 
-#define SIZE_XEN_CRASH_INFO_V2	(sizeof(unsigned long) * 10)
-
 /*
  * The value of dependence on machine
  */
@@ -719,6 +717,43 @@ unsigned long long vaddr_to_paddr_ia64(u
 #define pfn_to_paddr(X) \
 	(((unsigned long long)(X) + ARCH_PFN_OFFSET) << PAGESHIFT())
 
+/* Format of Xen crash info ELF note */
+typedef struct {
+	unsigned long xen_major_version;
+	unsigned long xen_minor_version;
+	unsigned long xen_extra_version;
+	unsigned long xen_changeset;
+	unsigned long xen_compiler;
+	unsigned long xen_compile_date;
+	unsigned long xen_compile_time;
+	unsigned long tainted;
+} xen_crash_info_com_t;
+
+typedef struct {
+	xen_crash_info_com_t com;
+#if defined(__x86__) || defined(__x86_64__)
+	/* added by changeset 2b43fb3afb3e: */
+	unsigned long dom0_pfn_to_mfn_frame_list_list;
+#endif
+#if defined(__ia64__)
+	/* added by changeset d7c3b12014b3: */
+	unsigned long dom0_mm_pgd_mfn;
+#endif
+} xen_crash_info_t;
+
+/* changeset 439a3e9459f2 added xen_phys_start
+ * to the middle of the struct... */
+typedef struct {
+	xen_crash_info_com_t com;
+#if defined(__x86__) || defined(__x86_64__)
+	unsigned long xen_phys_start;
+	unsigned long dom0_pfn_to_mfn_frame_list_list;
+#endif
+#if defined(__ia64__)
+	unsigned long dom0_mm_pgd_mfn;
+#endif
+} xen_crash_info_v2_t;
+
 struct mem_map_data {
 	unsigned long long	pfn_start;
 	unsigned long long	pfn_end;
@@ -902,6 +937,16 @@ struct DumpInfo {
 	/*
 	 * for Xen extraction
 	 */
+	union {				/* Both versions of Xen crash info: */
+		xen_crash_info_com_t *com;   /* common fields */
+		xen_crash_info_t *v1;	     /* without xen_phys_start */
+		xen_crash_info_v2_t *v2;     /* changeset 439a3e9459f2 */
+	} xen_crash_info;
+	int xen_crash_info_v;		/* Xen crash info version:
+					 *   0 .. xen_crash_info_com_t
+					 *   1 .. xen_crash_info_t
+					 *   2 .. xen_crash_info_v2_t */
+
 	unsigned long long	dom0_mapnr;  /* The number of page in domain-0.
 					      * Different from max_mapnr.
 					      * max_mapnr is the number of page
--- a/arch/x86_64.c
+++ b/arch/x86_64.c
@@ -30,6 +30,18 @@ is_vmalloc_addr(ulong vaddr)
 	    || (vaddr >= MODULES_VADDR && vaddr <= MODULES_END));
 }
 
+static unsigned long
+get_xen_p2m_mfn(void)
+{
+	if (info->xen_crash_info_v >= 2)
+		return info->xen_crash_info.v2->
+			dom0_pfn_to_mfn_frame_list_list;
+	if (info->xen_crash_info_v >= 1)
+		return info->xen_crash_info.v1->
+			dom0_pfn_to_mfn_frame_list_list;
+	return NOT_FOUND_LONG_VALUE;
+}
+
 int
 get_phys_base_x86_64(void)
 {
@@ -59,6 +71,7 @@ get_phys_base_x86_64(void)
 int
 get_machdep_info_x86_64(void)
 {
+	unsigned long p2m_mfn;
 	int i, j, mfns[MAX_X86_64_FRAMES];
 	unsigned long frame_mfn[MAX_X86_64_FRAMES];
 	unsigned long buf[MFNS_PER_FRAME];
@@ -72,9 +85,14 @@ get_machdep_info_x86_64(void)
 	 * Get the information for translating domain-0's physical
 	 * address into machine address.
 	 */
-	if (!readmem(MADDR_XEN, pfn_to_paddr(get_xen_p2m_mfn()),
-					 &frame_mfn, PAGESIZE())) {
-		ERRMSG("Can't get p2m_mfn.\n");
+	p2m_mfn = get_xen_p2m_mfn();
+	if (p2m_mfn == (unsigned long)NOT_FOUND_LONG_VALUE) {
+		ERRMSG("Can't get p2m_mfn address.\n");
+		return FALSE;
+	}
+	if (!readmem(MADDR_XEN, pfn_to_paddr(p2m_mfn),
+		     &frame_mfn, PAGESIZE())) {
+		ERRMSG("Can't read p2m_mfn.\n");
 		return FALSE;
 	}
 



_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

                 reply	other threads:[~2012-08-24 15:42 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=201208241742.07480.ptesarik@suse.cz \
    --to=ptesarik@suse.cz \
    --cc=Norbert.Trapp@ts.fujitsu.com \
    --cc=kexec@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox