From 2539676df46f7a9297e1ebd781f9bb0b51afb0c5 Mon Sep 17 00:00:00 2001 From: Don Slutz Date: Sat, 16 Nov 2013 18:28:02 -0500 Subject: [PATCH 3/3] xen-crashd: v2 to v3 bug fixes Fixup NIL handling. FAILMSG has errno not just an error code. convert_to_phys should return 0 on error, not 0-4095 Add support for TYPE and /dev/xenmem. Add support "PAGESIZE NIL" (new crash feature, may change). Update doc. Signed-off-by: Don Slutz --- docs/misc/crash-remote.txt | 14 +++---- tools/xen-crashd/Makefile | 3 ++ tools/xen-crashd/xen-crashd.8 | 48 ++++++++++++++++++++++ tools/xen-crashd/xen-crashd.c | 94 ++++++++++++++++++++++++++++++++++--------- 4 files changed, 134 insertions(+), 25 deletions(-) create mode 100644 tools/xen-crashd/xen-crashd.8 diff --git a/docs/misc/crash-remote.txt b/docs/misc/crash-remote.txt index 1b6baa5..4dc1336 100644 --- a/docs/misc/crash-remote.txt +++ b/docs/misc/crash-remote.txt @@ -59,12 +59,16 @@ Command notes: MACHINE_PID: Return the that crash understands and . + For Xen the server_pid is returned as 0. OPEN: - Currently only /dev/mem, /dev/kmem, and /dev/vmem are supported. The return is: + Currently only /dev/mem, /dev/kmem, and /dev/vmem are supported. + The return is: OPEN filename fid O_RDONLY filesize + Note: only read access is supported. + CLOSE: Not currently supported. @@ -78,17 +82,13 @@ READ_LIVE: physical one. The return is also special in that it starts with either FAIL or - DONE, a space and a 7 digit error code (fail) or a 7 digit length + DONE, a space and a 7 digit errno (fail) or a 7 digit length of data. Since the max size is one page the 7 digit number should not overflow. For DONE, right after the 7 digit number the raw data starts for bytes. If any part of the data is not mappable, the whole request fails. - The defined error code are: - 1: Transfer too big. - 2: Failed to map starting address. - 3: Failed to map ending address. - 4: Failed to convert virtual address to physical address. + errno is from #include PROC_VERSION: diff --git a/tools/xen-crashd/Makefile b/tools/xen-crashd/Makefile index cca96fe..5557450 100644 --- a/tools/xen-crashd/Makefile +++ b/tools/xen-crashd/Makefile @@ -7,6 +7,7 @@ CFLAGS += $(CFLAGS_libxenctrl) LDLIBS += $(LDLIBS_libxenctrl) LIBBIN = xen-crashd +MAN8 = $(wildcard *.8) .PHONY: all all: build @@ -17,7 +18,9 @@ build: $(BIN) $(LIBBIN) .PHONY: install install: build [ -z "$(LIBBIN)" ] || $(INSTALL_DIR) $(DESTDIR)$(PRIVATE_BINDIR) + $(INSTALL_DIR) $(DESTDIR)$(MAN8DIR) [ -z "$(LIBBIN)" ] || $(INSTALL_PROG) $(LIBBIN) $(DESTDIR)$(PRIVATE_BINDIR) + $(INSTALL_DATA) $(MAN8) $(DESTDIR)$(MAN8DIR) .PHONY: clean clean: diff --git a/tools/xen-crashd/xen-crashd.8 b/tools/xen-crashd/xen-crashd.8 new file mode 100644 index 0000000..464f407 --- /dev/null +++ b/tools/xen-crashd/xen-crashd.8 @@ -0,0 +1,48 @@ +.TH XEN-CRASHD 8 "15 November 2013" "Xen domain 0 utils" +.SH NAME +xen-crashd \- connect a Xen domain to +.B crash +.SH SYNOPSIS +.B xen-crashd +.I domain +[ +.I PORT +] +.SH DESCRIPTION +.B xen-crashd +is used to connect +.B crash +to a \fIdomain\fR. The \fIdomain\fR will be paused while +.B crash +is connected. Currently the code exits when +.B crash +disconnects. The default +.I PORT +is 5001. + +.SH EXAMPLE + /usr/lib/xen/bin/xen-crashd +.I 1 +& + \fBcrash\fR localhost:\fI5001\fR /usr/lib/debug/lib/modules/3.8.11-100.fc17.x86_64/vmlinux + +.SH IMPORTANT +The linux running +.B crash +must be the same architecture as the \fIdomain\fR. Like both +x86_64. Also the +.B crash +version must be new enough to understand the \fIdomain\fR's kernel. +If the kernel version are different, additional arguments maybe need +to get +.B crash +to work. Best results will be had using the same version of linux +while running +.B crash +as the \fIdomain\fR is running. + +.SH AUTHOR +Don Slutz + +.SH "SEE ALSO" +crash(8) diff --git a/tools/xen-crashd/xen-crashd.c b/tools/xen-crashd/xen-crashd.c index 249bb0a..dabab39 100644 --- a/tools/xen-crashd/xen-crashd.c +++ b/tools/xen-crashd/xen-crashd.c @@ -177,7 +177,7 @@ map_page(int vcpu, guest_word_t phys) mapped = xc_map_foreign_range(xc_handle, domid, XC_PAGE_SIZE, PROT_READ, mfn); if (mapped == NULL) { - if (debug & 0x004) { + if (debug & 0x044) { print_now(); printf("failed to map page for %08llx.\n", phys); } @@ -197,7 +197,7 @@ copy_phys(int vcpu, char * pv_dst, size_t cb, guest_word_t phys) /* optimize for the case where access is completely within the first page. */ local_addr = map_page(vcpu, phys); if (!local_addr) { - return 2; + return ENXIO; } if (cb <= cb_page) { memcpy(pv_dst, local_addr, cb); @@ -210,10 +210,10 @@ copy_phys(int vcpu, char * pv_dst, size_t cb, guest_word_t phys) /* Max transfer is XC_PAGE_SIZE... */ if (cb > XC_PAGE_SIZE) - return 1; + return EINVAL; local_addr = map_page(vcpu, phys); if (!local_addr) { - return 3; + return ENXIO; } memcpy(pv_dst, local_addr, cb); return 0; @@ -225,7 +225,10 @@ convert_to_phys(int vcpu, guest_word_t virt) unsigned long mfn = xc_translate_foreign_address(xc_handle, domid, vcpu, virt); unsigned long offset = virt & ~XC_PAGE_MASK; - return (mfn << XC_PAGE_SHIFT) + offset; + if (mfn == 0) + return 0; + else + return (mfn << XC_PAGE_SHIFT) + offset; } static int @@ -238,12 +241,12 @@ copy_virt(int vcpu, char * pv_dst, size_t cb, guest_word_t virt) size_t cb_page = XC_PAGE_SIZE - offset; if (mfn == 0) - return 4; + return EFAULT; /* optimize for the case where access is completely within the first page. */ local_addr = map_page(vcpu, phys); if (!local_addr) { - return 2; + return ENXIO; } if (cb <= cb_page) { memcpy(pv_dst, local_addr, cb); @@ -256,10 +259,10 @@ copy_virt(int vcpu, char * pv_dst, size_t cb, guest_word_t virt) /* Max transfer is XC_PAGE_SIZE... */ if (cb > XC_PAGE_SIZE) - return 1; + return EINVAL; local_addr = map_page(vcpu, phys); if (!local_addr) { - return 3; + return ENXIO; } memcpy(pv_dst, local_addr, cb); return 0; @@ -451,7 +454,7 @@ int main(int argc, char **argv) printf("bad len=%d page_size=%ld;%s %s %s %s %s\n", len, XC_PAGE_SIZE, recvbuf, p1, p2, p3, p4); len = 0; - rc2 = 4; + rc2 = EINVAL; } if (len) @@ -484,7 +487,7 @@ int main(int argc, char **argv) rc2 = copy_phys(vcpu, &sendbuf[DATA_HDRSIZE], len, addr); } if (rc2) { - if (debug & 0x004) { + if (debug & 0x044) { print_now(); printf("Failed rc2=%d\n", rc2); } @@ -661,6 +664,40 @@ int main(int argc, char **argv) if (tcp_write_string(msgsock, sendbuf)) break; } + else if (STRNEQ(recvbuf, "TYPE ")) + { + char *p1; + char *file; + + if (debug & 0x010) { + print_now(); + printf("req: %s\n", recvbuf); + } + p1 = strtok(recvbuf, " "); /* TYPE */ + file = strtok(NULL, " "); /* filename */ + if (STRNEQ(file, "/dev/mem")) + { + snprintf(sendbuf, sizeof(sendbuf), "%s %s DEVMEM", p1, file); + } + else if (STRNEQ(file, "/dev/kmem")) + { + snprintf(sendbuf, sizeof(sendbuf), "%s %s DEVMEM", p1, file); + } + else if (STRNEQ(file, "/dev/vmem")) + { + snprintf(sendbuf, sizeof(sendbuf), "%s %s DEVMEM", p1, file); + } + else if (STRNEQ(file, "/dev/xenmem")) + { + snprintf(sendbuf, sizeof(sendbuf), "%s %s DEVMEM", p1, file); + } + else + { + snprintf(sendbuf, sizeof(sendbuf), "%s %s ", p1, file); + } + if (tcp_write_string(msgsock, sendbuf)) + break; + } else if (STRNEQ(recvbuf, "VTOP")) { char *p1, *p2, *p3; @@ -718,6 +755,11 @@ int main(int argc, char **argv) fds[i] = 3; snprintf(sendbuf, sizeof(sendbuf), "%s %s %d O_RDONLY %lld", p1, file, i, 1024LL * 1024LL * 1024LL * 1024LL * 1024LL * 1024LL); } + else if (STRNEQ(file, "/dev/xenmem")) + { + fds[i] = 4; + snprintf(sendbuf, sizeof(sendbuf), "%s %s %d O_RDONLY %lld", p1, file, i, 1024LL * 1024LL * 1024LL * 1024LL * 1024LL * 1024LL); + } else { snprintf(sendbuf, sizeof(sendbuf), "%s %s ", p1, file); @@ -738,7 +780,7 @@ int main(int argc, char **argv) print_now(); printf("req: %s\n", recvbuf); } - p1 = strtok(recvbuf, " "); /* SIZE */ + p1 = strtok(recvbuf, " "); /* CLOSE */ p2 = strtok(NULL, " "); /* filename id */ snprintf(sendbuf, sizeof(sendbuf), "%s %s ", p1, p2); if (tcp_write_string(msgsock, sendbuf)) @@ -757,14 +799,30 @@ int main(int argc, char **argv) if (tcp_write_string(msgsock, sendbuf)) break; } - else if (STRNEQ(recvbuf, "PAGESIZE LIVE")) + else if (STRNEQ(recvbuf, "PAGESIZE ")) { + char *p1, *p2; + if (debug & 0x010) { print_now(); printf("req: %s\n", recvbuf); } - snprintf(sendbuf, sizeof(sendbuf), "%s %ld XEN %d", - recvbuf, XC_PAGE_SIZE, dominfo.max_vcpu_id + 1); + p1 = strtok(recvbuf, " "); /* PAGESIZE */ + p2 = strtok(NULL, " "); /* type */ + if (STRNEQ(p2, "LIVE")) + { + snprintf(sendbuf, sizeof(sendbuf), "%s %s %ld XEN %d", + p1, p2, XC_PAGE_SIZE, dominfo.max_vcpu_id + 1); + } + else if (STRNEQ(p2, "NIL")) + { + snprintf(sendbuf, sizeof(sendbuf), "%s %s %ld XEN %d", + p1, p2, XC_PAGE_SIZE, dominfo.max_vcpu_id + 1); + } + else + { + snprintf(sendbuf, sizeof(sendbuf), "%s %s ", p1, p2); + } if (tcp_write_string(msgsock, sendbuf)) break; } @@ -786,8 +844,8 @@ int main(int argc, char **argv) } nil_mode = 1; snprintf(sendbuf, sizeof(sendbuf), "%s XEN OK", recvbuf); - tcp_write_string(msgsock, sendbuf); - break; + if (tcp_write_string(msgsock, sendbuf)) + break; } else { @@ -798,7 +856,7 @@ int main(int argc, char **argv) print_now(); printf("unknown: %s\n", recvbuf); snprintf(sendbuf, sizeof(sendbuf), "%s ", recvbuf); - if(tcp_write_string(msgsock, sendbuf)) + if (tcp_write_string(msgsock, sendbuf)) break; } } while (msgsock >= 0); -- 1.7.11.7