aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-11-05 14:02:15 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2017-11-05 14:02:15 -0500
commitb772b8e3abb9e14f39a97a5e318e466ce96d8daf (patch)
tree00b0de231ef45557ea74763d32b59a211ee5f9d4
parent3131dc46729a60144acc90baebc55e8dce1516ff (diff)
parentec1e1b6109171d1890a437481c35b2b56d2327b8 (diff)
Merge branch 'core-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull core fixes from Ingo Molnar: - workaround for gcc asm handling - futex race fixes - objtool build warning fix - two watchdog fixes: a crash fix (revert) and a bug fix for /proc/sys/kernel/watchdog_thresh handling. * 'core-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: objtool: Prevent GCC from merging annotate_unreachable(), take 2 objtool: Resync objtool's instruction decoder source code copy with the kernel's latest version watchdog/hardlockup/perf: Use atomics to track in-use cpu counter watchdog/harclockup/perf: Revert a33d44843d45 ("watchdog/hardlockup/perf: Simplify deferred event destroy") futex: Fix more put_pi_state() vs. exit_pi_state_list() races
-rw-r--r--include/linux/compiler.h4
-rw-r--r--kernel/futex.c23
-rw-r--r--kernel/watchdog_hld.c15
-rw-r--r--tools/objtool/arch/x86/insn/gen-insn-attr-x86.awk1
4 files changed, 33 insertions, 10 deletions
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index fd8697aa4f73..202710420d6d 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -191,13 +191,13 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val,
191 asm("%c0:\n\t" \ 191 asm("%c0:\n\t" \
192 ".pushsection .discard.reachable\n\t" \ 192 ".pushsection .discard.reachable\n\t" \
193 ".long %c0b - .\n\t" \ 193 ".long %c0b - .\n\t" \
194 ".popsection\n\t" : : "i" (__LINE__)); \ 194 ".popsection\n\t" : : "i" (__COUNTER__)); \
195}) 195})
196#define annotate_unreachable() ({ \ 196#define annotate_unreachable() ({ \
197 asm("%c0:\n\t" \ 197 asm("%c0:\n\t" \
198 ".pushsection .discard.unreachable\n\t" \ 198 ".pushsection .discard.unreachable\n\t" \
199 ".long %c0b - .\n\t" \ 199 ".long %c0b - .\n\t" \
200 ".popsection\n\t" : : "i" (__LINE__)); \ 200 ".popsection\n\t" : : "i" (__COUNTER__)); \
201}) 201})
202#define ASM_UNREACHABLE \ 202#define ASM_UNREACHABLE \
203 "999:\n\t" \ 203 "999:\n\t" \
diff --git a/kernel/futex.c b/kernel/futex.c
index 0d638f008bb1..76ed5921117a 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -903,11 +903,27 @@ void exit_pi_state_list(struct task_struct *curr)
903 */ 903 */
904 raw_spin_lock_irq(&curr->pi_lock); 904 raw_spin_lock_irq(&curr->pi_lock);
905 while (!list_empty(head)) { 905 while (!list_empty(head)) {
906
907 next = head->next; 906 next = head->next;
908 pi_state = list_entry(next, struct futex_pi_state, list); 907 pi_state = list_entry(next, struct futex_pi_state, list);
909 key = pi_state->key; 908 key = pi_state->key;
910 hb = hash_futex(&key); 909 hb = hash_futex(&key);
910
911 /*
912 * We can race against put_pi_state() removing itself from the
913 * list (a waiter going away). put_pi_state() will first
914 * decrement the reference count and then modify the list, so
915 * its possible to see the list entry but fail this reference
916 * acquire.
917 *
918 * In that case; drop the locks to let put_pi_state() make
919 * progress and retry the loop.
920 */
921 if (!atomic_inc_not_zero(&pi_state->refcount)) {
922 raw_spin_unlock_irq(&curr->pi_lock);
923 cpu_relax();
924 raw_spin_lock_irq(&curr->pi_lock);
925 continue;
926 }
911 raw_spin_unlock_irq(&curr->pi_lock); 927 raw_spin_unlock_irq(&curr->pi_lock);
912 928
913 spin_lock(&hb->lock); 929 spin_lock(&hb->lock);
@@ -918,8 +934,10 @@ void exit_pi_state_list(struct task_struct *curr)
918 * task still owns the PI-state: 934 * task still owns the PI-state:
919 */ 935 */
920 if (head->next != next) { 936 if (head->next != next) {
937 /* retain curr->pi_lock for the loop invariant */
921 raw_spin_unlock(&pi_state->pi_mutex.wait_lock); 938 raw_spin_unlock(&pi_state->pi_mutex.wait_lock);
922 spin_unlock(&hb->lock); 939 spin_unlock(&hb->lock);
940 put_pi_state(pi_state);
923 continue; 941 continue;
924 } 942 }
925 943
@@ -927,9 +945,8 @@ void exit_pi_state_list(struct task_struct *curr)
927 WARN_ON(list_empty(&pi_state->list)); 945 WARN_ON(list_empty(&pi_state->list));
928 list_del_init(&pi_state->list); 946 list_del_init(&pi_state->list);
929 pi_state->owner = NULL; 947 pi_state->owner = NULL;
930 raw_spin_unlock(&curr->pi_lock);
931 948
932 get_pi_state(pi_state); 949 raw_spin_unlock(&curr->pi_lock);
933 raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock); 950 raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock);
934 spin_unlock(&hb->lock); 951 spin_unlock(&hb->lock);
935 952
diff --git a/kernel/watchdog_hld.c b/kernel/watchdog_hld.c
index 4583feb66393..e449a23e9d59 100644
--- a/kernel/watchdog_hld.c
+++ b/kernel/watchdog_hld.c
@@ -13,6 +13,7 @@
13#define pr_fmt(fmt) "NMI watchdog: " fmt 13#define pr_fmt(fmt) "NMI watchdog: " fmt
14 14
15#include <linux/nmi.h> 15#include <linux/nmi.h>
16#include <linux/atomic.h>
16#include <linux/module.h> 17#include <linux/module.h>
17#include <linux/sched/debug.h> 18#include <linux/sched/debug.h>
18 19
@@ -22,10 +23,11 @@
22static DEFINE_PER_CPU(bool, hard_watchdog_warn); 23static DEFINE_PER_CPU(bool, hard_watchdog_warn);
23static DEFINE_PER_CPU(bool, watchdog_nmi_touch); 24static DEFINE_PER_CPU(bool, watchdog_nmi_touch);
24static DEFINE_PER_CPU(struct perf_event *, watchdog_ev); 25static DEFINE_PER_CPU(struct perf_event *, watchdog_ev);
26static DEFINE_PER_CPU(struct perf_event *, dead_event);
25static struct cpumask dead_events_mask; 27static struct cpumask dead_events_mask;
26 28
27static unsigned long hardlockup_allcpu_dumped; 29static unsigned long hardlockup_allcpu_dumped;
28static unsigned int watchdog_cpus; 30static atomic_t watchdog_cpus = ATOMIC_INIT(0);
29 31
30void arch_touch_nmi_watchdog(void) 32void arch_touch_nmi_watchdog(void)
31{ 33{
@@ -189,7 +191,8 @@ void hardlockup_detector_perf_enable(void)
189 if (hardlockup_detector_event_create()) 191 if (hardlockup_detector_event_create())
190 return; 192 return;
191 193
192 if (!watchdog_cpus++) 194 /* use original value for check */
195 if (!atomic_fetch_inc(&watchdog_cpus))
193 pr_info("Enabled. Permanently consumes one hw-PMU counter.\n"); 196 pr_info("Enabled. Permanently consumes one hw-PMU counter.\n");
194 197
195 perf_event_enable(this_cpu_read(watchdog_ev)); 198 perf_event_enable(this_cpu_read(watchdog_ev));
@@ -204,8 +207,10 @@ void hardlockup_detector_perf_disable(void)
204 207
205 if (event) { 208 if (event) {
206 perf_event_disable(event); 209 perf_event_disable(event);
210 this_cpu_write(watchdog_ev, NULL);
211 this_cpu_write(dead_event, event);
207 cpumask_set_cpu(smp_processor_id(), &dead_events_mask); 212 cpumask_set_cpu(smp_processor_id(), &dead_events_mask);
208 watchdog_cpus--; 213 atomic_dec(&watchdog_cpus);
209 } 214 }
210} 215}
211 216
@@ -219,7 +224,7 @@ void hardlockup_detector_perf_cleanup(void)
219 int cpu; 224 int cpu;
220 225
221 for_each_cpu(cpu, &dead_events_mask) { 226 for_each_cpu(cpu, &dead_events_mask) {
222 struct perf_event *event = per_cpu(watchdog_ev, cpu); 227 struct perf_event *event = per_cpu(dead_event, cpu);
223 228
224 /* 229 /*
225 * Required because for_each_cpu() reports unconditionally 230 * Required because for_each_cpu() reports unconditionally
@@ -227,7 +232,7 @@ void hardlockup_detector_perf_cleanup(void)
227 */ 232 */
228 if (event) 233 if (event)
229 perf_event_release_kernel(event); 234 perf_event_release_kernel(event);
230 per_cpu(watchdog_ev, cpu) = NULL; 235 per_cpu(dead_event, cpu) = NULL;
231 } 236 }
232 cpumask_clear(&dead_events_mask); 237 cpumask_clear(&dead_events_mask);
233} 238}
diff --git a/tools/objtool/arch/x86/insn/gen-insn-attr-x86.awk b/tools/objtool/arch/x86/insn/gen-insn-attr-x86.awk
index a3d2c62fd805..b02a36b2c14f 100644
--- a/tools/objtool/arch/x86/insn/gen-insn-attr-x86.awk
+++ b/tools/objtool/arch/x86/insn/gen-insn-attr-x86.awk
@@ -1,4 +1,5 @@
1#!/bin/awk -f 1#!/bin/awk -f
2# SPDX-License-Identifier: GPL-2.0
2# gen-insn-attr-x86.awk: Instruction attribute table generator 3# gen-insn-attr-x86.awk: Instruction attribute table generator
3# Written by Masami Hiramatsu <mhiramat@redhat.com> 4# Written by Masami Hiramatsu <mhiramat@redhat.com>
4# 5#