From 8b628ad0ebe52c30e31298e868f2f5187f2f52da Mon Sep 17 00:00:00 2001 From: Jason Andryuk Date: Fri, 7 Nov 2025 16:44:53 -0500 Subject: [PATCH] xen/balloon: Initialize dom0 with XENMEM_current_reservation The balloon driver bases its action off the memory/target and memory/static-max xenstore keys. These are set by the toolstack and match the domain's hypervisor allocated pages - domain_tot_pages(). However, PVH and HVM domains query get_num_physpages() for the initial balloon driver current and target pages. get_num_physpages() is different from dom_totain_pages(), and has been observed way off in a PVH dom0. Here a PVH dom0 is assigned 917503 pages (3.5GB), but get_num_physpages() is 7312455: xen:balloon: pages curr 7312455 target 7312455 xen:balloon: current_reservation 917503 While Xen truncated the PVH dom0 memory map's RAM, Linux undoes that operation and restores RAM regions in pvh_reserve_extra_memory(). Use XENMEM_current_reveration to initialize the balloon driver current and target pages. This is the hypervisor value, and matches what the toolstack writes. This avoids any ballooning from the inital allocation. While domUs are affected, the implications of the change are unclear - only make the change for dom0. Signed-off-by: Jason Andryuk --- drivers/xen/balloon.c | 9 ++++++--- drivers/xen/mem-reservation.c | 8 ++++++++ include/xen/interface/memory.h | 5 +++++ include/xen/mem-reservation.h | 2 ++ 4 files changed, 21 insertions(+), 3 deletions(-) diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c index 528395133b4f..fa6cbe6ce2ca 100644 --- a/drivers/xen/balloon.c +++ b/drivers/xen/balloon.c @@ -713,10 +713,13 @@ static int __init balloon_init(void) #ifdef CONFIG_XEN_PV balloon_stats.current_pages = xen_pv_domain() - ? min(xen_start_info->nr_pages - xen_released_pages, max_pfn) - : get_num_physpages(); + ? min(xen_start_info->nr_pages - xen_released_pages, max_pfn) : + xen_initial_domain() ? xenmem_current_reservation() : + get_num_physpages(); #else - balloon_stats.current_pages = get_num_physpages(); + balloon_stats.current_pages = + xen_initial_domain() ? xenmem_current_reservation() : + get_num_physpages(); #endif balloon_stats.target_pages = balloon_stats.current_pages; balloon_stats.balloon_low = 0; diff --git a/drivers/xen/mem-reservation.c b/drivers/xen/mem-reservation.c index 24648836e0d4..40c5c40d34fe 100644 --- a/drivers/xen/mem-reservation.c +++ b/drivers/xen/mem-reservation.c @@ -113,3 +113,11 @@ int xenmem_reservation_decrease(int count, xen_pfn_t *frames) return HYPERVISOR_memory_op(XENMEM_decrease_reservation, &reservation); } EXPORT_SYMBOL_GPL(xenmem_reservation_decrease); + +long xenmem_current_reservation(void) +{ + struct xen_memory_domain domain = { .domid = DOMID_SELF }; + + return HYPERVISOR_memory_op(XENMEM_current_reservation, &domain); +} +EXPORT_SYMBOL_GPL(xenmem_current_reservation); diff --git a/include/xen/interface/memory.h b/include/xen/interface/memory.h index 1a371a825c55..72619a75fed2 100644 --- a/include/xen/interface/memory.h +++ b/include/xen/interface/memory.h @@ -104,6 +104,11 @@ DEFINE_GUEST_HANDLE_STRUCT(xen_memory_exchange); */ #define XENMEM_maximum_ram_page 2 +struct xen_memory_domain { + /* [IN] Domain information is being queried for. */ + domid_t domid; +}; + /* * Returns the current or maximum memory reservation, in pages, of the * specified domain (may be DOMID_SELF). Returns -ve errcode on failure. diff --git a/include/xen/mem-reservation.h b/include/xen/mem-reservation.h index a2ab516fcd2c..e86f0dcd7b7f 100644 --- a/include/xen/mem-reservation.h +++ b/include/xen/mem-reservation.h @@ -57,4 +57,6 @@ int xenmem_reservation_increase(int count, xen_pfn_t *frames); int xenmem_reservation_decrease(int count, xen_pfn_t *frames); +long xenmem_current_reservation(void); + #endif -- 2.52.0