From: Don Slutz <[email protected]>

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 <[email protected]>
---
 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

--
Crash-utility mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/crash-utility

Reply via email to