All of lore.kernel.org
 help / color / mirror / Atom feed
From: Marc Zyngier <maz@kernel.org>
To: Sascha Bischoff <Sascha.Bischoff@arm.com>
Cc: "linux-arm-kernel@lists.infradead.org"
	<linux-arm-kernel@lists.infradead.org>,
	"kvmarm@lists.linux.dev" <kvmarm@lists.linux.dev>,
	"kvm@vger.kernel.org" <kvm@vger.kernel.org>, nd <nd@arm.com>,
	"oliver.upton@linux.dev" <oliver.upton@linux.dev>,
	Joey Gouly <Joey.Gouly@arm.com>,
	Suzuki Poulose <Suzuki.Poulose@arm.com>,
	"yuzenghui@huawei.com" <yuzenghui@huawei.com>,
	"peter.maydell@linaro.org" <peter.maydell@linaro.org>,
	"lpieralisi@kernel.org" <lpieralisi@kernel.org>,
	Timothy Hayes <Timothy.Hayes@arm.com>
Subject: Re: [PATCH 15/32] KVM: arm64: gic-v5: Implement direct injection of PPIs
Date: Wed, 17 Dec 2025 11:40:31 +0000	[thread overview]
Message-ID: <861pktnxow.wl-maz@kernel.org> (raw)
In-Reply-To: <20251212152215.675767-16-sascha.bischoff@arm.com>

On Fri, 12 Dec 2025 15:22:40 +0000,
Sascha Bischoff <Sascha.Bischoff@arm.com> wrote:
> 
> GICv5 is able to directly inject PPI pending state into a guest using
> a mechanism called DVI whereby the pending bit for a paticular PPI is
> driven directly by the physically-connected hardware. This mechanism
> itself doesn't allow for any ID translation, so the host interrupt is
> directly mapped into a guest with the same interrupt ID.
> 
> When mapping a virtual interrupt to a physical interrupt via
> kvm_vgic_map_irq for a GICv5 guest, check if the interrupt itself is a
> PPI or not. If it is, and the host's interrupt ID matches that used
> for the guest DVI is enabled, and the interrupt itself is marked as
> directly_injected.
> 
> When the interrupt is unmapped again, this process is reversed, and
> DVI is disabled for the interrupt again.
> 
> Note: the expectation is that a directly injected PPI is disabled on
> the host while the guest state is loaded. The reason is that although
> DVI is enabled to drive the guest's pending state directly, the host
> pending state also remains driven. In order to avoid the same PPI
> firing on both the host and the guest, the host's interrupt must be
> disabled (masked). This is left up to the code that owns the device
> generating the PPI as this needs to be handled on a per-VM basis. One
> VM might use DVI, while another might not, in which case the physical
> PPI should be enabled for the latter.
> 
> Co-authored-by: Timothy Hayes <timothy.hayes@arm.com>
> Signed-off-by: Timothy Hayes <timothy.hayes@arm.com>
> Signed-off-by: Sascha Bischoff <sascha.bischoff@arm.com>
> ---
>  arch/arm64/kvm/vgic/vgic-v5.c | 22 ++++++++++++++++++++++
>  arch/arm64/kvm/vgic/vgic.c    | 16 ++++++++++++++++
>  arch/arm64/kvm/vgic/vgic.h    |  1 +
>  include/kvm/arm_vgic.h        |  1 +
>  4 files changed, 40 insertions(+)
> 
> diff --git a/arch/arm64/kvm/vgic/vgic-v5.c b/arch/arm64/kvm/vgic/vgic-v5.c
> index 2fb2db23ed39a..22558080711eb 100644
> --- a/arch/arm64/kvm/vgic/vgic-v5.c
> +++ b/arch/arm64/kvm/vgic/vgic-v5.c
> @@ -54,6 +54,28 @@ int vgic_v5_probe(const struct gic_kvm_info *info)
>  	return 0;
>  }
>  
> +/*
> + * Sets/clears the corresponding bit in the ICH_PPI_DVIR register.
> + */
> +int vgic_v5_set_ppi_dvi(struct kvm_vcpu *vcpu, u32 irq, bool dvi)
> +{
> +	struct vgic_v5_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v5;
> +	u32 ppi = FIELD_GET(GICV5_HWIRQ_ID, irq);
> +
> +	if (ppi >= 128)
> +		return -EINVAL;

Surely this is bad. *very* bad. How can we get here the first place?

> +
> +	if (dvi) {
> +		/* Set the bit */
> +		cpu_if->vgic_ppi_dvir[ppi / 64] |= 1UL << (ppi % 64);
> +	} else {
> +		/* Clear the bit */
> +		cpu_if->vgic_ppi_dvir[ppi / 64] &= ~(1UL << (ppi % 64));
> +	}

This should be simplified:

diff --git a/arch/arm64/kvm/vgic/vgic-v5.c b/arch/arm64/kvm/vgic/vgic-v5.c
index d74cc3543b9a4..f434ee85f7e1a 100644
--- a/arch/arm64/kvm/vgic/vgic-v5.c
+++ b/arch/arm64/kvm/vgic/vgic-v5.c
@@ -191,8 +191,8 @@ bool vgic_v5_ppi_set_pending_state(struct kvm_vcpu *vcpu,
 				   struct vgic_irq *irq)
 {
 	struct vgic_v5_cpu_if *cpu_if;
-	const u32 id_bit = BIT_ULL(irq->intid % 64);
 	const u32 reg = FIELD_GET(GICV5_HWIRQ_ID, irq->intid) / 64;
+	unsigned long *p;
 
 	if (!vcpu || !irq)
 		return false;
@@ -203,10 +203,8 @@ bool vgic_v5_ppi_set_pending_state(struct kvm_vcpu *vcpu,
 
 	cpu_if = &vcpu->arch.vgic_cpu.vgic_v5;
 
-	if (irq_is_pending(irq))
-		cpu_if->vgic_ppi_pendr[reg] |= id_bit;
-	else
-		cpu_if->vgic_ppi_pendr[reg] &= ~id_bit;
+	p = (unsigned long *)&cpu_if->vgic_ppi_pendr[reg];
+	__assign_bit(irq->intid % 64, p, irq_is_pending(irq));
 
 	return true;
 }
@@ -449,17 +447,13 @@ int vgic_v5_set_ppi_dvi(struct kvm_vcpu *vcpu, u32 irq, bool dvi)
 {
 	struct vgic_v5_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v5;
 	u32 ppi = FIELD_GET(GICV5_HWIRQ_ID, irq);
+	unsigned long *p;
 
 	if (ppi >= 128)
 		return -EINVAL;
 
-	if (dvi) {
-		/* Set the bit */
-		cpu_if->vgic_ppi_dvir[ppi / 64] |= 1UL << (ppi % 64);
-	} else {
-		/* Clear the bit */
-		cpu_if->vgic_ppi_dvir[ppi / 64] &= ~(1UL << (ppi % 64));
-	}
+	p = (unsigned long *)&cpu_if->vgic_ppi_dvir[ppi / 64];
+	__assign_bit(ppi % 64, p, dvi);
 
 	return 0;
 }

(yes, unsigned long and u64 are the same thing on any sane
architecture).

> +
> +	return 0;
> +}
> +
>  void vgic_v5_load(struct kvm_vcpu *vcpu)
>  {
>  	struct vgic_v5_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v5;
> diff --git a/arch/arm64/kvm/vgic/vgic.c b/arch/arm64/kvm/vgic/vgic.c
> index 1005ff5f36235..1fe3dcc997860 100644
> --- a/arch/arm64/kvm/vgic/vgic.c
> +++ b/arch/arm64/kvm/vgic/vgic.c
> @@ -577,12 +577,28 @@ static int kvm_vgic_map_irq(struct kvm_vcpu *vcpu, struct vgic_irq *irq,
>  	irq->host_irq = host_irq;
>  	irq->hwintid = data->hwirq;
>  	irq->ops = ops;
> +
> +	if (vgic_is_v5(vcpu->kvm)) {
> +		/* Nothing for us to do */
> +		if (!irq_is_ppi_v5(irq->intid))
> +			return 0;
> +
> +		if (FIELD_GET(GICV5_HWIRQ_ID, irq->intid) == irq->hwintid) {
> +			if (!vgic_v5_set_ppi_dvi(vcpu, irq->hwintid, true))
> +				irq->directly_injected = true;

The error handling gives me the creeps. If we can end-up at this stage
with the wrong INTID, we're screwed.

> +		}
> +	}
> +
>  	return 0;
>  }
>  
>  /* @irq->irq_lock must be held */
>  static inline void kvm_vgic_unmap_irq(struct vgic_irq *irq)
>  {
> +	if (irq->directly_injected && vgic_is_v5(irq->target_vcpu->kvm))
> +		WARN_ON(vgic_v5_set_ppi_dvi(irq->target_vcpu, irq->hwintid, false));
> +
> +	irq->directly_injected = false;
>  	irq->hw = false;
>  	irq->hwintid = 0;
>  	irq->ops = NULL;
> diff --git a/arch/arm64/kvm/vgic/vgic.h b/arch/arm64/kvm/vgic/vgic.h
> index 6e1f386dffade..b6e3f5e3aba18 100644
> --- a/arch/arm64/kvm/vgic/vgic.h
> +++ b/arch/arm64/kvm/vgic/vgic.h
> @@ -363,6 +363,7 @@ void vgic_debug_init(struct kvm *kvm);
>  void vgic_debug_destroy(struct kvm *kvm);
>  
>  int vgic_v5_probe(const struct gic_kvm_info *info);
> +int vgic_v5_set_ppi_dvi(struct kvm_vcpu *vcpu, u32 irq, bool dvi);
>  void vgic_v5_load(struct kvm_vcpu *vcpu);
>  void vgic_v5_put(struct kvm_vcpu *vcpu);
>  void vgic_v5_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
> diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
> index 45d83f45b065d..ce9e149b85a58 100644
> --- a/include/kvm/arm_vgic.h
> +++ b/include/kvm/arm_vgic.h
> @@ -163,6 +163,7 @@ struct vgic_irq {
>  	bool enabled:1;
>  	bool active:1;
>  	bool hw:1;			/* Tied to HW IRQ */
> +	bool directly_injected:1;	/* A directly injected HW IRQ */
>  	bool on_lr:1;			/* Present in a CPU LR */
>  	refcount_t refcount;		/* Used for LPIs */
>  	u32 hwintid;			/* HW INTID number */

Thanks,

	M.

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

  reply	other threads:[~2025-12-17 11:40 UTC|newest]

Thread overview: 73+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-12-12 15:22 [PATCH 00/32] KVM: arm64: Introduce vGIC-v5 with PPI support Sascha Bischoff
2025-12-12 15:22 ` [PATCH 02/32] KVM: arm64: gic-v3: Switch vGIC-v3 to use generated ICH_VMCR_EL2 Sascha Bischoff
2025-12-15 11:52   ` Marc Zyngier
2025-12-15 14:15     ` Sascha Bischoff
2025-12-12 15:22 ` [PATCH 01/32] KVM: arm64: Account for RES1 bits in DECLARE_FEAT_MAP() and co Sascha Bischoff
2025-12-12 15:22 ` [PATCH 04/32] arm64/sysreg: Add remaining GICv5 ICC_ & ICH_ sysregs for KVM support Sascha Bischoff
2025-12-12 15:22 ` [PATCH 03/32] arm64/sysreg: Drop ICH_HFGRTR_EL2.ICC_HAPR_EL1 and make RES1 Sascha Bischoff
2025-12-12 15:22 ` [PATCH 05/32] arm64/sysreg: Add GICR CDNMIA encoding Sascha Bischoff
2025-12-12 15:22 ` [PATCH 06/32] KVM: arm64: gic-v5: Add ARM_VGIC_V5 device to KVM headers Sascha Bischoff
2025-12-12 15:22 ` [PATCH 07/32] KVM: arm64: gic: Introduce interrupt type helpers Sascha Bischoff
2025-12-15 13:32   ` Marc Zyngier
2025-12-15 16:01     ` Sascha Bischoff
2025-12-15 16:05     ` Marc Zyngier
2025-12-16  8:57       ` Sascha Bischoff
2025-12-12 15:22 ` [PATCH 08/32] KVM: arm64: gic-v5: Sanitize ID_AA64PFR2_EL1.GCIE Sascha Bischoff
2025-12-12 15:22 ` [PATCH 10/32] KVM: arm64: gic-v5: Add emulation for ICC_IAFFID_EL1 accesses Sascha Bischoff
2025-12-15 17:31   ` Marc Zyngier
2025-12-16 10:57     ` Sascha Bischoff
2025-12-12 15:22 ` [PATCH 09/32] KVM: arm64: gic-v5: Compute GICv5 FGTs on vcpu load Sascha Bischoff
2025-12-12 16:24   ` Marc Zyngier
2025-12-15 17:37     ` Sascha Bischoff
2025-12-12 15:22 ` [PATCH 13/32] KVM: arm64: gic-v5: Add vgic-v5 save/restore hyp interface Sascha Bischoff
2025-12-17 11:07   ` Marc Zyngier
2025-12-17 21:42     ` Sascha Bischoff
2025-12-12 15:22 ` [PATCH 11/32] KVM: arm64: gic-v5: Trap and emulate ICH_PPI_HMRx_EL1 accesses Sascha Bischoff
2025-12-16 10:41   ` Marc Zyngier
2025-12-16 11:54     ` Sascha Bischoff
2025-12-16 15:09       ` Marc Zyngier
2025-12-12 15:22 ` [PATCH 12/32] KVM: arm64: gic: Set vgic_model before initing private IRQs Sascha Bischoff
2025-12-12 15:22 ` [PATCH 14/32] KVM: arm64: gic-v5: Implement GICv5 load/put and save/restore Sascha Bischoff
2025-12-13  5:59   ` kernel test robot
2025-12-15 10:54     ` Sascha Bischoff
2025-12-13  8:05   ` kernel test robot
2025-12-22 16:52   ` kernel test robot
2025-12-12 15:22 ` [PATCH 15/32] KVM: arm64: gic-v5: Implement direct injection of PPIs Sascha Bischoff
2025-12-17 11:40   ` Marc Zyngier [this message]
2026-01-07 14:50     ` Sascha Bischoff
2025-12-12 15:22 ` [PATCH 16/32] KVM: arm64: gic: Introduce irq_queue and set_pending_state to irq_ops Sascha Bischoff
2025-12-17  9:34   ` Marc Zyngier
2025-12-17 20:50     ` Sascha Bischoff
2025-12-12 15:22 ` [PATCH 19/32] KVM: arm64: gic-v5: Init Private IRQs (PPIs) for GICv5 Sascha Bischoff
2025-12-17 17:13   ` Marc Zyngier
2025-12-12 15:22 ` [PATCH 17/32] KVM: arm64: gic-v5: Implement PPI interrupt injection Sascha Bischoff
2025-12-17 10:33   ` Marc Zyngier
2025-12-17 21:10     ` Sascha Bischoff
2025-12-17 15:54   ` Joey Gouly
2026-01-07 16:28     ` Sascha Bischoff
2025-12-12 15:22 ` [PATCH 18/32] KVM: arm64: gic-v5: Check for pending PPIs Sascha Bischoff
2025-12-17 11:49   ` Joey Gouly
2025-12-17 12:00     ` Joey Gouly
2025-12-18  8:17       ` Sascha Bischoff
2025-12-17 14:29   ` Marc Zyngier
2026-01-07 15:59     ` Sascha Bischoff
2025-12-12 15:22 ` [PATCH 22/32] KVM: arm64: gic-v5: Reset vcpu state Sascha Bischoff
2025-12-12 15:22 ` [PATCH 21/32] KVM: arm64: gic-v5: Create, init vgic_v5 Sascha Bischoff
2025-12-12 15:22 ` [PATCH 20/32] KVM: arm64: gic-v5: Support GICv5 interrupts with KVM_IRQ_LINE Sascha Bischoff
2025-12-12 15:22 ` [PATCH 24/32] KVM: arm64: gic-v5: Mandate architected PPI for PMU emulation on GICv5 Sascha Bischoff
2025-12-12 15:22 ` [PATCH 23/32] KVM: arm64: gic-v5: Bump arch timer for GICv5 Sascha Bischoff
2025-12-15 15:50   ` Marc Zyngier
2025-12-16 10:55     ` Sascha Bischoff
2025-12-12 15:22 ` [PATCH 26/32] KVM: arm64: gic-v5: Hide FEAT_GCIE from NV GICv5 guests Sascha Bischoff
2025-12-12 15:22 ` [PATCH 25/32] KVM: arm64: gic: Hide GICv5 for protected guests Sascha Bischoff
2025-12-12 15:22 ` [PATCH 28/32] KVM: arm64: gic-v5: Set ICH_VCTLR_EL2.En on boot Sascha Bischoff
2025-12-12 15:22 ` [PATCH 27/32] KVM: arm64: gic-v5: Introduce kvm_arm_vgic_v5_ops and register them Sascha Bischoff
2025-12-12 15:22 ` [PATCH 29/32] irqchip/gic-v5: Check if impl is virt capable Sascha Bischoff
2025-12-16 15:40   ` Lorenzo Pieralisi
2025-12-17 20:46     ` Sascha Bischoff
2025-12-12 15:22 ` [PATCH 30/32] KVM: arm64: gic-v5: Probe for GICv5 device Sascha Bischoff
2025-12-12 15:22 ` [PATCH 32/32] KVM: arm64: selftests: Introduce a minimal GICv5 PPI selftest Sascha Bischoff
2025-12-12 15:22 ` [PATCH 31/32] Documentation: KVM: Introduce documentation for VGICv5 Sascha Bischoff
2025-12-15  0:15   ` kernel test robot
2025-12-15  9:56   ` Peter Maydell
2025-12-15 13:01     ` Sascha Bischoff

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=861pktnxow.wl-maz@kernel.org \
    --to=maz@kernel.org \
    --cc=Joey.Gouly@arm.com \
    --cc=Sascha.Bischoff@arm.com \
    --cc=Suzuki.Poulose@arm.com \
    --cc=Timothy.Hayes@arm.com \
    --cc=kvm@vger.kernel.org \
    --cc=kvmarm@lists.linux.dev \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=lpieralisi@kernel.org \
    --cc=nd@arm.com \
    --cc=oliver.upton@linux.dev \
    --cc=peter.maydell@linaro.org \
    --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.