diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-11-05 14:02:15 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-11-05 14:02:15 -0500 |
commit | b772b8e3abb9e14f39a97a5e318e466ce96d8daf (patch) | |
tree | 00b0de231ef45557ea74763d32b59a211ee5f9d4 | |
parent | 3131dc46729a60144acc90baebc55e8dce1516ff (diff) | |
parent | ec1e1b6109171d1890a437481c35b2b56d2327b8 (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.h | 4 | ||||
-rw-r--r-- | kernel/futex.c | 23 | ||||
-rw-r--r-- | kernel/watchdog_hld.c | 15 | ||||
-rw-r--r-- | tools/objtool/arch/x86/insn/gen-insn-attr-x86.awk | 1 |
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 @@ | |||
22 | static DEFINE_PER_CPU(bool, hard_watchdog_warn); | 23 | static DEFINE_PER_CPU(bool, hard_watchdog_warn); |
23 | static DEFINE_PER_CPU(bool, watchdog_nmi_touch); | 24 | static DEFINE_PER_CPU(bool, watchdog_nmi_touch); |
24 | static DEFINE_PER_CPU(struct perf_event *, watchdog_ev); | 25 | static DEFINE_PER_CPU(struct perf_event *, watchdog_ev); |
26 | static DEFINE_PER_CPU(struct perf_event *, dead_event); | ||
25 | static struct cpumask dead_events_mask; | 27 | static struct cpumask dead_events_mask; |
26 | 28 | ||
27 | static unsigned long hardlockup_allcpu_dumped; | 29 | static unsigned long hardlockup_allcpu_dumped; |
28 | static unsigned int watchdog_cpus; | 30 | static atomic_t watchdog_cpus = ATOMIC_INIT(0); |
29 | 31 | ||
30 | void arch_touch_nmi_watchdog(void) | 32 | void 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 | # |