]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
KVM: arm64: selftests: vgic_irq: Add timer deactivation test
authorMarc Zyngier <maz@kernel.org>
Thu, 20 Nov 2025 17:25:39 +0000 (17:25 +0000)
committerOliver Upton <oupton@kernel.org>
Mon, 24 Nov 2025 22:29:15 +0000 (14:29 -0800)
Add a new test case that triggers the HW deactivation emulation path
when trapping ICV_DIR_EL1. This is obviously tied to the way KVM
works now, but the test follows the expected architectural behaviour.

Tested-by: Fuad Tabba <tabba@google.com>
Signed-off-by: Marc Zyngier <maz@kernel.org>
Tested-by: Mark Brown <broonie@kernel.org>
Link: https://msgid.link/20251120172540.2267180-50-maz@kernel.org
Signed-off-by: Oliver Upton <oupton@kernel.org>
tools/testing/selftests/kvm/arm64/vgic_irq.c

index ff2c75749f5c54c1e8af90b6fee615d5cf3a56fc..9858187c7b6eaca07b6d33093446d6a3643e24af 100644 (file)
@@ -894,6 +894,70 @@ static void guest_code_group_en(struct test_args *args, int cpuid)
        GUEST_DONE();
 }
 
+static void guest_code_timer_spi(struct test_args *args, int cpuid)
+{
+       uint32_t intid;
+       u64 val;
+
+       gic_init(GIC_V3, 2);
+
+       gic_set_eoi_split(1);
+       gic_set_priority_mask(CPU_PRIO_MASK);
+
+       /* Add a pending SPI so that KVM starts trapping DIR */
+       gic_set_priority(MIN_SPI + cpuid, IRQ_DEFAULT_PRIO);
+       gic_irq_set_pending(MIN_SPI + cpuid);
+
+       /* Configure the timer with a higher priority, make it pending */
+       gic_set_priority(27, IRQ_DEFAULT_PRIO - 8);
+
+       isb();
+       val = read_sysreg(cntvct_el0);
+       write_sysreg(val, cntv_cval_el0);
+       write_sysreg(1, cntv_ctl_el0);
+       isb();
+
+       GUEST_ASSERT(gic_irq_get_pending(27));
+
+       /* Enable both interrupts */
+       gic_irq_enable(MIN_SPI + cpuid);
+       gic_irq_enable(27);
+
+       /* The timer must fire */
+       intid = wait_for_and_activate_irq();
+       GUEST_ASSERT(intid == 27);
+
+       /* Check that we can deassert it */
+       write_sysreg(0, cntv_ctl_el0);
+       isb();
+
+       GUEST_ASSERT(!gic_irq_get_pending(27));
+
+       /*
+        * Priority drop, deactivation -- we expect that the host
+        * deactivation will have been effective
+        */
+       gic_set_eoi(27);
+       gic_set_dir(27);
+
+       GUEST_ASSERT(!gic_irq_get_active(27));
+
+       /* Do it one more time */
+       isb();
+       val = read_sysreg(cntvct_el0);
+       write_sysreg(val, cntv_cval_el0);
+       write_sysreg(1, cntv_ctl_el0);
+       isb();
+
+       GUEST_ASSERT(gic_irq_get_pending(27));
+
+       /* The timer must fire again */
+       intid = wait_for_and_activate_irq();
+       GUEST_ASSERT(intid == 27);
+
+       GUEST_DONE();
+}
+
 static void *test_vcpu_run(void *arg)
 {
        struct kvm_vcpu *vcpu = arg;
@@ -1011,6 +1075,7 @@ int main(int argc, char **argv)
                test_vgic(nr_irqs, true /* level */, true /* eoi_split */);
                test_vgic_two_cpus(guest_code_asym_dir);
                test_vgic_two_cpus(guest_code_group_en);
+               test_vgic_two_cpus(guest_code_timer_spi);
        } else {
                test_vgic(nr_irqs, level_sensitive, eoi_split);
        }