Commit 10fd0285 authored by Marc Zyngier's avatar Marc Zyngier
Browse files

Merge branch kvm-arm64/selftests-6.18 into kvmarm-master/next



* kvm-arm64/selftests-6.18:
  : .
  : KVM/arm64 selftest updates for 6.18:
  :
  : - Large update to run EL1 selftests at EL2 when possible
  :   (20250917212044.294760-1-oliver.upton@linux.dev)
  :
  : - Work around lack of ID_AA64MMFR4_EL1 trapping on CPUs
  :   without FEAT_FGT
  :   (20250923173006.467455-1-oliver.upton@linux.dev)
  :
  : - Additional fixes and cleanups
  :   (20250920-kvm-arm64-id-aa64isar3-el1-v1-0-1764c1c1c96d@kernel.org)
  : .
  KVM: arm64: selftests: Cover ID_AA64ISAR3_EL1 in set_id_regs
  KVM: arm64: selftests: Remove a duplicate register listing in set_id_regs
  KVM: arm64: selftests: Cope with arch silliness in EL2 selftest
  KVM: arm64: selftests: Add basic test for running in VHE EL2
  KVM: arm64: selftests: Enable EL2 by default
  KVM: arm64: selftests: Initialize HCR_EL2
  KVM: arm64: selftests: Use the vCPU attr for setting nr of PMU counters
  KVM: arm64: selftests: Use hyp timer IRQs when test runs at EL2
  KVM: arm64: selftests: Select SMCCC conduit based on current EL
  KVM: arm64: selftests: Provide helper for getting default vCPU target
  KVM: arm64: selftests: Alias EL1 registers to EL2 counterparts
  KVM: arm64: selftests: Create a VGICv3 for 'default' VMs
  KVM: arm64: selftests: Add unsanitised helpers for VGICv3 creation
  KVM: arm64: selftests: Add helper to check for VGICv3 support
  KVM: arm64: selftests: Initialize VGICv3 only once
  KVM: arm64: selftests: Provide kvm_arch_vm_post_create() in library code

Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
parents 181ce6b0 b02a2c06
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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
+4 −9
Original line number Diff line number Diff line
@@ -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);
@@ -176,14 +174,14 @@ 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;
	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);
@@ -204,8 +202,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);
	__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);
@@ -215,6 +211,5 @@ struct kvm_vm *test_vm_create(void)

void test_vm_cleanup(struct kvm_vm *vm)
{
	close(gic_fd);
	kvm_vm_free(vm);
}
+4 −9
Original line number Diff line number Diff line
@@ -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);
@@ -935,8 +933,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,8 +947,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);
	__TEST_REQUIRE(gic_fd >= 0, "Failed to create vgic-v3");

	sync_global_to_guest(*vm, test_args);
	sync_global_to_guest(*vm, CVAL_MAX);
@@ -961,7 +955,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);
}

@@ -1042,6 +1035,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);

+71 −0
Original line number Diff line number Diff line
// 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 mmfr0 = read_sysreg_s(SYS_ID_AA64MMFR0_EL1);
	u64 mmfr1 = read_sysreg_s(SYS_ID_AA64MMFR1_EL1);
	u64 mmfr4 = read_sysreg_s(SYS_ID_AA64MMFR4_EL1);
	u8 e2h0 = SYS_FIELD_GET(ID_AA64MMFR4_EL1, E2H0, mmfr4);

	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);

	/*
	 * Traps of the complete ID register space are IMPDEF without FEAT_FGT,
	 * which is really annoying to deal with in KVM describing E2H as RES1.
	 *
	 * If the implementation doesn't honor the trap then expect the register
	 * to return all zeros.
	 */
	if (e2h0 == ID_AA64MMFR4_EL1_E2H0_IMP)
		GUEST_ASSERT_EQ(SYS_FIELD_GET(ID_AA64MMFR0_EL1, FGT, mmfr0),
				ID_AA64MMFR0_EL1_FGT_NI);
	else
		GUEST_ASSERT_EQ(e2h0, 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;
}
+1 −1
Original line number Diff line number Diff line
@@ -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:
Loading