Skip to content

Commit 890c608

Browse files
ouptonMarc Zyngier
authored andcommitted
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 <[email protected]> Signed-off-by: Marc Zyngier <[email protected]>
1 parent a46c09b commit 890c608

File tree

2 files changed

+54
-1
lines changed

2 files changed

+54
-1
lines changed

tools/testing/selftests/kvm/arm64/external_aborts.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,44 @@ static void test_mmio_ease(void)
359359
kvm_vm_free(vm);
360360
}
361361

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+
362400
int main(void)
363401
{
364402
test_mmio_abort();
@@ -369,4 +407,9 @@ int main(void)
369407
test_serror_emulated();
370408
test_mmio_ease();
371409
test_s1ptw_abort();
410+
411+
if (!test_supports_el2())
412+
return 0;
413+
414+
test_serror_amo();
372415
}

tools/testing/selftests/kvm/include/arm64/processor.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,17 @@ void test_wants_mte(void);
305305
void test_disable_default_vgic(void);
306306

307307
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)
309319
{
310320
return vcpu->init.features[0] & BIT(KVM_ARM_VCPU_HAS_EL2);
311321
}

0 commit comments

Comments
 (0)