[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v6 06/16] libs/call: cache up to 4 pages in hypercall bounce buffers


  • To: Anthony PERARD <anthony.perard@xxxxxxxxxx>
  • From: Frediano Ziglio <freddy77@xxxxxxxxx>
  • Date: Tue, 7 Jul 2026 15:47:07 +0100
  • Arc-authentication-results: i=1; mx.google.com; arc=none
  • Arc-message-signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20260327; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:dkim-signature; bh=ilRzyAAMmy3o+36yI2ZCcmkogGYNpjjWNytNdaDq+BQ=; fh=/xIDEt21AoDgIoFrvXO7IQvdlvHF73QaNWBe25gcoZE=; b=qPqTtsz70wzpps4vUrzCSCMSH7oz3PIKvaCFrUA1nru8+3vAYZOxUAGbdd7NnCNwUW 7/7YPo5t78rDXQceEFQEuic1cB9GGmA+ZAxCYKxzTraFdhrUU2ss1JpndZKLZsLzf6XS qpFYmNgqQlQtdoVw9YdEVHcSsD7E3UvqbI/iUffo6i2OEZM7Pf47Q5ySuGi5DpfAMByn ZDn2hXrM1ofvzlR5w+FTaDKM2rx9krpkLF26vVXbPby4In8I4oj+kcM450Vz5bW8/2IN jIbFcw5Vjzs/hVMX6+XP7sukc6gHpWpHSC3I0dk85VVwW4d+5AIFu0URNOpfkz31Bx5e JLiw==; darn=lists.xenproject.org
  • Arc-seal: i=1; a=rsa-sha256; t=1783435638; cv=none; d=google.com; s=arc-20260327; b=CgTpvBQ9wgKanytGJwa2TWM8K6fOSUGRYgMsG3Ll3oNyEa47PGiWcHrAi7DBfqL2yS MhPmqK7f87f7gYTitDUKYMDf20SQYhZTb+MDC64p9Z9hlSSBWDR9J5QlJbDUraHpXJ0P uqq7wZueqntoebmMDH2hpoByH77twt9lcqH5YCd7+3klN0Vf+diAThTbmjsZhKCVsL+g XoNXaIcUCtd1DG1eT+A/FIYokkzImaguCr0T9AM0Z9rVnfk+26UAgsBMnK3Yliw9CbnR WviHi2fuNLWI8u4AWI0CsBhR1m732z8MwyUfaQ20rpNmX8Qr3JhJ1kJJUEdC1X65zrUg tLaA==
  • Authentication-results: eu.smtp.expurgate.cloud; dkim=pass header.s=20251104 header.d=gmail.com header.i="@gmail.com" header.h="Content-Transfer-Encoding:Content-Type:Cc:To:Subject:Message-ID:Date:From:In-Reply-To:References:MIME-Version"
  • Cc: xen-devel@xxxxxxxxxxxxxxxxxxxx, Edwin Török <edwin.torok@xxxxxxxxxx>, Jan Beulich <jbeulich@xxxxxxxx>, Andrew Cooper <andrew.cooper3@xxxxxxxxxx>, Roger Pau Monné <roger.pau@xxxxxxxxxx>, Teddy Astie <teddy.astie@xxxxxxxxxx>, Juergen Gross <jgross@xxxxxxxx>, Frediano Ziglio <frediano.ziglio@xxxxxxxxxx>
  • Delivery-date: Tue, 07 Jul 2026 14:47:26 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>

On Tue, 7 Jul 2026 at 14:51, Anthony PERARD <anthony.perard@xxxxxxxxxx> wrote:
>
> On Fri, Jun 19, 2026 at 02:04:51PM +0100, Frediano Ziglio wrote:
> > From: Edwin Török <edwin.torok@xxxxxxxxxx>
> >
> > During migration there are a lot of mmap/munmap calls,
> > because `xc_get_pfn_type_batch` exceeds the default hypercall bounce
> > buffer cache size, and needs to allocate every time it is called.
>
> I think xc_get_pfn_type_batch() would allocate a buffer of 2 page top,
> in write_batch(), right ?
>

Yes. That however does not contradict the sense of the sentence (or
even the commit message).

> >
> > `munmap` is slow, especially in a PV Dom0 (takes an emulation fault),
> > so is best avoided.
> >
> > Eventually it'd be good if the memory pool from  xmalloc_tlsf.c
> > was reused here, but for now make it handle the commonly encountered
> > sizes (so far up to 4 pages).
> >

If a program uses 3/4 pages it will use the additional cache, if not
there's no much difference.

> > Signed-off-by: Edwin Török <edwin.torok@xxxxxxxxxx>
> > Signed-off-by: Frediano Ziglio <frediano.ziglio@xxxxxxxxxx>
> > --
> > Changes since v2:
> > - change prefix in subject.
> >
> > Changes since v4:
> > - fix off-by-one bug.
> >
> > Changes since v5:
> > - avoids potential buffer underflow if nr_pages is 0 calling cache_alloc.
> > ---
> >  tools/libs/call/buffer.c  | 31 ++++++++++++++++++++-----------
> >  tools/libs/call/core.c    |  3 ++-
> >  tools/libs/call/private.h |  8 +++++---
> >  3 files changed, 27 insertions(+), 15 deletions(-)
> >
> > diff --git a/tools/libs/call/buffer.c b/tools/libs/call/buffer.c
> > index 155e4f9d43..2f0515c273 100644
> > --- a/tools/libs/call/buffer.c
> > +++ b/tools/libs/call/buffer.c
> > @@ -49,6 +49,9 @@ static void *cache_alloc(xencall_handle *xcall, size_t 
> > nr_pages)
> >  {
> >      void *p = NULL;
> >
> > +    if ( nr_pages == 0 )
> > +        return NULL;
>
> By doing that check here, we don't update the stat anymore. And it's
> getting out-of-sync with the updates done in cache_free().
>
> Before, we where returning a cache entry for that, and cache_hit++. I
> think it's ok to return cache_miss++ instead.
>

Well... requesting 0 pages is weird by definition, even malloc(0) is
not well defined.
In theory in this case returning NULL would cause cache_free to not be
called as filtered by xencall_free_buffer_pages.

I think the most symmetric think would be adding a similar test in
cache_free, like

static int cache_free(xencall_handle *xcall, void *p, size_t nr_pages)
{
    int rc = 0;

    if ( nr_pages == 0 )
        return 1;

    cache_lock(xcall);


(the return 1 is needed to prevent the attempt to munmap the pointer
which does not make sense).

> >      cache_lock(xcall);
> >
> >      xcall->buffer_total_allocations++;
> > @@ -56,13 +59,13 @@ static void *cache_alloc(xencall_handle *xcall, size_t 
> > nr_pages)
> >      if ( xcall->buffer_current_allocations > 
> > xcall->buffer_maximum_allocations )
> >          xcall->buffer_maximum_allocations = 
> > xcall->buffer_current_allocations;
> >
> > -    if ( nr_pages > 1 )
> > +    if ( nr_pages > ARRAY_SIZE(xcall->buffer_cache) )
> >      {
> >          xcall->buffer_cache_toobig++;
> >      }
> > -    else if ( xcall->buffer_cache_nr > 0 )
> > +    else if ( xcall->buffer_cache_nr[nr_pages-1] > 0 )
> >      {
> > -        p = xcall->buffer_cache[--xcall->buffer_cache_nr];
> > +        p = 
> > xcall->buffer_cache[nr_pages-1][--xcall->buffer_cache_nr[nr_pages-1]];
> >          xcall->buffer_cache_hits++;
> >      }
> >      else
> > @@ -84,10 +87,10 @@ static int cache_free(xencall_handle *xcall, void *p, 
> > size_t nr_pages)
> >      xcall->buffer_total_releases++;
> >      xcall->buffer_current_allocations--;
> >
> > -    if ( nr_pages == 1 &&
> > -         xcall->buffer_cache_nr < BUFFER_CACHE_SIZE )
> > +    if ( nr_pages && nr_pages <= ARRAY_SIZE(xcall->buffer_cache) &&
> > +         xcall->buffer_cache_nr[nr_pages-1] < BUFFER_CACHE_SIZE )
> >      {
> > -        xcall->buffer_cache[xcall->buffer_cache_nr++] = p;
> > +        
> > xcall->buffer_cache[nr_pages-1][xcall->buffer_cache_nr[nr_pages-1]++] = p;
> >          rc = 1;
> >      }
> >
> > @@ -108,17 +111,23 @@ void buffer_release_cache(xencall_handle *xcall)
> >      DBGPRINTF("current allocations:%d maximum allocations:%d",
> >                xcall->buffer_current_allocations,
> >                xcall->buffer_maximum_allocations);
> > -    DBGPRINTF("cache current size:%d",
> > -              xcall->buffer_cache_nr);
> > +    for ( unsigned i = 0; i < ARRAY_SIZE(xcall->buffer_cache_nr); ++i )
> > +    {
> > +        DBGPRINTF("cache current size[%u pages]:%d", i+1,
> > +                xcall->buffer_cache_nr[i]);
> > +    }
> >      DBGPRINTF("cache hits:%d misses:%d toobig:%d",
> >                xcall->buffer_cache_hits,
> >                xcall->buffer_cache_misses,
> >                xcall->buffer_cache_toobig);
> >
> > -    while ( xcall->buffer_cache_nr > 0 )
> > +    for ( unsigned i = 0; i < ARRAY_SIZE(xcall->buffer_cache_nr); ++i )
> >      {
> > -        p = xcall->buffer_cache[--xcall->buffer_cache_nr];
> > -        osdep_free_pages(xcall, p, 1);
> > +        while ( xcall->buffer_cache_nr[i] > 0 )
> > +        {
> > +            p = xcall->buffer_cache[i][--xcall->buffer_cache_nr[i]];
> > +            osdep_free_pages(xcall, p, i + 1);
> > +        }
> >      }
> >
> >      cache_unlock(xcall);
> > diff --git a/tools/libs/call/core.c b/tools/libs/call/core.c
> > index 02c4f8e1ae..dd8877c1a0 100644
> > --- a/tools/libs/call/core.c
> > +++ b/tools/libs/call/core.c
> > @@ -14,6 +14,7 @@
> >   */
> >
> >  #include <stdlib.h>
> > +#include <string.h>
> >
> >  #include "private.h"
> >
> > @@ -44,7 +45,7 @@ xencall_handle *xencall_open(xentoollog_logger *logger, 
> > unsigned open_flags)
> >      xentoolcore__register_active_handle(&xcall->tc_ah);
> >
> >      xcall->flags = open_flags;
> > -    xcall->buffer_cache_nr = 0;
> > +    memset(xcall->buffer_cache_nr, 0, sizeof(xcall->buffer_cache_nr));
> >
> >      xcall->buffer_total_allocations = 0;
> >      xcall->buffer_total_releases = 0;
> > diff --git a/tools/libs/call/private.h b/tools/libs/call/private.h
> > index 9c3aa432ef..8e6a208975 100644
> > --- a/tools/libs/call/private.h
> > +++ b/tools/libs/call/private.h
> > @@ -31,13 +31,15 @@ struct xencall_handle {
> >      Xentoolcore__Active_Handle tc_ah;
> >
> >      /*
> > -     * A simple cache of unused, single page, hypercall buffers
> > +     * A simple cache of unused, small, hypercall buffers
> > +     * buffer_cache[i]'s size is (i+1) pages
> >       *
> >       * Protected by a global lock.
> >       */
> >  #define BUFFER_CACHE_SIZE 4
> > -    int buffer_cache_nr;
> > -    void *buffer_cache[BUFFER_CACHE_SIZE];
> > +#define BUFFER_CACHE_NRPAGES 4
> > +    int buffer_cache_nr[BUFFER_CACHE_NRPAGES];
> > +    void *buffer_cache[BUFFER_CACHE_NRPAGES][BUFFER_CACHE_SIZE];
> >
> >      /*
> >       * Hypercall buffer statistics. All protected by the global

Frediano



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.