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

Re: [PATCH v3 08/18] x86/domain_page: prepare the mapcache for per-vCPU accounting



On Thu, Oct 8, 2026 at 9:22 AM Roger Pau Monné <roger@xxxxxxxxxxxxxx> wrote:
>
> On Wed, Oct 07, 2026 at 11:40:41AM +0100, George Dunlap wrote:
> > From: Roger Pau Monné <roger.pau@xxxxxxxxxx>
> >
> > Currently, only PV domains have a mapcache, which is domain-wide one.
> > In preparation for enabling per-vCPU mapcaches for HVM domains, split
> > the accounting out into a struct mapcache, embedded in struct
> > mapcache_domain.
> >
> > Introduce has_mapcache(), for whether a vCPU has a mapcache, and
> > vcpu_mapcache(), which returns the accounting for a vCPU's mapcache
> > and, in *dcache, the domain-wide mapcache whose lock and TLB epoch the
> > caller has to take into account.  For now has_mapcache() is
> > is_pv_vcpu(), and vcpu_mapcache() always returns the domain's
> > accounting.  map_domain_page() and unmap_domain_page() stop repeating
> > the is_pv_vcpu() check mapcache_current_vcpu() has made.
> >
> > Move map_domain_page()'s handling of the domain-wide lock and TLB epoch
> > into three helpers: mapcache_lock() takes the lock and catches up with
> > a wrap another vCPU caused, mapcache_new_epoch() starts a new epoch
> > after a wrap, and mapcache_unlock() drops the lock.  A per-vCPU
> > mapcache can then skip them without map_domain_page() being
> > re-indented.
> >
> > struct mapcache_domain keeps its size (40 bytes, x86_64 debug build),
> > and so do the structures containing it.
> >
> > No functional change.
> >
> > Signed-off-by: Roger Pau Monné <roger.pau@xxxxxxxxxx>
> > Assisted-by: Claude Code:claude-fable-5, Claude Code:claude-opus-4-8, 
> > Claude Code:claude-opus-5-5
> > Signed-off-by: George Dunlap <gwd@xxxxxxxxxxxxxx>
> > ---
> > Changes in v3:
> > - New in this version, split out of "x86/hvm: introduce per-vCPU
> >   mapcache for vCPU-PT domains" for review.
> > ---
> >  xen/arch/x86/domain_page.c        | 155 ++++++++++++++++++++----------
> >  xen/arch/x86/include/asm/domain.h |  19 ++--
> >  2 files changed, 116 insertions(+), 58 deletions(-)
> >
> > diff --git a/xen/arch/x86/domain_page.c b/xen/arch/x86/domain_page.c
> > index 9119f735f5..5d90f77bed 100644
> > --- a/xen/arch/x86/domain_page.c
> > +++ b/xen/arch/x86/domain_page.c
> > @@ -18,17 +18,23 @@
> >  #include <asm/hardirq.h>
> >  #include <asm/setup.h>
> >
> > +/*
> > + * Whether v has a mapcache: PV vCPUs (whose domain-wide mapcache may 
> > still be
> > + * disabled, see mapcache_domain_init()).  HVM vCPUs reach everything 
> > through
> > + * the directmap, which covers all physical address space for them.
>
> I've been wondering whether there could be a way to write this comment
> so that it doesn't need rewording once we switch to per-vCPU
> mapcaches, as to avoid adding a comment here that will very likely be
> completely re-worded by a later change in the series.  However I
> cannot find anything much better rather than stripping most of the
> comment content.

I think describing it the way it is, then changing it, makes the
series or the state thereof more clear.  But I'm not precious about
it; we could make it something like this:

/*
 * Whether v may use a mapcache rather than the directmap (a PV domain's
 * mapcache may still be disabled, see mapcache_domain_init()).
 */

That said, as a meta-comment: We have a limited amount of time on my
contract, and also a limited amount of time before we want to check
this in to the tree.  Is spending our time changing non-functional
intermittent git tree state really what you want to spend that time
on?

>
> > + */
> > +static bool has_mapcache(const struct vcpu *v)
> > +{
> > +    return is_pv_vcpu(v);
> > +}
> > +
> >  static inline struct vcpu *mapcache_current_vcpu(void)
> >  {
> >      struct vcpu *v = this_cpu(pgtable_vcpu);
> >      struct vcpu *curr = current;
> >
> > -    /*
> > -     * During early boot pgtable_vcpu is not set, callers must handle NULL.
> > -     * Non-PV domains don't have a mapcache, the directmap covers all 
> > physical
> > -     * address space.
> > -     */
> > -    if ( !v || !is_pv_vcpu(v) )
> > +    /* During early boot pgtable_vcpu is not set, callers must handle 
> > NULL. */
> > +    if ( !v || !has_mapcache(v) )
> >          return NULL;
> >
> >      /*
> > @@ -54,6 +60,55 @@ static inline struct vcpu *mapcache_current_vcpu(void)
> >      return ACCESS_ONCE(this_cpu(pgtable_vcpu));
> >  }
> >
> > +/*
> > + * The accounting for v's mapcache: the domain's, with *dcache set so the
> > + * caller takes the domain-wide lock and TLB-epoch machinery into account.
> > + */
> > +static struct mapcache *vcpu_mapcache(struct vcpu *v,
> > +                                      struct mapcache_domain **dcache)
> > +{
> > +    struct domain *d = v->domain;
> > +
> > +    *dcache = &d->arch.pv.mapcache;
> > +    return &(*dcache)->cache;
> > +}
> > +
> > +/*
> > + * The domain-wide mapcache's lock and TLB-epoch machinery, taken around
> > + * allocating a slot: the domain's vCPUs share the mapcache's slots, and 
> > each
> > + * catches up with a wrap another one caused, flushing its TLB if it has 
> > not
> > + * been flushed since.
>
> Thinking forward about how this function will end up looking when we
> have per-vCPU map caches, do you maybe want to place this comment
> inside the function body itself?
>
> I expect per-vCPU splitting will add a short-circuit at the top of the
> function that will skip taking the lock or doing the flushing, and
> hence the comment won't need shuffling around?

Yup, we can do this.

> > + */
> > +static void mapcache_lock(struct mapcache_domain *dcache,
>
> Maybe mapcache_enter() would be a better suited name once there's no
> longer a need to take a lock for the mapcache?  Just wondering, no
> strong opinion really (the more that I don't even know how the code
> will end up looking yet).

Yeah, can do that.

> > +/* A wrap has just flushed this CPU's TLB: start a new epoch. */
> > +static void mapcache_new_epoch(struct mapcache_domain *dcache,
> > +                               struct mapcache_vcpu *vcache)
> > +{
>
> Since this is now a function on its own, I would possibly assert that
> dcache->lock is taken on entry.
>
> Let me know what you think of the suggestions above, overall I think
> the logic is fine.

Great, thanks.
 -George



 


Rackspace

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