From: marc.zyngier@arm.com (Marc Zyngier)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v2 3/4] jump_label: Provide hotplug context variants
Date: Wed, 2 Aug 2017 16:02:16 +0100 [thread overview]
Message-ID: <8ffa1548-7aa5-1d1f-e0f3-a862aad2534b@arm.com> (raw)
In-Reply-To: <20170802143748.dmthd3hvbq5pbelt@hirez.programming.kicks-ass.net>
On 02/08/17 15:37, Peter Zijlstra wrote:
> 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 <marc.zyngier@arm.com>
>> ---
>> 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 at redhat.com
>
> This patch now looks like so.
>
> ---
> Subject: jump_label: Provide hotplug context variants
> From: Marc Zyngier <marc.zyngier@arm.com>
> 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 at lists.infradead.org
> Cc: Leo Yan <leo.yan@linaro.org>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
> Link: http://lkml.kernel.org/r/20170801080257.5056-4-marc.zyngier at 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);
>
I've just tried this one of the affected systems, and it booted just
fine. So thumbs up from me.
Thanks again,
M.
--
Jazz is not dead. It just smells funny...
next prev parent reply other threads:[~2017-08-02 15:02 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-08-01 8:02 [PATCH v2 0/4] Working around CPU hotplug and static keys locking Marc Zyngier
2017-08-01 8:02 ` [PATCH v2 1/4] jump_label: Move cpu hotplug locking Marc Zyngier
2017-08-01 8:02 ` [PATCH v2 2/4] jump_label: Split out code under the hotplug lock Marc Zyngier
2017-08-01 8:02 ` [PATCH v2 3/4] jump_label: Provide hotplug context variants Marc Zyngier
2017-08-02 14:37 ` Peter Zijlstra
2017-08-02 15:02 ` Marc Zyngier [this message]
2017-08-01 8:02 ` [PATCH v2 4/4] clocksource/arm_arch_timer: Use static_branch_enable_cpuslocked() Marc Zyngier
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=8ffa1548-7aa5-1d1f-e0f3-a862aad2534b@arm.com \
--to=marc.zyngier@arm.com \
--cc=linux-arm-kernel@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).