All of lore.kernel.org
 help / color / mirror / Atom feed
From: Marc Zyngier <maz@kernel.org>
To: Oliver Upton <oliver.upton@linux.dev>
Cc: kvmarm@lists.linux.dev, James Morse <james.morse@arm.com>,
	Suzuki K Poulose <suzuki.poulose@arm.com>,
	Zenghui Yu <yuzenghui@huawei.com>,
	Eric Auger <eric.auger@redhat.com>
Subject: Re: [PATCH v2 09/19] KVM: arm64: vgic-its: Maintain a translation cache per ITS
Date: Sun, 21 Apr 2024 20:47:39 +0100	[thread overview]
Message-ID: <87ttjuqyzo.wl-maz@kernel.org> (raw)
In-Reply-To: <ZiVG3JoK1Soe6Eqj@linux.dev>

On Sun, 21 Apr 2024 18:03:24 +0100,
Oliver Upton <oliver.upton@linux.dev> wrote:
> 
> On Sun, Apr 21, 2024 at 11:30:09AM +0100, Marc Zyngier wrote:
> > On Fri, 19 Apr 2024 23:38:32 +0100,
> > Oliver Upton <oliver.upton@linux.dev> wrote:
> 
> [...]
> 
> > > +	if (xa_reserve_irq(&its->translation_cache, cache_key, GFP_KERNEL_ACCOUNT))
> > > +		return;
> > > +
> > 
> > This thing tickles me a bit. What does it mean from the PoV of the
> > caller? That although we have missed in the cache initially, someone
> > else is populating it?
> 
> Sorry, I'm a touch confused. This call is to preallocate space in the
> xarray to store something at index @cache_key. Even if there already was
> a valid entry (meaning no need for memory allocation), xa_reserve()
> ought to return 0.

Yup, I understood that. My question is about its actual effect.  From
a cache "client" perspective, it means that the translation isn't
getting cached because the same translation (in another context) is
being in the process of being cached at the same time.

> 
> > The final code reads like this:
> > 
> > 	if (xa_reserve_irq(&its->translation_cache, cache_key, GFP_KERNEL_ACCOUNT))
> > 		return;
> > 
> > 	xa_lock_irqsave(&its->translation_cache, flags);
> > 	rcu_read_lock();
> > 
> > 	/*
> > 	 * We could have raced with another CPU caching the same
> > 	 * translation behind our back, so let's check it is not in
> > 	 * already
> > 	 */
> > 	db = its->vgic_its_base + GITS_TRANSLATER;
> > 	if (__vgic_its_check_cache(kvm, db, devid, eventid))
> > 		goto out;
> > 
> > Does it mean we could drop this check? And even relax the locking?
> 
> I don't think so, a race still exists. For example, Userspace could issue
> concurrent calls to KVM_SIGNAL_MSI for the same device / event.

Really? When injecting an MSI, either you hit in the cache or you
don't. If you don't, you translate the hard way, then try to fit the
translation in the cache. If if you have a concurrent MSI being
signalled, whoever wins the "reserve" game wins, and it is "their"
translation that will make it into the cache.

At this stage, the locking becomes irrelevant for the purpose of
avoiding concurrent filling of the cache, because reserving serves as
a proxy for the store.

Or am I missing the point completely? Wouldn't be surprising... ;-)

> We could do away with the *explicit* locking if this code were
> restructured to drop references on old entries returned from xa_store(),
> like:
> 
> static void vgic_its_cache_translation(struct kvm *kvm, struct vgic_its *its,
> 				       u32 devid, u32 eventid,
> 				       struct vgic_irq *irq)
> {
> 	unsigned long cache_key = vgic_its_cache_key(devid, eventid);
> 	phys_addr_t db = its->vgic_its_base + GITS_TRANSLATER;
> 	struct vgic_irq *old;
> 
> 	/* Do not cache a directly injected interrupt */
> 	if (irq->hw)
> 		return;
> 
> 	/*
> 	 * The irq refcount is guaranteed to be nonzero while holding the
> 	 * its_lock, as the ITE (and the reference it holds) cannot be freed.
> 	 */
> 	lockdep_assert_held(&its->its_lock);
> 	vgic_get_irq_kref(irq);
> 
> 	/*
> 	 * We could have raced with another CPU caching the same translation
> 	 * behind our back. Ensure we don't leak a reference if that is the case.
> 	 */
> 	old = xa_store_irq(&its->translation_cache, cache_key, irq, GFP_KERNEL_ACCOUNT);
> 	if (old)
> 		vgic_put_irq(old);
> }

Exactly. By relying on the xarray for synchronisation, we can avoid
holding any extra lock and playing the reserve game. I'm pretty keen
on this version.

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.

  reply	other threads:[~2024-04-21 19:47 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-04-19 22:38 [PATCH v2 00/19] KVM: arm64: Transition to a per-ITS translation cache Oliver Upton
2024-04-19 22:38 ` [PATCH v2 01/19] KVM: Treat the device list as an rculist Oliver Upton
2024-04-22 18:30   ` Sean Christopherson
2024-04-22 18:35     ` Oliver Upton
2024-04-19 22:38 ` [PATCH v2 02/19] KVM: arm64: vgic-its: Walk LPI xarray in its_sync_lpi_pending_table() Oliver Upton
2024-04-19 22:38 ` [PATCH v2 03/19] KVM: arm64: vgic-its: Walk LPI xarray in vgic_its_invall() Oliver Upton
2024-04-19 22:38 ` [PATCH v2 04/19] KVM: arm64: vgic-its: Walk LPI xarray in vgic_its_cmd_handle_movall() Oliver Upton
2024-04-19 22:38 ` [PATCH v2 05/19] KVM: arm64: vgic-debug: Use an xarray mark for debug iterator Oliver Upton
2024-04-19 22:38 ` [PATCH v2 06/19] KVM: arm64: vgic-its: Get rid of vgic_copy_lpi_list() Oliver Upton
2024-04-19 22:38 ` [PATCH v2 07/19] KVM: arm64: vgic-its: Scope translation cache invalidations to an ITS Oliver Upton
2024-04-21  9:54   ` Marc Zyngier
2024-04-21 16:30     ` Oliver Upton
2024-04-19 22:38 ` [PATCH v2 08/19] KVM: arm64: vgic-its: Spin off helper for finding ITS by doorbell addr Oliver Upton
2024-04-19 22:38 ` [PATCH v2 09/19] KVM: arm64: vgic-its: Maintain a translation cache per ITS Oliver Upton
2024-04-20 19:08   ` Marc Zyngier
2024-04-21  7:28     ` Oliver Upton
2024-04-21 10:30   ` Marc Zyngier
2024-04-21 17:03     ` Oliver Upton
2024-04-21 19:47       ` Marc Zyngier [this message]
2024-04-21 20:58         ` Oliver Upton
2024-04-19 22:38 ` [PATCH v2 10/19] KVM: arm64: vgic-its: Use the per-ITS translation cache for injection Oliver Upton
2024-04-19 22:38 ` [PATCH v2 11/19] KVM: arm64: vgic-its: Rip out the global translation cache Oliver Upton
2024-04-19 22:38 ` [PATCH v2 12/19] KVM: arm64: vgic-its: Get rid of the lpi_list_lock Oliver Upton
2024-04-19 22:38 ` [PATCH v2 13/19] KVM: selftests: Align with kernel's GIC definitions Oliver Upton
2024-04-19 22:38 ` [PATCH v2 14/19] KVM: selftests: Standardise layout of GIC frames Oliver Upton
2024-04-19 22:38 ` [PATCH v2 15/19] KVM: selftests: Add quadword MMIO accessors Oliver Upton
2024-04-19 22:38 ` [PATCH v2 16/19] KVM: selftests: Add a minimal library for interacting with an ITS Oliver Upton
2024-04-19 22:38 ` [PATCH v2 17/19] KVM: selftests: Add helper for enabling LPIs on a redistributor Oliver Upton
2024-04-19 22:38 ` [PATCH v2 18/19] KVM: selftests: Use MPIDR_HWID_BITMASK from cputype.h Oliver Upton
2024-04-19 22:38 ` [PATCH v2 19/19] KVM: selftests: Add stress test for LPI injection Oliver Upton

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87ttjuqyzo.wl-maz@kernel.org \
    --to=maz@kernel.org \
    --cc=eric.auger@redhat.com \
    --cc=james.morse@arm.com \
    --cc=kvmarm@lists.linux.dev \
    --cc=oliver.upton@linux.dev \
    --cc=suzuki.poulose@arm.com \
    --cc=yuzenghui@huawei.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.