All of lore.kernel.org
 help / color / mirror / Atom feed
From: Don Slutz <dslutz@verizon.com>
To: Andrew Cooper <andrew.cooper3@citrix.com>
Cc: Ian Campbell <ian.campbell@citrix.com>,
	Stefano Stabellini <stefano.stabellini@eu.citrix.com>,
	George Dunlap <george.dunlap@eu.citrix.com>,
	Don Slutz <Don@CloudSwitch.com>,
	Ian Jackson <ian.jackson@eu.citrix.com>,
	Don Slutz <dslutz@verizon.com>,
	xen-devel@lists.xen.org
Subject: Re: [PATCH] Add xentrace/xen_crash.
Date: Tue, 15 Oct 2013 10:53:28 -0400	[thread overview]
Message-ID: <525D56E8.8050204@terremark.com> (raw)
In-Reply-To: <525C07DD.7000206@citrix.com>

On 10/14/13 11:03, Andrew Cooper wrote:
> On 14/10/13 15:07, Don Slutz wrote:
>> From: Don Slutz <Don@CloudSwitch.com>
>>
>> This allows crash to connect to a domU. Usage:
>>
>> usage: xen_crash <domid> [<optional port>]
>>
>>    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 <dslutz@verizon.com>
> 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 <ctype.h>
>> +#include <time.h>
>> +#include <stdlib.h>
>> +#include <sys/mman.h>
>> +#include <stdio.h>
>> +#include <sys/types.h>
>> +#include <sys/socket.h>
>> +#include <sys/ioctl.h>
>> +#include <sys/time.h>
>> +#include <sys/stat.h>
>> +#include <netinet/in.h>
>> +#include <netdb.h>
>> +#include <fcntl.h>
>> +#include <unistd.h>
>> +#include <errno.h>
>> +#include <signal.h>
>> +#include <string.h>
>> +#include <inttypes.h>
>> +#include <getopt.h>
>> +
>> +#include "xenctrl.h"
>> +#include <xen/foreign/x86_32.h>
>> +#include <xen/foreign/x86_64.h>
>> +#include <xen/hvm/save.h>
>> +
>> +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 <domid> [<optional port>]\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 <FAIL>", p1, file);
>> +                }
>> +            }
>> +            else
>> +            {
>> +                snprintf(sendbuf, sizeof(sendbuf), "%s %s <FAIL>", 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 <FAIL>", p1, p2);
>> +            if (RTTcpWrite(msgsock, sendbuf, strlen(sendbuf)))
>> +                break;
>> +        }
>> +        else if (STRNEQ(recvbuf, "PROC_VERSION"))
>> +        {
>> +            /*
>> +             * Perform the detection.
>> +             */
>> +            snprintf(sendbuf, sizeof(sendbuf), "<FAIL>");
>> +            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 <FAIL>", 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:
>> + */

  reply	other threads:[~2013-10-15 14:53 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-10-14 14:07 [PATCH] Add xentrace/xen_crash Don Slutz
2013-10-14 14:11 ` Don Slutz
2013-10-14 15:03 ` Andrew Cooper
2013-10-15 14:53   ` Don Slutz [this message]
2013-10-14 15:13 ` Ian Campbell
2013-10-15 15:25   ` Don Slutz
2013-10-15 15:47     ` Ian Campbell
2013-10-15 16:26       ` Don Slutz
2013-10-14 16:56 ` David Vrabel
2013-10-15 14:50   ` Don Slutz
2013-10-23 17:24     ` Konrad Rzeszutek Wilk

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=525D56E8.8050204@terremark.com \
    --to=dslutz@verizon.com \
    --cc=Don@CloudSwitch.com \
    --cc=andrew.cooper3@citrix.com \
    --cc=george.dunlap@eu.citrix.com \
    --cc=ian.campbell@citrix.com \
    --cc=ian.jackson@eu.citrix.com \
    --cc=stefano.stabellini@eu.citrix.com \
    --cc=xen-devel@lists.xen.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.