[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] xc_get_pfn_list() creates broken core files



I noticed that the p2m list in domain core files was incorrect. The problem lies
in XEN_DOMCTL_getmemlist, here:

227             list_ent = d->page_list.next;
228             for ( i = 0; (i < max_pfns) && (list_ent != &d->page_list); i++ 
)
229             {
230                 mfn = page_to_mfn(list_entry(
231                     list_ent, struct page_info, list));
...
238                 list_ent = mfn_to_page(mfn)->list.next;
239             }

This does not account correctly for 'holes' where the pfn no longer maps an
mfn, and thus doesn't appear on page_list. As a result the whole array gets out
of sync. What's the right fix here? Below is what I threw together to verify
the problem.

thanks,
john

diff --git a/tools/libxc/xc_core.c b/tools/libxc/xc_core.c
--- a/tools/libxc/xc_core.c
+++ b/tools/libxc/xc_core.c
@@ -103,7 +103,12 @@ xc_domain_dumpcore_via_callback(int xc_h
 
     for ( dump_mem = dump_mem_start, i = 0; i < nr_pages; i++ )
     {
-        copy_from_domain_page(xc_handle, domid, page_array[i], dump_mem);
+       fprintf(stderr, "page_array %d is %lx\n", i, page_array[i]);
+       if (page_array[i] == -1) {
+               memset(dump_mem, 0, PAGE_SIZE);
+       } else {
+               copy_from_domain_page(xc_handle, domid, page_array[i], 
dump_mem);
+       }
         dump_mem += PAGE_SIZE;
         if ( ((i + 1) % DUMP_INCREMENT == 0) || ((i + 1) == nr_pages) )
         {
diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c
--- a/xen/arch/x86/domctl.c
+++ b/xen/arch/x86/domctl.c
@@ -215,6 +215,7 @@ long arch_do_domctl(
         struct domain *d = find_domain_by_id(domctl->domain);
         unsigned long max_pfns = domctl->u.getmemlist.max_pfns;
         unsigned long mfn, gmfn;
+       unsigned long gpfn;
         struct list_head *list_ent;
 
         ret = -EINVAL;
@@ -255,6 +256,26 @@ long arch_do_domctl(
                 {
                     mfn = page_to_mfn(list_entry(
                         list_ent, struct page_info, list));
+                    gpfn = get_gpfn_from_mfn(mfn);
+#ifdef __x86_64__
+                    if (gpfn != 0x5555555555555555L)
+#else
+                    if (gpfn != 0x55555555L)
+#endif
+                    {
+                        /* Account for unmapped gpfn's. */
+                        while (i < gpfn)
+                        {
+                            unsigned long tmp = -1;
+                            if ( 
copy_to_guest_offset(domctl->u.getmemlist.buffer,
+                                                      i, &tmp, 1) )
+                            {
+                                 ret = -EFAULT;
+                                 break;
+                            }
+                            i++;
+                        }
+                    }
                     if ( copy_to_guest_offset(domctl->u.getmemlist.buffer,
                                               i, &mfn, 1) )
                     {


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

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