All of lore.kernel.org
 help / color / mirror / Atom feed
From: Vitaly Kuznetsov <vkuznets@redhat.com>
To: kvm@vger.kernel.org
Cc: Sean Christopherson <seanjc@google.com>,
	Maxim Levitsky <mlevitsk@redhat.com>,
	Wanpeng Li <wanpengli@tencent.com>,
	Jim Mattson <jmattson@google.com>,
	Michael Kelley <mikelley@microsoft.com>,
	Siddharth Chandrasekaran <sidcha@amazon.de>,
	Yuan Yao <yuan.yao@linux.intel.com>,
	linux-hyperv@vger.kernel.org, linux-kernel@vger.kernel.org,
	Paolo Bonzini <pbonzini@redhat.com>
Subject: Re: [PATCH v5 21/37] KVM: nSVM: hyper-v: Enable L2 TLB flush
Date: Tue, 31 May 2022 14:18:05 +0200	[thread overview]
Message-ID: <874k15q4jm.fsf@redhat.com> (raw)
In-Reply-To: <20220527155546.1528910-22-vkuznets@redhat.com>

Vitaly Kuznetsov <vkuznets@redhat.com> writes:

> Implement Hyper-V L2 TLB flush for nSVM. The feature needs to be enabled
> both in extended 'nested controls' in VMCB and partition assist page.
> According to Hyper-V TLFS, synthetic vmexit to L1 is performed with
> - HV_SVM_EXITCODE_ENL exit_code.
> - HV_SVM_ENL_EXITCODE_TRAP_AFTER_FLUSH exit_info_1.
>
> Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
> Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
> ---
>  arch/x86/kvm/svm/hyperv.c |  7 +++++++
>  arch/x86/kvm/svm/hyperv.h | 19 +++++++++++++++++++
>  arch/x86/kvm/svm/nested.c | 27 +++++++++++++++++++++++++--
>  3 files changed, 51 insertions(+), 2 deletions(-)
>
> diff --git a/arch/x86/kvm/svm/hyperv.c b/arch/x86/kvm/svm/hyperv.c
> index 911f51021af1..088f6429b24c 100644
> --- a/arch/x86/kvm/svm/hyperv.c
> +++ b/arch/x86/kvm/svm/hyperv.c
> @@ -8,4 +8,11 @@
>  
>  void svm_hv_inject_synthetic_vmexit_post_tlb_flush(struct kvm_vcpu *vcpu)
>  {
> +	struct vcpu_svm *svm = to_svm(vcpu);
> +
> +	svm->vmcb->control.exit_code = HV_SVM_EXITCODE_ENL;
> +	svm->vmcb->control.exit_code_hi = 0;
> +	svm->vmcb->control.exit_info_1 = HV_SVM_ENL_EXITCODE_TRAP_AFTER_FLUSH;
> +	svm->vmcb->control.exit_info_2 = 0;
> +	nested_svm_vmexit(svm);
>  }
> diff --git a/arch/x86/kvm/svm/hyperv.h b/arch/x86/kvm/svm/hyperv.h
> index dd2e393f84a0..6ea78499e21b 100644
> --- a/arch/x86/kvm/svm/hyperv.h
> +++ b/arch/x86/kvm/svm/hyperv.h
> @@ -33,6 +33,9 @@ struct hv_enlightenments {
>   */
>  #define VMCB_HV_NESTED_ENLIGHTENMENTS VMCB_SW
>  
> +#define HV_SVM_EXITCODE_ENL 0xF0000000
> +#define HV_SVM_ENL_EXITCODE_TRAP_AFTER_FLUSH   (1)
> +
>  static inline void nested_svm_hv_update_vm_vp_ids(struct kvm_vcpu *vcpu)
>  {
>  	struct vcpu_svm *svm = to_svm(vcpu);
> @@ -48,6 +51,22 @@ static inline void nested_svm_hv_update_vm_vp_ids(struct kvm_vcpu *vcpu)
>  	hv_vcpu->nested.vp_id = hve->hv_vp_id;
>  }
>  
> +static inline bool nested_svm_l2_tlb_flush_enabled(struct kvm_vcpu *vcpu)
> +{
> +	struct vcpu_svm *svm = to_svm(vcpu);
> +	struct hv_enlightenments *hve =
> +		(struct hv_enlightenments *)svm->nested.ctl.reserved_sw;
> +	struct hv_vp_assist_page assist_page;
> +
> +	if (unlikely(!kvm_hv_get_assist_page(vcpu, &assist_page)))
> +		return false;
> +
> +	if (!hve->hv_enlightenments_control.nested_flush_hypercall)
> +		return false;
> +
> +	return assist_page.nested_control.features.directhypercall;
> +}
> +
>  void svm_hv_inject_synthetic_vmexit_post_tlb_flush(struct kvm_vcpu *vcpu);
>  
>  #endif /* __ARCH_X86_KVM_SVM_HYPERV_H__ */
> diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c
> index b203e6cd75dc..083b95d85495 100644
> --- a/arch/x86/kvm/svm/nested.c
> +++ b/arch/x86/kvm/svm/nested.c
> @@ -171,8 +171,12 @@ void recalc_intercepts(struct vcpu_svm *svm)
>  		vmcb_clr_intercept(c, INTERCEPT_VINTR);
>  	}
>  
> -	/* We don't want to see VMMCALLs from a nested guest */
> -	vmcb_clr_intercept(c, INTERCEPT_VMMCALL);
> +	/*
> +	 * We want to see VMMCALLs from a nested guest only when Hyper-V L2 TLB
> +	 * flush feature is enabled.
> +	 */
> +	if (!nested_svm_l2_tlb_flush_enabled(&svm->vcpu))
> +		vmcb_clr_intercept(c, INTERCEPT_VMMCALL);

I've just noticed that this generates a warning:

[  823.047913] =============================
[  823.048376] WARNING: suspicious RCU usage
[  823.048745] 5.18.0-rc1+ #454 Not tainted
[  823.049098] -----------------------------
[  823.049435] include/linux/kvm_host.h:936 suspicious rcu_dereference_check() usage!
[  823.049791] 
               other info that might help us debug this:

[  823.050756] 
               rcu_scheduler_active = 2, debug_locks = 1
[  823.051410] 1 lock held by qemu-system-x86/8931:
[  823.051747]  #0: ffff8ad90c144fa8 (&vcpu->mutex){+.+.}-{3:3}, at: kvm_vcpu_ioctl+0x77/0x700 [kvm]
[  823.052171] 
               stack backtrace:
[  823.052849] CPU: 3 PID: 8931 Comm: qemu-system-x86 Kdump: loaded Not tainted 5.18.0-rc1+ #454
[  823.053230] Hardware name: Dell Inc. PowerEdge R6415/065PKD, BIOS 1.9.3 06/25/2019
[  823.053644] Call Trace:
[  823.054279]  <TASK>
[  823.054695]  dump_stack_lvl+0x6c/0x9b
[  823.055076]  kvm_read_guest_offset_cached+0x14a/0x190 [kvm]
[  823.055504]  kvm_hv_get_assist_page+0x40/0x50 [kvm]
[  823.055932]  recalc_intercepts+0x6f/0x140 [kvm_amd]
[  823.056317]  ? native_load_tr_desc+0x63/0x70
[  823.056696]  ? svm_vcpu_run+0x27f/0x780 [kvm_amd]
[  823.057080]  kvm_arch_vcpu_ioctl_run+0x1a9f/0x2220 [kvm]
[  823.057519]  ? kvm_vcpu_ioctl+0x275/0x700 [kvm]
[  823.057932]  kvm_vcpu_ioctl+0x275/0x700 [kvm]
[  823.058358]  __x64_sys_ioctl+0x82/0xb0
[  823.058747]  do_syscall_64+0x3b/0x90
[  823.059133]  entry_SYSCALL_64_after_hwframe+0x44/0xae
[  823.059519] RIP: 0033:0x7fcd123540ab
[  823.059899] Code: ff ff ff 85 c0 79 9b 49 c7 c4 ff ff ff ff 5b 5d 4c 89 e0 41 5c c3 66 0f 1f 84 00 00 00 00 00 f3 0f 1e fa b8 10 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 9d bd 0c 00 f7 d8 64 89 01 48
[  823.060787] RSP: 002b:00007fcd04dfa478 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
[  823.061246] RAX: ffffffffffffffda RBX: 000000000000ae80 RCX: 00007fcd123540ab
[  823.061702] RDX: 0000000000000000 RSI: 000000000000ae80 RDI: 0000000000000010
[  823.062166] RBP: 00005626d1d13c20 R08: 0000000000000000 R09: 00000000ffffffff
[  823.062628] R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
[  823.063096] R13: 00005626d111fa6e R14: 0000000000000000 R15: 00007fcd04dff640
[  823.063579]  </TASK>
[  823.064024] BUG: sleeping function called from invalid context at include/linux/uaccess.h:69
[  823.064485] in_atomic(): 1, irqs_disabled(): 1, non_block: 0, pid: 8931, name: qemu-system-x86
[  823.064956] preempt_count: 1, expected: 0
[  823.065416] RCU nest depth: 0, expected: 0

It is likely a bad idea to read guest memory from recalc_intercepts()
but we don't actually have to, we can cache the whole partition assist
page and update it upon VMRUN (and after svm_set_nested_state()). For
VMX, this can be part of enlightened vmentry.

>  
>  	for (i = 0; i < MAX_INTERCEPT; i++)
>  		c->intercepts[i] |= g->intercepts[i];
> @@ -489,6 +493,17 @@ static void nested_save_pending_event_to_vmcb12(struct vcpu_svm *svm,
>  
>  static void nested_svm_transition_tlb_flush(struct kvm_vcpu *vcpu)
>  {
> +	/*
> +	 * KVM_REQ_HV_TLB_FLUSH flushes entries from either L1's VP_ID or
> +	 * L2's VP_ID upon request from the guest. Make sure we check for
> +	 * pending entries for the case when the request got misplaced (e.g.
> +	 * a transition from L2->L1 happened while processing L2 TLB flush
> +	 * request or vice versa). kvm_hv_vcpu_flush_tlb() will not flush
> +	 * anything if there are no requests in the corresponding buffer.
> +	 */
> +	if (to_hv_vcpu(vcpu))
> +		kvm_make_request(KVM_REQ_HV_TLB_FLUSH, vcpu);
> +
>  	/*
>  	 * TODO: optimize unconditional TLB flush/MMU sync.  A partial list of
>  	 * things to fix before this can be conditional:
> @@ -1409,6 +1424,7 @@ static int svm_check_nested_events(struct kvm_vcpu *vcpu)
>  int nested_svm_exit_special(struct vcpu_svm *svm)
>  {
>  	u32 exit_code = svm->vmcb->control.exit_code;
> +	struct kvm_vcpu *vcpu = &svm->vcpu;
>  
>  	switch (exit_code) {
>  	case SVM_EXIT_INTR:
> @@ -1427,6 +1443,13 @@ int nested_svm_exit_special(struct vcpu_svm *svm)
>  			return NESTED_EXIT_HOST;
>  		break;
>  	}
> +	case SVM_EXIT_VMMCALL:
> +		/* Hyper-V L2 TLB flush hypercall is handled by L0 */
> +		if (guest_hv_cpuid_has_l2_tlb_flush(vcpu) &&
> +		    nested_svm_l2_tlb_flush_enabled(vcpu) &&
> +		    kvm_hv_is_tlb_flush_hcall(vcpu))
> +			return NESTED_EXIT_HOST;
> +		break;
>  	default:
>  		break;
>  	}

-- 
Vitaly


  reply	other threads:[~2022-05-31 12:18 UTC|newest]

Thread overview: 39+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-05-27 15:55 [PATCH v5 00/37] KVM: x86: hyper-v: Fine-grained TLB flush + L2 TLB flush features Vitaly Kuznetsov
2022-05-27 15:55 ` [PATCH v5 01/37] KVM: x86: Rename 'enable_direct_tlbflush' to 'enable_l2_tlb_flush' Vitaly Kuznetsov
2022-05-27 15:55 ` [PATCH v5 02/37] KVM: x86: hyper-v: Resurrect dedicated KVM_REQ_HV_TLB_FLUSH flag Vitaly Kuznetsov
2022-05-27 15:55 ` [PATCH v5 03/37] KVM: x86: hyper-v: Introduce TLB flush fifo Vitaly Kuznetsov
2022-05-27 15:55 ` [PATCH v5 04/37] KVM: x86: hyper-v: Add helper to read hypercall data for array Vitaly Kuznetsov
2022-05-27 15:55 ` [PATCH v5 05/37] KVM: x86: hyper-v: Handle HVCALL_FLUSH_VIRTUAL_ADDRESS_LIST{,EX} calls gently Vitaly Kuznetsov
2022-05-27 15:55 ` [PATCH v5 06/37] KVM: x86: hyper-v: Expose support for extended gva ranges for flush hypercalls Vitaly Kuznetsov
2022-05-27 15:55 ` [PATCH v5 07/37] KVM: x86: Prepare kvm_hv_flush_tlb() to handle L2's GPAs Vitaly Kuznetsov
2022-05-27 15:55 ` [PATCH v5 08/37] x86/hyperv: Introduce HV_MAX_SPARSE_VCPU_BANKS/HV_VCPUS_PER_SPARSE_BANK constants Vitaly Kuznetsov
2022-05-27 15:55 ` [PATCH v5 09/37] KVM: x86: hyper-v: Use HV_MAX_SPARSE_VCPU_BANKS/HV_VCPUS_PER_SPARSE_BANK instead of raw '64' Vitaly Kuznetsov
2022-05-27 15:55 ` [PATCH v5 10/37] KVM: x86: hyper-v: Don't use sparse_set_to_vcpu_mask() in kvm_hv_send_ipi() Vitaly Kuznetsov
2022-05-27 15:55 ` [PATCH v5 11/37] KVM: x86: hyper-v: Create a separate fifo for L2 TLB flush Vitaly Kuznetsov
2022-05-27 15:55 ` [PATCH v5 12/37] KVM: x86: hyper-v: Use preallocated buffer in 'struct kvm_vcpu_hv' instead of on-stack 'sparse_banks' Vitaly Kuznetsov
2022-05-27 15:55 ` [PATCH v5 13/37] KVM: nVMX: Keep track of hv_vm_id/hv_vp_id when eVMCS is in use Vitaly Kuznetsov
2022-05-27 15:55 ` [PATCH v5 14/37] KVM: nSVM: Keep track of Hyper-V hv_vm_id/hv_vp_id Vitaly Kuznetsov
2022-05-27 15:55 ` [PATCH v5 15/37] KVM: x86: Introduce .hv_inject_synthetic_vmexit_post_tlb_flush() nested hook Vitaly Kuznetsov
2022-05-27 15:55 ` [PATCH v5 16/37] KVM: x86: hyper-v: Introduce kvm_hv_is_tlb_flush_hcall() Vitaly Kuznetsov
2022-05-27 15:55 ` [PATCH v5 17/37] KVM: x86: hyper-v: L2 TLB flush Vitaly Kuznetsov
2022-05-27 15:55 ` [PATCH v5 18/37] KVM: x86: hyper-v: Introduce fast guest_hv_cpuid_has_l2_tlb_flush() check Vitaly Kuznetsov
2022-05-27 15:55 ` [PATCH v5 19/37] x86/hyperv: Fix 'struct hv_enlightened_vmcs' definition Vitaly Kuznetsov
2022-05-27 15:55 ` [PATCH v5 20/37] KVM: nVMX: hyper-v: Enable L2 TLB flush Vitaly Kuznetsov
2022-05-27 15:55 ` [PATCH v5 21/37] KVM: nSVM: " Vitaly Kuznetsov
2022-05-31 12:18   ` Vitaly Kuznetsov [this message]
2022-05-27 15:55 ` [PATCH v5 22/37] KVM: x86: Expose Hyper-V L2 TLB flush feature Vitaly Kuznetsov
2022-05-27 15:55 ` [PATCH v5 23/37] KVM: selftests: Better XMM read/write helpers Vitaly Kuznetsov
2022-05-27 15:55 ` [PATCH v5 24/37] KVM: selftests: Move HYPERV_LINUX_OS_ID definition to a common header Vitaly Kuznetsov
2022-05-27 15:55 ` [PATCH v5 25/37] KVM: selftests: Move the function doing Hyper-V hypercall " Vitaly Kuznetsov
2022-05-27 15:55 ` [PATCH v5 26/37] KVM: selftests: Hyper-V PV IPI selftest Vitaly Kuznetsov
2022-05-27 15:55 ` [PATCH v5 27/37] KVM: selftests: Fill in vm->vpages_mapped bitmap in virt_map() too Vitaly Kuznetsov
2022-05-27 15:55 ` [PATCH v5 28/37] KVM: selftests: Export vm_vaddr_unused_gap() to make it possible to request unmapped ranges Vitaly Kuznetsov
2022-05-27 15:55 ` [PATCH v5 29/37] KVM: selftests: Export _vm_get_page_table_entry() Vitaly Kuznetsov
2022-05-27 15:55 ` [PATCH v5 30/37] KVM: selftests: Hyper-V PV TLB flush selftest Vitaly Kuznetsov
2022-05-27 15:55 ` [PATCH v5 31/37] KVM: selftests: Sync 'struct hv_enlightened_vmcs' definition with hyperv-tlfs.h Vitaly Kuznetsov
2022-05-27 15:55 ` [PATCH v5 32/37] KVM: selftests: nVMX: Allocate Hyper-V partition assist page Vitaly Kuznetsov
2022-05-27 15:55 ` [PATCH v5 33/37] KVM: selftests: nSVM: Allocate Hyper-V partition assist and VP assist pages Vitaly Kuznetsov
2022-05-27 15:55 ` [PATCH v5 34/37] KVM: selftests: Sync 'struct hv_vp_assist_page' definition with hyperv-tlfs.h Vitaly Kuznetsov
2022-05-27 15:55 ` [PATCH v5 35/37] KVM: selftests: evmcs_test: Introduce L2 TLB flush test Vitaly Kuznetsov
2022-05-27 15:55 ` [PATCH v5 36/37] KVM: selftests: Move Hyper-V VP assist page enablement out of evmcs.h Vitaly Kuznetsov
2022-05-27 15:55 ` [PATCH v5 37/37] KVM: selftests: hyperv_svm_test: Introduce L2 TLB flush test Vitaly Kuznetsov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=874k15q4jm.fsf@redhat.com \
    --to=vkuznets@redhat.com \
    --cc=jmattson@google.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-hyperv@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mikelley@microsoft.com \
    --cc=mlevitsk@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=seanjc@google.com \
    --cc=sidcha@amazon.de \
    --cc=wanpengli@tencent.com \
    --cc=yuan.yao@linux.intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.