[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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.