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

Don Slutz dslutz at verizon.com
Wed Nov 20 01:33:39 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   |  3 +++
 remote.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 x86_64.c | 12 +++++++++++
 3 files changed, 88 insertions(+), 2 deletions(-)

diff --git a/defs.h b/defs.h
index 86b4fae..8d56da8 100755
--- a/defs.h
+++ b/defs.h
@@ -504,6 +504,8 @@ struct program_context {
 #define GET_LOG       (0x200ULL)
 #define VMCOREINFO    (0x400ULL)
 #define ALLOW_FP      (0x800ULL)
+#define REM_PAUSED_F (0x1000ULL)
+#define REMOTE_PAUSED() (pc->flags2 & REM_PAUSED_F)
 	char *cleanup;
 	char *namelist_orig;
 	char *namelist_debug_orig;
@@ -5525,6 +5527,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 204f7b8..a4069a7 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 *);
@@ -1815,6 +1816,9 @@ static int remote_tcp_write_string(int, const char *);
 
 struct _remote_context {
         uint flags;
+        int n_cpus;
+        int vfd;
+        char remote_type[10];
 } remote_context;
 
 #define NIL_FLAG       (0x01U)
@@ -1858,7 +1862,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, ","))) {
@@ -2290,6 +2294,62 @@ 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",
+                        (long long unsigned int)virt_phys_base,
+			(long long unsigned int)phys_base,
+			(long long unsigned int)text_start,
+			(long long unsigned int)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->n_cpus; 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:
@@ -3009,7 +3069,7 @@ remote_page_size(void)
 {
         char sendbuf[BUFSIZE];
         char recvbuf[BUFSIZE];
-        char *p1;
+        char *p1, *p2, *p3;
 	uint psz;
 
         BZERO(sendbuf, BUFSIZE);
@@ -3036,12 +3096,23 @@ 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->remote_type, p2, sizeof(rc->remote_type) - 1);
+                rc->remote_type[sizeof(rc->remote_type) - 1] = 0;
+		if (rc->remote_type[0] != 'L')
+			pc->flags2 |= REM_PAUSED_F;
+        }
+        if (p3)
+                rc->n_cpus = atoi(p3);
+
 	return psz;
 }
 
diff --git a/x86_64.c b/x86_64.c
index e8196f8..cc26fec 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()) {
-- 
1.8.4




More information about the Crash-utility mailing list