]> xenbits.xensource.com Git - xen.git/commitdiff
x86: make the pv-only e820 array be dynamic.
authorKeir Fraser <keir@xen.org>
Wed, 13 Apr 2011 15:10:26 +0000 (16:10 +0100)
committerKeir Fraser <keir@xen.org>
Wed, 13 Apr 2011 15:10:26 +0000 (16:10 +0100)
During creation of the PV domain we allocate the E820 structure to
have the amount of E820 entries on the machine, plus the number three.

This will allow the tool stack to fill the E820 with more than three
entries. Specifically the use cases is , where the toolstack retrieves
the E820, sanitizes it, and then sets it for the PV guest (for PCI
passthrough), this dynamic number of E820 is just right.

Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Signed-off-by: Keir Fraser <keir@xen.org>
xen/arch/x86/domain.c
xen/arch/x86/mm.c
xen/include/asm-x86/domain.h

index 8d24dbccdcc135d3b5142447b40e80635d27528c..37c9cd7a5495b6d265d33609f9673198e731f7af 100644 (file)
@@ -657,6 +657,8 @@ int arch_domain_create(struct domain *d, unsigned int domcr_flags)
         /* 32-bit PV guest by default only if Xen is not 64-bit. */
         d->arch.is_32bit_pv = d->arch.has_32bit_shinfo =
             (CONFIG_PAGING_LEVELS != 4);
+
+        spin_lock_init(&d->arch.pv_domain.e820_lock);
     }
 
     /* initialize default tsc behavior in case tools don't */
@@ -696,6 +698,8 @@ void arch_domain_destroy(struct domain *d)
 
     if ( is_hvm_domain(d) )
         hvm_domain_destroy(d);
+    else
+        xfree(d->arch.pv_domain.e820);
 
     vmce_destroy_msr(d);
     pci_release_devices(d);
index 4ef5228c839da4b42ad6d5c1b1dd31d25cd9b337..3ddbfaa515c12adb3b7fc879b96102c28bab11e6 100644 (file)
 #include <xen/iocap.h>
 #include <xen/guest_access.h>
 #include <xen/pfn.h>
+#include <xen/xmalloc.h>
 #include <asm/paging.h>
 #include <asm/shadow.h>
 #include <asm/page.h>
@@ -4713,11 +4714,12 @@ long arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg)
     {
         struct xen_foreign_memory_map fmap;
         struct domain *d;
+        struct e820entry *e820;
 
         if ( copy_from_guest(&fmap, arg, 1) )
             return -EFAULT;
 
-        if ( fmap.map.nr_entries > ARRAY_SIZE(d->arch.pv_domain.e820) )
+        if ( fmap.map.nr_entries > E820MAX )
             return -EINVAL;
 
         rc = rcu_lock_target_domain_by_id(fmap.domid, &d);
@@ -4737,9 +4739,25 @@ long arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg)
             return -EPERM;
         }
 
-        rc = copy_from_guest(d->arch.pv_domain.e820, fmap.map.buffer,
-                             fmap.map.nr_entries) ? -EFAULT : 0;
+        e820 = xmalloc_array(e820entry_t, fmap.map.nr_entries);
+        if ( e820 == NULL )
+        {
+            rcu_unlock_domain(d);
+            return -ENOMEM;
+        }
+        
+        if ( copy_from_guest(e820, fmap.map.buffer, fmap.map.nr_entries) )
+        {
+            xfree(e820);
+            rcu_unlock_domain(d);
+            return -EFAULT;
+        }
+
+        spin_lock(&d->arch.pv_domain.e820_lock);
+        xfree(d->arch.pv_domain.e820);
+        d->arch.pv_domain.e820 = e820;
         d->arch.pv_domain.nr_e820 = fmap.map.nr_entries;
+        spin_unlock(&d->arch.pv_domain.e820_lock);
 
         rcu_unlock_domain(d);
         return rc;
@@ -4750,19 +4768,29 @@ long arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg)
         struct xen_memory_map map;
         struct domain *d = current->domain;
 
-        /* Backwards compatibility. */
-        if ( d->arch.pv_domain.nr_e820 == 0 )
-            return -ENOSYS;
-
         if ( copy_from_guest(&map, arg, 1) )
             return -EFAULT;
 
+        spin_lock(&d->arch.pv_domain.e820_lock);
+
+        /* Backwards compatibility. */
+        if ( (d->arch.pv_domain.nr_e820 == 0) ||
+             (d->arch.pv_domain.e820 == NULL) )
+        {
+            spin_unlock(&d->arch.pv_domain.e820_lock);
+            return -ENOSYS;
+        }
+
         map.nr_entries = min(map.nr_entries, d->arch.pv_domain.nr_e820);
         if ( copy_to_guest(map.buffer, d->arch.pv_domain.e820,
                            map.nr_entries) ||
              copy_to_guest(arg, &map, 1) )
+        {
+            spin_unlock(&d->arch.pv_domain.e820_lock);
             return -EFAULT;
+        }
 
+        spin_unlock(&d->arch.pv_domain.e820_lock);
         return 0;
     }
 
index 0df43726f17b47b68c9ce2ab0dbb362824bfe5bb..244338ac6b245e62539f663638cb9986cc797561 100644 (file)
@@ -241,7 +241,8 @@ struct pv_domain
     unsigned long pirq_eoi_map_mfn;
 
     /* Pseudophysical e820 map (XENMEM_memory_map).  */
-    struct e820entry e820[3];
+    spinlock_t e820_lock;
+    struct e820entry *e820;
     unsigned int nr_e820;
 };