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/module.h> 135d5314d6SJason Wessel #include <linux/types.h> 145d5314d6SJason Wessel #include <linux/ctype.h> 155d5314d6SJason Wessel #include <linux/kernel.h> 165d5314d6SJason Wessel #include <linux/init.h> 175d5314d6SJason Wessel #include <linux/kdev_t.h> 185d5314d6SJason Wessel #include <linux/console.h> 195d5314d6SJason Wessel #include <linux/string.h> 205d5314d6SJason Wessel #include <linux/sched.h> 215d5314d6SJason Wessel #include <linux/smp.h> 225d5314d6SJason Wessel #include <linux/nmi.h> 235d5314d6SJason Wessel #include <linux/delay.h> 24a0de055cSJason Wessel #include <linux/kgdb.h> 255d5314d6SJason Wessel #include <linux/kdb.h> 265d5314d6SJason Wessel #include <linux/kallsyms.h> 275d5314d6SJason Wessel #include "kdb_private.h" 285d5314d6SJason Wessel 295d5314d6SJason Wessel #define CMD_BUFLEN 256 305d5314d6SJason Wessel char kdb_prompt_str[CMD_BUFLEN]; 315d5314d6SJason Wessel 32d37d39aeSJason Wessel int kdb_trap_printk; 3334aaff40SPetr Mladek int kdb_printf_cpu = -1; 345d5314d6SJason Wessel 3537f86b46SJason Wessel static int kgdb_transition_check(char *buffer) 365d5314d6SJason Wessel { 3737f86b46SJason Wessel if (buffer[0] != '+' && buffer[0] != '$') { 385d5314d6SJason Wessel KDB_STATE_SET(KGDB_TRANS); 395d5314d6SJason Wessel kdb_printf("%s", buffer); 4037f86b46SJason Wessel } else { 4137f86b46SJason Wessel int slen = strlen(buffer); 4237f86b46SJason Wessel if (slen > 3 && buffer[slen - 3] == '#') { 4337f86b46SJason Wessel kdb_gdb_state_pass(buffer); 4437f86b46SJason Wessel strcpy(buffer, "kgdb"); 4537f86b46SJason Wessel KDB_STATE_SET(DOING_KGDB); 4637f86b46SJason Wessel return 1; 475d5314d6SJason Wessel } 485d5314d6SJason Wessel } 4937f86b46SJason Wessel return 0; 5037f86b46SJason Wessel } 515d5314d6SJason Wessel 525d5314d6SJason Wessel static int kdb_read_get_key(char *buffer, size_t bufsize) 535d5314d6SJason Wessel { 545d5314d6SJason Wessel #define ESCAPE_UDELAY 1000 555d5314d6SJason Wessel #define ESCAPE_DELAY (2*1000000/ESCAPE_UDELAY) /* 2 seconds worth of udelays */ 565d5314d6SJason Wessel char escape_data[5]; /* longest vt100 escape sequence is 4 bytes */ 575d5314d6SJason Wessel char *ped = escape_data; 585d5314d6SJason Wessel int escape_delay = 0; 595d5314d6SJason Wessel get_char_func *f, *f_escape = NULL; 605d5314d6SJason Wessel int key; 615d5314d6SJason Wessel 625d5314d6SJason Wessel for (f = &kdb_poll_funcs[0]; ; ++f) { 635d5314d6SJason Wessel if (*f == NULL) { 645d5314d6SJason Wessel /* Reset NMI watchdog once per poll loop */ 655d5314d6SJason Wessel touch_nmi_watchdog(); 665d5314d6SJason Wessel f = &kdb_poll_funcs[0]; 675d5314d6SJason Wessel } 685d5314d6SJason Wessel if (escape_delay == 2) { 695d5314d6SJason Wessel *ped = '\0'; 705d5314d6SJason Wessel ped = escape_data; 715d5314d6SJason Wessel --escape_delay; 725d5314d6SJason Wessel } 735d5314d6SJason Wessel if (escape_delay == 1) { 745d5314d6SJason Wessel key = *ped++; 755d5314d6SJason Wessel if (!*ped) 765d5314d6SJason Wessel --escape_delay; 775d5314d6SJason Wessel break; 785d5314d6SJason Wessel } 795d5314d6SJason Wessel key = (*f)(); 805d5314d6SJason Wessel if (key == -1) { 815d5314d6SJason Wessel if (escape_delay) { 825d5314d6SJason Wessel udelay(ESCAPE_UDELAY); 835d5314d6SJason Wessel --escape_delay; 845d5314d6SJason Wessel } 855d5314d6SJason Wessel continue; 865d5314d6SJason Wessel } 875d5314d6SJason Wessel if (bufsize <= 2) { 885d5314d6SJason Wessel if (key == '\r') 895d5314d6SJason Wessel key = '\n'; 905d5314d6SJason Wessel *buffer++ = key; 915d5314d6SJason Wessel *buffer = '\0'; 925d5314d6SJason Wessel return -1; 935d5314d6SJason Wessel } 945d5314d6SJason Wessel if (escape_delay == 0 && key == '\e') { 955d5314d6SJason Wessel escape_delay = ESCAPE_DELAY; 965d5314d6SJason Wessel ped = escape_data; 975d5314d6SJason Wessel f_escape = f; 985d5314d6SJason Wessel } 995d5314d6SJason Wessel if (escape_delay) { 1005d5314d6SJason Wessel *ped++ = key; 1015d5314d6SJason Wessel if (f_escape != f) { 1025d5314d6SJason Wessel escape_delay = 2; 1035d5314d6SJason Wessel continue; 1045d5314d6SJason Wessel } 1055d5314d6SJason Wessel if (ped - escape_data == 1) { 1065d5314d6SJason Wessel /* \e */ 1075d5314d6SJason Wessel continue; 1085d5314d6SJason Wessel } else if (ped - escape_data == 2) { 1095d5314d6SJason Wessel /* \e<something> */ 1105d5314d6SJason Wessel if (key != '[') 1115d5314d6SJason Wessel escape_delay = 2; 1125d5314d6SJason Wessel continue; 1135d5314d6SJason Wessel } else if (ped - escape_data == 3) { 1145d5314d6SJason Wessel /* \e[<something> */ 1155d5314d6SJason Wessel int mapkey = 0; 1165d5314d6SJason Wessel switch (key) { 1175d5314d6SJason Wessel case 'A': /* \e[A, up arrow */ 1185d5314d6SJason Wessel mapkey = 16; 1195d5314d6SJason Wessel break; 1205d5314d6SJason Wessel case 'B': /* \e[B, down arrow */ 1215d5314d6SJason Wessel mapkey = 14; 1225d5314d6SJason Wessel break; 1235d5314d6SJason Wessel case 'C': /* \e[C, right arrow */ 1245d5314d6SJason Wessel mapkey = 6; 1255d5314d6SJason Wessel break; 1265d5314d6SJason Wessel case 'D': /* \e[D, left arrow */ 1275d5314d6SJason Wessel mapkey = 2; 1285d5314d6SJason Wessel break; 1295d5314d6SJason Wessel case '1': /* dropthrough */ 1305d5314d6SJason Wessel case '3': /* dropthrough */ 1315d5314d6SJason Wessel /* \e[<1,3,4>], may be home, del, end */ 1325d5314d6SJason Wessel case '4': 1335d5314d6SJason Wessel mapkey = -1; 1345d5314d6SJason Wessel break; 1355d5314d6SJason Wessel } 1365d5314d6SJason Wessel if (mapkey != -1) { 1375d5314d6SJason Wessel if (mapkey > 0) { 1385d5314d6SJason Wessel escape_data[0] = mapkey; 1395d5314d6SJason Wessel escape_data[1] = '\0'; 1405d5314d6SJason Wessel } 1415d5314d6SJason Wessel escape_delay = 2; 1425d5314d6SJason Wessel } 1435d5314d6SJason Wessel continue; 1445d5314d6SJason Wessel } else if (ped - escape_data == 4) { 1455d5314d6SJason Wessel /* \e[<1,3,4><something> */ 1465d5314d6SJason Wessel int mapkey = 0; 1475d5314d6SJason Wessel if (key == '~') { 1485d5314d6SJason Wessel switch (escape_data[2]) { 1495d5314d6SJason Wessel case '1': /* \e[1~, home */ 1505d5314d6SJason Wessel mapkey = 1; 1515d5314d6SJason Wessel break; 1525d5314d6SJason Wessel case '3': /* \e[3~, del */ 1535d5314d6SJason Wessel mapkey = 4; 1545d5314d6SJason Wessel break; 1555d5314d6SJason Wessel case '4': /* \e[4~, end */ 1565d5314d6SJason Wessel mapkey = 5; 1575d5314d6SJason Wessel break; 1585d5314d6SJason Wessel } 1595d5314d6SJason Wessel } 1605d5314d6SJason Wessel if (mapkey > 0) { 1615d5314d6SJason Wessel escape_data[0] = mapkey; 1625d5314d6SJason Wessel escape_data[1] = '\0'; 1635d5314d6SJason Wessel } 1645d5314d6SJason Wessel escape_delay = 2; 1655d5314d6SJason Wessel continue; 1665d5314d6SJason Wessel } 1675d5314d6SJason Wessel } 1685d5314d6SJason Wessel break; /* A key to process */ 1695d5314d6SJason Wessel } 1705d5314d6SJason Wessel return key; 1715d5314d6SJason Wessel } 1725d5314d6SJason Wessel 1735d5314d6SJason Wessel /* 1745d5314d6SJason Wessel * kdb_read 1755d5314d6SJason Wessel * 1765d5314d6SJason Wessel * This function reads a string of characters, terminated by 1775d5314d6SJason Wessel * a newline, or by reaching the end of the supplied buffer, 1785d5314d6SJason Wessel * from the current kernel debugger console device. 1795d5314d6SJason Wessel * Parameters: 1805d5314d6SJason Wessel * buffer - Address of character buffer to receive input characters. 1815d5314d6SJason Wessel * bufsize - size, in bytes, of the character buffer 1825d5314d6SJason Wessel * Returns: 1835d5314d6SJason Wessel * Returns a pointer to the buffer containing the received 1845d5314d6SJason Wessel * character string. This string will be terminated by a 1855d5314d6SJason Wessel * newline character. 1865d5314d6SJason Wessel * Locking: 1875d5314d6SJason Wessel * No locks are required to be held upon entry to this 1885d5314d6SJason Wessel * function. It is not reentrant - it relies on the fact 1895d5314d6SJason Wessel * that while kdb is running on only one "master debug" cpu. 1905d5314d6SJason Wessel * Remarks: 1915d5314d6SJason Wessel * 1925d5314d6SJason Wessel * The buffer size must be >= 2. A buffer size of 2 means that the caller only 1935d5314d6SJason Wessel * wants a single key. 1945d5314d6SJason Wessel * 1955d5314d6SJason Wessel * An escape key could be the start of a vt100 control sequence such as \e[D 1965d5314d6SJason Wessel * (left arrow) or it could be a character in its own right. The standard 1975d5314d6SJason Wessel * method for detecting the difference is to wait for 2 seconds to see if there 1985d5314d6SJason Wessel * are any other characters. kdb is complicated by the lack of a timer service 1995d5314d6SJason Wessel * (interrupts are off), by multiple input sources and by the need to sometimes 2005d5314d6SJason Wessel * return after just one key. Escape sequence processing has to be done as 2015d5314d6SJason Wessel * states in the polling loop. 2025d5314d6SJason Wessel */ 2035d5314d6SJason Wessel 2045d5314d6SJason Wessel static char *kdb_read(char *buffer, size_t bufsize) 2055d5314d6SJason Wessel { 2065d5314d6SJason Wessel char *cp = buffer; 2075d5314d6SJason Wessel char *bufend = buffer+bufsize-2; /* Reserve space for newline 2085d5314d6SJason Wessel * and null byte */ 2095d5314d6SJason Wessel char *lastchar; 2105d5314d6SJason Wessel char *p_tmp; 2115d5314d6SJason Wessel char tmp; 2125d5314d6SJason Wessel static char tmpbuffer[CMD_BUFLEN]; 2135d5314d6SJason Wessel int len = strlen(buffer); 2145d5314d6SJason Wessel int len_tmp; 2155d5314d6SJason Wessel int tab = 0; 2165d5314d6SJason Wessel int count; 2175d5314d6SJason Wessel int i; 2185d5314d6SJason Wessel int diag, dtab_count; 2195d5314d6SJason Wessel int key; 2205d5314d6SJason Wessel 2215d5314d6SJason Wessel 2225d5314d6SJason Wessel diag = kdbgetintenv("DTABCOUNT", &dtab_count); 2235d5314d6SJason Wessel if (diag) 2245d5314d6SJason Wessel dtab_count = 30; 2255d5314d6SJason Wessel 2265d5314d6SJason Wessel if (len > 0) { 2275d5314d6SJason Wessel cp += len; 2285d5314d6SJason Wessel if (*(buffer+len-1) == '\n') 2295d5314d6SJason Wessel cp--; 2305d5314d6SJason Wessel } 2315d5314d6SJason Wessel 2325d5314d6SJason Wessel lastchar = cp; 2335d5314d6SJason Wessel *cp = '\0'; 2345d5314d6SJason Wessel kdb_printf("%s", buffer); 2355d5314d6SJason Wessel poll_again: 2365d5314d6SJason Wessel key = kdb_read_get_key(buffer, bufsize); 2375d5314d6SJason Wessel if (key == -1) 2385d5314d6SJason Wessel return buffer; 2395d5314d6SJason Wessel if (key != 9) 2405d5314d6SJason Wessel tab = 0; 2415d5314d6SJason Wessel switch (key) { 2425d5314d6SJason Wessel case 8: /* backspace */ 2435d5314d6SJason Wessel if (cp > buffer) { 2445d5314d6SJason Wessel if (cp < lastchar) { 2455d5314d6SJason Wessel memcpy(tmpbuffer, cp, lastchar - cp); 2465d5314d6SJason Wessel memcpy(cp-1, tmpbuffer, lastchar - cp); 2475d5314d6SJason Wessel } 2485d5314d6SJason Wessel *(--lastchar) = '\0'; 2495d5314d6SJason Wessel --cp; 2505d5314d6SJason Wessel kdb_printf("\b%s \r", cp); 2515d5314d6SJason Wessel tmp = *cp; 2525d5314d6SJason Wessel *cp = '\0'; 2535d5314d6SJason Wessel kdb_printf(kdb_prompt_str); 2545d5314d6SJason Wessel kdb_printf("%s", buffer); 2555d5314d6SJason Wessel *cp = tmp; 2565d5314d6SJason Wessel } 2575d5314d6SJason Wessel break; 2585d5314d6SJason Wessel case 13: /* enter */ 2595d5314d6SJason Wessel *lastchar++ = '\n'; 2605d5314d6SJason Wessel *lastchar++ = '\0'; 26137f86b46SJason Wessel if (!KDB_STATE(KGDB_TRANS)) { 26237f86b46SJason Wessel KDB_STATE_SET(KGDB_TRANS); 26337f86b46SJason Wessel kdb_printf("%s", buffer); 26437f86b46SJason Wessel } 2655d5314d6SJason Wessel kdb_printf("\n"); 2665d5314d6SJason Wessel return buffer; 2675d5314d6SJason Wessel case 4: /* Del */ 2685d5314d6SJason Wessel if (cp < lastchar) { 2695d5314d6SJason Wessel memcpy(tmpbuffer, cp+1, lastchar - cp - 1); 2705d5314d6SJason Wessel memcpy(cp, tmpbuffer, lastchar - cp - 1); 2715d5314d6SJason Wessel *(--lastchar) = '\0'; 2725d5314d6SJason Wessel kdb_printf("%s \r", cp); 2735d5314d6SJason Wessel tmp = *cp; 2745d5314d6SJason Wessel *cp = '\0'; 2755d5314d6SJason Wessel kdb_printf(kdb_prompt_str); 2765d5314d6SJason Wessel kdb_printf("%s", buffer); 2775d5314d6SJason Wessel *cp = tmp; 2785d5314d6SJason Wessel } 2795d5314d6SJason Wessel break; 2805d5314d6SJason Wessel case 1: /* Home */ 2815d5314d6SJason Wessel if (cp > buffer) { 2825d5314d6SJason Wessel kdb_printf("\r"); 2835d5314d6SJason Wessel kdb_printf(kdb_prompt_str); 2845d5314d6SJason Wessel cp = buffer; 2855d5314d6SJason Wessel } 2865d5314d6SJason Wessel break; 2875d5314d6SJason Wessel case 5: /* End */ 2885d5314d6SJason Wessel if (cp < lastchar) { 2895d5314d6SJason Wessel kdb_printf("%s", cp); 2905d5314d6SJason Wessel cp = lastchar; 2915d5314d6SJason Wessel } 2925d5314d6SJason Wessel break; 2935d5314d6SJason Wessel case 2: /* Left */ 2945d5314d6SJason Wessel if (cp > buffer) { 2955d5314d6SJason Wessel kdb_printf("\b"); 2965d5314d6SJason Wessel --cp; 2975d5314d6SJason Wessel } 2985d5314d6SJason Wessel break; 2995d5314d6SJason Wessel case 14: /* Down */ 3005d5314d6SJason Wessel memset(tmpbuffer, ' ', 3015d5314d6SJason Wessel strlen(kdb_prompt_str) + (lastchar-buffer)); 3025d5314d6SJason Wessel *(tmpbuffer+strlen(kdb_prompt_str) + 3035d5314d6SJason Wessel (lastchar-buffer)) = '\0'; 3045d5314d6SJason Wessel kdb_printf("\r%s\r", tmpbuffer); 3055d5314d6SJason Wessel *lastchar = (char)key; 3065d5314d6SJason Wessel *(lastchar+1) = '\0'; 3075d5314d6SJason Wessel return lastchar; 3085d5314d6SJason Wessel case 6: /* Right */ 3095d5314d6SJason Wessel if (cp < lastchar) { 3105d5314d6SJason Wessel kdb_printf("%c", *cp); 3115d5314d6SJason Wessel ++cp; 3125d5314d6SJason Wessel } 3135d5314d6SJason Wessel break; 3145d5314d6SJason Wessel case 16: /* Up */ 3155d5314d6SJason Wessel memset(tmpbuffer, ' ', 3165d5314d6SJason Wessel strlen(kdb_prompt_str) + (lastchar-buffer)); 3175d5314d6SJason Wessel *(tmpbuffer+strlen(kdb_prompt_str) + 3185d5314d6SJason Wessel (lastchar-buffer)) = '\0'; 3195d5314d6SJason Wessel kdb_printf("\r%s\r", tmpbuffer); 3205d5314d6SJason Wessel *lastchar = (char)key; 3215d5314d6SJason Wessel *(lastchar+1) = '\0'; 3225d5314d6SJason Wessel return lastchar; 3235d5314d6SJason Wessel case 9: /* Tab */ 3245d5314d6SJason Wessel if (tab < 2) 3255d5314d6SJason Wessel ++tab; 3265d5314d6SJason Wessel p_tmp = buffer; 3275d5314d6SJason Wessel while (*p_tmp == ' ') 3285d5314d6SJason Wessel p_tmp++; 3295d5314d6SJason Wessel if (p_tmp > cp) 3305d5314d6SJason Wessel break; 3315d5314d6SJason Wessel memcpy(tmpbuffer, p_tmp, cp-p_tmp); 3325d5314d6SJason Wessel *(tmpbuffer + (cp-p_tmp)) = '\0'; 3335d5314d6SJason Wessel p_tmp = strrchr(tmpbuffer, ' '); 3345d5314d6SJason Wessel if (p_tmp) 3355d5314d6SJason Wessel ++p_tmp; 3365d5314d6SJason Wessel else 3375d5314d6SJason Wessel p_tmp = tmpbuffer; 3385d5314d6SJason Wessel len = strlen(p_tmp); 3395d5314d6SJason Wessel count = kallsyms_symbol_complete(p_tmp, 3405d5314d6SJason Wessel sizeof(tmpbuffer) - 3415d5314d6SJason Wessel (p_tmp - tmpbuffer)); 3425d5314d6SJason Wessel if (tab == 2 && count > 0) { 3435d5314d6SJason Wessel kdb_printf("\n%d symbols are found.", count); 3445d5314d6SJason Wessel if (count > dtab_count) { 3455d5314d6SJason Wessel count = dtab_count; 3465d5314d6SJason Wessel kdb_printf(" But only first %d symbols will" 3475d5314d6SJason Wessel " be printed.\nYou can change the" 3485d5314d6SJason Wessel " environment variable DTABCOUNT.", 3495d5314d6SJason Wessel count); 3505d5314d6SJason Wessel } 3515d5314d6SJason Wessel kdb_printf("\n"); 3525d5314d6SJason Wessel for (i = 0; i < count; i++) { 3535d5314d6SJason Wessel if (kallsyms_symbol_next(p_tmp, i) < 0) 3545d5314d6SJason Wessel break; 3555d5314d6SJason Wessel kdb_printf("%s ", p_tmp); 3565d5314d6SJason Wessel *(p_tmp + len) = '\0'; 3575d5314d6SJason Wessel } 3585d5314d6SJason Wessel if (i >= dtab_count) 3595d5314d6SJason Wessel kdb_printf("..."); 3605d5314d6SJason Wessel kdb_printf("\n"); 3615d5314d6SJason Wessel kdb_printf(kdb_prompt_str); 3625d5314d6SJason Wessel kdb_printf("%s", buffer); 3635d5314d6SJason Wessel } else if (tab != 2 && count > 0) { 3645d5314d6SJason Wessel len_tmp = strlen(p_tmp); 3655d5314d6SJason Wessel strncpy(p_tmp+len_tmp, cp, lastchar-cp+1); 3665d5314d6SJason Wessel len_tmp = strlen(p_tmp); 3675d5314d6SJason Wessel strncpy(cp, p_tmp+len, len_tmp-len + 1); 3685d5314d6SJason Wessel len = len_tmp - len; 3695d5314d6SJason Wessel kdb_printf("%s", cp); 3705d5314d6SJason Wessel cp += len; 3715d5314d6SJason Wessel lastchar += len; 3725d5314d6SJason Wessel } 3735d5314d6SJason Wessel kdb_nextline = 1; /* reset output line number */ 3745d5314d6SJason Wessel break; 3755d5314d6SJason Wessel default: 3765d5314d6SJason Wessel if (key >= 32 && lastchar < bufend) { 3775d5314d6SJason Wessel if (cp < lastchar) { 3785d5314d6SJason Wessel memcpy(tmpbuffer, cp, lastchar - cp); 3795d5314d6SJason Wessel memcpy(cp+1, tmpbuffer, lastchar - cp); 3805d5314d6SJason Wessel *++lastchar = '\0'; 3815d5314d6SJason Wessel *cp = key; 3825d5314d6SJason Wessel kdb_printf("%s\r", cp); 3835d5314d6SJason Wessel ++cp; 3845d5314d6SJason Wessel tmp = *cp; 3855d5314d6SJason Wessel *cp = '\0'; 3865d5314d6SJason Wessel kdb_printf(kdb_prompt_str); 3875d5314d6SJason Wessel kdb_printf("%s", buffer); 3885d5314d6SJason Wessel *cp = tmp; 3895d5314d6SJason Wessel } else { 3905d5314d6SJason Wessel *++lastchar = '\0'; 3915d5314d6SJason Wessel *cp++ = key; 3925d5314d6SJason Wessel /* The kgdb transition check will hide 3935d5314d6SJason Wessel * printed characters if we think that 3945d5314d6SJason Wessel * kgdb is connecting, until the check 3955d5314d6SJason Wessel * fails */ 39637f86b46SJason Wessel if (!KDB_STATE(KGDB_TRANS)) { 39737f86b46SJason Wessel if (kgdb_transition_check(buffer)) 39837f86b46SJason Wessel return buffer; 39937f86b46SJason Wessel } else { 4005d5314d6SJason Wessel kdb_printf("%c", key); 4015d5314d6SJason Wessel } 40237f86b46SJason Wessel } 4035d5314d6SJason Wessel /* Special escape to kgdb */ 4045d5314d6SJason Wessel if (lastchar - buffer >= 5 && 4055d5314d6SJason Wessel strcmp(lastchar - 5, "$?#3f") == 0) { 406f679c498SJason Wessel kdb_gdb_state_pass(lastchar - 5); 4075d5314d6SJason Wessel strcpy(buffer, "kgdb"); 4085d5314d6SJason Wessel KDB_STATE_SET(DOING_KGDB); 4095d5314d6SJason Wessel return buffer; 4105d5314d6SJason Wessel } 411f679c498SJason Wessel if (lastchar - buffer >= 11 && 412f679c498SJason Wessel strcmp(lastchar - 11, "$qSupported") == 0) { 413f679c498SJason Wessel kdb_gdb_state_pass(lastchar - 11); 4145d5314d6SJason Wessel strcpy(buffer, "kgdb"); 415d613d828SJason Wessel KDB_STATE_SET(DOING_KGDB); 4165d5314d6SJason Wessel return buffer; 4175d5314d6SJason Wessel } 4185d5314d6SJason Wessel } 4195d5314d6SJason Wessel break; 4205d5314d6SJason Wessel } 4215d5314d6SJason Wessel goto poll_again; 4225d5314d6SJason Wessel } 4235d5314d6SJason Wessel 4245d5314d6SJason Wessel /* 4255d5314d6SJason Wessel * kdb_getstr 4265d5314d6SJason Wessel * 4275d5314d6SJason Wessel * Print the prompt string and read a command from the 4285d5314d6SJason Wessel * input device. 4295d5314d6SJason Wessel * 4305d5314d6SJason Wessel * Parameters: 4315d5314d6SJason Wessel * buffer Address of buffer to receive command 4325d5314d6SJason Wessel * bufsize Size of buffer in bytes 4335d5314d6SJason Wessel * prompt Pointer to string to use as prompt string 4345d5314d6SJason Wessel * Returns: 4355d5314d6SJason Wessel * Pointer to command buffer. 4365d5314d6SJason Wessel * Locking: 4375d5314d6SJason Wessel * None. 4385d5314d6SJason Wessel * Remarks: 4395d5314d6SJason Wessel * For SMP kernels, the processor number will be 4405d5314d6SJason Wessel * substituted for %d, %x or %o in the prompt. 4415d5314d6SJason Wessel */ 4425d5314d6SJason Wessel 44332d375f6SDaniel Thompson char *kdb_getstr(char *buffer, size_t bufsize, const char *prompt) 4445d5314d6SJason Wessel { 4455d5314d6SJason Wessel if (prompt && kdb_prompt_str != prompt) 4465d5314d6SJason Wessel strncpy(kdb_prompt_str, prompt, CMD_BUFLEN); 4475d5314d6SJason Wessel kdb_printf(kdb_prompt_str); 4485d5314d6SJason Wessel kdb_nextline = 1; /* Prompt and input resets line number */ 4495d5314d6SJason Wessel return kdb_read(buffer, bufsize); 4505d5314d6SJason Wessel } 4515d5314d6SJason Wessel 4525d5314d6SJason Wessel /* 4535d5314d6SJason Wessel * kdb_input_flush 4545d5314d6SJason Wessel * 4555d5314d6SJason Wessel * Get rid of any buffered console input. 4565d5314d6SJason Wessel * 4575d5314d6SJason Wessel * Parameters: 4585d5314d6SJason Wessel * none 4595d5314d6SJason Wessel * Returns: 4605d5314d6SJason Wessel * nothing 4615d5314d6SJason Wessel * Locking: 4625d5314d6SJason Wessel * none 4635d5314d6SJason Wessel * Remarks: 4645d5314d6SJason Wessel * Call this function whenever you want to flush input. If there is any 4655d5314d6SJason Wessel * outstanding input, it ignores all characters until there has been no 4665d5314d6SJason Wessel * data for approximately 1ms. 4675d5314d6SJason Wessel */ 4685d5314d6SJason Wessel 4695d5314d6SJason Wessel static void kdb_input_flush(void) 4705d5314d6SJason Wessel { 4715d5314d6SJason Wessel get_char_func *f; 4725d5314d6SJason Wessel int res; 4735d5314d6SJason Wessel int flush_delay = 1; 4745d5314d6SJason Wessel while (flush_delay) { 4755d5314d6SJason Wessel flush_delay--; 4765d5314d6SJason Wessel empty: 4775d5314d6SJason Wessel touch_nmi_watchdog(); 4785d5314d6SJason Wessel for (f = &kdb_poll_funcs[0]; *f; ++f) { 4795d5314d6SJason Wessel res = (*f)(); 4805d5314d6SJason Wessel if (res != -1) { 4815d5314d6SJason Wessel flush_delay = 1; 4825d5314d6SJason Wessel goto empty; 4835d5314d6SJason Wessel } 4845d5314d6SJason Wessel } 4855d5314d6SJason Wessel if (flush_delay) 4865d5314d6SJason Wessel mdelay(1); 4875d5314d6SJason Wessel } 4885d5314d6SJason Wessel } 4895d5314d6SJason Wessel 4905d5314d6SJason Wessel /* 4915d5314d6SJason Wessel * kdb_printf 4925d5314d6SJason Wessel * 4935d5314d6SJason Wessel * Print a string to the output device(s). 4945d5314d6SJason Wessel * 4955d5314d6SJason Wessel * Parameters: 4965d5314d6SJason Wessel * printf-like format and optional args. 4975d5314d6SJason Wessel * Returns: 4985d5314d6SJason Wessel * 0 4995d5314d6SJason Wessel * Locking: 5005d5314d6SJason Wessel * None. 5015d5314d6SJason Wessel * Remarks: 5025d5314d6SJason Wessel * use 'kdbcons->write()' to avoid polluting 'log_buf' with 5035d5314d6SJason Wessel * kdb output. 5045d5314d6SJason Wessel * 5055d5314d6SJason Wessel * If the user is doing a cmd args | grep srch 5065d5314d6SJason Wessel * then kdb_grepping_flag is set. 5075d5314d6SJason Wessel * In that case we need to accumulate full lines (ending in \n) before 5085d5314d6SJason Wessel * searching for the pattern. 5095d5314d6SJason Wessel */ 5105d5314d6SJason Wessel 5115d5314d6SJason Wessel static char kdb_buffer[256]; /* A bit too big to go on stack */ 5125d5314d6SJason Wessel static char *next_avail = kdb_buffer; 5135d5314d6SJason Wessel static int size_avail; 5145d5314d6SJason Wessel static int suspend_grep; 5155d5314d6SJason Wessel 5165d5314d6SJason Wessel /* 5175d5314d6SJason Wessel * search arg1 to see if it contains arg2 5185d5314d6SJason Wessel * (kdmain.c provides flags for ^pat and pat$) 5195d5314d6SJason Wessel * 5205d5314d6SJason Wessel * return 1 for found, 0 for not found 5215d5314d6SJason Wessel */ 5225d5314d6SJason Wessel static int kdb_search_string(char *searched, char *searchfor) 5235d5314d6SJason Wessel { 5245d5314d6SJason Wessel char firstchar, *cp; 5255d5314d6SJason Wessel int len1, len2; 5265d5314d6SJason Wessel 5275d5314d6SJason Wessel /* not counting the newline at the end of "searched" */ 5285d5314d6SJason Wessel len1 = strlen(searched)-1; 5295d5314d6SJason Wessel len2 = strlen(searchfor); 5305d5314d6SJason Wessel if (len1 < len2) 5315d5314d6SJason Wessel return 0; 5325d5314d6SJason Wessel if (kdb_grep_leading && kdb_grep_trailing && len1 != len2) 5335d5314d6SJason Wessel return 0; 5345d5314d6SJason Wessel if (kdb_grep_leading) { 5355d5314d6SJason Wessel if (!strncmp(searched, searchfor, len2)) 5365d5314d6SJason Wessel return 1; 5375d5314d6SJason Wessel } else if (kdb_grep_trailing) { 5385d5314d6SJason Wessel if (!strncmp(searched+len1-len2, searchfor, len2)) 5395d5314d6SJason Wessel return 1; 5405d5314d6SJason Wessel } else { 5415d5314d6SJason Wessel firstchar = *searchfor; 5425d5314d6SJason Wessel cp = searched; 5435d5314d6SJason Wessel while ((cp = strchr(cp, firstchar))) { 5445d5314d6SJason Wessel if (!strncmp(cp, searchfor, len2)) 5455d5314d6SJason Wessel return 1; 5465d5314d6SJason Wessel cp++; 5475d5314d6SJason Wessel } 5485d5314d6SJason Wessel } 5495d5314d6SJason Wessel return 0; 5505d5314d6SJason Wessel } 5515d5314d6SJason Wessel 552f7d4ca8bSDaniel Thompson int vkdb_printf(enum kdb_msgsrc src, const char *fmt, va_list ap) 5535d5314d6SJason Wessel { 5545d5314d6SJason Wessel int diag; 5555d5314d6SJason Wessel int linecount; 55617b572e8SJason Wessel int colcount; 5575d5314d6SJason Wessel int logging, saved_loglevel = 0; 5585d5314d6SJason Wessel int retlen = 0; 5595d5314d6SJason Wessel int fnd, len; 560d5d8d3d0SPetr Mladek int this_cpu, old_cpu; 5615d5314d6SJason Wessel char *cp, *cp2, *cphold = NULL, replaced_byte = ' '; 5625d5314d6SJason Wessel char *moreprompt = "more> "; 5635d5314d6SJason Wessel struct console *c = console_drivers; 5645d5314d6SJason Wessel unsigned long uninitialized_var(flags); 5655d5314d6SJason Wessel 5665d5314d6SJason Wessel /* Serialize kdb_printf if multiple cpus try to write at once. 5675d5314d6SJason Wessel * But if any cpu goes recursive in kdb, just print the output, 5685d5314d6SJason Wessel * even if it is interleaved with any other text. 5695d5314d6SJason Wessel */ 57034aaff40SPetr Mladek local_irq_save(flags); 571d5d8d3d0SPetr Mladek this_cpu = smp_processor_id(); 572d5d8d3d0SPetr Mladek for (;;) { 573d5d8d3d0SPetr Mladek old_cpu = cmpxchg(&kdb_printf_cpu, -1, this_cpu); 574d5d8d3d0SPetr Mladek if (old_cpu == -1 || old_cpu == this_cpu) 575d5d8d3d0SPetr Mladek break; 576d5d8d3d0SPetr Mladek 577d5d8d3d0SPetr Mladek cpu_relax(); 5785d5314d6SJason Wessel } 5795d5314d6SJason Wessel 5805d5314d6SJason Wessel diag = kdbgetintenv("LINES", &linecount); 5815d5314d6SJason Wessel if (diag || linecount <= 1) 5825d5314d6SJason Wessel linecount = 24; 5835d5314d6SJason Wessel 58417b572e8SJason Wessel diag = kdbgetintenv("COLUMNS", &colcount); 58517b572e8SJason Wessel if (diag || colcount <= 1) 58617b572e8SJason Wessel colcount = 80; 58717b572e8SJason Wessel 5885d5314d6SJason Wessel diag = kdbgetintenv("LOGGING", &logging); 5895d5314d6SJason Wessel if (diag) 5905d5314d6SJason Wessel logging = 0; 5915d5314d6SJason Wessel 5925d5314d6SJason Wessel if (!kdb_grepping_flag || suspend_grep) { 5935d5314d6SJason Wessel /* normally, every vsnprintf starts a new buffer */ 5945d5314d6SJason Wessel next_avail = kdb_buffer; 5955d5314d6SJason Wessel size_avail = sizeof(kdb_buffer); 5965d5314d6SJason Wessel } 5975d5314d6SJason Wessel vsnprintf(next_avail, size_avail, fmt, ap); 5985d5314d6SJason Wessel 5995d5314d6SJason Wessel /* 6005d5314d6SJason Wessel * If kdb_parse() found that the command was cmd xxx | grep yyy 6015d5314d6SJason Wessel * then kdb_grepping_flag is set, and kdb_grep_string contains yyy 6025d5314d6SJason Wessel * 6035d5314d6SJason Wessel * Accumulate the print data up to a newline before searching it. 6045d5314d6SJason Wessel * (vsnprintf does null-terminate the string that it generates) 6055d5314d6SJason Wessel */ 6065d5314d6SJason Wessel 6075d5314d6SJason Wessel /* skip the search if prints are temporarily unconditional */ 6085d5314d6SJason Wessel if (!suspend_grep && kdb_grepping_flag) { 6095d5314d6SJason Wessel cp = strchr(kdb_buffer, '\n'); 6105d5314d6SJason Wessel if (!cp) { 6115d5314d6SJason Wessel /* 6125d5314d6SJason Wessel * Special cases that don't end with newlines 6135d5314d6SJason Wessel * but should be written without one: 6145d5314d6SJason Wessel * The "[nn]kdb> " prompt should 6155d5314d6SJason Wessel * appear at the front of the buffer. 6165d5314d6SJason Wessel * 6175d5314d6SJason Wessel * The "[nn]more " prompt should also be 6185d5314d6SJason Wessel * (MOREPROMPT -> moreprompt) 6195d5314d6SJason Wessel * written * but we print that ourselves, 6205d5314d6SJason Wessel * we set the suspend_grep flag to make 6215d5314d6SJason Wessel * it unconditional. 6225d5314d6SJason Wessel * 6235d5314d6SJason Wessel */ 6245d5314d6SJason Wessel if (next_avail == kdb_buffer) { 6255d5314d6SJason Wessel /* 6265d5314d6SJason Wessel * these should occur after a newline, 6275d5314d6SJason Wessel * so they will be at the front of the 6285d5314d6SJason Wessel * buffer 6295d5314d6SJason Wessel */ 6305d5314d6SJason Wessel cp2 = kdb_buffer; 6315d5314d6SJason Wessel len = strlen(kdb_prompt_str); 6325d5314d6SJason Wessel if (!strncmp(cp2, kdb_prompt_str, len)) { 6335d5314d6SJason Wessel /* 6345d5314d6SJason Wessel * We're about to start a new 6355d5314d6SJason Wessel * command, so we can go back 6365d5314d6SJason Wessel * to normal mode. 6375d5314d6SJason Wessel */ 6385d5314d6SJason Wessel kdb_grepping_flag = 0; 6395d5314d6SJason Wessel goto kdb_printit; 6405d5314d6SJason Wessel } 6415d5314d6SJason Wessel } 6425d5314d6SJason Wessel /* no newline; don't search/write the buffer 6435d5314d6SJason Wessel until one is there */ 6445d5314d6SJason Wessel len = strlen(kdb_buffer); 6455d5314d6SJason Wessel next_avail = kdb_buffer + len; 6465d5314d6SJason Wessel size_avail = sizeof(kdb_buffer) - len; 6475d5314d6SJason Wessel goto kdb_print_out; 6485d5314d6SJason Wessel } 6495d5314d6SJason Wessel 6505d5314d6SJason Wessel /* 6515d5314d6SJason Wessel * The newline is present; print through it or discard 6525d5314d6SJason Wessel * it, depending on the results of the search. 6535d5314d6SJason Wessel */ 6545d5314d6SJason Wessel cp++; /* to byte after the newline */ 6555d5314d6SJason Wessel replaced_byte = *cp; /* remember what/where it was */ 6565d5314d6SJason Wessel cphold = cp; 6575d5314d6SJason Wessel *cp = '\0'; /* end the string for our search */ 6585d5314d6SJason Wessel 6595d5314d6SJason Wessel /* 6605d5314d6SJason Wessel * We now have a newline at the end of the string 6615d5314d6SJason Wessel * Only continue with this output if it contains the 6625d5314d6SJason Wessel * search string. 6635d5314d6SJason Wessel */ 6645d5314d6SJason Wessel fnd = kdb_search_string(kdb_buffer, kdb_grep_string); 6655d5314d6SJason Wessel if (!fnd) { 6665d5314d6SJason Wessel /* 6675d5314d6SJason Wessel * At this point the complete line at the start 6685d5314d6SJason Wessel * of kdb_buffer can be discarded, as it does 6695d5314d6SJason Wessel * not contain what the user is looking for. 6705d5314d6SJason Wessel * Shift the buffer left. 6715d5314d6SJason Wessel */ 6725d5314d6SJason Wessel *cphold = replaced_byte; 6735d5314d6SJason Wessel strcpy(kdb_buffer, cphold); 6745d5314d6SJason Wessel len = strlen(kdb_buffer); 6755d5314d6SJason Wessel next_avail = kdb_buffer + len; 6765d5314d6SJason Wessel size_avail = sizeof(kdb_buffer) - len; 6775d5314d6SJason Wessel goto kdb_print_out; 6785d5314d6SJason Wessel } 679fb6daa75SDaniel Thompson if (kdb_grepping_flag >= KDB_GREPPING_FLAG_SEARCH) 680fb6daa75SDaniel Thompson /* 681fb6daa75SDaniel Thompson * This was a interactive search (using '/' at more 682fb6daa75SDaniel Thompson * prompt) and it has completed. Clear the flag. 683fb6daa75SDaniel Thompson */ 684fb6daa75SDaniel Thompson kdb_grepping_flag = 0; 6855d5314d6SJason Wessel /* 6865d5314d6SJason Wessel * at this point the string is a full line and 6875d5314d6SJason Wessel * should be printed, up to the null. 6885d5314d6SJason Wessel */ 6895d5314d6SJason Wessel } 6905d5314d6SJason Wessel kdb_printit: 6915d5314d6SJason Wessel 6925d5314d6SJason Wessel /* 6935d5314d6SJason Wessel * Write to all consoles. 6945d5314d6SJason Wessel */ 6955d5314d6SJason Wessel retlen = strlen(kdb_buffer); 69649795757SPetr Mladek cp = (char *) printk_skip_headers(kdb_buffer); 697a0de055cSJason Wessel if (!dbg_kdb_mode && kgdb_connected) { 698f7d4ca8bSDaniel Thompson gdbstub_msg_write(cp, retlen - (cp - kdb_buffer)); 699a0de055cSJason Wessel } else { 700b8adde8dSTim Bird if (dbg_io_ops && !dbg_io_ops->is_console) { 701f7d4ca8bSDaniel Thompson len = retlen - (cp - kdb_buffer); 702f7d4ca8bSDaniel Thompson cp2 = cp; 703efe2f29eSJason Wessel while (len--) { 704f7d4ca8bSDaniel Thompson dbg_io_ops->write_char(*cp2); 705f7d4ca8bSDaniel Thompson cp2++; 706efe2f29eSJason Wessel } 707efe2f29eSJason Wessel } 7085d5314d6SJason Wessel while (c) { 709f7d4ca8bSDaniel Thompson c->write(c, cp, retlen - (cp - kdb_buffer)); 7105d5314d6SJason Wessel touch_nmi_watchdog(); 7115d5314d6SJason Wessel c = c->next; 7125d5314d6SJason Wessel } 713a0de055cSJason Wessel } 7145d5314d6SJason Wessel if (logging) { 7155d5314d6SJason Wessel saved_loglevel = console_loglevel; 716a8fe19ebSBorislav Petkov console_loglevel = CONSOLE_LOGLEVEL_SILENT; 717f7d4ca8bSDaniel Thompson if (printk_get_level(kdb_buffer) || src == KDB_MSGSRC_PRINTK) 718f7d4ca8bSDaniel Thompson printk("%s", kdb_buffer); 719f7d4ca8bSDaniel Thompson else 720f7d4ca8bSDaniel Thompson pr_info("%s", kdb_buffer); 7215d5314d6SJason Wessel } 7225d5314d6SJason Wessel 72317b572e8SJason Wessel if (KDB_STATE(PAGER)) { 72417b572e8SJason Wessel /* 72517b572e8SJason Wessel * Check printed string to decide how to bump the 72617b572e8SJason Wessel * kdb_nextline to control when the more prompt should 72717b572e8SJason Wessel * show up. 72817b572e8SJason Wessel */ 72917b572e8SJason Wessel int got = 0; 73017b572e8SJason Wessel len = retlen; 73117b572e8SJason Wessel while (len--) { 73217b572e8SJason Wessel if (kdb_buffer[len] == '\n') { 7335d5314d6SJason Wessel kdb_nextline++; 73417b572e8SJason Wessel got = 0; 73517b572e8SJason Wessel } else if (kdb_buffer[len] == '\r') { 73617b572e8SJason Wessel got = 0; 73717b572e8SJason Wessel } else { 73817b572e8SJason Wessel got++; 73917b572e8SJason Wessel } 74017b572e8SJason Wessel } 74117b572e8SJason Wessel kdb_nextline += got / (colcount + 1); 74217b572e8SJason Wessel } 7435d5314d6SJason Wessel 7445d5314d6SJason Wessel /* check for having reached the LINES number of printed lines */ 74517b572e8SJason Wessel if (kdb_nextline >= linecount) { 7465d5314d6SJason Wessel char buf1[16] = ""; 7475d5314d6SJason Wessel 7485d5314d6SJason Wessel /* Watch out for recursion here. Any routine that calls 7495d5314d6SJason Wessel * kdb_printf will come back through here. And kdb_read 7505d5314d6SJason Wessel * uses kdb_printf to echo on serial consoles ... 7515d5314d6SJason Wessel */ 7525d5314d6SJason Wessel kdb_nextline = 1; /* In case of recursion */ 7535d5314d6SJason Wessel 7545d5314d6SJason Wessel /* 7555d5314d6SJason Wessel * Pause until cr. 7565d5314d6SJason Wessel */ 7575d5314d6SJason Wessel moreprompt = kdbgetenv("MOREPROMPT"); 7585d5314d6SJason Wessel if (moreprompt == NULL) 7595d5314d6SJason Wessel moreprompt = "more> "; 7605d5314d6SJason Wessel 7615d5314d6SJason Wessel kdb_input_flush(); 7625d5314d6SJason Wessel c = console_drivers; 7635d5314d6SJason Wessel 76478724b8eSJason Wessel if (dbg_io_ops && !dbg_io_ops->is_console) { 765efe2f29eSJason Wessel len = strlen(moreprompt); 766efe2f29eSJason Wessel cp = moreprompt; 767efe2f29eSJason Wessel while (len--) { 768efe2f29eSJason Wessel dbg_io_ops->write_char(*cp); 769efe2f29eSJason Wessel cp++; 770efe2f29eSJason Wessel } 771efe2f29eSJason Wessel } 7725d5314d6SJason Wessel while (c) { 7735d5314d6SJason Wessel c->write(c, moreprompt, strlen(moreprompt)); 7745d5314d6SJason Wessel touch_nmi_watchdog(); 7755d5314d6SJason Wessel c = c->next; 7765d5314d6SJason Wessel } 7775d5314d6SJason Wessel 7785d5314d6SJason Wessel if (logging) 7795d5314d6SJason Wessel printk("%s", moreprompt); 7805d5314d6SJason Wessel 7815d5314d6SJason Wessel kdb_read(buf1, 2); /* '2' indicates to return 7825d5314d6SJason Wessel * immediately after getting one key. */ 7835d5314d6SJason Wessel kdb_nextline = 1; /* Really set output line 1 */ 7845d5314d6SJason Wessel 7855d5314d6SJason Wessel /* empty and reset the buffer: */ 7865d5314d6SJason Wessel kdb_buffer[0] = '\0'; 7875d5314d6SJason Wessel next_avail = kdb_buffer; 7885d5314d6SJason Wessel size_avail = sizeof(kdb_buffer); 7895d5314d6SJason Wessel if ((buf1[0] == 'q') || (buf1[0] == 'Q')) { 7905d5314d6SJason Wessel /* user hit q or Q */ 7915d5314d6SJason Wessel KDB_FLAG_SET(CMD_INTERRUPT); /* command interrupted */ 7925d5314d6SJason Wessel KDB_STATE_CLEAR(PAGER); 7935d5314d6SJason Wessel /* end of command output; back to normal mode */ 7945d5314d6SJason Wessel kdb_grepping_flag = 0; 7955d5314d6SJason Wessel kdb_printf("\n"); 7965d5314d6SJason Wessel } else if (buf1[0] == ' ') { 79717b572e8SJason Wessel kdb_printf("\r"); 7985d5314d6SJason Wessel suspend_grep = 1; /* for this recursion */ 7995d5314d6SJason Wessel } else if (buf1[0] == '\n') { 8005d5314d6SJason Wessel kdb_nextline = linecount - 1; 8015d5314d6SJason Wessel kdb_printf("\r"); 8025d5314d6SJason Wessel suspend_grep = 1; /* for this recursion */ 803fb6daa75SDaniel Thompson } else if (buf1[0] == '/' && !kdb_grepping_flag) { 804fb6daa75SDaniel Thompson kdb_printf("\r"); 805fb6daa75SDaniel Thompson kdb_getstr(kdb_grep_string, KDB_GREP_STRLEN, 806fb6daa75SDaniel Thompson kdbgetenv("SEARCHPROMPT") ?: "search> "); 807fb6daa75SDaniel Thompson *strchrnul(kdb_grep_string, '\n') = '\0'; 808fb6daa75SDaniel Thompson kdb_grepping_flag += KDB_GREPPING_FLAG_SEARCH; 809fb6daa75SDaniel Thompson suspend_grep = 1; /* for this recursion */ 8105d5314d6SJason Wessel } else if (buf1[0] && buf1[0] != '\n') { 8115d5314d6SJason Wessel /* user hit something other than enter */ 8125d5314d6SJason Wessel suspend_grep = 1; /* for this recursion */ 813fb6daa75SDaniel Thompson if (buf1[0] != '/') 814fb6daa75SDaniel Thompson kdb_printf( 815fb6daa75SDaniel Thompson "\nOnly 'q', 'Q' or '/' are processed at " 816fb6daa75SDaniel Thompson "more prompt, input ignored\n"); 817fb6daa75SDaniel Thompson else 818fb6daa75SDaniel Thompson kdb_printf("\n'/' cannot be used during | " 819fb6daa75SDaniel Thompson "grep filtering, input ignored\n"); 8205d5314d6SJason Wessel } else if (kdb_grepping_flag) { 8215d5314d6SJason Wessel /* user hit enter */ 8225d5314d6SJason Wessel suspend_grep = 1; /* for this recursion */ 8235d5314d6SJason Wessel kdb_printf("\n"); 8245d5314d6SJason Wessel } 8255d5314d6SJason Wessel kdb_input_flush(); 8265d5314d6SJason Wessel } 8275d5314d6SJason Wessel 8285d5314d6SJason Wessel /* 8295d5314d6SJason Wessel * For grep searches, shift the printed string left. 8305d5314d6SJason Wessel * replaced_byte contains the character that was overwritten with 8315d5314d6SJason Wessel * the terminating null, and cphold points to the null. 8325d5314d6SJason Wessel * Then adjust the notion of available space in the buffer. 8335d5314d6SJason Wessel */ 8345d5314d6SJason Wessel if (kdb_grepping_flag && !suspend_grep) { 8355d5314d6SJason Wessel *cphold = replaced_byte; 8365d5314d6SJason Wessel strcpy(kdb_buffer, cphold); 8375d5314d6SJason Wessel len = strlen(kdb_buffer); 8385d5314d6SJason Wessel next_avail = kdb_buffer + len; 8395d5314d6SJason Wessel size_avail = sizeof(kdb_buffer) - len; 8405d5314d6SJason Wessel } 8415d5314d6SJason Wessel 8425d5314d6SJason Wessel kdb_print_out: 8435d5314d6SJason Wessel suspend_grep = 0; /* end of what may have been a recursive call */ 8445d5314d6SJason Wessel if (logging) 8455d5314d6SJason Wessel console_loglevel = saved_loglevel; 846d5d8d3d0SPetr Mladek /* kdb_printf_cpu locked the code above. */ 847d5d8d3d0SPetr Mladek smp_store_release(&kdb_printf_cpu, old_cpu); 848d5d8d3d0SPetr Mladek local_irq_restore(flags); 8495d5314d6SJason Wessel return retlen; 8505d5314d6SJason Wessel } 851d37d39aeSJason Wessel 852d37d39aeSJason Wessel int kdb_printf(const char *fmt, ...) 853d37d39aeSJason Wessel { 854d37d39aeSJason Wessel va_list ap; 855d37d39aeSJason Wessel int r; 856d37d39aeSJason Wessel 857d37d39aeSJason Wessel va_start(ap, fmt); 858f7d4ca8bSDaniel Thompson r = vkdb_printf(KDB_MSGSRC_INTERNAL, fmt, ap); 859d37d39aeSJason Wessel va_end(ap); 860d37d39aeSJason Wessel 861d37d39aeSJason Wessel return r; 862d37d39aeSJason Wessel } 863f7030bbcSJason Wessel EXPORT_SYMBOL_GPL(kdb_printf); 864