diff options
Diffstat (limited to 'kernel/printk.c')
-rw-r--r-- | kernel/printk.c | 177 |
1 files changed, 127 insertions, 50 deletions
diff --git a/kernel/printk.c b/kernel/printk.c index 0b31715f335a..96dcfcd9a2d4 100644 --- a/kernel/printk.c +++ b/kernel/printk.c | |||
@@ -43,19 +43,13 @@ | |||
43 | #include <linux/rculist.h> | 43 | #include <linux/rculist.h> |
44 | #include <linux/poll.h> | 44 | #include <linux/poll.h> |
45 | #include <linux/irq_work.h> | 45 | #include <linux/irq_work.h> |
46 | #include <linux/utsname.h> | ||
46 | 47 | ||
47 | #include <asm/uaccess.h> | 48 | #include <asm/uaccess.h> |
48 | 49 | ||
49 | #define CREATE_TRACE_POINTS | 50 | #define CREATE_TRACE_POINTS |
50 | #include <trace/events/printk.h> | 51 | #include <trace/events/printk.h> |
51 | 52 | ||
52 | /* | ||
53 | * Architectures can override it: | ||
54 | */ | ||
55 | void asmlinkage __attribute__((weak)) early_printk(const char *fmt, ...) | ||
56 | { | ||
57 | } | ||
58 | |||
59 | /* printk's without a loglevel use this.. */ | 53 | /* printk's without a loglevel use this.. */ |
60 | #define DEFAULT_MESSAGE_LOGLEVEL CONFIG_DEFAULT_MESSAGE_LOGLEVEL | 54 | #define DEFAULT_MESSAGE_LOGLEVEL CONFIG_DEFAULT_MESSAGE_LOGLEVEL |
61 | 55 | ||
@@ -63,8 +57,6 @@ void asmlinkage __attribute__((weak)) early_printk(const char *fmt, ...) | |||
63 | #define MINIMUM_CONSOLE_LOGLEVEL 1 /* Minimum loglevel we let people use */ | 57 | #define MINIMUM_CONSOLE_LOGLEVEL 1 /* Minimum loglevel we let people use */ |
64 | #define DEFAULT_CONSOLE_LOGLEVEL 7 /* anything MORE serious than KERN_DEBUG */ | 58 | #define DEFAULT_CONSOLE_LOGLEVEL 7 /* anything MORE serious than KERN_DEBUG */ |
65 | 59 | ||
66 | DECLARE_WAIT_QUEUE_HEAD(log_wait); | ||
67 | |||
68 | int console_printk[4] = { | 60 | int console_printk[4] = { |
69 | DEFAULT_CONSOLE_LOGLEVEL, /* console_loglevel */ | 61 | DEFAULT_CONSOLE_LOGLEVEL, /* console_loglevel */ |
70 | DEFAULT_MESSAGE_LOGLEVEL, /* default_message_loglevel */ | 62 | DEFAULT_MESSAGE_LOGLEVEL, /* default_message_loglevel */ |
@@ -224,6 +216,7 @@ struct log { | |||
224 | static DEFINE_RAW_SPINLOCK(logbuf_lock); | 216 | static DEFINE_RAW_SPINLOCK(logbuf_lock); |
225 | 217 | ||
226 | #ifdef CONFIG_PRINTK | 218 | #ifdef CONFIG_PRINTK |
219 | DECLARE_WAIT_QUEUE_HEAD(log_wait); | ||
227 | /* the next printk record to read by syslog(READ) or /proc/kmsg */ | 220 | /* the next printk record to read by syslog(READ) or /proc/kmsg */ |
228 | static u64 syslog_seq; | 221 | static u64 syslog_seq; |
229 | static u32 syslog_idx; | 222 | static u32 syslog_idx; |
@@ -609,7 +602,8 @@ static unsigned int devkmsg_poll(struct file *file, poll_table *wait) | |||
609 | /* return error when data has vanished underneath us */ | 602 | /* return error when data has vanished underneath us */ |
610 | if (user->seq < log_first_seq) | 603 | if (user->seq < log_first_seq) |
611 | ret = POLLIN|POLLRDNORM|POLLERR|POLLPRI; | 604 | ret = POLLIN|POLLRDNORM|POLLERR|POLLPRI; |
612 | ret = POLLIN|POLLRDNORM; | 605 | else |
606 | ret = POLLIN|POLLRDNORM; | ||
613 | } | 607 | } |
614 | raw_spin_unlock_irq(&logbuf_lock); | 608 | raw_spin_unlock_irq(&logbuf_lock); |
615 | 609 | ||
@@ -1266,7 +1260,7 @@ static void call_console_drivers(int level, const char *text, size_t len) | |||
1266 | { | 1260 | { |
1267 | struct console *con; | 1261 | struct console *con; |
1268 | 1262 | ||
1269 | trace_console(text, 0, len, len); | 1263 | trace_console(text, len); |
1270 | 1264 | ||
1271 | if (level >= console_loglevel && !ignore_loglevel) | 1265 | if (level >= console_loglevel && !ignore_loglevel) |
1272 | return; | 1266 | return; |
@@ -1724,6 +1718,29 @@ static size_t cont_print_text(char *text, size_t size) { return 0; } | |||
1724 | 1718 | ||
1725 | #endif /* CONFIG_PRINTK */ | 1719 | #endif /* CONFIG_PRINTK */ |
1726 | 1720 | ||
1721 | #ifdef CONFIG_EARLY_PRINTK | ||
1722 | struct console *early_console; | ||
1723 | |||
1724 | void early_vprintk(const char *fmt, va_list ap) | ||
1725 | { | ||
1726 | if (early_console) { | ||
1727 | char buf[512]; | ||
1728 | int n = vscnprintf(buf, sizeof(buf), fmt, ap); | ||
1729 | |||
1730 | early_console->write(early_console, buf, n); | ||
1731 | } | ||
1732 | } | ||
1733 | |||
1734 | asmlinkage void early_printk(const char *fmt, ...) | ||
1735 | { | ||
1736 | va_list ap; | ||
1737 | |||
1738 | va_start(ap, fmt); | ||
1739 | early_vprintk(fmt, ap); | ||
1740 | va_end(ap); | ||
1741 | } | ||
1742 | #endif | ||
1743 | |||
1727 | static int __add_preferred_console(char *name, int idx, char *options, | 1744 | static int __add_preferred_console(char *name, int idx, char *options, |
1728 | char *brl_options) | 1745 | char *brl_options) |
1729 | { | 1746 | { |
@@ -1957,45 +1974,6 @@ int is_console_locked(void) | |||
1957 | return console_locked; | 1974 | return console_locked; |
1958 | } | 1975 | } |
1959 | 1976 | ||
1960 | /* | ||
1961 | * Delayed printk version, for scheduler-internal messages: | ||
1962 | */ | ||
1963 | #define PRINTK_BUF_SIZE 512 | ||
1964 | |||
1965 | #define PRINTK_PENDING_WAKEUP 0x01 | ||
1966 | #define PRINTK_PENDING_SCHED 0x02 | ||
1967 | |||
1968 | static DEFINE_PER_CPU(int, printk_pending); | ||
1969 | static DEFINE_PER_CPU(char [PRINTK_BUF_SIZE], printk_sched_buf); | ||
1970 | |||
1971 | static void wake_up_klogd_work_func(struct irq_work *irq_work) | ||
1972 | { | ||
1973 | int pending = __this_cpu_xchg(printk_pending, 0); | ||
1974 | |||
1975 | if (pending & PRINTK_PENDING_SCHED) { | ||
1976 | char *buf = __get_cpu_var(printk_sched_buf); | ||
1977 | printk(KERN_WARNING "[sched_delayed] %s", buf); | ||
1978 | } | ||
1979 | |||
1980 | if (pending & PRINTK_PENDING_WAKEUP) | ||
1981 | wake_up_interruptible(&log_wait); | ||
1982 | } | ||
1983 | |||
1984 | static DEFINE_PER_CPU(struct irq_work, wake_up_klogd_work) = { | ||
1985 | .func = wake_up_klogd_work_func, | ||
1986 | .flags = IRQ_WORK_LAZY, | ||
1987 | }; | ||
1988 | |||
1989 | void wake_up_klogd(void) | ||
1990 | { | ||
1991 | preempt_disable(); | ||
1992 | if (waitqueue_active(&log_wait)) { | ||
1993 | this_cpu_or(printk_pending, PRINTK_PENDING_WAKEUP); | ||
1994 | irq_work_queue(&__get_cpu_var(wake_up_klogd_work)); | ||
1995 | } | ||
1996 | preempt_enable(); | ||
1997 | } | ||
1998 | |||
1999 | static void console_cont_flush(char *text, size_t size) | 1977 | static void console_cont_flush(char *text, size_t size) |
2000 | { | 1978 | { |
2001 | unsigned long flags; | 1979 | unsigned long flags; |
@@ -2458,6 +2436,44 @@ static int __init printk_late_init(void) | |||
2458 | late_initcall(printk_late_init); | 2436 | late_initcall(printk_late_init); |
2459 | 2437 | ||
2460 | #if defined CONFIG_PRINTK | 2438 | #if defined CONFIG_PRINTK |
2439 | /* | ||
2440 | * Delayed printk version, for scheduler-internal messages: | ||
2441 | */ | ||
2442 | #define PRINTK_BUF_SIZE 512 | ||
2443 | |||
2444 | #define PRINTK_PENDING_WAKEUP 0x01 | ||
2445 | #define PRINTK_PENDING_SCHED 0x02 | ||
2446 | |||
2447 | static DEFINE_PER_CPU(int, printk_pending); | ||
2448 | static DEFINE_PER_CPU(char [PRINTK_BUF_SIZE], printk_sched_buf); | ||
2449 | |||
2450 | static void wake_up_klogd_work_func(struct irq_work *irq_work) | ||
2451 | { | ||
2452 | int pending = __this_cpu_xchg(printk_pending, 0); | ||
2453 | |||
2454 | if (pending & PRINTK_PENDING_SCHED) { | ||
2455 | char *buf = __get_cpu_var(printk_sched_buf); | ||
2456 | printk(KERN_WARNING "[sched_delayed] %s", buf); | ||
2457 | } | ||
2458 | |||
2459 | if (pending & PRINTK_PENDING_WAKEUP) | ||
2460 | wake_up_interruptible(&log_wait); | ||
2461 | } | ||
2462 | |||
2463 | static DEFINE_PER_CPU(struct irq_work, wake_up_klogd_work) = { | ||
2464 | .func = wake_up_klogd_work_func, | ||
2465 | .flags = IRQ_WORK_LAZY, | ||
2466 | }; | ||
2467 | |||
2468 | void wake_up_klogd(void) | ||
2469 | { | ||
2470 | preempt_disable(); | ||
2471 | if (waitqueue_active(&log_wait)) { | ||
2472 | this_cpu_or(printk_pending, PRINTK_PENDING_WAKEUP); | ||
2473 | irq_work_queue(&__get_cpu_var(wake_up_klogd_work)); | ||
2474 | } | ||
2475 | preempt_enable(); | ||
2476 | } | ||
2461 | 2477 | ||
2462 | int printk_sched(const char *fmt, ...) | 2478 | int printk_sched(const char *fmt, ...) |
2463 | { | 2479 | { |
@@ -2834,4 +2850,65 @@ void kmsg_dump_rewind(struct kmsg_dumper *dumper) | |||
2834 | raw_spin_unlock_irqrestore(&logbuf_lock, flags); | 2850 | raw_spin_unlock_irqrestore(&logbuf_lock, flags); |
2835 | } | 2851 | } |
2836 | EXPORT_SYMBOL_GPL(kmsg_dump_rewind); | 2852 | EXPORT_SYMBOL_GPL(kmsg_dump_rewind); |
2853 | |||
2854 | static char dump_stack_arch_desc_str[128]; | ||
2855 | |||
2856 | /** | ||
2857 | * dump_stack_set_arch_desc - set arch-specific str to show with task dumps | ||
2858 | * @fmt: printf-style format string | ||
2859 | * @...: arguments for the format string | ||
2860 | * | ||
2861 | * The configured string will be printed right after utsname during task | ||
2862 | * dumps. Usually used to add arch-specific system identifiers. If an | ||
2863 | * arch wants to make use of such an ID string, it should initialize this | ||
2864 | * as soon as possible during boot. | ||
2865 | */ | ||
2866 | void __init dump_stack_set_arch_desc(const char *fmt, ...) | ||
2867 | { | ||
2868 | va_list args; | ||
2869 | |||
2870 | va_start(args, fmt); | ||
2871 | vsnprintf(dump_stack_arch_desc_str, sizeof(dump_stack_arch_desc_str), | ||
2872 | fmt, args); | ||
2873 | va_end(args); | ||
2874 | } | ||
2875 | |||
2876 | /** | ||
2877 | * dump_stack_print_info - print generic debug info for dump_stack() | ||
2878 | * @log_lvl: log level | ||
2879 | * | ||
2880 | * Arch-specific dump_stack() implementations can use this function to | ||
2881 | * print out the same debug information as the generic dump_stack(). | ||
2882 | */ | ||
2883 | void dump_stack_print_info(const char *log_lvl) | ||
2884 | { | ||
2885 | printk("%sCPU: %d PID: %d Comm: %.20s %s %s %.*s\n", | ||
2886 | log_lvl, raw_smp_processor_id(), current->pid, current->comm, | ||
2887 | print_tainted(), init_utsname()->release, | ||
2888 | (int)strcspn(init_utsname()->version, " "), | ||
2889 | init_utsname()->version); | ||
2890 | |||
2891 | if (dump_stack_arch_desc_str[0] != '\0') | ||
2892 | printk("%sHardware name: %s\n", | ||
2893 | log_lvl, dump_stack_arch_desc_str); | ||
2894 | |||
2895 | print_worker_info(log_lvl, current); | ||
2896 | } | ||
2897 | |||
2898 | /** | ||
2899 | * show_regs_print_info - print generic debug info for show_regs() | ||
2900 | * @log_lvl: log level | ||
2901 | * | ||
2902 | * show_regs() implementations can use this function to print out generic | ||
2903 | * debug information. | ||
2904 | */ | ||
2905 | void show_regs_print_info(const char *log_lvl) | ||
2906 | { | ||
2907 | dump_stack_print_info(log_lvl); | ||
2908 | |||
2909 | printk("%stask: %p ti: %p task.ti: %p\n", | ||
2910 | log_lvl, current, current_thread_info(), | ||
2911 | task_thread_info(current)); | ||
2912 | } | ||
2913 | |||
2837 | #endif | 2914 | #endif |