From: Don Slutz <dslutz(a)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(a)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