aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/debug/kdb/kdb_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/debug/kdb/kdb_main.c')
-rw-r--r--kernel/debug/kdb/kdb_main.c106
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);
138static char *__env[] = { 139static 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
1250do_full_getstr: 1238do_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 */
2041static int kdb_dmesg(int argc, const char **argv) 2029static 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}