[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH 5 of 5] xenctx: dump pagetable
# 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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |