From: Oliver Upton Date: Tue, 23 Sep 2025 17:30:06 +0000 (-0700) Subject: KVM: arm64: selftests: Cope with arch silliness in EL2 selftest X-Git-Tag: v6.18-rc1~95^2~5^2^2~2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=75b2fdc1a82195997cab4836f9e511cbe8c8eb52;p=thirdparty%2Fkernel%2Flinux.git KVM: arm64: selftests: Cope with arch silliness in EL2 selftest Implementations without FEAT_FGT aren't required to trap the entire ID register space when HCR_EL2.TID3 is set. This is a terrible idea, as the hypervisor may need to advertise the absence of a feature to the VM using a negative value in a signed field, FEAT_E2H0 being a great example of this. Cope with uncooperative implementations in the EL2 selftest by accepting a zero value when FEAT_FGT is absent and otherwise only tolerating the expected nonzero value. Signed-off-by: Oliver Upton Signed-off-by: Marc Zyngier --- diff --git a/tools/testing/selftests/kvm/arm64/hello_el2.c b/tools/testing/selftests/kvm/arm64/hello_el2.c index 3c1f44e43f657..bbe6862c6ab16 100644 --- a/tools/testing/selftests/kvm/arm64/hello_el2.c +++ b/tools/testing/selftests/kvm/arm64/hello_el2.c @@ -13,15 +13,28 @@ 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); - GUEST_ASSERT_EQ(SYS_FIELD_GET(ID_AA64MMFR4_EL1, E2H0, mmfr4), - ID_AA64MMFR4_EL1_E2H0_NI_NV1); + + /* + * 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(); }