Re: [PATCH v12 45/46] KVM: selftests: hyperv_svm_test: Introduce L2 TLB flush test

From: Sean Christopherson
Date: Wed Oct 26 2022 - 18:23:54 EST


On Fri, Oct 21, 2022, Vitaly Kuznetsov wrote:
> Enable Hyper-V L2 TLB flush and check that Hyper-V TLB flush hypercalls
> from L2 don't exit to L1 unless 'TlbLockCount' is set in the Partition
> assist page.
>
> Signed-off-by: Vitaly Kuznetsov <vkuznets@xxxxxxxxxx>
> ---
> .../selftests/kvm/include/x86_64/svm.h | 4 ++
> .../selftests/kvm/x86_64/hyperv_svm_test.c | 61 +++++++++++++++++--
> 2 files changed, 60 insertions(+), 5 deletions(-)
>
> diff --git a/tools/testing/selftests/kvm/include/x86_64/svm.h b/tools/testing/selftests/kvm/include/x86_64/svm.h
> index 483e6ae12f69..4803e1056055 100644
> --- a/tools/testing/selftests/kvm/include/x86_64/svm.h
> +++ b/tools/testing/selftests/kvm/include/x86_64/svm.h
> @@ -76,6 +76,10 @@ struct hv_vmcb_enlightenments {
> */
> #define HV_VMCB_NESTED_ENLIGHTENMENTS (1U << 31)
>
> +/* Synthetic VM-Exit */
> +#define HV_SVM_EXITCODE_ENL 0xf0000000
> +#define HV_SVM_ENL_EXITCODE_TRAP_AFTER_FLUSH (1)
> +
> struct __attribute__ ((__packed__)) vmcb_control_area {
> u32 intercept_cr;
> u32 intercept_dr;
> diff --git a/tools/testing/selftests/kvm/x86_64/hyperv_svm_test.c b/tools/testing/selftests/kvm/x86_64/hyperv_svm_test.c
> index 1c3fc38b4f15..edb779615a79 100644
> --- a/tools/testing/selftests/kvm/x86_64/hyperv_svm_test.c
> +++ b/tools/testing/selftests/kvm/x86_64/hyperv_svm_test.c
> @@ -25,6 +25,8 @@
>
> void l2_guest_code(void)
> {
> + u64 unused;
> +
> GUEST_SYNC(3);
> /* Exit to L1 */
> vmmcall();
> @@ -38,11 +40,30 @@ void l2_guest_code(void)
>
> GUEST_SYNC(5);
>
> + /* L2 TLB flush tests */
> + hyperv_hypercall(HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE |
> + HV_HYPERCALL_FAST_BIT, 0x0,
> + HV_FLUSH_ALL_VIRTUAL_ADDRESS_SPACES |
> + HV_FLUSH_ALL_PROCESSORS);
> + rdmsr(MSR_FS_BASE);

Why doesn't the SVM test need to clobber GPRs?

> + /*
> + * Note: hypercall status (RAX) is not preserved correctly by L1 after
> + * synthetic vmexit, use unchecked version.
> + */
> + __hyperv_hypercall(HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE |
> + HV_HYPERCALL_FAST_BIT, 0x0,
> + HV_FLUSH_ALL_VIRTUAL_ADDRESS_SPACES |
> + HV_FLUSH_ALL_PROCESSORS, &unused);
> + /* Make sure we're not issuing Hyper-V TLB flush call again */
> + __asm__ __volatile__ ("mov $0xdeadbeef, %rcx");

Heh, and a patch to vmmcall() itself "safe"...

> +
> /* Done, exit to L1 and never come back. */
> vmmcall();
> }