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