summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/printk/internal.h11
-rw-r--r--kernel/printk/nmi.c5
-rw-r--r--kernel/printk/printk.c10
3 files changed, 25 insertions, 1 deletions
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)
34 return this_cpu_read(printk_func)(fmt, args); 34 return this_cpu_read(printk_func)(fmt, args);
35} 35}
36 36
37extern atomic_t nmi_message_lost;
38static inline int get_nmi_message_lost(void)
39{
40 return atomic_xchg(&nmi_message_lost, 0);
41}
42
37#else /* CONFIG_PRINTK_NMI */ 43#else /* CONFIG_PRINTK_NMI */
38 44
39static inline __printf(1, 0) int vprintk_func(const char *fmt, va_list args) 45static 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)
41 return vprintk_default(fmt, args); 47 return vprintk_default(fmt, args);
42} 48}
43 49
50static inline int get_nmi_message_lost(void)
51{
52 return 0;
53}
54
44#endif /* CONFIG_PRINTK_NMI */ 55#endif /* CONFIG_PRINTK_NMI */
diff --git a/kernel/printk/nmi.c b/kernel/printk/nmi.c
index 303cf0d15e57..572f94922230 100644
--- a/kernel/printk/nmi.c
+++ b/kernel/printk/nmi.c
@@ -39,6 +39,7 @@
39 */ 39 */
40DEFINE_PER_CPU(printk_func_t, printk_func) = vprintk_default; 40DEFINE_PER_CPU(printk_func_t, printk_func) = vprintk_default;
41static int printk_nmi_irq_ready; 41static int printk_nmi_irq_ready;
42atomic_t nmi_message_lost;
42 43
43#define NMI_LOG_BUF_LEN (4096 - sizeof(atomic_t) - sizeof(struct irq_work)) 44#define NMI_LOG_BUF_LEN (4096 - sizeof(atomic_t) - sizeof(struct irq_work))
44 45
@@ -64,8 +65,10 @@ static int vprintk_nmi(const char *fmt, va_list args)
64again: 65again:
65 len = atomic_read(&s->len); 66 len = atomic_read(&s->len);
66 67
67 if (len >= sizeof(s->buffer)) 68 if (len >= sizeof(s->buffer)) {
69 atomic_inc(&nmi_message_lost);
68 return 0; 70 return 0;
71 }
69 72
70 /* 73 /*
71 * Make sure that all old data have been read before the buffer was 74 * 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 71eba0607034..e38579d730f4 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -1617,6 +1617,7 @@ asmlinkage int vprintk_emit(int facility, int level,
1617 unsigned long flags; 1617 unsigned long flags;
1618 int this_cpu; 1618 int this_cpu;
1619 int printed_len = 0; 1619 int printed_len = 0;
1620 int nmi_message_lost;
1620 bool in_sched = false; 1621 bool in_sched = false;
1621 /* cpu currently holding logbuf_lock in this function */ 1622 /* cpu currently holding logbuf_lock in this function */
1622 static unsigned int logbuf_cpu = UINT_MAX; 1623 static unsigned int logbuf_cpu = UINT_MAX;
@@ -1667,6 +1668,15 @@ asmlinkage int vprintk_emit(int facility, int level,
1667 strlen(recursion_msg)); 1668 strlen(recursion_msg));
1668 } 1669 }
1669 1670
1671 nmi_message_lost = get_nmi_message_lost();
1672 if (unlikely(nmi_message_lost)) {
1673 text_len = scnprintf(textbuf, sizeof(textbuf),
1674 "BAD LUCK: lost %d message(s) from NMI context!",
1675 nmi_message_lost);
1676 printed_len += log_store(0, 2, LOG_PREFIX|LOG_NEWLINE, 0,
1677 NULL, 0, textbuf, text_len);
1678 }
1679
1670 /* 1680 /*
1671 * The printf needs to come first; we need the syslog 1681 * The printf needs to come first; we need the syslog
1672 * prefix which might be passed-in as a parameter. 1682 * prefix which might be passed-in as a parameter.