Subject: fix balloon driver accounting for HVM-with-PoD case With PoD, ballooning down a guest to the target set through xenstore based on its totalram_pages value isn't sufficient, since that value doesn't include all the pages assigned to the guest. Since the delta is static, determine it once at load time. Signed-off-by: Jan Beulich --- sle11-2010-01-12.orig/drivers/xen/balloon/balloon.c 2009-08-31 11:48:33.000000000 +0200 +++ sle11-2010-01-12/drivers/xen/balloon/balloon.c 2010-02-01 13:35:47.000000000 +0100 @@ -90,6 +90,18 @@ static unsigned long frame_list[PAGE_SIZ #define dec_totalhigh_pages() ((void)0) #endif +#ifndef CONFIG_XEN +/* + * In HVM guests accounting here uses the Xen visible values, but the kernel + * determined totalram_pages value shouldn't get altered. Since totalram_pages + * includes neither the kernel static image nor any memory allocated prior to + * or from the bootmem allocator, we have to synchronize the two values. + */ +static unsigned long __read_mostly totalram_bias; +#else +#define totalram_bias 0 +#endif + /* List of ballooned pages, threaded through the mem_map array. */ static LIST_HEAD(ballooned_pages); @@ -305,7 +317,7 @@ static int increase_reservation(unsigned } bs.current_pages += rc; - totalram_pages = bs.current_pages; + totalram_pages = bs.current_pages - totalram_bias; out: balloon_unlock(flags); @@ -385,7 +397,7 @@ static int decrease_reservation(unsigned BUG_ON(ret != nr_pages); bs.current_pages -= nr_pages; - totalram_pages = bs.current_pages; + totalram_pages = bs.current_pages - totalram_bias; balloon_unlock(flags); @@ -524,7 +536,19 @@ static struct notifier_block xenstore_no static int __init balloon_init(void) { -#if defined(CONFIG_X86) && defined(CONFIG_XEN) +#if !defined(CONFIG_XEN) +# ifndef XENMEM_get_pod_target +# define XENMEM_get_pod_target 17 + typedef struct xen_pod_target { + uint64_t target_pages; + uint64_t tot_pages; + uint64_t pod_cache_pages; + uint64_t pod_entries; + domid_t domid; + } xen_pod_target_t; +# endif + xen_pod_target_t pod_target = { .domid = DOMID_SELF }; +#elif defined(CONFIG_X86) unsigned long pfn; struct page *page; #endif @@ -538,7 +562,20 @@ static int __init balloon_init(void) bs.current_pages = min(xen_start_info->nr_pages, max_pfn); totalram_pages = bs.current_pages; #else - bs.current_pages = totalram_pages; + totalram_bias = HYPERVISOR_memory_op( + HYPERVISOR_memory_op(XENMEM_get_pod_target, + &pod_target) != -ENOSYS + ? XENMEM_maximum_reservation + : XENMEM_current_reservation, + &pod_target.domid); + if ((long)totalram_bias != -ENOSYS) { + BUG_ON(totalram_bias < totalram_pages); + bs.current_pages = totalram_bias; + totalram_bias -= totalram_pages; + } else { + totalram_bias = 0; + bs.current_pages = totalram_pages; + } #endif bs.target_pages = bs.current_pages; bs.balloon_low = 0; @@ -671,7 +708,7 @@ struct page **alloc_empty_pages_and_page goto err; } - totalram_pages = --bs.current_pages; + totalram_pages = --bs.current_pages - totalram_bias; balloon_unlock(flags); }