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

[Xen-devel] [PATCH 5 of 5] xenctx: dump pagetable


  • To: xen-devel@xxxxxxxxxxxxxxxxxxx
  • From: Olaf Hering <olaf@xxxxxxxxx>
  • Date: Mon, 20 Jun 2011 17:27:01 +0200
  • Delivery-date: Mon, 20 Jun 2011 08:32:39 -0700
  • List-id: Xen developer discussion <xen-devel.lists.xensource.com>

# HG changeset patch
# User Olaf Hering <olaf@xxxxxxxxx>
# Date 1308582353 -7200
# Node ID 0443de5faea9b904b92219b3b804dec147697366
# Parent  ddf16ea954876d8af371f9751fc06eb4c9e78b36
xenctx: dump pagetable

This change is buggy...

diff -r ddf16ea95487 -r 0443de5faea9 tools/xentrace/xenctx.c
--- a/tools/xentrace/xenctx.c   Fri Jun 17 14:22:56 2011 +0200
+++ b/tools/xentrace/xenctx.c   Mon Jun 20 17:05:53 2011 +0200
@@ -25,21 +25,34 @@
 #include <getopt.h>
 
 #include "xenctrl.h"
+#include "xg_private.h"
+#include "xc_private.h"
 #include <xen/foreign/x86_32.h>
 #include <xen/foreign/x86_64.h>
 #include <xen/hvm/save.h>
 
+#define CR4_PAE 0x20
+#define EFER_LMA 0x400
+
 static struct xenctx {
     xc_interface *xc_handle;
     int domid;
     int frame_ptrs;
     int stack_trace;
+    int dump_pagetable;
     int disp_all;
     int all_vcpus;
     int self_paused;
     xc_dominfo_t dominfo;
 } xenctx;
 
+struct cpuctx {
+    vcpu_guest_context_any_t any;
+#if defined(__i386__) || defined(__x86_64__)
+    struct hvm_hw_cpu hvm;
+#endif
+} cpuctx;
+
 #if defined (__i386__) || defined (__x86_64__)
 typedef unsigned long long guest_word_t;
 #define FMT_32B_WORD "%08llx"
@@ -436,6 +449,184 @@ static guest_word_t frame_pointer(vcpu_g
         return ctx->x64.user_regs.rbp;
 }
 
+static void walk_l1(int vcpu, uint64_t l1, uint64_t virt)
+{
+    uint64_t *map;
+    unsigned long long e, l1e, phys_mask = ~(-1ull << 52) & (-1ull << 12);
+    char buf[123];
+    fflush(stdout);
+    map = xc_map_foreign_range(xenctx.xc_handle, xenctx.domid, PAGE_SIZE, 
PROT_READ, l1 >> PAGE_SHIFT);
+    if (!map) {
+        perror("xc_map_foreign_range l1");
+        return;
+    }
+    for (e = 0; e < L1_PAGETABLE_ENTRIES_X86_64; e++) {
+        l1e = map[e];
+        if (!l1e)
+            continue;
+        buf[0] = '\0';
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %c", l1e & ( 
1ull << 63) ? 'X' : 'x'); /* NX */
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %3llx", (l1e 
>> 52) & ~( 1ull << 11)); /* Available */
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %12llx", l1e 
& phys_mask); /* phys base adress */
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %llx", (l1e 
>> 9) & 0x7); /* Available */
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %c", l1e & 
_PAGE_GLOBAL ? 'G' : 'g');
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %c", l1e & 
_PAGE_PAT ? 'P' : 'p');
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %c", l1e & 
_PAGE_PSE ? 'S' : 's');
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %c", l1e & 
_PAGE_DIRTY ? 'D' : 'd');
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %c", l1e & 
_PAGE_ACCESSED ? 'A' : 'a');
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %c", l1e & 
_PAGE_PCD ? 'C' : 'c');
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %c", l1e & 
_PAGE_PWT ? 'T' : 't');
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %c", l1e & 
_PAGE_USER ? 'U' : 'u');
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %c", l1e & 
_PAGE_RW ? 'W' : 'w');
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %c", l1e & 
_PAGE_PRESENT ? 'P' : 'p');
+        printf("%3d l1e %3llx %016llx: %s %16llx\n", vcpu, e, l1e, buf, 
(unsigned long long)virt | (e << L1_PAGETABLE_SHIFT_X86_64));
+    }
+    munmap(map, PAGE_SIZE);
+}
+
+static void walk_l2(int vcpu, uint64_t l2, uint64_t virt)
+{
+    uint64_t *map;
+    unsigned long long e, l2e, l1_mask = ~(-1ull << 52) & (-1ull << 12);
+    char buf[123];
+    fflush(stdout);
+    map = xc_map_foreign_range(xenctx.xc_handle, xenctx.domid, PAGE_SIZE, 
PROT_READ, l2 >> PAGE_SHIFT);
+    if (!map) {
+        perror("xc_map_foreign_range l2");
+        return;
+    }
+    for (e = 0; e < L2_PAGETABLE_ENTRIES_X86_64; e++) {
+        l2e = map[e];
+        if (!l2e)
+            continue;
+        buf[0] = '\0';
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %c", l2e & ( 
1ull << 63) ? 'X' : 'x'); /* NX */
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %3llx", (l2e 
>> 52) & ~( 1ull << 11)); /* Available */
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %12llx", l2e 
& l1_mask); /* l1 base adress */
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %llx", (l2e 
>> 9) & 0x7); /* Available */
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %llx", (l2e 
>> 8) & 0x1); /* Ignored */
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %c", (l2e >> 
7) & 0x1 ? 'S' : 's'); /* SP */
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %llx", (l2e 
>> 6) & 0x1); /* Ignored */
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %c", l2e & 
_PAGE_ACCESSED ? 'A' : 'a');
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %c", l2e & 
_PAGE_PCD ? 'C' : 'c');
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %c", l2e & 
_PAGE_PWT ? 'T' : 't');
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %c", l2e & 
_PAGE_USER ? 'U' : 'u');
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %c", l2e & 
_PAGE_RW ? 'W' : 'w');
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %c", l2e & 
_PAGE_PRESENT ? 'P' : 'p');
+        printf("%3d l2e %3llx %016llx: %s\n", vcpu, e, l2e, buf);
+        if (l2e & _PAGE_PRESENT)
+            walk_l1(vcpu, l2e & l1_mask, virt | (e << 
L2_PAGETABLE_SHIFT_X86_64));
+    }
+    munmap(map, PAGE_SIZE);
+}
+
+static void walk_l3(int vcpu, uint64_t l3, uint64_t virt)
+{
+    uint64_t *map;
+    unsigned long long e, l3e, l2_mask = ~(-1ull << 52) & (-1ull << 12);
+    char buf[123];
+    fflush(stdout);
+    map = xc_map_foreign_range(xenctx.xc_handle, xenctx.domid, PAGE_SIZE, 
PROT_READ, l3 >> PAGE_SHIFT);
+    if (!map) {
+        perror("xc_map_foreign_range l3");
+        return;
+    }
+    for (e = 0; e < L3_PAGETABLE_ENTRIES_X86_64; e++) {
+        l3e = map[e];
+        if (!l3e)
+            continue;
+        buf[0] = '\0';
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %c", l3e & ( 
1ull << 63) ? 'X' : 'x'); /* NX */
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %3llx", (l3e 
>> 52) & ~( 1ull << 11)); /* Available */
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %12llx", l3e 
& l2_mask); /* l2 base adress */
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %llx", (l3e 
>> 9) & 0x7); /* Available */
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %llx", (l3e 
>> 8) & 0x1); /* MBZ */
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %c", (l3e >> 
7) & 0x1 ? 'S' : 's'); /* SP */
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %llx", (l3e 
>> 6) & 0x1); /* Ignored */
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %c", l3e & 
_PAGE_ACCESSED ? 'A' : 'a');
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %c", l3e & 
_PAGE_PCD ? 'C' : 'c');
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %c", l3e & 
_PAGE_PWT ? 'T' : 't');
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %c", l3e & 
_PAGE_USER ? 'U' : 'u');
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %c", l3e & 
_PAGE_RW ? 'W' : 'w');
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %c", l3e & 
_PAGE_PRESENT ? 'P' : 'p');
+        printf("%3d l3e %3llx %016llx: %s\n", vcpu, e, l3e, buf);
+        if (l3e & _PAGE_PRESENT)
+            walk_l2(vcpu, l3e & l2_mask, virt | (e << 
L3_PAGETABLE_SHIFT_X86_64));
+    }
+    munmap(map, PAGE_SIZE);
+}
+
+static void walk_l4(int vcpu, uint64_t l4)
+{
+    uint64_t *map;
+    unsigned long long e, l4e, l3_mask = ~(-1ull << 52) & (-1ull << 12), virt 
= 0;
+    char buf[123];
+    fflush(stdout);
+    map = xc_map_foreign_range(xenctx.xc_handle, xenctx.domid, PAGE_SIZE, 
PROT_READ, l4 >> PAGE_SHIFT);
+    if (!map) {
+        perror("xc_map_foreign_range l4");
+        return;
+    }
+    for (e = 0; e < L4_PAGETABLE_ENTRIES_X86_64; e++) {
+        l4e = map[e];
+        if (!l4e)
+            continue;
+        buf[0] = '\0';
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %c", l4e & ( 
1ull << 63) ? 'X' : 'x'); /* NX */
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %3llx", (l4e 
>> 52) & ~( 1ull << 11)); /* Available */
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %12llx", l4e 
& l3_mask); /* l3 base adress */
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %llx", (l4e 
>> 9) & 0x7); /* Available */
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %llx", (l4e 
>> 7) & 0x3); /* MBZ */
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %llx", (l4e 
>> 6) & 0x1); /* Ignored */
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %c", l4e & 
_PAGE_ACCESSED ? 'A' : 'a');
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %c", l4e & 
_PAGE_PCD ? 'C' : 'c');
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %c", l4e & 
_PAGE_PWT ? 'T' : 't');
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %c", l4e & 
_PAGE_USER ? 'u' : 'u');
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %c", l4e & 
_PAGE_RW ? 'W' : 'w');
+        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %c", l4e & 
_PAGE_PRESENT ? 'P' : 'p');
+        printf("%3d l4e %3llx %016llx: %s\n", vcpu, e, l4e, buf);
+        if (l4e & _PAGE_PRESENT)
+            walk_l3(vcpu, l4e & l3_mask, virt | (e << 
L4_PAGETABLE_SHIFT_X86_64));
+    }
+    munmap(map, PAGE_SIZE);
+}
+
+static void dump_pagetable(struct cpuctx *cpuctx, int vcpu)
+{
+    uint64_t paddr;
+    int pt_levels, size;
+
+    printf("\npagetable for vcpu %d\n", vcpu);
+    /* What kind of paging are we dealing with? */
+    if (xenctx.dominfo.hvm) {
+        if (!guest_protected_mode) {
+            printf("protected mode disabled\n");
+            return;
+        }
+        pt_levels = (cpuctx->hvm.msr_efer & EFER_LMA) ? 4 : (cpuctx->hvm.cr4 & 
CR4_PAE) ? 3 : 2;
+        paddr = cpuctx->hvm.cr3 & ((pt_levels == 3) ? ~0x1full : ~0xfffull);
+    } else {
+        if (guest_word_size == 8) {
+            pt_levels = 4;
+            paddr = cpuctx->any.x64.ctrlreg[3] & ~0xfffull;
+        } else {
+            pt_levels = 3;
+            paddr = ((uint64_t) xen_cr3_to_pfn(cpuctx->any.x32.ctrlreg[3])) << 
PAGE_SHIFT;
+        }
+    }
+
+    size = (pt_levels == 2 ? 4 : 8);
+    if (pt_levels == 4) {
+        walk_l4(vcpu, paddr);
+    } else if (pt_levels == 3) {
+        walk_l3(vcpu, paddr, 0);
+    } else {
+        walk_l2(vcpu, paddr, 0);
+    }
+    printf("\n");
+    fflush(stdout);
+}
+
 #elif defined(__ia64__)
 
 #define PTE_ED_SHIFT              52
@@ -853,9 +1044,11 @@ static int print_stack(vcpu_guest_contex
 
 static void dump_ctx(int vcpu)
 {
-    vcpu_guest_context_any_t ctx;
+    struct cpuctx cpuctx;
 
-    if (xc_vcpu_getcontext(xenctx.xc_handle, xenctx.domid, vcpu, &ctx) < 0) {
+    memset(&cpuctx, 0, sizeof(cpuctx));
+
+    if (xc_vcpu_getcontext(xenctx.xc_handle, xenctx.domid, vcpu, &cpuctx.any) 
< 0) {
         perror("xc_vcpu_getcontext");
         return;
     }
@@ -863,16 +1056,15 @@ static void dump_ctx(int vcpu)
 #if defined(__i386__) || defined(__x86_64__)
     {
         if (xenctx.dominfo.hvm) {
-            struct hvm_hw_cpu cpuctx;
             xen_capabilities_info_t xen_caps = "";
             if (xc_domain_hvm_getcontext_partial(
                     xenctx.xc_handle, xenctx.domid, HVM_SAVE_CODE(CPU),
-                    vcpu, &cpuctx, sizeof cpuctx) != 0) {
+                    vcpu, &cpuctx.hvm, sizeof (cpuctx.hvm)) != 0) {
                 perror("xc_domain_hvm_getcontext_partial");
                 return;
             }
-            guest_word_size = (cpuctx.msr_efer & 0x400) ? 8 : 4;
-            guest_protected_mode = (cpuctx.cr0 & CR0_PE);
+            guest_word_size = (cpuctx.hvm.msr_efer & EFER_LMA) ? 8 : 4;
+            guest_protected_mode = (cpuctx.hvm.cr0 & CR0_PE);
             /* HVM guest context records are always host-sized */
             if (xc_version(xenctx.xc_handle, XENVER_capabilities, &xen_caps) 
!= 0) {
                 perror("xc_version");
@@ -890,14 +1082,18 @@ static void dump_ctx(int vcpu)
     }
 #endif
 
-    print_ctx(&ctx);
+    print_ctx(&cpuctx.any);
 #ifndef NO_TRANSLATION
-    if (print_code(&ctx, vcpu))
+    if (print_code(&cpuctx.any, vcpu))
         return;
-    if (is_kernel_text(instr_pointer(&ctx)))
-        if (print_stack(&ctx, vcpu, guest_word_size))
+    if (is_kernel_text(instr_pointer(&cpuctx.any)))
+        if (print_stack(&cpuctx.any, vcpu, guest_word_size))
             return;
 #endif
+#if defined(__i386__) || defined(__x86_64__)
+    if (xenctx.dump_pagetable)
+        dump_pagetable(&cpuctx, vcpu);
+#endif
 }
 
 static void dump_all_vcpus(void)
@@ -926,6 +1122,10 @@ static void usage(void)
     printf("  -s SYMTAB, --symbol-table=SYMTAB\n");
     printf("                    read symbol table from SYMTAB.\n");
     printf("  -S --stack-trace  print a complete stack trace.\n");
+#if defined(__i386__) || defined(__x86_64__)
+    printf("  -P --dump-pagetable\n");
+    printf("                    print a complete pagetable for the given 
vcpu.\n");
+#endif
     printf("  -k, --kernel-start\n");
     printf("                    set user/kernel split. (default 
0xc0000000)\n");
 #ifdef __ia64__
@@ -941,7 +1141,7 @@ int main(int argc, char **argv)
 {
     int ch;
     int ret;
-    static const char *sopts = "fs:hak:SC"
+    static const char *sopts = "fs:hak:SPC"
 #ifdef __ia64__
         "r:"
 #endif
@@ -951,6 +1151,9 @@ int main(int argc, char **argv)
         {"symbol-table", 1, NULL, 's'},
         {"frame-pointers", 0, NULL, 'f'},
         {"kernel-start", 1, NULL, 'k'},
+#if defined(__i386__) || defined(__x86_64__)
+        {"dump-pagetable", 0, NULL, 'P'},
+#endif
 #ifdef __ia64__
         {"regs", 1, NULL, 'r'},
 #endif
@@ -974,6 +1177,11 @@ int main(int argc, char **argv)
         case 'S':
             xenctx.stack_trace = 1;
             break;
+#if defined(__i386__) || defined(__x86_64__)
+        case 'P':
+            xenctx.dump_pagetable = 1;
+            break;
+#endif
 #ifdef __ia64__
         case 'r':
             {

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


 


Rackspace

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