All of lore.kernel.org
 help / color / mirror / Atom feed
From: Maximilian Dittgen <mdittgen@amazon.de>
To: <maz@kernel.org>, <oliver.upton@linux.dev>
Cc: <pbonzini@redhat.com>, <shuah@kernel.org>,
	<linux-arm-kernel@lists.infradead.org>, <kvmarm@lists.linux.dev>,
	<linux-kselftest@vger.kernel.org>, <kvm@vger.kernel.org>,
	<mdittgen@amazon.de>, <lilitj@amazon.de>, <sauravsc@amazon.de>,
	<nh-open-source@amazon.com>
Subject: [RFC PATCH 01/13] KVM: Introduce config option for per-vCPU vLPI enablement
Date: Thu, 20 Nov 2025 15:02:50 +0100	[thread overview]
Message-ID: <20251120140305.63515-2-mdittgen@amazon.de> (raw)
In-Reply-To: <20251120140305.63515-1-mdittgen@amazon.de>

Add CONFIG_ARM_GIC_V3_PER_VCPU_VLPI to control whether vLPI direct
injection is to be enabled on a system-wide or a per-vCPU basis.

When enabled, vPEs can be allocated/deallocated to vCPUs on an ad-hoc,
per-vCPU basis in runtime. When disabled, keep current vgic_v4_init
behavior of automatic vCPU vPE allocation upon VM initialization.

We declare three ioctls numbers to manage per-vCPU vLPI enablement:
- KVM_ENABLE_VCPU_VLPI, which given a vCPU ID, allocates a vPE and
initializes the vCPU for receiving direct vLPI interrupts.
- KVM_DISABLE_VCPU_VLPI, which given a vCPU ID, disables the vCPU’s
ability to receive direct vLPI interrupts and frees its underlying vPE
structure.
- KVM_QUERY_VCPU_VLPI, which given a vCPU ID, returns a boolean
describing whether the vCPU is configured to receive direct vLPI
interrupts.

This commit declares the kconfig, ioctl numbers, and documentation.
Implementation will come throughout this patch set.

Signed-off-by: Maximilian Dittgen <mdittgen@amazon.de>
---
 Documentation/virt/kvm/api.rst | 56 ++++++++++++++++++++++++++++++++++
 arch/arm64/kvm/arm.c           | 15 +++++++++
 arch/arm64/kvm/vgic/vgic-v4.c  |  9 ++++++
 arch/arm64/kvm/vgic/vgic.h     |  2 ++
 drivers/irqchip/Kconfig        | 13 ++++++++
 include/uapi/linux/kvm.h       |  6 ++++
 6 files changed, 101 insertions(+)

diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
index 27f726ff8fe0..dcfb326dff10 100644
--- a/Documentation/virt/kvm/api.rst
+++ b/Documentation/virt/kvm/api.rst
@@ -6517,6 +6517,62 @@ the capability to be present.
 
 `flags` must currently be zero.
 
+4.XXX KVM_ENABLE_VCPU_VLPI
+--------------------------
+
+:Capability: KVM_CAP_ARM_PER_VCPU_VLPI
+:Architectures: arm64
+:Type: vm ioctl
+:Parameters: int vcpu_id (in)
+:Returns: 0 on success, negative value on error
+
+This ioctl enables GICv4 direct vLPI injection for the specified vCPU.
+Allocates vPE structures (doorbell IRQ, vPE table entry, virtual pending
+table, vPEID) and upgrades existing software-forwarded LPIs targeting
+this vCPU to hardware-forwarded vLPIs.
+
+If GICv4.1 is supported and vSGIs are disabled on the specified vCPU,
+this ioctl enables vCPU vSGI support.
+
+Requires CONFIG_ARM_GIC_V3_PER_VCPU_VLPI and GICv4 hardware support.
+
+Returns -EINVAL if vGICv4 is not initialized or if the passed vcpu_id
+does not map to a vCPU.
+
+4.XXX KVM_DISABLE_VCPU_VLPI
+---------------------------
+
+:Capability: KVM_CAP_ARM_PER_VCPU_VLPI
+:Architectures: arm64
+:Type: vm ioctl
+:Parameters: int vcpu_id (in)
+:Returns: 0 on success, negative value on error
+
+This ioctl disables GICv4 direct vLPI injection for the specified vCPU.
+Downgrades hardware-forwarded vLPIs to software-forwarded LPIs and frees
+vPE structures. Pending interrupts in the virtual pending table may be
+lost.
+
+If vSGIs are enabled on the specified vCPU, this ioctl disables them.
+
+Returns -EINVAL if vGICv4 is not initialized or if the passed vcpu_id
+does not map to a vCPU.
+
+4.XXX KVM_QUERY_VCPU_VLPI
+-------------------------
+
+:Capability: KVM_CAP_ARM_PER_VCPU_VLPI
+:Architectures: arm64
+:Type: vm ioctl
+:Parameters: int vcpu_id (in)
+:Returns: 1 if enabled, 0 if disabled, negative value on error
+
+This ioctl queries whether GICv4 direct vLPI injection is enabled for
+the specified vCPU.
+
+Returns -EINVAL if vGICv4 is not initialized or if the passed vcpu_id
+does not map to a vCPU.
+
 
 .. _kvm_run:
 
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index 452d0c85281e..2839e11ba2c1 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -424,6 +424,9 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
 		else
 			r = kvm_supports_cacheable_pfnmap();
 		break;
+	case KVM_CAP_ARM_PER_VCPU_VLPI:
+		r = kvm_per_vcpu_vlpi_supported();
+		break;
 
 	default:
 		r = 0;
@@ -1947,6 +1950,18 @@ int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
 			return -EFAULT;
 		return kvm_vm_ioctl_get_reg_writable_masks(kvm, &range);
 	}
+	case KVM_ENABLE_VCPU_VLPI: {
+		/* TODO: create ioctl handler function */
+		return -ENOSYS;
+	}
+	case KVM_DISABLE_VCPU_VLPI: {
+		/* TODO: create ioctl handler function */
+		return -ENOSYS;
+	}
+	case KVM_QUERY_VCPU_VLPI: {
+		/* TODO: create ioctl handler function */
+		return -ENOSYS;
+	}
 	default:
 		return -EINVAL;
 	}
diff --git a/arch/arm64/kvm/vgic/vgic-v4.c b/arch/arm64/kvm/vgic/vgic-v4.c
index 09c3e9eb23f8..9ef12c33b3f7 100644
--- a/arch/arm64/kvm/vgic/vgic-v4.c
+++ b/arch/arm64/kvm/vgic/vgic-v4.c
@@ -226,6 +226,15 @@ void vgic_v4_get_vlpi_state(struct vgic_irq *irq, bool *val)
 	*val = !!(*ptr & mask);
 }
 
+bool kvm_per_vcpu_vlpi_supported(void)
+{
+#ifdef CONFIG_ARM_GIC_V3_PER_VCPU_VLPI
+	return kvm_vgic_global_state.has_gicv4;
+#else
+	return false;
+#endif
+}
+
 int vgic_v4_request_vpe_irq(struct kvm_vcpu *vcpu, int irq)
 {
 	return request_irq(irq, vgic_v4_doorbell_handler, 0, "vcpu", vcpu);
diff --git a/arch/arm64/kvm/vgic/vgic.h b/arch/arm64/kvm/vgic/vgic.h
index 5f0fc96b4dc2..99894806a4e9 100644
--- a/arch/arm64/kvm/vgic/vgic.h
+++ b/arch/arm64/kvm/vgic/vgic.h
@@ -467,4 +467,6 @@ static inline bool vgic_is_v3(struct kvm *kvm)
 int vgic_its_debug_init(struct kvm_device *dev);
 void vgic_its_debug_destroy(struct kvm_device *dev);
 
+bool kvm_per_vcpu_vlpi_supported(void);
+
 #endif
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index a61c6dc63c29..1c3e0c6d3177 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -52,6 +52,19 @@ config ARM_GIC_V3_ITS
 	default ARM_GIC_V3
 	select IRQ_MSI_IOMMU
 
+config ARM_GIC_V3_PER_VCPU_VLPI
+	bool "ARM GICv4 per-vCPU vLPI direct injection support"
+	depends on ARM_GIC_V3_ITS
+	default n
+	help
+	  Enable GICv4 direct injection of MSIs as vLPIs on a per vCPU
+	  basis. Enables partial vLPI enablement on systems with more
+	  vCPU capacity than vPE capacity. When enabled, all vCPUs
+	  will boot without GICv4 vPE structures and handle interrupts
+	  as software LPIs. KVM_ENABLE_VCPU_VLPI ioctl must then be called on
+	  individual vCPUs to initialize their GICv4 structs and upgrade
+	  targeting LPIs to vLPIs.
+
 config ARM_GIC_V3_ITS_FSL_MC
 	bool
 	depends on ARM_GIC_V3_ITS
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 1e541193e98d..002fe0f4841d 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -973,6 +973,7 @@ struct kvm_enable_cap {
 #define KVM_CAP_ARM_CACHEABLE_PFNMAP_SUPPORTED 243
 #define KVM_CAP_GUEST_MEMFD_FLAGS 244
 #define KVM_CAP_ARM_SEA_TO_USER 245
+#define KVM_CAP_ARM_PER_VCPU_VLPI 246
 
 struct kvm_irq_routing_irqchip {
 	__u32 irqchip;
@@ -1451,6 +1452,11 @@ struct kvm_enc_region {
 #define KVM_GET_SREGS2             _IOR(KVMIO,  0xcc, struct kvm_sregs2)
 #define KVM_SET_SREGS2             _IOW(KVMIO,  0xcd, struct kvm_sregs2)
 
+/* Per-vCPU vLPI enablement/disablement */
+#define KVM_ENABLE_VCPU_VLPI    _IOW(KVMIO, 0xf0, int)
+#define KVM_DISABLE_VCPU_VLPI    _IOW(KVMIO, 0xf1, int)
+#define KVM_QUERY_VCPU_VLPI    _IOR(KVMIO, 0xf2, int)
+
 #define KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE    (1 << 0)
 #define KVM_DIRTY_LOG_INITIALLY_SET            (1 << 1)
 
-- 
2.50.1 (Apple Git-155)




Amazon Web Services Development Center Germany GmbH
Tamara-Danz-Str. 13
10243 Berlin
Geschaeftsfuehrung: Christian Schlaeger, Christof Hellmis
Eingetragen am Amtsgericht Charlottenburg unter HRB 257764 B
Sitz: Berlin
Ust-ID: DE 365 538 597

  reply	other threads:[~2025-11-20 14:03 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-11-20 14:02 [RFC PATCH 00/13] Introduce per-vCPU vLPI injection control API Maximilian Dittgen
2025-11-20 14:02 ` Maximilian Dittgen [this message]
2025-11-20 16:18   ` [RFC PATCH 01/13] KVM: Introduce config option for per-vCPU vLPI enablement Marc Zyngier
2025-11-20 14:02 ` [RFC PATCH 02/13] KVM: arm64: Disable auto vCPU vPE assignment with per-vCPU vLPI config Maximilian Dittgen
2025-11-20 14:02 ` [RFC PATCH 03/13] KVM: arm64: Refactor out locked section of kvm_vgic_v4_set_forwarding() Maximilian Dittgen
2025-11-20 14:02 ` [RFC PATCH 04/13] KVM: arm64: Implement vLPI QUERY ioctl for per-vCPU vLPI injection API Maximilian Dittgen
2025-11-20 14:02 ` [RFC PATCH 05/13] KVM: arm64: Implement vLPI ENABLE " Maximilian Dittgen
2025-11-23  2:03   ` kernel test robot
2025-11-23  2:34   ` kernel test robot
2025-11-20 14:02 ` [RFC PATCH 06/13] KVM: arm64: Resolve race between vCPU scheduling and vLPI enablement Maximilian Dittgen
2025-11-20 14:02 ` [RFC PATCH 07/13] KVM: arm64: Implement vLPI DISABLE ioctl for per-vCPU vLPI Injection API Maximilian Dittgen
2025-11-20 14:02 ` [RFC PATCH 08/13] KVM: arm64: Make per-vCPU vLPI control ioctls atomic Maximilian Dittgen
2025-11-20 14:02 ` [RFC PATCH 09/13] KVM: arm64: Couple vSGI enablement with per-vCPU vPE allocation Maximilian Dittgen
2025-11-20 14:02 ` [RFC PATCH 10/13] KVM: selftests: fix MAPC RDbase target formatting in vgic_lpi_stress Maximilian Dittgen
2025-11-20 14:03 ` [RFC PATCH 11/13] KVM: Ioctl to set up userspace-injected MSIs as software-bypassing vLPIs Maximilian Dittgen
2025-11-20 14:03 ` [RFC PATCH 12/13] KVM: arm64: selftests: Add support for stress testing direct-injected vLPIs Maximilian Dittgen
2025-11-20 14:03 ` [RFC PATCH 13/13] KVM: arm64: selftests: Add test for per-vCPU vLPI control API Maximilian Dittgen
2025-11-20 14:40 ` [RFC PATCH 00/13] Introduce per-vCPU vLPI injection " Marc Zyngier

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=20251120140305.63515-2-mdittgen@amazon.de \
    --to=mdittgen@amazon.de \
    --cc=kvm@vger.kernel.org \
    --cc=kvmarm@lists.linux.dev \
    --cc=lilitj@amazon.de \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=maz@kernel.org \
    --cc=nh-open-source@amazon.com \
    --cc=oliver.upton@linux.dev \
    --cc=pbonzini@redhat.com \
    --cc=sauravsc@amazon.de \
    --cc=shuah@kernel.org \
    /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.