From mboxrd@z Thu Jan 1 00:00:00 1970 From: Don Slutz Subject: Re: [PATCH] Add xentrace/xen_crash. Date: Tue, 15 Oct 2013 10:53:28 -0400 Message-ID: <525D56E8.8050204@terremark.com> References: <1381759647-29797-1-git-send-email-dslutz@verizon.com> <525C07DD.7000206@citrix.com> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii"; Format="flowed" Content-Transfer-Encoding: 7bit Return-path: In-Reply-To: <525C07DD.7000206@citrix.com> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org To: Andrew Cooper Cc: Ian Campbell , Stefano Stabellini , George Dunlap , Don Slutz , Ian Jackson , Don Slutz , xen-devel@lists.xen.org List-Id: xen-devel@lists.xenproject.org On 10/14/13 11:03, Andrew Cooper wrote: > On 14/10/13 15:07, Don Slutz wrote: >> From: Don Slutz >> >> This allows crash to connect to a domU. Usage: >> >> usage: xen_crash [] >> >> xen_crash 1& >> crash localhost:5001 /usr/lib/debug/lib/modules/3.8.11-100.fc17.x86_64/vmlinux >> >> The domU will be paused while crash is connected. Currently the code exits when crash disconnects. >> >> Signed-off-by: Don Slutz > This looks good in principle. > > However, I am not sure tools/xentrace/ is an appropriate place for it, > as it is unrelated to xentrace. I was not sure either. Parts are based on xenctx which is here. > Also, the name "xen_crash" is a bit too generic, and implies its purpose > is to crash a guest, rather than to attach `crash` to a guest. > > What about xen-crashd, as it is a daemon? That would be fine with me. > > ~Andrew -Don Slutz >> --- >> .gitignore | 1 + >> tools/xentrace/Makefile | 5 +- >> tools/xentrace/xen_crash.c | 697 ++++++++++++++++++++++++++++++++++++++++++++ >> 3 files changed, 702 insertions(+), 1 deletions(-) >> create mode 100644 tools/xentrace/xen_crash.c >> >> diff --git a/.gitignore b/.gitignore >> index 3253675..51226f5 100644 >> --- a/.gitignore >> +++ b/.gitignore >> @@ -278,6 +278,7 @@ tools/xenstore/xs_watch_stress >> tools/xentrace/xentrace_setsize >> tools/xentrace/tbctl >> tools/xentrace/xenctx >> +tools/xentrace/xen_crash >> tools/xentrace/xentrace >> tools/xm-test/ramdisk/buildroot >> tools/xm-test/aclocal.m4 >> diff --git a/tools/xentrace/Makefile b/tools/xentrace/Makefile >> index 63b09c0..a2313c6 100644 >> --- a/tools/xentrace/Makefile >> +++ b/tools/xentrace/Makefile >> @@ -7,7 +7,7 @@ CFLAGS += $(CFLAGS_libxenctrl) >> LDLIBS += $(LDLIBS_libxenctrl) >> >> BIN = xentrace xentrace_setsize >> -LIBBIN = xenctx >> +LIBBIN = xenctx xen_crash >> SCRIPTS = xentrace_format >> MAN1 = $(wildcard *.1) >> MAN8 = $(wildcard *.8) >> @@ -40,6 +40,9 @@ xentrace: xentrace.o >> xenctx: xenctx.o >> $(CC) $(LDFLAGS) -o $@ $< $(LDLIBS) $(APPEND_LDFLAGS) >> >> +xen_crash: xen_crash.o >> + $(CC) $(LDFLAGS) -o $@ $< $(LDLIBS) $(APPEND_LDFLAGS) >> + >> xentrace_setsize: setsize.o >> $(CC) $(LDFLAGS) -o $@ $< $(LDLIBS) $(APPEND_LDFLAGS) >> >> diff --git a/tools/xentrace/xen_crash.c b/tools/xentrace/xen_crash.c >> new file mode 100644 >> index 0000000..6a4bb34 >> --- /dev/null >> +++ b/tools/xentrace/xen_crash.c >> @@ -0,0 +1,697 @@ >> +/****************************************************************************** >> + * tools/xentrace/xen_crash.c >> + * >> + * Connect crash to DOMu. >> + * >> + * Copyright (C) 2012 by Cloud Switch, Inc. >> + * >> + */ >> + >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> + >> +#include "xenctrl.h" >> +#include >> +#include >> +#include >> + >> +xc_interface *xc_handle = 0; >> +int domid = 0; >> +int debug = 0; >> + >> +typedef unsigned long long guest_word_t; >> +#define FMT_32B_WORD "%08llx" >> +#define FMT_64B_WORD "%016llx" >> + >> +/* Word-length of the guest's own data structures */ >> +int guest_word_size = sizeof (unsigned long); >> +/* Word-length of the context record we get from xen */ >> +int ctxt_word_size = sizeof (unsigned long); >> +int guest_protected_mode = 1; >> + >> +#define MACHINE_TYPE "X86_64" >> + >> +#define STRNEQ(A, B) (B && \ >> + (strncmp((char *)(A), (char *)(B), strlen((char *)(B))) == 0)) >> +#define FAILMSG "FAIL " >> +#define DONEMSG "DONE " >> +#define DATAMSG "DATA " >> + >> +#define DATA_HDRSIZE 13 /* strlen("XXXX ") + strlen("0131072") + NULL */ >> + >> +#define BUFSIZE 127 >> +#define READBUFSIZE DATA_HDRSIZE + XC_PAGE_SIZE >> + >> +#define MAX_REMOTE_FDS 10 >> + >> +void >> +print_now(void) >> +{ >> + struct timeval tp; >> + struct timezone tzp; >> + char *timeout; >> + int imil; >> + >> + gettimeofday(&tp, &tzp); >> + timeout = ctime(&tp.tv_sec); >> + imil = tp.tv_usec / 1000; >> + timeout += 4; /* Skip day of week */ >> + *(timeout + 3) = 0; /* Trim at space after month */ >> + *(timeout + 6) = 0; /* Trim at space after day */ >> + *(timeout + 15) = 0; /* Trim at seconds. */ >> + *(timeout + 20) = 0; /* Trim after year. */ >> + printf("%s %s %s %s.%.3d ", timeout + 4, timeout, timeout + 18, >> + timeout + 7, imil); >> +} >> + >> +int >> +RTTcpWrite(int Sock, const void *pvBuffer, size_t cbBuffer) >> +{ >> + if (debug & 4) { >> + print_now(); >> + printf("rtn: %s\n", (char*)pvBuffer); >> + } >> + do >> + { >> + size_t cbNow = cbBuffer; >> + ssize_t cbWritten = send(Sock, (const char *)pvBuffer, cbNow, MSG_NOSIGNAL); >> + >> + if (cbWritten < 0) >> + return 1; >> + cbBuffer -= cbWritten; >> + pvBuffer = (char *)pvBuffer + cbWritten; >> + } while (cbBuffer); >> + >> + return 0; >> +} >> + >> + >> +static void * >> +map_page(int vcpu, guest_word_t phys) >> +{ >> + static unsigned long previous_mfn = 0; >> + static void *mapped = NULL; >> + >> + unsigned long mfn = phys >> XC_PAGE_SHIFT; >> + unsigned long offset = phys & ~XC_PAGE_MASK; >> + >> + if (mapped && mfn == previous_mfn) >> + goto out; >> + >> + if (mapped) >> + munmap(mapped, XC_PAGE_SIZE); >> + >> + previous_mfn = mfn; >> + >> + mapped = xc_map_foreign_range(xc_handle, domid, XC_PAGE_SIZE, PROT_READ, mfn); >> + >> + if (mapped == NULL) { >> + if (debug & 2) { >> + print_now(); >> + printf("failed to map page for %08llx.\n", phys); >> + } >> + return NULL; >> + } >> + >> + out: >> + return (void *)(mapped + offset); >> +} >> + >> +static int >> +copy_phys(int vcpu, char * pvDst, size_t cb, guest_word_t phys) >> +{ >> + void * localAddr; >> + size_t cbPage = XC_PAGE_SIZE - (phys & ~XC_PAGE_MASK); >> + >> + /* optimize for the case where access is completely within the first page. */ >> + localAddr = map_page(vcpu, phys); >> + if (!localAddr) { >> + return 2; >> + } >> + if (cb <= cbPage) { >> + memcpy(pvDst, localAddr, cb); >> + return 0; >> + } >> + memcpy(pvDst, localAddr, cbPage); >> + pvDst += cbPage; >> + phys += cbPage; >> + cb -= cbPage; >> + >> + /* Max transfer is XC_PAGE_SIZE... */ >> + if (cb > XC_PAGE_SIZE) >> + return 1; >> + localAddr = map_page(vcpu, phys); >> + if (!localAddr) { >> + return 3; >> + } >> + memcpy(pvDst, localAddr, cb); >> + return 0; >> +} >> + >> +static guest_word_t >> +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; >> +} >> + >> +static int >> +copy_virt(int vcpu, char * pvDst, size_t cb, guest_word_t virt) >> +{ >> + void * localAddr; >> + unsigned long mfn = xc_translate_foreign_address(xc_handle, domid, vcpu, virt); >> + unsigned long offset = virt & ~XC_PAGE_MASK; >> + guest_word_t phys = (mfn << XC_PAGE_SHIFT) + offset; >> + size_t cbPage = XC_PAGE_SIZE - offset; >> + >> + /* optimize for the case where access is completely within the first page. */ >> + >> + localAddr = map_page(vcpu, phys); >> + if (!localAddr) { >> + return 2; >> + } >> + if (cb <= cbPage) { >> + memcpy(pvDst, localAddr, cb); >> + return 0; >> + } >> + memcpy(pvDst, localAddr, cbPage); >> + pvDst += cbPage; >> + phys += cbPage; >> + cb -= cbPage; >> + >> + /* Max transfer is XC_PAGE_SIZE... */ >> + if (cb > XC_PAGE_SIZE) >> + return 1; >> + localAddr = map_page(vcpu, phys); >> + if (!localAddr) { >> + return 3; >> + } >> + memcpy(pvDst, localAddr, cb); >> + return 0; >> +} >> + >> +int main(int argc, char **argv) >> +{ >> + int port=5001; >> + int sock; >> + unsigned int length; >> + struct sockaddr_in server; >> + int msgsock; >> + int nfds; >> + int reuseaddr; >> + int count; >> + int pass; >> + int i; >> + char recvbuf[BUFSIZE + 1]; >> + char sendbuf[READBUFSIZE + 1]; >> + int fds[MAX_REMOTE_FDS]; >> + size_t cbRead = 0; >> + >> + int ret; >> + int vcpu; >> + vcpu_guest_context_any_t ctx; >> + xc_dominfo_t dominfo; >> + struct hvm_hw_cpu cpuctx; >> + >> + if (argc < 2 || argc > 4) { >> + printf("usage: xen_crash []\n"); >> + exit(-1); >> + } >> + >> + domid = atoi(argv[1]); >> + if (domid==0) { >> + fprintf(stderr, "cannot trace dom0\n"); >> + exit(-1); >> + } >> + >> + if (argc > 2) >> + port = atoi(argv[2]); >> + if (argc > 3) >> + debug = atoi(argv[3]); >> + >> + signal(SIGPIPE, SIG_IGN); >> + >> + sock = socket(AF_INET, SOCK_STREAM, 0); >> + if (sock < 0) { >> + perror("socket()"); >> + exit(1); >> + } >> + reuseaddr = 1; >> + if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&reuseaddr, >> + sizeof reuseaddr) < 0) { >> + perror("setsockopt()"); >> + exit(2); >> + } >> + server.sin_family = AF_INET; >> + server.sin_addr.s_addr = INADDR_ANY; >> + server.sin_port = htons(port); >> + count = -1; >> + errno = EADDRINUSE; >> + for (pass=0; (errno == EADDRINUSE) && (count < 0); pass++) { >> + if ((count = bind(sock, (struct sockaddr *) & server, sizeof server)) < >> + 0) { >> + if (errno != EADDRINUSE) { >> + /* printf("Errno is %d\n", errno); */ >> + perror("bind()"); >> + exit(3); >> + } >> + sleep(1); /* Waiting for kernel... */ >> + } >> + } >> + length = sizeof server; >> + if (getsockname(sock, (struct sockaddr *) & server, &length) < 0) { >> + perror("getsockname()"); >> + exit(4); >> + } >> + print_now(); >> + if (pass == 1) >> + printf("Socket ready on port %d after 1 bind call\n", port); >> + else >> + printf("Socket ready on port %d after %d bind calls\n", port, pass); >> + listen(sock, 1); >> + msgsock = accept(sock, NULL, NULL); >> + if (msgsock == -1) >> + perror("accept()"); >> + else { >> + print_now(); >> + printf("Accepted a connection.\n"); >> + close(sock); /* All done for now */ >> + errno = 0; /* Just in case */ >> + nfds = msgsock + 1; >> + } >> + >> + xc_handle = xc_interface_open(0,0,0); /* for accessing control interface */ >> + >> + ret = xc_domain_getinfo(xc_handle, domid, 1, &dominfo); >> + if (ret < 0) { >> + perror("xc_domain_getinfo"); >> + exit(-1); >> + } >> + >> + ret = xc_domain_pause(xc_handle, domid); >> + if (ret < 0) { >> + perror("xc_domain_pause"); >> + exit(-1); >> + } >> + >> + vcpu = 0; >> + ret = xc_vcpu_getcontext(xc_handle, domid, vcpu, &ctx); >> + if (ret < 0) { >> + if (!dominfo.paused) >> + xc_domain_unpause(xc_handle, domid); >> + perror("xc_vcpu_getcontext"); >> + exit(-1); >> + } >> + >> + if (dominfo.hvm) { >> + xen_capabilities_info_t xen_caps = ""; >> + if (xc_domain_hvm_getcontext_partial( >> + xc_handle, domid, HVM_SAVE_CODE(CPU), >> + vcpu, &cpuctx, sizeof cpuctx) != 0) { >> + perror("xc_domain_hvm_getcontext_partial"); >> + exit(-1); >> + } >> + guest_word_size = (cpuctx.msr_efer & 0x400) ? 8 : 4; >> + guest_protected_mode = (cpuctx.cr0 & 0x1); >> + /* HVM guest context records are always host-sized */ >> + if (xc_version(xc_handle, XENVER_capabilities, &xen_caps) != 0) { >> + perror("xc_version"); >> + exit(-1); >> + } >> + ctxt_word_size = (strstr(xen_caps, "xen-3.0-x86_64")) ? 8 : 4; >> + } else { >> + struct xen_domctl domctl; >> + memset(&domctl, 0, sizeof domctl); >> + domctl.domain = domid; >> + domctl.cmd = XEN_DOMCTL_get_address_size; >> + if (xc_domctl(xc_handle, &domctl) == 0) >> + ctxt_word_size = guest_word_size = domctl.u.address_size.size / 8; >> + } >> + >> + for (i = 0; i < MAX_REMOTE_FDS; i++) >> + fds[i] = -1; >> + >> + do { >> + cbRead = recv(msgsock, recvbuf, BUFSIZE, MSG_NOSIGNAL); >> + if (cbRead <= 0) { >> + close(msgsock); >> + msgsock = -1; >> + break; >> + } >> + recvbuf[cbRead] = 0; >> + >> + if (debug & 1) { >> + print_now(); >> + printf("req: %s\n", recvbuf); >> + } >> + >> + if (STRNEQ(recvbuf, "READ_LIVE")) >> + { >> + char *p1, *p2, *p3, *p4; >> + int rc2 = 0; >> + guest_word_t addr; >> + int fid; >> + int len; >> + >> + p1 = strtok(recvbuf, " "); /* READ_LIVE */ >> + p1 = strtok(NULL, " "); /* fid */ >> + p2 = strtok(NULL, " "); /* paddress or vaddress */ >> + p3 = strtok(NULL, " "); /* length */ >> + p4 = strtok(NULL, " "); /* vaddress or vcpu */ >> + >> + fid = atoi(p1); >> + addr = strtoull(p2, NULL, 16); >> + len = atoi(p3); >> + if (len < 0 || len > XC_PAGE_SIZE) >> + { >> + print_now(); >> + 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; >> + } >> + >> + if (len) >> + { >> + if (p4 && (fds[fid] == 3)) { >> + int myCpu = atoi(p4); >> + guest_word_t pAddr = convert_to_phys(myCpu, addr); >> + >> + if (debug & 2) { >> + print_now(); >> + printf("copy_virt(%d,,%d, 0x%llx)[%s %s %s %s] pAddr=0x%lx\n", >> + myCpu, len, addr, p1, p2, p3, p4, (long)pAddr); >> + } >> + rc2 = copy_virt(myCpu, &sendbuf[DATA_HDRSIZE], len, addr); >> + } else { >> + if (debug & 2) { >> + print_now(); >> + printf("copy_phys(%d,,%d, 0x%llx)[%s %s %s]\n", >> + vcpu, len, addr, p1, p2, p3); >> + } >> + rc2 = copy_phys(vcpu, &sendbuf[DATA_HDRSIZE], len, addr); >> + } >> + if (rc2) { >> + if (debug & 2) { >> + print_now(); >> + printf("Failed rc2=%d\n", rc2); >> + } >> + len = 0; >> + } >> + } >> + >> + if (!len) { >> + snprintf(sendbuf, sizeof(sendbuf), "%s%07ld", FAILMSG, (ulong)rc2); >> + } else { >> + snprintf(sendbuf, sizeof(sendbuf), "%s%07ld", DONEMSG, (ulong)len); >> + } >> + if (RTTcpWrite(msgsock, sendbuf, len + DATA_HDRSIZE)) >> + break; >> + } >> + else if (STRNEQ(recvbuf, "FETCH_LIVE_IP_SP_BP ")) >> + { >> + char *p1, *p2; >> + int cpu; >> + long g2ip = 0; >> + short g2cs = 0; >> + short g2ss = 0; >> + long g2sp = 0; >> + long g2bp = 0; >> + >> + p1 = strtok(recvbuf, " "); /* FETCH_LIVE_IP_SP_BP */ >> + p2 = strtok(NULL, " "); /* cpu */ >> + >> + cpu = atoi(p2); >> + if (cpu != vcpu) { >> + vcpu = cpu; >> + ret = xc_vcpu_getcontext(xc_handle, domid, vcpu, &ctx); >> + if (ret < 0) { >> + if (!dominfo.paused) >> + xc_domain_unpause(xc_handle, domid); >> + perror("xc_vcpu_getcontext"); >> + exit(-1); >> + } >> + if (dominfo.hvm) { >> + if (xc_domain_hvm_getcontext_partial( >> + xc_handle, domid, HVM_SAVE_CODE(CPU), >> + vcpu, &cpuctx, sizeof cpuctx) != 0) { >> + perror("xc_domain_hvm_getcontext_partial"); >> + exit(-1); >> + } >> + } >> + } >> + >> + if (ctxt_word_size == 4) { >> + struct cpu_user_regs_x86_32 * regs = &(ctx.x32.user_regs); >> + >> + g2ip = regs->eip; >> + g2sp = regs->esp; >> + g2bp = regs->ebp; >> + g2cs = regs->cs; >> + g2ss = regs->ss; >> + } else { >> + struct cpu_user_regs_x86_64 * regs = &(ctx.x64.user_regs); >> + >> + if (dominfo.hvm) { >> + g2ip = cpuctx.rip; >> + g2sp = cpuctx.rsp; >> + g2bp = cpuctx.rbp; >> + g2cs = cpuctx.cs_sel; >> + g2ss = cpuctx.ss_sel; >> + if (debug & 0x100) { >> + if (g2ip != regs->rip) { >> + printf("g2ip(%lx) != rip(%lx)\n", g2ip, regs->rip); >> + } >> + if (g2sp != regs->rsp) { >> + printf("g2sp(%lx) != rsp(%lx)\n", g2sp, regs->rsp); >> + } >> + if (g2bp != regs->rbp) { >> + printf("g2bp(%lx) != rbp(%lx)\n", g2bp, regs->rbp); >> + } >> + if (g2cs != regs->cs) { >> + printf("g2cs(%x) != cs(%x)\n", g2cs, regs->cs); >> + } >> + if (g2ss != regs->ss) { >> + printf("g2ss(%x) != ss(%x)\n", g2ss, regs->ss); >> + } >> + } >> + } else { >> + g2ip = regs->rip; >> + g2sp = regs->rsp; >> + g2bp = regs->rbp; >> + g2cs = regs->cs; >> + g2ss = regs->ss; >> + } >> + } >> + >> + snprintf(sendbuf, sizeof(sendbuf), "%s %d %04x:%lx %04x:%lx %lx", >> + p1, cpu, g2cs, g2ip, g2ss, g2sp, g2bp); >> + if (RTTcpWrite(msgsock, sendbuf, strlen(sendbuf))) >> + break; >> + } >> + else if (STRNEQ(recvbuf, "FETCH_LIVE_CR3 ")) >> + { >> + char *p1, *p2; >> + int cpu; >> + long g2cr3 = 0; >> + >> + p1 = strtok(recvbuf, " "); /* FETCH_LIVE_CR3 */ >> + p2 = strtok(NULL, " "); /* cpu */ >> + >> + cpu = atoi(p2); >> + if (cpu != vcpu) { >> + vcpu = cpu; >> + ret = xc_vcpu_getcontext(xc_handle, domid, vcpu, &ctx); >> + if (ret < 0) { >> + if (!dominfo.paused) >> + xc_domain_unpause(xc_handle, domid); >> + perror("xc_vcpu_getcontext"); >> + exit(-1); >> + } >> + if (dominfo.hvm) { >> + if (xc_domain_hvm_getcontext_partial( >> + xc_handle, domid, HVM_SAVE_CODE(CPU), >> + vcpu, &cpuctx, sizeof cpuctx) != 0) { >> + perror("xc_domain_hvm_getcontext_partial"); >> + exit(-1); >> + } >> + } >> + } >> + >> + if (ctxt_word_size == 4) { >> + g2cr3 = ctx.x32.ctrlreg[3]; >> + } else { >> + if (dominfo.hvm) { >> + g2cr3 = cpuctx.cr3; >> + if (debug & 0x100) { >> + if (g2cr3 != ctx.x64.ctrlreg[3]) { >> + printf("g2cr3(%lx) != cr3(%lx)\n", g2cr3, ctx.x64.ctrlreg[3]); >> + } >> + } >> + } else { >> + g2cr3 = ctx.x64.ctrlreg[3]; >> + } >> + } >> + >> + snprintf(sendbuf, sizeof(sendbuf), "%s %d %lx", >> + p1, cpu, g2cr3); >> + if (RTTcpWrite(msgsock, sendbuf, strlen(sendbuf))) >> + break; >> + } >> + else if (STRNEQ(recvbuf, "MACHINE_PID")) >> + { >> + snprintf(sendbuf, sizeof(sendbuf), "%s %s %d", >> + recvbuf, MACHINE_TYPE, 0); >> + if (RTTcpWrite(msgsock, sendbuf, strlen(sendbuf))) >> + break; >> + } >> + else if (STRNEQ(recvbuf, "VTOP")) >> + { >> + char *p1, *p2, *p3; >> + int cpu; >> + guest_word_t vAddr, pAddr; >> + >> + p1 = strtok(recvbuf, " "); /* VTOP */ >> + p2 = strtok(NULL, " "); /* cpu */ >> + p3 = strtok(NULL, " "); /* vaddress */ >> + >> + cpu = atoi(p2); >> + vAddr = strtoull(p3, NULL, 16); >> + >> + pAddr = convert_to_phys(cpu, vAddr); >> + >> + snprintf(sendbuf, sizeof(sendbuf), "%s %d %lx %lx", >> + p1, cpu, (long)vAddr, (long)pAddr); >> + if (RTTcpWrite(msgsock, sendbuf, strlen(sendbuf))) >> + break; >> + } >> + else if (STRNEQ(recvbuf, "OPEN ")) >> + { >> + char *p1; >> + char *file; >> + >> + p1 = strtok(recvbuf, " "); /* OPEN */ >> + file = strtok(NULL, " "); /* filename */ >> + >> + for (i = 0; i < MAX_REMOTE_FDS; i++) { >> + if (fds[i] == -1) >> + break; >> + } >> + >> + if (i < MAX_REMOTE_FDS) { >> + if (STRNEQ(file, "/dev/mem")) >> + { >> + fds[i] = 1; >> + snprintf(sendbuf, sizeof(sendbuf), "%s %s %d O_RDONLY %lld", p1, file, i, 1024LL * 1024LL * 1024LL * 1024LL); >> + } >> + else if (STRNEQ(file, "/dev/kmem")) >> + { >> + fds[i] = 2; >> + snprintf(sendbuf, sizeof(sendbuf), "%s %s %d O_RDONLY %lld", p1, file, i, 1024LL * 1024LL * 1024LL * 1024LL); >> + } >> + else if (STRNEQ(file, "/dev/vmem")) >> + { >> + fds[i] = 3; >> + snprintf(sendbuf, sizeof(sendbuf), "%s %s %d O_RDONLY %lld", p1, file, i, 1024LL * 1024LL * 1024LL * 1024LL); >> + } >> + else >> + { >> + snprintf(sendbuf, sizeof(sendbuf), "%s %s ", p1, file); >> + } >> + } >> + else >> + { >> + snprintf(sendbuf, sizeof(sendbuf), "%s %s ", p1, file); >> + } >> + if (RTTcpWrite(msgsock, sendbuf, strlen(sendbuf))) >> + break; >> + } >> + else if (STRNEQ(recvbuf, "CLOSE ")) >> + { >> + char *p1, *p2; >> + >> + p1 = strtok(recvbuf, " "); /* SIZE */ >> + p2 = strtok(NULL, " "); /* filename id */ >> + snprintf(sendbuf, sizeof(sendbuf), "%s %s ", p1, p2); >> + if (RTTcpWrite(msgsock, sendbuf, strlen(sendbuf))) >> + break; >> + } >> + else if (STRNEQ(recvbuf, "PROC_VERSION")) >> + { >> + /* >> + * Perform the detection. >> + */ >> + snprintf(sendbuf, sizeof(sendbuf), ""); >> + if (RTTcpWrite(msgsock, sendbuf, strlen(sendbuf))) >> + break; >> + } >> + else if (STRNEQ(recvbuf, "PAGESIZE LIVE")) >> + { >> + snprintf(sendbuf, sizeof(sendbuf), "%s %ld XEN %d", >> + recvbuf, XC_PAGE_SIZE, dominfo.max_vcpu_id + 1); >> + if (RTTcpWrite(msgsock, sendbuf, strlen(sendbuf))) >> + break; >> + } >> + else if (STRNEQ(recvbuf, "EXIT")) >> + { >> + snprintf(sendbuf, sizeof(sendbuf), "%s OK", recvbuf); >> + RTTcpWrite(msgsock, sendbuf, strlen(sendbuf)); >> + break; >> + } >> + else >> + { >> + print_now(); >> + printf("unknown: %s\n", recvbuf); >> + snprintf(sendbuf, sizeof(sendbuf), "%s ", recvbuf); >> + if(RTTcpWrite(msgsock, sendbuf, strlen(sendbuf))) >> + break; >> + } >> + } while (msgsock >= 0); >> + if (msgsock >= 0) >> + close(msgsock); >> + >> + if (!dominfo.paused) { >> + ret = xc_domain_unpause(xc_handle, domid); >> + if (ret < 0) { >> + perror("xc_domain_unpause"); >> + exit(-1); >> + } >> + } >> + >> + xc_interface_close(xc_handle); >> + if (ret < 0) { >> + perror("xc_interface_close"); >> + exit(-1); >> + } >> + >> + return 0; >> +} >> + >> +/* >> + * Local variables: >> + * mode: C >> + * c-set-style: "BSD" >> + * c-basic-offset: 4 >> + * tab-width: 4 >> + * indent-tabs-mode: nil >> + * End: >> + */