From nobody Sun Apr 12 02:46:59 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 60333C3F6B0 for ; Wed, 3 Aug 2022 13:45:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231585AbiHCNpu (ORCPT ); Wed, 3 Aug 2022 09:45:50 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60492 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238062AbiHCNpp (ORCPT ); Wed, 3 Aug 2022 09:45:45 -0400 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 3672C5F47 for ; Wed, 3 Aug 2022 06:45:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1659534343; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=B7Bnmjr1GYcy9AYoYFcWJ7ZyYTvu6PCIgTkw/CC+mfQ=; b=Ho5KQ/aeu67qcmeIzEBvKT1lK7wDJa8p6m/PbFPfdWC/xHWav9VRJAXzB4Z3N1qERvbXVt sBYhPvgogAmSeelBOU5A2vdwZV56SxYkNIuFXjk/8dbdKmaZdhBQJ65xO4sI5zyVbpZ96n R7RBBcpZNnY6qOXKMHcFP+ksDtj4gW8= Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-606-kBTFjs_mMI2X5-iNfCnS1w-1; Wed, 03 Aug 2022 09:45:41 -0400 X-MC-Unique: kBTFjs_mMI2X5-iNfCnS1w-1 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 5B684382C96F; Wed, 3 Aug 2022 13:45:40 +0000 (UTC) Received: from fedora.redhat.com (unknown [10.40.195.93]) by smtp.corp.redhat.com (Postfix) with ESMTP id 100BC2166B26; Wed, 3 Aug 2022 13:45:37 +0000 (UTC) From: Vitaly Kuznetsov To: kvm@vger.kernel.org, Paolo Bonzini , Sean Christopherson Cc: Wanpeng Li , Jim Mattson , Michael Kelley , Siddharth Chandrasekaran , Yuan Yao , Maxim Levitsky , linux-hyperv@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v9 11/40] KVM: x86: hyper-v: Create a separate fifo for L2 TLB flush Date: Wed, 3 Aug 2022 15:45:37 +0200 Message-Id: <20220803134537.399208-1-vkuznets@redhat.com> In-Reply-To: <20220803134110.397885-1-vkuznets@redhat.com> References: <20220803134110.397885-1-vkuznets@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" To handle L2 TLB flush requests, KVM needs to use a separate fifo from regular (L1) Hyper-V TLB flush requests: e.g. when a request to flush something in L2 is made, the target vCPU can transition from L2 to L1, receive a request to flush a GVA for L1 and then try to enter L2 back. The first request needs to be processed at this point. Similarly, requests to flush GVAs in L1 must wait until L2 exits to L1. No functional change as KVM doesn't handle L2 TLB flush requests from L2 yet. Signed-off-by: Vitaly Kuznetsov --- arch/x86/include/asm/kvm_host.h | 8 +++++++- arch/x86/kvm/hyperv.c | 11 +++++++---- arch/x86/kvm/hyperv.h | 18 +++++++++++++++--- 3 files changed, 29 insertions(+), 8 deletions(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_hos= t.h index c16f74beb047..83c2331f7701 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -612,6 +612,12 @@ struct kvm_vcpu_hv_synic { */ #define KVM_HV_TLB_FLUSHALL_ENTRY ((u64)-1) =20 +enum hv_tlb_flush_fifos { + HV_L1_TLB_FLUSH_FIFO, + HV_L2_TLB_FLUSH_FIFO, + HV_NR_TLB_FLUSH_FIFOS, +}; + struct kvm_vcpu_hv_tlb_flush_fifo { spinlock_t write_lock; DECLARE_KFIFO(entries, u64, KVM_HV_TLB_FLUSH_FIFO_SIZE); @@ -637,7 +643,7 @@ struct kvm_vcpu_hv { u32 syndbg_cap_eax; /* HYPERV_CPUID_SYNDBG_PLATFORM_CAPABILITIES.EAX */ } cpuid_cache; =20 - struct kvm_vcpu_hv_tlb_flush_fifo tlb_flush_fifo; + struct kvm_vcpu_hv_tlb_flush_fifo tlb_flush_fifo[HV_NR_TLB_FLUSH_FIFOS]; }; =20 /* Xen HVM per vcpu emulation context */ diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c index b903c9de8d39..d27fb4a6d94b 100644 --- a/arch/x86/kvm/hyperv.c +++ b/arch/x86/kvm/hyperv.c @@ -956,8 +956,10 @@ static int kvm_hv_vcpu_init(struct kvm_vcpu *vcpu) =20 hv_vcpu->vp_index =3D vcpu->vcpu_idx; =20 - INIT_KFIFO(hv_vcpu->tlb_flush_fifo.entries); - spin_lock_init(&hv_vcpu->tlb_flush_fifo.write_lock); + for (i =3D 0; i < HV_NR_TLB_FLUSH_FIFOS; i++) { + INIT_KFIFO(hv_vcpu->tlb_flush_fifo[i].entries); + spin_lock_init(&hv_vcpu->tlb_flush_fifo[i].write_lock); + } =20 return 0; } @@ -1843,7 +1845,8 @@ static void hv_tlb_flush_enqueue(struct kvm_vcpu *vcp= u, u64 *entries, int count) if (!hv_vcpu) return; =20 - tlb_flush_fifo =3D &hv_vcpu->tlb_flush_fifo; + /* kvm_hv_flush_tlb() is not ready to handle requests for L2s yet */ + tlb_flush_fifo =3D &hv_vcpu->tlb_flush_fifo[HV_L1_TLB_FLUSH_FIFO]; =20 spin_lock_irqsave(&tlb_flush_fifo->write_lock, flags); =20 @@ -1880,7 +1883,7 @@ void kvm_hv_vcpu_flush_tlb(struct kvm_vcpu *vcpu) return; } =20 - tlb_flush_fifo =3D &hv_vcpu->tlb_flush_fifo; + tlb_flush_fifo =3D kvm_hv_get_tlb_flush_fifo(vcpu, is_guest_mode(vcpu)); =20 count =3D kfifo_out(&tlb_flush_fifo->entries, entries, KVM_HV_TLB_FLUSH_F= IFO_SIZE); =20 diff --git a/arch/x86/kvm/hyperv.h b/arch/x86/kvm/hyperv.h index e5b32266ff7d..8a902b59aa46 100644 --- a/arch/x86/kvm/hyperv.h +++ b/arch/x86/kvm/hyperv.h @@ -22,6 +22,7 @@ #define __ARCH_X86_KVM_HYPERV_H__ =20 #include +#include "x86.h" =20 /* * The #defines related to the synthetic debugger are required by KDNet, b= ut @@ -147,16 +148,27 @@ int kvm_vm_ioctl_hv_eventfd(struct kvm *kvm, struct k= vm_hyperv_eventfd *args); int kvm_get_hv_cpuid(struct kvm_vcpu *vcpu, struct kvm_cpuid2 *cpuid, struct kvm_cpuid_entry2 __user *entries); =20 +static inline struct kvm_vcpu_hv_tlb_flush_fifo *kvm_hv_get_tlb_flush_fifo= (struct kvm_vcpu *vcpu, + bool is_guest_mode) +{ + struct kvm_vcpu_hv *hv_vcpu =3D to_hv_vcpu(vcpu); + int i =3D is_guest_mode ? HV_L2_TLB_FLUSH_FIFO : + HV_L1_TLB_FLUSH_FIFO; + + /* KVM does not handle L2 TLB flush requests yet */ + WARN_ON_ONCE(i !=3D HV_L1_TLB_FLUSH_FIFO); + + return &hv_vcpu->tlb_flush_fifo[i]; +} =20 static inline void kvm_hv_vcpu_empty_flush_tlb(struct kvm_vcpu *vcpu) { struct kvm_vcpu_hv_tlb_flush_fifo *tlb_flush_fifo; - struct kvm_vcpu_hv *hv_vcpu =3D to_hv_vcpu(vcpu); =20 - if (!hv_vcpu || !kvm_check_request(KVM_REQ_HV_TLB_FLUSH, vcpu)) + if (!to_hv_vcpu(vcpu) || !kvm_check_request(KVM_REQ_HV_TLB_FLUSH, vcpu)) return; =20 - tlb_flush_fifo =3D &hv_vcpu->tlb_flush_fifo; + tlb_flush_fifo =3D kvm_hv_get_tlb_flush_fifo(vcpu, is_guest_mode(vcpu)); =20 kfifo_reset_out(&tlb_flush_fifo->entries); } --=20 2.35.3