Received: by 2002:a05:6602:18e:0:0:0:0 with SMTP id m14csp2378361ioo; Sat, 28 May 2022 11:47:34 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzoOiYe91SvpB9n9FAz/oU3H/Wo63n6PniDuffHnUb6jrKQPVrmg2xamRlHbXSbGvuoXgFt X-Received: by 2002:a05:6402:b09:b0:42d:bd80:11ac with SMTP id bm9-20020a0564020b0900b0042dbd8011acmr3006946edb.244.1653763654555; Sat, 28 May 2022 11:47:34 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1653763654; cv=none; d=google.com; s=arc-20160816; b=Z1vCoOdA3MwdFf4j+MjLJyBeLzbwF0ZmK1hkbAqu+R7kTqFPdFhBJ8XERodGuEQTIN 9xuJytaQkoF6H5UxXf/kNL4Y2ev39PtRWfpK1Kv3peEH/8DOtM+aoy2rhZiLOkSSxZzK ErhJ0dbQf0VMeRJHoI0/OG27+p/eU7Dfuye2paM0wMO/wzbfHRS1Ez5wYbdJjtj1YYBm 0JuuOJPDc2OoDDPRmIhkXrEpktUNC9XjzDrVBKPJuVAvUVVSGpldnsNCjTh0/3elSPnS 5j8XFr9vivKu7vJHp7fFZc1OOmQGJcFJR973D8/H+0zBNXrvtGjwpUunrbBaHwf8NLnw mOOA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:user-agent:in-reply-to:content-disposition :mime-version:references:message-id:subject:cc:to:from:date :dkim-signature; bh=tmt9uHcjPfZH7tTfGTZZ+5Ka1gVgaafxT8XWLfjODEw=; b=CNN7kZ3pq1QBqA+2kWffAZ6XeEPb7WC3YbsptIs9zxQ1GHUujk8HSu4rQwllTh5yrp bmIxNMcNcAbv3h10Q4LD7d/2gapnVEO6cGnQHZFgl6BfQ8mnF81OqjPUUk6GCVZVEWrT aKHpQEtquMbnH6H7QRffqkolY3EJOz1Ehg0akx5xUNlVctFZkJwlp7CUoz1EEIrpW2dV 6HD/wS1GI1zA6qgp+zQPlNso/K5M2pJI0z0zhncdmPLxa1i/Da0vSo9RIkq3ZAruR3kS CTJP6/HY5O0Ui6QIDVxu0FFBrPNj8IVzxnN9LAOiNE6FwW8Iuphpj8kO19SyHmlF1KSt XHHA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=nqk0AfCs; spf=softfail (google.com: domain of transitioning linux-kernel-owner@vger.kernel.org does not designate 23.128.96.19 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Return-Path: Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net. [23.128.96.19]) by mx.google.com with ESMTPS id h15-20020aa7de0f000000b0042abbf2c3c8si6208633edv.465.2022.05.28.11.47.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 28 May 2022 11:47:34 -0700 (PDT) Received-SPF: softfail (google.com: domain of transitioning linux-kernel-owner@vger.kernel.org does not designate 23.128.96.19 as permitted sender) client-ip=23.128.96.19; Authentication-Results: mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=nqk0AfCs; spf=softfail (google.com: domain of transitioning linux-kernel-owner@vger.kernel.org does not designate 23.128.96.19 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 50EB22D1D8; Sat, 28 May 2022 11:37:05 -0700 (PDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240226AbiE0Ijj (ORCPT + 99 others); Fri, 27 May 2022 04:39:39 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59084 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229946AbiE0Ijh (ORCPT ); Fri, 27 May 2022 04:39:37 -0400 Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DA6FCAB; Fri, 27 May 2022 01:39:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1653640774; x=1685176774; h=date:from:to:cc:subject:message-id:references: mime-version:in-reply-to; bh=nUtExxzslm+WHneUQWLHkDWMpNsTjMfZCy8Z14gS70o=; b=nqk0AfCsq3cISUdzFsF4g0SWGWEr2+O9RSJuKFRn6wAOYRoCnd2kKMA9 4DxOsHq3re3UYrAWKTOw4NIoNMMxm1sOKNUTz1k+8CyAU73WzSL1dnrsw FU9ps1c5qWG+tVDFSroAVI3gqbZd/wOeiScJ3ZTYnyoS9Ok2WgkEccD6N AzxReF1aPFD3eqMZnB0xL6kXLh5HFpuxnVlNTP3odHNjCwbh9FjojJP7b tdC5FlmVfo13P8yYBl8qSGat1uzoyImMBx3Yw7U5D62/ICfQnITVuePVi Iq45TWKkulqFGt0ubnM+4EMmIM1VOUM+424TqC0TeKZsUI7352hJi/920 w==; X-IronPort-AV: E=McAfee;i="6400,9594,10359"; a="274523414" X-IronPort-AV: E=Sophos;i="5.91,254,1647327600"; d="scan'208";a="274523414" Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 May 2022 01:39:34 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.91,254,1647327600"; d="scan'208";a="560647894" Received: from yy-desk-7060.sh.intel.com (HELO localhost) ([10.239.159.76]) by orsmga002.jf.intel.com with ESMTP; 27 May 2022 01:39:31 -0700 Date: Fri, 27 May 2022 16:39:30 +0800 From: Yuan Yao To: Vitaly Kuznetsov Cc: kvm@vger.kernel.org, Paolo Bonzini , Sean Christopherson , Maxim Levitsky , Wanpeng Li , Jim Mattson , Michael Kelley , Siddharth Chandrasekaran , linux-hyperv@vger.kernel.org, linux-kernel@vger.kernel.org Subject: Re: [PATCH v4 05/37] KVM: x86: hyper-v: Handle HVCALL_FLUSH_VIRTUAL_ADDRESS_LIST{,EX} calls gently Message-ID: <20220527083930.okdenkvxephom5wq@yy-desk-7060> References: <20220525090133.1264239-1-vkuznets@redhat.com> <20220525090133.1264239-6-vkuznets@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20220525090133.1264239-6-vkuznets@redhat.com> User-Agent: NeoMutt/20171215 X-Spam-Status: No, score=-2.7 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,RDNS_NONE,SPF_HELO_NONE,T_SCC_BODY_TEXT_LINE autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Wed, May 25, 2022 at 11:01:01AM +0200, Vitaly Kuznetsov wrote: > Currently, HVCALL_FLUSH_VIRTUAL_ADDRESS_LIST{,EX} calls are handled > the exact same way as HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE{,EX}: by > flushing the whole VPID and this is sub-optimal. Switch to handling > these requests with 'flush_tlb_gva()' hooks instead. Use the newly > introduced TLB flush fifo to queue the requests. > > Signed-off-by: Vitaly Kuznetsov > --- > arch/x86/kvm/hyperv.c | 102 +++++++++++++++++++++++++++++++++++++----- > 1 file changed, 90 insertions(+), 12 deletions(-) > > diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c > index 762b0b699fdf..576749973727 100644 > --- a/arch/x86/kvm/hyperv.c > +++ b/arch/x86/kvm/hyperv.c > @@ -1806,32 +1806,84 @@ static u64 kvm_get_sparse_vp_set(struct kvm *kvm, struct kvm_hv_hcall *hc, > sparse_banks, consumed_xmm_halves, offset); > } > > -static void hv_tlb_flush_enqueue(struct kvm_vcpu *vcpu) > +static int kvm_hv_get_tlb_flush_entries(struct kvm *kvm, struct kvm_hv_hcall *hc, u64 entries[], > + int consumed_xmm_halves, gpa_t offset) > +{ > + return kvm_hv_get_hc_data(kvm, hc, hc->rep_cnt, hc->rep_cnt, > + entries, consumed_xmm_halves, offset); > +} > + > +static void hv_tlb_flush_enqueue(struct kvm_vcpu *vcpu, u64 *entries, int count) > { > struct kvm_vcpu_hv_tlb_flush_fifo *tlb_flush_fifo; > struct kvm_vcpu_hv *hv_vcpu = to_hv_vcpu(vcpu); > u64 entry = KVM_HV_TLB_FLUSHALL_ENTRY; > + unsigned long flags; > > if (!hv_vcpu) > return; > > tlb_flush_fifo = &hv_vcpu->tlb_flush_fifo; > > - kfifo_in_spinlocked(&tlb_flush_fifo->entries, &entry, 1, &tlb_flush_fifo->write_lock); > + spin_lock_irqsave(&tlb_flush_fifo->write_lock, flags); > + > + /* > + * All entries should fit on the fifo leaving one free for 'flush all' > + * entry in case another request comes in. In case there's not enough > + * space, just put 'flush all' entry there. > + */ > + if (count && entries && count < kfifo_avail(&tlb_flush_fifo->entries)) { > + WARN_ON(kfifo_in(&tlb_flush_fifo->entries, entries, count) != count); > + goto out_unlock; > + } > + > + /* > + * Note: full fifo always contains 'flush all' entry, no need to check the > + * return value. > + */ > + kfifo_in(&tlb_flush_fifo->entries, &entry, 1); > + > +out_unlock: > + spin_unlock_irqrestore(&tlb_flush_fifo->write_lock, flags); > } > > void kvm_hv_vcpu_flush_tlb(struct kvm_vcpu *vcpu) Where's the caller to this kvm_hv_vcpu_flush_tlb() ? I didn't see th caller in patch 1-22 and remains are self-testing patches, any thing I missed ? > { > struct kvm_vcpu_hv_tlb_flush_fifo *tlb_flush_fifo; > struct kvm_vcpu_hv *hv_vcpu = to_hv_vcpu(vcpu); > + u64 entries[KVM_HV_TLB_FLUSH_FIFO_SIZE]; > + int i, j, count; > + gva_t gva; > > - kvm_vcpu_flush_tlb_guest(vcpu); > - > - if (!hv_vcpu) > + if (!tdp_enabled || !hv_vcpu) { > + kvm_vcpu_flush_tlb_guest(vcpu); > return; > + } > > tlb_flush_fifo = &hv_vcpu->tlb_flush_fifo; > > + count = kfifo_out(&tlb_flush_fifo->entries, entries, KVM_HV_TLB_FLUSH_FIFO_SIZE); > + > + for (i = 0; i < count; i++) { > + if (entries[i] == KVM_HV_TLB_FLUSHALL_ENTRY) > + goto out_flush_all; > + > + /* > + * Lower 12 bits of 'address' encode the number of additional > + * pages to flush. > + */ > + gva = entries[i] & PAGE_MASK; > + for (j = 0; j < (entries[i] & ~PAGE_MASK) + 1; j++) > + static_call(kvm_x86_flush_tlb_gva)(vcpu, gva + j * PAGE_SIZE); > + > + ++vcpu->stat.tlb_flush; > + } > + goto out_empty_ring; > + > +out_flush_all: > + kvm_vcpu_flush_tlb_guest(vcpu); > + > +out_empty_ring: > kfifo_reset_out(&tlb_flush_fifo->entries); > } > > @@ -1841,11 +1893,21 @@ static u64 kvm_hv_flush_tlb(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc) > struct hv_tlb_flush_ex flush_ex; > struct hv_tlb_flush flush; > DECLARE_BITMAP(vcpu_mask, KVM_MAX_VCPUS); > + /* > + * Normally, there can be no more than 'KVM_HV_TLB_FLUSH_FIFO_SIZE' > + * entries on the TLB flush fifo. The last entry, however, needs to be > + * always left free for 'flush all' entry which gets placed when > + * there is not enough space to put all the requested entries. > + */ > + u64 __tlb_flush_entries[KVM_HV_TLB_FLUSH_FIFO_SIZE - 1]; > + u64 *tlb_flush_entries; > u64 valid_bank_mask; > u64 sparse_banks[KVM_HV_MAX_SPARSE_VCPU_SET_BITS]; > struct kvm_vcpu *v; > unsigned long i; > bool all_cpus; > + int consumed_xmm_halves = 0; > + gpa_t data_offset; > > /* > * The Hyper-V TLFS doesn't allow more than 64 sparse banks, e.g. the > @@ -1861,10 +1923,12 @@ static u64 kvm_hv_flush_tlb(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc) > flush.address_space = hc->ingpa; > flush.flags = hc->outgpa; > flush.processor_mask = sse128_lo(hc->xmm[0]); > + consumed_xmm_halves = 1; > } else { > if (unlikely(kvm_read_guest(kvm, hc->ingpa, > &flush, sizeof(flush)))) > return HV_STATUS_INVALID_HYPERCALL_INPUT; > + data_offset = sizeof(flush); > } > > trace_kvm_hv_flush_tlb(flush.processor_mask, > @@ -1888,10 +1952,12 @@ static u64 kvm_hv_flush_tlb(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc) > flush_ex.flags = hc->outgpa; > memcpy(&flush_ex.hv_vp_set, > &hc->xmm[0], sizeof(hc->xmm[0])); > + consumed_xmm_halves = 2; > } else { > if (unlikely(kvm_read_guest(kvm, hc->ingpa, &flush_ex, > sizeof(flush_ex)))) > return HV_STATUS_INVALID_HYPERCALL_INPUT; > + data_offset = sizeof(flush_ex); > } > > trace_kvm_hv_flush_tlb_ex(flush_ex.hv_vp_set.valid_bank_mask, > @@ -1907,25 +1973,37 @@ static u64 kvm_hv_flush_tlb(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc) > return HV_STATUS_INVALID_HYPERCALL_INPUT; > > if (all_cpus) > - goto do_flush; > + goto read_flush_entries; > > if (!hc->var_cnt) > goto ret_success; > > - if (kvm_get_sparse_vp_set(kvm, hc, sparse_banks, 2, > - offsetof(struct hv_tlb_flush_ex, > - hv_vp_set.bank_contents))) > + if (kvm_get_sparse_vp_set(kvm, hc, sparse_banks, consumed_xmm_halves, > + data_offset)) > + return HV_STATUS_INVALID_HYPERCALL_INPUT; > + data_offset += hc->var_cnt * sizeof(sparse_banks[0]); > + consumed_xmm_halves += hc->var_cnt; > + } > + > +read_flush_entries: > + if (hc->code == HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE || > + hc->code == HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE_EX || > + hc->rep_cnt > ARRAY_SIZE(__tlb_flush_entries)) { > + tlb_flush_entries = NULL; > + } else { > + if (kvm_hv_get_tlb_flush_entries(kvm, hc, __tlb_flush_entries, > + consumed_xmm_halves, data_offset)) > return HV_STATUS_INVALID_HYPERCALL_INPUT; > + tlb_flush_entries = __tlb_flush_entries; > } > > -do_flush: > /* > * vcpu->arch.cr3 may not be up-to-date for running vCPUs so we can't > * analyze it here, flush TLB regardless of the specified address space. > */ > if (all_cpus) { > kvm_for_each_vcpu(i, v, kvm) > - hv_tlb_flush_enqueue(v); > + hv_tlb_flush_enqueue(v, tlb_flush_entries, hc->rep_cnt); > > kvm_make_all_cpus_request(kvm, KVM_REQ_HV_TLB_FLUSH); > } else { > @@ -1935,7 +2013,7 @@ static u64 kvm_hv_flush_tlb(struct kvm_vcpu *vcpu, struct kvm_hv_hcall *hc) > v = kvm_get_vcpu(kvm, i); > if (!v) > continue; > - hv_tlb_flush_enqueue(v); > + hv_tlb_flush_enqueue(v, tlb_flush_entries, hc->rep_cnt); > } > > kvm_make_vcpus_request_mask(kvm, KVM_REQ_HV_TLB_FLUSH, vcpu_mask); > -- > 2.35.3 >