* [PATCH 0/2] KVM: arm64: Reject mismatched GICv3 ITS/VGIC models @ 2026-10-16 15:22 Sascha Bischoff 2026-10-16 15:22 ` [PATCH 1/2] KVM: arm64: vgic: Require matching VGIC model for GICv3 ITS Sascha Bischoff 2026-10-16 15:22 ` [PATCH 2/2] KVM: selftests: Reject GICv3 ITS with a GICv5 VGIC Sascha Bischoff 0 siblings, 2 replies; 6+ messages in thread From: Sascha Bischoff @ 2026-10-16 15:22 UTC (permalink / raw) To: linux-arm-kernel, kvmarm, kvm Cc: maz, oupton, fuad.tabba, joey.gouly, seiden, suzuki.poulose, yuzenghui On a GICv5 host with legacy GICv3 support, KVM exposes both VGIC models to userspace. A VM can create a GICv3 ITS alongside a GICv5 VGIC, because neither creation path checks the model of the other device. The ITS sets has_its, but a GICv5 VM cannot use a GICv3 ITS for MSI translation. Creating the ITS before the VGIC also lets userspace select an incompatible VGIC model later. Record the VGIC model required by a GICv3 ITS and reject incompatible device creation in either order. The second patch tests both orderings, skipping the test if the host does not offer a GICv3 ITS. This series is based on kvmarm/next-7.4+fixes-7.3-2. Sascha Sascha Bischoff (2): KVM: arm64: vgic: Require matching VGIC model for GICv3 ITS KVM: selftests: Reject GICv3 ITS with a GICv5 VGIC arch/arm64/kvm/vgic/vgic-init.c | 5 ++++ arch/arm64/kvm/vgic/vgic-its.c | 9 ++++++ include/kvm/arm_vgic.h | 2 ++ tools/testing/selftests/kvm/arm64/vgic_v5.c | 32 +++++++++++++++++++++ 4 files changed, 48 insertions(+) base-commit: 678f16b6e4767096aa3e3e6eef60e981b3f61e12 -- 2.34.1 ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 1/2] KVM: arm64: vgic: Require matching VGIC model for GICv3 ITS 2026-10-16 15:22 [PATCH 0/2] KVM: arm64: Reject mismatched GICv3 ITS/VGIC models Sascha Bischoff @ 2026-10-16 15:22 ` Sascha Bischoff 2026-10-16 15:35 ` sashiko-bot 2026-10-17 11:51 ` Marc Zyngier 2026-10-16 15:22 ` [PATCH 2/2] KVM: selftests: Reject GICv3 ITS with a GICv5 VGIC Sascha Bischoff 1 sibling, 2 replies; 6+ messages in thread From: Sascha Bischoff @ 2026-10-16 15:22 UTC (permalink / raw) To: linux-arm-kernel, kvmarm, kvm Cc: maz, oupton, fuad.tabba, joey.gouly, seiden, suzuki.poulose, yuzenghui On a GICv5 host with legacy support, KVM registers both VGICv3 and VGICv5 devices. A VM can create a GICv3 ITS with another VGIC model, setting has_its even though that model cannot use the GICv3 ITS. Reject GICv3 ITS creation when the VM already has an incompatible VGIC. KVM also permits creating an ITS before its VGIC, so record the model required by the ITS and reject a later incompatible VGIC. Preserve either creation order when the models match. Signed-off-by: Sascha Bischoff <sascha.bischoff@arm.com> --- arch/arm64/kvm/vgic/vgic-init.c | 5 +++++ arch/arm64/kvm/vgic/vgic-its.c | 9 +++++++++ include/kvm/arm_vgic.h | 2 ++ 3 files changed, 16 insertions(+) diff --git a/arch/arm64/kvm/vgic/vgic-init.c b/arch/arm64/kvm/vgic/vgic-init.c index b5ea1e39c6862..48a92555fa6ab 100644 --- a/arch/arm64/kvm/vgic/vgic-init.c +++ b/arch/arm64/kvm/vgic/vgic-init.c @@ -125,6 +125,11 @@ int kvm_vgic_create(struct kvm *kvm, u32 type) goto out_unlock; } + if (kvm->arch.vgic.its_model && kvm->arch.vgic.its_model != type) { + ret = -ENODEV; + goto out_unlock; + } + if (kvm_id_regs_final(kvm)) goto out_unlock; ret = 0; diff --git a/arch/arm64/kvm/vgic/vgic-its.c b/arch/arm64/kvm/vgic/vgic-its.c index e5657cb603567..bf901626ea6df 100644 --- a/arch/arm64/kvm/vgic/vgic-its.c +++ b/arch/arm64/kvm/vgic/vgic-its.c @@ -1875,6 +1875,14 @@ static int vgic_its_create(struct kvm_device *dev, u32 type) mutex_lock(&dev->kvm->arch.config_lock); + if ((irqchip_in_kernel(dev->kvm) && !vgic_is_v3(dev->kvm)) || + (dev->kvm->arch.vgic.its_model && + dev->kvm->arch.vgic.its_model != KVM_DEV_TYPE_ARM_VGIC_V3)) { + mutex_unlock(&dev->kvm->arch.config_lock); + kfree(its); + return -ENODEV; + } + if (vgic_initialized(dev->kvm)) { ret = vgic_v4_init(dev->kvm); if (ret < 0) { @@ -1903,6 +1911,7 @@ static int vgic_its_create(struct kvm_device *dev, u32 type) dev->kvm->arch.vgic.msis_require_devid = true; dev->kvm->arch.vgic.has_its = true; + dev->kvm->arch.vgic.its_model = KVM_DEV_TYPE_ARM_VGIC_V3; its->enabled = false; its->dev = dev; diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h index 7be81b936bf10..a2b6b328808ba 100644 --- a/include/kvm/arm_vgic.h +++ b/include/kvm/arm_vgic.h @@ -548,6 +548,8 @@ struct vgic_dist { struct vgic_io_device cpuif_iodev; bool has_its; + /* VGIC model required by the VM's ITS devices. */ + u32 its_model; bool table_write_in_progress; /* -- 2.34.1 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH 1/2] KVM: arm64: vgic: Require matching VGIC model for GICv3 ITS 2026-10-16 15:22 ` [PATCH 1/2] KVM: arm64: vgic: Require matching VGIC model for GICv3 ITS Sascha Bischoff @ 2026-10-16 15:35 ` sashiko-bot 2026-10-17 11:51 ` Marc Zyngier 1 sibling, 0 replies; 6+ messages in thread From: sashiko-bot @ 2026-10-16 15:35 UTC (permalink / raw) To: Sascha Bischoff, kvmarm, kvm; +Cc: Oliver Upton, Marc Zyngier Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [Medium] kvm: vgic: its_model state leak on ITS creation failure prevents VGIC fallback -- commit 1db9490bd1d4f94f4d1c1d3aee70dca948f96eb7 Author: Sascha Bischoff <sascha.bischoff@arm.com> KVM: arm64: vgic: Require matching VGIC model for GICv3 ITS On a GICv5 host with legacy support, KVM registers both VGICv3 and VGICv5 devices. A VM can create a GICv3 ITS with another VGIC model, setting has_its even though that model cannot use the GICv3 ITS. > diff --git a/arch/arm64/kvm/vgic/vgic-its.c b/arch/arm64/kvm/vgic/vgic-its.c > index e5657cb603567..bf901626ea6df 100644 > --- a/arch/arm64/kvm/vgic/vgic-its.c > +++ b/arch/arm64/kvm/vgic/vgic-its.c [ ... ] > @@ -1903,6 +1911,7 @@ static int vgic_its_create(struct kvm_device *dev, u32 type) > > dev->kvm->arch.vgic.msis_require_devid = true; > dev->kvm->arch.vgic.has_its = true; > + dev->kvm->arch.vgic.its_model = KVM_DEV_TYPE_ARM_VGIC_V3; > its->enabled = false; > its->dev = dev; [Severity: Medium] When vgic_its_create() successfully executes, it updates the VM-wide state (its_model, has_its, msis_require_devid) to reflect the ITS device. If the generic kvm_ioctl_create_device() subsequently fails at anon_inode_getfd() due to process FD exhaustion, it aborts the device creation and calls the vgic_its_destroy() cleanup callback. However, vgic_its_destroy() does not roll back the its_model VM-wide property: arch/arm64/kvm/vgic/vgic-its.c:vgic_its_destroy() { ... 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); kfree(kvm_dev); } Consequently, the VM permanently records that it requires a GICv3 VGIC model. Does this state inconsistency prevent userspace from recovering and falling back to a different VGIC model (such as VGICv5) after an ephemeral FD allocation error, or if userspace intentionally closes the ITS file descriptor before creating the VGIC? -- Sashiko AI review · https://sashiko.dev/#/patchset/20261016152225.898761-1-sascha.bischoff@arm.com?part=1 ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 1/2] KVM: arm64: vgic: Require matching VGIC model for GICv3 ITS 2026-10-16 15:22 ` [PATCH 1/2] KVM: arm64: vgic: Require matching VGIC model for GICv3 ITS Sascha Bischoff 2026-10-16 15:35 ` sashiko-bot @ 2026-10-17 11:51 ` Marc Zyngier 1 sibling, 0 replies; 6+ messages in thread From: Marc Zyngier @ 2026-10-17 11:51 UTC (permalink / raw) To: Sascha Bischoff Cc: linux-arm-kernel, kvmarm, kvm, oupton, fuad.tabba, joey.gouly, seiden, suzuki.poulose, yuzenghui On Fri, 16 Oct 2026 16:22:23 +0100, Sascha Bischoff <sascha.bischoff@arm.com> wrote: > > On a GICv5 host with legacy support, KVM registers both VGICv3 and > VGICv5 devices. A VM can create a GICv3 ITS with another VGIC model, > setting has_its even though that model cannot use the GICv3 ITS. > > Reject GICv3 ITS creation when the VM already has an incompatible VGIC. > KVM also permits creating an ITS before its VGIC, so record the model > required by the ITS and reject a later incompatible VGIC. Preserve > either creation order when the models match. > > Signed-off-by: Sascha Bischoff <sascha.bischoff@arm.com> > --- > arch/arm64/kvm/vgic/vgic-init.c | 5 +++++ > arch/arm64/kvm/vgic/vgic-its.c | 9 +++++++++ > include/kvm/arm_vgic.h | 2 ++ > 3 files changed, 16 insertions(+) > > diff --git a/arch/arm64/kvm/vgic/vgic-init.c b/arch/arm64/kvm/vgic/vgic-init.c > index b5ea1e39c6862..48a92555fa6ab 100644 > --- a/arch/arm64/kvm/vgic/vgic-init.c > +++ b/arch/arm64/kvm/vgic/vgic-init.c > @@ -125,6 +125,11 @@ int kvm_vgic_create(struct kvm *kvm, u32 type) > goto out_unlock; > } > > + if (kvm->arch.vgic.its_model && kvm->arch.vgic.its_model != type) { > + ret = -ENODEV; > + goto out_unlock; > + } > + > if (kvm_id_regs_final(kvm)) > goto out_unlock; > ret = 0; > diff --git a/arch/arm64/kvm/vgic/vgic-its.c b/arch/arm64/kvm/vgic/vgic-its.c > index e5657cb603567..bf901626ea6df 100644 > --- a/arch/arm64/kvm/vgic/vgic-its.c > +++ b/arch/arm64/kvm/vgic/vgic-its.c > @@ -1875,6 +1875,14 @@ static int vgic_its_create(struct kvm_device *dev, u32 type) > > mutex_lock(&dev->kvm->arch.config_lock); > > + if ((irqchip_in_kernel(dev->kvm) && !vgic_is_v3(dev->kvm)) || > + (dev->kvm->arch.vgic.its_model && > + dev->kvm->arch.vgic.its_model != KVM_DEV_TYPE_ARM_VGIC_V3)) { > + mutex_unlock(&dev->kvm->arch.config_lock); > + kfree(its); > + return -ENODEV; > + } > + A comment would go a long way to make it clear what this is checking for: - if a GIC already exists and is not v3, fail - if an ITS already exists and is not v3, fail > if (vgic_initialized(dev->kvm)) { > ret = vgic_v4_init(dev->kvm); > if (ret < 0) { > @@ -1903,6 +1911,7 @@ static int vgic_its_create(struct kvm_device *dev, u32 type) > > dev->kvm->arch.vgic.msis_require_devid = true; > dev->kvm->arch.vgic.has_its = true; > + dev->kvm->arch.vgic.its_model = KVM_DEV_TYPE_ARM_VGIC_V3; > its->enabled = false; > its->dev = dev; > > diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h > index 7be81b936bf10..a2b6b328808ba 100644 > --- a/include/kvm/arm_vgic.h > +++ b/include/kvm/arm_vgic.h > @@ -548,6 +548,8 @@ struct vgic_dist { > struct vgic_io_device cpuif_iodev; > > bool has_its; > + /* VGIC model required by the VM's ITS devices. */ > + u32 its_model; I reckon that has_its and its_model can be made the same thing, since its_model == 0 indicates the lack of ITS, and it is otherwise the same as vgic_model. I ended up with this (untested). Thoughts? M. diff --git a/arch/arm64/kvm/vgic/vgic-init.c b/arch/arm64/kvm/vgic/vgic-init.c index 2d915769cdc7c..c70390b7fcab6 100644 --- a/arch/arm64/kvm/vgic/vgic-init.c +++ b/arch/arm64/kvm/vgic/vgic-init.c @@ -456,6 +456,9 @@ int kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu) */ if (vcpu->vcpu_id >= kvm_vgic_global_state.max_gicv5_vcpus) return -EINVAL; + break; + default: + unreachable(); } return ret; @@ -572,6 +575,8 @@ static void kvm_vgic_dist_destroy(struct kvm *kvm) kfree(dist->vgic_v5_irs_data); dist->vgic_v5_irs_data = NULL; break; + default: + unreachable(); } xa_destroy(&dist->lpi_xa); diff --git a/arch/arm64/kvm/vgic/vgic-its.c b/arch/arm64/kvm/vgic/vgic-its.c index 0ec461df74cd9..171e5e345c220 100644 --- a/arch/arm64/kvm/vgic/vgic-its.c +++ b/arch/arm64/kvm/vgic/vgic-its.c @@ -1963,7 +1963,6 @@ static int vgic_its_create(struct kvm_device *dev, u32 type) xa_init(&its->translation_cache); dev->kvm->arch.vgic.msis_require_devid = true; - dev->kvm->arch.vgic.has_its = true; dev->kvm->arch.vgic.its_model = KVM_DEV_TYPE_ARM_VGIC_V3; its->enabled = false; its->dev = dev; diff --git a/arch/arm64/kvm/vgic/vgic-mmio-v3.c b/arch/arm64/kvm/vgic/vgic-mmio-v3.c index 636c576b2b99e..282fac37b6642 100644 --- a/arch/arm64/kvm/vgic/vgic-mmio-v3.c +++ b/arch/arm64/kvm/vgic/vgic-mmio-v3.c @@ -42,10 +42,7 @@ bool vgic_has_its(struct kvm *kvm) { struct vgic_dist *dist = &kvm->arch.vgic; - if (dist->vgic_model != KVM_DEV_TYPE_ARM_VGIC_V3) - return false; - - return dist->has_its; + return (dist->its_model == dist->vgic_model); } bool vgic_supports_direct_msis(struct kvm *kvm) diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h index c4135815884b6..4b2c41917b77c 100644 --- a/include/kvm/arm_vgic.h +++ b/include/kvm/arm_vgic.h @@ -503,7 +503,9 @@ struct vgic_dist { bool initialized; /* vGIC model the kernel emulates for the guest (GICv2 or GICv3) */ - u32 vgic_model; + enum kvm_device_type vgic_model; + /* VGIC model required by the VM's ITS devices. */ + enum kvm_device_type its_model; /* Implementation revision as reported in the GICD_IIDR */ u32 implementation_rev; @@ -548,9 +550,6 @@ struct vgic_dist { struct vgic_io_device dist_iodev; struct vgic_io_device cpuif_iodev; - bool has_its; - /* VGIC model required by the VM's ITS devices. */ - u32 its_model; bool table_write_in_progress; /* -- Jazz isn't dead. It just smells funny. ^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 2/2] KVM: selftests: Reject GICv3 ITS with a GICv5 VGIC 2026-10-16 15:22 [PATCH 0/2] KVM: arm64: Reject mismatched GICv3 ITS/VGIC models Sascha Bischoff 2026-10-16 15:22 ` [PATCH 1/2] KVM: arm64: vgic: Require matching VGIC model for GICv3 ITS Sascha Bischoff @ 2026-10-16 15:22 ` Sascha Bischoff 2026-10-16 15:36 ` sashiko-bot 1 sibling, 1 reply; 6+ messages in thread From: Sascha Bischoff @ 2026-10-16 15:22 UTC (permalink / raw) To: linux-arm-kernel, kvmarm, kvm Cc: maz, oupton, fuad.tabba, joey.gouly, seiden, suzuki.poulose, yuzenghui Check that a GICv3 ITS and a GICv5 VGIC cannot be paired, regardless of which device is created first. Skip the check when the host does not expose a GICv3 ITS. Signed-off-by: Sascha Bischoff <sascha.bischoff@arm.com> --- tools/testing/selftests/kvm/arm64/vgic_v5.c | 32 +++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/tools/testing/selftests/kvm/arm64/vgic_v5.c b/tools/testing/selftests/kvm/arm64/vgic_v5.c index d5df742b23001..5bf7d99d29147 100644 --- a/tools/testing/selftests/kvm/arm64/vgic_v5.c +++ b/tools/testing/selftests/kvm/arm64/vgic_v5.c @@ -2003,8 +2003,40 @@ int test_kvm_device(u32 gic_dev_type) return 0; } +static void test_vgic_v3_its_with_vgic_v5(void) +{ + struct kvm_vm *vm = vm_create_barebones(); + int gic_fd, its_fd, ret; + + if (__kvm_test_create_device(vm, KVM_DEV_TYPE_ARM_VGIC_ITS)) { + pr_info("No GICv3 ITS support; skipping mixed-model test.\n"); + kvm_vm_free(vm); + return; + } + + gic_fd = kvm_create_device(vm, KVM_DEV_TYPE_ARM_VGIC_V5); + ret = __kvm_create_device(vm, KVM_DEV_TYPE_ARM_VGIC_ITS); + TEST_ASSERT(ret < 0 && errno == ENODEV, + "GICv3 ITS created after GICv5 VGIC: ret=%d errno=%d", + ret, errno); + close(gic_fd); + kvm_vm_free(vm); + + vm = vm_create_barebones(); + its_fd = kvm_create_device(vm, KVM_DEV_TYPE_ARM_VGIC_ITS); + ret = __kvm_create_device(vm, KVM_DEV_TYPE_ARM_VGIC_V5); + TEST_ASSERT(ret < 0 && errno == ENODEV, + "GICv5 VGIC created after GICv3 ITS: ret=%d errno=%d", + ret, errno); + close(its_fd); + kvm_vm_free(vm); +} + void run_tests(u32 gic_dev_type) { + pr_info("Test VGICv5 and GICv3 ITS model mismatch\n"); + test_vgic_v3_its_with_vgic_v5(); + pr_info("Test VGICv5 address attrs\n"); test_vgic_v5_addr_attrs(); -- 2.34.1 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH 2/2] KVM: selftests: Reject GICv3 ITS with a GICv5 VGIC 2026-10-16 15:22 ` [PATCH 2/2] KVM: selftests: Reject GICv3 ITS with a GICv5 VGIC Sascha Bischoff @ 2026-10-16 15:36 ` sashiko-bot 0 siblings, 0 replies; 6+ messages in thread From: sashiko-bot @ 2026-10-16 15:36 UTC (permalink / raw) To: Sascha Bischoff, kvmarm, kvm; +Cc: Oliver Upton, Marc Zyngier Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [Medium] selftests: vgic_v5.c uses ad hoc skip messages and direct exit() instead of TAP -- commit 1b97dfda1bac7a30c8395c0645ac8efb945b4639 Author: Sascha Bischoff <sascha.bischoff@arm.com> KVM: selftests: Reject GICv3 ITS with a GICv5 VGIC Check that a GICv3 ITS and a GICv5 VGIC cannot be paired, regardless of which device is created first. Skip the check when the host does not expose a GICv3 ITS. > diff --git a/tools/testing/selftests/kvm/arm64/vgic_v5.c b/tools/testing/selftests/kvm/arm64/vgic_v5.c > index d5df742b23001..5bf7d99d29147 100644 > --- a/tools/testing/selftests/kvm/arm64/vgic_v5.c > +++ b/tools/testing/selftests/kvm/arm64/vgic_v5.c [ ... ] > @@ -2003,8 +2003,40 @@ int test_kvm_device(u32 gic_dev_type) > return 0; > } > > +static void test_vgic_v3_its_with_vgic_v5(void) > +{ > + struct kvm_vm *vm = vm_create_barebones(); > + int gic_fd, its_fd, ret; > + > + if (__kvm_test_create_device(vm, KVM_DEV_TYPE_ARM_VGIC_ITS)) { > + pr_info("No GICv3 ITS support; skipping mixed-model test.\n"); > + kvm_vm_free(vm); > + return; > + } [Severity: Medium] When running test_vgic_v3_its_with_vgic_v5() on a host without GICv3 ITS support, this prints an unstructured skip message and returns directly. Could this be converted to use a TAP reporting macro like ksft_test_result_skip() instead of an ad-hoc pr_info() and return? Additionally, running the test suite on a host without GICv5 support calls exit(KSFT_SKIP) directly in main() instead of using ksft_exit_skip(). Are there plans to update the main() exit path as well? -- Sashiko AI review · https://sashiko.dev/#/patchset/20261016152225.898761-1-sascha.bischoff@arm.com?part=2 ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-10-17 11:48 UTC | newest] Thread overview: 6+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-10-16 15:22 [PATCH 0/2] KVM: arm64: Reject mismatched GICv3 ITS/VGIC models Sascha Bischoff 2026-10-16 15:22 ` [PATCH 1/2] KVM: arm64: vgic: Require matching VGIC model for GICv3 ITS Sascha Bischoff 2026-10-16 15:35 ` sashiko-bot 2026-10-17 11:51 ` Marc Zyngier 2026-10-16 15:22 ` [PATCH 2/2] KVM: selftests: Reject GICv3 ITS with a GICv5 VGIC Sascha Bischoff 2026-10-16 15:36 ` sashiko-bot
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.