xc_map_foreign_pages(), a convenient alternative to xc_map_foreign_batch()
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Fri, 7 Sep 2007 10:39:10 +0000 (11:39 +0100)
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Fri, 7 Sep 2007 10:39:10 +0000 (11:39 +0100)
xc_map_foreign_batch() can succeed partially.  It is awkward to use
when you're only interested in complete success.  Provide new
xc_map_foreign_pages() convenience function for that kind of use.
Also convert two obvious calls to use it.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
tools/ioemu/hw/cirrus_vga.c
tools/ioemu/vl.c
tools/libxc/xc_misc.c
tools/libxc/xenctrl.h
tools/xenfb/xenfb.c

index cc73390716c1a077bd890769c5a4e6350b5e2ebe..68ec0b392bac10344f063f74596c615b91a04d14 100644 (file)
@@ -2565,7 +2565,7 @@ static void *set_vram_mapping(unsigned long begin, unsigned long end)
         return NULL;
     }
 
-    vram_pointer = xc_map_foreign_batch(xc_handle, domid,
+    vram_pointer = xc_map_foreign_pages(xc_handle, domid,
                                         PROT_READ|PROT_WRITE,
                                         extent_start, nr_extents);
     if (vram_pointer == NULL) {
index b1c3cca009029a03a41e1d254db4985a24d50fba..350a1e2e2089989527985a3c7ac3f502e0b3fb09 100644 (file)
@@ -6948,7 +6948,7 @@ static void qemu_remap_bucket(struct map_cache *entry,
         j = ((i + BITS_PER_LONG) > (MCACHE_BUCKET_SIZE >> PAGE_SHIFT)) ?
             (MCACHE_BUCKET_SIZE >> PAGE_SHIFT) % BITS_PER_LONG : BITS_PER_LONG;
         while (j > 0)
-            word = (word << 1) | !(pfns[i + --j] & 0xF0000000UL);
+            word = (word << 1) | (((pfns[i + --j] >> 28) & 0xf) != 0xf);
         entry->valid_mapping[i / BITS_PER_LONG] = word;
     }
 }
index 13fa65ff18524b9e5616f308817ab7fc92eea414..ba50866b5668294482f6cfcfd898208fe8dd8bac 100644 (file)
@@ -226,6 +226,39 @@ int xc_hvm_set_pci_link_route(
     return rc;
 }
 
+void *xc_map_foreign_pages(int xc_handle, uint32_t dom, int prot,
+                           const xen_pfn_t *arr, int num)
+{
+    xen_pfn_t *pfn;
+    void *res;
+    int i;
+
+    pfn = malloc(num * sizeof(*pfn));
+    if (!pfn)
+        return NULL;
+    memcpy(pfn, arr, num * sizeof(*pfn));
+
+    res = xc_map_foreign_batch(xc_handle, dom, prot, pfn, num);
+    if (res) {
+        for (i = 0; i < num; i++) {
+            if ((pfn[i] & 0xF0000000UL) == 0xF0000000UL) {
+                /*
+                 * xc_map_foreign_batch() doesn't give us an error
+                 * code, so we have to make one up.  May not be the
+                 * appropriate one.
+                 */
+                errno = EINVAL;
+                munmap(res, num * PAGE_SIZE);
+                res = NULL;
+                break;
+            }
+        }
+    }
+
+    free(pfn);
+    return res;
+}
+
 /*
  * Local variables:
  * mode: C
index 591e6c25a3336309e07d672ed97eed9774290241..e39e899cc6b7c513676d906a2d863fe6cd1a1662 100644 (file)
@@ -646,6 +646,14 @@ void *xc_map_foreign_range(int xc_handle, uint32_t dom,
                             int size, int prot,
                             unsigned long mfn );
 
+void *xc_map_foreign_pages(int xc_handle, uint32_t dom, int prot,
+                           const xen_pfn_t *arr, int num );
+
+/**
+ * Like xc_map_foreign_pages(), except it can succeeed partially.
+ * When a page cannot be mapped, its PFN in @arr is or'ed with
+ * 0xF0000000 to indicate the error.
+ */
 void *xc_map_foreign_batch(int xc_handle, uint32_t dom, int prot,
                            xen_pfn_t *arr, int num );
 
index fcc83e63558ed620deaa95bcb619940efaca903b..e94e01eee44d8972c16a09a7c2aeff3c0018d150 100644 (file)
@@ -398,21 +398,15 @@ static int xenfb_map_fb(struct xenfb_private *xenfb, int domid)
        if (!pgmfns || !fbmfns)
                goto out;
 
-       /*
-        * Bug alert: xc_map_foreign_batch() can fail partly and
-        * return a non-null value.  This is a design flaw.  When it
-        * happens, we happily continue here, and later crash on
-        * access.
-        */
        xenfb_copy_mfns(mode, n_fbdirs, pgmfns, pd);
-       map = xc_map_foreign_batch(xenfb->xc, domid,
+       map = xc_map_foreign_pages(xenfb->xc, domid,
                                   PROT_READ, pgmfns, n_fbdirs);
        if (map == NULL)
                goto out;
        xenfb_copy_mfns(mode, n_fbmfns, fbmfns, map);
        munmap(map, n_fbdirs * XC_PAGE_SIZE);
 
-       xenfb->pub.pixels = xc_map_foreign_batch(xenfb->xc, domid,
+       xenfb->pub.pixels = xc_map_foreign_pages(xenfb->xc, domid,
                                PROT_READ | PROT_WRITE, fbmfns, n_fbmfns);
        if (xenfb->pub.pixels == NULL)
                goto out;