[Crash-utility] [PATCH 3/7] Add get_remote_phys_base.

Don Slutz dslutz at verizon.com
Tue Nov 19 11:46:42 UTC 2013


From: Don Slutz <dslutz at verizon.com>

The most common mismatch between crash and older kernels is
phys_base.  In the remote case, see if the remote server supports
vitrual memory access, and if so, see if phys_base can be retreived.

Signed-off-by: Don Slutz <dslutz at verizon.com>
---
 defs.h   |  1 +
 remote.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 x86_64.c | 24 +++++++++++++++++++++
 3 files changed, 98 insertions(+), 2 deletions(-)

diff --git a/defs.h b/defs.h
index 4cb2113..e7073c6 100755
--- a/defs.h
+++ b/defs.h
@@ -5526,6 +5526,7 @@ void dump_sockets_workhorse(ulong, ulong, struct reference *);
  *  remote.c
  */
 int is_remote_daemon(char *);
+physaddr_t get_remote_phys_base(physaddr_t, physaddr_t);
 void remote_fd_init(void);
 int get_remote_file(struct remote_file *);
 uint remote_page_size(void);
diff --git a/remote.c b/remote.c
index 823aba0..58588ce 100755
--- a/remote.c
+++ b/remote.c
@@ -1797,6 +1797,7 @@ static void copy_to_local_namelist(struct remote_file *);
 static char *create_local_namelist(struct remote_file *);
 static int remote_find_booted_kernel(struct remote_file *);
 static int remote_proc_version(char *);
+static int validate_phys_base(physaddr_t, physaddr_t, physaddr_t);
 static int remote_file_open(struct remote_file *);
 static int remote_file_close(struct remote_file *);
 static int identical_namelist(char *, struct remote_file *);
@@ -1813,6 +1814,14 @@ static int remote_tcp_read_string(int, const char *, size_t, int);
 static int remote_tcp_write(int, const void *, size_t);
 static int remote_tcp_write_string(int, const char *);
 
+struct _remote_context {
+        int nCpus;
+        int vFd;
+        char remoteType[10];
+} remote_context;
+
+struct _remote_context *rc = &remote_context;
+
 /*
  *  Parse, verify and establish a connection with the network daemon
  *  specified on the crash command line.
@@ -1848,7 +1857,7 @@ is_remote_daemon(char *dp)
 
 	pc->port = 0;
 	pc->server = pc->server_memsrc = NULL;
-	pc->rmfd = pc->rkfd = -1;
+	rc->vFd = pc->rmfd = pc->rkfd = -1;
 	file1 = file2 = NULL;
 
 	if ((filep = strstr(dp, ","))) {
@@ -2280,6 +2289,59 @@ remote_proc_version(char *buf)
 }
 
 /*
+ *  Check that virt_phys_base when accessed via
+ *  phys_base - text_start is phys_base.
+ */
+static int
+validate_phys_base(physaddr_t phys_base, physaddr_t text_start, physaddr_t virt_phys_base)
+{
+        ulong value;
+
+        if (CRASHDEBUG(3))
+                fprintf(fp, "validate_phys_base: virt_phys_base=0x%llx phys_base=0x%llx text_start=0x%llx calc=0x%llx\n",
+                        virt_phys_base, phys_base, text_start, virt_phys_base + phys_base - text_start);
+
+        if (READMEM(pc->rmfd, (void*)&value, sizeof(value),
+		    virt_phys_base, virt_phys_base + phys_base - text_start)
+	    == sizeof(value)) {
+                if (value == phys_base)
+                        return 1;
+        }
+        return 0;
+}
+
+/*
+ *  Get remote phys_base based on virtual address of "phys_base".
+ */
+physaddr_t
+get_remote_phys_base(physaddr_t text_start, physaddr_t virt_phys_base)
+{
+        int vcpu;
+        ulong value;
+
+	if (rc->vFd < 0) {
+		struct remote_file remote_file, *rfp;
+
+		rfp = &remote_file;
+		BZERO(rfp, sizeof(struct remote_file));
+		rfp->filename = "/dev/vmem";
+		if (remote_file_open(rfp)) {
+			rc->vFd = rfp->fd;
+		} else
+			return 0;
+	}
+
+        for (vcpu = 0; vcpu < rc->nCpus; vcpu++)
+                if (remote_memory_read(rc->vFd, (void*)&value, sizeof(value),
+				       virt_phys_base, vcpu) == sizeof(value)) {
+                        if (validate_phys_base(value, text_start, virt_phys_base))
+                                return value;
+                }
+
+        return 0;
+}
+
+/*
  *
  *   Set up the file descriptors and file name strings if they haven't
  *   been set up before:
@@ -2999,7 +3061,7 @@ remote_page_size(void)
 {
         char sendbuf[BUFSIZE];
         char recvbuf[BUFSIZE];
-        char *p1;
+        char *p1, *p2, *p3;
 	uint psz;
 
         BZERO(sendbuf, BUFSIZE);
@@ -3026,12 +3088,21 @@ remote_page_size(void)
         strtok(recvbuf, " ");           /* PAGESIZE */
         p1 = strtok(NULL, " ");         /* LIVE, MCLXCD or LKCD */
         p1 = strtok(NULL, " ");         /* page size */
+        p2 = strtok(NULL, " ");         /* remote type */
+        p3 = strtok(NULL, " ");         /* number of Cpus */
 	psz = atoi(p1);
 
 	if (psz > MAXRECVBUFSIZE)
 		error(FATAL, 
 		   "remote page size %d is larger than MAXRECVBUFSIZE!\n", psz);
 
+        if (p2) {
+                strncpy(rc->remoteType, p2, sizeof(rc->remoteType) - 1);
+                rc->remoteType[sizeof(rc->remoteType) - 1] = 0;
+        }
+        if (p3)
+                rc->nCpus = atoi(p3);
+
 	return psz;
 }
 
diff --git a/x86_64.c b/x86_64.c
index e8196f8..e5f8f19 100755
--- a/x86_64.c
+++ b/x86_64.c
@@ -5838,6 +5838,18 @@ x86_64_calc_phys_base(void)
 			return;
 		else
 			text_start = symbol_value("_text");
+		if (REMOTE()) {
+			phys_base = get_remote_phys_base(text_start, symbol_value("phys_base"));
+			if (phys_base) {
+				machdep->machspec->phys_base = phys_base;
+				if (CRASHDEBUG(1)) {
+					fprintf(fp, "_text: %lx  ", text_start);
+					fprintf(fp, "phys_base: %lx\n\n",
+						machdep->machspec->phys_base);
+				}
+				return;
+			}
+		}
 	}
 
 	if (ACTIVE()) {
@@ -7680,3 +7692,15 @@ x86_64_verify_paddr(uint64_t paddr)
 }
 
 #endif  /* X86_64 */ 
+
+/*
+ * Specify Emacs local variables so the formating
+ * of the code stays the same.
+ *
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 8
+ * indent-tabs-mode: t
+ * End:
+ */
-- 
1.8.4




More information about the Crash-utility mailing list