diff -r ab15b6853300 xen/arch/x86/domain.c --- a/xen/arch/x86/domain.c Wed Apr 13 09:18:10 2011 +0100 +++ b/xen/arch/x86/domain.c Wed Apr 13 09:44:23 2011 +0100 @@ -657,6 +657,8 @@ /* 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 @@ if ( is_hvm_domain(d) ) hvm_domain_destroy(d); + else + xfree(d->arch.pv_domain.e820); vmce_destroy_msr(d); pci_release_devices(d); diff -r ab15b6853300 xen/arch/x86/mm.c --- a/xen/arch/x86/mm.c Wed Apr 13 09:18:10 2011 +0100 +++ b/xen/arch/x86/mm.c Wed Apr 13 09:44:23 2011 +0100 @@ -100,6 +100,7 @@ #include #include #include +#include #include #include #include @@ -4713,11 +4714,12 @@ { 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 @@ 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 @@ 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; } diff -r ab15b6853300 xen/include/asm-x86/domain.h --- a/xen/include/asm-x86/domain.h Wed Apr 13 09:18:10 2011 +0100 +++ b/xen/include/asm-x86/domain.h Wed Apr 13 09:44:23 2011 +0100 @@ -241,7 +241,8 @@ 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; };