15d5314d6SJason Wessel /* 25d5314d6SJason Wessel * Kernel Debugger Architecture Independent Console I/O handler 35d5314d6SJason Wessel * 45d5314d6SJason Wessel * This file is subject to the terms and conditions of the GNU General Public 55d5314d6SJason Wessel * License. See the file "COPYING" in the main directory of this archive 65d5314d6SJason Wessel * for more details. 75d5314d6SJason Wessel * 85d5314d6SJason Wessel * Copyright (c) 1999-2006 Silicon Graphics, Inc. All Rights Reserved. 95d5314d6SJason Wessel * Copyright (c) 2009 Wind River Systems, Inc. All Rights Reserved. 105d5314d6SJason Wessel */ 115d5314d6SJason Wessel 125d5314d6SJason Wessel #include <linux/types.h> 135d5314d6SJason Wessel #include <linux/ctype.h> 145d5314d6SJason Wessel #include <linux/kernel.h> 155d5314d6SJason Wessel #include <linux/init.h> 165d5314d6SJason Wessel #include <linux/kdev_t.h> 175d5314d6SJason Wessel #include <linux/console.h> 185d5314d6SJason Wessel #include <linux/string.h> 195d5314d6SJason Wessel #include <linux/sched.h> 205d5314d6SJason Wessel #include <linux/smp.h> 215d5314d6SJason Wessel #include <linux/nmi.h> 225d5314d6SJason Wessel #include <linux/delay.h> 23a0de055cSJason Wessel #include <linux/kgdb.h> 245d5314d6SJason Wessel #include <linux/kdb.h> 255d5314d6SJason Wessel #include <linux/kallsyms.h> 265d5314d6SJason Wessel #include "kdb_private.h" 275d5314d6SJason Wessel 285d5314d6SJason Wessel #define CMD_BUFLEN 256 295d5314d6SJason Wessel char kdb_prompt_str[CMD_BUFLEN]; 305d5314d6SJason Wessel 31d37d39aeSJason Wessel int kdb_trap_printk; 3234aaff40SPetr Mladek int kdb_printf_cpu = -1; 335d5314d6SJason Wessel 3437f86b46SJason Wessel static int kgdb_transition_check(char *buffer) 355d5314d6SJason Wessel { 3637f86b46SJason Wessel if (buffer[0] != '+' && buffer[0] != '$') { 375d5314d6SJason Wessel KDB_STATE_SET(KGDB_TRANS); 385d5314d6SJason Wessel kdb_printf("%s", buffer); 3937f86b46SJason Wessel } else { 4037f86b46SJason Wessel int slen = strlen(buffer); 4137f86b46SJason Wessel if (slen > 3 && buffer[slen - 3] == '#') { 4237f86b46SJason Wessel kdb_gdb_state_pass(buffer); 4337f86b46SJason Wessel strcpy(buffer, "kgdb"); 4437f86b46SJason Wessel KDB_STATE_SET(DOING_KGDB); 4537f86b46SJason Wessel return 1; 465d5314d6SJason Wessel } 475d5314d6SJason Wessel } 4837f86b46SJason Wessel return 0; 4937f86b46SJason Wessel } 505d5314d6SJason Wessel 5153b63136SDaniel Thompson /** 5253b63136SDaniel Thompson * kdb_handle_escape() - validity check on an accumulated escape sequence. 5353b63136SDaniel Thompson * @buf: Accumulated escape characters to be examined. Note that buf 5453b63136SDaniel Thompson * is not a string, it is an array of characters and need not be 5553b63136SDaniel Thompson * nil terminated. 5653b63136SDaniel Thompson * @sz: Number of accumulated escape characters. 5753b63136SDaniel Thompson * 5853b63136SDaniel Thompson * Return: -1 if the escape sequence is unwanted, 0 if it is incomplete, 5953b63136SDaniel Thompson * otherwise it returns a mapped key value to pass to the upper layers. 6053b63136SDaniel Thompson */ 6153b63136SDaniel Thompson static int kdb_handle_escape(char *buf, size_t sz) 6253b63136SDaniel Thompson { 6353b63136SDaniel Thompson char *lastkey = buf + sz - 1; 6453b63136SDaniel Thompson 6553b63136SDaniel Thompson switch (sz) { 6653b63136SDaniel Thompson case 1: 6753b63136SDaniel Thompson if (*lastkey == '\e') 6853b63136SDaniel Thompson return 0; 6953b63136SDaniel Thompson break; 7053b63136SDaniel Thompson 7153b63136SDaniel Thompson case 2: /* \e<something> */ 7253b63136SDaniel Thompson if (*lastkey == '[') 7353b63136SDaniel Thompson return 0; 7453b63136SDaniel Thompson break; 7553b63136SDaniel Thompson 7653b63136SDaniel Thompson case 3: 7753b63136SDaniel Thompson switch (*lastkey) { 7853b63136SDaniel Thompson case 'A': /* \e[A, up arrow */ 7953b63136SDaniel Thompson return 16; 8053b63136SDaniel Thompson case 'B': /* \e[B, down arrow */ 8153b63136SDaniel Thompson return 14; 8253b63136SDaniel Thompson case 'C': /* \e[C, right arrow */ 8353b63136SDaniel Thompson return 6; 8453b63136SDaniel Thompson case 'D': /* \e[D, left arrow */ 8553b63136SDaniel Thompson return 2; 8653b63136SDaniel Thompson case '1': /* \e[<1,3,4>], may be home, del, end */ 8753b63136SDaniel Thompson case '3': 8853b63136SDaniel Thompson case '4': 8953b63136SDaniel Thompson return 0; 9053b63136SDaniel Thompson } 9153b63136SDaniel Thompson break; 9253b63136SDaniel Thompson 9353b63136SDaniel Thompson case 4: 9453b63136SDaniel Thompson if (*lastkey == '~') { 9553b63136SDaniel Thompson switch (buf[2]) { 9653b63136SDaniel Thompson case '1': /* \e[1~, home */ 9753b63136SDaniel Thompson return 1; 9853b63136SDaniel Thompson case '3': /* \e[3~, del */ 9953b63136SDaniel Thompson return 4; 10053b63136SDaniel Thompson case '4': /* \e[4~, end */ 10153b63136SDaniel Thompson return 5; 10253b63136SDaniel Thompson } 10353b63136SDaniel Thompson } 10453b63136SDaniel Thompson break; 10553b63136SDaniel Thompson } 10653b63136SDaniel Thompson 10753b63136SDaniel Thompson return -1; 10853b63136SDaniel Thompson } 10953b63136SDaniel Thompson 1104f27e824SDaniel Thompson /** 1114f27e824SDaniel Thompson * kdb_getchar() - Read a single character from a kdb console (or consoles). 1124f27e824SDaniel Thompson * 1134f27e824SDaniel Thompson * Other than polling the various consoles that are currently enabled, 1144f27e824SDaniel Thompson * most of the work done in this function is dealing with escape sequences. 1154f27e824SDaniel Thompson * 1164f27e824SDaniel Thompson * An escape key could be the start of a vt100 control sequence such as \e[D 1174f27e824SDaniel Thompson * (left arrow) or it could be a character in its own right. The standard 1184f27e824SDaniel Thompson * method for detecting the difference is to wait for 2 seconds to see if there 1194f27e824SDaniel Thompson * are any other characters. kdb is complicated by the lack of a timer service 1204f27e824SDaniel Thompson * (interrupts are off), by multiple input sources. Escape sequence processing 1214f27e824SDaniel Thompson * has to be done as states in the polling loop. 1224f27e824SDaniel Thompson * 1234f27e824SDaniel Thompson * Return: The key pressed or a control code derived from an escape sequence. 1244f27e824SDaniel Thompson */ 1254f27e824SDaniel Thompson char kdb_getchar(void) 1265d5314d6SJason Wessel { 1275d5314d6SJason Wessel #define ESCAPE_UDELAY 1000 1285d5314d6SJason Wessel #define ESCAPE_DELAY (2*1000000/ESCAPE_UDELAY) /* 2 seconds worth of udelays */ 129cdca8d89SDaniel Thompson char buf[4]; /* longest vt100 escape sequence is 4 bytes */ 130cdca8d89SDaniel Thompson char *pbuf = buf; 1315d5314d6SJason Wessel int escape_delay = 0; 132cdca8d89SDaniel Thompson get_char_func *f, *f_prev = NULL; 1335d5314d6SJason Wessel int key; 1341ed05558SDouglas Anderson static bool last_char_was_cr; 1355d5314d6SJason Wessel 1365d5314d6SJason Wessel for (f = &kdb_poll_funcs[0]; ; ++f) { 1375d5314d6SJason Wessel if (*f == NULL) { 1385d5314d6SJason Wessel /* Reset NMI watchdog once per poll loop */ 1395d5314d6SJason Wessel touch_nmi_watchdog(); 1405d5314d6SJason Wessel f = &kdb_poll_funcs[0]; 1415d5314d6SJason Wessel } 142d04213afSDaniel Thompson 1435d5314d6SJason Wessel key = (*f)(); 1445d5314d6SJason Wessel if (key == -1) { 1455d5314d6SJason Wessel if (escape_delay) { 1465d5314d6SJason Wessel udelay(ESCAPE_UDELAY); 147d04213afSDaniel Thompson if (--escape_delay == 0) 148d04213afSDaniel Thompson return '\e'; 1495d5314d6SJason Wessel } 1505d5314d6SJason Wessel continue; 1515d5314d6SJason Wessel } 152d04213afSDaniel Thompson 153cdca8d89SDaniel Thompson /* 1541ed05558SDouglas Anderson * The caller expects that newlines are either CR or LF. However 1551ed05558SDouglas Anderson * some terminals send _both_ CR and LF. Avoid having to handle 1561ed05558SDouglas Anderson * this in the caller by stripping the LF if we saw a CR right 1571ed05558SDouglas Anderson * before. 1581ed05558SDouglas Anderson */ 1591ed05558SDouglas Anderson if (last_char_was_cr && key == '\n') { 1601ed05558SDouglas Anderson last_char_was_cr = false; 1611ed05558SDouglas Anderson continue; 1621ed05558SDouglas Anderson } 1631ed05558SDouglas Anderson last_char_was_cr = (key == '\r'); 1641ed05558SDouglas Anderson 1651ed05558SDouglas Anderson /* 166cdca8d89SDaniel Thompson * When the first character is received (or we get a change 167cdca8d89SDaniel Thompson * input source) we set ourselves up to handle an escape 168cdca8d89SDaniel Thompson * sequences (just in case). 169cdca8d89SDaniel Thompson */ 170cdca8d89SDaniel Thompson if (f_prev != f) { 171cdca8d89SDaniel Thompson f_prev = f; 172cdca8d89SDaniel Thompson pbuf = buf; 1735d5314d6SJason Wessel escape_delay = ESCAPE_DELAY; 1745d5314d6SJason Wessel } 17553b63136SDaniel Thompson 176cdca8d89SDaniel Thompson *pbuf++ = key; 177cdca8d89SDaniel Thompson key = kdb_handle_escape(buf, pbuf - buf); 178c58ff643SDaniel Thompson if (key < 0) /* no escape sequence; return best character */ 179c58ff643SDaniel Thompson return buf[pbuf - buf == 2 ? 1 : 0]; 180cdca8d89SDaniel Thompson if (key > 0) 1815d5314d6SJason Wessel return key; 1825d5314d6SJason Wessel } 1835d5314d6SJason Wessel 184cdca8d89SDaniel Thompson unreachable(); 185cdca8d89SDaniel Thompson } 186cdca8d89SDaniel Thompson 187d373d3c6SDaniel Thompson /** 188d373d3c6SDaniel Thompson * kdb_position_cursor() - Place cursor in the correct horizontal position 189d373d3c6SDaniel Thompson * @prompt: Nil-terminated string containing the prompt string 190d373d3c6SDaniel Thompson * @buffer: Nil-terminated string containing the entire command line 191d373d3c6SDaniel Thompson * @cp: Cursor position, pointer the character in buffer where the cursor 192d373d3c6SDaniel Thompson * should be positioned. 193d373d3c6SDaniel Thompson * 194d373d3c6SDaniel Thompson * The cursor is positioned by sending a carriage-return and then printing 195d373d3c6SDaniel Thompson * the content of the line until we reach the correct cursor position. 196d373d3c6SDaniel Thompson * 197d373d3c6SDaniel Thompson * There is some additional fine detail here. 198d373d3c6SDaniel Thompson * 199d373d3c6SDaniel Thompson * Firstly, even though kdb_printf() will correctly format zero-width fields 200d373d3c6SDaniel Thompson * we want the second call to kdb_printf() to be conditional. That keeps things 201d373d3c6SDaniel Thompson * a little cleaner when LOGGING=1. 202d373d3c6SDaniel Thompson * 203d373d3c6SDaniel Thompson * Secondly, we can't combine everything into one call to kdb_printf() since 204d373d3c6SDaniel Thompson * that renders into a fixed length buffer and the combined print could result 205d373d3c6SDaniel Thompson * in unwanted truncation. 206d373d3c6SDaniel Thompson */ 207d373d3c6SDaniel Thompson static void kdb_position_cursor(char *prompt, char *buffer, char *cp) 208d373d3c6SDaniel Thompson { 209d373d3c6SDaniel Thompson kdb_printf("\r%s", kdb_prompt_str); 210d373d3c6SDaniel Thompson if (cp > buffer) 211d373d3c6SDaniel Thompson kdb_printf("%.*s", (int)(cp - buffer), buffer); 212d373d3c6SDaniel Thompson } 213d373d3c6SDaniel Thompson 2145d5314d6SJason Wessel /* 2155d5314d6SJason Wessel * kdb_read 2165d5314d6SJason Wessel * 2175d5314d6SJason Wessel * This function reads a string of characters, terminated by 2185d5314d6SJason Wessel * a newline, or by reaching the end of the supplied buffer, 2195d5314d6SJason Wessel * from the current kernel debugger console device. 2205d5314d6SJason Wessel * Parameters: 2215d5314d6SJason Wessel * buffer - Address of character buffer to receive input characters. 2225d5314d6SJason Wessel * bufsize - size, in bytes, of the character buffer 2235d5314d6SJason Wessel * Returns: 2245d5314d6SJason Wessel * Returns a pointer to the buffer containing the received 2255d5314d6SJason Wessel * character string. This string will be terminated by a 2265d5314d6SJason Wessel * newline character. 2275d5314d6SJason Wessel * Locking: 2285d5314d6SJason Wessel * No locks are required to be held upon entry to this 2295d5314d6SJason Wessel * function. It is not reentrant - it relies on the fact 2305d5314d6SJason Wessel * that while kdb is running on only one "master debug" cpu. 2315d5314d6SJason Wessel * Remarks: 2324f27e824SDaniel Thompson * The buffer size must be >= 2. 2335d5314d6SJason Wessel */ 2345d5314d6SJason Wessel 2355d5314d6SJason Wessel static char *kdb_read(char *buffer, size_t bufsize) 2365d5314d6SJason Wessel { 2375d5314d6SJason Wessel char *cp = buffer; 2385d5314d6SJason Wessel char *bufend = buffer+bufsize-2; /* Reserve space for newline 2395d5314d6SJason Wessel * and null byte */ 2405d5314d6SJason Wessel char *lastchar; 2415d5314d6SJason Wessel char *p_tmp; 2425d5314d6SJason Wessel static char tmpbuffer[CMD_BUFLEN]; 2435d5314d6SJason Wessel int len = strlen(buffer); 2445d5314d6SJason Wessel int len_tmp; 2455d5314d6SJason Wessel int tab = 0; 2465d5314d6SJason Wessel int count; 2475d5314d6SJason Wessel int i; 2485d5314d6SJason Wessel int diag, dtab_count; 249c2b94c72SPrarit Bhargava int key, buf_size, ret; 2505d5314d6SJason Wessel 2515d5314d6SJason Wessel 2525d5314d6SJason Wessel diag = kdbgetintenv("DTABCOUNT", &dtab_count); 2535d5314d6SJason Wessel if (diag) 2545d5314d6SJason Wessel dtab_count = 30; 2555d5314d6SJason Wessel 2565d5314d6SJason Wessel if (len > 0) { 2575d5314d6SJason Wessel cp += len; 2585d5314d6SJason Wessel if (*(buffer+len-1) == '\n') 2595d5314d6SJason Wessel cp--; 2605d5314d6SJason Wessel } 2615d5314d6SJason Wessel 2625d5314d6SJason Wessel lastchar = cp; 2635d5314d6SJason Wessel *cp = '\0'; 2645d5314d6SJason Wessel kdb_printf("%s", buffer); 2655d5314d6SJason Wessel poll_again: 2664f27e824SDaniel Thompson key = kdb_getchar(); 2675d5314d6SJason Wessel if (key != 9) 2685d5314d6SJason Wessel tab = 0; 2695d5314d6SJason Wessel switch (key) { 2705d5314d6SJason Wessel case 8: /* backspace */ 2715d5314d6SJason Wessel if (cp > buffer) { 2725d5314d6SJason Wessel if (cp < lastchar) { 2735d5314d6SJason Wessel memcpy(tmpbuffer, cp, lastchar - cp); 2745d5314d6SJason Wessel memcpy(cp-1, tmpbuffer, lastchar - cp); 2755d5314d6SJason Wessel } 2765d5314d6SJason Wessel *(--lastchar) = '\0'; 2775d5314d6SJason Wessel --cp; 278d373d3c6SDaniel Thompson kdb_printf("\b%s ", cp); 279d373d3c6SDaniel Thompson kdb_position_cursor(kdb_prompt_str, buffer, cp); 2805d5314d6SJason Wessel } 2815d5314d6SJason Wessel break; 2821ed05558SDouglas Anderson case 10: /* linefeed */ 2831ed05558SDouglas Anderson case 13: /* carriage return */ 2845d5314d6SJason Wessel *lastchar++ = '\n'; 2855d5314d6SJason Wessel *lastchar++ = '\0'; 28637f86b46SJason Wessel if (!KDB_STATE(KGDB_TRANS)) { 28737f86b46SJason Wessel KDB_STATE_SET(KGDB_TRANS); 28837f86b46SJason Wessel kdb_printf("%s", buffer); 28937f86b46SJason Wessel } 2905d5314d6SJason Wessel kdb_printf("\n"); 2915d5314d6SJason Wessel return buffer; 2925d5314d6SJason Wessel case 4: /* Del */ 2935d5314d6SJason Wessel if (cp < lastchar) { 2945d5314d6SJason Wessel memcpy(tmpbuffer, cp+1, lastchar - cp - 1); 2955d5314d6SJason Wessel memcpy(cp, tmpbuffer, lastchar - cp - 1); 2965d5314d6SJason Wessel *(--lastchar) = '\0'; 297d373d3c6SDaniel Thompson kdb_printf("%s ", cp); 298d373d3c6SDaniel Thompson kdb_position_cursor(kdb_prompt_str, buffer, cp); 2995d5314d6SJason Wessel } 3005d5314d6SJason Wessel break; 3015d5314d6SJason Wessel case 1: /* Home */ 3025d5314d6SJason Wessel if (cp > buffer) { 3035d5314d6SJason Wessel cp = buffer; 304d373d3c6SDaniel Thompson kdb_position_cursor(kdb_prompt_str, buffer, cp); 3055d5314d6SJason Wessel } 3065d5314d6SJason Wessel break; 3075d5314d6SJason Wessel case 5: /* End */ 3085d5314d6SJason Wessel if (cp < lastchar) { 3095d5314d6SJason Wessel kdb_printf("%s", cp); 3105d5314d6SJason Wessel cp = lastchar; 3115d5314d6SJason Wessel } 3125d5314d6SJason Wessel break; 3135d5314d6SJason Wessel case 2: /* Left */ 3145d5314d6SJason Wessel if (cp > buffer) { 3155d5314d6SJason Wessel kdb_printf("\b"); 3165d5314d6SJason Wessel --cp; 3175d5314d6SJason Wessel } 3185d5314d6SJason Wessel break; 3195d5314d6SJason Wessel case 14: /* Down */ 320e00ec562SDaniel Thompson case 16: /* Up */ 3215d5314d6SJason Wessel memset(tmpbuffer, ' ', 3225d5314d6SJason Wessel strlen(kdb_prompt_str) + (lastchar-buffer)); 3235d5314d6SJason Wessel *(tmpbuffer+strlen(kdb_prompt_str) + 3245d5314d6SJason Wessel (lastchar-buffer)) = '\0'; 3255d5314d6SJason Wessel kdb_printf("\r%s\r", tmpbuffer); 3265d5314d6SJason Wessel *lastchar = (char)key; 3275d5314d6SJason Wessel *(lastchar+1) = '\0'; 3285d5314d6SJason Wessel return lastchar; 3295d5314d6SJason Wessel case 6: /* Right */ 3305d5314d6SJason Wessel if (cp < lastchar) { 3315d5314d6SJason Wessel kdb_printf("%c", *cp); 3325d5314d6SJason Wessel ++cp; 3335d5314d6SJason Wessel } 3345d5314d6SJason Wessel break; 3355d5314d6SJason Wessel case 9: /* Tab */ 3365d5314d6SJason Wessel if (tab < 2) 3375d5314d6SJason Wessel ++tab; 3385d5314d6SJason Wessel p_tmp = buffer; 3395d5314d6SJason Wessel while (*p_tmp == ' ') 3405d5314d6SJason Wessel p_tmp++; 3415d5314d6SJason Wessel if (p_tmp > cp) 3425d5314d6SJason Wessel break; 3435d5314d6SJason Wessel memcpy(tmpbuffer, p_tmp, cp-p_tmp); 3445d5314d6SJason Wessel *(tmpbuffer + (cp-p_tmp)) = '\0'; 3455d5314d6SJason Wessel p_tmp = strrchr(tmpbuffer, ' '); 3465d5314d6SJason Wessel if (p_tmp) 3475d5314d6SJason Wessel ++p_tmp; 3485d5314d6SJason Wessel else 3495d5314d6SJason Wessel p_tmp = tmpbuffer; 3505d5314d6SJason Wessel len = strlen(p_tmp); 351c2b94c72SPrarit Bhargava buf_size = sizeof(tmpbuffer) - (p_tmp - tmpbuffer); 352c2b94c72SPrarit Bhargava count = kallsyms_symbol_complete(p_tmp, buf_size); 3535d5314d6SJason Wessel if (tab == 2 && count > 0) { 3545d5314d6SJason Wessel kdb_printf("\n%d symbols are found.", count); 3555d5314d6SJason Wessel if (count > dtab_count) { 3565d5314d6SJason Wessel count = dtab_count; 3575d5314d6SJason Wessel kdb_printf(" But only first %d symbols will" 3585d5314d6SJason Wessel " be printed.\nYou can change the" 3595d5314d6SJason Wessel " environment variable DTABCOUNT.", 3605d5314d6SJason Wessel count); 3615d5314d6SJason Wessel } 3625d5314d6SJason Wessel kdb_printf("\n"); 3635d5314d6SJason Wessel for (i = 0; i < count; i++) { 364c2b94c72SPrarit Bhargava ret = kallsyms_symbol_next(p_tmp, i, buf_size); 365c2b94c72SPrarit Bhargava if (WARN_ON(!ret)) 3665d5314d6SJason Wessel break; 367c2b94c72SPrarit Bhargava if (ret != -E2BIG) 3685d5314d6SJason Wessel kdb_printf("%s ", p_tmp); 369c2b94c72SPrarit Bhargava else 370c2b94c72SPrarit Bhargava kdb_printf("%s... ", p_tmp); 3715d5314d6SJason Wessel *(p_tmp + len) = '\0'; 3725d5314d6SJason Wessel } 3735d5314d6SJason Wessel if (i >= dtab_count) 3745d5314d6SJason Wessel kdb_printf("..."); 3755d5314d6SJason Wessel kdb_printf("\n"); 3765d5314d6SJason Wessel kdb_printf(kdb_prompt_str); 3775d5314d6SJason Wessel kdb_printf("%s", buffer); 378958ba65aSDaniel Thompson if (cp != lastchar) 379958ba65aSDaniel Thompson kdb_position_cursor(kdb_prompt_str, buffer, cp); 3805d5314d6SJason Wessel } else if (tab != 2 && count > 0) { 381107e825cSDaniel Thompson /* How many new characters do we want from tmpbuffer? */ 382107e825cSDaniel Thompson len_tmp = strlen(p_tmp) - len; 383107e825cSDaniel Thompson if (lastchar + len_tmp >= bufend) 384107e825cSDaniel Thompson len_tmp = bufend - lastchar; 385107e825cSDaniel Thompson 386107e825cSDaniel Thompson if (len_tmp) { 387107e825cSDaniel Thompson /* + 1 ensures the '\0' is memmove'd */ 388107e825cSDaniel Thompson memmove(cp+len_tmp, cp, (lastchar-cp) + 1); 389107e825cSDaniel Thompson memcpy(cp, p_tmp+len, len_tmp); 3905d5314d6SJason Wessel kdb_printf("%s", cp); 391107e825cSDaniel Thompson cp += len_tmp; 392107e825cSDaniel Thompson lastchar += len_tmp; 393958ba65aSDaniel Thompson if (cp != lastchar) 394958ba65aSDaniel Thompson kdb_position_cursor(kdb_prompt_str, 395958ba65aSDaniel Thompson buffer, cp); 396107e825cSDaniel Thompson } 3975d5314d6SJason Wessel } 3985d5314d6SJason Wessel kdb_nextline = 1; /* reset output line number */ 3995d5314d6SJason Wessel break; 4005d5314d6SJason Wessel default: 4015d5314d6SJason Wessel if (key >= 32 && lastchar < bufend) { 4025d5314d6SJason Wessel if (cp < lastchar) { 4035d5314d6SJason Wessel memcpy(tmpbuffer, cp, lastchar - cp); 4045d5314d6SJason Wessel memcpy(cp+1, tmpbuffer, lastchar - cp); 4055d5314d6SJason Wessel *++lastchar = '\0'; 4065d5314d6SJason Wessel *cp = key; 407d373d3c6SDaniel Thompson kdb_printf("%s", cp); 4085d5314d6SJason Wessel ++cp; 409d373d3c6SDaniel Thompson kdb_position_cursor(kdb_prompt_str, buffer, cp); 4105d5314d6SJason Wessel } else { 4115d5314d6SJason Wessel *++lastchar = '\0'; 4125d5314d6SJason Wessel *cp++ = key; 4135d5314d6SJason Wessel /* The kgdb transition check will hide 4145d5314d6SJason Wessel * printed characters if we think that 4155d5314d6SJason Wessel * kgdb is connecting, until the check 4165d5314d6SJason Wessel * fails */ 41737f86b46SJason Wessel if (!KDB_STATE(KGDB_TRANS)) { 41837f86b46SJason Wessel if (kgdb_transition_check(buffer)) 41937f86b46SJason Wessel return buffer; 42037f86b46SJason Wessel } else { 4215d5314d6SJason Wessel kdb_printf("%c", key); 4225d5314d6SJason Wessel } 42337f86b46SJason Wessel } 4245d5314d6SJason Wessel /* Special escape to kgdb */ 4255d5314d6SJason Wessel if (lastchar - buffer >= 5 && 4265d5314d6SJason Wessel strcmp(lastchar - 5, "$?#3f") == 0) { 427f679c498SJason Wessel kdb_gdb_state_pass(lastchar - 5); 4285d5314d6SJason Wessel strcpy(buffer, "kgdb"); 4295d5314d6SJason Wessel KDB_STATE_SET(DOING_KGDB); 4305d5314d6SJason Wessel return buffer; 4315d5314d6SJason Wessel } 432f679c498SJason Wessel if (lastchar - buffer >= 11 && 433f679c498SJason Wessel strcmp(lastchar - 11, "$qSupported") == 0) { 434f679c498SJason Wessel kdb_gdb_state_pass(lastchar - 11); 4355d5314d6SJason Wessel strcpy(buffer, "kgdb"); 436d613d828SJason Wessel KDB_STATE_SET(DOING_KGDB); 4375d5314d6SJason Wessel return buffer; 4385d5314d6SJason Wessel } 4395d5314d6SJason Wessel } 4405d5314d6SJason Wessel break; 4415d5314d6SJason Wessel } 4425d5314d6SJason Wessel goto poll_again; 4435d5314d6SJason Wessel } 4445d5314d6SJason Wessel 4455d5314d6SJason Wessel /* 4465d5314d6SJason Wessel * kdb_getstr 4475d5314d6SJason Wessel * 4485d5314d6SJason Wessel * Print the prompt string and read a command from the 4495d5314d6SJason Wessel * input device. 4505d5314d6SJason Wessel * 4515d5314d6SJason Wessel * Parameters: 4525d5314d6SJason Wessel * buffer Address of buffer to receive command 4535d5314d6SJason Wessel * bufsize Size of buffer in bytes 4545d5314d6SJason Wessel * prompt Pointer to string to use as prompt string 4555d5314d6SJason Wessel * Returns: 4565d5314d6SJason Wessel * Pointer to command buffer. 4575d5314d6SJason Wessel * Locking: 4585d5314d6SJason Wessel * None. 4595d5314d6SJason Wessel * Remarks: 4605d5314d6SJason Wessel * For SMP kernels, the processor number will be 4615d5314d6SJason Wessel * substituted for %d, %x or %o in the prompt. 4625d5314d6SJason Wessel */ 4635d5314d6SJason Wessel 46432d375f6SDaniel Thompson char *kdb_getstr(char *buffer, size_t bufsize, const char *prompt) 4655d5314d6SJason Wessel { 4665d5314d6SJason Wessel if (prompt && kdb_prompt_str != prompt) 467ca976bfbSWenlin Kang strscpy(kdb_prompt_str, prompt, CMD_BUFLEN); 4685d5314d6SJason Wessel kdb_printf(kdb_prompt_str); 4695d5314d6SJason Wessel kdb_nextline = 1; /* Prompt and input resets line number */ 4705d5314d6SJason Wessel return kdb_read(buffer, bufsize); 4715d5314d6SJason Wessel } 4725d5314d6SJason Wessel 4735d5314d6SJason Wessel /* 4745d5314d6SJason Wessel * kdb_input_flush 4755d5314d6SJason Wessel * 4765d5314d6SJason Wessel * Get rid of any buffered console input. 4775d5314d6SJason Wessel * 4785d5314d6SJason Wessel * Parameters: 4795d5314d6SJason Wessel * none 4805d5314d6SJason Wessel * Returns: 4815d5314d6SJason Wessel * nothing 4825d5314d6SJason Wessel * Locking: 4835d5314d6SJason Wessel * none 4845d5314d6SJason Wessel * Remarks: 4855d5314d6SJason Wessel * Call this function whenever you want to flush input. If there is any 4865d5314d6SJason Wessel * outstanding input, it ignores all characters until there has been no 4875d5314d6SJason Wessel * data for approximately 1ms. 4885d5314d6SJason Wessel */ 4895d5314d6SJason Wessel 4905d5314d6SJason Wessel static void kdb_input_flush(void) 4915d5314d6SJason Wessel { 4925d5314d6SJason Wessel get_char_func *f; 4935d5314d6SJason Wessel int res; 4945d5314d6SJason Wessel int flush_delay = 1; 4955d5314d6SJason Wessel while (flush_delay) { 4965d5314d6SJason Wessel flush_delay--; 4975d5314d6SJason Wessel empty: 4985d5314d6SJason Wessel touch_nmi_watchdog(); 4995d5314d6SJason Wessel for (f = &kdb_poll_funcs[0]; *f; ++f) { 5005d5314d6SJason Wessel res = (*f)(); 5015d5314d6SJason Wessel if (res != -1) { 5025d5314d6SJason Wessel flush_delay = 1; 5035d5314d6SJason Wessel goto empty; 5045d5314d6SJason Wessel } 5055d5314d6SJason Wessel } 5065d5314d6SJason Wessel if (flush_delay) 5075d5314d6SJason Wessel mdelay(1); 5085d5314d6SJason Wessel } 5095d5314d6SJason Wessel } 5105d5314d6SJason Wessel 5115d5314d6SJason Wessel /* 5125d5314d6SJason Wessel * kdb_printf 5135d5314d6SJason Wessel * 5145d5314d6SJason Wessel * Print a string to the output device(s). 5155d5314d6SJason Wessel * 5165d5314d6SJason Wessel * Parameters: 5175d5314d6SJason Wessel * printf-like format and optional args. 5185d5314d6SJason Wessel * Returns: 5195d5314d6SJason Wessel * 0 5205d5314d6SJason Wessel * Locking: 5215d5314d6SJason Wessel * None. 5225d5314d6SJason Wessel * Remarks: 5235d5314d6SJason Wessel * use 'kdbcons->write()' to avoid polluting 'log_buf' with 5245d5314d6SJason Wessel * kdb output. 5255d5314d6SJason Wessel * 5265d5314d6SJason Wessel * If the user is doing a cmd args | grep srch 5275d5314d6SJason Wessel * then kdb_grepping_flag is set. 5285d5314d6SJason Wessel * In that case we need to accumulate full lines (ending in \n) before 5295d5314d6SJason Wessel * searching for the pattern. 5305d5314d6SJason Wessel */ 5315d5314d6SJason Wessel 5325d5314d6SJason Wessel static char kdb_buffer[256]; /* A bit too big to go on stack */ 5335d5314d6SJason Wessel static char *next_avail = kdb_buffer; 5345d5314d6SJason Wessel static int size_avail; 5355d5314d6SJason Wessel static int suspend_grep; 5365d5314d6SJason Wessel 5375d5314d6SJason Wessel /* 5385d5314d6SJason Wessel * search arg1 to see if it contains arg2 5395d5314d6SJason Wessel * (kdmain.c provides flags for ^pat and pat$) 5405d5314d6SJason Wessel * 5415d5314d6SJason Wessel * return 1 for found, 0 for not found 5425d5314d6SJason Wessel */ 5435d5314d6SJason Wessel static int kdb_search_string(char *searched, char *searchfor) 5445d5314d6SJason Wessel { 5455d5314d6SJason Wessel char firstchar, *cp; 5465d5314d6SJason Wessel int len1, len2; 5475d5314d6SJason Wessel 5485d5314d6SJason Wessel /* not counting the newline at the end of "searched" */ 5495d5314d6SJason Wessel len1 = strlen(searched)-1; 5505d5314d6SJason Wessel len2 = strlen(searchfor); 5515d5314d6SJason Wessel if (len1 < len2) 5525d5314d6SJason Wessel return 0; 5535d5314d6SJason Wessel if (kdb_grep_leading && kdb_grep_trailing && len1 != len2) 5545d5314d6SJason Wessel return 0; 5555d5314d6SJason Wessel if (kdb_grep_leading) { 5565d5314d6SJason Wessel if (!strncmp(searched, searchfor, len2)) 5575d5314d6SJason Wessel return 1; 5585d5314d6SJason Wessel } else if (kdb_grep_trailing) { 5595d5314d6SJason Wessel if (!strncmp(searched+len1-len2, searchfor, len2)) 5605d5314d6SJason Wessel return 1; 5615d5314d6SJason Wessel } else { 5625d5314d6SJason Wessel firstchar = *searchfor; 5635d5314d6SJason Wessel cp = searched; 5645d5314d6SJason Wessel while ((cp = strchr(cp, firstchar))) { 5655d5314d6SJason Wessel if (!strncmp(cp, searchfor, len2)) 5665d5314d6SJason Wessel return 1; 5675d5314d6SJason Wessel cp++; 5685d5314d6SJason Wessel } 5695d5314d6SJason Wessel } 5705d5314d6SJason Wessel return 0; 5715d5314d6SJason Wessel } 5725d5314d6SJason Wessel 5739d71b344SSumit Garg static void kdb_msg_write(const char *msg, int msg_len) 5749d71b344SSumit Garg { 5759d71b344SSumit Garg struct console *c; 576fcdb84ccSCengiz Can const char *cp; 577b8ef04beSJohn Ogness int cookie; 578fcdb84ccSCengiz Can int len; 5799d71b344SSumit Garg 5809d71b344SSumit Garg if (msg_len == 0) 5819d71b344SSumit Garg return; 5829d71b344SSumit Garg 583fcdb84ccSCengiz Can cp = msg; 584fcdb84ccSCengiz Can len = msg_len; 5859d71b344SSumit Garg 5869d71b344SSumit Garg while (len--) { 5879d71b344SSumit Garg dbg_io_ops->write_char(*cp); 5889d71b344SSumit Garg cp++; 5899d71b344SSumit Garg } 5909d71b344SSumit Garg 591b8ef04beSJohn Ogness /* 592b8ef04beSJohn Ogness * The console_srcu_read_lock() only provides safe console list 593b8ef04beSJohn Ogness * traversal. The use of the ->write() callback relies on all other 594b8ef04beSJohn Ogness * CPUs being stopped at the moment and console drivers being able to 595b8ef04beSJohn Ogness * handle reentrance when @oops_in_progress is set. 596b8ef04beSJohn Ogness * 597b8ef04beSJohn Ogness * There is no guarantee that every console driver can handle 598b8ef04beSJohn Ogness * reentrance in this way; the developer deploying the debugger 599b8ef04beSJohn Ogness * is responsible for ensuring that the console drivers they 600b8ef04beSJohn Ogness * have selected handle reentrance appropriately. 601b8ef04beSJohn Ogness */ 602b8ef04beSJohn Ogness cookie = console_srcu_read_lock(); 603b8ef04beSJohn Ogness for_each_console_srcu(c) { 604b8ef04beSJohn Ogness if (!(console_srcu_read_flags(c) & CON_ENABLED)) 605e8857288SSumit Garg continue; 6065946d1f5SSumit Garg if (c == dbg_io_ops->cons) 6075946d1f5SSumit Garg continue; 6086d3e0d8cSJohn Ogness if (!c->write) 6096d3e0d8cSJohn Ogness continue; 6102a78b85bSSumit Garg /* 6112a78b85bSSumit Garg * Set oops_in_progress to encourage the console drivers to 6122a78b85bSSumit Garg * disregard their internal spin locks: in the current calling 6132a78b85bSSumit Garg * context the risk of deadlock is a bigger problem than risks 6142a78b85bSSumit Garg * due to re-entering the console driver. We operate directly on 6152a78b85bSSumit Garg * oops_in_progress rather than using bust_spinlocks() because 6162a78b85bSSumit Garg * the calls bust_spinlocks() makes on exit are not appropriate 6172a78b85bSSumit Garg * for this calling context. 6182a78b85bSSumit Garg */ 6192a78b85bSSumit Garg ++oops_in_progress; 6209d71b344SSumit Garg c->write(c, msg, msg_len); 6212a78b85bSSumit Garg --oops_in_progress; 6229d71b344SSumit Garg touch_nmi_watchdog(); 6239d71b344SSumit Garg } 624b8ef04beSJohn Ogness console_srcu_read_unlock(cookie); 6259d71b344SSumit Garg } 6269d71b344SSumit Garg 627f7d4ca8bSDaniel Thompson int vkdb_printf(enum kdb_msgsrc src, const char *fmt, va_list ap) 6285d5314d6SJason Wessel { 6295d5314d6SJason Wessel int diag; 6305d5314d6SJason Wessel int linecount; 63117b572e8SJason Wessel int colcount; 6325d5314d6SJason Wessel int logging, saved_loglevel = 0; 6335d5314d6SJason Wessel int retlen = 0; 6345d5314d6SJason Wessel int fnd, len; 635d5d8d3d0SPetr Mladek int this_cpu, old_cpu; 6365d5314d6SJason Wessel char *cp, *cp2, *cphold = NULL, replaced_byte = ' '; 6375d5314d6SJason Wessel char *moreprompt = "more> "; 6383f649ab7SKees Cook unsigned long flags; 6395d5314d6SJason Wessel 6405d5314d6SJason Wessel /* Serialize kdb_printf if multiple cpus try to write at once. 6415d5314d6SJason Wessel * But if any cpu goes recursive in kdb, just print the output, 6425d5314d6SJason Wessel * even if it is interleaved with any other text. 6435d5314d6SJason Wessel */ 64434aaff40SPetr Mladek local_irq_save(flags); 645d5d8d3d0SPetr Mladek this_cpu = smp_processor_id(); 646d5d8d3d0SPetr Mladek for (;;) { 647d5d8d3d0SPetr Mladek old_cpu = cmpxchg(&kdb_printf_cpu, -1, this_cpu); 648d5d8d3d0SPetr Mladek if (old_cpu == -1 || old_cpu == this_cpu) 649d5d8d3d0SPetr Mladek break; 650d5d8d3d0SPetr Mladek 651d5d8d3d0SPetr Mladek cpu_relax(); 6525d5314d6SJason Wessel } 6535d5314d6SJason Wessel 6545d5314d6SJason Wessel diag = kdbgetintenv("LINES", &linecount); 6555d5314d6SJason Wessel if (diag || linecount <= 1) 6565d5314d6SJason Wessel linecount = 24; 6575d5314d6SJason Wessel 65817b572e8SJason Wessel diag = kdbgetintenv("COLUMNS", &colcount); 65917b572e8SJason Wessel if (diag || colcount <= 1) 66017b572e8SJason Wessel colcount = 80; 66117b572e8SJason Wessel 6625d5314d6SJason Wessel diag = kdbgetintenv("LOGGING", &logging); 6635d5314d6SJason Wessel if (diag) 6645d5314d6SJason Wessel logging = 0; 6655d5314d6SJason Wessel 6665d5314d6SJason Wessel if (!kdb_grepping_flag || suspend_grep) { 6675d5314d6SJason Wessel /* normally, every vsnprintf starts a new buffer */ 6685d5314d6SJason Wessel next_avail = kdb_buffer; 6695d5314d6SJason Wessel size_avail = sizeof(kdb_buffer); 6705d5314d6SJason Wessel } 6715d5314d6SJason Wessel vsnprintf(next_avail, size_avail, fmt, ap); 6725d5314d6SJason Wessel 6735d5314d6SJason Wessel /* 6745d5314d6SJason Wessel * If kdb_parse() found that the command was cmd xxx | grep yyy 6755d5314d6SJason Wessel * then kdb_grepping_flag is set, and kdb_grep_string contains yyy 6765d5314d6SJason Wessel * 6775d5314d6SJason Wessel * Accumulate the print data up to a newline before searching it. 6785d5314d6SJason Wessel * (vsnprintf does null-terminate the string that it generates) 6795d5314d6SJason Wessel */ 6805d5314d6SJason Wessel 6815d5314d6SJason Wessel /* skip the search if prints are temporarily unconditional */ 6825d5314d6SJason Wessel if (!suspend_grep && kdb_grepping_flag) { 6835d5314d6SJason Wessel cp = strchr(kdb_buffer, '\n'); 6845d5314d6SJason Wessel if (!cp) { 6855d5314d6SJason Wessel /* 6865d5314d6SJason Wessel * Special cases that don't end with newlines 6875d5314d6SJason Wessel * but should be written without one: 6885d5314d6SJason Wessel * The "[nn]kdb> " prompt should 6895d5314d6SJason Wessel * appear at the front of the buffer. 6905d5314d6SJason Wessel * 6915d5314d6SJason Wessel * The "[nn]more " prompt should also be 6925d5314d6SJason Wessel * (MOREPROMPT -> moreprompt) 6935d5314d6SJason Wessel * written * but we print that ourselves, 6945d5314d6SJason Wessel * we set the suspend_grep flag to make 6955d5314d6SJason Wessel * it unconditional. 6965d5314d6SJason Wessel * 6975d5314d6SJason Wessel */ 6985d5314d6SJason Wessel if (next_avail == kdb_buffer) { 6995d5314d6SJason Wessel /* 7005d5314d6SJason Wessel * these should occur after a newline, 7015d5314d6SJason Wessel * so they will be at the front of the 7025d5314d6SJason Wessel * buffer 7035d5314d6SJason Wessel */ 7045d5314d6SJason Wessel cp2 = kdb_buffer; 7055d5314d6SJason Wessel len = strlen(kdb_prompt_str); 7065d5314d6SJason Wessel if (!strncmp(cp2, kdb_prompt_str, len)) { 7075d5314d6SJason Wessel /* 7085d5314d6SJason Wessel * We're about to start a new 7095d5314d6SJason Wessel * command, so we can go back 7105d5314d6SJason Wessel * to normal mode. 7115d5314d6SJason Wessel */ 7125d5314d6SJason Wessel kdb_grepping_flag = 0; 7135d5314d6SJason Wessel goto kdb_printit; 7145d5314d6SJason Wessel } 7155d5314d6SJason Wessel } 7165d5314d6SJason Wessel /* no newline; don't search/write the buffer 7175d5314d6SJason Wessel until one is there */ 7185d5314d6SJason Wessel len = strlen(kdb_buffer); 7195d5314d6SJason Wessel next_avail = kdb_buffer + len; 7205d5314d6SJason Wessel size_avail = sizeof(kdb_buffer) - len; 7215d5314d6SJason Wessel goto kdb_print_out; 7225d5314d6SJason Wessel } 7235d5314d6SJason Wessel 7245d5314d6SJason Wessel /* 7255d5314d6SJason Wessel * The newline is present; print through it or discard 7265d5314d6SJason Wessel * it, depending on the results of the search. 7275d5314d6SJason Wessel */ 7285d5314d6SJason Wessel cp++; /* to byte after the newline */ 7295d5314d6SJason Wessel replaced_byte = *cp; /* remember what/where it was */ 7305d5314d6SJason Wessel cphold = cp; 7315d5314d6SJason Wessel *cp = '\0'; /* end the string for our search */ 7325d5314d6SJason Wessel 7335d5314d6SJason Wessel /* 7345d5314d6SJason Wessel * We now have a newline at the end of the string 7355d5314d6SJason Wessel * Only continue with this output if it contains the 7365d5314d6SJason Wessel * search string. 7375d5314d6SJason Wessel */ 7385d5314d6SJason Wessel fnd = kdb_search_string(kdb_buffer, kdb_grep_string); 7395d5314d6SJason Wessel if (!fnd) { 7405d5314d6SJason Wessel /* 7415d5314d6SJason Wessel * At this point the complete line at the start 7425d5314d6SJason Wessel * of kdb_buffer can be discarded, as it does 7435d5314d6SJason Wessel * not contain what the user is looking for. 7445d5314d6SJason Wessel * Shift the buffer left. 7455d5314d6SJason Wessel */ 7465d5314d6SJason Wessel *cphold = replaced_byte; 7475d5314d6SJason Wessel strcpy(kdb_buffer, cphold); 7485d5314d6SJason Wessel len = strlen(kdb_buffer); 7495d5314d6SJason Wessel next_avail = kdb_buffer + len; 7505d5314d6SJason Wessel size_avail = sizeof(kdb_buffer) - len; 7515d5314d6SJason Wessel goto kdb_print_out; 7525d5314d6SJason Wessel } 753d081a6e3SDaniel Thompson if (kdb_grepping_flag >= KDB_GREPPING_FLAG_SEARCH) { 754fb6daa75SDaniel Thompson /* 755fb6daa75SDaniel Thompson * This was a interactive search (using '/' at more 756d081a6e3SDaniel Thompson * prompt) and it has completed. Replace the \0 with 757d081a6e3SDaniel Thompson * its original value to ensure multi-line strings 758d081a6e3SDaniel Thompson * are handled properly, and return to normal mode. 759fb6daa75SDaniel Thompson */ 760d081a6e3SDaniel Thompson *cphold = replaced_byte; 761fb6daa75SDaniel Thompson kdb_grepping_flag = 0; 762d081a6e3SDaniel Thompson } 7635d5314d6SJason Wessel /* 7645d5314d6SJason Wessel * at this point the string is a full line and 7655d5314d6SJason Wessel * should be printed, up to the null. 7665d5314d6SJason Wessel */ 7675d5314d6SJason Wessel } 7685d5314d6SJason Wessel kdb_printit: 7695d5314d6SJason Wessel 7705d5314d6SJason Wessel /* 7715d5314d6SJason Wessel * Write to all consoles. 7725d5314d6SJason Wessel */ 7735d5314d6SJason Wessel retlen = strlen(kdb_buffer); 77449795757SPetr Mladek cp = (char *) printk_skip_headers(kdb_buffer); 7759d71b344SSumit Garg if (!dbg_kdb_mode && kgdb_connected) 776f7d4ca8bSDaniel Thompson gdbstub_msg_write(cp, retlen - (cp - kdb_buffer)); 7779d71b344SSumit Garg else 7789d71b344SSumit Garg kdb_msg_write(cp, retlen - (cp - kdb_buffer)); 7799d71b344SSumit Garg 7805d5314d6SJason Wessel if (logging) { 7815d5314d6SJason Wessel saved_loglevel = console_loglevel; 782a8fe19ebSBorislav Petkov console_loglevel = CONSOLE_LOGLEVEL_SILENT; 783f7d4ca8bSDaniel Thompson if (printk_get_level(kdb_buffer) || src == KDB_MSGSRC_PRINTK) 784f7d4ca8bSDaniel Thompson printk("%s", kdb_buffer); 785f7d4ca8bSDaniel Thompson else 786f7d4ca8bSDaniel Thompson pr_info("%s", kdb_buffer); 7875d5314d6SJason Wessel } 7885d5314d6SJason Wessel 78917b572e8SJason Wessel if (KDB_STATE(PAGER)) { 79017b572e8SJason Wessel /* 79117b572e8SJason Wessel * Check printed string to decide how to bump the 79217b572e8SJason Wessel * kdb_nextline to control when the more prompt should 79317b572e8SJason Wessel * show up. 79417b572e8SJason Wessel */ 79517b572e8SJason Wessel int got = 0; 79617b572e8SJason Wessel len = retlen; 79717b572e8SJason Wessel while (len--) { 79817b572e8SJason Wessel if (kdb_buffer[len] == '\n') { 7995d5314d6SJason Wessel kdb_nextline++; 80017b572e8SJason Wessel got = 0; 80117b572e8SJason Wessel } else if (kdb_buffer[len] == '\r') { 80217b572e8SJason Wessel got = 0; 80317b572e8SJason Wessel } else { 80417b572e8SJason Wessel got++; 80517b572e8SJason Wessel } 80617b572e8SJason Wessel } 80717b572e8SJason Wessel kdb_nextline += got / (colcount + 1); 80817b572e8SJason Wessel } 8095d5314d6SJason Wessel 8105d5314d6SJason Wessel /* check for having reached the LINES number of printed lines */ 81117b572e8SJason Wessel if (kdb_nextline >= linecount) { 8124f27e824SDaniel Thompson char ch; 8135d5314d6SJason Wessel 8145d5314d6SJason Wessel /* Watch out for recursion here. Any routine that calls 8155d5314d6SJason Wessel * kdb_printf will come back through here. And kdb_read 8165d5314d6SJason Wessel * uses kdb_printf to echo on serial consoles ... 8175d5314d6SJason Wessel */ 8185d5314d6SJason Wessel kdb_nextline = 1; /* In case of recursion */ 8195d5314d6SJason Wessel 8205d5314d6SJason Wessel /* 8215d5314d6SJason Wessel * Pause until cr. 8225d5314d6SJason Wessel */ 8235d5314d6SJason Wessel moreprompt = kdbgetenv("MOREPROMPT"); 8245d5314d6SJason Wessel if (moreprompt == NULL) 8255d5314d6SJason Wessel moreprompt = "more> "; 8265d5314d6SJason Wessel 8275d5314d6SJason Wessel kdb_input_flush(); 8289d71b344SSumit Garg kdb_msg_write(moreprompt, strlen(moreprompt)); 8295d5314d6SJason Wessel 8305d5314d6SJason Wessel if (logging) 8315d5314d6SJason Wessel printk("%s", moreprompt); 8325d5314d6SJason Wessel 8334f27e824SDaniel Thompson ch = kdb_getchar(); 8345d5314d6SJason Wessel kdb_nextline = 1; /* Really set output line 1 */ 8355d5314d6SJason Wessel 8365d5314d6SJason Wessel /* empty and reset the buffer: */ 8375d5314d6SJason Wessel kdb_buffer[0] = '\0'; 8385d5314d6SJason Wessel next_avail = kdb_buffer; 8395d5314d6SJason Wessel size_avail = sizeof(kdb_buffer); 8404f27e824SDaniel Thompson if ((ch == 'q') || (ch == 'Q')) { 8415d5314d6SJason Wessel /* user hit q or Q */ 8425d5314d6SJason Wessel KDB_FLAG_SET(CMD_INTERRUPT); /* command interrupted */ 8435d5314d6SJason Wessel KDB_STATE_CLEAR(PAGER); 8445d5314d6SJason Wessel /* end of command output; back to normal mode */ 8455d5314d6SJason Wessel kdb_grepping_flag = 0; 8465d5314d6SJason Wessel kdb_printf("\n"); 8474f27e824SDaniel Thompson } else if (ch == ' ') { 84817b572e8SJason Wessel kdb_printf("\r"); 8495d5314d6SJason Wessel suspend_grep = 1; /* for this recursion */ 8504f27e824SDaniel Thompson } else if (ch == '\n' || ch == '\r') { 8515d5314d6SJason Wessel kdb_nextline = linecount - 1; 8525d5314d6SJason Wessel kdb_printf("\r"); 8535d5314d6SJason Wessel suspend_grep = 1; /* for this recursion */ 8544f27e824SDaniel Thompson } else if (ch == '/' && !kdb_grepping_flag) { 855fb6daa75SDaniel Thompson kdb_printf("\r"); 856fb6daa75SDaniel Thompson kdb_getstr(kdb_grep_string, KDB_GREP_STRLEN, 857fb6daa75SDaniel Thompson kdbgetenv("SEARCHPROMPT") ?: "search> "); 858fb6daa75SDaniel Thompson *strchrnul(kdb_grep_string, '\n') = '\0'; 859fb6daa75SDaniel Thompson kdb_grepping_flag += KDB_GREPPING_FLAG_SEARCH; 860fb6daa75SDaniel Thompson suspend_grep = 1; /* for this recursion */ 8614f27e824SDaniel Thompson } else if (ch) { 8624f27e824SDaniel Thompson /* user hit something unexpected */ 8635d5314d6SJason Wessel suspend_grep = 1; /* for this recursion */ 8644f27e824SDaniel Thompson if (ch != '/') 865fb6daa75SDaniel Thompson kdb_printf( 866fb6daa75SDaniel Thompson "\nOnly 'q', 'Q' or '/' are processed at " 867fb6daa75SDaniel Thompson "more prompt, input ignored\n"); 868fb6daa75SDaniel Thompson else 869fb6daa75SDaniel Thompson kdb_printf("\n'/' cannot be used during | " 870fb6daa75SDaniel Thompson "grep filtering, input ignored\n"); 8715d5314d6SJason Wessel } else if (kdb_grepping_flag) { 8725d5314d6SJason Wessel /* user hit enter */ 8735d5314d6SJason Wessel suspend_grep = 1; /* for this recursion */ 8745d5314d6SJason Wessel kdb_printf("\n"); 8755d5314d6SJason Wessel } 8765d5314d6SJason Wessel kdb_input_flush(); 8775d5314d6SJason Wessel } 8785d5314d6SJason Wessel 8795d5314d6SJason Wessel /* 8805d5314d6SJason Wessel * For grep searches, shift the printed string left. 8815d5314d6SJason Wessel * replaced_byte contains the character that was overwritten with 8825d5314d6SJason Wessel * the terminating null, and cphold points to the null. 8835d5314d6SJason Wessel * Then adjust the notion of available space in the buffer. 8845d5314d6SJason Wessel */ 8855d5314d6SJason Wessel if (kdb_grepping_flag && !suspend_grep) { 8865d5314d6SJason Wessel *cphold = replaced_byte; 8875d5314d6SJason Wessel strcpy(kdb_buffer, cphold); 8885d5314d6SJason Wessel len = strlen(kdb_buffer); 8895d5314d6SJason Wessel next_avail = kdb_buffer + len; 8905d5314d6SJason Wessel size_avail = sizeof(kdb_buffer) - len; 8915d5314d6SJason Wessel } 8925d5314d6SJason Wessel 8935d5314d6SJason Wessel kdb_print_out: 8945d5314d6SJason Wessel suspend_grep = 0; /* end of what may have been a recursive call */ 8955d5314d6SJason Wessel if (logging) 8965d5314d6SJason Wessel console_loglevel = saved_loglevel; 897d5d8d3d0SPetr Mladek /* kdb_printf_cpu locked the code above. */ 898d5d8d3d0SPetr Mladek smp_store_release(&kdb_printf_cpu, old_cpu); 899d5d8d3d0SPetr Mladek local_irq_restore(flags); 9005d5314d6SJason Wessel return retlen; 9015d5314d6SJason Wessel } 902d37d39aeSJason Wessel 903d37d39aeSJason Wessel int kdb_printf(const char *fmt, ...) 904d37d39aeSJason Wessel { 905d37d39aeSJason Wessel va_list ap; 906d37d39aeSJason Wessel int r; 907d37d39aeSJason Wessel 908d37d39aeSJason Wessel va_start(ap, fmt); 909f7d4ca8bSDaniel Thompson r = vkdb_printf(KDB_MSGSRC_INTERNAL, fmt, ap); 910d37d39aeSJason Wessel va_end(ap); 911d37d39aeSJason Wessel 912d37d39aeSJason Wessel return r; 913d37d39aeSJason Wessel } 914f7030bbcSJason Wessel EXPORT_SYMBOL_GPL(kdb_printf); 915