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

KVM: arm64: selftests: Test effective value of HCR_EL2.AMO

A defect against the architecture now allows an implementation to treat
AMO as 1 when HCR_EL2.{E2H, TGE} = {1, 0}. KVM now takes advantage of
this interpretation to address a quality of emulation issue w.r.t.
SError injection.

Add a corresponding test case and expect a pending SError to be taken.

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
890c608b a46c09b3

+54 -1
+43
tools/testing/selftests/kvm/arm64/external_aborts.c
··· 359 359 kvm_vm_free(vm); 360 360 } 361 361 362 + static void test_serror_amo_guest(void) 363 + { 364 + /* 365 + * The ISB is entirely unnecessary (and highlights how FEAT_NV2 is borked) 366 + * since the write is redirected to memory. But don't write (intentionally) 367 + * broken code! 368 + */ 369 + sysreg_clear_set(hcr_el2, HCR_EL2_AMO | HCR_EL2_TGE, 0); 370 + isb(); 371 + 372 + GUEST_SYNC(0); 373 + GUEST_ASSERT(read_sysreg(isr_el1) & ISR_EL1_A); 374 + 375 + /* 376 + * KVM treats the effective value of AMO as 1 when 377 + * HCR_EL2.{E2H,TGE} = {1, 0}, meaning the SError will be taken when 378 + * unmasked. 379 + */ 380 + local_serror_enable(); 381 + isb(); 382 + local_serror_disable(); 383 + 384 + GUEST_FAIL("Should've taken pending SError exception"); 385 + } 386 + 387 + static void test_serror_amo(void) 388 + { 389 + struct kvm_vcpu *vcpu; 390 + struct kvm_vm *vm = vm_create_with_dabt_handler(&vcpu, test_serror_amo_guest, 391 + unexpected_dabt_handler); 392 + 393 + vm_install_exception_handler(vm, VECTOR_ERROR_CURRENT, expect_serror_handler); 394 + vcpu_run_expect_sync(vcpu); 395 + vcpu_inject_serror(vcpu); 396 + vcpu_run_expect_done(vcpu); 397 + kvm_vm_free(vm); 398 + } 399 + 362 400 int main(void) 363 401 { 364 402 test_mmio_abort(); ··· 407 369 test_serror_emulated(); 408 370 test_mmio_ease(); 409 371 test_s1ptw_abort(); 372 + 373 + if (!test_supports_el2()) 374 + return 0; 375 + 376 + test_serror_amo(); 410 377 }
+11 -1
tools/testing/selftests/kvm/include/arm64/processor.h
··· 305 305 void test_disable_default_vgic(void); 306 306 307 307 bool vm_supports_el2(struct kvm_vm *vm); 308 - static bool vcpu_has_el2(struct kvm_vcpu *vcpu) 308 + 309 + static inline bool test_supports_el2(void) 310 + { 311 + struct kvm_vm *vm = vm_create(1); 312 + bool supported = vm_supports_el2(vm); 313 + 314 + kvm_vm_free(vm); 315 + return supported; 316 + } 317 + 318 + static inline bool vcpu_has_el2(struct kvm_vcpu *vcpu) 309 319 { 310 320 return vcpu->init.features[0] & BIT(KVM_ARM_VCPU_HAS_EL2); 311 321 }