Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1289559 > unrolled thread
| Started by | Petr Mladek <pmladek@suse.com> |
|---|---|
| First post | 2015-12-11 14:30 +0100 |
| Last post | 2015-12-11 14:40 +0100 |
| Articles | 4 — 1 participant |
Back to article view | Back to linux.kernel
[PATCH v4 0/4] Cleaning printk stuff in NMI context Petr Mladek <pmladek@suse.com> - 2015-12-11 14:30 +0100
[PATCH v4 2/4] printk/nmi: Use IRQ work only when ready Petr Mladek <pmladek@suse.com> - 2015-12-11 14:30 +0100
[PATCH v4 3/4] printk/nmi: Warn when some message has been lost in NMI context Petr Mladek <pmladek@suse.com> - 2015-12-11 14:30 +0100
Re: [PATCH v4 0/4] Cleaning printk stuff in NMI context Petr Mladek <pmladek@suse.com> - 2015-12-11 14:40 +0100
| From | Petr Mladek <pmladek@suse.com> |
|---|---|
| Date | 2015-12-11 14:30 +0100 |
| Subject | [PATCH v4 0/4] Cleaning printk stuff in NMI context |
| Message-ID | <qEvVM-4Wy-9@gated-at.bofh.it> |
Hi Andrew,
this is just a quick respin of the previous version. It changes
the few details as you suggested. Also it fixes the build problem
on ARM as reported by Geert and Arnd.
I rather send the whole patch set because there is the renamed header.
Also the extra blank space affects two patches. I hope that it will
safe you some work. Please, let me know if you would prefer
incremental patches.
Changes against v3:
+ used size_t for "len" and "size"
+ replaced WARN() with pr_err()
+ renamed kernel/printk/printk.h -> internal.h
+ fixed build on ARM (undefined NMI_LOG_BUF_SHIFT)
Changes against v2:
+ fixed compilation problems reported by 0-day build robot
+ MN10300 and Xtensa architectures will get handled separately
+ dropped the patch that printed NMI messages directly when Oops
in progress; it made the solution less reliable
+ made the size of the buffer configurable; use real numbers
instead of PAGE_SIZE
Changes against v1:
+ rebased on top of 4.4-rc2; there the old implementation was
moved to lib/nmi_backtrace.c and used also on arm; I hope that
I got the arm side correctly; I was not able to test on arm :-(
+ defined HAVE_NMI on arm for !CPU_V7M instead of !CPU_V7;
handle_fiq_as_nmi() is called from entry-armv.S that
is compiled when !CPU_V7M
+ defined HAVE_NMI also on mips; it calls nmi_enter() and
seems to have real NMIs (or am I wrong?)
+ serialized backtraces when printing directly
(oops_in_progress)
Petr Mladek (4):
printk/nmi: Generic solution for safe printk in NMI
printk/nmi: Use IRQ work only when ready
printk/nmi: Warn when some message has been lost in NMI context
printk/nmi: Increase the size of NMI buffer and make it configurable
arch/Kconfig | 7 ++
arch/arm/Kconfig | 2 +
arch/arm/kernel/smp.c | 2 +
arch/avr32/Kconfig | 1 +
arch/blackfin/Kconfig | 1 +
arch/cris/Kconfig | 1 +
arch/mips/Kconfig | 1 +
arch/powerpc/Kconfig | 1 +
arch/s390/Kconfig | 1 +
arch/sh/Kconfig | 1 +
arch/sparc/Kconfig | 1 +
arch/tile/Kconfig | 1 +
arch/x86/Kconfig | 1 +
arch/x86/kernel/apic/hw_nmi.c | 1 -
include/linux/hardirq.h | 2 +
include/linux/percpu.h | 3 -
include/linux/printk.h | 12 ++-
init/Kconfig | 27 +++++
init/main.c | 1 +
kernel/printk/Makefile | 1 +
kernel/printk/internal.h | 55 +++++++++++
kernel/printk/nmi.c | 222 ++++++++++++++++++++++++++++++++++++++++++
kernel/printk/printk.c | 29 +++---
lib/nmi_backtrace.c | 89 +----------------
24 files changed, 356 insertions(+), 107 deletions(-)
create mode 100644 kernel/printk/internal.h
create mode 100644 kernel/printk/nmi.c
--
1.8.5.6
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [next] | [standalone]
| From | Petr Mladek <pmladek@suse.com> |
|---|---|
| Date | 2015-12-11 14:30 +0100 |
| Subject | [PATCH v4 2/4] printk/nmi: Use IRQ work only when ready |
| Message-ID | <qEvVM-4Wy-23@gated-at.bofh.it> |
| In reply to | #1289559 |
NMIs could happen at any time. This patch makes sure that the safe
printk() in NMI will schedule IRQ work only when the related
structs are initialized.
All pending messages are flushed when the IRQ work is being
initialized.
Signed-off-by: Petr Mladek <pmladek@suse.com>
Cc: Jan Kara <jack@suse.cz>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Daniel Thompson <daniel.thompson@linaro.org>
Cc: Jiri Kosina <jkosina@suse.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: David Miller <davem@davemloft.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---
kernel/printk/nmi.c | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/kernel/printk/nmi.c b/kernel/printk/nmi.c
index b5d1359402c5..9a506bd18b9d 100644
--- a/kernel/printk/nmi.c
+++ b/kernel/printk/nmi.c
@@ -38,6 +38,7 @@
* were handled or when IRQs are blocked.
*/
DEFINE_PER_CPU(printk_func_t, printk_func) = vprintk_default;
+static int printk_nmi_irq_ready;
#define NMI_LOG_BUF_LEN (4096 - sizeof(atomic_t) - sizeof(struct irq_work))
@@ -84,8 +85,11 @@ again:
goto again;
/* Get flushed in a more safe context. */
- if (add)
+ if (add && printk_nmi_irq_ready) {
+ /* Make sure that IRQ work is really initialized. */
+ smp_rmb();
irq_work_queue(&s->work);
+ }
return add;
}
@@ -194,6 +198,13 @@ void __init printk_nmi_init(void)
init_irq_work(&s->work, __printk_nmi_flush);
}
+
+ /* Make sure that IRQ works are initialized before enabling. */
+ smp_wmb();
+ printk_nmi_irq_ready = 1;
+
+ /* Flush pending messages that did not have scheduled IRQ works. */
+ printk_nmi_flush();
}
void printk_nmi_enter(void)
--
1.8.5.6
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Petr Mladek <pmladek@suse.com> |
|---|---|
| Date | 2015-12-11 14:30 +0100 |
| Subject | [PATCH v4 3/4] printk/nmi: Warn when some message has been lost in NMI context |
| Message-ID | <qEvVN-4Wy-25@gated-at.bofh.it> |
| In reply to | #1289559 |
We could not resize the temporary buffer in NMI context. Let's warn
if a message is lost.
This is rather theoretical. printk() should not be used in NMI.
The only sensible use is when we want to print backtrace from all
CPUs. The current buffer should be enough for this purpose.
Signed-off-by: Petr Mladek <pmladek@suse.com>
Cc: Jan Kara <jack@suse.cz>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Daniel Thompson <daniel.thompson@linaro.org>
Cc: Jiri Kosina <jkosina@suse.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: David Miller <davem@davemloft.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---
kernel/printk/internal.h | 11 +++++++++++
kernel/printk/nmi.c | 5 ++++-
kernel/printk/printk.c | 10 ++++++++++
3 files changed, 25 insertions(+), 1 deletion(-)
diff --git a/kernel/printk/internal.h b/kernel/printk/internal.h
index 2de99faedfc1..341bedccc065 100644
--- a/kernel/printk/internal.h
+++ b/kernel/printk/internal.h
@@ -34,6 +34,12 @@ static inline __printf(1, 0) int vprintk_func(const char *fmt, va_list args)
return this_cpu_read(printk_func)(fmt, args);
}
+extern atomic_t nmi_message_lost;
+static inline int get_nmi_message_lost(void)
+{
+ return atomic_xchg(&nmi_message_lost, 0);
+}
+
#else /* CONFIG_PRINTK_NMI */
static inline __printf(1, 0) int vprintk_func(const char *fmt, va_list args)
@@ -41,4 +47,9 @@ static inline __printf(1, 0) int vprintk_func(const char *fmt, va_list args)
return vprintk_default(fmt, args);
}
+static inline int get_nmi_message_lost(void)
+{
+ return 0;
+}
+
#endif /* CONFIG_PRINTK_NMI */
diff --git a/kernel/printk/nmi.c b/kernel/printk/nmi.c
index 9a506bd18b9d..d86f55cccf31 100644
--- a/kernel/printk/nmi.c
+++ b/kernel/printk/nmi.c
@@ -39,6 +39,7 @@
*/
DEFINE_PER_CPU(printk_func_t, printk_func) = vprintk_default;
static int printk_nmi_irq_ready;
+atomic_t nmi_message_lost;
#define NMI_LOG_BUF_LEN (4096 - sizeof(atomic_t) - sizeof(struct irq_work))
@@ -64,8 +65,10 @@ static int vprintk_nmi(const char *fmt, va_list args)
again:
len = atomic_read(&s->len);
- if (len >= sizeof(s->buffer))
+ if (len >= sizeof(s->buffer)) {
+ atomic_inc(&nmi_message_lost);
return 0;
+ }
/*
* Make sure that all old data have been read before the buffer was
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index 480ad05ab299..71183a308b9e 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -1669,6 +1669,7 @@ asmlinkage int vprintk_emit(int facility, int level,
unsigned long flags;
int this_cpu;
int printed_len = 0;
+ int nmi_message_lost;
bool in_sched = false;
/* cpu currently holding logbuf_lock in this function */
static unsigned int logbuf_cpu = UINT_MAX;
@@ -1719,6 +1720,15 @@ asmlinkage int vprintk_emit(int facility, int level,
strlen(recursion_msg));
}
+ nmi_message_lost = get_nmi_message_lost();
+ if (unlikely(nmi_message_lost)) {
+ text_len = scnprintf(textbuf, sizeof(textbuf),
+ "BAD LUCK: lost %d message(s) from NMI context!",
+ nmi_message_lost);
+ printed_len += log_store(0, 2, LOG_PREFIX|LOG_NEWLINE, 0,
+ NULL, 0, textbuf, text_len);
+ }
+
/*
* The printf needs to come first; we need the syslog
* prefix which might be passed-in as a parameter.
--
1.8.5.6
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Petr Mladek <pmladek@suse.com> |
|---|---|
| Date | 2015-12-11 14:40 +0100 |
| Message-ID | <qEw5t-52w-29@gated-at.bofh.it> |
| In reply to | #1289559 |
On Fri 2015-12-11 14:20:48, Petr Mladek wrote:
> Hi Andrew,
>
> this is just a quick respin of the previous version. It changes
> the few details as you suggested. Also it fixes the build problem
> on ARM as reported by Geert and Arnd.
>
> I rather send the whole patch set because there is the renamed header.
> Also the extra blank space affects two patches. I hope that it will
> safe you some work. Please, let me know if you would prefer
> incremental patches.
>
>
> Changes against v3:
>
> + used size_t for "len" and "size"
>
> + replaced WARN() with pr_err()
>
> + renamed kernel/printk/printk.h -> internal.h
>
> + fixed build on ARM (undefined NMI_LOG_BUF_SHIFT)
Please, find below the diff between the two branches based on v3 and
v4 of the patch set. I hope that it might help.
diff --git a/init/Kconfig b/init/Kconfig
index efcff25a112d..61cfd96a3c96 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -870,7 +870,7 @@ config NMI_LOG_BUF_SHIFT
int "Temporary per-CPU NMI log buffer size (12 => 4KB, 13 => 8KB)"
range 10 21
default 13
- depends on PRINTK && HAVE_NMI
+ depends on PRINTK_NMI
help
Select the size of a per-CPU buffer where NMI messages are temporary
stored. They are copied to the main log buffer in a safe context
diff --git a/kernel/printk/printk.h b/kernel/printk/internal.h
similarity index 97%
rename from kernel/printk/printk.h
rename to kernel/printk/internal.h
index 7f778b609492..341bedccc065 100644
--- a/kernel/printk/printk.h
+++ b/kernel/printk/internal.h
@@ -1,5 +1,5 @@
/*
- * printk.h - printk internal definitions
+ * internal.h - printk internal definitions
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
diff --git a/kernel/printk/nmi.c b/kernel/printk/nmi.c
index 78c07d441b4e..92c61e960c4a 100644
--- a/kernel/printk/nmi.c
+++ b/kernel/printk/nmi.c
@@ -22,7 +22,7 @@
#include <linux/irq_work.h>
#include <linux/printk.h>
-#include "printk.h"
+#include "internal.h"
/*
* printk() could not take logbuf_lock in NMI context. Instead,
@@ -60,12 +60,13 @@ static DEFINE_PER_CPU(struct nmi_seq_buf, nmi_print_seq);
static int vprintk_nmi(const char *fmt, va_list args)
{
struct nmi_seq_buf *s = this_cpu_ptr(&nmi_print_seq);
- int add = 0, len;
+ int add = 0;
+ size_t len;
again:
len = atomic_read(&s->len);
- if (len >= sizeof(s->buffer)) {
+ if (len >= sizeof(s->buffer)) {
atomic_inc(&nmi_message_lost);
return 0;
}
@@ -117,7 +118,8 @@ static void __printk_nmi_flush(struct irq_work *work)
static raw_spinlock_t read_lock =
__RAW_SPIN_LOCK_INITIALIZER(read_lock);
struct nmi_seq_buf *s = container_of(work, struct nmi_seq_buf, work);
- int len, size, i, last_i;
+ size_t len, size;
+ int i, last_i;
/*
* The lock has two functions. First, one reader has to flush all
@@ -137,7 +139,9 @@ more:
* the buffer an unexpected way. If we printed something then
* @len must only increase.
*/
- WARN_ON(i && i >= len);
+ if (i && i >= len)
+ pr_err("printk_nmi_flush: internal error: i=%d >= len=%lu\n",
+ i, len);
if (!len)
goto out; /* Someone else has already flushed the buffer. */
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index a6bb0b0838f3..71183a308b9e 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -54,7 +54,7 @@
#include "console_cmdline.h"
#include "braille.h"
-#include "printk.h"
+#include "internal.h"
int console_printk[4] = {
CONSOLE_LOGLEVEL_DEFAULT, /* console_loglevel */
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web