[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH 2 of 4] get_page_type: Print out extra information when failing to get page_type
# HG changeset patch # User Konrad Rzeszutek Wilk <konrad.wilk@xxxxxxxxxx> # Date 1345579709 14400 # Node ID 8ed3eef706710c9c476a8d984bfb2861d92bedfb # Parent 635917c6dac4ab8748572fcbeb3e745428684e15 get_page_type: Print out extra information when failing to get page_type. When any reference to __get_page_type is called and it fails, we get: (XEN) mm.c:2429:d0 Bad type (saw 1400000000000002 != exp 7000000000000000) for mfn 10e392 (pfn 1bf6c) with this patch we get some extra details such as: (XEN) debug.c:127:d0 cr3: 10d80b000, searching for 10e392 (XEN) debug.c:111:d0 cr3(10d80b000) has mfn(10e392) in level PUD/L3: [258][272] (XEN) debug.c:111:d0 cr3(10d80b000) has mfn(10e392) in level PMD/L2: [258][511][511] (XEN) debug.c:111:d0 cr3(10d80b000) has mfn(10e392) in level PGD/L4: [272] (XEN) debug.c:111:d0 cr3(10d80b000) has mfn(10e392) in level PUD/L3: [511][511] where it actually is in the pagetable of the guest. This is useful b/c we can figure out where it is, and use that to figure out where the OS thinks it is. Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@xxxxxxxxxx> diff -r 635917c6dac4 -r 8ed3eef70671 xen/arch/x86/debug.c --- a/xen/arch/x86/debug.c Tue Aug 21 16:08:29 2012 -0400 +++ b/xen/arch/x86/debug.c Tue Aug 21 16:08:29 2012 -0400 @@ -70,8 +70,127 @@ dbg_hvm_va2mfn(dbgva_t vaddr, struct dom return mfn; } +#define LEVEL_L4 4 +#define LEVEL_L3 3 +#define LEVEL_L2 2 +#define LEVEL_L1 1 +#define UNDEFINED 0 +static void dbg_print_mfn(struct domain *dp, unsigned long mfn, + int l4i, int l3i, int l2i, int l1i) +{ + char s[32]; + char *p; + static const char *const names[] = { + [LEVEL_L4] = "PGD/L4", + [LEVEL_L3] = "PUD/L3", + [LEVEL_L2] = "PMD/L2", + [LEVEL_L1] = "PTE/L1", + [UNDEFINED] = "unknown", + }; + unsigned level = 0; + p = s; + if (l4i >= 0) { + p += snprintf(p, ARRAY_SIZE(s), "[%d]", l4i); + level = LEVEL_L4; + } + if (l3i >= 0) { + p += snprintf(p, ARRAY_SIZE(s) - (p - s), "[%d]", l3i); + level = LEVEL_L3; + } + if (l2i >= 0) { + p += snprintf(p, ARRAY_SIZE(s) - (p - s), "[%d]", l2i); + level = LEVEL_L2; + } + if (l1i >= 0) { + p += snprintf(p, ARRAY_SIZE(s) - (p - s), "[%d]", l1i); + level = LEVEL_L1; + } + gdprintk(XENLOG_WARNING , "cr3(%lx) has mfn(%lx) in level %s: %s\n", + dp->vcpu[0]->arch.cr3, mfn, names[level], s); +#undef LEVEL_L4 +#undef LEVEL_L3 +#undef LEVEL_L2 +#undef LEVEL_L1 +#undef UNDEFINED +} +void +dbg_pv_mfn(unsigned long find_mfn, struct domain *dp) +{ #if defined(__x86_64__) + l4_pgentry_t l4e, *l4t; +#endif + l3_pgentry_t l3e, *l3t; + l2_pgentry_t l2e, *l2t; + l1_pgentry_t l1e, *l1t; + unsigned long cr3 = dp->vcpu[0]->arch.cr3; + int l4i, l3i, l2i, l1i; + unsigned long mfn; + gdprintk(XENLOG_WARNING , "cr3: %lx, searching for %lx\n", + dp->vcpu[0]->arch.cr3, find_mfn); + + l4i = l3i = l2i = l1i = 0; +#if defined(__x86_64__) + for ( l4i = 0; l4i < L4_PAGETABLE_ENTRIES; l4i++ ) + { + + l4t = map_domain_page(cr3 >> PAGE_SHIFT); + l4e = l4t[l4i]; + mfn = l4e_get_pfn(l4e); + if (mfn == find_mfn) + dbg_print_mfn(dp, mfn, l4i, /* L3 */-1, /* L2 */-1, /* L1 */-1); + + if ( !(l4e_get_flags(l4e) & _PAGE_PRESENT) ) + continue; + mfn = l4e_get_pfn(l4e); + unmap_domain_page(l4t); + l3t = map_domain_page(mfn); +#else + /* 32-bit start */ + l3t = map_domain_page(cr3 >> PAGE_SHIFT); + l3t += (cr3 & 0xFE0UL) >> 3; +#endif + for ( l3i = 0; l3i < L3_PAGETABLE_ENTRIES; l3i++ ) + { + l3e = l3t[l3i]; + mfn = l3e_get_pfn(l3e); + if ( mfn == find_mfn ) + dbg_print_mfn(dp, mfn, l4i, l3i, /* L2 */-1, /* L1 */-1); + + if ( !(l3e_get_flags(l3e) & _PAGE_PRESENT) ) + continue; + l2t = map_domain_page(mfn); + for ( l2i = 0; l2i < L2_PAGETABLE_ENTRIES; l2i++ ) + { + l2e = l2t[l2i]; + mfn = l2e_get_pfn(l2e); + if (mfn == find_mfn ) + dbg_print_mfn(dp, mfn, l4i, l3i, l2i, /* L1 */-1); + + if ( !(l2e_get_flags(l2e) & _PAGE_PRESENT) || + (l2e_get_flags(l2e) & _PAGE_PSE) ) + continue; + l1t = map_domain_page(mfn); + for ( l1i = 0; l1i < L1_PAGETABLE_ENTRIES; l1i ++ ) + { + l1e = l1t[l1i]; + mfn = l1e_get_pfn(l1e); + if ( !mfn_valid(mfn) ) + continue; + if ( mfn == find_mfn ) + dbg_print_mfn(dp, mfn, l4i, l3i, l2i, l1i); + } + unmap_domain_page(l1t); + } + unmap_domain_page(l2t); + } + unmap_domain_page(l3t); +#if defined(__x86_64__) + } +#endif +} + +#if defined(__x86_64__) /* * pgd3val: this is the value of init_mm.pgd[3] in a PV guest. It is optional. * This to assist debug of modules in the guest. The kernel address diff -r 635917c6dac4 -r 8ed3eef70671 xen/arch/x86/mm.c --- a/xen/arch/x86/mm.c Tue Aug 21 16:08:29 2012 -0400 +++ b/xen/arch/x86/mm.c Tue Aug 21 16:08:29 2012 -0400 @@ -2422,6 +2422,8 @@ static int __put_page_type(struct page_i } +extern void dbg_pv_mfn(unsigned long mfn, struct domain *d); + static int __get_page_type(struct page_info *page, unsigned long type, int preemptible) { @@ -2503,6 +2505,7 @@ static int __get_page_type(struct page_i "for mfn %lx (pfn %lx)", x, type, page_to_mfn(page), get_gpfn_from_mfn(page_to_mfn(page))); + dbg_pv_mfn(page_to_mfn(page), page_get_owner(page)); return -EINVAL; } else if ( unlikely(!(x & PGT_validated)) ) _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |