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 | 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