[PATCH 2/2] xen/balloon: improve accuracy of initial balloon target for dom0

Roger Pau Monne posted 2 patches 1 week, 2 days ago
[PATCH 2/2] xen/balloon: improve accuracy of initial balloon target for dom0
Posted by Roger Pau Monne 1 week, 2 days ago
The dom0 balloon target set by the toolstack is the value returned by
XENMEM_current_reservation.  Do the same in the kernel balloon driver and
set the current allocation to the value returned by
XENMEM_current_reservation.  On my test system this causes the kernel
balloon driver target to exactly match the value set by the toolstack in
xenstore.

Note this approach can be used by both PV and PVH dom0s, as the toolstack
always uses XENMEM_current_reservation to set the initial target regardless
of the dom0 type.

Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
---
 drivers/xen/balloon.c | 27 +++++++++++++++++----------
 1 file changed, 17 insertions(+), 10 deletions(-)

diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c
index 8c44a25a7d2b..9b6531eb28b6 100644
--- a/drivers/xen/balloon.c
+++ b/drivers/xen/balloon.c
@@ -724,7 +724,8 @@ static int __init balloon_add_regions(void)
 static int __init balloon_init(void)
 {
 	struct task_struct *task;
-	unsigned long current_pages;
+	long current_pages = 0;
+	domid_t domid = DOMID_SELF;
 	int rc;
 
 	if (!xen_domain())
@@ -732,15 +733,21 @@ static int __init balloon_init(void)
 
 	pr_info("Initialising balloon driver\n");
 
-	if (xen_pv_domain()) {
-		if (xen_released_pages >= xen_start_info->nr_pages)
-			goto underflow;
-		current_pages = min(xen_start_info->nr_pages -
-		                    xen_released_pages, max_pfn);
-	} else {
-		if (xen_unpopulated_pages >= get_num_physpages())
-			goto underflow;
-		current_pages = get_num_physpages() - xen_unpopulated_pages;
+	if (xen_initial_domain())
+		current_pages = HYPERVISOR_memory_op(XENMEM_current_reservation,
+		                                     &domid);
+	if (current_pages <= 0) {
+		if (xen_pv_domain()) {
+			if (xen_released_pages >= xen_start_info->nr_pages)
+				goto underflow;
+			current_pages = min(xen_start_info->nr_pages -
+			                    xen_released_pages, max_pfn);
+		} else {
+			if (xen_unpopulated_pages >= get_num_physpages())
+				goto underflow;
+			current_pages = get_num_physpages() -
+			                xen_unpopulated_pages;
+		}
 	}
 
 	balloon_stats.current_pages = current_pages;
-- 
2.51.0

Re: [PATCH 2/2] xen/balloon: improve accuracy of initial balloon target for dom0
Posted by Jürgen Groß 1 week, 2 days ago
On 28.01.26 12:05, Roger Pau Monne wrote:
> The dom0 balloon target set by the toolstack is the value returned by
> XENMEM_current_reservation.  Do the same in the kernel balloon driver and
> set the current allocation to the value returned by
> XENMEM_current_reservation.  On my test system this causes the kernel
> balloon driver target to exactly match the value set by the toolstack in
> xenstore.
> 
> Note this approach can be used by both PV and PVH dom0s, as the toolstack
> always uses XENMEM_current_reservation to set the initial target regardless
> of the dom0 type.
> 
> Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>

Reviewed-by: Juergen Gross <jgross@suse.com>


Juergen
Re: [PATCH 2/2] xen/balloon: improve accuracy of initial balloon target for dom0
Posted by Jürgen Groß 1 week, 2 days ago
On 28.01.26 12:05, Roger Pau Monne wrote:
> The dom0 balloon target set by the toolstack is the value returned by
> XENMEM_current_reservation.  Do the same in the kernel balloon driver and
> set the current allocation to the value returned by
> XENMEM_current_reservation.  On my test system this causes the kernel
> balloon driver target to exactly match the value set by the toolstack in
> xenstore.
> 
> Note this approach can be used by both PV and PVH dom0s, as the toolstack
> always uses XENMEM_current_reservation to set the initial target regardless
> of the dom0 type.
> 
> Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
> ---
>   drivers/xen/balloon.c | 27 +++++++++++++++++----------
>   1 file changed, 17 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c
> index 8c44a25a7d2b..9b6531eb28b6 100644
> --- a/drivers/xen/balloon.c
> +++ b/drivers/xen/balloon.c
> @@ -724,7 +724,8 @@ static int __init balloon_add_regions(void)
>   static int __init balloon_init(void)
>   {
>   	struct task_struct *task;
> -	unsigned long current_pages;
> +	long current_pages = 0;
> +	domid_t domid = DOMID_SELF;
>   	int rc;
>   
>   	if (!xen_domain())
> @@ -732,15 +733,21 @@ static int __init balloon_init(void)
>   
>   	pr_info("Initialising balloon driver\n");
>   
> -	if (xen_pv_domain()) {
> -		if (xen_released_pages >= xen_start_info->nr_pages)
> -			goto underflow;
> -		current_pages = min(xen_start_info->nr_pages -
> -		                    xen_released_pages, max_pfn);
> -	} else {
> -		if (xen_unpopulated_pages >= get_num_physpages())
> -			goto underflow;
> -		current_pages = get_num_physpages() - xen_unpopulated_pages;
> +	if (xen_initial_domain())
> +		current_pages = HYPERVISOR_memory_op(XENMEM_current_reservation,
> +		                                     &domid);

Is there any specific reason why this should be limited to dom0?

I _think_ this should work for other domains, too.


Juergen

> +	if (current_pages <= 0) {
> +		if (xen_pv_domain()) {
> +			if (xen_released_pages >= xen_start_info->nr_pages)
> +				goto underflow;
> +			current_pages = min(xen_start_info->nr_pages -
> +			                    xen_released_pages, max_pfn);
> +		} else {
> +			if (xen_unpopulated_pages >= get_num_physpages())
> +				goto underflow;
> +			current_pages = get_num_physpages() -
> +			                xen_unpopulated_pages;
> +		}
>   	}
>   
>   	balloon_stats.current_pages = current_pages;

Re: [PATCH 2/2] xen/balloon: improve accuracy of initial balloon target for dom0
Posted by Roger Pau Monné 1 week, 2 days ago
On Wed, Jan 28, 2026 at 12:31:13PM +0100, Jürgen Groß wrote:
> On 28.01.26 12:05, Roger Pau Monne wrote:
> > The dom0 balloon target set by the toolstack is the value returned by
> > XENMEM_current_reservation.  Do the same in the kernel balloon driver and
> > set the current allocation to the value returned by
> > XENMEM_current_reservation.  On my test system this causes the kernel
> > balloon driver target to exactly match the value set by the toolstack in
> > xenstore.
> > 
> > Note this approach can be used by both PV and PVH dom0s, as the toolstack
> > always uses XENMEM_current_reservation to set the initial target regardless
> > of the dom0 type.
> > 
> > Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
> > ---
> >   drivers/xen/balloon.c | 27 +++++++++++++++++----------
> >   1 file changed, 17 insertions(+), 10 deletions(-)
> > 
> > diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c
> > index 8c44a25a7d2b..9b6531eb28b6 100644
> > --- a/drivers/xen/balloon.c
> > +++ b/drivers/xen/balloon.c
> > @@ -724,7 +724,8 @@ static int __init balloon_add_regions(void)
> >   static int __init balloon_init(void)
> >   {
> >   	struct task_struct *task;
> > -	unsigned long current_pages;
> > +	long current_pages = 0;
> > +	domid_t domid = DOMID_SELF;
> >   	int rc;
> >   	if (!xen_domain())
> > @@ -732,15 +733,21 @@ static int __init balloon_init(void)
> >   	pr_info("Initialising balloon driver\n");
> > -	if (xen_pv_domain()) {
> > -		if (xen_released_pages >= xen_start_info->nr_pages)
> > -			goto underflow;
> > -		current_pages = min(xen_start_info->nr_pages -
> > -		                    xen_released_pages, max_pfn);
> > -	} else {
> > -		if (xen_unpopulated_pages >= get_num_physpages())
> > -			goto underflow;
> > -		current_pages = get_num_physpages() - xen_unpopulated_pages;
> > +	if (xen_initial_domain())
> > +		current_pages = HYPERVISOR_memory_op(XENMEM_current_reservation,
> > +		                                     &domid);
> 
> Is there any specific reason why this should be limited to dom0?
> 
> I _think_ this should work for other domains, too.

Sadly it doesn't, I've already tested.  The value returned by
XENMEM_current_reservation on PV guests is slightly different than
what's in xen_start_info->nr_pages, which exactly what the toolstack
writes in xenstore.  I assume there's some other stuff that's
accounted for in d->tot_pages, but don't really know what I'm afraid.

And in the HVM/PVH case using XENMEM_current_reservation for domUs
would also take into account the Video memory, which skews the target.

This is the best I could do I'm afraid, at the expense of having so
many different way to fetch the information.

Thanks, Roger.
Re: [PATCH 2/2] xen/balloon: improve accuracy of initial balloon target for dom0
Posted by Jürgen Groß 1 week, 2 days ago
On 28.01.26 12:54, Roger Pau Monné wrote:
> On Wed, Jan 28, 2026 at 12:31:13PM +0100, Jürgen Groß wrote:
>> On 28.01.26 12:05, Roger Pau Monne wrote:
>>> The dom0 balloon target set by the toolstack is the value returned by
>>> XENMEM_current_reservation.  Do the same in the kernel balloon driver and
>>> set the current allocation to the value returned by
>>> XENMEM_current_reservation.  On my test system this causes the kernel
>>> balloon driver target to exactly match the value set by the toolstack in
>>> xenstore.
>>>
>>> Note this approach can be used by both PV and PVH dom0s, as the toolstack
>>> always uses XENMEM_current_reservation to set the initial target regardless
>>> of the dom0 type.
>>>
>>> Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
>>> ---
>>>    drivers/xen/balloon.c | 27 +++++++++++++++++----------
>>>    1 file changed, 17 insertions(+), 10 deletions(-)
>>>
>>> diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c
>>> index 8c44a25a7d2b..9b6531eb28b6 100644
>>> --- a/drivers/xen/balloon.c
>>> +++ b/drivers/xen/balloon.c
>>> @@ -724,7 +724,8 @@ static int __init balloon_add_regions(void)
>>>    static int __init balloon_init(void)
>>>    {
>>>    	struct task_struct *task;
>>> -	unsigned long current_pages;
>>> +	long current_pages = 0;
>>> +	domid_t domid = DOMID_SELF;
>>>    	int rc;
>>>    	if (!xen_domain())
>>> @@ -732,15 +733,21 @@ static int __init balloon_init(void)
>>>    	pr_info("Initialising balloon driver\n");
>>> -	if (xen_pv_domain()) {
>>> -		if (xen_released_pages >= xen_start_info->nr_pages)
>>> -			goto underflow;
>>> -		current_pages = min(xen_start_info->nr_pages -
>>> -		                    xen_released_pages, max_pfn);
>>> -	} else {
>>> -		if (xen_unpopulated_pages >= get_num_physpages())
>>> -			goto underflow;
>>> -		current_pages = get_num_physpages() - xen_unpopulated_pages;
>>> +	if (xen_initial_domain())
>>> +		current_pages = HYPERVISOR_memory_op(XENMEM_current_reservation,
>>> +		                                     &domid);
>>
>> Is there any specific reason why this should be limited to dom0?
>>
>> I _think_ this should work for other domains, too.
> 
> Sadly it doesn't, I've already tested.  The value returned by
> XENMEM_current_reservation on PV guests is slightly different than
> what's in xen_start_info->nr_pages, which exactly what the toolstack
> writes in xenstore.  I assume there's some other stuff that's
> accounted for in d->tot_pages, but don't really know what I'm afraid.
> 
> And in the HVM/PVH case using XENMEM_current_reservation for domUs
> would also take into account the Video memory, which skews the target.
> 
> This is the best I could do I'm afraid, at the expense of having so
> many different way to fetch the information.

Meh, too bad.

For now I think we need to live with that. But for the future I'd like to
suggest to add a new Xenstore node memory/reservation-diff containing the
difference between XENMEM_current_reservation output and the tools' view
of the domain's memory size.

The balloon driver could read that node in balloon_init() and use
XENMEM_current_reservation in case the node is found.


Juergen