linux-hyperv.vger.kernel.org archive mirror
 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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).