From patchwork Wed Nov 1 20:58:53 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Waiman Long X-Patchwork-Id: 10037071 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 936BB604D7 for ; Wed, 1 Nov 2017 21:01:51 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8DB0328C08 for ; Wed, 1 Nov 2017 21:01:51 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 8C00B28C00; Wed, 1 Nov 2017 21:01:51 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id CE11928C0B for ; Wed, 1 Nov 2017 21:01:50 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1eA06j-0004DH-E9; Wed, 01 Nov 2017 20:59:29 +0000 Received: from mail6.bemta6.messagelabs.com ([193.109.254.103]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1eA06i-0004D0-6x for xen-devel@lists.xenproject.org; Wed, 01 Nov 2017 20:59:28 +0000 Received: from [85.158.143.35] by server-5.bemta-6.messagelabs.com id E9/9E-29911-FA53AF95; Wed, 01 Nov 2017 20:59:27 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFprNIsWRWlGSWpSXmKPExsVysWW7jO4601+ RBo29phbft0xmcmD0OPzhCksAYxRrZl5SfkUCa8aEy4eYCw4bVqyfPpelgfGoZhcjF4eQwGwm iY79i5m7GDk5WATsJTpvnGUEsRkFyiQ2tbxggbBzJF58PsQG0bCCUeLLtC2sIAk2ATWJP7c6W UESIgL9jBJ9z/YygTjMAk+YJf6tfMoEUiUsEC0x69E0VogVqhI71l8FW8Er4CjRePwjWJxTwE liyspZ7CC2EFD86KInYDUSAtoSF9ofsYAMlRDoY5R4vH0R8wRG/gWMDKsY1YtTi8pSi3RN9JK KMtMzSnITM3N0DQ3M9HJTi4sT01NzEpOK9ZLzczcxAoOIAQh2MHZf9j/EKMnBpCTKq3n/Z6QQ X1J+SmVGYnFGfFFpTmrxIUYZDg4lCV4Jk1+RQoJFqempFWmZOcBwhklLcPAoifAqgaR5iwsSc 4sz0yFSpxiNOY5tuvyHiePZzNcNzEIsefl5qVLivPuNgUoFQEozSvPgBsHi7BKjrJQwLyPQaU I8BalFuZklqPKvGMU5GJWEedlAFvJk5pXA7XsFdAoT0CleEj9ATilJREhJNTAeUOJ/eUBvntI dhmvCkxVO8OboppU0X1159ewG+xmvzl0N5Hs06eJcTqnzv7bOTrP481LufMw/obSWGZkiIiI3 WS7MqE6+s0N9S93Xdk6tBUIHfjaG9Z/Uzp23+esuw5V9dVMfC84pCG1cvbtj/5pdsY7be6XM+ 725lC+anufs2uPNttGS5+1tJZbijERDLeai4kQAfmJ0U64CAAA= X-Env-Sender: longman@redhat.com X-Msg-Ref: server-13.tower-21.messagelabs.com!1509569965!74135866!1 X-Originating-IP: [209.132.183.28] X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: VHJ1c3RlZCBJUDogMjA5LjEzMi4xODMuMjggPT4gNTQwNjQ=\n X-StarScan-Received: X-StarScan-Version: 9.4.45; banners=-,-,- X-VirusChecked: Checked Received: (qmail 28575 invoked from network); 1 Nov 2017 20:59:26 -0000 Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by server-13.tower-21.messagelabs.com with DHE-RSA-AES256-GCM-SHA384 encrypted SMTP; 1 Nov 2017 20:59:26 -0000 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id E04AC5F7AC; Wed, 1 Nov 2017 20:59:24 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com E04AC5F7AC Received: from llong.com (dhcp-17-221.bos.redhat.com [10.18.17.221]) by smtp.corp.redhat.com (Postfix) with ESMTP id 171E760C9F; Wed, 1 Nov 2017 20:59:23 +0000 (UTC) From: Waiman Long To: Thomas Gleixner , Ingo Molnar , "H. Peter Anvin" , Jonathan Corbet Date: Wed, 1 Nov 2017 16:58:53 -0400 Message-Id: <1509569934-4919-2-git-send-email-longman@redhat.com> In-Reply-To: <1509569934-4919-1-git-send-email-longman@redhat.com> References: <1509569934-4919-1-git-send-email-longman@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Wed, 01 Nov 2017 20:59:25 +0000 (UTC) Cc: Juergen Gross , Rusty Russell , kvm@vger.kernel.org, =?UTF-8?q?Radim=20Kr=C4=8Dm=C3=A1=C5=99?= , Peter Zijlstra , x86@kernel.org, linux-kernel@vger.kernel.org, virtualization@lists.linux-foundation.org, Waiman Long , Paolo Bonzini , xen-devel@lists.xenproject.org, Alok Kataria , Boris Ostrovsky Subject: [Xen-devel] [PATCH-tip v2 1/2] x86/paravirt: Add kernel parameter to choose paravirt lock type X-BeenThere: xen-devel@lists.xen.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: xen-devel-bounces@lists.xen.org Sender: "Xen-devel" X-Virus-Scanned: ClamAV using ClamSMTP Currently, there are 3 different lock types that can be chosen for the x86 architecture: - qspinlock - pvqspinlock - unfair lock One of the above lock types will be chosen at boot time depending on a number of different factors. Ideally, the hypervisors should be able to pick the best performing lock type for the current VM configuration. That is not currently the case as the performance of each lock type are affected by many different factors like the number of vCPUs in the VM, the amount vCPU overcommitment, the CPU type and so on. Generally speaking, unfair lock performs well for VMs with a small number of vCPUs. Native qspinlock may perform better than pvqspinlock if there is vCPU pinning and there is no vCPU over-commitment. This patch adds a new kernel parameter to allow administrator to choose the paravirt spinlock type to be used. VM administrators can experiment with the different lock types and choose one that can best suit their need, if they want to. Hypervisor developers can also use that to experiment with different lock types so that they can come up with a better algorithm to pick the best lock type. The hypervisor paravirt spinlock code will override this new parameter in determining if pvqspinlock should be used. The parameter, however, will override Xen's xen_nopvspin in term of disabling unfair lock. Signed-off-by: Waiman Long --- Documentation/admin-guide/kernel-parameters.txt | 7 +++++ arch/x86/include/asm/paravirt.h | 9 ++++++ arch/x86/kernel/kvm.c | 3 ++ arch/x86/kernel/paravirt.c | 40 ++++++++++++++++++++++++- arch/x86/xen/spinlock.c | 12 ++++---- 5 files changed, 65 insertions(+), 6 deletions(-) diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index f7df49d..c98d9c7 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -3275,6 +3275,13 @@ [KNL] Number of legacy pty's. Overwrites compiled-in default number. + pvlock_type= [X86,PV_OPS] + Specify the paravirt spinlock type to be used. + Options are: + queued - native queued spinlock + pv - paravirt queued spinlock + unfair - simple TATAS unfair lock + quiet [KNL] Disable most log messages r128= [HW,DRM] diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h index 12deec7..c8f9ad9 100644 --- a/arch/x86/include/asm/paravirt.h +++ b/arch/x86/include/asm/paravirt.h @@ -690,6 +690,15 @@ static __always_inline bool pv_vcpu_is_preempted(long cpu) #endif /* SMP && PARAVIRT_SPINLOCKS */ +enum pv_spinlock_type { + locktype_auto = 0, + locktype_queued = 1, + locktype_paravirt = 2, + locktype_unfair = 4, +}; + +extern enum pv_spinlock_type pv_spinlock_type; + #ifdef CONFIG_X86_32 #define PV_SAVE_REGS "pushl %ecx; pushl %edx;" #define PV_RESTORE_REGS "popl %edx; popl %ecx;" diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c index 8bb9594..3faee63 100644 --- a/arch/x86/kernel/kvm.c +++ b/arch/x86/kernel/kvm.c @@ -646,6 +646,9 @@ void __init kvm_spinlock_init(void) if (!kvm_para_has_feature(KVM_FEATURE_PV_UNHALT)) return; + if (pv_spinlock_type & (locktype_queued|locktype_unfair)) + return; + __pv_init_lock_hash(); pv_lock_ops.queued_spin_lock_slowpath = __pv_queued_spin_lock_slowpath; pv_lock_ops.queued_spin_unlock = PV_CALLEE_SAVE(__pv_queued_spin_unlock); diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c index 041096b..aee6756 100644 --- a/arch/x86/kernel/paravirt.c +++ b/arch/x86/kernel/paravirt.c @@ -115,11 +115,48 @@ unsigned paravirt_patch_jmp(void *insnbuf, const void *target, return 5; } +/* + * The kernel argument "pvlock_type=" can be used to explicitly specify + * which type of spinlocks to be used. Currently, there are 3 options: + * 1) queued - the native queued spinlock + * 2) pv - the paravirt queued spinlock (if CONFIG_PARAVIRT_SPINLOCKS) + * 3) unfair - the simple TATAS unfair lock + * + * If this argument is not specified, the kernel will automatically choose + * an appropriate one depending on X86_FEATURE_HYPERVISOR and hypervisor + * specific settings. + */ +enum pv_spinlock_type __read_mostly pv_spinlock_type = locktype_auto; + +static int __init pvlock_setup(char *s) +{ + if (!s) + return -EINVAL; + + if (!strcmp(s, "queued")) + pv_spinlock_type = locktype_queued; + else if (!strcmp(s, "pv")) + pv_spinlock_type = locktype_paravirt; + else if (!strcmp(s, "unfair")) + pv_spinlock_type = locktype_unfair; + else + return -EINVAL; + + pr_info("PV lock type = %s (%d)\n", s, pv_spinlock_type); + return 0; +} + +early_param("pvlock_type", pvlock_setup); + DEFINE_STATIC_KEY_TRUE(virt_spin_lock_key); void __init native_pv_lock_init(void) { - if (!static_cpu_has(X86_FEATURE_HYPERVISOR)) + if (pv_spinlock_type == locktype_unfair) + return; + + if (!static_cpu_has(X86_FEATURE_HYPERVISOR) || + (pv_spinlock_type == locktype_queued)) static_branch_disable(&virt_spin_lock_key); } @@ -473,3 +510,4 @@ struct pv_mmu_ops pv_mmu_ops __ro_after_init = { EXPORT_SYMBOL (pv_mmu_ops); EXPORT_SYMBOL_GPL(pv_info); EXPORT_SYMBOL (pv_irq_ops); +EXPORT_SYMBOL (pv_spinlock_type); diff --git a/arch/x86/xen/spinlock.c b/arch/x86/xen/spinlock.c index 1e1462d..d5f79ac 100644 --- a/arch/x86/xen/spinlock.c +++ b/arch/x86/xen/spinlock.c @@ -81,8 +81,9 @@ void xen_init_lock_cpu(int cpu) int irq; char *name; - if (!xen_pvspin) { - if (cpu == 0) + if (!xen_pvspin || + (pv_spinlock_type & (locktype_queued|locktype_unfair))) { + if ((cpu == 0) && !pv_spinlock_type) static_branch_disable(&virt_spin_lock_key); return; } @@ -109,7 +110,8 @@ void xen_init_lock_cpu(int cpu) void xen_uninit_lock_cpu(int cpu) { - if (!xen_pvspin) + if (!xen_pvspin || + (pv_spinlock_type & (locktype_queued|locktype_unfair))) return; unbind_from_irqhandler(per_cpu(lock_kicker_irq, cpu), NULL); @@ -130,8 +132,8 @@ void xen_uninit_lock_cpu(int cpu) */ void __init xen_init_spinlocks(void) { - - if (!xen_pvspin) { + if (!xen_pvspin || + (pv_spinlock_type & (locktype_queued|locktype_unfair))) { printk(KERN_DEBUG "xen: PV spinlocks disabled\n"); return; }