From patchwork Wed Aug 2 14:37:48 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Zijlstra X-Patchwork-Id: 9876867 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 A1363602BC for ; Wed, 2 Aug 2017 14:38:03 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8F0D2287B4 for ; Wed, 2 Aug 2017 14:38:03 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 82045287CB; Wed, 2 Aug 2017 14:38:03 +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=-1.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id D5C41287B4 for ; Wed, 2 Aug 2017 14:38:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:In-Reply-To:MIME-Version:References: Message-ID:Subject:To:From:Date:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=WjMcL/2H+Dc/Dci3oZnlWH1ApFmzu3gJMND2+Xvuqx4=; b=MVRVriDqBcOgGk Vp6Vo3trbrhCINYlIBmSUZkka1HwF7uwVID+IUNN1khn1IThiYvTuNyD7UcoHwc4bVAwSpl53rddu HvYzb5l3sXIoJ6PVlXCGDWZK6AAAaBY+61EGF3cYSTraA6G+gXV+OE7D8M0S47C/9e8RljipRZ8pv 1uULYv498oQvk2r84kfX1bVPBsI3SKSVSt2iBlV5YIU1fHmhAmbxbJ5n7jBVytEMujJanda0e5iZm LhS+nBqoMXG5KFbh23n72LXNbUcjS9P3oloKFmEORjOxXAw8OgKO5EAtJvRLQf0z/IEnU7yTpzr3T a0+QgOgCxYfgzc6507SA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1dcumZ-0005FX-L5; Wed, 02 Aug 2017 14:37:55 +0000 Received: from merlin.infradead.org ([2001:8b0:10b:1231::1]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1dcumY-0005FG-60 for linux-arm-kernel@bombadil.infradead.org; Wed, 02 Aug 2017 14:37:54 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=merlin.20170209; h=In-Reply-To:Content-Type:MIME-Version: References:Message-ID:Subject:Cc:To:From:Date:Sender:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=rNNQ4Wdimm32wPh0eYsYs6NsE32kd1+WV2m0QeXY64g=; b=0Y2mTnukAOTBmADYw5ZV81ias xUAN71b1D7W9HPaXKHg4nVhwiIE9FzzYPieN4OXZGzL8MpXa+9J/VTORNExkKQ8YX8TaHHKdSJRyP z2ydrP033HRtIgDfqOxLJdWQ7M9lEE1RenKSYPXXSdZHemr4HpGnav0aZm2HL4i4wM2TxWAQpTVC2 NHubg4/33DxTsnsmebgzKZS/nFA1DOa4KohcZVVyYmmArGuaDRNB2HJAUywJRf6rM4m44Mite4pUg JKvvLNv3lh+V6elvkbY7kPDYjBpZWd2qGVhImkRFJ1eeaSUqLr+7c0R8uFl8MXyAtFTz/Wf6gPQz9 hBHroKgRA==; Received: from j217100.upc-j.chello.nl ([24.132.217.100] helo=hirez.programming.kicks-ass.net) by merlin.infradead.org with esmtpsa (Exim 4.87 #1 (Red Hat Linux)) id 1dcumU-0007Ud-6H; Wed, 02 Aug 2017 14:37:50 +0000 Received: by hirez.programming.kicks-ass.net (Postfix, from userid 1000) id 26D60202E0F6E; Wed, 2 Aug 2017 16:37:48 +0200 (CEST) Date: Wed, 2 Aug 2017 16:37:48 +0200 From: Peter Zijlstra To: Marc Zyngier Subject: Re: [PATCH v2 3/4] jump_label: Provide hotplug context variants Message-ID: <20170802143748.dmthd3hvbq5pbelt@hirez.programming.kicks-ass.net> References: <20170801080257.5056-1-marc.zyngier@arm.com> <20170801080257.5056-4-marc.zyngier@arm.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20170801080257.5056-4-marc.zyngier@arm.com> User-Agent: NeoMutt/20170609 (1.8.3) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Paolo Bonzini , Thomas Gleixner , linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Leo Yan Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP On Tue, Aug 01, 2017 at 09:02:56AM +0100, Marc Zyngier wrote: > As using the normal static key API under the hotplug lock is > pretty much impossible, let's provide a variant of some of them > that require the hotplug lock to have already been taken. > > These function are only meant to be used in CPU hotplug callbacks. > > Signed-off-by: Marc Zyngier > --- > Documentation/static-keys.txt | 15 +++++++++++++++ > include/linux/jump_label.h | 11 +++++++++-- > kernel/jump_label.c | 20 ++++++++++++++++++++ > 3 files changed, 44 insertions(+), 2 deletions(-) I stuffed them in my locking/core branch on top of Paolo's patches: https://lkml.kernel.org/r/1501601046-35683-1-git-send-email-pbonzini@redhat.com This patch now looks like so. --- Subject: jump_label: Provide hotplug context variants From: Marc Zyngier Date: Tue, 1 Aug 2017 09:02:56 +0100 As using the normal static key API under the hotplug lock is pretty much impossible, let's provide a variant of some of them that require the hotplug lock to have already been taken. These function are only meant to be used in CPU hotplug callbacks. Cc: linux-arm-kernel@lists.infradead.org Cc: Leo Yan Cc: Thomas Gleixner Signed-off-by: Marc Zyngier Signed-off-by: Peter Zijlstra (Intel) Link: http://lkml.kernel.org/r/20170801080257.5056-4-marc.zyngier@arm.com --- Documentation/static-keys.txt | 15 +++++++++++++++ include/linux/jump_label.h | 11 +++++++++-- kernel/jump_label.c | 22 ++++++++++++++++++---- 3 files changed, 42 insertions(+), 6 deletions(-) --- a/Documentation/static-keys.txt +++ b/Documentation/static-keys.txt @@ -154,6 +154,21 @@ and 'static_key_count()'. In general, i should be protected with the same mutex used around the enable/disable or increment/decrement function. +Note that switching branches results in some locks being taken, +particularly the CPU hotplug lock (in order to avoid races against +CPUs being brought in the kernel whilst the kernel is getting +patched). Calling the static key API from within a hotplug notifier is +thus a sure deadlock recipe. In order to still allow use of the +functionnality, the following functions are provided: + + static_key_enable_cpuslocked() + static_key_disable_cpuslocked() + static_branch_enable_cpuslocked() + static_branch_disable_cpuslocked() + +These functions are *not* general purpose, and must only be used when +you really know that you're in the above context, and no other. + Where an array of keys is required, it can be defined as:: DEFINE_STATIC_KEY_ARRAY_TRUE(keys, count); --- a/include/linux/jump_label.h +++ b/include/linux/jump_label.h @@ -163,6 +163,8 @@ extern void jump_label_apply_nops(struct extern int static_key_count(struct static_key *key); extern void static_key_enable(struct static_key *key); extern void static_key_disable(struct static_key *key); +extern void static_key_enable_cpuslocked(struct static_key *key); +extern void static_key_disable_cpuslocked(struct static_key *key); /* * We should be using ATOMIC_INIT() for initializing .enabled, but @@ -254,6 +256,9 @@ static inline void static_key_disable(st atomic_set(&key->enabled, 0); } +#define static_key_enable_cpuslocked(k) static_key_enable((k)) +#define static_key_disable_cpuslocked(k) static_key_disable((k)) + #define STATIC_KEY_INIT_TRUE { .enabled = ATOMIC_INIT(1) } #define STATIC_KEY_INIT_FALSE { .enabled = ATOMIC_INIT(0) } @@ -415,8 +420,10 @@ extern bool ____wrong_branch_error(void) * Normal usage; boolean enable/disable. */ -#define static_branch_enable(x) static_key_enable(&(x)->key) -#define static_branch_disable(x) static_key_disable(&(x)->key) +#define static_branch_enable(x) static_key_enable(&(x)->key) +#define static_branch_disable(x) static_key_disable(&(x)->key) +#define static_branch_enable_cpuslocked(x) static_key_enable_cpuslocked(&(x)->key) +#define static_branch_disable_cpuslocked(x) static_key_disable_cpuslocked(&(x)->key) #endif /* __ASSEMBLY__ */ --- a/kernel/jump_label.c +++ b/kernel/jump_label.c @@ -126,15 +126,15 @@ void static_key_slow_inc(struct static_k } EXPORT_SYMBOL_GPL(static_key_slow_inc); -void static_key_enable(struct static_key *key) +void static_key_enable_cpuslocked(struct static_key *key) { STATIC_KEY_CHECK_USE(); + if (atomic_read(&key->enabled) > 0) { WARN_ON_ONCE(atomic_read(&key->enabled) != 1); return; } - cpus_read_lock(); jump_label_lock(); if (atomic_read(&key->enabled) == 0) { atomic_set(&key->enabled, -1); @@ -145,23 +145,37 @@ void static_key_enable(struct static_key atomic_set_release(&key->enabled, 1); } jump_label_unlock(); +} +EXPORT_SYMBOL_GPL(static_key_enable_cpuslocked); + +void static_key_enable(struct static_key *key) +{ + cpus_read_lock(); + static_key_enable_cpuslocked(key); cpus_read_unlock(); } EXPORT_SYMBOL_GPL(static_key_enable); -void static_key_disable(struct static_key *key) +void static_key_disable_cpuslocked(struct static_key *key) { STATIC_KEY_CHECK_USE(); + if (atomic_read(&key->enabled) != 1) { WARN_ON_ONCE(atomic_read(&key->enabled) != 0); return; } - cpus_read_lock(); jump_label_lock(); if (atomic_cmpxchg(&key->enabled, 1, 0)) jump_label_update(key); jump_label_unlock(); +} +EXPORT_SYMBOL_GPL(static_key_disable_cpuslocked); + +void static_key_disable(struct static_key *key) +{ + cpus_read_lock(); + static_key_disable_cpuslocked(key); cpus_read_unlock(); } EXPORT_SYMBOL_GPL(static_key_disable);