Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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 <oliver.upton@linux.dev>
Signed-off-by: Marc Zyngier <maz@kernel.org>

authored by

Oliver Upton and committed by
Marc Zyngier
75b2fdc1 f677b0ef

+15 -2
+15 -2
tools/testing/selftests/kvm/arm64/hello_el2.c
··· 13 13 14 14 static void guest_code(void) 15 15 { 16 + u64 mmfr0 = read_sysreg_s(SYS_ID_AA64MMFR0_EL1); 16 17 u64 mmfr1 = read_sysreg_s(SYS_ID_AA64MMFR1_EL1); 17 18 u64 mmfr4 = read_sysreg_s(SYS_ID_AA64MMFR4_EL1); 19 + u8 e2h0 = SYS_FIELD_GET(ID_AA64MMFR4_EL1, E2H0, mmfr4); 18 20 19 21 GUEST_ASSERT_EQ(get_current_el(), 2); 20 22 GUEST_ASSERT(read_sysreg(hcr_el2) & HCR_EL2_E2H); 21 23 GUEST_ASSERT_EQ(SYS_FIELD_GET(ID_AA64MMFR1_EL1, VH, mmfr1), 22 24 ID_AA64MMFR1_EL1_VH_IMP); 23 - GUEST_ASSERT_EQ(SYS_FIELD_GET(ID_AA64MMFR4_EL1, E2H0, mmfr4), 24 - ID_AA64MMFR4_EL1_E2H0_NI_NV1); 25 + 26 + /* 27 + * Traps of the complete ID register space are IMPDEF without FEAT_FGT, 28 + * which is really annoying to deal with in KVM describing E2H as RES1. 29 + * 30 + * If the implementation doesn't honor the trap then expect the register 31 + * to return all zeros. 32 + */ 33 + if (e2h0 == ID_AA64MMFR4_EL1_E2H0_IMP) 34 + GUEST_ASSERT_EQ(SYS_FIELD_GET(ID_AA64MMFR0_EL1, FGT, mmfr0), 35 + ID_AA64MMFR0_EL1_FGT_NI); 36 + else 37 + GUEST_ASSERT_EQ(e2h0, ID_AA64MMFR4_EL1_E2H0_NI_NV1); 25 38 26 39 GUEST_DONE(); 27 40 }