diff options
Diffstat (limited to 'kernel/debug/kdb/kdb_main.c')
| -rw-r--r-- | kernel/debug/kdb/kdb_main.c | 106 |
1 files changed, 34 insertions, 72 deletions
diff --git a/kernel/debug/kdb/kdb_main.c b/kernel/debug/kdb/kdb_main.c index 67b847dfa2bb..31df1706b9a9 100644 --- a/kernel/debug/kdb/kdb_main.c +++ b/kernel/debug/kdb/kdb_main.c | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #include <linux/ctype.h> | 14 | #include <linux/ctype.h> |
| 15 | #include <linux/string.h> | 15 | #include <linux/string.h> |
| 16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
| 17 | #include <linux/kmsg_dump.h> | ||
| 17 | #include <linux/reboot.h> | 18 | #include <linux/reboot.h> |
| 18 | #include <linux/sched.h> | 19 | #include <linux/sched.h> |
| 19 | #include <linux/sysrq.h> | 20 | #include <linux/sysrq.h> |
| @@ -138,11 +139,10 @@ static const int __nkdb_err = sizeof(kdbmsgs) / sizeof(kdbmsg_t); | |||
| 138 | static char *__env[] = { | 139 | static char *__env[] = { |
| 139 | #if defined(CONFIG_SMP) | 140 | #if defined(CONFIG_SMP) |
| 140 | "PROMPT=[%d]kdb> ", | 141 | "PROMPT=[%d]kdb> ", |
| 141 | "MOREPROMPT=[%d]more> ", | ||
| 142 | #else | 142 | #else |
| 143 | "PROMPT=kdb> ", | 143 | "PROMPT=kdb> ", |
| 144 | "MOREPROMPT=more> ", | ||
| 145 | #endif | 144 | #endif |
| 145 | "MOREPROMPT=more> ", | ||
| 146 | "RADIX=16", | 146 | "RADIX=16", |
| 147 | "MDCOUNT=8", /* lines of md output */ | 147 | "MDCOUNT=8", /* lines of md output */ |
| 148 | KDB_PLATFORM_ENV, | 148 | KDB_PLATFORM_ENV, |
| @@ -1235,18 +1235,6 @@ static int kdb_local(kdb_reason_t reason, int error, struct pt_regs *regs, | |||
| 1235 | *cmdbuf = '\0'; | 1235 | *cmdbuf = '\0'; |
| 1236 | *(cmd_hist[cmd_head]) = '\0'; | 1236 | *(cmd_hist[cmd_head]) = '\0'; |
| 1237 | 1237 | ||
| 1238 | if (KDB_FLAG(ONLY_DO_DUMP)) { | ||
| 1239 | /* kdb is off but a catastrophic error requires a dump. | ||
| 1240 | * Take the dump and reboot. | ||
| 1241 | * Turn on logging so the kdb output appears in the log | ||
| 1242 | * buffer in the dump. | ||
| 1243 | */ | ||
| 1244 | const char *setargs[] = { "set", "LOGGING", "1" }; | ||
| 1245 | kdb_set(2, setargs); | ||
| 1246 | kdb_reboot(0, NULL); | ||
| 1247 | /*NOTREACHED*/ | ||
| 1248 | } | ||
| 1249 | |||
| 1250 | do_full_getstr: | 1238 | do_full_getstr: |
| 1251 | #if defined(CONFIG_SMP) | 1239 | #if defined(CONFIG_SMP) |
| 1252 | snprintf(kdb_prompt_str, CMD_BUFLEN, kdbgetenv("PROMPT"), | 1240 | snprintf(kdb_prompt_str, CMD_BUFLEN, kdbgetenv("PROMPT"), |
| @@ -2040,8 +2028,15 @@ static int kdb_env(int argc, const char **argv) | |||
| 2040 | */ | 2028 | */ |
| 2041 | static int kdb_dmesg(int argc, const char **argv) | 2029 | static int kdb_dmesg(int argc, const char **argv) |
| 2042 | { | 2030 | { |
| 2043 | char *syslog_data[4], *start, *end, c = '\0', *p; | 2031 | int diag; |
| 2044 | int diag, logging, logsize, lines = 0, adjust = 0, n; | 2032 | int logging; |
| 2033 | int lines = 0; | ||
| 2034 | int adjust = 0; | ||
| 2035 | int n = 0; | ||
| 2036 | int skip = 0; | ||
| 2037 | struct kmsg_dumper dumper = { .active = 1 }; | ||
| 2038 | size_t len; | ||
| 2039 | char buf[201]; | ||
| 2045 | 2040 | ||
| 2046 | if (argc > 2) | 2041 | if (argc > 2) |
| 2047 | return KDB_ARGCOUNT; | 2042 | return KDB_ARGCOUNT; |
| @@ -2064,22 +2059,10 @@ static int kdb_dmesg(int argc, const char **argv) | |||
| 2064 | kdb_set(2, setargs); | 2059 | kdb_set(2, setargs); |
| 2065 | } | 2060 | } |
| 2066 | 2061 | ||
| 2067 | /* syslog_data[0,1] physical start, end+1. syslog_data[2,3] | 2062 | kmsg_dump_rewind_nolock(&dumper); |
| 2068 | * logical start, end+1. */ | 2063 | while (kmsg_dump_get_line_nolock(&dumper, 1, NULL, 0, NULL)) |
| 2069 | kdb_syslog_data(syslog_data); | 2064 | n++; |
| 2070 | if (syslog_data[2] == syslog_data[3]) | 2065 | |
| 2071 | return 0; | ||
| 2072 | logsize = syslog_data[1] - syslog_data[0]; | ||
| 2073 | start = syslog_data[2]; | ||
| 2074 | end = syslog_data[3]; | ||
| 2075 | #define KDB_WRAP(p) (((p - syslog_data[0]) % logsize) + syslog_data[0]) | ||
| 2076 | for (n = 0, p = start; p < end; ++p) { | ||
| 2077 | c = *KDB_WRAP(p); | ||
| 2078 | if (c == '\n') | ||
| 2079 | ++n; | ||
| 2080 | } | ||
| 2081 | if (c != '\n') | ||
| 2082 | ++n; | ||
| 2083 | if (lines < 0) { | 2066 | if (lines < 0) { |
| 2084 | if (adjust >= n) | 2067 | if (adjust >= n) |
| 2085 | kdb_printf("buffer only contains %d lines, nothing " | 2068 | kdb_printf("buffer only contains %d lines, nothing " |
| @@ -2087,21 +2070,11 @@ static int kdb_dmesg(int argc, const char **argv) | |||
| 2087 | else if (adjust - lines >= n) | 2070 | else if (adjust - lines >= n) |
| 2088 | kdb_printf("buffer only contains %d lines, last %d " | 2071 | kdb_printf("buffer only contains %d lines, last %d " |
| 2089 | "lines printed\n", n, n - adjust); | 2072 | "lines printed\n", n, n - adjust); |
| 2090 | if (adjust) { | 2073 | skip = adjust; |
| 2091 | for (; start < end && adjust; ++start) { | 2074 | lines = abs(lines); |
| 2092 | if (*KDB_WRAP(start) == '\n') | ||
| 2093 | --adjust; | ||
| 2094 | } | ||
| 2095 | if (start < end) | ||
| 2096 | ++start; | ||
| 2097 | } | ||
| 2098 | for (p = start; p < end && lines; ++p) { | ||
| 2099 | if (*KDB_WRAP(p) == '\n') | ||
| 2100 | ++lines; | ||
| 2101 | } | ||
| 2102 | end = p; | ||
| 2103 | } else if (lines > 0) { | 2075 | } else if (lines > 0) { |
| 2104 | int skip = n - (adjust + lines); | 2076 | skip = n - lines - adjust; |
| 2077 | lines = abs(lines); | ||
| 2105 | if (adjust >= n) { | 2078 | if (adjust >= n) { |
| 2106 | kdb_printf("buffer only contains %d lines, " | 2079 | kdb_printf("buffer only contains %d lines, " |
| 2107 | "nothing printed\n", n); | 2080 | "nothing printed\n", n); |
| @@ -2112,35 +2085,24 @@ static int kdb_dmesg(int argc, const char **argv) | |||
| 2112 | kdb_printf("buffer only contains %d lines, first " | 2085 | kdb_printf("buffer only contains %d lines, first " |
| 2113 | "%d lines printed\n", n, lines); | 2086 | "%d lines printed\n", n, lines); |
| 2114 | } | 2087 | } |
| 2115 | for (; start < end && skip; ++start) { | 2088 | } else { |
| 2116 | if (*KDB_WRAP(start) == '\n') | 2089 | lines = n; |
| 2117 | --skip; | ||
| 2118 | } | ||
| 2119 | for (p = start; p < end && lines; ++p) { | ||
| 2120 | if (*KDB_WRAP(p) == '\n') | ||
| 2121 | --lines; | ||
| 2122 | } | ||
| 2123 | end = p; | ||
| 2124 | } | 2090 | } |
| 2125 | /* Do a line at a time (max 200 chars) to reduce protocol overhead */ | 2091 | |
| 2126 | c = '\n'; | 2092 | if (skip >= n || skip < 0) |
| 2127 | while (start != end) { | 2093 | return 0; |
| 2128 | char buf[201]; | 2094 | |
| 2129 | p = buf; | 2095 | kmsg_dump_rewind_nolock(&dumper); |
| 2130 | if (KDB_FLAG(CMD_INTERRUPT)) | 2096 | while (kmsg_dump_get_line_nolock(&dumper, 1, buf, sizeof(buf), &len)) { |
| 2131 | return 0; | 2097 | if (skip) { |
| 2132 | while (start < end && (c = *KDB_WRAP(start)) && | 2098 | skip--; |
| 2133 | (p - buf) < sizeof(buf)-1) { | 2099 | continue; |
| 2134 | ++start; | ||
| 2135 | *p++ = c; | ||
| 2136 | if (c == '\n') | ||
| 2137 | break; | ||
| 2138 | } | 2100 | } |
| 2139 | *p = '\0'; | 2101 | if (!lines--) |
| 2140 | kdb_printf("%s", buf); | 2102 | break; |
| 2103 | |||
| 2104 | kdb_printf("%.*s\n", (int)len - 1, buf); | ||
| 2141 | } | 2105 | } |
| 2142 | if (c != '\n') | ||
| 2143 | kdb_printf("\n"); | ||
| 2144 | 2106 | ||
| 2145 | return 0; | 2107 | return 0; |
| 2146 | } | 2108 | } |
