WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] Add support to xenctx for printing stack traces on x86_3

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] Add support to xenctx for printing stack traces on x86_32 and x86_64.
From: Xen patchbot -unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Thu, 22 Dec 2005 18:18:07 +0000
Delivery-date: Thu, 22 Dec 2005 18:21:14 +0000
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Ian.Campbell@xxxxxxxxxxxxx
# Node ID 8d5d4d58407f7071ee1dc0cc2418ffce508d8c1c
# Parent  934470721c46e85651a364ab5d8369e8fde8798d
Add support to xenctx for printing stack traces on x86_32 and x86_64.

To support this add xc_translate_foreign_address to libxc. This function
walks page tables and translates virtual addresses using a given domain
and vcpu page table.

Signed-off-by: Ian Campbell <Ian.Campbell@xxxxxxxxxxxxx>

diff -r 934470721c46 -r 8d5d4d58407f tools/libxc/Makefile
--- a/tools/libxc/Makefile      Wed Dec 21 19:18:19 2005
+++ b/tools/libxc/Makefile      Thu Dec 22 14:33:19 2005
@@ -27,6 +27,11 @@
 ifeq ($(XEN_TARGET_ARCH),x86_32)
 SRCS       += xc_ptrace.c
 SRCS       += xc_ptrace_core.c
+SRCS       += xc_pagetab.c
+endif
+
+ifeq ($(XEN_TARGET_ARCH),x86_64)
+SRCS       += xc_pagetab.c
 endif
 
 BUILD_SRCS :=
diff -r 934470721c46 -r 8d5d4d58407f tools/libxc/xenctrl.h
--- a/tools/libxc/xenctrl.h     Wed Dec 21 19:18:19 2005
+++ b/tools/libxc/xenctrl.h     Thu Dec 22 14:33:19 2005
@@ -416,6 +416,19 @@
 void *xc_map_foreign_batch(int xc_handle, uint32_t dom, int prot,
                            unsigned long *arr, int num );
 
+/**
+ * Translates a virtual address in the context of a given domain and
+ * vcpu returning the machine page frame number of the associated
+ * page.
+ *
+ * @parm xc_handle a handle on an open hypervisor interface
+ * @parm dom the domain to perform the translation in
+ * @parm vcpu the vcpu to perform the translation on
+ * @parm virt the virtual address to translate
+ */
+unsigned long xc_translate_foreign_address(int xc_handle, uint32_t dom,
+                                          int vcpu, unsigned long long virt);
+
 int xc_get_pfn_list(int xc_handle, uint32_t domid, unsigned long *pfn_buf, 
                     unsigned long max_pfns);
 
diff -r 934470721c46 -r 8d5d4d58407f tools/xentrace/Makefile
--- a/tools/xentrace/Makefile   Wed Dec 21 19:18:19 2005
+++ b/tools/xentrace/Makefile   Thu Dec 22 14:33:19 2005
@@ -15,25 +15,29 @@
 OBJS     = $(patsubst %.c,%.o,$(wildcard *.c))
 
 BIN      = xentrace tbctl setsize
+LIBBIN   = xenctx
 SCRIPTS  = xentrace_format
 MAN1     = $(wildcard *.1)
 MAN8     = $(wildcard *.8)
 
 all: build
-build: $(BIN)
+build: $(BIN) $(LIBBIN)
 
 install: build
        [ -d $(DESTDIR)/usr/bin ] || $(INSTALL_DIR) $(DESTDIR)/usr/bin
+       [ -d $(DESTDIR)/usr/$(LIBDIR)/xen/bin ] || \
+               $(INSTALL_DIR) $(DESTDIR)/usr/$(LIBDIR)/xen/bin
        [ -d $(DESTDIR)/usr/share/man/man1 ] || \
                $(INSTALL_DIR) $(DESTDIR)/usr/share/man/man1
        [ -d $(DESTDIR)/usr/share/man/man8 ] || \
                $(INSTALL_DIR) $(DESTDIR)/usr/share/man/man8
        $(INSTALL_PROG) $(BIN) $(SCRIPTS) $(DESTDIR)/usr/bin
+       $(INSTALL_PROG) $(LIBBIN) $(DESTDIR)/usr/$(LIBDIR)/xen/bin
        $(INSTALL_DATA) $(MAN1) $(DESTDIR)/usr/share/man/man1
        $(INSTALL_DATA) $(MAN8) $(DESTDIR)/usr/share/man/man8
 
 clean:
-       $(RM) *.a *.so *.o *.rpm $(BIN)
+       $(RM) *.a *.so *.o *.rpm $(BIN) $(LIBBIN)
 
 %: %.c $(HDRS) Makefile
        $(CC) $(CFLAGS) -o $@ $< -L$(XEN_LIBXC) -lxenctrl
diff -r 934470721c46 -r 8d5d4d58407f tools/xentrace/xenctx.c
--- a/tools/xentrace/xenctx.c   Wed Dec 21 19:18:19 2005
+++ b/tools/xentrace/xenctx.c   Thu Dec 22 14:33:19 2005
@@ -20,15 +20,184 @@
 #include <errno.h>
 #include <argp.h>
 #include <signal.h>
+#include <string.h>
+#include <getopt.h>
 
 #include "xenctrl.h"
+
+int xc_handle = 0;
+int domid = 0;
+int frame_ptrs = 0;
+int stack_trace = 0;
+
+#if defined (__i386__)
+#define FMT_SIZE_T             "%08x"
+#define STACK_POINTER(regs)    (regs->esp)
+#define FRAME_POINTER(regs)    (regs->ebp)
+#define INSTR_POINTER(regs)    (regs->eip)
+#define STACK_ROWS             4
+#define STACK_COLS             8
+#elif defined (__x86_64__)
+#define FMT_SIZE_T             "%016lx"
+#define STACK_POINTER(regs)    (regs->rsp)
+#define FRAME_POINTER(regs)    (regs->rbp)
+#define INSTR_POINTER(regs)    (regs->rip)
+#define STACK_ROWS             4
+#define STACK_COLS             4
+#endif
+
+struct symbol {
+    size_t address;
+    char type;
+    char *name;
+    struct symbol *next;
+} *symbol_table = NULL;
+
+size_t kernel_stext, kernel_etext, kernel_sinittext, kernel_einittext;
+
+int is_kernel_text(size_t addr)
+{
+#if defined (__i386__)
+    if (symbol_table == NULL)
+        return (addr > 0xc000000);
+#elif defined (__x86_64__)
+    if (symbol_table == NULL)
+        return (addr > 0xffffffff80000000UL);
+#endif
+
+    if (addr >= kernel_stext &&
+        addr <= kernel_etext)
+        return 1;
+    if (addr >= kernel_sinittext &&
+        addr <= kernel_einittext)
+        return 1;
+    return 0;
+}
+
+void free_symbol(struct symbol *symbol)
+{
+    if (symbol == NULL)
+        return;
+    if (symbol->name)
+        free(symbol->name);
+    free(symbol);
+}
+
+void insert_symbol(struct symbol *symbol)
+{
+    static struct symbol *prev = NULL;
+    struct symbol *s = symbol_table;
+
+    if (s == NULL) {
+        symbol_table = symbol;
+        symbol->next = NULL;
+        return;
+    }
+
+    /* The System.map is usually already sorted... */
+    if (prev
+        && prev->address < symbol->address
+        && (!prev->next || prev->next->address > symbol->address)) {
+        s = prev;
+    } else {
+        /* ... otherwise do crappy/slow search for the correct place */
+        while(s && s->next && s->next->address < symbol->address)
+            s = s->next;
+    }
+
+    symbol->next = s->next;
+    s->next = symbol;
+    prev = symbol;
+}
+
+struct symbol *lookup_symbol(size_t address)
+{
+    struct symbol *s = symbol_table;
+
+    while(s && s->next && s->next->address < address)
+        s = s->next;
+
+    if (s && s->address < address)
+        return s;
+
+    return NULL;
+}
+
+void print_symbol(size_t addr)
+{
+    struct symbol *s;
+
+    if (!is_kernel_text(addr))
+        return;
+
+    s = lookup_symbol(addr);
+
+    if (s==NULL)
+        return;
+
+    if (addr==s->address)
+        printf("%s", s->name);
+    else
+        printf("%s+%#x", s->name, (unsigned int)(addr - s->address));
+}
+
+void read_symbol_table(const char *symtab)
+{
+    char line[256];
+    char *p;
+    struct symbol *symbol;
+    FILE *f;
+
+    f = fopen(symtab, "r");
+    if(f == NULL) {
+        fprintf(stderr, "failed to open symbol table %s\n", symtab);
+        exit(-1);
+    }
+
+    while(!feof(f)) {
+        if(fgets(line,256,f)==NULL)
+            break;
+
+        symbol = malloc(sizeof(*symbol));
+
+        /* need more checks for syntax here... */
+        symbol->address = strtoull(line, &p, 16);
+        p++;
+        symbol->type = *p++;
+        p++;
+
+        /* in the future we should handle the module name
+         * being appended here, this would allow us to use
+         * /proc/kallsyms as our symbol table
+         */
+        if (p[strlen(p)-1] == '\n')
+            p[strlen(p)-1] = '\0';
+        symbol->name = strdup(p);
+
+        insert_symbol(symbol);
+
+        if (strcmp(symbol->name, "_stext") == 0)
+            kernel_stext = symbol->address;
+        else if (strcmp(symbol->name, "_etext") == 0)
+            kernel_etext = symbol->address;
+        else if (strcmp(symbol->name, "_sinittext") == 0)
+            kernel_sinittext = symbol->address;
+        else if (strcmp(symbol->name, "_einittext") == 0)
+            kernel_einittext = symbol->address;
+    }
+
+    fclose(f);
+}
 
 #ifdef __i386__
 void print_ctx(vcpu_guest_context_t *ctx1)
 {
     struct cpu_user_regs *regs = &ctx1->user_regs;
 
-    printf("eip: %08x\t", regs->eip);
+    printf("eip: %08x ", regs->eip);
+    print_symbol(regs->eip);
+    printf("\n");
+
     printf("esp: %08x\n", regs->esp);
 
     printf("eax: %08x\t", regs->eax);
@@ -51,7 +220,9 @@
 {
     struct cpu_user_regs *regs = &ctx1->user_regs;
 
-    printf("rip: %08lx\t", regs->rip);
+    printf("rip: %08lx ", regs->rip);
+    print_symbol(regs->rip);
+    printf("\n");
     printf("rsp: %08lx\n", regs->rsp);
 
     printf("rax: %08lx\t", regs->rax);
@@ -63,8 +234,8 @@
     printf("rdi: %08lx\t", regs->rdi);
     printf("rbp: %08lx\n", regs->rbp);
 
-    printf("r8: %08lx\t", regs->r8);
-    printf("r9: %08lx\t", regs->r9);
+    printf(" r8: %08lx\t", regs->r8);
+    printf(" r9: %08lx\t", regs->r9);
     printf("r10: %08lx\t", regs->r10);
     printf("r11: %08lx\n", regs->r11);
 
@@ -81,35 +252,238 @@
 }
 #endif
 
-void dump_ctx(uint32_t domid, uint32_t vcpu)
+void *map_page(vcpu_guest_context_t *ctx, int vcpu, size_t virt)
+{
+    static unsigned long previous_mfn = 0;
+    static void *mapped = NULL;
+
+    unsigned long mfn = xc_translate_foreign_address(xc_handle, domid, vcpu, 
virt);
+    unsigned long offset = virt & ~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) {
+        fprintf(stderr, "failed to map page.\n");
+        exit(-1);
+    }
+
+ out:
+    return (void *)(mapped + offset);
+}
+
+void print_stack(vcpu_guest_context_t *ctx, int vcpu)
+{
+    struct cpu_user_regs *regs = &ctx->user_regs;
+    size_t stack = STACK_POINTER(regs);
+    size_t stack_limit = (STACK_POINTER(regs) & XC_PAGE_MASK) + XC_PAGE_SIZE;
+    size_t frame;
+    size_t instr;
+    size_t *p;
+    int i;
+
+    printf("\n");
+    printf("Stack:\n");
+    for (i=1; i<STACK_ROWS+1 && stack < stack_limit; i++) {
+        while(stack < stack_limit && stack < STACK_POINTER(regs) + 
i*STACK_COLS*sizeof(stack)) {
+            p = map_page(ctx, vcpu, stack);
+            printf(" " FMT_SIZE_T, *p);
+            stack += sizeof(stack);
+        }
+        printf("\n");
+    }
+    printf("\n");
+
+    printf("Code:\n");
+    instr = INSTR_POINTER(regs) - 21;
+    for(i=0; i<32; i++) {
+        unsigned char *c = map_page(ctx, vcpu, instr+i);
+        if (instr+i == INSTR_POINTER(regs))
+            printf("<%02x> ", *c);
+        else
+            printf("%02x ", *c);
+    }
+    printf("\n");
+
+    printf("\n");
+
+    if(stack_trace)
+        printf("Stack Trace:\n");
+    else
+        printf("Call Trace:\n");
+    printf("%c [<" FMT_SIZE_T ">] ", stack_trace ? '*' : ' ', 
INSTR_POINTER(regs));
+
+    print_symbol(INSTR_POINTER(regs));
+    printf(" <--\n");
+    if (frame_ptrs) {
+        stack = STACK_POINTER(regs);
+        frame = FRAME_POINTER(regs);
+        while(frame && stack < stack_limit) {
+            if (stack_trace) {
+                while (stack < frame) {
+                    p = map_page(ctx, vcpu, stack);
+                    printf("|   " FMT_SIZE_T "   ", *p);
+                    printf("\n");
+                    stack += sizeof(*p);
+                }
+            } else {
+                stack = frame;
+            }
+
+            p = map_page(ctx, vcpu, stack);
+            frame = *p;
+            if (stack_trace)
+                printf("|-- " FMT_SIZE_T "\n", *p);
+            stack += sizeof(*p);
+
+            if (frame) {
+                p = map_page(ctx, vcpu, stack);
+                printf("%c [<" FMT_SIZE_T ">] ", stack_trace ? '|' : ' ', *p);
+                print_symbol(*p);
+                printf("\n");
+                stack += sizeof(*p);
+            }
+        }
+    } else {
+        stack = STACK_POINTER(regs);
+        while(stack < stack_limit) {
+            p = map_page(ctx, vcpu, stack);
+            if (is_kernel_text(*p)) {
+                printf("  [<" FMT_SIZE_T ">] ", *p);
+                print_symbol(*p);
+                printf("\n");
+            } else if (stack_trace) {
+                printf("    " FMT_SIZE_T "\n", *p);
+            }
+            stack += sizeof(*p);
+        }
+    }
+}
+
+void dump_ctx(int vcpu)
 {
     int ret;
     vcpu_guest_context_t ctx;
 
-    int xc_handle = xc_interface_open(); /* for accessing control interface */
+    xc_handle = xc_interface_open(); /* for accessing control interface */
+
+    ret = xc_domain_pause(xc_handle, domid);
+    if (ret < 0) {
+        perror("xc_domain_pause");
+        exit(-1);
+    }
 
     ret = xc_domain_get_vcpu_context(xc_handle, domid, vcpu, &ctx);
-    if (ret != 0) {
+    if (ret < 0) {
+        xc_domain_unpause(xc_handle, domid);
         perror("xc_domain_get_vcpu_context");
         exit(-1);
     }
+
     print_ctx(&ctx);
+    if (is_kernel_text(ctx.user_regs.eip))
+        print_stack(&ctx, vcpu);
+
+    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);
+    }
+}
+
+void usage(void)
+{
+    printf("usage:\n\n");
+
+    printf("  xenctx [options] <DOMAIN> [VCPU]\n\n");
+
+    printf("options:\n");
+    printf("  -f, --frame-pointers\n");
+    printf("                    assume the kernel was compiled with\n");
+    printf("                    frame pointers.\n");
+    printf("  -s SYMTAB, --symbol-table=SYMTAB\n");
+    printf("                    read symbol table from SYMTAB.\n");
+    printf("  --stack-trace     print a complete stack trace.\n");
 }
 
 int main(int argc, char **argv)
 {
+    int ch;
+    const char *sopts = "fs:h";
+    const struct option lopts[] = {
+        {"stack-trace", 0, NULL, 'S'},
+        {"symbol-table", 1, NULL, 's'},
+        {"frame-pointers", 0, NULL, 'f'},
+        {"help", 0, NULL, 'h'},
+        {0, 0, 0, 0}
+    };
+    const char *symbol_table = NULL;
+
     int vcpu = 0;
 
-    if (argc < 2) {
-        printf("usage: xenctx <domid> <optional vcpu>\n");
-        exit(-1);
-    }
-
-    if (argc == 3)
-        vcpu = atoi(argv[2]);
-
-    dump_ctx(atoi(argv[1]), vcpu);
+    while ((ch = getopt_long(argc, argv, sopts, lopts, NULL)) != -1) {
+        switch(ch) {
+        case 'f':
+            frame_ptrs = 1;
+            break;
+        case 's':
+            symbol_table = optarg;
+            break;
+        case 'S':
+            stack_trace = 1;
+            break;
+        case 'h':
+            usage();
+            exit(-1);
+        case '?':
+            fprintf(stderr, "%s --help for more options\n", argv[0]);
+            exit(-1);
+        }
+    }
+
+    argv += optind; argc -= optind;
+
+    if (argc < 1 || argc > 2) {
+        printf("usage: xenctx [options] <domid> <optional vcpu>\n");
+        exit(-1);
+    }
+
+    domid = atoi(argv[0]);
+    if (domid==0) {
+            fprintf(stderr, "cannot trace dom0\n");
+            exit(-1);
+    }
+
+    if (argc == 2)
+        vcpu = atoi(argv[1]);
+
+    if (symbol_table)
+        read_symbol_table(symbol_table);
+
+    dump_ctx(vcpu);
 
     return 0;
 }
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff -r 934470721c46 -r 8d5d4d58407f tools/libxc/xc_pagetab.c
--- /dev/null   Wed Dec 21 19:18:19 2005
+++ b/tools/libxc/xc_pagetab.c  Thu Dec 22 14:33:19 2005
@@ -0,0 +1,192 @@
+/******************************************************************************
+ * xc_pagetab.c
+ *
+ * Function to translate virtual to physical addresses.
+ */
+#include "xc_private.h"
+
+#if defined(__i386__)
+
+#define L1_PAGETABLE_SHIFT_PAE 12
+#define L2_PAGETABLE_SHIFT_PAE 21
+#define L3_PAGETABLE_SHIFT_PAE 30
+
+#define L1_PAGETABLE_SHIFT             12
+#define L2_PAGETABLE_SHIFT             22
+
+#define L0_PAGETABLE_MASK_PAE  0x0000000ffffff000ULL
+#define L1_PAGETABLE_MASK_PAE  0x1ffULL
+#define L2_PAGETABLE_MASK_PAE  0x1ffULL
+#define L3_PAGETABLE_MASK_PAE  0x3ULL
+
+#define L0_PAGETABLE_MASK              0xfffff000ULL
+#define L1_PAGETABLE_MASK              0x3ffULL
+#define L2_PAGETABLE_MASK              0x3ffULL
+
+#elif defined(__x86_64__)
+
+#define L1_PAGETABLE_SHIFT_PAE 12
+#define L2_PAGETABLE_SHIFT_PAE 21
+#define L3_PAGETABLE_SHIFT_PAE 30
+#define L4_PAGETABLE_SHIFT_PAE 39
+
+#define L1_PAGETABLE_SHIFT             L1_PAGETABLE_SHIFT_PAE
+#define L2_PAGETABLE_SHIFT             L2_PAGETABLE_SHIFT_PAE
+
+#define L0_PAGETABLE_MASK_PAE  0x000000fffffff000ULL
+#define L1_PAGETABLE_MASK_PAE  0x1ffULL
+#define L2_PAGETABLE_MASK_PAE  0x1ffULL
+#define L3_PAGETABLE_MASK_PAE  0x1ffULL
+#define L4_PAGETABLE_MASK_PAE  0x1ffULL
+
+#define L0_PAGETABLE_MASK              L0_PAGETABLE_MASK_PAE
+#define L1_PAGETABLE_MASK              L1_PAGETABLE_MASK_PAE
+#define L2_PAGETABLE_MASK              L2_PAGETABLE_MASK_PAE
+
+#endif
+
+unsigned long xc_translate_foreign_address(int xc_handle, uint32_t dom,
+                                           int vcpu, unsigned long long virt )
+{
+    vcpu_guest_context_t ctx;
+    unsigned long long cr3;
+    void *pd, *pt, *pdppage = NULL, *pdp, *pml = NULL;
+    unsigned long long pde, pte, pdpe, pmle;
+    unsigned long mfn = 0;
+#if defined (__i386__)
+    static int pt_levels = 0;
+
+    if (pt_levels == 0) {
+        xen_capabilities_info_t xen_caps = "";
+
+        if (xc_version(xc_handle, XENVER_capabilities, &xen_caps) != 0)
+            goto out;
+        if (strstr(xen_caps, "xen-3.0-x86_64"))
+            pt_levels = 4;
+        else if (strstr(xen_caps, "xen-3.0-x86_32p"))
+            pt_levels = 3;
+        else if (strstr(xen_caps, "xen-3.0-x86_32"))
+            pt_levels = 2;
+        else
+            goto out;
+    }
+#elif defined (__x86_64__)
+#define pt_levels 4
+#endif
+
+    if (xc_domain_get_vcpu_context(xc_handle, dom, vcpu, &ctx) != 0) {
+        fprintf(stderr, "failed to retreive vcpu context\n");
+        goto out;
+    }
+    cr3 = ctx.ctrlreg[3];
+
+    /* Page Map Level 4 */
+
+#if defined(__i386__)
+    pmle = cr3;
+#elif defined(__x86_64__)
+    pml = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, PROT_READ, cr3 >> 
PAGE_SHIFT);
+    if (pml == NULL) {
+        fprintf(stderr, "failed to map PML4\n");
+        goto out;
+    }
+    pmle = *(unsigned long long *)(pml + 8 * ((virt >> L4_PAGETABLE_SHIFT_PAE) 
& L4_PAGETABLE_MASK_PAE));
+    if((pmle & 1) == 0) {
+        fprintf(stderr, "page entry not present in PML4\n");
+        goto out_unmap_pml;
+    }
+#endif
+
+    /* Page Directory Pointer Table */
+
+    if (pt_levels >= 3) {
+        pdppage = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, PROT_READ, 
pmle >> PAGE_SHIFT);
+        if (pdppage == NULL) {
+            fprintf(stderr, "failed to map PDP\n");
+            goto out_unmap_pml;
+        }
+        if (pt_levels >= 4)
+            pdp = pdppage;
+        else
+            /* PDP is only 32 bit aligned with 3 level pts */
+            pdp = pdppage + (pmle & ~(XC_PAGE_MASK | 0x1f));
+
+        pdpe = *(unsigned long long *)(pdp + 8 * ((virt >> 
L3_PAGETABLE_SHIFT_PAE) & L3_PAGETABLE_MASK_PAE));
+
+        if((pdpe & 1) == 0) {
+            fprintf(stderr, "page entry not present in PDP\n");
+            goto out_unmap_pdp;
+        }
+    } else {
+        pdpe = pmle;
+    }
+
+    /* Page Directory */
+
+    pd = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, PROT_READ, pdpe >> 
PAGE_SHIFT);
+    if (pd == NULL) {
+        fprintf(stderr, "failed to map PD\n");
+        goto out_unmap_pdp;
+    }
+
+    if (pt_levels >= 3)
+        pde = *(unsigned long long *)(pd + 8 * ((virt >> 
L2_PAGETABLE_SHIFT_PAE) & L2_PAGETABLE_MASK_PAE));
+    else
+        pde = *(unsigned long long *)(pd + 4 * ((virt >> L2_PAGETABLE_SHIFT) & 
L2_PAGETABLE_MASK));
+
+    if ((pde & 1) == 0) {
+        fprintf(stderr, "page entry not present in PD\n");
+        goto out_unmap_pd;
+    }
+
+    /* Page Table */
+
+    if (pde & 0x00000008) { /* 4M page (or 2M in PAE mode) */
+        fprintf(stderr, "Cannot currently cope with 2/4M pages\n");
+        exit(-1);
+    } else { /* 4k page */
+        pt = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, PROT_READ,
+                                  pde >> PAGE_SHIFT);
+
+        if (pt == NULL) {
+            fprintf(stderr, "failed to map PT\n");
+            goto out_unmap_pd;
+        }
+
+        if (pt_levels >= 3)
+            pte = *(unsigned long long *)(pt + 8 * ((virt >> 
L1_PAGETABLE_SHIFT_PAE) & L1_PAGETABLE_MASK_PAE));
+        else
+            pte = *(unsigned long long *)(pt + 4 * ((virt >> 
L1_PAGETABLE_SHIFT) & L1_PAGETABLE_MASK));
+
+        if ((pte & 0x00000001) == 0) {
+            fprintf(stderr, "page entry not present in PT\n");
+            goto out_unmap_pt;
+        }
+
+        if (pt_levels >= 3)
+            mfn = (pte & L0_PAGETABLE_MASK_PAE) >> PAGE_SHIFT;
+        else
+            mfn = (pte & L0_PAGETABLE_MASK) >> PAGE_SHIFT;
+    }
+
+ out_unmap_pt:
+    munmap(pt, PAGE_SIZE);
+ out_unmap_pd:
+    munmap(pd, PAGE_SIZE);
+ out_unmap_pdp:
+    munmap(pdppage, PAGE_SIZE);
+ out_unmap_pml:
+    munmap(pml, PAGE_SIZE);
+ out:
+    return mfn;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] Add support to xenctx for printing stack traces on x86_32 and x86_64., Xen patchbot -unstable <=