Received: by 2002:a05:6602:18e:0:0:0:0 with SMTP id m14csp2436781ioo; Sat, 28 May 2022 13:38:53 -0700 (PDT) X-Google-Smtp-Source: ABdhPJybadZdo6tRd1a5qshOhc5b9+MgHNfn74qxb4DABbGET1whSKCICqrpZysdhEWD9pXD6mQv X-Received: by 2002:a17:903:240c:b0:153:c452:f282 with SMTP id e12-20020a170903240c00b00153c452f282mr47651522plo.88.1653770333677; Sat, 28 May 2022 13:38:53 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1653770333; cv=none; d=google.com; s=arc-20160816; b=sQxMJ3Tkr94enMfG21iyVJYyDuvEOr/gS8dw60jmNWDbJwch1ezkrnmPalko34l0bA GyNFRhaFNIYXywWYGpDCwMwAbnTRz9B4z7eAXjlUunMIT3Bt4/53Wk0nIqRoMOy8w/6v n0FitzEEStEgUbA9/JiOCdGrIG+PE7SyicuGeQldiWnpNoBfz96Vg3ygEXYneK62YDTK yMEFiLiPM3uSJUPv2AmQZmO61tpHRyT2Zrk7BjGnw9v73t8fJlaSzGQgl8N5PyVKmYmS K41fXTtLTAoQFLVEorRjb9j2ChbWFVY1HXRY+6N+2aTF79ycDDpa0nHfiazZO/Q3aCQo qm1A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:mime-version:message-id:date:references :in-reply-to:subject:cc:to:from:dkim-signature; bh=cwtSE0b0Kap2XlkQ7keZo11av4qenVk73lRytgMZ82Q=; b=p7mB4gigQwqQfjMP3MydIX/ZwEj2yR0wRmsRZcMRQ9kXJIQ1J5fbsYP8K4YmlHDDsX GbGKNEMIsx51+I4rcvNilJ3yMfZVrbFCddYIYLO4p3SAt4SOihYJEsP6Ruh2aUkZEpFu etAzj08juqYaU0MzHf3Jj4slBI+7G0re8KjQYYB5ICSahhVv1Y/9b0qLbFCwuVRXcxZw 8TjrEBgQL89D+W7j/xLe18Zq0kbs+enDBqOKc7dJXLaxYYy1FbDO4YMuSvWTxi5KjUMD W25NVYgw/TxkJqY40ucYr7OsE3fNT0w8NTDtbQ5OLHXoOm7m2yV7WK9poauJy/lKdmJa Owiw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=WUv7wGLf; 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=redhat.com Return-Path: Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net. [23.128.96.19]) by mx.google.com with ESMTPS id d7-20020a170903230700b0015e93c5d222si10673366plh.186.2022.05.28.13.38.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 28 May 2022 13:38:53 -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=@redhat.com header.s=mimecast20190719 header.b=WUv7wGLf; 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=redhat.com Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 32D0660AA9; Sat, 28 May 2022 12:41:09 -0700 (PDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1352718AbiE0Lus (ORCPT + 99 others); Fri, 27 May 2022 07:50:48 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57130 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1351894AbiE0Lrt (ORCPT ); Fri, 27 May 2022 07:47:49 -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 7D7C414AC84 for ; Fri, 27 May 2022 04:43:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1653651793; 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: in-reply-to:in-reply-to:references:references; bh=cwtSE0b0Kap2XlkQ7keZo11av4qenVk73lRytgMZ82Q=; b=WUv7wGLfTl2gBdmnyu6IHnkFP15FbKIw1p6sytzcdaE9iJVK0qUqHyrwLvoQ+nr0M/srUz YZs2dNahBmeuHcvf5PfKU36yk6vlgQQWUtrg2PeeUDcFDs6nmOeZKXK95hXJjhEcRX4gPv KNqxj2wDtixjAwImIVaaPnNWlZ3oNVg= Received: from mail-ej1-f69.google.com (mail-ej1-f69.google.com [209.85.218.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-182-GQIvWwN0OX-_hA9quNDGCw-1; Fri, 27 May 2022 07:43:12 -0400 X-MC-Unique: GQIvWwN0OX-_hA9quNDGCw-1 Received: by mail-ej1-f69.google.com with SMTP id i7-20020a170906850700b006fec53a78c3so2325075ejx.1 for ; Fri, 27 May 2022 04:43:11 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:in-reply-to:references:date :message-id:mime-version; bh=cwtSE0b0Kap2XlkQ7keZo11av4qenVk73lRytgMZ82Q=; b=DpudMdZiTGXDeR9FSGUSQMnMTRRO8JH160TowicmuaZorLgNRn5ZvX+wtBu3Ch+eZB dhD3+QTEjxJeY2kkOLBFS8z8SSPjfSadc15ETFGqFQ+SGu7D1xA7Af2dqm5tn+Yubgq6 RAyybJTP+OoFNkuOuQrZnby2+IIUZSw07g0V39jmbomlOA+dwKlMewA8hAEtd6UbYLSO o1WiFNlIIrkQ/1/mY5/lDZOv4SJSttd9PdiwCjGupNkfbFLfd6eb2MbeWrYCbk2eypUj x8HZG7MmakEWfTqNv56IsGYBnH7VobMPrC1m0vIi2+hWk6BcMxK0hujawQPKqNQlYnA+ aGvQ== X-Gm-Message-State: AOAM530txhRAIlbszcSLylCJRRbQyNvDW3G+JZVGlwO7sNxCAKtMVFsX MWj4RKMWlpb9v1qiUPsBSBGtxfgIY/V52s+29xuFt6W8g4WfnIBo3QIU4B691rjfCJDdwXKnJb9 OBLtQ82Us6ytqgk94ZAfXZPbI234yLbx6RK6iUVVEzTrjoyCPSqYtxSvmRZZ9igfQnk0mvatGrs kk X-Received: by 2002:a17:906:7217:b0:6fe:9448:6142 with SMTP id m23-20020a170906721700b006fe94486142mr37290936ejk.241.1653651790940; Fri, 27 May 2022 04:43:10 -0700 (PDT) X-Received: by 2002:a17:906:7217:b0:6fe:9448:6142 with SMTP id m23-20020a170906721700b006fe94486142mr37290901ejk.241.1653651790624; Fri, 27 May 2022 04:43:10 -0700 (PDT) Received: from fedora (nat-2.ign.cz. [91.219.240.2]) by smtp.gmail.com with ESMTPSA id bq8-20020a170906d0c800b006feb71acbb3sm1386134ejb.105.2022.05.27.04.43.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 27 May 2022 04:43:10 -0700 (PDT) From: Vitaly Kuznetsov To: Yuan Yao 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 In-Reply-To: <20220527083930.okdenkvxephom5wq@yy-desk-7060> References: <20220525090133.1264239-1-vkuznets@redhat.com> <20220525090133.1264239-6-vkuznets@redhat.com> <20220527083930.okdenkvxephom5wq@yy-desk-7060> Date: Fri, 27 May 2022 13:43:09 +0200 Message-ID: <87ilprqjzm.fsf@redhat.com> MIME-Version: 1.0 Content-Type: text/plain X-Spam-Status: No, score=-2.8 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,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 Yuan Yao writes: > 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 ? No, I screwed up. It was present in kvm_service_local_tlb_flush_requests() in previous versions but somehow disappeared. This also means that I haven't tested this properly. Thanks for catching this! v5 is coming to rescue! > >> { >> 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 >> > -- Vitaly