X-Git-Url: https://git.stricted.de/?a=blobdiff_plain;f=kernel%2Fprintk.c;h=617bc0d08e2b77ae53b7b6ea28700f3298b9b891;hb=9d35d890f30da36a08570b39b7939b48b9cfbaff;hp=fa36e149442092f28dd339b03345f2a07fe91b31;hpb=ff9129b06cfb05cb5920f1151c75506afe1586fe;p=GitHub%2Fmt8127%2Fandroid_kernel_alcatel_ttab.git diff --git a/kernel/printk.c b/kernel/printk.c index fa36e1494420..617bc0d08e2b 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -16,6 +16,7 @@ * 01Mar01 Andrew Morton */ + #include #include #include @@ -34,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -45,18 +47,32 @@ #include #include #include +#include +#include #include #define CREATE_TRACE_POINTS #include +/* Some options {*/ +#define LOG_TOO_MUCH_WARNING +#ifdef LOG_TOO_MUCH_WARNING +static int log_in_resume; +#endif +/* Some options }*/ +#ifdef CONFIG_EARLY_PRINTK_DIRECT +extern void printascii(char *); +#endif + +bool printk_disable_uart = 0; +static DEFINE_PER_CPU(char, printk_state); /* printk's without a loglevel use this.. */ #define DEFAULT_MESSAGE_LOGLEVEL CONFIG_DEFAULT_MESSAGE_LOGLEVEL /* We show everything that is MORE important than this.. */ #define MINIMUM_CONSOLE_LOGLEVEL 1 /* Minimum loglevel we let people use */ -#define DEFAULT_CONSOLE_LOGLEVEL 7 /* anything MORE serious than KERN_DEBUG */ +#define DEFAULT_CONSOLE_LOGLEVEL 6 /* anything MORE serious than KERN_INFO */ int console_printk[4] = { DEFAULT_CONSOLE_LOGLEVEL, /* console_loglevel */ @@ -64,6 +80,7 @@ int console_printk[4] = { MINIMUM_CONSOLE_LOGLEVEL, /* minimum_console_loglevel */ DEFAULT_CONSOLE_LOGLEVEL, /* default_console_loglevel */ }; +EXPORT_SYMBOL_GPL(console_printk); /* * Low level drivers may need that to know if they can schedule in @@ -107,7 +124,7 @@ static struct console *exclusive_console; */ struct console_cmdline { - char name[8]; /* Name of the driver */ + char name[16]; /* Name of the driver */ int index; /* Minor dev. to use */ char *options; /* Options for the driver */ #ifdef CONFIG_A11Y_BRAILLE_CONSOLE @@ -225,12 +242,12 @@ static enum log_flags syslog_prev; static size_t syslog_partial; /* index and sequence number of the first record stored in the buffer */ -static u64 log_first_seq; -static u32 log_first_idx; +/*static*/ u64 log_first_seq; +/*static*/ u32 log_first_idx; /* index and sequence number of the next record to store in the buffer */ -static u64 log_next_seq; -static u32 log_next_idx; +/*static*/ u64 log_next_seq; +/*static*/ u32 log_next_idx; /* the next printk record to write to the console */ static u64 console_seq; @@ -255,6 +272,31 @@ static char __log_buf[__LOG_BUF_LEN] __aligned(LOG_ALIGN); static char *log_buf = __log_buf; static u32 log_buf_len = __LOG_BUF_LEN; +#ifdef CONFIG_MT_PRINTK_UART_CONSOLE + +extern int mt_need_uart_console; +inline void mt_disable_uart() +{ + if (mt_need_uart_console == 0) { + printk("<< printk console disable >>\n"); + printk_disable_uart = 1; + } else { + printk("<< printk console can't be disabled >>\n"); + } +} +inline void mt_enable_uart() +{ + if (mt_need_uart_console == 1) { + if (printk_disable_uart == 0) + return; + printk_disable_uart = 0; + printk("<< printk console enable >>\n"); + } else { + printk("<< printk console can't be enabled >>\n"); + } +} + +#endif /* cpu currently holding logbuf_lock */ static volatile unsigned int logbuf_cpu = UINT_MAX; @@ -310,9 +352,24 @@ static void log_store(int facility, int level, { struct log *msg; u32 size, pad_len; - + int this_cpu = smp_processor_id(); + char state = __raw_get_cpu_var(printk_state); + if (state == 0) { + __raw_get_cpu_var(printk_state) = ' '; + state = ' '; + } + /*printk prefix {*/ + char tbuf[50]; + unsigned tlen; + if (console_suspended == 0) { + tlen = snprintf(tbuf, sizeof(tbuf), "%c(%x)[%d:%s]", + state, this_cpu, current->pid, current->comm); + } else { + tlen = snprintf(tbuf, sizeof(tbuf), "%c%x)", state, this_cpu); + } + /*printk prefix }*/ /* number of '\0' padding bytes to next message */ - size = sizeof(struct log) + text_len + dict_len; + size = sizeof(struct log) + text_len +tlen + dict_len; pad_len = (-size) & (LOG_ALIGN - 1); size += pad_len; @@ -344,7 +401,10 @@ static void log_store(int facility, int level, /* fill message */ msg = (struct log *)(log_buf + log_next_idx); - memcpy(log_text(msg), text, text_len); + //memcpy(log_text(msg), text, text_len); + memcpy(log_text(msg), tbuf, tlen); + memcpy(log_text(msg) + tlen, text, text_len); + text_len += tlen; msg->text_len = text_len; memcpy(log_dict(msg), dict, dict_len); msg->dict_len = dict_len; @@ -363,6 +423,53 @@ static void log_store(int facility, int level, log_next_seq++; } +#ifdef CONFIG_SECURITY_DMESG_RESTRICT +int dmesg_restrict = 1; +#else +int dmesg_restrict; +#endif + +static int syslog_action_restricted(int type) +{ + if (dmesg_restrict) + return 1; + /* + * Unless restricted, we allow "read all" and "get buffer size" + * for everybody. + */ + return type != SYSLOG_ACTION_READ_ALL && + type != SYSLOG_ACTION_SIZE_BUFFER; +} + +static int check_syslog_permissions(int type, bool from_file) +{ + /* + * If this is from /proc/kmsg and we've already opened it, then we've + * already done the capabilities checks at open time. + */ + if (from_file && type != SYSLOG_ACTION_OPEN) + return 0; + + if (syslog_action_restricted(type)) { + if (capable(CAP_SYSLOG)) + return 0; + /* + * For historical reasons, accept CAP_SYS_ADMIN too, with + * a warning. + */ + if (capable(CAP_SYS_ADMIN)) { + pr_warn_once("%s (%d): Attempt to access syslog with " + "CAP_SYS_ADMIN but no CAP_SYSLOG " + "(deprecated).\n", + current->comm, task_pid_nr(current)); + return 0; + } + return -EPERM; + } + return security_syslog(type); +} + + /* /dev/kmsg - userspace message inject/listen interface */ struct devkmsg_user { u64 seq; @@ -620,7 +727,8 @@ static int devkmsg_open(struct inode *inode, struct file *file) if ((file->f_flags & O_ACCMODE) == O_WRONLY) return 0; - err = security_syslog(SYSLOG_ACTION_READ_ALL); + err = check_syslog_permissions(SYSLOG_ACTION_READ_ALL, + SYSLOG_FROM_READER); if (err) return err; @@ -813,51 +921,13 @@ static inline void boot_delay_msec(int level) } #endif -#ifdef CONFIG_SECURITY_DMESG_RESTRICT -int dmesg_restrict = 1; -#else -int dmesg_restrict; -#endif - -static int syslog_action_restricted(int type) -{ - if (dmesg_restrict) - return 1; - /* Unless restricted, we allow "read all" and "get buffer size" for everybody */ - return type != SYSLOG_ACTION_READ_ALL && type != SYSLOG_ACTION_SIZE_BUFFER; -} - -static int check_syslog_permissions(int type, bool from_file) -{ - /* - * If this is from /proc/kmsg and we've already opened it, then we've - * already done the capabilities checks at open time. - */ - if (from_file && type != SYSLOG_ACTION_OPEN) - return 0; - - if (syslog_action_restricted(type)) { - if (capable(CAP_SYSLOG)) - return 0; - /* For historical reasons, accept CAP_SYS_ADMIN too, with a warning */ - if (capable(CAP_SYS_ADMIN)) { - printk_once(KERN_WARNING "%s (%d): " - "Attempt to access syslog with CAP_SYS_ADMIN " - "but no CAP_SYSLOG (deprecated).\n", - current->comm, task_pid_nr(current)); - return 0; - } - return -EPERM; - } - return 0; -} - #if defined(CONFIG_PRINTK_TIME) static bool printk_time = 1; #else static bool printk_time; #endif module_param_named(time, printk_time, bool, S_IRUGO | S_IWUSR); +module_param_named(disable_uart, printk_disable_uart, bool, S_IRUGO | S_IWUSR); static size_t print_time(u64 ts, char *buf) { @@ -869,9 +939,9 @@ static size_t print_time(u64 ts, char *buf) rem_nsec = do_div(ts, 1000000000); if (!buf) - return snprintf(NULL, 0, "[%5lu.000000] ", (unsigned long)ts); + return snprintf(NULL, 0, "[%5lu.000000]", (unsigned long)ts); - return sprintf(buf, "[%5lu.%06lu] ", + return sprintf(buf, "[%5lu.%06lu]", (unsigned long)ts, rem_nsec / 1000); } @@ -1249,7 +1319,7 @@ out: SYSCALL_DEFINE3(syslog, int, type, char __user *, buf, int, len) { - return do_syslog(type, buf, len, SYSLOG_FROM_CALL); + return do_syslog(type, buf, len, SYSLOG_FROM_READER); } /* @@ -1269,6 +1339,8 @@ static void call_console_drivers(int level, const char *text, size_t len) return; for_each_console(con) { + if (printk_disable_uart && (con->flags & CON_CONSDEV)) + continue; if (exclusive_console && con != exclusive_console) continue; if (!(con->flags & CON_ENABLED)) @@ -1360,9 +1432,9 @@ static int console_trylock_for_printk(unsigned int cpu) } } logbuf_cpu = UINT_MAX; + raw_spin_unlock(&logbuf_lock); if (wake) up(&console_sem); - raw_spin_unlock(&logbuf_lock); return retval; } @@ -1496,7 +1568,11 @@ asmlinkage int vprintk_emit(int facility, int level, unsigned long flags; int this_cpu; int printed_len = 0; - + int in_irq_disable, in_non_preempt; + in_irq_disable = irqs_disabled(); + in_non_preempt = in_atomic(); + vscnprintf(text, sizeof(textbuf), fmt, args); + memset(text, 0x0, sizeof(textbuf)); boot_delay_msec(level); printk_delay(); @@ -1569,12 +1645,27 @@ asmlinkage int vprintk_emit(int facility, int level, } } +#ifdef CONFIG_EARLY_PRINTK_DIRECT + printascii(text); +#endif + if (level == -1) level = default_message_loglevel; if (dict) lflags |= LOG_PREFIX|LOG_NEWLINE; - + +#ifdef CONFIG_PRINTK_PROCESS_INFO + if (in_irq_disable) + __raw_get_cpu_var(printk_state) = '-'; +#ifdef CONFIG_MT_PRINTK_UART_CONSOLE + else if (printk_disable_uart == 0) + __raw_get_cpu_var(printk_state) = '.'; +#endif + else + __raw_get_cpu_var(printk_state) = ' '; +#endif + if (!(lflags & LOG_NEWLINE)) { /* * Flush the conflicting buffer. An earlier newline was missing, @@ -1890,16 +1981,28 @@ void suspend_console(void) console_lock(); console_suspended = 1; up(&console_sem); + mutex_release(&console_lock_dep_map, 1, _RET_IP_); } +EXPORT_SYMBOL_GPL(suspend_console); void resume_console(void) { if (!console_suspend_enabled) return; down(&console_sem); + mutex_acquire(&console_lock_dep_map, 0, 0, _RET_IP_); console_suspended = 0; - console_unlock(); +#ifdef LOG_TOO_MUCH_WARNING +// __raw_get_cpu_var(MT_trace_in_resume_console) = 1; +// log_in_resume = 1; + console_unlock(); +// log_in_resume = 0; +// __raw_get_cpu_var(MT_trace_in_resume_console) = 0; +#else + console_unlock(); +#endif } +EXPORT_SYMBOL_GPL(resume_console); /** * console_cpu_notify - print deferred console messages after CPU hotplug @@ -2018,6 +2121,10 @@ out: * * console_unlock(); may be called from any context. */ +#ifdef LOG_TOO_MUCH_WARNING +static int console_log_max = 400000; +static int already_skip_log; +#endif void console_unlock(void) { static char text[LOG_LINE_MAX + PREFIX_MAX]; @@ -2025,6 +2132,12 @@ void console_unlock(void) unsigned long flags; bool wake_klogd = false; bool retry; +#ifdef LOG_TOO_MUCH_WARNING + unsigned long total_log_size = 0; + unsigned long long t1 = 0, t2 = 0; + char aee_str[512]; + int org_loglevel = console_loglevel; +#endif if (console_suspended) { up(&console_sem); @@ -2042,6 +2155,12 @@ again: int level; raw_spin_lock_irqsave(&logbuf_lock, flags); +#ifdef LOG_TOO_MUCH_WARNING /*For Resume log too much*/ + if (log_in_resume) { + t1 = sched_clock(); + } +#endif + if (seen_seq != log_next_seq) { wake_klogd = true; seen_seq = log_next_seq; @@ -2084,8 +2203,41 @@ skip: raw_spin_unlock(&logbuf_lock); stop_critical_timings(); /* don't trace print latency */ - call_console_drivers(level, text, len); - start_critical_timings(); +#ifdef LOG_TOO_MUCH_WARNING + /* + For uart console, 10us/per chars + 400,000 chars = need to wait 4.0 sec + normal case: 4sec + */ + if (log_in_resume) { + org_loglevel = console_loglevel; + console_loglevel = 4; + } + total_log_size += len; + if (total_log_size < console_log_max) + call_console_drivers(level, text, len); + else if (!already_skip_log) { + sprintf(aee_str, "PRINTK too much:%lu", total_log_size); + aee_kernel_warning(aee_str, "Need to shrink kernel log"); + already_skip_log = 1; + } + /**/ + start_critical_timings(); + /* For Resume log too much*/ + if (log_in_resume) { + t2 = sched_clock(); + console_loglevel = org_loglevel; + if (t2 - t1 > 100000000) { + sprintf( aee_str,"[RESUME CONSOLE too long:%lluns>100ms] s:%lluns, e:%lluns\n", t2 - t1, t1, t2); + aee_kernel_warning(aee_str, "Need to shrink kernel log"); + } + } + + /**/ +#else + start_critical_timings(); + call_console_drivers(level, text, len); +#endif local_irq_restore(flags); } console_locked = 0; @@ -2281,6 +2433,8 @@ void register_console(struct console *newcon) */ for (i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++) { + BUILD_BUG_ON(sizeof(console_cmdline[i].name) != + sizeof(newcon->name)); if (strcmp(console_cmdline[i].name, newcon->name) != 0) continue; if (newcon->index >= 0 && @@ -2447,6 +2601,7 @@ late_initcall(printk_late_init); static DEFINE_PER_CPU(int, printk_pending); static DEFINE_PER_CPU(char [PRINTK_BUF_SIZE], printk_sched_buf); +static DEFINE_PER_CPU(int, printk_sched_length); static void wake_up_klogd_work_func(struct irq_work *irq_work) { @@ -2454,7 +2609,10 @@ static void wake_up_klogd_work_func(struct irq_work *irq_work) if (pending & PRINTK_PENDING_SCHED) { char *buf = __get_cpu_var(printk_sched_buf); - printk(KERN_WARNING "[sched_delayed] %s", buf); + printk(KERN_WARNING "[printk_delayed:start]\n"); + printk(KERN_WARNING "%s", buf); + printk(KERN_WARNING "[printk_delayed:done]\n"); + __get_cpu_var(printk_sched_length) = 0; } if (pending & PRINTK_PENDING_WAKEUP) @@ -2476,18 +2634,25 @@ void wake_up_klogd(void) preempt_enable(); } -int printk_sched(const char *fmt, ...) +int printk_deferred(const char *fmt, ...) { unsigned long flags; va_list args; char *buf; int r; - + int buf_length; local_irq_save(flags); buf = __get_cpu_var(printk_sched_buf); + buf_length = __get_cpu_var(printk_sched_length); va_start(args, fmt); - r = vsnprintf(buf, PRINTK_BUF_SIZE, fmt, args); + if(PRINTK_BUF_SIZE >= buf_length){ + r = vsnprintf((buf_length + buf), PRINTK_BUF_SIZE-buf_length, fmt, args); + __get_cpu_var(printk_sched_length) += r; + }else{ + printk("delayed log buf overflow, size:%d\n", buf_length); + r = 0; + } va_end(args); __this_cpu_or(printk_pending, PRINTK_PENDING_SCHED); @@ -2912,4 +3077,10 @@ void show_regs_print_info(const char *log_lvl) task_thread_info(current)); } +void get_kernel_log_buffer(unsigned long *addr, unsigned long *size, unsigned long *start) +{ + *addr = (unsigned long)log_buf; + *size = log_buf_len; + *start = (unsigned long)&log_first_idx; +} #endif