# HG changeset patch # User Keir Fraser # Date 1302707426 -3600 # Node ID 3f00c5faa12aed4d0993391f71b7f12cf92f0208 # Parent eb3b40bf0ba21ca518fdc0b4f86cd49228bbb853 x86: make the pv-only e820 array be dynamic. 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. [backport of c/s 23225] Signed-off-by: Konrad Rzeszutek Wilk Signed-off-by: Keir Fraser diff -r eb3b40bf0ba2 xen/arch/x86/domain.c --- a/xen/arch/x86/domain.c Tue Dec 13 14:12:56 2011 -0500 +++ b/xen/arch/x86/domain.c Tue Dec 13 14:15:01 2011 -0500 @@ -557,6 +557,8 @@ int arch_domain_create(struct domain *d, /* 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.e820_lock); } memset(d->arch.cpuids, 0, sizeof(d->arch.cpuids)); @@ -603,6 +605,8 @@ void arch_domain_destroy(struct domain * if ( is_hvm_domain(d) ) hvm_domain_destroy(d); + else + xfree(d->arch.e820); vmce_destroy_msr(d); pci_release_devices(d); diff -r eb3b40bf0ba2 xen/arch/x86/mm.c --- a/xen/arch/x86/mm.c Tue Dec 13 14:12:56 2011 -0500 +++ b/xen/arch/x86/mm.c Tue Dec 13 14:15:01 2011 -0500 @@ -99,6 +99,7 @@ #include #include #include +#include #include #include #include @@ -4667,11 +4668,12 @@ long arch_memory_op(int op, XEN_GUEST_HA { 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.e820) ) + if ( fmap.map.nr_entries > E820MAX ) return -EINVAL; rc = rcu_lock_target_domain_by_id(fmap.domid, &d); @@ -4685,9 +4687,25 @@ long arch_memory_op(int op, XEN_GUEST_HA return rc; } - rc = copy_from_guest(d->arch.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.e820_lock); + xfree(d->arch.e820); + d->arch.e820 = e820; d->arch.nr_e820 = fmap.map.nr_entries; + spin_unlock(&d->arch.e820_lock); rcu_unlock_domain(d); return rc; @@ -4698,18 +4716,28 @@ long arch_memory_op(int op, XEN_GUEST_HA struct xen_memory_map map; struct domain *d = current->domain; - /* Backwards compatibility. */ - if ( d->arch.nr_e820 == 0 ) - return -ENOSYS; - if ( copy_from_guest(&map, arg, 1) ) return -EFAULT; + spin_lock(&d->arch.e820_lock); + + /* Backwards compatibility. */ + if ( (d->arch.nr_e820 == 0) || + (d->arch.e820 == NULL) ) + { + spin_unlock(&d->arch.e820_lock); + return -ENOSYS; + } + map.nr_entries = min(map.nr_entries, d->arch.nr_e820); if ( copy_to_guest(map.buffer, d->arch.e820, map.nr_entries) || copy_to_guest(arg, &map, 1) ) + { + spin_unlock(&d->arch.e820_lock); return -EFAULT; - + } + + spin_unlock(&d->arch.e820_lock); return 0; } diff -r eb3b40bf0ba2 xen/include/asm-x86/domain.h --- a/xen/include/asm-x86/domain.h Tue Dec 13 14:12:56 2011 -0500 +++ b/xen/include/asm-x86/domain.h Tue Dec 13 14:15:01 2011 -0500 @@ -270,7 +270,8 @@ struct arch_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; /* Maximum physical-address bitwidth supported by this guest. */