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