diff --git a/xen.spec b/xen.spec index 5a3d615..adf8869 100644 --- a/xen.spec +++ b/xen.spec @@ -51,7 +51,7 @@ Summary: Xen is a virtual machine monitor Name: xen Version: 4.6.0 -Release: 1%{?dist} +Release: 2%{?dist} Group: Development/Libraries License: GPLv2+ and LGPLv2+ and BSD URL: http://xen.org/ @@ -94,6 +94,15 @@ Patch26: qemu.git-ce317461573bac12b10d67699b4ddf1f97cf066c.patch Patch27: qemu.git-29b9f5efd78ae0f9cc02dd169b6e80d2c404bade.patch Patch28: qemu.git-0cf33fb6b49a19de32859e2cdc6021334f448fb3.patch Patch29: qemu.trad.CVE-2015-7295.patch +Patch30: xsa145.patch +Patch31: xsa146.patch +Patch32: xsa147.patch +Patch33: xsa148.patch +Patch34: xsa149.patch +Patch35: xsa150.patch +Patch36: xsa151.patch +Patch37: xsa152.patch +Patch38: xsa153-libxl.patch BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root @@ -289,6 +298,15 @@ manage Xen virtual machines. %patch27 -p1 %patch28 -p1 %patch29 -p1 +%patch30 -p1 +%patch31 -p1 +%patch32 -p1 +%patch33 -p1 +%patch34 -p1 +%patch35 -p1 +%patch36 -p1 +%patch37 -p1 +%patch38 -p1 # stubdom sources cp -v %{SOURCE10} %{SOURCE11} %{SOURCE12} %{SOURCE13} %{SOURCE14} %{SOURCE15} stubdom @@ -815,6 +833,25 @@ rm -rf %{buildroot} %endif %changelog +* Thu Oct 29 2015 Michael Young - 4.6.0-2 +- nine security updates (#1276344) + arm: Host crash when preempting a multicall [XSA-145, CVE-2015-7812] + arm: various unimplemented hypercalls log without rate limiting + [XSA-146, CVE-2015-7813] + arm: Race between domain destruction and memory allocation decrease + [XSA-147, CVE-2015-7814] + x86: Uncontrolled creation of large page mappings by PV guests + [XSA-148, CVE-2015-7835] + leak of main per-domain vcpu pointer array [XSA-149, CVE-2015-7969] + x86: Long latency populate-on-demand operation is not preemptible + [XSA-150, CVE-2015-7970] + x86: leak of per-domain profiling-related vcpu pointer array + [XSA-151, CVE-2015-7969] + x86: some pmu and profiling hypercalls log without rate limiting + [XSA-152, CVE-2015-7971] + x86: populate-on-demand balloon size inaccuracy can crash guests + [XSA-153, CVE-2015-7972] + * Sun Oct 11 2015 Michael Young - 4.6.0-1 - update to xen-4.6.0 xen-dumpdir.patch no longer needed diff --git a/xsa145.patch b/xsa145.patch new file mode 100644 index 0000000..5f7db1e --- /dev/null +++ b/xsa145.patch @@ -0,0 +1,46 @@ +xen/arm: Support hypercall_create_continuation for multicall + +Multicall for ARM has been supported since commit f0dbdc6 "xen: arm: fully +implement multicall interface.". Although, if an hypercall in multicall +requires preemption, it will crash the host: + +(XEN) Xen BUG at domain.c:347 +(XEN) ----[ Xen-4.7-unstable arm64 debug=y Tainted: C ]---- +[...] +(XEN) Xen call trace: +(XEN) [<00000000002420cc>] hypercall_create_continuation+0x64/0x380 (PC) +(XEN) [<0000000000217274>] do_memory_op+0x1b00/0x2334 (LR) +(XEN) [<0000000000250d2c>] do_multicall_call+0x114/0x124 +(XEN) [<0000000000217ff0>] do_multicall+0x17c/0x23c +(XEN) [<000000000024f97c>] do_trap_hypercall+0x90/0x12c +(XEN) [<0000000000251ca8>] do_trap_hypervisor+0xd2c/0x1ba4 +(XEN) [<00000000002582cc>] guest_sync+0x88/0xb8 +(XEN) +(XEN) +(XEN) **************************************** +(XEN) Panic on CPU 5: +(XEN) Xen BUG at domain.c:347 +(XEN) **************************************** +(XEN) +(XEN) Manual reset required ('noreboot' specified) + +Looking to the code, the support of multicall looks valid to me, as we only +need to fill call.args[...]. So drop the BUG(); + +This is XSA-145. + +Acked-by: Ian Campbell + +diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c +index 575745c..5c5ac9e 100644 +--- a/xen/arch/arm/domain.c ++++ b/xen/arch/arm/domain.c +@@ -344,8 +344,6 @@ unsigned long hypercall_create_continuation( + + if ( test_bit(_MCSF_in_multicall, &mcs->flags) ) + { +- BUG(); /* XXX multicalls not implemented yet. */ +- + __set_bit(_MCSF_call_preempted, &mcs->flags); + + for ( i = 0; *p != '\0'; i++ ) diff --git a/xsa146.patch b/xsa146.patch new file mode 100644 index 0000000..03d62f3 --- /dev/null +++ b/xsa146.patch @@ -0,0 +1,42 @@ +xen: arm: rate-limit logging from unimplemented PHYSDEVOP and HVMOP. + +These are guest accessible and should therefore be rate-limited. +Moreover, include them only in debug builds. + +This is XSA-146. + +Signed-off-by: Ian Campbell +Reviewed-by: Jan Beulich + +diff --git a/xen/arch/arm/hvm.c b/xen/arch/arm/hvm.c +index 471c4cd..1de290f 100644 +--- a/xen/arch/arm/hvm.c ++++ b/xen/arch/arm/hvm.c +@@ -57,7 +57,7 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE_PARAM(void) arg) + + default: + { +- printk("%s: Bad HVM op %ld.\n", __func__, op); ++ gdprintk(XENLOG_DEBUG, "HVMOP op=%lu: not implemented\n", op); + rc = -ENOSYS; + break; + } +diff --git a/xen/arch/arm/physdev.c b/xen/arch/arm/physdev.c +index 61b4a18..b1ba22e 100644 +--- a/xen/arch/arm/physdev.c ++++ b/xen/arch/arm/physdev.c +@@ -8,12 +8,13 @@ + #include + #include + #include ++#include + #include + + + int do_physdev_op(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg) + { +- printk("%s %d cmd=%d: not implemented yet\n", __func__, __LINE__, cmd); ++ gdprintk(XENLOG_DEBUG, "PHYSDEVOP cmd=%d: not implemented\n", cmd); + return -ENOSYS; + } + diff --git a/xsa147.patch b/xsa147.patch new file mode 100644 index 0000000..682d074 --- /dev/null +++ b/xsa147.patch @@ -0,0 +1,38 @@ +xen: arm: handle races between relinquish_memory and free_domheap_pages + +Primarily this means XENMEM_decrease_reservation from a toolstack +domain. + +Unlike x86 we have no requirement right now to queue such pages onto +a separate list, if we hit this race then the other code has already +fully accepted responsibility for freeing this page and therefore +there is no more for relinquish_memory to do. + +This is XSA-147. + +Signed-off-by: Ian Campbell +Reviewed-by: Julien Grall +Reviewed-by: Jan Beulich + +diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c +index 575745c..aac64cb 100644 +--- a/xen/arch/arm/domain.c ++++ b/xen/arch/arm/domain.c +@@ -764,8 +764,15 @@ static int relinquish_memory(struct domain *d, struct page_list_head *list) + { + /* Grab a reference to the page so it won't disappear from under us. */ + if ( unlikely(!get_page(page, d)) ) +- /* Couldn't get a reference -- someone is freeing this page. */ +- BUG(); ++ /* ++ * Couldn't get a reference -- someone is freeing this page and ++ * has already committed to doing so, so no more to do here. ++ * ++ * Note that the page must be left on the list, a list_del ++ * here will clash with the list_del done by the other ++ * party in the race and corrupt the list head. ++ */ ++ continue; + + if ( test_and_clear_bit(_PGC_allocated, &page->count_info) ) + put_page(page); diff --git a/xsa148.patch b/xsa148.patch new file mode 100644 index 0000000..3b6843a --- /dev/null +++ b/xsa148.patch @@ -0,0 +1,39 @@ +x86: guard against undue super page PTE creation + +When optional super page support got added (commit bd1cd81d64 "x86: PV +support for hugepages"), two adjustments were missed: mod_l2_entry() +needs to consider the PSE and RW bits when deciding whether to use the +fast path, and the PSE bit must not be removed from L2_DISALLOW_MASK +unconditionally. + +This is XSA-148. + +Signed-off-by: Jan Beulich +Reviewed-by: Tim Deegan + +--- a/xen/arch/x86/mm.c ++++ b/xen/arch/x86/mm.c +@@ -160,7 +160,10 @@ static void put_superpage(unsigned long + static uint32_t base_disallow_mask; + /* Global bit is allowed to be set on L1 PTEs. Intended for user mappings. */ + #define L1_DISALLOW_MASK ((base_disallow_mask | _PAGE_GNTTAB) & ~_PAGE_GLOBAL) +-#define L2_DISALLOW_MASK (base_disallow_mask & ~_PAGE_PSE) ++ ++#define L2_DISALLOW_MASK (unlikely(opt_allow_superpage) \ ++ ? base_disallow_mask & ~_PAGE_PSE \ ++ : base_disallow_mask) + + #define l3_disallow_mask(d) (!is_pv_32bit_domain(d) ? \ + base_disallow_mask : 0xFFFFF198U) +@@ -1841,7 +1844,10 @@ static int mod_l2_entry(l2_pgentry_t *pl + } + + /* Fast path for identical mapping and presence. */ +- if ( !l2e_has_changed(ol2e, nl2e, _PAGE_PRESENT) ) ++ if ( !l2e_has_changed(ol2e, nl2e, ++ unlikely(opt_allow_superpage) ++ ? _PAGE_PSE | _PAGE_RW | _PAGE_PRESENT ++ : _PAGE_PRESENT) ) + { + adjust_guest_l2e(nl2e, d); + if ( UPDATE_ENTRY(l2, pl2e, ol2e, nl2e, pfn, vcpu, preserve_ad) ) diff --git a/xsa149.patch b/xsa149.patch new file mode 100644 index 0000000..41103b2 --- /dev/null +++ b/xsa149.patch @@ -0,0 +1,20 @@ +xen: free domain's vcpu array + +This was overlooked in fb442e2171 ("x86_64: allow more vCPU-s per +guest"). + +This is XSA-149. + +Signed-off-by: Jan Beulich +Reviewed-by: Ian Campbell + +--- a/xen/common/domain.c ++++ b/xen/common/domain.c +@@ -841,6 +841,7 @@ static void complete_domain_destroy(stru + + xsm_free_security_domain(d); + free_cpumask_var(d->domain_dirty_cpumask); ++ xfree(d->vcpu); + free_domain_struct(d); + + send_global_virq(VIRQ_DOM_EXC); diff --git a/xsa150.patch b/xsa150.patch new file mode 100644 index 0000000..f5ef12e --- /dev/null +++ b/xsa150.patch @@ -0,0 +1,201 @@ +x86/PoD: Eager sweep for zeroed pages + +Based on the contents of a guests physical address space, +p2m_pod_emergency_sweep() could degrade into a linear memcmp() from 0 to +max_gfn, which runs non-preemptibly. + +As p2m_pod_emergency_sweep() runs behind the scenes in a number of contexts, +making it preemptible is not feasible. + +Instead, a different approach is taken. Recently-populated pages are eagerly +checked for reclaimation, which amortises the p2m_pod_emergency_sweep() +operation across each p2m_pod_demand_populate() operation. + +Note that in the case that a 2M superpage can't be reclaimed as a superpage, +it is shattered if 4K pages of zeros can be reclaimed. This is unfortunate +but matches the previous behaviour, and is required to avoid regressions +(domain crash from PoD exhaustion) with VMs configured close to the limit. + +This is CVE-2015-7970 / XSA-150. + +Signed-off-by: Andrew Cooper +Reviewed-by: Jan Beulich +Reviewed-by: George Dunlap + +--- a/xen/arch/x86/mm/p2m-pod.c ++++ b/xen/arch/x86/mm/p2m-pod.c +@@ -920,28 +920,6 @@ p2m_pod_zero_check(struct p2m_domain *p2 + } + + #define POD_SWEEP_LIMIT 1024 +- +-/* When populating a new superpage, look at recently populated superpages +- * hoping that they've been zeroed. This will snap up zeroed pages as soon as +- * the guest OS is done with them. */ +-static void +-p2m_pod_check_last_super(struct p2m_domain *p2m, unsigned long gfn_aligned) +-{ +- unsigned long check_gfn; +- +- ASSERT(p2m->pod.last_populated_index < POD_HISTORY_MAX); +- +- check_gfn = p2m->pod.last_populated[p2m->pod.last_populated_index]; +- +- p2m->pod.last_populated[p2m->pod.last_populated_index] = gfn_aligned; +- +- p2m->pod.last_populated_index = +- ( p2m->pod.last_populated_index + 1 ) % POD_HISTORY_MAX; +- +- p2m_pod_zero_check_superpage(p2m, check_gfn); +-} +- +- + #define POD_SWEEP_STRIDE 16 + static void + p2m_pod_emergency_sweep(struct p2m_domain *p2m) +@@ -982,7 +960,7 @@ p2m_pod_emergency_sweep(struct p2m_domai + * NB that this is a zero-sum game; we're increasing our cache size + * by re-increasing our 'debt'. Since we hold the pod lock, + * (entry_count - count) must remain the same. */ +- if ( p2m->pod.count > 0 && i < limit ) ++ if ( i < limit && (p2m->pod.count > 0 || hypercall_preempt_check()) ) + break; + } + +@@ -994,6 +972,58 @@ p2m_pod_emergency_sweep(struct p2m_domai + + } + ++static void pod_eager_reclaim(struct p2m_domain *p2m) ++{ ++ struct pod_mrp_list *mrp = &p2m->pod.mrp; ++ unsigned int i = 0; ++ ++ /* ++ * Always check one page for reclaimation. ++ * ++ * If the PoD pool is empty, keep checking some space is found, or all ++ * entries have been exhaused. ++ */ ++ do ++ { ++ unsigned int idx = (mrp->idx + i++) % ARRAY_SIZE(mrp->list); ++ unsigned long gfn = mrp->list[idx]; ++ ++ if ( gfn != INVALID_GFN ) ++ { ++ if ( gfn & POD_LAST_SUPERPAGE ) ++ { ++ gfn &= ~POD_LAST_SUPERPAGE; ++ ++ if ( p2m_pod_zero_check_superpage(p2m, gfn) == 0 ) ++ { ++ unsigned int x; ++ ++ for ( x = 0; x < SUPERPAGE_PAGES; ++x, ++gfn ) ++ p2m_pod_zero_check(p2m, &gfn, 1); ++ } ++ } ++ else ++ p2m_pod_zero_check(p2m, &gfn, 1); ++ ++ mrp->list[idx] = INVALID_GFN; ++ } ++ ++ } while ( (p2m->pod.count == 0) && (i < ARRAY_SIZE(mrp->list)) ); ++} ++ ++static void pod_eager_record(struct p2m_domain *p2m, ++ unsigned long gfn, unsigned int order) ++{ ++ struct pod_mrp_list *mrp = &p2m->pod.mrp; ++ ++ ASSERT(mrp->list[mrp->idx] == INVALID_GFN); ++ ASSERT(gfn != INVALID_GFN); ++ ++ mrp->list[mrp->idx++] = ++ gfn | (order == PAGE_ORDER_2M ? POD_LAST_SUPERPAGE : 0); ++ mrp->idx %= ARRAY_SIZE(mrp->list); ++} ++ + int + p2m_pod_demand_populate(struct p2m_domain *p2m, unsigned long gfn, + unsigned int order, +@@ -1034,6 +1064,8 @@ p2m_pod_demand_populate(struct p2m_domai + return 0; + } + ++ pod_eager_reclaim(p2m); ++ + /* Only sweep if we're actually out of memory. Doing anything else + * causes unnecessary time and fragmentation of superpages in the p2m. */ + if ( p2m->pod.count == 0 ) +@@ -1070,6 +1102,8 @@ p2m_pod_demand_populate(struct p2m_domai + p2m->pod.entry_count -= (1 << order); + BUG_ON(p2m->pod.entry_count < 0); + ++ pod_eager_record(p2m, gfn_aligned, order); ++ + if ( tb_init_done ) + { + struct { +@@ -1085,12 +1119,6 @@ p2m_pod_demand_populate(struct p2m_domai + __trace_var(TRC_MEM_POD_POPULATE, 0, sizeof(t), &t); + } + +- /* Check the last guest demand-populate */ +- if ( p2m->pod.entry_count > p2m->pod.count +- && (order == PAGE_ORDER_2M) +- && (q & P2M_ALLOC) ) +- p2m_pod_check_last_super(p2m, gfn_aligned); +- + pod_unlock(p2m); + return 0; + out_of_memory: +--- a/xen/arch/x86/mm/p2m.c ++++ b/xen/arch/x86/mm/p2m.c +@@ -58,6 +58,7 @@ boolean_param("hap_2mb", opt_hap_2mb); + /* Init the datastructures for later use by the p2m code */ + static int p2m_initialise(struct domain *d, struct p2m_domain *p2m) + { ++ unsigned int i; + int ret = 0; + + mm_rwlock_init(&p2m->lock); +@@ -73,6 +74,9 @@ static int p2m_initialise(struct domain + + p2m->np2m_base = P2M_BASE_EADDR; + ++ for ( i = 0; i < ARRAY_SIZE(p2m->pod.mrp.list); ++i ) ++ p2m->pod.mrp.list[i] = INVALID_GFN; ++ + if ( hap_enabled(d) && cpu_has_vmx ) + ret = ept_p2m_init(p2m); + else +--- a/xen/include/asm-x86/p2m.h ++++ b/xen/include/asm-x86/p2m.h +@@ -292,10 +292,20 @@ struct p2m_domain { + entry_count; /* # of pages in p2m marked pod */ + unsigned long reclaim_single; /* Last gpfn of a scan */ + unsigned long max_guest; /* gpfn of max guest demand-populate */ +-#define POD_HISTORY_MAX 128 +- /* gpfn of last guest superpage demand-populated */ +- unsigned long last_populated[POD_HISTORY_MAX]; +- unsigned int last_populated_index; ++ ++ /* ++ * Tracking of the most recently populated PoD pages, for eager ++ * reclamation. ++ */ ++ struct pod_mrp_list { ++#define NR_POD_MRP_ENTRIES 32 ++ ++/* Encode ORDER_2M superpage in top bit of GFN */ ++#define POD_LAST_SUPERPAGE (INVALID_GFN & ~(INVALID_GFN >> 1)) ++ ++ unsigned long list[NR_POD_MRP_ENTRIES]; ++ unsigned int idx; ++ } mrp; + mm_lock_t lock; /* Locking of private pod structs, * + * not relying on the p2m lock. */ + } pod; diff --git a/xsa151.patch b/xsa151.patch new file mode 100644 index 0000000..1f0277e --- /dev/null +++ b/xsa151.patch @@ -0,0 +1,28 @@ +xenoprof: free domain's vcpu array + +This was overlooked in fb442e2171 ("x86_64: allow more vCPU-s per +guest"). + +This is XSA-151. + +Signed-off-by: Jan Beulich +Reviewed-by: Ian Campbell + +--- a/xen/common/xenoprof.c ++++ b/xen/common/xenoprof.c +@@ -239,6 +239,7 @@ static int alloc_xenoprof_struct( + d->xenoprof->rawbuf = alloc_xenheap_pages(get_order_from_pages(npages), 0); + if ( d->xenoprof->rawbuf == NULL ) + { ++ xfree(d->xenoprof->vcpu); + xfree(d->xenoprof); + d->xenoprof = NULL; + return -ENOMEM; +@@ -286,6 +287,7 @@ void free_xenoprof_pages(struct domain * + free_xenheap_pages(x->rawbuf, order); + } + ++ xfree(x->vcpu); + xfree(x); + d->xenoprof = NULL; + } diff --git a/xsa152.patch b/xsa152.patch new file mode 100644 index 0000000..6fbc90f --- /dev/null +++ b/xsa152.patch @@ -0,0 +1,66 @@ +x86: rate-limit logging in do_xen{oprof,pmu}_op() + +Some of the sub-ops are acessible to all guests, and hence should be +rate-limited. In the xenoprof case, just like for XSA-146, include them +only in debug builds. Since the vPMU code is rather new, allow them to +be always present, but downgrade them to (rate limited) guest messages. + +This is XSA-152. + +Signed-off-by: Jan Beulich +Reviewed-by: Ian Campbell + +--- a/xen/arch/x86/cpu/vpmu.c ++++ b/xen/arch/x86/cpu/vpmu.c +@@ -682,8 +682,8 @@ long do_xenpmu_op(unsigned int op, XEN_G + vpmu_mode = pmu_params.val; + else if ( vpmu_mode != pmu_params.val ) + { +- printk(XENLOG_WARNING +- "VPMU: Cannot change mode while active VPMUs exist\n"); ++ gprintk(XENLOG_WARNING, ++ "VPMU: Cannot change mode while active VPMUs exist\n"); + ret = -EBUSY; + } + +@@ -714,8 +714,8 @@ long do_xenpmu_op(unsigned int op, XEN_G + vpmu_features = pmu_params.val; + else + { +- printk(XENLOG_WARNING "VPMU: Cannot change features while" +- " active VPMUs exist\n"); ++ gprintk(XENLOG_WARNING, ++ "VPMU: Cannot change features while active VPMUs exist\n"); + ret = -EBUSY; + } + +--- a/xen/common/xenoprof.c ++++ b/xen/common/xenoprof.c +@@ -676,15 +676,13 @@ ret_t do_xenoprof_op(int op, XEN_GUEST_H + + if ( (op < 0) || (op > XENOPROF_last_op) ) + { +- printk("xenoprof: invalid operation %d for domain %d\n", +- op, current->domain->domain_id); ++ gdprintk(XENLOG_DEBUG, "invalid operation %d\n", op); + return -EINVAL; + } + + if ( !NONPRIV_OP(op) && (current->domain != xenoprof_primary_profiler) ) + { +- printk("xenoprof: dom %d denied privileged operation %d\n", +- current->domain->domain_id, op); ++ gdprintk(XENLOG_DEBUG, "denied privileged operation %d\n", op); + return -EPERM; + } + +@@ -907,8 +905,7 @@ ret_t do_xenoprof_op(int op, XEN_GUEST_H + spin_unlock(&xenoprof_lock); + + if ( ret < 0 ) +- printk("xenoprof: operation %d failed for dom %d (status : %d)\n", +- op, current->domain->domain_id, ret); ++ gdprintk(XENLOG_DEBUG, "operation %d failed: %d\n", op, ret); + + return ret; + } diff --git a/xsa153-libxl.patch b/xsa153-libxl.patch new file mode 100644 index 0000000..14a50eb --- /dev/null +++ b/xsa153-libxl.patch @@ -0,0 +1,86 @@ +From 27593ec62bdad8621df910931349d964a6dbaa8c Mon Sep 17 00:00:00 2001 +From: Ian Jackson +Date: Wed, 21 Oct 2015 16:18:30 +0100 +Subject: [PATCH XSA-153 v3] libxl: adjust PoD target by memory fudge, too + +PoD guests need to balloon at least as far as required by PoD, or risk +crashing. Currently they don't necessarily know what the right value +is, because our memory accounting is (at the very least) confusing. + +Apply the memory limit fudge factor to the in-hypervisor PoD memory +target, too. This will increase the size of the guest's PoD cache by +the fudge factor LIBXL_MAXMEM_CONSTANT (currently 1Mby). This ensures +that even with a slightly-off balloon driver, the guest will be +stable even under memory pressure. + +There are two call sites of xc_domain_set_pod_target that need fixing: + +The one in libxl_set_memory_target is straightforward. + +The one in xc_hvm_build_x86.c:setup_guest is more awkward. Simply +setting the PoD target differently does not work because the various +amounts of memory during domain construction no longer match up. +Instead, we adjust the guest memory target in xenstore (but only for +PoD guests). + +This introduces a 1Mby discrepancy between the balloon target of a PoD +guest at boot, and the target set by an apparently-equivalent `xl +mem-set' (or similar) later. This approach is low-risk for a security +fix but we need to fix this up properly in xen.git#staging and +probably also in stable trees. + +This is XSA-153. + +Signed-off-by: Ian Jackson +--- + tools/libxl/libxl.c | 2 +- + tools/libxl/libxl_dom.c | 9 ++++++++- + 2 files changed, 9 insertions(+), 2 deletions(-) + +diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c +index d38d0c7..1366177 100644 +--- a/tools/libxl/libxl.c ++++ b/tools/libxl/libxl.c +@@ -4815,7 +4815,7 @@ retry_transaction: + } + + rc = xc_domain_set_pod_target(ctx->xch, domid, +- new_target_memkb / 4, NULL, NULL, NULL); ++ (new_target_memkb + LIBXL_MAXMEM_CONSTANT) / 4, NULL, NULL, NULL); + if (rc != 0) { + LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, + "xc_domain_set_pod_target domid=%d, memkb=%d " +diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c +index b514377..8019f4e 100644 +--- a/tools/libxl/libxl_dom.c ++++ b/tools/libxl/libxl_dom.c +@@ -486,6 +486,7 @@ int libxl__build_post(libxl__gc *gc, uint32_t domid, + xs_transaction_t t; + char **ents; + int i, rc; ++ int64_t mem_target_fudge; + + if (info->num_vnuma_nodes && !info->num_vcpu_soft_affinity) { + rc = set_vnuma_affinity(gc, domid, info); +@@ -518,11 +519,17 @@ int libxl__build_post(libxl__gc *gc, uint32_t domid, + } + } + ++ mem_target_fudge = ++ (info->type == LIBXL_DOMAIN_TYPE_HVM && ++ info->max_memkb > info->target_memkb) ++ ? LIBXL_MAXMEM_CONSTANT : 0; ++ + ents = libxl__calloc(gc, 12 + (info->max_vcpus * 2) + 2, sizeof(char *)); + ents[0] = "memory/static-max"; + ents[1] = GCSPRINTF("%"PRId64, info->max_memkb); + ents[2] = "memory/target"; +- ents[3] = GCSPRINTF("%"PRId64, info->target_memkb - info->video_memkb); ++ ents[3] = GCSPRINTF("%"PRId64, info->target_memkb - info->video_memkb ++ - mem_target_fudge); + ents[4] = "memory/videoram"; + ents[5] = GCSPRINTF("%"PRId64, info->video_memkb); + ents[6] = "domid"; +-- +1.7.10.4 +