summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>2016-06-03 11:25:41 +0200
committerSebastian Andrzej Siewior <bigeasy@linutronix.de>2016-06-03 11:25:41 +0200
commitb296f297d1ef2fb8e24b1d9d14120c2fe431c2ee (patch)
tree4c79e3ee6efe360665b358a88047ee7ef8318232
parentb888c44961779f0d86ac8a8e3b417fa45eceb4ea (diff)
download4.9-rt-patches-b296f297d1ef2fb8e24b1d9d14120c2fe431c2ee.tar.gz
[ANNOUNCE] 4.6.1-rt3
Dear RT folks! I'm pleased to announce the v4.6.1-rt3 patch set. Changes since v4.6.1-rt2: - On return from interrupt on ARM we could schedule with lazy preempt count > 0 under some circumstances. It isn't toxic but it shouldn't happen. Noticed by Thomas Gleixner. - The way the preempt counter is accessed on non-x86 architectures allowed the compiler to reorder the code slightly. This led to decrementing the preempt counter, checking for the need resched bit followed by writing the counter back. An interrupt between the last two steps will lead to a missing preemption point and thus high latencies. Patch by Peter Zijlstra. - The recorded preemption counter in event trace points (such as raw_syscall_entry) are off by one because each trace point increments the counter. This has been corrected. - It is now ensured that there are no attempts to print from IRQ or NMI context. On certain events such as hard-lockup-detector we would attempt to grab sleeping locks. - Allow lru_add_drain_all() to perform its work remotely. Patch by Luiz Capitulino and Rik van Riel. Known issues - CPU hotplug got a little better but can deadlock. The delta patch against 4.6.1-rt2 is appended below and can be found here: https://cdn.kernel.org/pub/linux/kernel/projects/rt/4.6/incr/patch-4.6.1-rt2-rt3.patch.xz You can get this release via the git tree at: git://git.kernel.org/pub/scm/linux/kernel/git/rt/linux-rt-devel.git v4.6.1-rt3 The RT patch against 4.6.1 can be found here: https://cdn.kernel.org/pub/linux/kernel/projects/rt/4.6/patch-4.6.1-rt3.patch.xz The split quilt queue is available at: https://cdn.kernel.org/pub/linux/kernel/projects/rt/4.6/patches-4.6.1-rt3.tar.xz Sebastian Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-rw-r--r--patches/arm-lazy-preempt-correct-resched-condition.patch31
-rw-r--r--patches/kernel-printk-Don-t-try-to-print-from-IRQ-NMI-region.patch41
-rw-r--r--patches/kernel-rtmutex-only-warn-once-on-a-try-lock-from-bad.patch26
-rw-r--r--patches/locallock-add-local_lock_on.patch31
-rw-r--r--patches/localversion.patch2
-rw-r--r--patches/mm-perform-lru_add_drain_all-remotely.patch101
-rw-r--r--patches/sched-preempt-Fix-preempt_count-manipulations.patch51
-rw-r--r--patches/series7
-rw-r--r--patches/signals-allow-rt-tasks-to-cache-one-sigqueue-struct.patch2
-rw-r--r--patches/trace-correct-off-by-one-while-recording-the-trace-e.patch49
10 files changed, 339 insertions, 2 deletions
diff --git a/patches/arm-lazy-preempt-correct-resched-condition.patch b/patches/arm-lazy-preempt-correct-resched-condition.patch
new file mode 100644
index 00000000000000..b7f4f1a19cca31
--- /dev/null
+++ b/patches/arm-lazy-preempt-correct-resched-condition.patch
@@ -0,0 +1,31 @@
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Tue, 24 May 2016 12:56:38 +0200
+Subject: [PATCH] arm: lazy preempt: correct resched condition
+
+If we get out of preempt_schedule_irq() then we check for NEED_RESCHED
+and call the former function again if set because the preemption counter
+has be zero at this point.
+However the counter for lazy-preempt might not be zero therefore we have
+to check the counter before looking at the need_resched_lazy flag.
+
+Cc: stable-rt@vger.kernel.org
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ arch/arm/kernel/entry-armv.S | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/arch/arm/kernel/entry-armv.S
++++ b/arch/arm/kernel/entry-armv.S
+@@ -244,7 +244,11 @@ ENDPROC(__irq_svc)
+ bne 1b
+ tst r0, #_TIF_NEED_RESCHED_LAZY
+ reteq r8 @ go again
+- b 1b
++ ldr r0, [tsk, #TI_PREEMPT_LAZY] @ get preempt lazy count
++ teq r0, #0 @ if preempt lazy count != 0
++ beq 1b
++ ret r8 @ go again
++
+ #endif
+
+ __und_fault:
diff --git a/patches/kernel-printk-Don-t-try-to-print-from-IRQ-NMI-region.patch b/patches/kernel-printk-Don-t-try-to-print-from-IRQ-NMI-region.patch
new file mode 100644
index 00000000000000..589c691cc46ee0
--- /dev/null
+++ b/patches/kernel-printk-Don-t-try-to-print-from-IRQ-NMI-region.patch
@@ -0,0 +1,41 @@
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Thu, 19 May 2016 17:45:27 +0200
+Subject: [PATCH] kernel/printk: Don't try to print from IRQ/NMI region
+
+On -RT we try to acquire sleeping locks which might lead to warnings
+from lockdep or a warn_on() from spin_try_lock() (which is a rtmutex on
+RT).
+We don't print in general from a IRQ off region so we should not try
+this via console_unblank() / bust_spinlocks() as well.
+
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ kernel/printk/printk.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -1502,6 +1502,11 @@ static void call_console_drivers(int lev
+ if (!console_drivers)
+ return;
+
++ if (IS_ENABLED(CONFIG_PREEMPT_RT_BASE)) {
++ if (in_irq() || in_nmi())
++ return;
++ }
++
+ migrate_disable();
+ for_each_console(con) {
+ if (exclusive_console && con != exclusive_console)
+@@ -2434,6 +2439,11 @@ void console_unblank(void)
+ {
+ struct console *c;
+
++ if (IS_ENABLED(CONFIG_PREEMPT_RT_BASE)) {
++ if (in_irq() || in_nmi())
++ return;
++ }
++
+ /*
+ * console_unblank can no longer be called in interrupt context unless
+ * oops_in_progress is set to 1..
diff --git a/patches/kernel-rtmutex-only-warn-once-on-a-try-lock-from-bad.patch b/patches/kernel-rtmutex-only-warn-once-on-a-try-lock-from-bad.patch
new file mode 100644
index 00000000000000..f279849d57722d
--- /dev/null
+++ b/patches/kernel-rtmutex-only-warn-once-on-a-try-lock-from-bad.patch
@@ -0,0 +1,26 @@
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Thu, 19 May 2016 17:12:34 +0200
+Subject: [PATCH] kernel/rtmutex: only warn once on a try lock from bad
+ context
+
+One warning should be enough to get one motivated to fix this. It is
+possible that this happens more than once and so starts flooding the
+output. Later the prints will be suppressed so we only get half of it.
+Depending on the console system used it might not be helpfull.
+
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ kernel/locking/rtmutex.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/kernel/locking/rtmutex.c
++++ b/kernel/locking/rtmutex.c
+@@ -1479,7 +1479,7 @@ EXPORT_SYMBOL_GPL(rt_mutex_timed_lock);
+ int __sched rt_mutex_trylock(struct rt_mutex *lock)
+ {
+ #ifdef CONFIG_PREEMPT_RT_FULL
+- if (WARN_ON(in_irq() || in_nmi()))
++ if (WARN_ON_ONCE(in_irq() || in_nmi()))
+ #else
+ if (WARN_ON(in_irq() || in_nmi() || in_serving_softirq()))
+ #endif
diff --git a/patches/locallock-add-local_lock_on.patch b/patches/locallock-add-local_lock_on.patch
new file mode 100644
index 00000000000000..0c714f2192f59e
--- /dev/null
+++ b/patches/locallock-add-local_lock_on.patch
@@ -0,0 +1,31 @@
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Fri, 27 May 2016 15:11:51 +0200
+Subject: [PATCH] locallock: add local_lock_on()
+
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ include/linux/locallock.h | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/include/linux/locallock.h
++++ b/include/linux/locallock.h
+@@ -60,6 +60,9 @@ static inline void __local_lock(struct l
+ #define local_lock(lvar) \
+ do { __local_lock(&get_local_var(lvar)); } while (0)
+
++#define local_lock_on(lvar, cpu) \
++ do { __local_lock(&per_cpu(lvar, cpu)); } while (0)
++
+ static inline int __local_trylock(struct local_irq_lock *lv)
+ {
+ if (lv->owner != current && spin_trylock_local(&lv->lock)) {
+@@ -98,6 +101,9 @@ static inline void __local_unlock(struct
+ put_local_var(lvar); \
+ } while (0)
+
++#define local_unlock_on(lvar, cpu) \
++ do { __local_unlock(&per_cpu(lvar, cpu)); } while (0)
++
+ static inline void __local_lock_irq(struct local_irq_lock *lv)
+ {
+ spin_lock_irqsave(&lv->lock, lv->flags);
diff --git a/patches/localversion.patch b/patches/localversion.patch
index 279489a1d1455d..e36eb4b6666a7e 100644
--- a/patches/localversion.patch
+++ b/patches/localversion.patch
@@ -10,4 +10,4 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
--- /dev/null
+++ b/localversion-rt
@@ -0,0 +1 @@
-+-rt2
++-rt3
diff --git a/patches/mm-perform-lru_add_drain_all-remotely.patch b/patches/mm-perform-lru_add_drain_all-remotely.patch
new file mode 100644
index 00000000000000..ac2befde1f6b1a
--- /dev/null
+++ b/patches/mm-perform-lru_add_drain_all-remotely.patch
@@ -0,0 +1,101 @@
+From: Luiz Capitulino <lcapitulino@redhat.com>
+Date: Fri, 27 May 2016 15:03:28 +0200
+Subject: [PATCH] mm: perform lru_add_drain_all() remotely
+
+lru_add_drain_all() works by scheduling lru_add_drain_cpu() to run
+on all CPUs that have non-empty LRU pagevecs and then waiting for
+the scheduled work to complete. However, workqueue threads may never
+have the chance to run on a CPU that's running a SCHED_FIFO task.
+This causes lru_add_drain_all() to block forever.
+
+This commit solves this problem by changing lru_add_drain_all()
+to drain the LRU pagevecs of remote CPUs. This is done by grabbing
+swapvec_lock and calling lru_add_drain_cpu().
+
+PS: This is based on an idea and initial implementation by
+ Rik van Riel.
+
+Signed-off-by: Rik van Riel <riel@redhat.com>
+Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ mm/swap.c | 37 ++++++++++++++++++++++++++++++-------
+ 1 file changed, 30 insertions(+), 7 deletions(-)
+
+--- a/mm/swap.c
++++ b/mm/swap.c
+@@ -596,9 +596,15 @@ void lru_add_drain_cpu(int cpu)
+ unsigned long flags;
+
+ /* No harm done if a racing interrupt already did this */
++#ifdef CONFIG_PREEMPT_RT_BASE
++ local_lock_irqsave_on(rotate_lock, flags, cpu);
++ pagevec_move_tail(pvec);
++ local_unlock_irqrestore_on(rotate_lock, flags, cpu);
++#else
+ local_lock_irqsave(rotate_lock, flags);
+ pagevec_move_tail(pvec);
+ local_unlock_irqrestore(rotate_lock, flags);
++#endif
+ }
+
+ pvec = &per_cpu(lru_deactivate_file_pvecs, cpu);
+@@ -666,12 +672,32 @@ void lru_add_drain(void)
+ local_unlock_cpu(swapvec_lock);
+ }
+
++
++#ifdef CONFIG_PREEMPT_RT_BASE
++static inline void remote_lru_add_drain(int cpu, struct cpumask *has_work)
++{
++ local_lock_on(swapvec_lock, cpu);
++ lru_add_drain_cpu(cpu);
++ local_unlock_on(swapvec_lock, cpu);
++}
++
++#else
++
+ static void lru_add_drain_per_cpu(struct work_struct *dummy)
+ {
+ lru_add_drain();
+ }
+
+ static DEFINE_PER_CPU(struct work_struct, lru_add_drain_work);
++static inline void remote_lru_add_drain(int cpu, struct cpumask *has_work)
++{
++ struct work_struct *work = &per_cpu(lru_add_drain_work, cpu);
++
++ INIT_WORK(work, lru_add_drain_per_cpu);
++ schedule_work_on(cpu, work);
++ cpumask_set_cpu(cpu, has_work);
++}
++#endif
+
+ void lru_add_drain_all(void)
+ {
+@@ -684,21 +710,18 @@ void lru_add_drain_all(void)
+ cpumask_clear(&has_work);
+
+ for_each_online_cpu(cpu) {
+- struct work_struct *work = &per_cpu(lru_add_drain_work, cpu);
+-
+ if (pagevec_count(&per_cpu(lru_add_pvec, cpu)) ||
+ pagevec_count(&per_cpu(lru_rotate_pvecs, cpu)) ||
+ pagevec_count(&per_cpu(lru_deactivate_file_pvecs, cpu)) ||
+ pagevec_count(&per_cpu(lru_deactivate_pvecs, cpu)) ||
+- need_activate_page_drain(cpu)) {
+- INIT_WORK(work, lru_add_drain_per_cpu);
+- schedule_work_on(cpu, work);
+- cpumask_set_cpu(cpu, &has_work);
+- }
++ need_activate_page_drain(cpu))
++ remote_lru_add_drain(cpu, &has_work);
+ }
+
++#ifndef CONFIG_PREEMPT_RT_BASE
+ for_each_cpu(cpu, &has_work)
+ flush_work(&per_cpu(lru_add_drain_work, cpu));
++#endif
+
+ put_online_cpus();
+ mutex_unlock(&lock);
diff --git a/patches/sched-preempt-Fix-preempt_count-manipulations.patch b/patches/sched-preempt-Fix-preempt_count-manipulations.patch
new file mode 100644
index 00000000000000..c46c0980d8f34e
--- /dev/null
+++ b/patches/sched-preempt-Fix-preempt_count-manipulations.patch
@@ -0,0 +1,51 @@
+From: Peter Zijlstra <peterz@infradead.org>
+Date: Mon, 16 May 2016 15:01:11 +0200
+Subject: [PATCH] sched,preempt: Fix preempt_count manipulations
+
+Vikram reported that his ARM64 compiler managed to 'optimize' away the
+preempt_count manipulations in code like:
+
+ preempt_enable_no_resched();
+ put_user();
+ preempt_disable();
+
+Irrespective of that fact that that is horrible code that should be
+fixed for many reasons, it does highlight a deficiency in the generic
+preempt_count manipulators. As it is never right to combine/elide
+preempt_count manipulations like this.
+
+Therefore sprinkle some volatile in the two generic accessors to
+ensure the compiler is aware of the fact that the preempt_count is
+observed outside of the regular program-order view and thus cannot be
+optimized away like this.
+
+x86; the only arch not using the generic code is not affected as we
+do all this in asm in order to use the segment base per-cpu stuff.
+
+Cc: stable@vger.kernel.org
+Cc: stable-rt@vger.kernel.org
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Fixes: a787870924db ("sched, arch: Create asm/preempt.h")
+Reported-by: Vikram Mulukutla <markivx@codeaurora.org>
+Tested-by: Vikram Mulukutla <markivx@codeaurora.org>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ include/asm-generic/preempt.h | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/include/asm-generic/preempt.h
++++ b/include/asm-generic/preempt.h
+@@ -7,10 +7,10 @@
+
+ static __always_inline int preempt_count(void)
+ {
+- return current_thread_info()->preempt_count;
++ return READ_ONCE(current_thread_info()->preempt_count);
+ }
+
+-static __always_inline int *preempt_count_ptr(void)
++static __always_inline volatile int *preempt_count_ptr(void)
+ {
+ return &current_thread_info()->preempt_count;
+ }
diff --git a/patches/series b/patches/series
index c019ba64861e01..e83d7ba4507fc2 100644
--- a/patches/series
+++ b/patches/series
@@ -19,6 +19,7 @@ sched-provide-a-tsk_nr_cpus_allowed-helper.patch
sc16is7xx_Drop_bogus_use_of_IRQF_ONESHOT.patch
crypto-ccp-remove-rwlocks_types.h.patch
infiniband-ulp-ipoib-remove-pkey_mutex.patch
+sched-preempt-Fix-preempt_count-manipulations.patch
# Those two should vanish soon (not use PIT during bootup)
at91_dont_enable_disable_clock.patch
@@ -73,6 +74,7 @@ kernel-SRCU-provide-a-static-initializer.patch
############################################################
# Stuff which should go upstream ASAP
############################################################
+trace-correct-off-by-one-while-recording-the-trace-e.patch
# SCHED BLOCK/WQ
block-shorten-interrupt-disabled-regions.patch
@@ -180,6 +182,7 @@ preempt-nort-rt-variants.patch
# local locks & migrate disable
introduce_migrate_disable_cpu_light.patch
rt-local-irq-lock.patch
+locallock-add-local_lock_on.patch
# ANNOTATE local_irq_disable sites
ata-disable-interrupts-if-non-rt.patch
@@ -220,6 +223,7 @@ mm-page_alloc-reduce-lock-sections-further.patch
# MM SWAP
mm-convert-swap-to-percpu-locked.patch
+mm-perform-lru_add_drain_all-remotely.patch
# MM vmstat
mm-make-vmstat-rt-aware.patch
@@ -313,6 +317,7 @@ kernel-migrate_disable-do-fastpath-in-atomic-irqs-of.patch
irq-allow-disabling-of-softirq-processing-in-irq-thread-context.patch
softirq-split-timer-softirqs-out-of-ksoftirqd.patch
rtmutex-trylock-is-okay-on-RT.patch
+kernel-rtmutex-only-warn-once-on-a-try-lock-from-bad.patch
# RAID5
md-raid5-percpu-handling-rt-aware.patch
@@ -442,6 +447,7 @@ snd-pcm-fix-snd_pcm_stream_lock-irqs_disabled-splats.patch
# CONSOLE. NEEDS more thought !!!
printk-rt-aware.patch
+kernel-printk-Don-t-try-to-print-from-IRQ-NMI-region.patch
HACK-printk-drop-the-logbuf_lock-more-often.patch
# POWERC
@@ -549,6 +555,7 @@ preempt-lazy-support.patch
preempt-lazy-check-preempt_schedule.patch
x86-preempt-lazy.patch
arm-preempt-lazy-support.patch
+arm-lazy-preempt-correct-resched-condition.patch
powerpc-preempt-lazy-support.patch
arch-arm64-Add-lazy-preempt-support.patch
arm-arm64-lazy-preempt-add-TIF_NEED_RESCHED_LAZY-to-.patch
diff --git a/patches/signals-allow-rt-tasks-to-cache-one-sigqueue-struct.patch b/patches/signals-allow-rt-tasks-to-cache-one-sigqueue-struct.patch
index ee5ed64adafd89..5b3d87fcb8c161 100644
--- a/patches/signals-allow-rt-tasks-to-cache-one-sigqueue-struct.patch
+++ b/patches/signals-allow-rt-tasks-to-cache-one-sigqueue-struct.patch
@@ -27,7 +27,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
sigset_t saved_sigmask; /* restored if set_restore_sigmask() was used */
--- a/include/linux/signal.h
+++ b/include/linux/signal.h
-@@ -218,6 +218,7 @@ static inline void init_sigpending(struc
+@@ -233,6 +233,7 @@ static inline void init_sigpending(struc
}
extern void flush_sigqueue(struct sigpending *queue);
diff --git a/patches/trace-correct-off-by-one-while-recording-the-trace-e.patch b/patches/trace-correct-off-by-one-while-recording-the-trace-e.patch
new file mode 100644
index 00000000000000..5461b472b3d7bc
--- /dev/null
+++ b/patches/trace-correct-off-by-one-while-recording-the-trace-e.patch
@@ -0,0 +1,49 @@
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Wed, 25 May 2016 14:03:50 +0200
+Subject: [PATCH] trace: correct off by one while recording the trace-event
+
+Trace events like raw_syscalls show always a preempt code of one. The
+reason is that on PREEMPT kernels rcu_read_lock_sched_notrace()
+increases the preemption counter and the function recording the counter
+is caller within the RCU section.
+
+Cc: stable-rt@vger.kernel.org
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ include/linux/tracepoint.h | 13 +++++++++++++
+ kernel/trace/trace_events.c | 2 +-
+ 2 files changed, 14 insertions(+), 1 deletion(-)
+
+--- a/include/linux/tracepoint.h
++++ b/include/linux/tracepoint.h
+@@ -33,6 +33,19 @@ struct trace_enum_map {
+
+ #define TRACEPOINT_DEFAULT_PRIO 10
+
++/*
++ * The preempt count recorded in trace_event_raw_event_# are off by one due to
++ * rcu_read_lock_sched_notrace() in __DO_TRACE. This is corrected here.
++ */
++static inline int event_preempt_count(void)
++{
++#ifdef CONFIG_PREEMPT
++ return preempt_count() - 1;
++#else
++ return 0;
++#endif
++}
++
+ extern int
+ tracepoint_probe_register(struct tracepoint *tp, void *probe, void *data);
+ extern int
+--- a/kernel/trace/trace_events.c
++++ b/kernel/trace/trace_events.c
+@@ -243,7 +243,7 @@ void *trace_event_buffer_reserve(struct
+ return NULL;
+
+ local_save_flags(fbuffer->flags);
+- fbuffer->pc = preempt_count();
++ fbuffer->pc = event_preempt_count();
+ fbuffer->trace_file = trace_file;
+
+ fbuffer->event =