linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/13] KVM: arm64: selftests: Run selftests in VHE EL2
@ 2025-09-17 21:20 Oliver Upton
  2025-09-17 21:20 ` [PATCH 01/13] KVM: arm64: selftests: Provide kvm_arch_vm_post_create() in library code Oliver Upton
                   ` (13 more replies)
  0 siblings, 14 replies; 20+ messages in thread
From: Oliver Upton @ 2025-09-17 21:20 UTC (permalink / raw)
  To: kvmarm
  Cc: Marc Zyngier, Joey Gouly, Suzuki K Poulose, Zenghui Yu,
	Paolo Bonzini, Sean Christopherson, Christian Borntraeger,
	Janosch Frank, Claudio Imbrenda, David Hildenbrand,
	linux-arm-kernel, kvm, Oliver Upton

I've been working on some MMU-related features that are unused by KVM
meaning they're somewhat annoying to test. Because of that, I found the
time / patience to port our existing selftests infrastructure over to
running in VHE EL2, opportunistically promoting tests when the stars
align.

Creating a VGIC is a hard requirement of enabling EL2 for a VM. As a
consequence of this, I need to eat my words from my earlier conversation
with Sean on this topic and hammer in a default VGICv3. This requires
some participation from the arch-neutral code given the ordering
constraints on vCPU and VGIC creation.

At the tail end of this series is a sanity test for EL2 but nothing is
actually running nested (yet). Despite that, running in EL2 has proven
valuable already as it has uncovered a bug [*].

This is all _very_ lightly tested on an M2 :) Applies to 6.17-rc4

[*]: https://lore.kernel.org/kvmarm/20250917203125.283116-1-oliver.upton@linux.dev/

Oliver Upton (13):
  KVM: arm64: selftests: Provide kvm_arch_vm_post_create() in library
    code
  KVM: arm64: selftests: Initialize VGICv3 only once
  KVM: arm64: selftests: Add helper to check for VGICv3 support
  KVM: arm64: selftests: Add unsanitised helpers for VGICv3 creation
  KVM: arm64: selftests: Create a VGICv3 for 'default' VMs
  KVM: arm64: selftests: Alias EL1 registers to EL2 counterparts
  KVM: arm64: selftests: Provide helper for getting default vCPU target
  KVM: arm64: selftests: Select SMCCC conduit based on current EL
  KVM: arm64: selftests: Use hyp timer IRQs when test runs at EL2
  KVM: arm64: selftests: Use the vCPU attr for setting nr of PMU
    counters
  KVM: arm64: selftests: Initialize HCR_EL2
  KVM: arm64: selftests: Enable EL2 by default
  KVM: arm64: selftests: Add basic test for running in VHE EL2

 tools/testing/selftests/kvm/Makefile.kvm      |  1 +
 .../testing/selftests/kvm/arm64/arch_timer.c  | 13 +--
 .../kvm/arm64/arch_timer_edge_cases.c         | 13 +--
 tools/testing/selftests/kvm/arm64/hello_el2.c | 58 ++++++++++++
 .../testing/selftests/kvm/arm64/hypercalls.c  |  2 +-
 tools/testing/selftests/kvm/arm64/kvm-uuid.c  |  2 +-
 .../testing/selftests/kvm/arm64/no-vgic-v3.c  |  2 +
 tools/testing/selftests/kvm/arm64/psci_test.c | 13 +--
 .../testing/selftests/kvm/arm64/set_id_regs.c | 20 ++--
 .../selftests/kvm/arm64/smccc_filter.c        | 17 +++-
 tools/testing/selftests/kvm/arm64/vgic_init.c |  2 +
 tools/testing/selftests/kvm/arm64/vgic_irq.c  |  4 +-
 .../selftests/kvm/arm64/vgic_lpi_stress.c     |  8 +-
 .../selftests/kvm/arm64/vpmu_counter_access.c | 75 +++++++--------
 .../selftests/kvm/dirty_log_perf_test.c       | 35 -------
 tools/testing/selftests/kvm/dirty_log_test.c  |  1 +
 tools/testing/selftests/kvm/get-reg-list.c    |  9 +-
 .../selftests/kvm/include/arm64/arch_timer.h  | 24 +++++
 .../kvm/include/arm64/kvm_util_arch.h         |  5 +-
 .../selftests/kvm/include/arm64/processor.h   | 73 +++++++++++++++
 .../selftests/kvm/include/arm64/vgic.h        |  3 +
 .../testing/selftests/kvm/include/kvm_util.h  |  7 +-
 .../selftests/kvm/lib/arm64/processor.c       | 91 ++++++++++++++++---
 tools/testing/selftests/kvm/lib/arm64/vgic.c  | 64 +++++++++----
 tools/testing/selftests/kvm/lib/kvm_util.c    | 15 ++-
 .../testing/selftests/kvm/lib/x86/processor.c |  2 +-
 tools/testing/selftests/kvm/s390/cmma_test.c  |  2 +-
 tools/testing/selftests/kvm/steal_time.c      |  2 +-
 28 files changed, 395 insertions(+), 168 deletions(-)
 create mode 100644 tools/testing/selftests/kvm/arm64/hello_el2.c


base-commit: b320789d6883cc00ac78ce83bccbfe7ed58afcf0
-- 
2.47.3



^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 01/13] KVM: arm64: selftests: Provide kvm_arch_vm_post_create() in library code
  2025-09-17 21:20 [PATCH 00/13] KVM: arm64: selftests: Run selftests in VHE EL2 Oliver Upton
@ 2025-09-17 21:20 ` Oliver Upton
  2025-09-18  1:25   ` Itaru Kitayama
  2025-09-17 21:20 ` [PATCH 02/13] KVM: arm64: selftests: Initialize VGICv3 only once Oliver Upton
                   ` (12 subsequent siblings)
  13 siblings, 1 reply; 20+ messages in thread
From: Oliver Upton @ 2025-09-17 21:20 UTC (permalink / raw)
  To: kvmarm
  Cc: Marc Zyngier, Joey Gouly, Suzuki K Poulose, Zenghui Yu,
	Paolo Bonzini, Sean Christopherson, Christian Borntraeger,
	Janosch Frank, Claudio Imbrenda, David Hildenbrand,
	linux-arm-kernel, kvm, Oliver Upton

In order to compel the default usage of EL2 in selftests, move
kvm_arch_vm_post_create() to library code and expose an opt-in for using
MTE by default.

Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
---
 .../testing/selftests/kvm/arm64/set_id_regs.c | 19 +++++--------------
 .../selftests/kvm/include/arm64/processor.h   |  2 ++
 .../selftests/kvm/lib/arm64/processor.c       | 13 +++++++++++++
 3 files changed, 20 insertions(+), 14 deletions(-)

diff --git a/tools/testing/selftests/kvm/arm64/set_id_regs.c b/tools/testing/selftests/kvm/arm64/set_id_regs.c
index 189321e96925..a2d367a2c93c 100644
--- a/tools/testing/selftests/kvm/arm64/set_id_regs.c
+++ b/tools/testing/selftests/kvm/arm64/set_id_regs.c
@@ -15,8 +15,6 @@
 #include "test_util.h"
 #include <linux/bitfield.h>
 
-bool have_cap_arm_mte;
-
 enum ftr_type {
 	FTR_EXACT,			/* Use a predefined safe value */
 	FTR_LOWER_SAFE,			/* Smaller value is safe */
@@ -568,7 +566,9 @@ static void test_user_set_mte_reg(struct kvm_vcpu *vcpu)
 	uint64_t mte_frac;
 	int idx, err;
 
-	if (!have_cap_arm_mte) {
+	val = vcpu_get_reg(vcpu, KVM_ARM64_SYS_REG(SYS_ID_AA64PFR1_EL1));
+	mte = FIELD_GET(ID_AA64PFR1_EL1_MTE, val);
+	if (!mte) {
 		ksft_test_result_skip("MTE capability not supported, nothing to test\n");
 		return;
 	}
@@ -593,9 +593,6 @@ static void test_user_set_mte_reg(struct kvm_vcpu *vcpu)
 	 * from unsupported (0xF) to supported (0).
 	 *
 	 */
-	val = vcpu_get_reg(vcpu, KVM_ARM64_SYS_REG(SYS_ID_AA64PFR1_EL1));
-
-	mte = FIELD_GET(ID_AA64PFR1_EL1_MTE, val);
 	mte_frac = FIELD_GET(ID_AA64PFR1_EL1_MTE_frac, val);
 	if (mte != ID_AA64PFR1_EL1_MTE_MTE2 ||
 	    mte_frac != ID_AA64PFR1_EL1_MTE_frac_NI) {
@@ -750,14 +747,6 @@ static void test_reset_preserves_id_regs(struct kvm_vcpu *vcpu)
 	ksft_test_result_pass("%s\n", __func__);
 }
 
-void kvm_arch_vm_post_create(struct kvm_vm *vm)
-{
-	if (vm_check_cap(vm, KVM_CAP_ARM_MTE)) {
-		vm_enable_cap(vm, KVM_CAP_ARM_MTE, 0);
-		have_cap_arm_mte = true;
-	}
-}
-
 int main(void)
 {
 	struct kvm_vcpu *vcpu;
@@ -769,6 +758,8 @@ int main(void)
 	TEST_REQUIRE(kvm_has_cap(KVM_CAP_ARM_SUPPORTED_REG_MASK_RANGES));
 	TEST_REQUIRE(kvm_has_cap(KVM_CAP_ARM_WRITABLE_IMP_ID_REGS));
 
+	test_wants_mte();
+
 	vm = vm_create(1);
 	vm_enable_cap(vm, KVM_CAP_ARM_WRITABLE_IMP_ID_REGS, 0);
 	vcpu = vm_vcpu_add(vm, 0, guest_code);
diff --git a/tools/testing/selftests/kvm/include/arm64/processor.h b/tools/testing/selftests/kvm/include/arm64/processor.h
index 255fed769a8a..8370fc94041d 100644
--- a/tools/testing/selftests/kvm/include/arm64/processor.h
+++ b/tools/testing/selftests/kvm/include/arm64/processor.h
@@ -300,4 +300,6 @@ void smccc_smc(uint32_t function_id, uint64_t arg0, uint64_t arg1,
 /* Execute a Wait For Interrupt instruction. */
 void wfi(void);
 
+void test_wants_mte(void);
+
 #endif /* SELFTEST_KVM_PROCESSOR_H */
diff --git a/tools/testing/selftests/kvm/lib/arm64/processor.c b/tools/testing/selftests/kvm/lib/arm64/processor.c
index eb115123d741..caed1998c7b3 100644
--- a/tools/testing/selftests/kvm/lib/arm64/processor.c
+++ b/tools/testing/selftests/kvm/lib/arm64/processor.c
@@ -653,3 +653,16 @@ void wfi(void)
 {
 	asm volatile("wfi");
 }
+
+static bool request_mte;
+
+void test_wants_mte(void)
+{
+	request_mte = true;
+}
+
+void kvm_arch_vm_post_create(struct kvm_vm *vm)
+{
+	if (request_mte && vm_check_cap(vm, KVM_CAP_ARM_MTE))
+		vm_enable_cap(vm, KVM_CAP_ARM_MTE, 0);
+}
-- 
2.47.3



^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 02/13] KVM: arm64: selftests: Initialize VGICv3 only once
  2025-09-17 21:20 [PATCH 00/13] KVM: arm64: selftests: Run selftests in VHE EL2 Oliver Upton
  2025-09-17 21:20 ` [PATCH 01/13] KVM: arm64: selftests: Provide kvm_arch_vm_post_create() in library code Oliver Upton
@ 2025-09-17 21:20 ` Oliver Upton
  2025-09-18 10:44   ` Zenghui Yu
  2025-09-17 21:20 ` [PATCH 03/13] KVM: arm64: selftests: Add helper to check for VGICv3 support Oliver Upton
                   ` (11 subsequent siblings)
  13 siblings, 1 reply; 20+ messages in thread
From: Oliver Upton @ 2025-09-17 21:20 UTC (permalink / raw)
  To: kvmarm
  Cc: Marc Zyngier, Joey Gouly, Suzuki K Poulose, Zenghui Yu,
	Paolo Bonzini, Sean Christopherson, Christian Borntraeger,
	Janosch Frank, Claudio Imbrenda, David Hildenbrand,
	linux-arm-kernel, kvm, Oliver Upton

vgic_v3_setup() unnecessarily initializes the vgic twice. Keep the
initialization after configuring MMIO frames and get rid of the other.

Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
---
 tools/testing/selftests/kvm/lib/arm64/vgic.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/tools/testing/selftests/kvm/lib/arm64/vgic.c b/tools/testing/selftests/kvm/lib/arm64/vgic.c
index 4427f43f73ea..64e793795563 100644
--- a/tools/testing/selftests/kvm/lib/arm64/vgic.c
+++ b/tools/testing/selftests/kvm/lib/arm64/vgic.c
@@ -56,9 +56,6 @@ int vgic_v3_setup(struct kvm_vm *vm, unsigned int nr_vcpus, uint32_t nr_irqs)
 
 	kvm_device_attr_set(gic_fd, KVM_DEV_ARM_VGIC_GRP_NR_IRQS, 0, &nr_irqs);
 
-	kvm_device_attr_set(gic_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
-			    KVM_DEV_ARM_VGIC_CTRL_INIT, NULL);
-
 	attr = GICD_BASE_GPA;
 	kvm_device_attr_set(gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
 			    KVM_VGIC_V3_ADDR_TYPE_DIST, &attr);
-- 
2.47.3



^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 03/13] KVM: arm64: selftests: Add helper to check for VGICv3 support
  2025-09-17 21:20 [PATCH 00/13] KVM: arm64: selftests: Run selftests in VHE EL2 Oliver Upton
  2025-09-17 21:20 ` [PATCH 01/13] KVM: arm64: selftests: Provide kvm_arch_vm_post_create() in library code Oliver Upton
  2025-09-17 21:20 ` [PATCH 02/13] KVM: arm64: selftests: Initialize VGICv3 only once Oliver Upton
@ 2025-09-17 21:20 ` Oliver Upton
  2025-09-18  1:45   ` Itaru Kitayama
  2025-09-17 21:20 ` [PATCH 04/13] KVM: arm64: selftests: Add unsanitised helpers for VGICv3 creation Oliver Upton
                   ` (10 subsequent siblings)
  13 siblings, 1 reply; 20+ messages in thread
From: Oliver Upton @ 2025-09-17 21:20 UTC (permalink / raw)
  To: kvmarm
  Cc: Marc Zyngier, Joey Gouly, Suzuki K Poulose, Zenghui Yu,
	Paolo Bonzini, Sean Christopherson, Christian Borntraeger,
	Janosch Frank, Claudio Imbrenda, David Hildenbrand,
	linux-arm-kernel, kvm, Oliver Upton

Introduce a proper predicate for probing VGICv3 by performing a 'test'
creation of the device on a dummy VM.

Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
---
 tools/testing/selftests/kvm/arm64/arch_timer.c        |  3 ++-
 .../selftests/kvm/arm64/arch_timer_edge_cases.c       |  3 ++-
 tools/testing/selftests/kvm/arm64/vgic_irq.c          |  3 ++-
 tools/testing/selftests/kvm/arm64/vgic_lpi_stress.c   |  4 ++--
 .../testing/selftests/kvm/arm64/vpmu_counter_access.c |  3 +--
 tools/testing/selftests/kvm/include/arm64/vgic.h      |  1 +
 tools/testing/selftests/kvm/lib/arm64/vgic.c          | 11 +++++++++++
 7 files changed, 21 insertions(+), 7 deletions(-)

diff --git a/tools/testing/selftests/kvm/arm64/arch_timer.c b/tools/testing/selftests/kvm/arm64/arch_timer.c
index eeba1cc87ff8..aaf4285f832a 100644
--- a/tools/testing/selftests/kvm/arm64/arch_timer.c
+++ b/tools/testing/selftests/kvm/arm64/arch_timer.c
@@ -184,6 +184,8 @@ struct kvm_vm *test_vm_create(void)
 	unsigned int i;
 	int nr_vcpus = test_args.nr_vcpus;
 
+	TEST_REQUIRE(kvm_supports_vgic_v3());
+
 	vm = vm_create_with_vcpus(nr_vcpus, guest_code, vcpus);
 
 	vm_init_descriptor_tables(vm);
@@ -205,7 +207,6 @@ struct kvm_vm *test_vm_create(void)
 
 	test_init_timer_irq(vm);
 	gic_fd = vgic_v3_setup(vm, nr_vcpus, 64);
-	__TEST_REQUIRE(gic_fd >= 0, "Failed to create vgic-v3");
 
 	/* Make all the test's cmdline args visible to the guest */
 	sync_global_to_guest(vm, test_args);
diff --git a/tools/testing/selftests/kvm/arm64/arch_timer_edge_cases.c b/tools/testing/selftests/kvm/arm64/arch_timer_edge_cases.c
index ce74d069cb7b..d349d80d8418 100644
--- a/tools/testing/selftests/kvm/arm64/arch_timer_edge_cases.c
+++ b/tools/testing/selftests/kvm/arm64/arch_timer_edge_cases.c
@@ -952,7 +952,6 @@ static void test_vm_create(struct kvm_vm **vm, struct kvm_vcpu **vcpu,
 
 	test_init_timer_irq(*vm, *vcpu);
 	gic_fd = vgic_v3_setup(*vm, 1, 64);
-	__TEST_REQUIRE(gic_fd >= 0, "Failed to create vgic-v3");
 
 	sync_global_to_guest(*vm, test_args);
 	sync_global_to_guest(*vm, CVAL_MAX);
@@ -1042,6 +1041,8 @@ int main(int argc, char *argv[])
 	/* Tell stdout not to buffer its content */
 	setbuf(stdout, NULL);
 
+	TEST_REQUIRE(kvm_supports_vgic_v3());
+
 	if (!parse_args(argc, argv))
 		exit(KSFT_SKIP);
 
diff --git a/tools/testing/selftests/kvm/arm64/vgic_irq.c b/tools/testing/selftests/kvm/arm64/vgic_irq.c
index a09dd423c2d7..9fc9e8e44ecd 100644
--- a/tools/testing/selftests/kvm/arm64/vgic_irq.c
+++ b/tools/testing/selftests/kvm/arm64/vgic_irq.c
@@ -752,7 +752,6 @@ static void test_vgic(uint32_t nr_irqs, bool level_sensitive, bool eoi_split)
 	vcpu_args_set(vcpu, 1, args_gva);
 
 	gic_fd = vgic_v3_setup(vm, 1, nr_irqs);
-	__TEST_REQUIRE(gic_fd >= 0, "Failed to create vgic-v3, skipping");
 
 	vm_install_exception_handler(vm, VECTOR_IRQ_CURRENT,
 		guest_irq_handlers[args.eoi_split][args.level_sensitive]);
@@ -802,6 +801,8 @@ int main(int argc, char **argv)
 	int opt;
 	bool eoi_split = false;
 
+	TEST_REQUIRE(kvm_supports_vgic_v3());
+
 	while ((opt = getopt(argc, argv, "hn:e:l:")) != -1) {
 		switch (opt) {
 		case 'n':
diff --git a/tools/testing/selftests/kvm/arm64/vgic_lpi_stress.c b/tools/testing/selftests/kvm/arm64/vgic_lpi_stress.c
index fc4fe52fb6f8..cc2b21d374af 100644
--- a/tools/testing/selftests/kvm/arm64/vgic_lpi_stress.c
+++ b/tools/testing/selftests/kvm/arm64/vgic_lpi_stress.c
@@ -215,8 +215,6 @@ static void setup_test_data(void)
 static void setup_gic(void)
 {
 	gic_fd = vgic_v3_setup(vm, test_data.nr_cpus, 64);
-	__TEST_REQUIRE(gic_fd >= 0, "Failed to create GICv3");
-
 	its_fd = vgic_its_setup(vm);
 }
 
@@ -374,6 +372,8 @@ int main(int argc, char **argv)
 	u32 nr_threads;
 	int c;
 
+	TEST_REQUIRE(kvm_supports_vgic_v3());
+
 	while ((c = getopt(argc, argv, "hv:d:e:i:")) != -1) {
 		switch (c) {
 		case 'v':
diff --git a/tools/testing/selftests/kvm/arm64/vpmu_counter_access.c b/tools/testing/selftests/kvm/arm64/vpmu_counter_access.c
index a0c4ab839155..01f61657de45 100644
--- a/tools/testing/selftests/kvm/arm64/vpmu_counter_access.c
+++ b/tools/testing/selftests/kvm/arm64/vpmu_counter_access.c
@@ -436,8 +436,6 @@ static void create_vpmu_vm(void *guest_code)
 	vpmu_vm.vcpu = aarch64_vcpu_add(vpmu_vm.vm, 0, &init, guest_code);
 	vcpu_init_descriptor_tables(vpmu_vm.vcpu);
 	vpmu_vm.gic_fd = vgic_v3_setup(vpmu_vm.vm, 1, 64);
-	__TEST_REQUIRE(vpmu_vm.gic_fd >= 0,
-		       "Failed to create vgic-v3, skipping");
 
 	/* Make sure that PMUv3 support is indicated in the ID register */
 	dfr0 = vcpu_get_reg(vpmu_vm.vcpu, KVM_ARM64_SYS_REG(SYS_ID_AA64DFR0_EL1));
@@ -634,6 +632,7 @@ int main(void)
 	uint64_t i, pmcr_n;
 
 	TEST_REQUIRE(kvm_has_cap(KVM_CAP_ARM_PMU_V3));
+	TEST_REQUIRE(kvm_supports_vgic_v3());
 
 	pmcr_n = get_pmcr_n_limit();
 	for (i = 0; i <= pmcr_n; i++) {
diff --git a/tools/testing/selftests/kvm/include/arm64/vgic.h b/tools/testing/selftests/kvm/include/arm64/vgic.h
index c481d0c00a5d..b858fa8195b4 100644
--- a/tools/testing/selftests/kvm/include/arm64/vgic.h
+++ b/tools/testing/selftests/kvm/include/arm64/vgic.h
@@ -16,6 +16,7 @@
 	((uint64_t)(flags) << 12) | \
 	index)
 
+bool kvm_supports_vgic_v3(void);
 int vgic_v3_setup(struct kvm_vm *vm, unsigned int nr_vcpus, uint32_t nr_irqs);
 
 #define VGIC_MAX_RESERVED	1023
diff --git a/tools/testing/selftests/kvm/lib/arm64/vgic.c b/tools/testing/selftests/kvm/lib/arm64/vgic.c
index 64e793795563..661744c6532e 100644
--- a/tools/testing/selftests/kvm/lib/arm64/vgic.c
+++ b/tools/testing/selftests/kvm/lib/arm64/vgic.c
@@ -15,6 +15,17 @@
 #include "gic.h"
 #include "gic_v3.h"
 
+bool kvm_supports_vgic_v3(void)
+{
+	struct kvm_vm *vm = vm_create_barebones();
+	int r;
+
+	r = __kvm_test_create_device(vm, KVM_DEV_TYPE_ARM_VGIC_V3);
+	kvm_vm_free(vm);
+
+	return !r;
+}
+
 /*
  * vGIC-v3 default host setup
  *
-- 
2.47.3



^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 04/13] KVM: arm64: selftests: Add unsanitised helpers for VGICv3 creation
  2025-09-17 21:20 [PATCH 00/13] KVM: arm64: selftests: Run selftests in VHE EL2 Oliver Upton
                   ` (2 preceding siblings ...)
  2025-09-17 21:20 ` [PATCH 03/13] KVM: arm64: selftests: Add helper to check for VGICv3 support Oliver Upton
@ 2025-09-17 21:20 ` Oliver Upton
  2025-09-17 21:20 ` [PATCH 05/13] KVM: arm64: selftests: Create a VGICv3 for 'default' VMs Oliver Upton
                   ` (9 subsequent siblings)
  13 siblings, 0 replies; 20+ messages in thread
From: Oliver Upton @ 2025-09-17 21:20 UTC (permalink / raw)
  To: kvmarm
  Cc: Marc Zyngier, Joey Gouly, Suzuki K Poulose, Zenghui Yu,
	Paolo Bonzini, Sean Christopherson, Christian Borntraeger,
	Janosch Frank, Claudio Imbrenda, David Hildenbrand,
	linux-arm-kernel, kvm, Oliver Upton

vgic_v3_setup() has a good bit of sanity checking internally to ensure
that vCPUs have actually been created and match the dimensioning of the
vgic itself. Spin off an unsanitised setup and initialization helper so
vgic initialization can be wired in around a 'default' VM's vCPU
creation.

Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
---
 .../selftests/kvm/include/arm64/vgic.h        |  2 +
 tools/testing/selftests/kvm/lib/arm64/vgic.c  | 50 ++++++++++++-------
 2 files changed, 35 insertions(+), 17 deletions(-)

diff --git a/tools/testing/selftests/kvm/include/arm64/vgic.h b/tools/testing/selftests/kvm/include/arm64/vgic.h
index b858fa8195b4..688beccc9436 100644
--- a/tools/testing/selftests/kvm/include/arm64/vgic.h
+++ b/tools/testing/selftests/kvm/include/arm64/vgic.h
@@ -17,6 +17,8 @@
 	index)
 
 bool kvm_supports_vgic_v3(void);
+int __vgic_v3_setup(struct kvm_vm *vm, unsigned int nr_vcpus, uint32_t nr_irqs);
+void __vgic_v3_init(int fd);
 int vgic_v3_setup(struct kvm_vm *vm, unsigned int nr_vcpus, uint32_t nr_irqs);
 
 #define VGIC_MAX_RESERVED	1023
diff --git a/tools/testing/selftests/kvm/lib/arm64/vgic.c b/tools/testing/selftests/kvm/lib/arm64/vgic.c
index 661744c6532e..d0f7bd0984b8 100644
--- a/tools/testing/selftests/kvm/lib/arm64/vgic.c
+++ b/tools/testing/selftests/kvm/lib/arm64/vgic.c
@@ -41,24 +41,11 @@ bool kvm_supports_vgic_v3(void)
  * redistributor regions of the guest. Since it depends on the number of
  * vCPUs for the VM, it must be called after all the vCPUs have been created.
  */
-int vgic_v3_setup(struct kvm_vm *vm, unsigned int nr_vcpus, uint32_t nr_irqs)
+int __vgic_v3_setup(struct kvm_vm *vm, unsigned int nr_vcpus, uint32_t nr_irqs)
 {
 	int gic_fd;
 	uint64_t attr;
-	struct list_head *iter;
-	unsigned int nr_gic_pages, nr_vcpus_created = 0;
-
-	TEST_ASSERT(nr_vcpus, "Number of vCPUs cannot be empty");
-
-	/*
-	 * Make sure that the caller is infact calling this
-	 * function after all the vCPUs are added.
-	 */
-	list_for_each(iter, &vm->vcpus)
-		nr_vcpus_created++;
-	TEST_ASSERT(nr_vcpus == nr_vcpus_created,
-			"Number of vCPUs requested (%u) doesn't match with the ones created for the VM (%u)",
-			nr_vcpus, nr_vcpus_created);
+	unsigned int nr_gic_pages;
 
 	/* Distributor setup */
 	gic_fd = __kvm_create_device(vm, KVM_DEV_TYPE_ARM_VGIC_V3);
@@ -81,10 +68,39 @@ int vgic_v3_setup(struct kvm_vm *vm, unsigned int nr_vcpus, uint32_t nr_irqs)
 						KVM_VGIC_V3_REDIST_SIZE * nr_vcpus);
 	virt_map(vm, GICR_BASE_GPA, GICR_BASE_GPA, nr_gic_pages);
 
-	kvm_device_attr_set(gic_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
+	return gic_fd;
+}
+
+void __vgic_v3_init(int fd)
+{
+	kvm_device_attr_set(fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
 			    KVM_DEV_ARM_VGIC_CTRL_INIT, NULL);
+}
 
-	return gic_fd;
+int vgic_v3_setup(struct kvm_vm *vm, unsigned int nr_vcpus, uint32_t nr_irqs)
+{
+	unsigned int nr_vcpus_created = 0;
+	struct list_head *iter;
+	int fd;
+
+	TEST_ASSERT(nr_vcpus, "Number of vCPUs cannot be empty");
+
+	/*
+	 * Make sure that the caller is infact calling this
+	 * function after all the vCPUs are added.
+	 */
+	list_for_each(iter, &vm->vcpus)
+		nr_vcpus_created++;
+	TEST_ASSERT(nr_vcpus == nr_vcpus_created,
+		    "Number of vCPUs requested (%u) doesn't match with the ones created for the VM (%u)",
+		    nr_vcpus, nr_vcpus_created);
+
+	fd = __vgic_v3_setup(vm, nr_vcpus, nr_irqs);
+	if (fd < 0)
+		return fd;
+
+	__vgic_v3_init(fd);
+	return fd;
 }
 
 /* should only work for level sensitive interrupts */
-- 
2.47.3



^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 05/13] KVM: arm64: selftests: Create a VGICv3 for 'default' VMs
  2025-09-17 21:20 [PATCH 00/13] KVM: arm64: selftests: Run selftests in VHE EL2 Oliver Upton
                   ` (3 preceding siblings ...)
  2025-09-17 21:20 ` [PATCH 04/13] KVM: arm64: selftests: Add unsanitised helpers for VGICv3 creation Oliver Upton
@ 2025-09-17 21:20 ` Oliver Upton
  2025-09-17 21:20 ` [PATCH 06/13] KVM: arm64: selftests: Alias EL1 registers to EL2 counterparts Oliver Upton
                   ` (8 subsequent siblings)
  13 siblings, 0 replies; 20+ messages in thread
From: Oliver Upton @ 2025-09-17 21:20 UTC (permalink / raw)
  To: kvmarm
  Cc: Marc Zyngier, Joey Gouly, Suzuki K Poulose, Zenghui Yu,
	Paolo Bonzini, Sean Christopherson, Christian Borntraeger,
	Janosch Frank, Claudio Imbrenda, David Hildenbrand,
	linux-arm-kernel, kvm, Oliver Upton

Start creating a VGICv3 by default unless explicitly opted-out by the
test. While having an interrupt controller is nice, the real benefit
here is clearing a hurdle for EL2 VMs which mandate the presence of a
VGIC.

Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
---
 .../testing/selftests/kvm/arm64/arch_timer.c  |  4 ---
 .../kvm/arm64/arch_timer_edge_cases.c         |  4 ---
 .../testing/selftests/kvm/arm64/no-vgic-v3.c  |  2 ++
 tools/testing/selftests/kvm/arm64/psci_test.c |  1 +
 .../testing/selftests/kvm/arm64/set_id_regs.c |  1 +
 .../selftests/kvm/arm64/smccc_filter.c        |  1 +
 tools/testing/selftests/kvm/arm64/vgic_init.c |  2 ++
 tools/testing/selftests/kvm/arm64/vgic_irq.c  |  1 +
 .../selftests/kvm/arm64/vgic_lpi_stress.c     |  4 +--
 .../selftests/kvm/arm64/vpmu_counter_access.c |  5 ++-
 .../selftests/kvm/dirty_log_perf_test.c       | 35 -------------------
 tools/testing/selftests/kvm/dirty_log_test.c  |  1 +
 .../kvm/include/arm64/kvm_util_arch.h         |  5 ++-
 .../selftests/kvm/include/arm64/processor.h   |  1 +
 .../testing/selftests/kvm/include/kvm_util.h  |  4 ++-
 .../selftests/kvm/lib/arm64/processor.c       | 26 +++++++++++++-
 tools/testing/selftests/kvm/lib/kvm_util.c    | 15 ++++++--
 .../testing/selftests/kvm/lib/x86/processor.c |  2 +-
 tools/testing/selftests/kvm/s390/cmma_test.c  |  2 +-
 19 files changed, 60 insertions(+), 56 deletions(-)

diff --git a/tools/testing/selftests/kvm/arm64/arch_timer.c b/tools/testing/selftests/kvm/arm64/arch_timer.c
index aaf4285f832a..c753013319bc 100644
--- a/tools/testing/selftests/kvm/arm64/arch_timer.c
+++ b/tools/testing/selftests/kvm/arm64/arch_timer.c
@@ -176,8 +176,6 @@ static void test_init_timer_irq(struct kvm_vm *vm)
 	pr_debug("ptimer_irq: %d; vtimer_irq: %d\n", ptimer_irq, vtimer_irq);
 }
 
-static int gic_fd;
-
 struct kvm_vm *test_vm_create(void)
 {
 	struct kvm_vm *vm;
@@ -206,7 +204,6 @@ struct kvm_vm *test_vm_create(void)
 		vcpu_init_descriptor_tables(vcpus[i]);
 
 	test_init_timer_irq(vm);
-	gic_fd = vgic_v3_setup(vm, nr_vcpus, 64);
 
 	/* Make all the test's cmdline args visible to the guest */
 	sync_global_to_guest(vm, test_args);
@@ -216,6 +213,5 @@ struct kvm_vm *test_vm_create(void)
 
 void test_vm_cleanup(struct kvm_vm *vm)
 {
-	close(gic_fd);
 	kvm_vm_free(vm);
 }
diff --git a/tools/testing/selftests/kvm/arm64/arch_timer_edge_cases.c b/tools/testing/selftests/kvm/arm64/arch_timer_edge_cases.c
index d349d80d8418..5c60262f4c2e 100644
--- a/tools/testing/selftests/kvm/arm64/arch_timer_edge_cases.c
+++ b/tools/testing/selftests/kvm/arm64/arch_timer_edge_cases.c
@@ -935,8 +935,6 @@ static void test_init_timer_irq(struct kvm_vm *vm, struct kvm_vcpu *vcpu)
 	pr_debug("ptimer_irq: %d; vtimer_irq: %d\n", ptimer_irq, vtimer_irq);
 }
 
-static int gic_fd;
-
 static void test_vm_create(struct kvm_vm **vm, struct kvm_vcpu **vcpu,
 			   enum arch_timer timer)
 {
@@ -951,7 +949,6 @@ static void test_vm_create(struct kvm_vm **vm, struct kvm_vcpu **vcpu,
 	vcpu_args_set(*vcpu, 1, timer);
 
 	test_init_timer_irq(*vm, *vcpu);
-	gic_fd = vgic_v3_setup(*vm, 1, 64);
 
 	sync_global_to_guest(*vm, test_args);
 	sync_global_to_guest(*vm, CVAL_MAX);
@@ -960,7 +957,6 @@ static void test_vm_create(struct kvm_vm **vm, struct kvm_vcpu **vcpu,
 
 static void test_vm_cleanup(struct kvm_vm *vm)
 {
-	close(gic_fd);
 	kvm_vm_free(vm);
 }
 
diff --git a/tools/testing/selftests/kvm/arm64/no-vgic-v3.c b/tools/testing/selftests/kvm/arm64/no-vgic-v3.c
index f222538e6084..152c34776981 100644
--- a/tools/testing/selftests/kvm/arm64/no-vgic-v3.c
+++ b/tools/testing/selftests/kvm/arm64/no-vgic-v3.c
@@ -163,6 +163,8 @@ int main(int argc, char *argv[])
 	struct kvm_vm *vm;
 	uint64_t pfr0;
 
+	test_disable_default_vgic();
+
 	vm = vm_create_with_one_vcpu(&vcpu, NULL);
 	pfr0 = vcpu_get_reg(vcpu, KVM_ARM64_SYS_REG(SYS_ID_AA64PFR0_EL1));
 	__TEST_REQUIRE(FIELD_GET(ID_AA64PFR0_EL1_GIC, pfr0),
diff --git a/tools/testing/selftests/kvm/arm64/psci_test.c b/tools/testing/selftests/kvm/arm64/psci_test.c
index ab491ee9e5f7..cf208390fd0e 100644
--- a/tools/testing/selftests/kvm/arm64/psci_test.c
+++ b/tools/testing/selftests/kvm/arm64/psci_test.c
@@ -95,6 +95,7 @@ static struct kvm_vm *setup_vm(void *guest_code, struct kvm_vcpu **source,
 	*source = aarch64_vcpu_add(vm, 0, &init, guest_code);
 	*target = aarch64_vcpu_add(vm, 1, &init, guest_code);
 
+	kvm_arch_vm_finalize_vcpus(vm);
 	return vm;
 }
 
diff --git a/tools/testing/selftests/kvm/arm64/set_id_regs.c b/tools/testing/selftests/kvm/arm64/set_id_regs.c
index a2d367a2c93c..77718628facf 100644
--- a/tools/testing/selftests/kvm/arm64/set_id_regs.c
+++ b/tools/testing/selftests/kvm/arm64/set_id_regs.c
@@ -763,6 +763,7 @@ int main(void)
 	vm = vm_create(1);
 	vm_enable_cap(vm, KVM_CAP_ARM_WRITABLE_IMP_ID_REGS, 0);
 	vcpu = vm_vcpu_add(vm, 0, guest_code);
+	kvm_arch_vm_finalize_vcpus(vm);
 
 	/* Check for AARCH64 only system */
 	val = vcpu_get_reg(vcpu, KVM_ARM64_SYS_REG(SYS_ID_AA64PFR0_EL1));
diff --git a/tools/testing/selftests/kvm/arm64/smccc_filter.c b/tools/testing/selftests/kvm/arm64/smccc_filter.c
index 2d189f3da228..eb5551d21dbe 100644
--- a/tools/testing/selftests/kvm/arm64/smccc_filter.c
+++ b/tools/testing/selftests/kvm/arm64/smccc_filter.c
@@ -73,6 +73,7 @@ static struct kvm_vm *setup_vm(struct kvm_vcpu **vcpu)
 	init.features[0] |= (1 << KVM_ARM_VCPU_PSCI_0_2);
 
 	*vcpu = aarch64_vcpu_add(vm, 0, &init, guest_main);
+	kvm_arch_vm_finalize_vcpus(vm);
 	return vm;
 }
 
diff --git a/tools/testing/selftests/kvm/arm64/vgic_init.c b/tools/testing/selftests/kvm/arm64/vgic_init.c
index a8e0f46bc0ab..8d6d3a4ae4db 100644
--- a/tools/testing/selftests/kvm/arm64/vgic_init.c
+++ b/tools/testing/selftests/kvm/arm64/vgic_init.c
@@ -994,6 +994,8 @@ int main(int ac, char **av)
 	int pa_bits;
 	int cnt_impl = 0;
 
+	test_disable_default_vgic();
+
 	pa_bits = vm_guest_mode_params[VM_MODE_DEFAULT].pa_bits;
 	max_phys_size = 1ULL << pa_bits;
 
diff --git a/tools/testing/selftests/kvm/arm64/vgic_irq.c b/tools/testing/selftests/kvm/arm64/vgic_irq.c
index 9fc9e8e44ecd..6338f5bbdb70 100644
--- a/tools/testing/selftests/kvm/arm64/vgic_irq.c
+++ b/tools/testing/selftests/kvm/arm64/vgic_irq.c
@@ -802,6 +802,7 @@ int main(int argc, char **argv)
 	bool eoi_split = false;
 
 	TEST_REQUIRE(kvm_supports_vgic_v3());
+	test_disable_default_vgic();
 
 	while ((opt = getopt(argc, argv, "hn:e:l:")) != -1) {
 		switch (opt) {
diff --git a/tools/testing/selftests/kvm/arm64/vgic_lpi_stress.c b/tools/testing/selftests/kvm/arm64/vgic_lpi_stress.c
index cc2b21d374af..87922a89b134 100644
--- a/tools/testing/selftests/kvm/arm64/vgic_lpi_stress.c
+++ b/tools/testing/selftests/kvm/arm64/vgic_lpi_stress.c
@@ -27,7 +27,7 @@ static vm_paddr_t gpa_base;
 
 static struct kvm_vm *vm;
 static struct kvm_vcpu **vcpus;
-static int gic_fd, its_fd;
+static int its_fd;
 
 static struct test_data {
 	bool		request_vcpus_stop;
@@ -214,7 +214,6 @@ static void setup_test_data(void)
 
 static void setup_gic(void)
 {
-	gic_fd = vgic_v3_setup(vm, test_data.nr_cpus, 64);
 	its_fd = vgic_its_setup(vm);
 }
 
@@ -353,7 +352,6 @@ static void setup_vm(void)
 static void destroy_vm(void)
 {
 	close(its_fd);
-	close(gic_fd);
 	kvm_vm_free(vm);
 	free(vcpus);
 }
diff --git a/tools/testing/selftests/kvm/arm64/vpmu_counter_access.c b/tools/testing/selftests/kvm/arm64/vpmu_counter_access.c
index 01f61657de45..4a7e8e85a1b8 100644
--- a/tools/testing/selftests/kvm/arm64/vpmu_counter_access.c
+++ b/tools/testing/selftests/kvm/arm64/vpmu_counter_access.c
@@ -28,7 +28,6 @@
 struct vpmu_vm {
 	struct kvm_vm *vm;
 	struct kvm_vcpu *vcpu;
-	int gic_fd;
 };
 
 static struct vpmu_vm vpmu_vm;
@@ -435,7 +434,8 @@ static void create_vpmu_vm(void *guest_code)
 	init.features[0] |= (1 << KVM_ARM_VCPU_PMU_V3);
 	vpmu_vm.vcpu = aarch64_vcpu_add(vpmu_vm.vm, 0, &init, guest_code);
 	vcpu_init_descriptor_tables(vpmu_vm.vcpu);
-	vpmu_vm.gic_fd = vgic_v3_setup(vpmu_vm.vm, 1, 64);
+
+	kvm_arch_vm_finalize_vcpus(vpmu_vm.vm);
 
 	/* Make sure that PMUv3 support is indicated in the ID register */
 	dfr0 = vcpu_get_reg(vpmu_vm.vcpu, KVM_ARM64_SYS_REG(SYS_ID_AA64DFR0_EL1));
@@ -451,7 +451,6 @@ static void create_vpmu_vm(void *guest_code)
 
 static void destroy_vpmu_vm(void)
 {
-	close(vpmu_vm.gic_fd);
 	kvm_vm_free(vpmu_vm.vm);
 }
 
diff --git a/tools/testing/selftests/kvm/dirty_log_perf_test.c b/tools/testing/selftests/kvm/dirty_log_perf_test.c
index e79817bd0e29..0a1ea1d1e2d8 100644
--- a/tools/testing/selftests/kvm/dirty_log_perf_test.c
+++ b/tools/testing/selftests/kvm/dirty_log_perf_test.c
@@ -20,38 +20,6 @@
 #include "guest_modes.h"
 #include "ucall_common.h"
 
-#ifdef __aarch64__
-#include "arm64/vgic.h"
-
-static int gic_fd;
-
-static void arch_setup_vm(struct kvm_vm *vm, unsigned int nr_vcpus)
-{
-	/*
-	 * The test can still run even if hardware does not support GICv3, as it
-	 * is only an optimization to reduce guest exits.
-	 */
-	gic_fd = vgic_v3_setup(vm, nr_vcpus, 64);
-}
-
-static void arch_cleanup_vm(struct kvm_vm *vm)
-{
-	if (gic_fd > 0)
-		close(gic_fd);
-}
-
-#else /* __aarch64__ */
-
-static void arch_setup_vm(struct kvm_vm *vm, unsigned int nr_vcpus)
-{
-}
-
-static void arch_cleanup_vm(struct kvm_vm *vm)
-{
-}
-
-#endif
-
 /* How many host loops to run by default (one KVM_GET_DIRTY_LOG for each loop)*/
 #define TEST_HOST_LOOP_N		2UL
 
@@ -166,8 +134,6 @@ static void run_test(enum vm_guest_mode mode, void *arg)
 		vm_enable_cap(vm, KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2,
 			      dirty_log_manual_caps);
 
-	arch_setup_vm(vm, nr_vcpus);
-
 	/* Start the iterations */
 	iteration = 0;
 	host_quit = false;
@@ -285,7 +251,6 @@ static void run_test(enum vm_guest_mode mode, void *arg)
 	}
 
 	memstress_free_bitmaps(bitmaps, p->slots);
-	arch_cleanup_vm(vm);
 	memstress_destroy_vm(vm);
 }
 
diff --git a/tools/testing/selftests/kvm/dirty_log_test.c b/tools/testing/selftests/kvm/dirty_log_test.c
index 23593d9eeba9..d58a641b0e6a 100644
--- a/tools/testing/selftests/kvm/dirty_log_test.c
+++ b/tools/testing/selftests/kvm/dirty_log_test.c
@@ -585,6 +585,7 @@ static struct kvm_vm *create_vm(enum vm_guest_mode mode, struct kvm_vcpu **vcpu,
 
 	log_mode_create_vm_done(vm);
 	*vcpu = vm_vcpu_add(vm, 0, guest_code);
+	kvm_arch_vm_finalize_vcpus(vm);
 	return vm;
 }
 
diff --git a/tools/testing/selftests/kvm/include/arm64/kvm_util_arch.h b/tools/testing/selftests/kvm/include/arm64/kvm_util_arch.h
index e43a57d99b56..b973bb2c64a6 100644
--- a/tools/testing/selftests/kvm/include/arm64/kvm_util_arch.h
+++ b/tools/testing/selftests/kvm/include/arm64/kvm_util_arch.h
@@ -2,6 +2,9 @@
 #ifndef SELFTEST_KVM_UTIL_ARCH_H
 #define SELFTEST_KVM_UTIL_ARCH_H
 
-struct kvm_vm_arch {};
+struct kvm_vm_arch {
+	bool	has_gic;
+	int	gic_fd;
+};
 
 #endif  // SELFTEST_KVM_UTIL_ARCH_H
diff --git a/tools/testing/selftests/kvm/include/arm64/processor.h b/tools/testing/selftests/kvm/include/arm64/processor.h
index 8370fc94041d..8c066ba1deb5 100644
--- a/tools/testing/selftests/kvm/include/arm64/processor.h
+++ b/tools/testing/selftests/kvm/include/arm64/processor.h
@@ -301,5 +301,6 @@ void smccc_smc(uint32_t function_id, uint64_t arg0, uint64_t arg1,
 void wfi(void);
 
 void test_wants_mte(void);
+void test_disable_default_vgic(void);
 
 #endif /* SELFTEST_KVM_PROCESSOR_H */
diff --git a/tools/testing/selftests/kvm/include/kvm_util.h b/tools/testing/selftests/kvm/include/kvm_util.h
index 23a506d7eca3..3ab1fffbc3f2 100644
--- a/tools/testing/selftests/kvm/include/kvm_util.h
+++ b/tools/testing/selftests/kvm/include/kvm_util.h
@@ -1257,7 +1257,9 @@ static inline int __vm_disable_nx_huge_pages(struct kvm_vm *vm)
  */
 void kvm_selftest_arch_init(void);
 
-void kvm_arch_vm_post_create(struct kvm_vm *vm);
+void kvm_arch_vm_post_create(struct kvm_vm *vm, unsigned int nr_vcpus);
+void kvm_arch_vm_finalize_vcpus(struct kvm_vm *vm);
+void kvm_arch_vm_release(struct kvm_vm *vm);
 
 bool vm_is_gpa_protected(struct kvm_vm *vm, vm_paddr_t paddr);
 
diff --git a/tools/testing/selftests/kvm/lib/arm64/processor.c b/tools/testing/selftests/kvm/lib/arm64/processor.c
index caed1998c7b3..de77d9a7e0cd 100644
--- a/tools/testing/selftests/kvm/lib/arm64/processor.c
+++ b/tools/testing/selftests/kvm/lib/arm64/processor.c
@@ -12,6 +12,7 @@
 #include "kvm_util.h"
 #include "processor.h"
 #include "ucall_common.h"
+#include "vgic.h"
 
 #include <linux/bitfield.h>
 #include <linux/sizes.h>
@@ -655,14 +656,37 @@ void wfi(void)
 }
 
 static bool request_mte;
+static bool request_vgic = true;
 
 void test_wants_mte(void)
 {
 	request_mte = true;
 }
 
-void kvm_arch_vm_post_create(struct kvm_vm *vm)
+void test_disable_default_vgic(void)
+{
+	request_vgic = false;
+}
+
+void kvm_arch_vm_post_create(struct kvm_vm *vm, unsigned int nr_vcpus)
 {
 	if (request_mte && vm_check_cap(vm, KVM_CAP_ARM_MTE))
 		vm_enable_cap(vm, KVM_CAP_ARM_MTE, 0);
+
+	if (request_vgic && kvm_supports_vgic_v3()) {
+		vm->arch.gic_fd = __vgic_v3_setup(vm, nr_vcpus, 64);
+		vm->arch.has_gic = true;
+	}
+}
+
+void kvm_arch_vm_finalize_vcpus(struct kvm_vm *vm)
+{
+	if (vm->arch.has_gic)
+		__vgic_v3_init(vm->arch.gic_fd);
+}
+
+void kvm_arch_vm_release(struct kvm_vm *vm)
+{
+	if (vm->arch.has_gic)
+		close(vm->arch.gic_fd);
 }
diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/kvm/lib/kvm_util.c
index c3f5142b0a54..67f32d41a59c 100644
--- a/tools/testing/selftests/kvm/lib/kvm_util.c
+++ b/tools/testing/selftests/kvm/lib/kvm_util.c
@@ -517,7 +517,7 @@ struct kvm_vm *__vm_create(struct vm_shape shape, uint32_t nr_runnable_vcpus,
 	guest_rng = new_guest_random_state(guest_random_seed);
 	sync_global_to_guest(vm, guest_rng);
 
-	kvm_arch_vm_post_create(vm);
+	kvm_arch_vm_post_create(vm, nr_runnable_vcpus);
 
 	return vm;
 }
@@ -555,6 +555,7 @@ struct kvm_vm *__vm_create_with_vcpus(struct vm_shape shape, uint32_t nr_vcpus,
 	for (i = 0; i < nr_vcpus; ++i)
 		vcpus[i] = vm_vcpu_add(vm, i, guest_code);
 
+	kvm_arch_vm_finalize_vcpus(vm);
 	return vm;
 }
 
@@ -805,6 +806,8 @@ void kvm_vm_release(struct kvm_vm *vmp)
 
 	/* Free cached stats metadata and close FD */
 	kvm_stats_release(&vmp->stats);
+
+	kvm_arch_vm_release(vmp);
 }
 
 static void __vm_mem_region_delete(struct kvm_vm *vm,
@@ -2330,7 +2333,15 @@ void kvm_get_stat(struct kvm_binary_stats *stats, const char *name,
 	TEST_FAIL("Unable to find stat '%s'", name);
 }
 
-__weak void kvm_arch_vm_post_create(struct kvm_vm *vm)
+__weak void kvm_arch_vm_post_create(struct kvm_vm *vm, unsigned int nr_vcpus)
+{
+}
+
+__weak void kvm_arch_vm_finalize_vcpus(struct kvm_vm *vm)
+{
+}
+
+__weak void kvm_arch_vm_release(struct kvm_vm *vm)
 {
 }
 
diff --git a/tools/testing/selftests/kvm/lib/x86/processor.c b/tools/testing/selftests/kvm/lib/x86/processor.c
index d4c19ac885a9..bff75aa341bf 100644
--- a/tools/testing/selftests/kvm/lib/x86/processor.c
+++ b/tools/testing/selftests/kvm/lib/x86/processor.c
@@ -625,7 +625,7 @@ void assert_on_unhandled_exception(struct kvm_vcpu *vcpu)
 		REPORT_GUEST_ASSERT(uc);
 }
 
-void kvm_arch_vm_post_create(struct kvm_vm *vm)
+void kvm_arch_vm_post_create(struct kvm_vm *vm, unsigned int nr_vcpus)
 {
 	int r;
 
diff --git a/tools/testing/selftests/kvm/s390/cmma_test.c b/tools/testing/selftests/kvm/s390/cmma_test.c
index 85cc8c18d6e7..e39a724fe860 100644
--- a/tools/testing/selftests/kvm/s390/cmma_test.c
+++ b/tools/testing/selftests/kvm/s390/cmma_test.c
@@ -145,7 +145,7 @@ static void finish_vm_setup(struct kvm_vm *vm)
 	slot0 = memslot2region(vm, 0);
 	ucall_init(vm, slot0->region.guest_phys_addr + slot0->region.memory_size);
 
-	kvm_arch_vm_post_create(vm);
+	kvm_arch_vm_post_create(vm, 0);
 }
 
 static struct kvm_vm *create_vm_two_memslots(void)
-- 
2.47.3



^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 06/13] KVM: arm64: selftests: Alias EL1 registers to EL2 counterparts
  2025-09-17 21:20 [PATCH 00/13] KVM: arm64: selftests: Run selftests in VHE EL2 Oliver Upton
                   ` (4 preceding siblings ...)
  2025-09-17 21:20 ` [PATCH 05/13] KVM: arm64: selftests: Create a VGICv3 for 'default' VMs Oliver Upton
@ 2025-09-17 21:20 ` Oliver Upton
  2025-09-17 21:20 ` [PATCH 07/13] KVM: arm64: selftests: Provide helper for getting default vCPU target Oliver Upton
                   ` (7 subsequent siblings)
  13 siblings, 0 replies; 20+ messages in thread
From: Oliver Upton @ 2025-09-17 21:20 UTC (permalink / raw)
  To: kvmarm
  Cc: Marc Zyngier, Joey Gouly, Suzuki K Poulose, Zenghui Yu,
	Paolo Bonzini, Sean Christopherson, Christian Borntraeger,
	Janosch Frank, Claudio Imbrenda, David Hildenbrand,
	linux-arm-kernel, kvm, Oliver Upton

FEAT_VHE has the somewhat nice property of implicitly redirecting EL1
register aliases to their corresponding EL2 representations when E2H=1.
Unfortunately, there's no such abstraction for userspace and EL2
registers are always accessed by their canonical encoding.

Introduce a helper that applies EL2 redirections to sysregs and use
aggressive inlining to catch misuse at compile time. Go a little past
the architectural definition for ease of use for test authors (e.g. the
stack pointer).

Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
---
 .../selftests/kvm/arm64/vpmu_counter_access.c |  4 +-
 .../selftests/kvm/include/arm64/processor.h   | 54 +++++++++++++++++++
 .../testing/selftests/kvm/include/kvm_util.h  |  3 ++
 .../selftests/kvm/lib/arm64/processor.c       | 19 +++----
 4 files changed, 69 insertions(+), 11 deletions(-)

diff --git a/tools/testing/selftests/kvm/arm64/vpmu_counter_access.c b/tools/testing/selftests/kvm/arm64/vpmu_counter_access.c
index 4a7e8e85a1b8..36a3a8b4e0b5 100644
--- a/tools/testing/selftests/kvm/arm64/vpmu_counter_access.c
+++ b/tools/testing/selftests/kvm/arm64/vpmu_counter_access.c
@@ -517,7 +517,7 @@ static void run_access_test(uint64_t pmcr_n)
 	vcpu = vpmu_vm.vcpu;
 
 	/* Save the initial sp to restore them later to run the guest again */
-	sp = vcpu_get_reg(vcpu, ARM64_CORE_REG(sp_el1));
+	sp = vcpu_get_reg(vcpu, ctxt_reg_alias(vcpu, SYS_SP_EL1));
 
 	run_vcpu(vcpu, pmcr_n);
 
@@ -529,7 +529,7 @@ static void run_access_test(uint64_t pmcr_n)
 	init.features[0] |= (1 << KVM_ARM_VCPU_PMU_V3);
 	aarch64_vcpu_setup(vcpu, &init);
 	vcpu_init_descriptor_tables(vcpu);
-	vcpu_set_reg(vcpu, ARM64_CORE_REG(sp_el1), sp);
+	vcpu_set_reg(vcpu, ctxt_reg_alias(vcpu, SYS_SP_EL1), sp);
 	vcpu_set_reg(vcpu, ARM64_CORE_REG(regs.pc), (uint64_t)guest_code);
 
 	run_vcpu(vcpu, pmcr_n);
diff --git a/tools/testing/selftests/kvm/include/arm64/processor.h b/tools/testing/selftests/kvm/include/arm64/processor.h
index 8c066ba1deb5..5a4b29c1b965 100644
--- a/tools/testing/selftests/kvm/include/arm64/processor.h
+++ b/tools/testing/selftests/kvm/include/arm64/processor.h
@@ -303,4 +303,58 @@ void wfi(void);
 void test_wants_mte(void);
 void test_disable_default_vgic(void);
 
+static bool vcpu_has_el2(struct kvm_vcpu *vcpu)
+{
+	return vcpu->init.features[0] & BIT(KVM_ARM_VCPU_HAS_EL2);
+}
+
+#define MAPPED_EL2_SYSREG(el2, el1)		\
+	case SYS_##el1:				\
+		if (vcpu_has_el2(vcpu))		\
+			alias = SYS_##el2;	\
+		break
+
+
+static __always_inline u64 ctxt_reg_alias(struct kvm_vcpu *vcpu, u32 encoding)
+{
+	u32 alias = encoding;
+
+	BUILD_BUG_ON(!__builtin_constant_p(encoding));
+
+	switch (encoding) {
+	MAPPED_EL2_SYSREG(SCTLR_EL2,		SCTLR_EL1);
+	MAPPED_EL2_SYSREG(CPTR_EL2,		CPACR_EL1);
+	MAPPED_EL2_SYSREG(TTBR0_EL2,		TTBR0_EL1);
+	MAPPED_EL2_SYSREG(TTBR1_EL2,		TTBR1_EL1);
+	MAPPED_EL2_SYSREG(TCR_EL2,		TCR_EL1);
+	MAPPED_EL2_SYSREG(VBAR_EL2,		VBAR_EL1);
+	MAPPED_EL2_SYSREG(AFSR0_EL2,		AFSR0_EL1);
+	MAPPED_EL2_SYSREG(AFSR1_EL2,		AFSR1_EL1);
+	MAPPED_EL2_SYSREG(ESR_EL2,		ESR_EL1);
+	MAPPED_EL2_SYSREG(FAR_EL2,		FAR_EL1);
+	MAPPED_EL2_SYSREG(MAIR_EL2,		MAIR_EL1);
+	MAPPED_EL2_SYSREG(TCR2_EL2,		TCR2_EL1);
+	MAPPED_EL2_SYSREG(PIR_EL2,		PIR_EL1);
+	MAPPED_EL2_SYSREG(PIRE0_EL2,		PIRE0_EL1);
+	MAPPED_EL2_SYSREG(POR_EL2,		POR_EL1);
+	MAPPED_EL2_SYSREG(AMAIR_EL2,		AMAIR_EL1);
+	MAPPED_EL2_SYSREG(ELR_EL2,		ELR_EL1);
+	MAPPED_EL2_SYSREG(SPSR_EL2,		SPSR_EL1);
+	MAPPED_EL2_SYSREG(ZCR_EL2,		ZCR_EL1);
+	MAPPED_EL2_SYSREG(CONTEXTIDR_EL2,	CONTEXTIDR_EL1);
+	MAPPED_EL2_SYSREG(SCTLR2_EL2,		SCTLR2_EL1);
+	MAPPED_EL2_SYSREG(CNTHCTL_EL2,		CNTKCTL_EL1);
+	case SYS_SP_EL1:
+		if (!vcpu_has_el2(vcpu))
+			return ARM64_CORE_REG(sp_el1);
+
+		alias = SYS_SP_EL2;
+		break;
+	default:
+		BUILD_BUG();
+	}
+
+	return KVM_ARM64_SYS_REG(alias);
+}
+
 #endif /* SELFTEST_KVM_PROCESSOR_H */
diff --git a/tools/testing/selftests/kvm/include/kvm_util.h b/tools/testing/selftests/kvm/include/kvm_util.h
index 3ab1fffbc3f2..11b6c5aa3f12 100644
--- a/tools/testing/selftests/kvm/include/kvm_util.h
+++ b/tools/testing/selftests/kvm/include/kvm_util.h
@@ -63,6 +63,9 @@ struct kvm_vcpu {
 	struct kvm_run *run;
 #ifdef __x86_64__
 	struct kvm_cpuid2 *cpuid;
+#endif
+#ifdef __aarch64__
+	struct kvm_vcpu_init init;
 #endif
 	struct kvm_binary_stats stats;
 	struct kvm_dirty_gfn *dirty_gfns;
diff --git a/tools/testing/selftests/kvm/lib/arm64/processor.c b/tools/testing/selftests/kvm/lib/arm64/processor.c
index de77d9a7e0cd..311660a9f655 100644
--- a/tools/testing/selftests/kvm/lib/arm64/processor.c
+++ b/tools/testing/selftests/kvm/lib/arm64/processor.c
@@ -283,15 +283,16 @@ void aarch64_vcpu_setup(struct kvm_vcpu *vcpu, struct kvm_vcpu_init *init)
 	}
 
 	vcpu_ioctl(vcpu, KVM_ARM_VCPU_INIT, init);
+	vcpu->init = *init;
 
 	/*
 	 * Enable FP/ASIMD to avoid trapping when accessing Q0-Q15
 	 * registers, which the variable argument list macros do.
 	 */
-	vcpu_set_reg(vcpu, KVM_ARM64_SYS_REG(SYS_CPACR_EL1), 3 << 20);
+	vcpu_set_reg(vcpu, ctxt_reg_alias(vcpu, SYS_CPACR_EL1), 3 << 20);
 
-	sctlr_el1 = vcpu_get_reg(vcpu, KVM_ARM64_SYS_REG(SYS_SCTLR_EL1));
-	tcr_el1 = vcpu_get_reg(vcpu, KVM_ARM64_SYS_REG(SYS_TCR_EL1));
+	sctlr_el1 = vcpu_get_reg(vcpu, ctxt_reg_alias(vcpu, SYS_SCTLR_EL1));
+	tcr_el1 = vcpu_get_reg(vcpu, ctxt_reg_alias(vcpu, SYS_TCR_EL1));
 
 	/* Configure base granule size */
 	switch (vm->mode) {
@@ -358,10 +359,10 @@ void aarch64_vcpu_setup(struct kvm_vcpu *vcpu, struct kvm_vcpu_init *init)
 	if (use_lpa2_pte_format(vm))
 		tcr_el1 |= TCR_DS;
 
-	vcpu_set_reg(vcpu, KVM_ARM64_SYS_REG(SYS_SCTLR_EL1), sctlr_el1);
-	vcpu_set_reg(vcpu, KVM_ARM64_SYS_REG(SYS_TCR_EL1), tcr_el1);
-	vcpu_set_reg(vcpu, KVM_ARM64_SYS_REG(SYS_MAIR_EL1), DEFAULT_MAIR_EL1);
-	vcpu_set_reg(vcpu, KVM_ARM64_SYS_REG(SYS_TTBR0_EL1), ttbr0_el1);
+	vcpu_set_reg(vcpu, ctxt_reg_alias(vcpu, SYS_SCTLR_EL1), sctlr_el1);
+	vcpu_set_reg(vcpu, ctxt_reg_alias(vcpu, SYS_TCR_EL1), tcr_el1);
+	vcpu_set_reg(vcpu, ctxt_reg_alias(vcpu, SYS_MAIR_EL1), DEFAULT_MAIR_EL1);
+	vcpu_set_reg(vcpu, ctxt_reg_alias(vcpu, SYS_TTBR0_EL1), ttbr0_el1);
 	vcpu_set_reg(vcpu, KVM_ARM64_SYS_REG(SYS_TPIDR_EL1), vcpu->id);
 }
 
@@ -396,7 +397,7 @@ static struct kvm_vcpu *__aarch64_vcpu_add(struct kvm_vm *vm, uint32_t vcpu_id,
 
 	aarch64_vcpu_setup(vcpu, init);
 
-	vcpu_set_reg(vcpu, ARM64_CORE_REG(sp_el1), stack_vaddr + stack_size);
+	vcpu_set_reg(vcpu, ctxt_reg_alias(vcpu, SYS_SP_EL1), stack_vaddr + stack_size);
 	return vcpu;
 }
 
@@ -466,7 +467,7 @@ void vcpu_init_descriptor_tables(struct kvm_vcpu *vcpu)
 {
 	extern char vectors;
 
-	vcpu_set_reg(vcpu, KVM_ARM64_SYS_REG(SYS_VBAR_EL1), (uint64_t)&vectors);
+	vcpu_set_reg(vcpu, ctxt_reg_alias(vcpu, SYS_VBAR_EL1), (uint64_t)&vectors);
 }
 
 void route_exception(struct ex_regs *regs, int vector)
-- 
2.47.3



^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 07/13] KVM: arm64: selftests: Provide helper for getting default vCPU target
  2025-09-17 21:20 [PATCH 00/13] KVM: arm64: selftests: Run selftests in VHE EL2 Oliver Upton
                   ` (5 preceding siblings ...)
  2025-09-17 21:20 ` [PATCH 06/13] KVM: arm64: selftests: Alias EL1 registers to EL2 counterparts Oliver Upton
@ 2025-09-17 21:20 ` Oliver Upton
  2025-09-17 21:56   ` Itaru Kitayama
  2025-09-17 21:20 ` [PATCH 08/13] KVM: arm64: selftests: Select SMCCC conduit based on current EL Oliver Upton
                   ` (6 subsequent siblings)
  13 siblings, 1 reply; 20+ messages in thread
From: Oliver Upton @ 2025-09-17 21:20 UTC (permalink / raw)
  To: kvmarm
  Cc: Marc Zyngier, Joey Gouly, Suzuki K Poulose, Zenghui Yu,
	Paolo Bonzini, Sean Christopherson, Christian Borntraeger,
	Janosch Frank, Claudio Imbrenda, David Hildenbrand,
	linux-arm-kernel, kvm, Oliver Upton

The default vCPU target in KVM selftests is pretty boring in that it
doesn't enable any vCPU features. Expose a helper for getting the
default target to prepare for cramming in more features. Call
KVM_ARM_PREFERRED_TARGET directly from get-reg-list as it needs
fine-grained control over feature flags.

Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
---
 tools/testing/selftests/kvm/arm64/psci_test.c   |  2 +-
 .../testing/selftests/kvm/arm64/smccc_filter.c  |  2 +-
 .../selftests/kvm/arm64/vpmu_counter_access.c   |  4 ++--
 tools/testing/selftests/kvm/get-reg-list.c      |  9 ++++++---
 .../selftests/kvm/include/arm64/processor.h     |  2 ++
 .../testing/selftests/kvm/lib/arm64/processor.c | 17 +++++++++++------
 6 files changed, 23 insertions(+), 13 deletions(-)

diff --git a/tools/testing/selftests/kvm/arm64/psci_test.c b/tools/testing/selftests/kvm/arm64/psci_test.c
index cf208390fd0e..0d4680da66d1 100644
--- a/tools/testing/selftests/kvm/arm64/psci_test.c
+++ b/tools/testing/selftests/kvm/arm64/psci_test.c
@@ -89,7 +89,7 @@ static struct kvm_vm *setup_vm(void *guest_code, struct kvm_vcpu **source,
 
 	vm = vm_create(2);
 
-	vm_ioctl(vm, KVM_ARM_PREFERRED_TARGET, &init);
+	kvm_get_default_vcpu_target(vm, &init);
 	init.features[0] |= (1 << KVM_ARM_VCPU_PSCI_0_2);
 
 	*source = aarch64_vcpu_add(vm, 0, &init, guest_code);
diff --git a/tools/testing/selftests/kvm/arm64/smccc_filter.c b/tools/testing/selftests/kvm/arm64/smccc_filter.c
index eb5551d21dbe..a8e22d866ea7 100644
--- a/tools/testing/selftests/kvm/arm64/smccc_filter.c
+++ b/tools/testing/selftests/kvm/arm64/smccc_filter.c
@@ -64,7 +64,7 @@ static struct kvm_vm *setup_vm(struct kvm_vcpu **vcpu)
 	struct kvm_vm *vm;
 
 	vm = vm_create(1);
-	vm_ioctl(vm, KVM_ARM_PREFERRED_TARGET, &init);
+	kvm_get_default_vcpu_target(vm, &init);
 
 	/*
 	 * Enable in-kernel emulation of PSCI to ensure that calls are denied
diff --git a/tools/testing/selftests/kvm/arm64/vpmu_counter_access.c b/tools/testing/selftests/kvm/arm64/vpmu_counter_access.c
index 36a3a8b4e0b5..2a8f31c8e59f 100644
--- a/tools/testing/selftests/kvm/arm64/vpmu_counter_access.c
+++ b/tools/testing/selftests/kvm/arm64/vpmu_counter_access.c
@@ -430,7 +430,7 @@ static void create_vpmu_vm(void *guest_code)
 	}
 
 	/* Create vCPU with PMUv3 */
-	vm_ioctl(vpmu_vm.vm, KVM_ARM_PREFERRED_TARGET, &init);
+	kvm_get_default_vcpu_target(vpmu_vm.vm, &init);
 	init.features[0] |= (1 << KVM_ARM_VCPU_PMU_V3);
 	vpmu_vm.vcpu = aarch64_vcpu_add(vpmu_vm.vm, 0, &init, guest_code);
 	vcpu_init_descriptor_tables(vpmu_vm.vcpu);
@@ -525,7 +525,7 @@ static void run_access_test(uint64_t pmcr_n)
 	 * Reset and re-initialize the vCPU, and run the guest code again to
 	 * check if PMCR_EL0.N is preserved.
 	 */
-	vm_ioctl(vpmu_vm.vm, KVM_ARM_PREFERRED_TARGET, &init);
+	kvm_get_default_vcpu_target(vpmu_vm.vm, &init);
 	init.features[0] |= (1 << KVM_ARM_VCPU_PMU_V3);
 	aarch64_vcpu_setup(vcpu, &init);
 	vcpu_init_descriptor_tables(vcpu);
diff --git a/tools/testing/selftests/kvm/get-reg-list.c b/tools/testing/selftests/kvm/get-reg-list.c
index 91f05f78e824..f4644c9d2d3b 100644
--- a/tools/testing/selftests/kvm/get-reg-list.c
+++ b/tools/testing/selftests/kvm/get-reg-list.c
@@ -116,10 +116,13 @@ void __weak finalize_vcpu(struct kvm_vcpu *vcpu, struct vcpu_reg_list *c)
 }
 
 #ifdef __aarch64__
-static void prepare_vcpu_init(struct vcpu_reg_list *c, struct kvm_vcpu_init *init)
+static void prepare_vcpu_init(struct kvm_vm *vm, struct vcpu_reg_list *c,
+			      struct kvm_vcpu_init *init)
 {
 	struct vcpu_reg_sublist *s;
 
+	vm_ioctl(vm, KVM_ARM_PREFERRED_TARGET, init);
+
 	for_each_sublist(c, s)
 		if (s->capability)
 			init->features[s->feature / 32] |= 1 << (s->feature % 32);
@@ -127,10 +130,10 @@ static void prepare_vcpu_init(struct vcpu_reg_list *c, struct kvm_vcpu_init *ini
 
 static struct kvm_vcpu *vcpu_config_get_vcpu(struct vcpu_reg_list *c, struct kvm_vm *vm)
 {
-	struct kvm_vcpu_init init = { .target = -1, };
+	struct kvm_vcpu_init init;
 	struct kvm_vcpu *vcpu;
 
-	prepare_vcpu_init(c, &init);
+	prepare_vcpu_init(vm, c, &init);
 	vcpu = __vm_vcpu_add(vm, 0);
 	aarch64_vcpu_setup(vcpu, &init);
 
diff --git a/tools/testing/selftests/kvm/include/arm64/processor.h b/tools/testing/selftests/kvm/include/arm64/processor.h
index 5a4b29c1b965..87f50efed720 100644
--- a/tools/testing/selftests/kvm/include/arm64/processor.h
+++ b/tools/testing/selftests/kvm/include/arm64/processor.h
@@ -357,4 +357,6 @@ static __always_inline u64 ctxt_reg_alias(struct kvm_vcpu *vcpu, u32 encoding)
 	return KVM_ARM64_SYS_REG(alias);
 }
 
+void kvm_get_default_vcpu_target(struct kvm_vm *vm, struct kvm_vcpu_init *init);
+
 #endif /* SELFTEST_KVM_PROCESSOR_H */
diff --git a/tools/testing/selftests/kvm/lib/arm64/processor.c b/tools/testing/selftests/kvm/lib/arm64/processor.c
index 311660a9f655..5ae65fefd48c 100644
--- a/tools/testing/selftests/kvm/lib/arm64/processor.c
+++ b/tools/testing/selftests/kvm/lib/arm64/processor.c
@@ -267,19 +267,24 @@ void virt_arch_dump(FILE *stream, struct kvm_vm *vm, uint8_t indent)
 	}
 }
 
+void kvm_get_default_vcpu_target(struct kvm_vm *vm, struct kvm_vcpu_init *init)
+{
+	struct kvm_vcpu_init preferred = {};
+
+	vm_ioctl(vm, KVM_ARM_PREFERRED_TARGET, &preferred);
+
+	*init = preferred;
+}
+
 void aarch64_vcpu_setup(struct kvm_vcpu *vcpu, struct kvm_vcpu_init *init)
 {
 	struct kvm_vcpu_init default_init = { .target = -1, };
 	struct kvm_vm *vm = vcpu->vm;
 	uint64_t sctlr_el1, tcr_el1, ttbr0_el1;
 
-	if (!init)
+	if (!init) {
+		kvm_get_default_vcpu_target(vm, &default_init);
 		init = &default_init;
-
-	if (init->target == -1) {
-		struct kvm_vcpu_init preferred;
-		vm_ioctl(vm, KVM_ARM_PREFERRED_TARGET, &preferred);
-		init->target = preferred.target;
 	}
 
 	vcpu_ioctl(vcpu, KVM_ARM_VCPU_INIT, init);
-- 
2.47.3



^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 08/13] KVM: arm64: selftests: Select SMCCC conduit based on current EL
  2025-09-17 21:20 [PATCH 00/13] KVM: arm64: selftests: Run selftests in VHE EL2 Oliver Upton
                   ` (6 preceding siblings ...)
  2025-09-17 21:20 ` [PATCH 07/13] KVM: arm64: selftests: Provide helper for getting default vCPU target Oliver Upton
@ 2025-09-17 21:20 ` Oliver Upton
  2025-09-17 21:20 ` [PATCH 09/13] KVM: arm64: selftests: Use hyp timer IRQs when test runs at EL2 Oliver Upton
                   ` (5 subsequent siblings)
  13 siblings, 0 replies; 20+ messages in thread
From: Oliver Upton @ 2025-09-17 21:20 UTC (permalink / raw)
  To: kvmarm
  Cc: Marc Zyngier, Joey Gouly, Suzuki K Poulose, Zenghui Yu,
	Paolo Bonzini, Sean Christopherson, Christian Borntraeger,
	Janosch Frank, Claudio Imbrenda, David Hildenbrand,
	linux-arm-kernel, kvm, Oliver Upton

HVCs are taken within the VM when EL2 is in use. Ensure tests use the
SMC instruction when running at EL2 to interact with the host.

Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
---
 tools/testing/selftests/kvm/arm64/hypercalls.c      |  2 +-
 tools/testing/selftests/kvm/arm64/kvm-uuid.c        |  2 +-
 tools/testing/selftests/kvm/arm64/psci_test.c       | 10 +++++-----
 .../testing/selftests/kvm/include/arm64/processor.h | 13 +++++++++++++
 tools/testing/selftests/kvm/steal_time.c            |  2 +-
 5 files changed, 21 insertions(+), 8 deletions(-)

diff --git a/tools/testing/selftests/kvm/arm64/hypercalls.c b/tools/testing/selftests/kvm/arm64/hypercalls.c
index 44cfcf8a7f46..bf038a0371f4 100644
--- a/tools/testing/selftests/kvm/arm64/hypercalls.c
+++ b/tools/testing/selftests/kvm/arm64/hypercalls.c
@@ -108,7 +108,7 @@ static void guest_test_hvc(const struct test_hvc_info *hc_info)
 
 	for (i = 0; i < hvc_info_arr_sz; i++, hc_info++) {
 		memset(&res, 0, sizeof(res));
-		smccc_hvc(hc_info->func_id, hc_info->arg1, 0, 0, 0, 0, 0, 0, &res);
+		do_smccc(hc_info->func_id, hc_info->arg1, 0, 0, 0, 0, 0, 0, &res);
 
 		switch (stage) {
 		case TEST_STAGE_HVC_IFACE_FEAT_DISABLED:
diff --git a/tools/testing/selftests/kvm/arm64/kvm-uuid.c b/tools/testing/selftests/kvm/arm64/kvm-uuid.c
index af9581b860f1..b5be9133535a 100644
--- a/tools/testing/selftests/kvm/arm64/kvm-uuid.c
+++ b/tools/testing/selftests/kvm/arm64/kvm-uuid.c
@@ -25,7 +25,7 @@ static void guest_code(void)
 {
 	struct arm_smccc_res res = {};
 
-	smccc_hvc(ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID, 0, 0, 0, 0, 0, 0, 0, &res);
+	do_smccc(ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID, 0, 0, 0, 0, 0, 0, 0, &res);
 
 	__GUEST_ASSERT(res.a0 == ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_0 &&
 		       res.a1 == ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_1 &&
diff --git a/tools/testing/selftests/kvm/arm64/psci_test.c b/tools/testing/selftests/kvm/arm64/psci_test.c
index 0d4680da66d1..98e49f710aef 100644
--- a/tools/testing/selftests/kvm/arm64/psci_test.c
+++ b/tools/testing/selftests/kvm/arm64/psci_test.c
@@ -27,7 +27,7 @@ static uint64_t psci_cpu_on(uint64_t target_cpu, uint64_t entry_addr,
 {
 	struct arm_smccc_res res;
 
-	smccc_hvc(PSCI_0_2_FN64_CPU_ON, target_cpu, entry_addr, context_id,
+	do_smccc(PSCI_0_2_FN64_CPU_ON, target_cpu, entry_addr, context_id,
 		  0, 0, 0, 0, &res);
 
 	return res.a0;
@@ -38,7 +38,7 @@ static uint64_t psci_affinity_info(uint64_t target_affinity,
 {
 	struct arm_smccc_res res;
 
-	smccc_hvc(PSCI_0_2_FN64_AFFINITY_INFO, target_affinity, lowest_affinity_level,
+	do_smccc(PSCI_0_2_FN64_AFFINITY_INFO, target_affinity, lowest_affinity_level,
 		  0, 0, 0, 0, 0, &res);
 
 	return res.a0;
@@ -48,7 +48,7 @@ static uint64_t psci_system_suspend(uint64_t entry_addr, uint64_t context_id)
 {
 	struct arm_smccc_res res;
 
-	smccc_hvc(PSCI_1_0_FN64_SYSTEM_SUSPEND, entry_addr, context_id,
+	do_smccc(PSCI_1_0_FN64_SYSTEM_SUSPEND, entry_addr, context_id,
 		  0, 0, 0, 0, 0, &res);
 
 	return res.a0;
@@ -58,7 +58,7 @@ static uint64_t psci_system_off2(uint64_t type, uint64_t cookie)
 {
 	struct arm_smccc_res res;
 
-	smccc_hvc(PSCI_1_3_FN64_SYSTEM_OFF2, type, cookie, 0, 0, 0, 0, 0, &res);
+	do_smccc(PSCI_1_3_FN64_SYSTEM_OFF2, type, cookie, 0, 0, 0, 0, 0, &res);
 
 	return res.a0;
 }
@@ -67,7 +67,7 @@ static uint64_t psci_features(uint32_t func_id)
 {
 	struct arm_smccc_res res;
 
-	smccc_hvc(PSCI_1_0_FN_PSCI_FEATURES, func_id, 0, 0, 0, 0, 0, 0, &res);
+	do_smccc(PSCI_1_0_FN_PSCI_FEATURES, func_id, 0, 0, 0, 0, 0, 0, &res);
 
 	return res.a0;
 }
diff --git a/tools/testing/selftests/kvm/include/arm64/processor.h b/tools/testing/selftests/kvm/include/arm64/processor.h
index 87f50efed720..f037c1bb8e63 100644
--- a/tools/testing/selftests/kvm/include/arm64/processor.h
+++ b/tools/testing/selftests/kvm/include/arm64/processor.h
@@ -359,4 +359,17 @@ static __always_inline u64 ctxt_reg_alias(struct kvm_vcpu *vcpu, u32 encoding)
 
 void kvm_get_default_vcpu_target(struct kvm_vm *vm, struct kvm_vcpu_init *init);
 
+static inline unsigned int get_current_el(void)
+{
+	return (read_sysreg(CurrentEL) >> 2) & 0x3;
+}
+
+#define do_smccc(...)				\
+do {						\
+	if (get_current_el() == 2)		\
+		smccc_smc(__VA_ARGS__);		\
+	else					\
+		smccc_hvc(__VA_ARGS__);		\
+} while (0)
+
 #endif /* SELFTEST_KVM_PROCESSOR_H */
diff --git a/tools/testing/selftests/kvm/steal_time.c b/tools/testing/selftests/kvm/steal_time.c
index cce2520af720..8edc1fca345b 100644
--- a/tools/testing/selftests/kvm/steal_time.c
+++ b/tools/testing/selftests/kvm/steal_time.c
@@ -118,7 +118,7 @@ static int64_t smccc(uint32_t func, uint64_t arg)
 {
 	struct arm_smccc_res res;
 
-	smccc_hvc(func, arg, 0, 0, 0, 0, 0, 0, &res);
+	do_smccc(func, arg, 0, 0, 0, 0, 0, 0, &res);
 	return res.a0;
 }
 
-- 
2.47.3



^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 09/13] KVM: arm64: selftests: Use hyp timer IRQs when test runs at EL2
  2025-09-17 21:20 [PATCH 00/13] KVM: arm64: selftests: Run selftests in VHE EL2 Oliver Upton
                   ` (7 preceding siblings ...)
  2025-09-17 21:20 ` [PATCH 08/13] KVM: arm64: selftests: Select SMCCC conduit based on current EL Oliver Upton
@ 2025-09-17 21:20 ` Oliver Upton
  2025-09-17 21:20 ` [PATCH 10/13] KVM: arm64: selftests: Use the vCPU attr for setting nr of PMU counters Oliver Upton
                   ` (4 subsequent siblings)
  13 siblings, 0 replies; 20+ messages in thread
From: Oliver Upton @ 2025-09-17 21:20 UTC (permalink / raw)
  To: kvmarm
  Cc: Marc Zyngier, Joey Gouly, Suzuki K Poulose, Zenghui Yu,
	Paolo Bonzini, Sean Christopherson, Christian Borntraeger,
	Janosch Frank, Claudio Imbrenda, David Hildenbrand,
	linux-arm-kernel, kvm, Oliver Upton

Arch timer registers are redirected to their hypervisor counterparts
when running in VHE EL2. This is great, except for the fact that the
hypervisor timers use different PPIs. Use the correct INTIDs when that
is the case.

Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
---
 .../testing/selftests/kvm/arm64/arch_timer.c  |  6 ++---
 .../kvm/arm64/arch_timer_edge_cases.c         |  6 ++---
 .../selftests/kvm/include/arm64/arch_timer.h  | 24 +++++++++++++++++++
 3 files changed, 28 insertions(+), 8 deletions(-)

diff --git a/tools/testing/selftests/kvm/arm64/arch_timer.c b/tools/testing/selftests/kvm/arm64/arch_timer.c
index c753013319bc..d592a4515399 100644
--- a/tools/testing/selftests/kvm/arm64/arch_timer.c
+++ b/tools/testing/selftests/kvm/arm64/arch_timer.c
@@ -165,10 +165,8 @@ static void guest_code(void)
 static void test_init_timer_irq(struct kvm_vm *vm)
 {
 	/* Timer initid should be same for all the vCPUs, so query only vCPU-0 */
-	vcpu_device_attr_get(vcpus[0], KVM_ARM_VCPU_TIMER_CTRL,
-			     KVM_ARM_VCPU_TIMER_IRQ_PTIMER, &ptimer_irq);
-	vcpu_device_attr_get(vcpus[0], KVM_ARM_VCPU_TIMER_CTRL,
-			     KVM_ARM_VCPU_TIMER_IRQ_VTIMER, &vtimer_irq);
+	ptimer_irq = vcpu_get_ptimer_irq(vcpus[0]);
+	vtimer_irq = vcpu_get_vtimer_irq(vcpus[0]);
 
 	sync_global_to_guest(vm, ptimer_irq);
 	sync_global_to_guest(vm, vtimer_irq);
diff --git a/tools/testing/selftests/kvm/arm64/arch_timer_edge_cases.c b/tools/testing/selftests/kvm/arm64/arch_timer_edge_cases.c
index 5c60262f4c2e..91906414a474 100644
--- a/tools/testing/selftests/kvm/arm64/arch_timer_edge_cases.c
+++ b/tools/testing/selftests/kvm/arm64/arch_timer_edge_cases.c
@@ -924,10 +924,8 @@ static void test_run(struct kvm_vm *vm, struct kvm_vcpu *vcpu)
 
 static void test_init_timer_irq(struct kvm_vm *vm, struct kvm_vcpu *vcpu)
 {
-	vcpu_device_attr_get(vcpu, KVM_ARM_VCPU_TIMER_CTRL,
-			     KVM_ARM_VCPU_TIMER_IRQ_PTIMER, &ptimer_irq);
-	vcpu_device_attr_get(vcpu, KVM_ARM_VCPU_TIMER_CTRL,
-			     KVM_ARM_VCPU_TIMER_IRQ_VTIMER, &vtimer_irq);
+	ptimer_irq = vcpu_get_ptimer_irq(vcpu);
+	vtimer_irq = vcpu_get_vtimer_irq(vcpu);
 
 	sync_global_to_guest(vm, ptimer_irq);
 	sync_global_to_guest(vm, vtimer_irq);
diff --git a/tools/testing/selftests/kvm/include/arm64/arch_timer.h b/tools/testing/selftests/kvm/include/arm64/arch_timer.h
index bf461de34785..e2c4e9f0010f 100644
--- a/tools/testing/selftests/kvm/include/arm64/arch_timer.h
+++ b/tools/testing/selftests/kvm/include/arm64/arch_timer.h
@@ -155,4 +155,28 @@ static inline void timer_set_next_tval_ms(enum arch_timer timer, uint32_t msec)
 	timer_set_tval(timer, msec_to_cycles(msec));
 }
 
+static inline u32 vcpu_get_vtimer_irq(struct kvm_vcpu *vcpu)
+{
+	u32 intid;
+	u64 attr;
+
+	attr = vcpu_has_el2(vcpu) ? KVM_ARM_VCPU_TIMER_IRQ_HVTIMER :
+				    KVM_ARM_VCPU_TIMER_IRQ_VTIMER;
+	vcpu_device_attr_get(vcpu, KVM_ARM_VCPU_TIMER_CTRL, attr, &intid);
+
+	return intid;
+}
+
+static inline u32 vcpu_get_ptimer_irq(struct kvm_vcpu *vcpu)
+{
+	u32 intid;
+	u64 attr;
+
+	attr = vcpu_has_el2(vcpu) ? KVM_ARM_VCPU_TIMER_IRQ_HPTIMER :
+				    KVM_ARM_VCPU_TIMER_IRQ_PTIMER;
+	vcpu_device_attr_get(vcpu, KVM_ARM_VCPU_TIMER_CTRL, attr, &intid);
+
+	return intid;
+}
+
 #endif /* SELFTEST_KVM_ARCH_TIMER_H */
-- 
2.47.3



^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 10/13] KVM: arm64: selftests: Use the vCPU attr for setting nr of PMU counters
  2025-09-17 21:20 [PATCH 00/13] KVM: arm64: selftests: Run selftests in VHE EL2 Oliver Upton
                   ` (8 preceding siblings ...)
  2025-09-17 21:20 ` [PATCH 09/13] KVM: arm64: selftests: Use hyp timer IRQs when test runs at EL2 Oliver Upton
@ 2025-09-17 21:20 ` Oliver Upton
  2025-09-17 21:20 ` [PATCH 11/13] KVM: arm64: selftests: Initialize HCR_EL2 Oliver Upton
                   ` (3 subsequent siblings)
  13 siblings, 0 replies; 20+ messages in thread
From: Oliver Upton @ 2025-09-17 21:20 UTC (permalink / raw)
  To: kvmarm
  Cc: Marc Zyngier, Joey Gouly, Suzuki K Poulose, Zenghui Yu,
	Paolo Bonzini, Sean Christopherson, Christian Borntraeger,
	Janosch Frank, Claudio Imbrenda, David Hildenbrand,
	linux-arm-kernel, kvm, Oliver Upton

Configuring the number of implemented counters via PMCR_EL0.N was a bad
idea in retrospect as it interacts poorly with nested. Migrate the
selftest to use the vCPU attribute instead of the KVM_SET_ONE_REG
mechanism.

Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
---
 .../selftests/kvm/arm64/vpmu_counter_access.c | 59 +++++++++----------
 1 file changed, 28 insertions(+), 31 deletions(-)

diff --git a/tools/testing/selftests/kvm/arm64/vpmu_counter_access.c b/tools/testing/selftests/kvm/arm64/vpmu_counter_access.c
index 2a8f31c8e59f..ae36325c022f 100644
--- a/tools/testing/selftests/kvm/arm64/vpmu_counter_access.c
+++ b/tools/testing/selftests/kvm/arm64/vpmu_counter_access.c
@@ -44,11 +44,6 @@ static uint64_t get_pmcr_n(uint64_t pmcr)
 	return FIELD_GET(ARMV8_PMU_PMCR_N, pmcr);
 }
 
-static void set_pmcr_n(uint64_t *pmcr, uint64_t pmcr_n)
-{
-	u64p_replace_bits((__u64 *) pmcr, pmcr_n, ARMV8_PMU_PMCR_N);
-}
-
 static uint64_t get_counters_mask(uint64_t n)
 {
 	uint64_t mask = BIT(ARMV8_PMU_CYCLE_IDX);
@@ -414,10 +409,6 @@ static void create_vpmu_vm(void *guest_code)
 		.attr = KVM_ARM_VCPU_PMU_V3_IRQ,
 		.addr = (uint64_t)&irq,
 	};
-	struct kvm_device_attr init_attr = {
-		.group = KVM_ARM_VCPU_PMU_V3_CTRL,
-		.attr = KVM_ARM_VCPU_PMU_V3_INIT,
-	};
 
 	/* The test creates the vpmu_vm multiple times. Ensure a clean state */
 	memset(&vpmu_vm, 0, sizeof(vpmu_vm));
@@ -444,9 +435,7 @@ static void create_vpmu_vm(void *guest_code)
 		    pmuver >= ID_AA64DFR0_EL1_PMUVer_IMP,
 		    "Unexpected PMUVER (0x%x) on the vCPU with PMUv3", pmuver);
 
-	/* Initialize vPMU */
 	vcpu_ioctl(vpmu_vm.vcpu, KVM_SET_DEVICE_ATTR, &irq_attr);
-	vcpu_ioctl(vpmu_vm.vcpu, KVM_SET_DEVICE_ATTR, &init_attr);
 }
 
 static void destroy_vpmu_vm(void)
@@ -472,33 +461,28 @@ static void run_vcpu(struct kvm_vcpu *vcpu, uint64_t pmcr_n)
 	}
 }
 
-static void test_create_vpmu_vm_with_pmcr_n(uint64_t pmcr_n, bool expect_fail)
+static void test_create_vpmu_vm_with_nr_counters(unsigned int nr_counters, bool expect_fail)
 {
 	struct kvm_vcpu *vcpu;
-	uint64_t pmcr, pmcr_orig;
+	unsigned int prev;
+	int ret;
 
 	create_vpmu_vm(guest_code);
 	vcpu = vpmu_vm.vcpu;
 
-	pmcr_orig = vcpu_get_reg(vcpu, KVM_ARM64_SYS_REG(SYS_PMCR_EL0));
-	pmcr = pmcr_orig;
+	prev = get_pmcr_n(vcpu_get_reg(vcpu, KVM_ARM64_SYS_REG(SYS_PMCR_EL0)));
 
-	/*
-	 * Setting a larger value of PMCR.N should not modify the field, and
-	 * return a success.
-	 */
-	set_pmcr_n(&pmcr, pmcr_n);
-	vcpu_set_reg(vcpu, KVM_ARM64_SYS_REG(SYS_PMCR_EL0), pmcr);
-	pmcr = vcpu_get_reg(vcpu, KVM_ARM64_SYS_REG(SYS_PMCR_EL0));
+	ret = __vcpu_device_attr_set(vcpu, KVM_ARM_VCPU_PMU_V3_CTRL,
+				     KVM_ARM_VCPU_PMU_V3_SET_NR_COUNTERS, &nr_counters);
 
 	if (expect_fail)
-		TEST_ASSERT(pmcr_orig == pmcr,
-			    "PMCR.N modified by KVM to a larger value (PMCR: 0x%lx) for pmcr_n: 0x%lx",
-			    pmcr, pmcr_n);
+		TEST_ASSERT(ret && errno == EINVAL,
+			    "Setting more PMU counters (%u) than available (%u) unexpectedly succeeded",
+			    nr_counters, prev);
 	else
-		TEST_ASSERT(pmcr_n == get_pmcr_n(pmcr),
-			    "Failed to update PMCR.N to %lu (received: %lu)",
-			    pmcr_n, get_pmcr_n(pmcr));
+		TEST_ASSERT(!ret, KVM_IOCTL_ERROR(KVM_SET_DEVICE_ATTR, ret));
+
+	vcpu_device_attr_set(vcpu, KVM_ARM_VCPU_PMU_V3_CTRL, KVM_ARM_VCPU_PMU_V3_INIT, NULL);
 }
 
 /*
@@ -513,7 +497,7 @@ static void run_access_test(uint64_t pmcr_n)
 
 	pr_debug("Test with pmcr_n %lu\n", pmcr_n);
 
-	test_create_vpmu_vm_with_pmcr_n(pmcr_n, false);
+	test_create_vpmu_vm_with_nr_counters(pmcr_n, false);
 	vcpu = vpmu_vm.vcpu;
 
 	/* Save the initial sp to restore them later to run the guest again */
@@ -554,7 +538,7 @@ static void run_pmregs_validity_test(uint64_t pmcr_n)
 	uint64_t set_reg_id, clr_reg_id, reg_val;
 	uint64_t valid_counters_mask, max_counters_mask;
 
-	test_create_vpmu_vm_with_pmcr_n(pmcr_n, false);
+	test_create_vpmu_vm_with_nr_counters(pmcr_n, false);
 	vcpu = vpmu_vm.vcpu;
 
 	valid_counters_mask = get_counters_mask(pmcr_n);
@@ -608,7 +592,7 @@ static void run_error_test(uint64_t pmcr_n)
 {
 	pr_debug("Error test with pmcr_n %lu (larger than the host)\n", pmcr_n);
 
-	test_create_vpmu_vm_with_pmcr_n(pmcr_n, true);
+	test_create_vpmu_vm_with_nr_counters(pmcr_n, true);
 	destroy_vpmu_vm();
 }
 
@@ -626,12 +610,25 @@ static uint64_t get_pmcr_n_limit(void)
 	return get_pmcr_n(pmcr);
 }
 
+static bool kvm_supports_nr_counters_attr(void)
+{
+	bool supported;
+
+	create_vpmu_vm(NULL);
+	supported = !__vcpu_has_device_attr(vpmu_vm.vcpu, KVM_ARM_VCPU_PMU_V3_CTRL,
+					    KVM_ARM_VCPU_PMU_V3_SET_NR_COUNTERS);
+	destroy_vpmu_vm();
+
+	return supported;
+}
+
 int main(void)
 {
 	uint64_t i, pmcr_n;
 
 	TEST_REQUIRE(kvm_has_cap(KVM_CAP_ARM_PMU_V3));
 	TEST_REQUIRE(kvm_supports_vgic_v3());
+	TEST_REQUIRE(kvm_supports_nr_counters_attr());
 
 	pmcr_n = get_pmcr_n_limit();
 	for (i = 0; i <= pmcr_n; i++) {
-- 
2.47.3



^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 11/13] KVM: arm64: selftests: Initialize HCR_EL2
  2025-09-17 21:20 [PATCH 00/13] KVM: arm64: selftests: Run selftests in VHE EL2 Oliver Upton
                   ` (9 preceding siblings ...)
  2025-09-17 21:20 ` [PATCH 10/13] KVM: arm64: selftests: Use the vCPU attr for setting nr of PMU counters Oliver Upton
@ 2025-09-17 21:20 ` Oliver Upton
  2025-09-17 21:20 ` [PATCH 12/13] KVM: arm64: selftests: Enable EL2 by default Oliver Upton
                   ` (2 subsequent siblings)
  13 siblings, 0 replies; 20+ messages in thread
From: Oliver Upton @ 2025-09-17 21:20 UTC (permalink / raw)
  To: kvmarm
  Cc: Marc Zyngier, Joey Gouly, Suzuki K Poulose, Zenghui Yu,
	Paolo Bonzini, Sean Christopherson, Christian Borntraeger,
	Janosch Frank, Claudio Imbrenda, David Hildenbrand,
	linux-arm-kernel, kvm, Oliver Upton

Initialize HCR_EL2 such that EL2&0 is considered 'InHost', allowing the
use of (mostly) unmodified EL1 selftests at EL2.

Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
---
 tools/testing/selftests/kvm/lib/arm64/processor.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/tools/testing/selftests/kvm/lib/arm64/processor.c b/tools/testing/selftests/kvm/lib/arm64/processor.c
index 5ae65fefd48c..4339de2fc482 100644
--- a/tools/testing/selftests/kvm/lib/arm64/processor.c
+++ b/tools/testing/selftests/kvm/lib/arm64/processor.c
@@ -369,6 +369,12 @@ void aarch64_vcpu_setup(struct kvm_vcpu *vcpu, struct kvm_vcpu_init *init)
 	vcpu_set_reg(vcpu, ctxt_reg_alias(vcpu, SYS_MAIR_EL1), DEFAULT_MAIR_EL1);
 	vcpu_set_reg(vcpu, ctxt_reg_alias(vcpu, SYS_TTBR0_EL1), ttbr0_el1);
 	vcpu_set_reg(vcpu, KVM_ARM64_SYS_REG(SYS_TPIDR_EL1), vcpu->id);
+
+	if (!vcpu_has_el2(vcpu))
+		return;
+
+	vcpu_set_reg(vcpu, KVM_ARM64_SYS_REG(SYS_HCR_EL2),
+		     HCR_EL2_RW | HCR_EL2_TGE | HCR_EL2_E2H);
 }
 
 void vcpu_arch_dump(FILE *stream, struct kvm_vcpu *vcpu, uint8_t indent)
-- 
2.47.3



^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 12/13] KVM: arm64: selftests: Enable EL2 by default
  2025-09-17 21:20 [PATCH 00/13] KVM: arm64: selftests: Run selftests in VHE EL2 Oliver Upton
                   ` (10 preceding siblings ...)
  2025-09-17 21:20 ` [PATCH 11/13] KVM: arm64: selftests: Initialize HCR_EL2 Oliver Upton
@ 2025-09-17 21:20 ` Oliver Upton
  2025-09-17 21:20 ` [PATCH 13/13] KVM: arm64: selftests: Add basic test for running in VHE EL2 Oliver Upton
  2025-09-24 18:37 ` [PATCH 00/13] KVM: arm64: selftests: Run selftests " Marc Zyngier
  13 siblings, 0 replies; 20+ messages in thread
From: Oliver Upton @ 2025-09-17 21:20 UTC (permalink / raw)
  To: kvmarm
  Cc: Marc Zyngier, Joey Gouly, Suzuki K Poulose, Zenghui Yu,
	Paolo Bonzini, Sean Christopherson, Christian Borntraeger,
	Janosch Frank, Claudio Imbrenda, David Hildenbrand,
	linux-arm-kernel, kvm, Oliver Upton

Take advantage of VHE to implicitly promote KVM selftests to run at EL2
with only slight modification. Update the smccc_filter test to account
for this now that the EL2-ness of a VM is visible to tests.

Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
---
 tools/testing/selftests/kvm/arm64/smccc_filter.c   | 14 +++++++++++++-
 .../selftests/kvm/include/arm64/processor.h        |  1 +
 tools/testing/selftests/kvm/lib/arm64/processor.c  | 12 ++++++++++++
 3 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/tools/testing/selftests/kvm/arm64/smccc_filter.c b/tools/testing/selftests/kvm/arm64/smccc_filter.c
index a8e22d866ea7..1763b9d45400 100644
--- a/tools/testing/selftests/kvm/arm64/smccc_filter.c
+++ b/tools/testing/selftests/kvm/arm64/smccc_filter.c
@@ -22,8 +22,20 @@ enum smccc_conduit {
 	SMC_INSN,
 };
 
+static bool test_runs_at_el2(void)
+{
+	struct kvm_vm *vm = vm_create(1);
+	struct kvm_vcpu_init init;
+
+	kvm_get_default_vcpu_target(vm, &init);
+	kvm_vm_free(vm);
+
+	return init.features[0] & BIT(KVM_ARM_VCPU_HAS_EL2);
+}
+
 #define for_each_conduit(conduit)					\
-	for (conduit = HVC_INSN; conduit <= SMC_INSN; conduit++)
+	for (conduit = test_runs_at_el2() ? SMC_INSN : HVC_INSN;	\
+	     conduit <= SMC_INSN; conduit++)
 
 static void guest_main(uint32_t func_id, enum smccc_conduit conduit)
 {
diff --git a/tools/testing/selftests/kvm/include/arm64/processor.h b/tools/testing/selftests/kvm/include/arm64/processor.h
index f037c1bb8e63..b6b86e2cd59c 100644
--- a/tools/testing/selftests/kvm/include/arm64/processor.h
+++ b/tools/testing/selftests/kvm/include/arm64/processor.h
@@ -303,6 +303,7 @@ void wfi(void);
 void test_wants_mte(void);
 void test_disable_default_vgic(void);
 
+bool vm_supports_el2(struct kvm_vm *vm);
 static bool vcpu_has_el2(struct kvm_vcpu *vcpu)
 {
 	return vcpu->init.features[0] & BIT(KVM_ARM_VCPU_HAS_EL2);
diff --git a/tools/testing/selftests/kvm/lib/arm64/processor.c b/tools/testing/selftests/kvm/lib/arm64/processor.c
index 4339de2fc482..74324915b41e 100644
--- a/tools/testing/selftests/kvm/lib/arm64/processor.c
+++ b/tools/testing/selftests/kvm/lib/arm64/processor.c
@@ -267,11 +267,23 @@ void virt_arch_dump(FILE *stream, struct kvm_vm *vm, uint8_t indent)
 	}
 }
 
+bool vm_supports_el2(struct kvm_vm *vm)
+{
+	const char *value = getenv("NV");
+
+	if (value && *value == '0')
+		return false;
+
+	return vm_check_cap(vm, KVM_CAP_ARM_EL2) && vm->arch.has_gic;
+}
+
 void kvm_get_default_vcpu_target(struct kvm_vm *vm, struct kvm_vcpu_init *init)
 {
 	struct kvm_vcpu_init preferred = {};
 
 	vm_ioctl(vm, KVM_ARM_PREFERRED_TARGET, &preferred);
+	if (vm_supports_el2(vm))
+		preferred.features[0] |= BIT(KVM_ARM_VCPU_HAS_EL2);
 
 	*init = preferred;
 }
-- 
2.47.3



^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 13/13] KVM: arm64: selftests: Add basic test for running in VHE EL2
  2025-09-17 21:20 [PATCH 00/13] KVM: arm64: selftests: Run selftests in VHE EL2 Oliver Upton
                   ` (11 preceding siblings ...)
  2025-09-17 21:20 ` [PATCH 12/13] KVM: arm64: selftests: Enable EL2 by default Oliver Upton
@ 2025-09-17 21:20 ` Oliver Upton
  2025-09-24 18:37 ` [PATCH 00/13] KVM: arm64: selftests: Run selftests " Marc Zyngier
  13 siblings, 0 replies; 20+ messages in thread
From: Oliver Upton @ 2025-09-17 21:20 UTC (permalink / raw)
  To: kvmarm
  Cc: Marc Zyngier, Joey Gouly, Suzuki K Poulose, Zenghui Yu,
	Paolo Bonzini, Sean Christopherson, Christian Borntraeger,
	Janosch Frank, Claudio Imbrenda, David Hildenbrand,
	linux-arm-kernel, kvm, Oliver Upton

Add an embarrassingly simple selftest for sanity checking KVM's VHE EL2
and test that the ID register bits are consistent with HCR_EL2.E2H being
RES1.

Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
---
 tools/testing/selftests/kvm/Makefile.kvm      |  1 +
 tools/testing/selftests/kvm/arm64/hello_el2.c | 58 +++++++++++++++++++
 2 files changed, 59 insertions(+)
 create mode 100644 tools/testing/selftests/kvm/arm64/hello_el2.c

diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selftests/kvm/Makefile.kvm
index 41b40c676d7f..5d59267d4089 100644
--- a/tools/testing/selftests/kvm/Makefile.kvm
+++ b/tools/testing/selftests/kvm/Makefile.kvm
@@ -156,6 +156,7 @@ TEST_GEN_PROGS_arm64 = $(TEST_GEN_PROGS_COMMON)
 TEST_GEN_PROGS_arm64 += arm64/aarch32_id_regs
 TEST_GEN_PROGS_arm64 += arm64/arch_timer_edge_cases
 TEST_GEN_PROGS_arm64 += arm64/debug-exceptions
+TEST_GEN_PROGS_arm64 += arm64/hello_el2
 TEST_GEN_PROGS_arm64 += arm64/host_sve
 TEST_GEN_PROGS_arm64 += arm64/hypercalls
 TEST_GEN_PROGS_arm64 += arm64/external_aborts
diff --git a/tools/testing/selftests/kvm/arm64/hello_el2.c b/tools/testing/selftests/kvm/arm64/hello_el2.c
new file mode 100644
index 000000000000..3c1f44e43f65
--- /dev/null
+++ b/tools/testing/selftests/kvm/arm64/hello_el2.c
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * hello_el2 - Basic KVM selftest for VM running at EL2 with E2H=RES1
+ *
+ * Copyright 2025 Google LLC
+ */
+#include "kvm_util.h"
+#include "processor.h"
+#include "test_util.h"
+#include "ucall.h"
+
+#include <asm/sysreg.h>
+
+static void guest_code(void)
+{
+	u64 mmfr1 = read_sysreg_s(SYS_ID_AA64MMFR1_EL1);
+	u64 mmfr4 = read_sysreg_s(SYS_ID_AA64MMFR4_EL1);
+
+	GUEST_ASSERT_EQ(get_current_el(), 2);
+	GUEST_ASSERT(read_sysreg(hcr_el2) & HCR_EL2_E2H);
+	GUEST_ASSERT_EQ(SYS_FIELD_GET(ID_AA64MMFR1_EL1, VH, mmfr1),
+			ID_AA64MMFR1_EL1_VH_IMP);
+	GUEST_ASSERT_EQ(SYS_FIELD_GET(ID_AA64MMFR4_EL1, E2H0, mmfr4),
+			ID_AA64MMFR4_EL1_E2H0_NI_NV1);
+
+	GUEST_DONE();
+}
+
+int main(void)
+{
+	struct kvm_vcpu_init init;
+	struct kvm_vcpu *vcpu;
+	struct kvm_vm *vm;
+	struct ucall uc;
+
+	TEST_REQUIRE(kvm_check_cap(KVM_CAP_ARM_EL2));
+
+	vm = vm_create(1);
+
+	kvm_get_default_vcpu_target(vm, &init);
+	init.features[0] |= BIT(KVM_ARM_VCPU_HAS_EL2);
+	vcpu = aarch64_vcpu_add(vm, 0, &init, guest_code);
+	kvm_arch_vm_finalize_vcpus(vm);
+
+	vcpu_run(vcpu);
+	switch (get_ucall(vcpu, &uc)) {
+	case UCALL_DONE:
+		break;
+	case UCALL_ABORT:
+		REPORT_GUEST_ASSERT(uc);
+		break;
+	default:
+		TEST_FAIL("Unhandled ucall: %ld\n", uc.cmd);
+	}
+
+	kvm_vm_free(vm);
+	return 0;
+}
-- 
2.47.3



^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [PATCH 07/13] KVM: arm64: selftests: Provide helper for getting default vCPU target
  2025-09-17 21:20 ` [PATCH 07/13] KVM: arm64: selftests: Provide helper for getting default vCPU target Oliver Upton
@ 2025-09-17 21:56   ` Itaru Kitayama
  2025-09-17 22:00     ` Oliver Upton
  0 siblings, 1 reply; 20+ messages in thread
From: Itaru Kitayama @ 2025-09-17 21:56 UTC (permalink / raw)
  To: Oliver Upton
  Cc: kvmarm, Marc Zyngier, Joey Gouly, Suzuki K Poulose, Zenghui Yu,
	Paolo Bonzini, Sean Christopherson, Christian Borntraeger,
	Janosch Frank, Claudio Imbrenda, David Hildenbrand,
	linux-arm-kernel, kvm

On Wed, Sep 17, 2025 at 02:20:37PM -0700, Oliver Upton wrote:
> The default vCPU target in KVM selftests is pretty boring in that it
> doesn't enable any vCPU features. Expose a helper for getting the
> default target to prepare for cramming in more features. Call
> KVM_ARM_PREFERRED_TARGET directly from get-reg-list as it needs
> fine-grained control over feature flags.
> 
> Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
> ---
>  tools/testing/selftests/kvm/arm64/psci_test.c   |  2 +-
>  .../testing/selftests/kvm/arm64/smccc_filter.c  |  2 +-
>  .../selftests/kvm/arm64/vpmu_counter_access.c   |  4 ++--
>  tools/testing/selftests/kvm/get-reg-list.c      |  9 ++++++---
>  .../selftests/kvm/include/arm64/processor.h     |  2 ++
>  .../testing/selftests/kvm/lib/arm64/processor.c | 17 +++++++++++------
>  6 files changed, 23 insertions(+), 13 deletions(-)
> 
> diff --git a/tools/testing/selftests/kvm/arm64/psci_test.c b/tools/testing/selftests/kvm/arm64/psci_test.c
> index cf208390fd0e..0d4680da66d1 100644
> --- a/tools/testing/selftests/kvm/arm64/psci_test.c
> +++ b/tools/testing/selftests/kvm/arm64/psci_test.c
> @@ -89,7 +89,7 @@ static struct kvm_vm *setup_vm(void *guest_code, struct kvm_vcpu **source,
>  
>  	vm = vm_create(2);
>  
> -	vm_ioctl(vm, KVM_ARM_PREFERRED_TARGET, &init);
> +	kvm_get_default_vcpu_target(vm, &init);
>  	init.features[0] |= (1 << KVM_ARM_VCPU_PSCI_0_2);
>  
>  	*source = aarch64_vcpu_add(vm, 0, &init, guest_code);

I wonder if the ioctl() can be called unconditionally in the 
aarch64_vcpu_add() function. If the intention is that the kvm selftest
code needs to write this way I am fine with that.

Reviewed-by: Itaru Kitayama <itaru.kitayama@fujitsu.com>

> diff --git a/tools/testing/selftests/kvm/arm64/smccc_filter.c b/tools/testing/selftests/kvm/arm64/smccc_filter.c
> index eb5551d21dbe..a8e22d866ea7 100644
> --- a/tools/testing/selftests/kvm/arm64/smccc_filter.c
> +++ b/tools/testing/selftests/kvm/arm64/smccc_filter.c
> @@ -64,7 +64,7 @@ static struct kvm_vm *setup_vm(struct kvm_vcpu **vcpu)
>  	struct kvm_vm *vm;
>  
>  	vm = vm_create(1);
> -	vm_ioctl(vm, KVM_ARM_PREFERRED_TARGET, &init);
> +	kvm_get_default_vcpu_target(vm, &init);
>  
>  	/*
>  	 * Enable in-kernel emulation of PSCI to ensure that calls are denied
> diff --git a/tools/testing/selftests/kvm/arm64/vpmu_counter_access.c b/tools/testing/selftests/kvm/arm64/vpmu_counter_access.c
> index 36a3a8b4e0b5..2a8f31c8e59f 100644
> --- a/tools/testing/selftests/kvm/arm64/vpmu_counter_access.c
> +++ b/tools/testing/selftests/kvm/arm64/vpmu_counter_access.c
> @@ -430,7 +430,7 @@ static void create_vpmu_vm(void *guest_code)
>  	}
>  
>  	/* Create vCPU with PMUv3 */
> -	vm_ioctl(vpmu_vm.vm, KVM_ARM_PREFERRED_TARGET, &init);
> +	kvm_get_default_vcpu_target(vpmu_vm.vm, &init);
>  	init.features[0] |= (1 << KVM_ARM_VCPU_PMU_V3);
>  	vpmu_vm.vcpu = aarch64_vcpu_add(vpmu_vm.vm, 0, &init, guest_code);
>  	vcpu_init_descriptor_tables(vpmu_vm.vcpu);
> @@ -525,7 +525,7 @@ static void run_access_test(uint64_t pmcr_n)
>  	 * Reset and re-initialize the vCPU, and run the guest code again to
>  	 * check if PMCR_EL0.N is preserved.
>  	 */
> -	vm_ioctl(vpmu_vm.vm, KVM_ARM_PREFERRED_TARGET, &init);
> +	kvm_get_default_vcpu_target(vpmu_vm.vm, &init);
>  	init.features[0] |= (1 << KVM_ARM_VCPU_PMU_V3);
>  	aarch64_vcpu_setup(vcpu, &init);
>  	vcpu_init_descriptor_tables(vcpu);
> diff --git a/tools/testing/selftests/kvm/get-reg-list.c b/tools/testing/selftests/kvm/get-reg-list.c
> index 91f05f78e824..f4644c9d2d3b 100644
> --- a/tools/testing/selftests/kvm/get-reg-list.c
> +++ b/tools/testing/selftests/kvm/get-reg-list.c
> @@ -116,10 +116,13 @@ void __weak finalize_vcpu(struct kvm_vcpu *vcpu, struct vcpu_reg_list *c)
>  }
>  
>  #ifdef __aarch64__
> -static void prepare_vcpu_init(struct vcpu_reg_list *c, struct kvm_vcpu_init *init)
> +static void prepare_vcpu_init(struct kvm_vm *vm, struct vcpu_reg_list *c,
> +			      struct kvm_vcpu_init *init)
>  {
>  	struct vcpu_reg_sublist *s;
>  
> +	vm_ioctl(vm, KVM_ARM_PREFERRED_TARGET, init);
> +
>  	for_each_sublist(c, s)
>  		if (s->capability)
>  			init->features[s->feature / 32] |= 1 << (s->feature % 32);
> @@ -127,10 +130,10 @@ static void prepare_vcpu_init(struct vcpu_reg_list *c, struct kvm_vcpu_init *ini
>  
>  static struct kvm_vcpu *vcpu_config_get_vcpu(struct vcpu_reg_list *c, struct kvm_vm *vm)
>  {
> -	struct kvm_vcpu_init init = { .target = -1, };
> +	struct kvm_vcpu_init init;
>  	struct kvm_vcpu *vcpu;
>  
> -	prepare_vcpu_init(c, &init);
> +	prepare_vcpu_init(vm, c, &init);
>  	vcpu = __vm_vcpu_add(vm, 0);
>  	aarch64_vcpu_setup(vcpu, &init);
>  
> diff --git a/tools/testing/selftests/kvm/include/arm64/processor.h b/tools/testing/selftests/kvm/include/arm64/processor.h
> index 5a4b29c1b965..87f50efed720 100644
> --- a/tools/testing/selftests/kvm/include/arm64/processor.h
> +++ b/tools/testing/selftests/kvm/include/arm64/processor.h
> @@ -357,4 +357,6 @@ static __always_inline u64 ctxt_reg_alias(struct kvm_vcpu *vcpu, u32 encoding)
>  	return KVM_ARM64_SYS_REG(alias);
>  }
>  
> +void kvm_get_default_vcpu_target(struct kvm_vm *vm, struct kvm_vcpu_init *init);
> +
>  #endif /* SELFTEST_KVM_PROCESSOR_H */
> diff --git a/tools/testing/selftests/kvm/lib/arm64/processor.c b/tools/testing/selftests/kvm/lib/arm64/processor.c
> index 311660a9f655..5ae65fefd48c 100644
> --- a/tools/testing/selftests/kvm/lib/arm64/processor.c
> +++ b/tools/testing/selftests/kvm/lib/arm64/processor.c
> @@ -267,19 +267,24 @@ void virt_arch_dump(FILE *stream, struct kvm_vm *vm, uint8_t indent)
>  	}
>  }
>  
> +void kvm_get_default_vcpu_target(struct kvm_vm *vm, struct kvm_vcpu_init *init)
> +{
> +	struct kvm_vcpu_init preferred = {};
> +
> +	vm_ioctl(vm, KVM_ARM_PREFERRED_TARGET, &preferred);
> +
> +	*init = preferred;
> +}
> +
>  void aarch64_vcpu_setup(struct kvm_vcpu *vcpu, struct kvm_vcpu_init *init)
>  {
>  	struct kvm_vcpu_init default_init = { .target = -1, };
>  	struct kvm_vm *vm = vcpu->vm;
>  	uint64_t sctlr_el1, tcr_el1, ttbr0_el1;
>  
> -	if (!init)
> +	if (!init) {
> +		kvm_get_default_vcpu_target(vm, &default_init);
>  		init = &default_init;
> -
> -	if (init->target == -1) {
> -		struct kvm_vcpu_init preferred;
> -		vm_ioctl(vm, KVM_ARM_PREFERRED_TARGET, &preferred);
> -		init->target = preferred.target;
>  	}
>  
>  	vcpu_ioctl(vcpu, KVM_ARM_VCPU_INIT, init);
> -- 
> 2.47.3
> 


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 07/13] KVM: arm64: selftests: Provide helper for getting default vCPU target
  2025-09-17 21:56   ` Itaru Kitayama
@ 2025-09-17 22:00     ` Oliver Upton
  0 siblings, 0 replies; 20+ messages in thread
From: Oliver Upton @ 2025-09-17 22:00 UTC (permalink / raw)
  To: Itaru Kitayama
  Cc: kvmarm, Marc Zyngier, Joey Gouly, Suzuki K Poulose, Zenghui Yu,
	Paolo Bonzini, Sean Christopherson, Christian Borntraeger,
	Janosch Frank, Claudio Imbrenda, David Hildenbrand,
	linux-arm-kernel, kvm

Hi Itaru,

Appreciate the review.

On Thu, Sep 18, 2025 at 06:56:27AM +0900, Itaru Kitayama wrote:
> On Wed, Sep 17, 2025 at 02:20:37PM -0700, Oliver Upton wrote:
> > The default vCPU target in KVM selftests is pretty boring in that it
> > doesn't enable any vCPU features. Expose a helper for getting the
> > default target to prepare for cramming in more features. Call
> > KVM_ARM_PREFERRED_TARGET directly from get-reg-list as it needs
> > fine-grained control over feature flags.
> > 
> > Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
> > ---
> >  tools/testing/selftests/kvm/arm64/psci_test.c   |  2 +-
> >  .../testing/selftests/kvm/arm64/smccc_filter.c  |  2 +-
> >  .../selftests/kvm/arm64/vpmu_counter_access.c   |  4 ++--
> >  tools/testing/selftests/kvm/get-reg-list.c      |  9 ++++++---
> >  .../selftests/kvm/include/arm64/processor.h     |  2 ++
> >  .../testing/selftests/kvm/lib/arm64/processor.c | 17 +++++++++++------
> >  6 files changed, 23 insertions(+), 13 deletions(-)
> > 
> > diff --git a/tools/testing/selftests/kvm/arm64/psci_test.c b/tools/testing/selftests/kvm/arm64/psci_test.c
> > index cf208390fd0e..0d4680da66d1 100644
> > --- a/tools/testing/selftests/kvm/arm64/psci_test.c
> > +++ b/tools/testing/selftests/kvm/arm64/psci_test.c
> > @@ -89,7 +89,7 @@ static struct kvm_vm *setup_vm(void *guest_code, struct kvm_vcpu **source,
> >  
> >  	vm = vm_create(2);
> >  
> > -	vm_ioctl(vm, KVM_ARM_PREFERRED_TARGET, &init);
> > +	kvm_get_default_vcpu_target(vm, &init);
> >  	init.features[0] |= (1 << KVM_ARM_VCPU_PSCI_0_2);
> >  
> >  	*source = aarch64_vcpu_add(vm, 0, &init, guest_code);
> 
> I wonder if the ioctl() can be called unconditionally in the 
> aarch64_vcpu_add() function. If the intention is that the kvm selftest
> code needs to write this way I am fine with that.

I had a similar thought but decided against it as tests may need
fine-grained control over the feature flags (like above). I would hope
that most users will use the 'default' VM infrastructure if they do not
need this sort of control.

> Reviewed-by: Itaru Kitayama <itaru.kitayama@fujitsu.com>

Thanks!

Best,
Oliver


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 01/13] KVM: arm64: selftests: Provide kvm_arch_vm_post_create() in library code
  2025-09-17 21:20 ` [PATCH 01/13] KVM: arm64: selftests: Provide kvm_arch_vm_post_create() in library code Oliver Upton
@ 2025-09-18  1:25   ` Itaru Kitayama
  0 siblings, 0 replies; 20+ messages in thread
From: Itaru Kitayama @ 2025-09-18  1:25 UTC (permalink / raw)
  To: Oliver Upton
  Cc: kvmarm, Marc Zyngier, Joey Gouly, Suzuki K Poulose, Zenghui Yu,
	Paolo Bonzini, Sean Christopherson, Christian Borntraeger,
	Janosch Frank, Claudio Imbrenda, David Hildenbrand,
	linux-arm-kernel, kvm

On Wed, Sep 17, 2025 at 02:20:31PM -0700, Oliver Upton wrote:
> In order to compel the default usage of EL2 in selftests, move
> kvm_arch_vm_post_create() to library code and expose an opt-in for using
> MTE by default.
> 
> Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
> ---
>  .../testing/selftests/kvm/arm64/set_id_regs.c | 19 +++++--------------
>  .../selftests/kvm/include/arm64/processor.h   |  2 ++
>  .../selftests/kvm/lib/arm64/processor.c       | 13 +++++++++++++
>  3 files changed, 20 insertions(+), 14 deletions(-)
> 
> diff --git a/tools/testing/selftests/kvm/arm64/set_id_regs.c b/tools/testing/selftests/kvm/arm64/set_id_regs.c
> index 189321e96925..a2d367a2c93c 100644
> --- a/tools/testing/selftests/kvm/arm64/set_id_regs.c
> +++ b/tools/testing/selftests/kvm/arm64/set_id_regs.c
> @@ -15,8 +15,6 @@
>  #include "test_util.h"
>  #include <linux/bitfield.h>
>  
> -bool have_cap_arm_mte;
> -
>  enum ftr_type {
>  	FTR_EXACT,			/* Use a predefined safe value */
>  	FTR_LOWER_SAFE,			/* Smaller value is safe */
> @@ -568,7 +566,9 @@ static void test_user_set_mte_reg(struct kvm_vcpu *vcpu)
>  	uint64_t mte_frac;
>  	int idx, err;
>  
> -	if (!have_cap_arm_mte) {
> +	val = vcpu_get_reg(vcpu, KVM_ARM64_SYS_REG(SYS_ID_AA64PFR1_EL1));
> +	mte = FIELD_GET(ID_AA64PFR1_EL1_MTE, val);
> +	if (!mte) {
>  		ksft_test_result_skip("MTE capability not supported, nothing to test\n");
>  		return;
>  	}
> @@ -593,9 +593,6 @@ static void test_user_set_mte_reg(struct kvm_vcpu *vcpu)
>  	 * from unsupported (0xF) to supported (0).
>  	 *
>  	 */
> -	val = vcpu_get_reg(vcpu, KVM_ARM64_SYS_REG(SYS_ID_AA64PFR1_EL1));
> -
> -	mte = FIELD_GET(ID_AA64PFR1_EL1_MTE, val);
>  	mte_frac = FIELD_GET(ID_AA64PFR1_EL1_MTE_frac, val);
>  	if (mte != ID_AA64PFR1_EL1_MTE_MTE2 ||
>  	    mte_frac != ID_AA64PFR1_EL1_MTE_frac_NI) {
> @@ -750,14 +747,6 @@ static void test_reset_preserves_id_regs(struct kvm_vcpu *vcpu)
>  	ksft_test_result_pass("%s\n", __func__);
>  }
>  
> -void kvm_arch_vm_post_create(struct kvm_vm *vm)
> -{
> -	if (vm_check_cap(vm, KVM_CAP_ARM_MTE)) {
> -		vm_enable_cap(vm, KVM_CAP_ARM_MTE, 0);
> -		have_cap_arm_mte = true;
> -	}
> -}
> -
>  int main(void)
>  {
>  	struct kvm_vcpu *vcpu;
> @@ -769,6 +758,8 @@ int main(void)
>  	TEST_REQUIRE(kvm_has_cap(KVM_CAP_ARM_SUPPORTED_REG_MASK_RANGES));
>  	TEST_REQUIRE(kvm_has_cap(KVM_CAP_ARM_WRITABLE_IMP_ID_REGS));
>  
> +	test_wants_mte();
> +
>  	vm = vm_create(1);
>  	vm_enable_cap(vm, KVM_CAP_ARM_WRITABLE_IMP_ID_REGS, 0);
>  	vcpu = vm_vcpu_add(vm, 0, guest_code);
> diff --git a/tools/testing/selftests/kvm/include/arm64/processor.h b/tools/testing/selftests/kvm/include/arm64/processor.h
> index 255fed769a8a..8370fc94041d 100644
> --- a/tools/testing/selftests/kvm/include/arm64/processor.h
> +++ b/tools/testing/selftests/kvm/include/arm64/processor.h
> @@ -300,4 +300,6 @@ void smccc_smc(uint32_t function_id, uint64_t arg0, uint64_t arg1,
>  /* Execute a Wait For Interrupt instruction. */
>  void wfi(void);
>  
> +void test_wants_mte(void);
> +
>  #endif /* SELFTEST_KVM_PROCESSOR_H */
> diff --git a/tools/testing/selftests/kvm/lib/arm64/processor.c b/tools/testing/selftests/kvm/lib/arm64/processor.c
> index eb115123d741..caed1998c7b3 100644
> --- a/tools/testing/selftests/kvm/lib/arm64/processor.c
> +++ b/tools/testing/selftests/kvm/lib/arm64/processor.c
> @@ -653,3 +653,16 @@ void wfi(void)
>  {
>  	asm volatile("wfi");
>  }
> +
> +static bool request_mte;
> +
> +void test_wants_mte(void)
> +{
> +	request_mte = true;
> +}
> +
> +void kvm_arch_vm_post_create(struct kvm_vm *vm)
> +{
> +	if (request_mte && vm_check_cap(vm, KVM_CAP_ARM_MTE))
> +		vm_enable_cap(vm, KVM_CAP_ARM_MTE, 0);
> +}
> -- 
> 2.47.3
>

Hi,
On FVP RevC with the kernel your series applied, I see set_id_regs fails
to execute.

# ./arm64/set_id_regs
Random seed: 0x6b8b4567
TAP version 13
1..102
ok 1 ID_AA64DFR0_EL1_DoubleLock
ok 2 ID_AA64DFR0_EL1_WRPs
ok 3 ID_AA64DFR0_EL1_PMUVer
ok 4 ID_AA64DFR0_EL1_DebugVer
ok 5 # SKIP ID_DFR0_EL1_PerfMon on AARCH64 only system
ok 6 # SKIP ID_DFR0_EL1_CopDbg on AARCH64 only system
ok 7 ID_AA64ISAR0_EL1_RNDR
ok 8 ID_AA64ISAR0_EL1_TLB
ok 9 ID_AA64ISAR0_EL1_TS
ok 10 ID_AA64ISAR0_EL1_FHM
ok 11 ID_AA64ISAR0_EL1_DP
ok 12 ID_AA64ISAR0_EL1_SM4
ok 13 ID_AA64ISAR0_EL1_SM3
ok 14 ID_AA64ISAR0_EL1_SHA3
ok 15 ID_AA64ISAR0_EL1_RDM
ok 16 ID_AA64ISAR0_EL1_TME
ok 17 ID_AA64ISAR0_EL1_ATOMIC
ok 18 ID_AA64ISAR0_EL1_CRC32
ok 19 ID_AA64ISAR0_EL1_SHA2
ok 20 ID_AA64ISAR0_EL1_SHA1
ok 21 ID_AA64ISAR0_EL1_AES
ok 22 ID_AA64ISAR1_EL1_LS64
ok 23 ID_AA64ISAR1_EL1_XS
ok 24 ID_AA64ISAR1_EL1_I8MM
ok 25 ID_AA64ISAR1_EL1_DGH
ok 26 ID_AA64ISAR1_EL1_BF16
ok 27 ID_AA64ISAR1_EL1_SPECRES
ok 28 ID_AA64ISAR1_EL1_SB
ok 29 ID_AA64ISAR1_EL1_FRINTTS
ok 30 ID_AA64ISAR1_EL1_LRCPC
ok 31 ID_AA64ISAR1_EL1_FCMA
ok 32 ID_AA64ISAR1_EL1_JSCVT
ok 33 ID_AA64ISAR1_EL1_DPB
ok 34 ID_AA64ISAR2_EL1_BC
ok 35 ID_AA64ISAR2_EL1_RPRES
ok 36 ID_AA64ISAR2_EL1_WFxT
ok 37 ID_AA64PFR0_EL1_CSV3
ok 38 ID_AA64PFR0_EL1_CSV2
ok 39 ID_AA64PFR0_EL1_DIT
ok 40 ID_AA64PFR0_EL1_SEL2
ok 41 ID_AA64PFR0_EL1_GIC
ok 42 ID_AA64PFR0_EL1_EL3
ok 43 ID_AA64PFR0_EL1_EL2
ok 44 ID_AA64PFR0_EL1_EL1
ok 45 ID_AA64PFR0_EL1_EL0
ok 46 ID_AA64PFR1_EL1_DF2
ok 47 ID_AA64PFR1_EL1_CSV2_frac
ok 48 ID_AA64PFR1_EL1_SSBS
ok 49 ID_AA64PFR1_EL1_BT
ok 50 ID_AA64MMFR0_EL1_ECV
ok 51 ID_AA64MMFR0_EL1_EXS
==== Test Assertion Failure ====
  include/kvm_util.h:815: !ret
    pid=897 tid=897 errno=22 - Invalid argument
    sh: line 1: addr2line: command not found
      KVM_SET_ONE_REG failed, rc: -1 errno: 22 (Invalid argument)



^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 03/13] KVM: arm64: selftests: Add helper to check for VGICv3 support
  2025-09-17 21:20 ` [PATCH 03/13] KVM: arm64: selftests: Add helper to check for VGICv3 support Oliver Upton
@ 2025-09-18  1:45   ` Itaru Kitayama
  0 siblings, 0 replies; 20+ messages in thread
From: Itaru Kitayama @ 2025-09-18  1:45 UTC (permalink / raw)
  To: Oliver Upton
  Cc: kvmarm, Marc Zyngier, Joey Gouly, Suzuki K Poulose, Zenghui Yu,
	Paolo Bonzini, Sean Christopherson, Christian Borntraeger,
	Janosch Frank, Claudio Imbrenda, David Hildenbrand,
	linux-arm-kernel, kvm

On Wed, Sep 17, 2025 at 02:20:33PM -0700, Oliver Upton wrote:
> Introduce a proper predicate for probing VGICv3 by performing a 'test'
> creation of the device on a dummy VM.
> 
> Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
> ---
>  tools/testing/selftests/kvm/arm64/arch_timer.c        |  3 ++-
>  .../selftests/kvm/arm64/arch_timer_edge_cases.c       |  3 ++-
>  tools/testing/selftests/kvm/arm64/vgic_irq.c          |  3 ++-
>  tools/testing/selftests/kvm/arm64/vgic_lpi_stress.c   |  4 ++--
>  .../testing/selftests/kvm/arm64/vpmu_counter_access.c |  3 +--
>  tools/testing/selftests/kvm/include/arm64/vgic.h      |  1 +
>  tools/testing/selftests/kvm/lib/arm64/vgic.c          | 11 +++++++++++
>  7 files changed, 21 insertions(+), 7 deletions(-)
> 
> diff --git a/tools/testing/selftests/kvm/arm64/arch_timer.c b/tools/testing/selftests/kvm/arm64/arch_timer.c
> index eeba1cc87ff8..aaf4285f832a 100644
> --- a/tools/testing/selftests/kvm/arm64/arch_timer.c
> +++ b/tools/testing/selftests/kvm/arm64/arch_timer.c
> @@ -184,6 +184,8 @@ struct kvm_vm *test_vm_create(void)
>  	unsigned int i;
>  	int nr_vcpus = test_args.nr_vcpus;
>  
> +	TEST_REQUIRE(kvm_supports_vgic_v3());
> +
>  	vm = vm_create_with_vcpus(nr_vcpus, guest_code, vcpus);
>  
>  	vm_init_descriptor_tables(vm);
> @@ -205,7 +207,6 @@ struct kvm_vm *test_vm_create(void)
>  
>  	test_init_timer_irq(vm);
>  	gic_fd = vgic_v3_setup(vm, nr_vcpus, 64);
> -	__TEST_REQUIRE(gic_fd >= 0, "Failed to create vgic-v3");
>  
>  	/* Make all the test's cmdline args visible to the guest */
>  	sync_global_to_guest(vm, test_args);
> diff --git a/tools/testing/selftests/kvm/arm64/arch_timer_edge_cases.c b/tools/testing/selftests/kvm/arm64/arch_timer_edge_cases.c
> index ce74d069cb7b..d349d80d8418 100644
> --- a/tools/testing/selftests/kvm/arm64/arch_timer_edge_cases.c
> +++ b/tools/testing/selftests/kvm/arm64/arch_timer_edge_cases.c
> @@ -952,7 +952,6 @@ static void test_vm_create(struct kvm_vm **vm, struct kvm_vcpu **vcpu,
>  
>  	test_init_timer_irq(*vm, *vcpu);
>  	gic_fd = vgic_v3_setup(*vm, 1, 64);
> -	__TEST_REQUIRE(gic_fd >= 0, "Failed to create vgic-v3");
>  
>  	sync_global_to_guest(*vm, test_args);
>  	sync_global_to_guest(*vm, CVAL_MAX);
> @@ -1042,6 +1041,8 @@ int main(int argc, char *argv[])
>  	/* Tell stdout not to buffer its content */
>  	setbuf(stdout, NULL);
>  
> +	TEST_REQUIRE(kvm_supports_vgic_v3());
> +
>  	if (!parse_args(argc, argv))
>  		exit(KSFT_SKIP);
>  
> diff --git a/tools/testing/selftests/kvm/arm64/vgic_irq.c b/tools/testing/selftests/kvm/arm64/vgic_irq.c
> index a09dd423c2d7..9fc9e8e44ecd 100644
> --- a/tools/testing/selftests/kvm/arm64/vgic_irq.c
> +++ b/tools/testing/selftests/kvm/arm64/vgic_irq.c
> @@ -752,7 +752,6 @@ static void test_vgic(uint32_t nr_irqs, bool level_sensitive, bool eoi_split)
>  	vcpu_args_set(vcpu, 1, args_gva);
>  
>  	gic_fd = vgic_v3_setup(vm, 1, nr_irqs);
> -	__TEST_REQUIRE(gic_fd >= 0, "Failed to create vgic-v3, skipping");
>  
>  	vm_install_exception_handler(vm, VECTOR_IRQ_CURRENT,
>  		guest_irq_handlers[args.eoi_split][args.level_sensitive]);
> @@ -802,6 +801,8 @@ int main(int argc, char **argv)
>  	int opt;
>  	bool eoi_split = false;
>  
> +	TEST_REQUIRE(kvm_supports_vgic_v3());
> +
>  	while ((opt = getopt(argc, argv, "hn:e:l:")) != -1) {
>  		switch (opt) {
>  		case 'n':
> diff --git a/tools/testing/selftests/kvm/arm64/vgic_lpi_stress.c b/tools/testing/selftests/kvm/arm64/vgic_lpi_stress.c
> index fc4fe52fb6f8..cc2b21d374af 100644
> --- a/tools/testing/selftests/kvm/arm64/vgic_lpi_stress.c
> +++ b/tools/testing/selftests/kvm/arm64/vgic_lpi_stress.c
> @@ -215,8 +215,6 @@ static void setup_test_data(void)
>  static void setup_gic(void)
>  {
>  	gic_fd = vgic_v3_setup(vm, test_data.nr_cpus, 64);
> -	__TEST_REQUIRE(gic_fd >= 0, "Failed to create GICv3");
> -
>  	its_fd = vgic_its_setup(vm);
>  }
>  
> @@ -374,6 +372,8 @@ int main(int argc, char **argv)
>  	u32 nr_threads;
>  	int c;
>  
> +	TEST_REQUIRE(kvm_supports_vgic_v3());
> +
>  	while ((c = getopt(argc, argv, "hv:d:e:i:")) != -1) {
>  		switch (c) {
>  		case 'v':
> diff --git a/tools/testing/selftests/kvm/arm64/vpmu_counter_access.c b/tools/testing/selftests/kvm/arm64/vpmu_counter_access.c
> index a0c4ab839155..01f61657de45 100644
> --- a/tools/testing/selftests/kvm/arm64/vpmu_counter_access.c
> +++ b/tools/testing/selftests/kvm/arm64/vpmu_counter_access.c
> @@ -436,8 +436,6 @@ static void create_vpmu_vm(void *guest_code)
>  	vpmu_vm.vcpu = aarch64_vcpu_add(vpmu_vm.vm, 0, &init, guest_code);
>  	vcpu_init_descriptor_tables(vpmu_vm.vcpu);
>  	vpmu_vm.gic_fd = vgic_v3_setup(vpmu_vm.vm, 1, 64);
> -	__TEST_REQUIRE(vpmu_vm.gic_fd >= 0,
> -		       "Failed to create vgic-v3, skipping");
>  
>  	/* Make sure that PMUv3 support is indicated in the ID register */
>  	dfr0 = vcpu_get_reg(vpmu_vm.vcpu, KVM_ARM64_SYS_REG(SYS_ID_AA64DFR0_EL1));
> @@ -634,6 +632,7 @@ int main(void)
>  	uint64_t i, pmcr_n;
>  
>  	TEST_REQUIRE(kvm_has_cap(KVM_CAP_ARM_PMU_V3));
> +	TEST_REQUIRE(kvm_supports_vgic_v3());
>  
>  	pmcr_n = get_pmcr_n_limit();
>  	for (i = 0; i <= pmcr_n; i++) {
> diff --git a/tools/testing/selftests/kvm/include/arm64/vgic.h b/tools/testing/selftests/kvm/include/arm64/vgic.h
> index c481d0c00a5d..b858fa8195b4 100644
> --- a/tools/testing/selftests/kvm/include/arm64/vgic.h
> +++ b/tools/testing/selftests/kvm/include/arm64/vgic.h
> @@ -16,6 +16,7 @@
>  	((uint64_t)(flags) << 12) | \
>  	index)
>  
> +bool kvm_supports_vgic_v3(void);
>  int vgic_v3_setup(struct kvm_vm *vm, unsigned int nr_vcpus, uint32_t nr_irqs);
>  
>  #define VGIC_MAX_RESERVED	1023
> diff --git a/tools/testing/selftests/kvm/lib/arm64/vgic.c b/tools/testing/selftests/kvm/lib/arm64/vgic.c
> index 64e793795563..661744c6532e 100644
> --- a/tools/testing/selftests/kvm/lib/arm64/vgic.c
> +++ b/tools/testing/selftests/kvm/lib/arm64/vgic.c
> @@ -15,6 +15,17 @@
>  #include "gic.h"
>  #include "gic_v3.h"
>  
> +bool kvm_supports_vgic_v3(void)
> +{
> +	struct kvm_vm *vm = vm_create_barebones();
> +	int r;
> +
> +	r = __kvm_test_create_device(vm, KVM_DEV_TYPE_ARM_VGIC_V3);
> +	kvm_vm_free(vm);
> +
> +	return !r;
> +}
> +
>  /*
>   * vGIC-v3 default host setup
>   *
> -- 
> 2.47.3
> 

Oliver
The arch_timer_edge_cases selftest does not return nor fails on FVP RevC.
I boot the system with kvm-arm.mode=nested.

Thanks,
Itaru.


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 02/13] KVM: arm64: selftests: Initialize VGICv3 only once
  2025-09-17 21:20 ` [PATCH 02/13] KVM: arm64: selftests: Initialize VGICv3 only once Oliver Upton
@ 2025-09-18 10:44   ` Zenghui Yu
  0 siblings, 0 replies; 20+ messages in thread
From: Zenghui Yu @ 2025-09-18 10:44 UTC (permalink / raw)
  To: Oliver Upton
  Cc: kvmarm, Marc Zyngier, Joey Gouly, Suzuki K Poulose, Paolo Bonzini,
	Sean Christopherson, Christian Borntraeger, Janosch Frank,
	Claudio Imbrenda, David Hildenbrand, linux-arm-kernel, kvm

On 2025/9/18 5:20, Oliver Upton wrote:
> vgic_v3_setup() unnecessarily initializes the vgic twice. Keep the
> initialization after configuring MMIO frames and get rid of the other.
> 
> Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
> ---
>  tools/testing/selftests/kvm/lib/arm64/vgic.c | 3 ---
>  1 file changed, 3 deletions(-)
> 
> diff --git a/tools/testing/selftests/kvm/lib/arm64/vgic.c b/tools/testing/selftests/kvm/lib/arm64/vgic.c
> index 4427f43f73ea..64e793795563 100644
> --- a/tools/testing/selftests/kvm/lib/arm64/vgic.c
> +++ b/tools/testing/selftests/kvm/lib/arm64/vgic.c
> @@ -56,9 +56,6 @@ int vgic_v3_setup(struct kvm_vm *vm, unsigned int nr_vcpus, uint32_t nr_irqs)
>  
>  	kvm_device_attr_set(gic_fd, KVM_DEV_ARM_VGIC_GRP_NR_IRQS, 0, &nr_irqs);
>  
> -	kvm_device_attr_set(gic_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
> -			    KVM_DEV_ARM_VGIC_CTRL_INIT, NULL);
> -

.. which was added by commit e5410ee2806d ("KVM: selftests: aarch64:
Cmdline arg to set number of IRQs in vgic_irq test").

>  	attr = GICD_BASE_GPA;
>  	kvm_device_attr_set(gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
>  			    KVM_VGIC_V3_ADDR_TYPE_DIST, &attr);

Reviewed-by: Zenghui Yu <yuzenghui@huawei.com>

Thanks,
Zenghui


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 00/13] KVM: arm64: selftests: Run selftests in VHE EL2
  2025-09-17 21:20 [PATCH 00/13] KVM: arm64: selftests: Run selftests in VHE EL2 Oliver Upton
                   ` (12 preceding siblings ...)
  2025-09-17 21:20 ` [PATCH 13/13] KVM: arm64: selftests: Add basic test for running in VHE EL2 Oliver Upton
@ 2025-09-24 18:37 ` Marc Zyngier
  13 siblings, 0 replies; 20+ messages in thread
From: Marc Zyngier @ 2025-09-24 18:37 UTC (permalink / raw)
  To: kvmarm, Oliver Upton
  Cc: Joey Gouly, Suzuki K Poulose, Zenghui Yu, Paolo Bonzini,
	Sean Christopherson, Christian Borntraeger, Janosch Frank,
	Claudio Imbrenda, David Hildenbrand, linux-arm-kernel, kvm

On Wed, 17 Sep 2025 14:20:30 -0700, Oliver Upton wrote:
> I've been working on some MMU-related features that are unused by KVM
> meaning they're somewhat annoying to test. Because of that, I found the
> time / patience to port our existing selftests infrastructure over to
> running in VHE EL2, opportunistically promoting tests when the stars
> align.
> 
> Creating a VGIC is a hard requirement of enabling EL2 for a VM. As a
> consequence of this, I need to eat my words from my earlier conversation
> with Sean on this topic and hammer in a default VGICv3. This requires
> some participation from the arch-neutral code given the ordering
> constraints on vCPU and VGIC creation.
> 
> [...]

Applied to next, thanks!

[01/13] KVM: arm64: selftests: Provide kvm_arch_vm_post_create() in library code
        commit: 7326348209a0079a83c7bd7963a0e32d26af61c8
[02/13] KVM: arm64: selftests: Initialize VGICv3 only once
        commit: a5022da5f9a3a791ff2caf5fe3789561ae687747
[03/13] KVM: arm64: selftests: Add helper to check for VGICv3 support
        commit: b712afa7a1cdb787f311f51c04df81fc6f026368
[04/13] KVM: arm64: selftests: Add unsanitised helpers for VGICv3 creation
        commit: b8daa7ceac1c56e39b6ef4e62510a7d846511695
[05/13] KVM: arm64: selftests: Create a VGICv3 for 'default' VMs
        commit: 8911c7dbc607212bf3dfc963004b062588c0ab38
[06/13] KVM: arm64: selftests: Alias EL1 registers to EL2 counterparts
        commit: 1c9604ba234711ca759f1147f2fbc7a94a5a486d
[07/13] KVM: arm64: selftests: Provide helper for getting default vCPU target
        commit: a1b91ac2381d86aa47b7109bbcde0c71e775f6d9
[08/13] KVM: arm64: selftests: Select SMCCC conduit based on current EL
        commit: d72543ac728ae4a4708cbefad2761df84599c268
[09/13] KVM: arm64: selftests: Use hyp timer IRQs when test runs at EL2
        commit: 0910778e49c6639d265ab2d7a47d0b461b8e2963
[10/13] KVM: arm64: selftests: Use the vCPU attr for setting nr of PMU counters
        commit: 7ae44d1cdad8a2483465373b9c9e91f0461ca9b2
[11/13] KVM: arm64: selftests: Initialize HCR_EL2
        commit: 05c93cbe6653e7e77567962aa6533b618df5e19f
[12/13] KVM: arm64: selftests: Enable EL2 by default
        commit: 2de21fb62387459f762c93eec3d04e4f7540b952
[13/13] KVM: arm64: selftests: Add basic test for running in VHE EL2
        commit: f677b0efa93ce0afb127ccffb8aaf708045fcf10

Cheers,

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




^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2025-09-24 18:38 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-09-17 21:20 [PATCH 00/13] KVM: arm64: selftests: Run selftests in VHE EL2 Oliver Upton
2025-09-17 21:20 ` [PATCH 01/13] KVM: arm64: selftests: Provide kvm_arch_vm_post_create() in library code Oliver Upton
2025-09-18  1:25   ` Itaru Kitayama
2025-09-17 21:20 ` [PATCH 02/13] KVM: arm64: selftests: Initialize VGICv3 only once Oliver Upton
2025-09-18 10:44   ` Zenghui Yu
2025-09-17 21:20 ` [PATCH 03/13] KVM: arm64: selftests: Add helper to check for VGICv3 support Oliver Upton
2025-09-18  1:45   ` Itaru Kitayama
2025-09-17 21:20 ` [PATCH 04/13] KVM: arm64: selftests: Add unsanitised helpers for VGICv3 creation Oliver Upton
2025-09-17 21:20 ` [PATCH 05/13] KVM: arm64: selftests: Create a VGICv3 for 'default' VMs Oliver Upton
2025-09-17 21:20 ` [PATCH 06/13] KVM: arm64: selftests: Alias EL1 registers to EL2 counterparts Oliver Upton
2025-09-17 21:20 ` [PATCH 07/13] KVM: arm64: selftests: Provide helper for getting default vCPU target Oliver Upton
2025-09-17 21:56   ` Itaru Kitayama
2025-09-17 22:00     ` Oliver Upton
2025-09-17 21:20 ` [PATCH 08/13] KVM: arm64: selftests: Select SMCCC conduit based on current EL Oliver Upton
2025-09-17 21:20 ` [PATCH 09/13] KVM: arm64: selftests: Use hyp timer IRQs when test runs at EL2 Oliver Upton
2025-09-17 21:20 ` [PATCH 10/13] KVM: arm64: selftests: Use the vCPU attr for setting nr of PMU counters Oliver Upton
2025-09-17 21:20 ` [PATCH 11/13] KVM: arm64: selftests: Initialize HCR_EL2 Oliver Upton
2025-09-17 21:20 ` [PATCH 12/13] KVM: arm64: selftests: Enable EL2 by default Oliver Upton
2025-09-17 21:20 ` [PATCH 13/13] KVM: arm64: selftests: Add basic test for running in VHE EL2 Oliver Upton
2025-09-24 18:37 ` [PATCH 00/13] KVM: arm64: selftests: Run selftests " Marc Zyngier

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).