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: Sat, 20 Apr 2024 20:08:36 +0100	[thread overview]
Message-ID: <87wmorrgwb.wl-maz@kernel.org> (raw)
In-Reply-To: <20240419223842.951452-10-oliver.upton@linux.dev>

On Fri, 19 Apr 2024 23:38:32 +0100,
Oliver Upton <oliver.upton@linux.dev> wrote:
> 
> Within the context of a single ITS, it is possible to use an xarray to
> cache the device ID & event ID translation to a particular irq
> descriptor. Take advantage of this to build a translation cache capable
> of fitting all valid translations for a given ITS.
> 
> Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
> ---
>  arch/arm64/kvm/vgic/vgic-its.c | 26 +++++++++++++++++++++++++-
>  include/kvm/arm_vgic.h         |  6 ++++++
>  2 files changed, 31 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/kvm/vgic/vgic-its.c b/arch/arm64/kvm/vgic/vgic-its.c
> index be17a53d16ef..fd576377c084 100644
> --- a/arch/arm64/kvm/vgic/vgic-its.c
> +++ b/arch/arm64/kvm/vgic/vgic-its.c
> @@ -530,6 +530,11 @@ static struct vgic_its *__vgic_doorbell_to_its(struct kvm *kvm, gpa_t db)
>  	return iodev->its;
>  }
>  
> +static unsigned long vgic_its_cache_key(u32 devid, u32 eventid)
> +{
> +	return (((unsigned long)devid) << 32) | eventid;
> +}
> +

Although this is correct, you may want to use the fact that our
EIDs/DIDs are limited to 16 bits, as advertised in GITS_TYPER. By
having a more compact index, you'd get better performance from the
xarray itself (this is alluded to in the documentation).

>  static struct vgic_irq *__vgic_its_check_cache(struct vgic_dist *dist,
>  					       phys_addr_t db,
>  					       u32 devid, u32 eventid)
> @@ -583,6 +588,7 @@ 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);
>  	struct vgic_dist *dist = &kvm->arch.vgic;
>  	struct vgic_translation_cache_entry *cte;
>  	unsigned long flags;
> @@ -592,6 +598,9 @@ static void vgic_its_cache_translation(struct kvm *kvm, struct vgic_its *its,
>  	if (irq->hw)
>  		return;
>  
> +	if (xa_reserve_irq(&its->translation_cache, cache_key, GFP_KERNEL_ACCOUNT))
> +		return;
> +
>  	raw_spin_lock_irqsave(&dist->lpi_list_lock, flags);
>  
>  	if (unlikely(list_empty(&dist->lpi_translation_cache)))
> @@ -624,6 +633,11 @@ static void vgic_its_cache_translation(struct kvm *kvm, struct vgic_its *its,
>  	 */
>  	lockdep_assert_held(&its->its_lock);
>  	vgic_get_irq_kref(irq);
> +	/*
> +	 * Get a second ref for the ITS' translation cache. This will
> +	 * disappear.

Is that for the *global* translation cache? Or this one? I guess there
is one for each, but a clearer comment would help, even if this gets
removed three patches down the line.

> +	 */
> +	vgic_get_irq_kref(irq);
>  
>  	cte->db		= db;
>  	cte->devid	= devid;
> @@ -633,6 +647,7 @@ static void vgic_its_cache_translation(struct kvm *kvm, struct vgic_its *its,
>  	/* Move the new translation to the head of the list */
>  	list_move(&cte->entry, &dist->lpi_translation_cache);
>  
> +	xa_store(&its->translation_cache, cache_key, irq, 0);
>  out:
>  	raw_spin_unlock_irqrestore(&dist->lpi_list_lock, flags);
>  }
> @@ -641,7 +656,8 @@ static void vgic_its_invalidate_cache(struct vgic_its *its)
>  {
>  	struct vgic_dist *dist = &kvm->arch.vgic;
>  	struct vgic_translation_cache_entry *cte;
> -	unsigned long flags;
> +	unsigned long flags, idx;
> +	struct vgic_irq *irq;
>  
>  	raw_spin_lock_irqsave(&dist->lpi_list_lock, flags);
>  
> @@ -658,6 +674,11 @@ static void vgic_its_invalidate_cache(struct vgic_its *its)
>  	}
>  
>  	raw_spin_unlock_irqrestore(&dist->lpi_list_lock, flags);
> +
> +	xa_for_each(&its->translation_cache, idx, irq) {
> +		xa_erase(&its->translation_cache, idx);
> +		vgic_put_irq(its->dev->kvm, irq);
> +	}
>  }
>  
>  void vgic_its_invalidate_all_caches(struct kvm *kvm)
> @@ -1967,6 +1988,7 @@ static int vgic_its_create(struct kvm_device *dev, u32 type)
>  
>  	INIT_LIST_HEAD(&its->device_list);
>  	INIT_LIST_HEAD(&its->collection_list);
> +	xa_init_flags(&its->translation_cache, XA_FLAGS_LOCK_IRQ);
>  
>  	dev->kvm->arch.vgic.msis_require_devid = true;
>  	dev->kvm->arch.vgic.has_its = true;
> @@ -1997,6 +2019,8 @@ static void vgic_its_destroy(struct kvm_device *kvm_dev)
>  
>  	vgic_its_free_device_list(kvm, its);
>  	vgic_its_free_collection_list(kvm, its);
> +	vgic_its_invalidate_cache(its);
> +	xa_destroy(&its->translation_cache);
>  
>  	mutex_unlock(&its->its_lock);
>  	kfree(its);
> diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
> index ac7f15ec1586..0b027ed71dac 100644
> --- a/include/kvm/arm_vgic.h
> +++ b/include/kvm/arm_vgic.h
> @@ -210,6 +210,12 @@ struct vgic_its {
>  	struct mutex		its_lock;
>  	struct list_head	device_list;
>  	struct list_head	collection_list;
> +
> +	/*
> +	 * Caches the (device_id, event_id) -> vgic_irq translation for
> +	 * *deliverable* LPIs.

Can you clarify what "deliverable" LPIs are? That's not an
architectural term, and I'd rather you describe the conditions that
allow the LPI to be cached (my guess is: mapped and enabled).

> +	 */
> +	struct xarray		translation_cache;
>  };
>  
>  struct vgic_state_iter;

Thanks,

	M.

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

  reply	other threads:[~2024-04-20 19:08 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 [this message]
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
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=87wmorrgwb.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.