[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] Add support to xenctx for printing stack traces on x86_32 and x86_64.



# HG changeset patch
# User Ian.Campbell@xxxxxxxxxxxxx
# Node ID 0bb5205fa6adb7db6787ff12a0987916e35afc70
# Parent  2f4dff8ec8645c00bf411568c2409332c1b02b9c
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>

xen-unstable cset: 8d5d4d58407f7071ee1dc0cc2418ffce508d8c1c
committer: Robert Read <robert@xxxxxxxxxxxxx>

diff -r 2f4dff8ec864 -r 0bb5205fa6ad tools/libxc/Makefile
--- a/tools/libxc/Makefile      Fri Dec 30 10:55:19 2005
+++ b/tools/libxc/Makefile      Thu Dec 22 06: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 2f4dff8ec864 -r 0bb5205fa6ad tools/libxc/xenctrl.h
--- a/tools/libxc/xenctrl.h     Fri Dec 30 10:55:19 2005
+++ b/tools/libxc/xenctrl.h     Thu Dec 22 06:33:19 2005
@@ -415,6 +415,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 2f4dff8ec864 -r 0bb5205fa6ad tools/xentrace/Makefile
--- a/tools/xentrace/Makefile   Fri Dec 30 10:55:19 2005
+++ b/tools/xentrace/Makefile   Thu Dec 22 06: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 2f4dff8ec864 -r 0bb5205fa6ad tools/xentrace/xenctx.c
--- a/tools/xentrace/xenctx.c   Fri Dec 30 10:55:19 2005
+++ b/tools/xentrace/xenctx.c   Thu Dec 22 06: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 2f4dff8ec864 -r 0bb5205fa6ad tools/libxc/xc_pagetab.c
--- /dev/null   Fri Dec 30 10:55:19 2005
+++ b/tools/libxc/xc_pagetab.c  Thu Dec 22 06: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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.