Loading include/linux/printk.h +4 −0 Original line number Original line Diff line number Diff line Loading @@ -148,9 +148,13 @@ void early_printk(const char *s, ...) { } #ifdef CONFIG_PRINTK_NMI #ifdef CONFIG_PRINTK_NMI extern void printk_nmi_enter(void); extern void printk_nmi_enter(void); extern void printk_nmi_exit(void); extern void printk_nmi_exit(void); extern void printk_nmi_direct_enter(void); extern void printk_nmi_direct_exit(void); #else #else static inline void printk_nmi_enter(void) { } static inline void printk_nmi_enter(void) { } static inline void printk_nmi_exit(void) { } static inline void printk_nmi_exit(void) { } static inline void printk_nmi_direct_enter(void) { } static inline void printk_nmi_direct_exit(void) { } #endif /* PRINTK_NMI */ #endif /* PRINTK_NMI */ #ifdef CONFIG_PRINTK #ifdef CONFIG_PRINTK Loading kernel/printk/internal.h +8 −1 Original line number Original line Diff line number Diff line Loading @@ -19,11 +19,16 @@ #ifdef CONFIG_PRINTK #ifdef CONFIG_PRINTK #define PRINTK_SAFE_CONTEXT_MASK 0x3fffffff #define PRINTK_SAFE_CONTEXT_MASK 0x3fffffff #define PRINTK_NMI_DEFERRED_CONTEXT_MASK 0x40000000 #define PRINTK_NMI_DIRECT_CONTEXT_MASK 0x40000000 #define PRINTK_NMI_CONTEXT_MASK 0x80000000 #define PRINTK_NMI_CONTEXT_MASK 0x80000000 extern raw_spinlock_t logbuf_lock; extern raw_spinlock_t logbuf_lock; __printf(5, 0) int vprintk_store(int facility, int level, const char *dict, size_t dictlen, const char *fmt, va_list args); __printf(1, 0) int vprintk_default(const char *fmt, va_list args); __printf(1, 0) int vprintk_default(const char *fmt, va_list args); __printf(1, 0) int vprintk_deferred(const char *fmt, va_list args); __printf(1, 0) int vprintk_deferred(const char *fmt, va_list args); __printf(1, 0) int vprintk_func(const char *fmt, va_list args); __printf(1, 0) int vprintk_func(const char *fmt, va_list args); Loading Loading @@ -54,6 +59,8 @@ void __printk_safe_exit(void); local_irq_enable(); \ local_irq_enable(); \ } while (0) } while (0) void defer_console_output(void); #else #else __printf(1, 0) int vprintk_func(const char *fmt, va_list args) { return 0; } __printf(1, 0) int vprintk_func(const char *fmt, va_list args) { return 0; } Loading kernel/printk/printk.c +35 −22 Original line number Original line Diff line number Diff line Loading @@ -1829,7 +1829,8 @@ static size_t log_output(int facility, int level, enum log_flags lflags, const c return log_store(facility, level, lflags, 0, dict, dictlen, text, text_len); return log_store(facility, level, lflags, 0, dict, dictlen, text, text_len); } } asmlinkage int vprintk_emit(int facility, int level, /* Must be called under logbuf_lock. */ int vprintk_store(int facility, int level, const char *dict, size_t dictlen, const char *dict, size_t dictlen, const char *fmt, va_list args) const char *fmt, va_list args) { { Loading @@ -1837,20 +1838,7 @@ asmlinkage int vprintk_emit(int facility, int level, char *text = textbuf; char *text = textbuf; size_t text_len; size_t text_len; enum log_flags lflags = 0; enum log_flags lflags = 0; unsigned long flags; int printed_len; bool in_sched = false; if (level == LOGLEVEL_SCHED) { level = LOGLEVEL_DEFAULT; in_sched = true; } boot_delay_msec(level); printk_delay(); /* This stops the holder of console_sem just where we want him */ logbuf_lock_irqsave(flags); /* /* * The printf needs to come first; we need the syslog * The printf needs to come first; we need the syslog * prefix which might be passed-in as a parameter. * prefix which might be passed-in as a parameter. Loading Loading @@ -1894,8 +1882,29 @@ asmlinkage int vprintk_emit(int facility, int level, if (suppress_message_printing(level)) if (suppress_message_printing(level)) lflags |= LOG_NOCONS; lflags |= LOG_NOCONS; printed_len = log_output(facility, level, lflags, dict, dictlen, text, text_len); return log_output(facility, level, lflags, dict, dictlen, text, text_len); } asmlinkage int vprintk_emit(int facility, int level, const char *dict, size_t dictlen, const char *fmt, va_list args) { int printed_len; bool in_sched = false; unsigned long flags; if (level == LOGLEVEL_SCHED) { level = LOGLEVEL_DEFAULT; in_sched = true; } boot_delay_msec(level); printk_delay(); /* This stops the holder of console_sem just where we want him */ logbuf_lock_irqsave(flags); printed_len = vprintk_store(facility, level, dict, dictlen, fmt, args); logbuf_unlock_irqrestore(flags); logbuf_unlock_irqrestore(flags); /* If called from the scheduler, we can not call up(). */ /* If called from the scheduler, we can not call up(). */ Loading Loading @@ -2884,16 +2893,20 @@ void wake_up_klogd(void) preempt_enable(); preempt_enable(); } } int vprintk_deferred(const char *fmt, va_list args) void defer_console_output(void) { { int r; r = vprintk_emit(0, LOGLEVEL_SCHED, NULL, 0, fmt, args); preempt_disable(); preempt_disable(); __this_cpu_or(printk_pending, PRINTK_PENDING_OUTPUT); __this_cpu_or(printk_pending, PRINTK_PENDING_OUTPUT); irq_work_queue(this_cpu_ptr(&wake_up_klogd_work)); irq_work_queue(this_cpu_ptr(&wake_up_klogd_work)); preempt_enable(); preempt_enable(); } int vprintk_deferred(const char *fmt, va_list args) { int r; r = vprintk_emit(0, LOGLEVEL_SCHED, NULL, 0, fmt, args); defer_console_output(); return r; return r; } } Loading kernel/printk/printk_safe.c +37 −21 Original line number Original line Diff line number Diff line Loading @@ -308,24 +308,33 @@ static __printf(1, 0) int vprintk_nmi(const char *fmt, va_list args) void printk_nmi_enter(void) void printk_nmi_enter(void) { { /* * The size of the extra per-CPU buffer is limited. Use it only when * the main one is locked. If this CPU is not in the safe context, * the lock must be taken on another CPU and we could wait for it. */ if ((this_cpu_read(printk_context) & PRINTK_SAFE_CONTEXT_MASK) && raw_spin_is_locked(&logbuf_lock)) { this_cpu_or(printk_context, PRINTK_NMI_CONTEXT_MASK); this_cpu_or(printk_context, PRINTK_NMI_CONTEXT_MASK); } else { this_cpu_or(printk_context, PRINTK_NMI_DEFERRED_CONTEXT_MASK); } } } void printk_nmi_exit(void) void printk_nmi_exit(void) { { this_cpu_and(printk_context, this_cpu_and(printk_context, ~PRINTK_NMI_CONTEXT_MASK); ~(PRINTK_NMI_CONTEXT_MASK | } PRINTK_NMI_DEFERRED_CONTEXT_MASK)); /* * Marks a code that might produce many messages in NMI context * and the risk of losing them is more critical than eventual * reordering. * * It has effect only when called in NMI context. Then printk() * will try to store the messages into the main logbuf directly * and use the per-CPU buffers only as a fallback when the lock * is not available. */ void printk_nmi_direct_enter(void) { if (this_cpu_read(printk_context) & PRINTK_NMI_CONTEXT_MASK) this_cpu_or(printk_context, PRINTK_NMI_DIRECT_CONTEXT_MASK); } void printk_nmi_direct_exit(void) { this_cpu_and(printk_context, ~PRINTK_NMI_DIRECT_CONTEXT_MASK); } } #else #else Loading Loading @@ -363,6 +372,20 @@ void __printk_safe_exit(void) __printf(1, 0) int vprintk_func(const char *fmt, va_list args) __printf(1, 0) int vprintk_func(const char *fmt, va_list args) { { /* * Try to use the main logbuf even in NMI. But avoid calling console * drivers that might have their own locks. */ if ((this_cpu_read(printk_context) & PRINTK_NMI_DIRECT_CONTEXT_MASK) && raw_spin_trylock(&logbuf_lock)) { int len; len = vprintk_store(0, LOGLEVEL_DEFAULT, NULL, 0, fmt, args); raw_spin_unlock(&logbuf_lock); defer_console_output(); return len; } /* Use extra buffer in NMI when logbuf_lock is taken or in safe mode. */ /* Use extra buffer in NMI when logbuf_lock is taken or in safe mode. */ if (this_cpu_read(printk_context) & PRINTK_NMI_CONTEXT_MASK) if (this_cpu_read(printk_context) & PRINTK_NMI_CONTEXT_MASK) return vprintk_nmi(fmt, args); return vprintk_nmi(fmt, args); Loading @@ -371,13 +394,6 @@ __printf(1, 0) int vprintk_func(const char *fmt, va_list args) if (this_cpu_read(printk_context) & PRINTK_SAFE_CONTEXT_MASK) if (this_cpu_read(printk_context) & PRINTK_SAFE_CONTEXT_MASK) return vprintk_safe(fmt, args); return vprintk_safe(fmt, args); /* * Use the main logbuf when logbuf_lock is available in NMI. * But avoid calling console drivers that might have their own locks. */ if (this_cpu_read(printk_context) & PRINTK_NMI_DEFERRED_CONTEXT_MASK) return vprintk_deferred(fmt, args); /* No obstacles. */ /* No obstacles. */ return vprintk_default(fmt, args); return vprintk_default(fmt, args); } } Loading kernel/trace/trace.c +3 −1 Original line number Original line Diff line number Diff line Loading @@ -8265,6 +8265,7 @@ void ftrace_dump(enum ftrace_dump_mode oops_dump_mode) tracing_off(); tracing_off(); local_irq_save(flags); local_irq_save(flags); printk_nmi_direct_enter(); /* Simulate the iterator */ /* Simulate the iterator */ trace_init_global_iter(&iter); trace_init_global_iter(&iter); Loading Loading @@ -8345,6 +8346,7 @@ void ftrace_dump(enum ftrace_dump_mode oops_dump_mode) atomic_dec(&per_cpu_ptr(iter.trace_buffer->data, cpu)->disabled); atomic_dec(&per_cpu_ptr(iter.trace_buffer->data, cpu)->disabled); } } atomic_dec(&dump_running); atomic_dec(&dump_running); printk_nmi_direct_exit(); local_irq_restore(flags); local_irq_restore(flags); } } EXPORT_SYMBOL_GPL(ftrace_dump); EXPORT_SYMBOL_GPL(ftrace_dump); Loading Loading
include/linux/printk.h +4 −0 Original line number Original line Diff line number Diff line Loading @@ -148,9 +148,13 @@ void early_printk(const char *s, ...) { } #ifdef CONFIG_PRINTK_NMI #ifdef CONFIG_PRINTK_NMI extern void printk_nmi_enter(void); extern void printk_nmi_enter(void); extern void printk_nmi_exit(void); extern void printk_nmi_exit(void); extern void printk_nmi_direct_enter(void); extern void printk_nmi_direct_exit(void); #else #else static inline void printk_nmi_enter(void) { } static inline void printk_nmi_enter(void) { } static inline void printk_nmi_exit(void) { } static inline void printk_nmi_exit(void) { } static inline void printk_nmi_direct_enter(void) { } static inline void printk_nmi_direct_exit(void) { } #endif /* PRINTK_NMI */ #endif /* PRINTK_NMI */ #ifdef CONFIG_PRINTK #ifdef CONFIG_PRINTK Loading
kernel/printk/internal.h +8 −1 Original line number Original line Diff line number Diff line Loading @@ -19,11 +19,16 @@ #ifdef CONFIG_PRINTK #ifdef CONFIG_PRINTK #define PRINTK_SAFE_CONTEXT_MASK 0x3fffffff #define PRINTK_SAFE_CONTEXT_MASK 0x3fffffff #define PRINTK_NMI_DEFERRED_CONTEXT_MASK 0x40000000 #define PRINTK_NMI_DIRECT_CONTEXT_MASK 0x40000000 #define PRINTK_NMI_CONTEXT_MASK 0x80000000 #define PRINTK_NMI_CONTEXT_MASK 0x80000000 extern raw_spinlock_t logbuf_lock; extern raw_spinlock_t logbuf_lock; __printf(5, 0) int vprintk_store(int facility, int level, const char *dict, size_t dictlen, const char *fmt, va_list args); __printf(1, 0) int vprintk_default(const char *fmt, va_list args); __printf(1, 0) int vprintk_default(const char *fmt, va_list args); __printf(1, 0) int vprintk_deferred(const char *fmt, va_list args); __printf(1, 0) int vprintk_deferred(const char *fmt, va_list args); __printf(1, 0) int vprintk_func(const char *fmt, va_list args); __printf(1, 0) int vprintk_func(const char *fmt, va_list args); Loading Loading @@ -54,6 +59,8 @@ void __printk_safe_exit(void); local_irq_enable(); \ local_irq_enable(); \ } while (0) } while (0) void defer_console_output(void); #else #else __printf(1, 0) int vprintk_func(const char *fmt, va_list args) { return 0; } __printf(1, 0) int vprintk_func(const char *fmt, va_list args) { return 0; } Loading
kernel/printk/printk.c +35 −22 Original line number Original line Diff line number Diff line Loading @@ -1829,7 +1829,8 @@ static size_t log_output(int facility, int level, enum log_flags lflags, const c return log_store(facility, level, lflags, 0, dict, dictlen, text, text_len); return log_store(facility, level, lflags, 0, dict, dictlen, text, text_len); } } asmlinkage int vprintk_emit(int facility, int level, /* Must be called under logbuf_lock. */ int vprintk_store(int facility, int level, const char *dict, size_t dictlen, const char *dict, size_t dictlen, const char *fmt, va_list args) const char *fmt, va_list args) { { Loading @@ -1837,20 +1838,7 @@ asmlinkage int vprintk_emit(int facility, int level, char *text = textbuf; char *text = textbuf; size_t text_len; size_t text_len; enum log_flags lflags = 0; enum log_flags lflags = 0; unsigned long flags; int printed_len; bool in_sched = false; if (level == LOGLEVEL_SCHED) { level = LOGLEVEL_DEFAULT; in_sched = true; } boot_delay_msec(level); printk_delay(); /* This stops the holder of console_sem just where we want him */ logbuf_lock_irqsave(flags); /* /* * The printf needs to come first; we need the syslog * The printf needs to come first; we need the syslog * prefix which might be passed-in as a parameter. * prefix which might be passed-in as a parameter. Loading Loading @@ -1894,8 +1882,29 @@ asmlinkage int vprintk_emit(int facility, int level, if (suppress_message_printing(level)) if (suppress_message_printing(level)) lflags |= LOG_NOCONS; lflags |= LOG_NOCONS; printed_len = log_output(facility, level, lflags, dict, dictlen, text, text_len); return log_output(facility, level, lflags, dict, dictlen, text, text_len); } asmlinkage int vprintk_emit(int facility, int level, const char *dict, size_t dictlen, const char *fmt, va_list args) { int printed_len; bool in_sched = false; unsigned long flags; if (level == LOGLEVEL_SCHED) { level = LOGLEVEL_DEFAULT; in_sched = true; } boot_delay_msec(level); printk_delay(); /* This stops the holder of console_sem just where we want him */ logbuf_lock_irqsave(flags); printed_len = vprintk_store(facility, level, dict, dictlen, fmt, args); logbuf_unlock_irqrestore(flags); logbuf_unlock_irqrestore(flags); /* If called from the scheduler, we can not call up(). */ /* If called from the scheduler, we can not call up(). */ Loading Loading @@ -2884,16 +2893,20 @@ void wake_up_klogd(void) preempt_enable(); preempt_enable(); } } int vprintk_deferred(const char *fmt, va_list args) void defer_console_output(void) { { int r; r = vprintk_emit(0, LOGLEVEL_SCHED, NULL, 0, fmt, args); preempt_disable(); preempt_disable(); __this_cpu_or(printk_pending, PRINTK_PENDING_OUTPUT); __this_cpu_or(printk_pending, PRINTK_PENDING_OUTPUT); irq_work_queue(this_cpu_ptr(&wake_up_klogd_work)); irq_work_queue(this_cpu_ptr(&wake_up_klogd_work)); preempt_enable(); preempt_enable(); } int vprintk_deferred(const char *fmt, va_list args) { int r; r = vprintk_emit(0, LOGLEVEL_SCHED, NULL, 0, fmt, args); defer_console_output(); return r; return r; } } Loading
kernel/printk/printk_safe.c +37 −21 Original line number Original line Diff line number Diff line Loading @@ -308,24 +308,33 @@ static __printf(1, 0) int vprintk_nmi(const char *fmt, va_list args) void printk_nmi_enter(void) void printk_nmi_enter(void) { { /* * The size of the extra per-CPU buffer is limited. Use it only when * the main one is locked. If this CPU is not in the safe context, * the lock must be taken on another CPU and we could wait for it. */ if ((this_cpu_read(printk_context) & PRINTK_SAFE_CONTEXT_MASK) && raw_spin_is_locked(&logbuf_lock)) { this_cpu_or(printk_context, PRINTK_NMI_CONTEXT_MASK); this_cpu_or(printk_context, PRINTK_NMI_CONTEXT_MASK); } else { this_cpu_or(printk_context, PRINTK_NMI_DEFERRED_CONTEXT_MASK); } } } void printk_nmi_exit(void) void printk_nmi_exit(void) { { this_cpu_and(printk_context, this_cpu_and(printk_context, ~PRINTK_NMI_CONTEXT_MASK); ~(PRINTK_NMI_CONTEXT_MASK | } PRINTK_NMI_DEFERRED_CONTEXT_MASK)); /* * Marks a code that might produce many messages in NMI context * and the risk of losing them is more critical than eventual * reordering. * * It has effect only when called in NMI context. Then printk() * will try to store the messages into the main logbuf directly * and use the per-CPU buffers only as a fallback when the lock * is not available. */ void printk_nmi_direct_enter(void) { if (this_cpu_read(printk_context) & PRINTK_NMI_CONTEXT_MASK) this_cpu_or(printk_context, PRINTK_NMI_DIRECT_CONTEXT_MASK); } void printk_nmi_direct_exit(void) { this_cpu_and(printk_context, ~PRINTK_NMI_DIRECT_CONTEXT_MASK); } } #else #else Loading Loading @@ -363,6 +372,20 @@ void __printk_safe_exit(void) __printf(1, 0) int vprintk_func(const char *fmt, va_list args) __printf(1, 0) int vprintk_func(const char *fmt, va_list args) { { /* * Try to use the main logbuf even in NMI. But avoid calling console * drivers that might have their own locks. */ if ((this_cpu_read(printk_context) & PRINTK_NMI_DIRECT_CONTEXT_MASK) && raw_spin_trylock(&logbuf_lock)) { int len; len = vprintk_store(0, LOGLEVEL_DEFAULT, NULL, 0, fmt, args); raw_spin_unlock(&logbuf_lock); defer_console_output(); return len; } /* Use extra buffer in NMI when logbuf_lock is taken or in safe mode. */ /* Use extra buffer in NMI when logbuf_lock is taken or in safe mode. */ if (this_cpu_read(printk_context) & PRINTK_NMI_CONTEXT_MASK) if (this_cpu_read(printk_context) & PRINTK_NMI_CONTEXT_MASK) return vprintk_nmi(fmt, args); return vprintk_nmi(fmt, args); Loading @@ -371,13 +394,6 @@ __printf(1, 0) int vprintk_func(const char *fmt, va_list args) if (this_cpu_read(printk_context) & PRINTK_SAFE_CONTEXT_MASK) if (this_cpu_read(printk_context) & PRINTK_SAFE_CONTEXT_MASK) return vprintk_safe(fmt, args); return vprintk_safe(fmt, args); /* * Use the main logbuf when logbuf_lock is available in NMI. * But avoid calling console drivers that might have their own locks. */ if (this_cpu_read(printk_context) & PRINTK_NMI_DEFERRED_CONTEXT_MASK) return vprintk_deferred(fmt, args); /* No obstacles. */ /* No obstacles. */ return vprintk_default(fmt, args); return vprintk_default(fmt, args); } } Loading
kernel/trace/trace.c +3 −1 Original line number Original line Diff line number Diff line Loading @@ -8265,6 +8265,7 @@ void ftrace_dump(enum ftrace_dump_mode oops_dump_mode) tracing_off(); tracing_off(); local_irq_save(flags); local_irq_save(flags); printk_nmi_direct_enter(); /* Simulate the iterator */ /* Simulate the iterator */ trace_init_global_iter(&iter); trace_init_global_iter(&iter); Loading Loading @@ -8345,6 +8346,7 @@ void ftrace_dump(enum ftrace_dump_mode oops_dump_mode) atomic_dec(&per_cpu_ptr(iter.trace_buffer->data, cpu)->disabled); atomic_dec(&per_cpu_ptr(iter.trace_buffer->data, cpu)->disabled); } } atomic_dec(&dump_running); atomic_dec(&dump_running); printk_nmi_direct_exit(); local_irq_restore(flags); local_irq_restore(flags); } } EXPORT_SYMBOL_GPL(ftrace_dump); EXPORT_SYMBOL_GPL(ftrace_dump); Loading