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-devel

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

To: xen-devel@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-devel] [PATCH 5 of 5] xenctx: dump pagetable
From: Olaf Hering <olaf@xxxxxxxxx>
Date: Mon, 20 Jun 2011 17:27:01 +0200
Delivery-date: Mon, 20 Jun 2011 08:32:39 -0700
Dkim-signature: v=1; a=rsa-sha1; c=relaxed/relaxed; t=1308583621; l=13279; s=domk; d=aepfle.de; h=To:From:Date:References:In-Reply-To:Subject: Content-Transfer-Encoding:MIME-Version:Content-Type:X-RZG-CLASS-ID: X-RZG-AUTH; bh=ZP3/ecYTpHTtg4pw6N0+lj72fN8=; b=Npf5IGXljtKHaxhI3YL7R3KqbPlf0/sedenHCdrGT7ZGGGcDX1251Y5/IesCMa/AvAq wGy8IW+nhDA9ND/I9D/b6EHHlvHISmWXt+tyF3mLP3zycJ9BEpURCkVS19/SC9OsZg23l qurX1Mz62Vt8Ud8sMoUngGdOyw64RwE/wdU=
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
In-reply-to: <patchbomb.1308583616@xxxxxxxxxxxx>
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
References: <patchbomb.1308583616@xxxxxxxxxxxx>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Mercurial-patchbomb/1.7.5
# 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