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; 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 515d5314d6SJason Wessel static int kdb_read_get_key(char *buffer, size_t bufsize) 525d5314d6SJason Wessel { 535d5314d6SJason Wessel #define ESCAPE_UDELAY 1000 545d5314d6SJason Wessel #define ESCAPE_DELAY (2*1000000/ESCAPE_UDELAY) /* 2 seconds worth of udelays */ 555d5314d6SJason Wessel char escape_data[5]; /* longest vt100 escape sequence is 4 bytes */ 565d5314d6SJason Wessel char *ped = escape_data; 575d5314d6SJason Wessel int escape_delay = 0; 585d5314d6SJason Wessel get_char_func *f, *f_escape = NULL; 595d5314d6SJason Wessel int key; 605d5314d6SJason Wessel 615d5314d6SJason Wessel for (f = &kdb_poll_funcs[0]; ; ++f) { 625d5314d6SJason Wessel if (*f == NULL) { 635d5314d6SJason Wessel /* Reset NMI watchdog once per poll loop */ 645d5314d6SJason Wessel touch_nmi_watchdog(); 655d5314d6SJason Wessel f = &kdb_poll_funcs[0]; 665d5314d6SJason Wessel } 675d5314d6SJason Wessel if (escape_delay == 2) { 685d5314d6SJason Wessel *ped = '\0'; 695d5314d6SJason Wessel ped = escape_data; 705d5314d6SJason Wessel --escape_delay; 715d5314d6SJason Wessel } 725d5314d6SJason Wessel if (escape_delay == 1) { 735d5314d6SJason Wessel key = *ped++; 745d5314d6SJason Wessel if (!*ped) 755d5314d6SJason Wessel --escape_delay; 765d5314d6SJason Wessel break; 775d5314d6SJason Wessel } 785d5314d6SJason Wessel key = (*f)(); 795d5314d6SJason Wessel if (key == -1) { 805d5314d6SJason Wessel if (escape_delay) { 815d5314d6SJason Wessel udelay(ESCAPE_UDELAY); 825d5314d6SJason Wessel --escape_delay; 835d5314d6SJason Wessel } 845d5314d6SJason Wessel continue; 855d5314d6SJason Wessel } 865d5314d6SJason Wessel if (bufsize <= 2) { 875d5314d6SJason Wessel if (key == '\r') 885d5314d6SJason Wessel key = '\n'; 895d5314d6SJason Wessel *buffer++ = key; 905d5314d6SJason Wessel *buffer = '\0'; 915d5314d6SJason Wessel return -1; 925d5314d6SJason Wessel } 935d5314d6SJason Wessel if (escape_delay == 0 && key == '\e') { 945d5314d6SJason Wessel escape_delay = ESCAPE_DELAY; 955d5314d6SJason Wessel ped = escape_data; 965d5314d6SJason Wessel f_escape = f; 975d5314d6SJason Wessel } 985d5314d6SJason Wessel if (escape_delay) { 995d5314d6SJason Wessel *ped++ = key; 1005d5314d6SJason Wessel if (f_escape != f) { 1015d5314d6SJason Wessel escape_delay = 2; 1025d5314d6SJason Wessel continue; 1035d5314d6SJason Wessel } 1045d5314d6SJason Wessel if (ped - escape_data == 1) { 1055d5314d6SJason Wessel /* \e */ 1065d5314d6SJason Wessel continue; 1075d5314d6SJason Wessel } else if (ped - escape_data == 2) { 1085d5314d6SJason Wessel /* \e<something> */ 1095d5314d6SJason Wessel if (key != '[') 1105d5314d6SJason Wessel escape_delay = 2; 1115d5314d6SJason Wessel continue; 1125d5314d6SJason Wessel } else if (ped - escape_data == 3) { 1135d5314d6SJason Wessel /* \e[<something> */ 1145d5314d6SJason Wessel int mapkey = 0; 1155d5314d6SJason Wessel switch (key) { 1165d5314d6SJason Wessel case 'A': /* \e[A, up arrow */ 1175d5314d6SJason Wessel mapkey = 16; 1185d5314d6SJason Wessel break; 1195d5314d6SJason Wessel case 'B': /* \e[B, down arrow */ 1205d5314d6SJason Wessel mapkey = 14; 1215d5314d6SJason Wessel break; 1225d5314d6SJason Wessel case 'C': /* \e[C, right arrow */ 1235d5314d6SJason Wessel mapkey = 6; 1245d5314d6SJason Wessel break; 1255d5314d6SJason Wessel case 'D': /* \e[D, left arrow */ 1265d5314d6SJason Wessel mapkey = 2; 1275d5314d6SJason Wessel break; 1285d5314d6SJason Wessel case '1': /* dropthrough */ 1295d5314d6SJason Wessel case '3': /* dropthrough */ 1305d5314d6SJason Wessel /* \e[<1,3,4>], may be home, del, end */ 1315d5314d6SJason Wessel case '4': 1325d5314d6SJason Wessel mapkey = -1; 1335d5314d6SJason Wessel break; 1345d5314d6SJason Wessel } 1355d5314d6SJason Wessel if (mapkey != -1) { 1365d5314d6SJason Wessel if (mapkey > 0) { 1375d5314d6SJason Wessel escape_data[0] = mapkey; 1385d5314d6SJason Wessel escape_data[1] = '\0'; 1395d5314d6SJason Wessel } 1405d5314d6SJason Wessel escape_delay = 2; 1415d5314d6SJason Wessel } 1425d5314d6SJason Wessel continue; 1435d5314d6SJason Wessel } else if (ped - escape_data == 4) { 1445d5314d6SJason Wessel /* \e[<1,3,4><something> */ 1455d5314d6SJason Wessel int mapkey = 0; 1465d5314d6SJason Wessel if (key == '~') { 1475d5314d6SJason Wessel switch (escape_data[2]) { 1485d5314d6SJason Wessel case '1': /* \e[1~, home */ 1495d5314d6SJason Wessel mapkey = 1; 1505d5314d6SJason Wessel break; 1515d5314d6SJason Wessel case '3': /* \e[3~, del */ 1525d5314d6SJason Wessel mapkey = 4; 1535d5314d6SJason Wessel break; 1545d5314d6SJason Wessel case '4': /* \e[4~, end */ 1555d5314d6SJason Wessel mapkey = 5; 1565d5314d6SJason Wessel break; 1575d5314d6SJason Wessel } 1585d5314d6SJason Wessel } 1595d5314d6SJason Wessel if (mapkey > 0) { 1605d5314d6SJason Wessel escape_data[0] = mapkey; 1615d5314d6SJason Wessel escape_data[1] = '\0'; 1625d5314d6SJason Wessel } 1635d5314d6SJason Wessel escape_delay = 2; 1645d5314d6SJason Wessel continue; 1655d5314d6SJason Wessel } 1665d5314d6SJason Wessel } 1675d5314d6SJason Wessel break; /* A key to process */ 1685d5314d6SJason Wessel } 1695d5314d6SJason Wessel return key; 1705d5314d6SJason Wessel } 1715d5314d6SJason Wessel 1725d5314d6SJason Wessel /* 1735d5314d6SJason Wessel * kdb_read 1745d5314d6SJason Wessel * 1755d5314d6SJason Wessel * This function reads a string of characters, terminated by 1765d5314d6SJason Wessel * a newline, or by reaching the end of the supplied buffer, 1775d5314d6SJason Wessel * from the current kernel debugger console device. 1785d5314d6SJason Wessel * Parameters: 1795d5314d6SJason Wessel * buffer - Address of character buffer to receive input characters. 1805d5314d6SJason Wessel * bufsize - size, in bytes, of the character buffer 1815d5314d6SJason Wessel * Returns: 1825d5314d6SJason Wessel * Returns a pointer to the buffer containing the received 1835d5314d6SJason Wessel * character string. This string will be terminated by a 1845d5314d6SJason Wessel * newline character. 1855d5314d6SJason Wessel * Locking: 1865d5314d6SJason Wessel * No locks are required to be held upon entry to this 1875d5314d6SJason Wessel * function. It is not reentrant - it relies on the fact 1885d5314d6SJason Wessel * that while kdb is running on only one "master debug" cpu. 1895d5314d6SJason Wessel * Remarks: 1905d5314d6SJason Wessel * 1915d5314d6SJason Wessel * The buffer size must be >= 2. A buffer size of 2 means that the caller only 1925d5314d6SJason Wessel * wants a single key. 1935d5314d6SJason Wessel * 1945d5314d6SJason Wessel * An escape key could be the start of a vt100 control sequence such as \e[D 1955d5314d6SJason Wessel * (left arrow) or it could be a character in its own right. The standard 1965d5314d6SJason Wessel * method for detecting the difference is to wait for 2 seconds to see if there 1975d5314d6SJason Wessel * are any other characters. kdb is complicated by the lack of a timer service 1985d5314d6SJason Wessel * (interrupts are off), by multiple input sources and by the need to sometimes 1995d5314d6SJason Wessel * return after just one key. Escape sequence processing has to be done as 2005d5314d6SJason Wessel * states in the polling loop. 2015d5314d6SJason Wessel */ 2025d5314d6SJason Wessel 2035d5314d6SJason Wessel static char *kdb_read(char *buffer, size_t bufsize) 2045d5314d6SJason Wessel { 2055d5314d6SJason Wessel char *cp = buffer; 2065d5314d6SJason Wessel char *bufend = buffer+bufsize-2; /* Reserve space for newline 2075d5314d6SJason Wessel * and null byte */ 2085d5314d6SJason Wessel char *lastchar; 2095d5314d6SJason Wessel char *p_tmp; 2105d5314d6SJason Wessel char tmp; 2115d5314d6SJason Wessel static char tmpbuffer[CMD_BUFLEN]; 2125d5314d6SJason Wessel int len = strlen(buffer); 2135d5314d6SJason Wessel int len_tmp; 2145d5314d6SJason Wessel int tab = 0; 2155d5314d6SJason Wessel int count; 2165d5314d6SJason Wessel int i; 2175d5314d6SJason Wessel int diag, dtab_count; 2185d5314d6SJason Wessel int key; 2195d5314d6SJason Wessel 2205d5314d6SJason Wessel 2215d5314d6SJason Wessel diag = kdbgetintenv("DTABCOUNT", &dtab_count); 2225d5314d6SJason Wessel if (diag) 2235d5314d6SJason Wessel dtab_count = 30; 2245d5314d6SJason Wessel 2255d5314d6SJason Wessel if (len > 0) { 2265d5314d6SJason Wessel cp += len; 2275d5314d6SJason Wessel if (*(buffer+len-1) == '\n') 2285d5314d6SJason Wessel cp--; 2295d5314d6SJason Wessel } 2305d5314d6SJason Wessel 2315d5314d6SJason Wessel lastchar = cp; 2325d5314d6SJason Wessel *cp = '\0'; 2335d5314d6SJason Wessel kdb_printf("%s", buffer); 2345d5314d6SJason Wessel poll_again: 2355d5314d6SJason Wessel key = kdb_read_get_key(buffer, bufsize); 2365d5314d6SJason Wessel if (key == -1) 2375d5314d6SJason Wessel return buffer; 2385d5314d6SJason Wessel if (key != 9) 2395d5314d6SJason Wessel tab = 0; 2405d5314d6SJason Wessel switch (key) { 2415d5314d6SJason Wessel case 8: /* backspace */ 2425d5314d6SJason Wessel if (cp > buffer) { 2435d5314d6SJason Wessel if (cp < lastchar) { 2445d5314d6SJason Wessel memcpy(tmpbuffer, cp, lastchar - cp); 2455d5314d6SJason Wessel memcpy(cp-1, tmpbuffer, lastchar - cp); 2465d5314d6SJason Wessel } 2475d5314d6SJason Wessel *(--lastchar) = '\0'; 2485d5314d6SJason Wessel --cp; 2495d5314d6SJason Wessel kdb_printf("\b%s \r", cp); 2505d5314d6SJason Wessel tmp = *cp; 2515d5314d6SJason Wessel *cp = '\0'; 2525d5314d6SJason Wessel kdb_printf(kdb_prompt_str); 2535d5314d6SJason Wessel kdb_printf("%s", buffer); 2545d5314d6SJason Wessel *cp = tmp; 2555d5314d6SJason Wessel } 2565d5314d6SJason Wessel break; 2575d5314d6SJason Wessel case 13: /* enter */ 2585d5314d6SJason Wessel *lastchar++ = '\n'; 2595d5314d6SJason Wessel *lastchar++ = '\0'; 26037f86b46SJason Wessel if (!KDB_STATE(KGDB_TRANS)) { 26137f86b46SJason Wessel KDB_STATE_SET(KGDB_TRANS); 26237f86b46SJason Wessel kdb_printf("%s", buffer); 26337f86b46SJason Wessel } 2645d5314d6SJason Wessel kdb_printf("\n"); 2655d5314d6SJason Wessel return buffer; 2665d5314d6SJason Wessel case 4: /* Del */ 2675d5314d6SJason Wessel if (cp < lastchar) { 2685d5314d6SJason Wessel memcpy(tmpbuffer, cp+1, lastchar - cp - 1); 2695d5314d6SJason Wessel memcpy(cp, tmpbuffer, lastchar - cp - 1); 2705d5314d6SJason Wessel *(--lastchar) = '\0'; 2715d5314d6SJason Wessel kdb_printf("%s \r", cp); 2725d5314d6SJason Wessel tmp = *cp; 2735d5314d6SJason Wessel *cp = '\0'; 2745d5314d6SJason Wessel kdb_printf(kdb_prompt_str); 2755d5314d6SJason Wessel kdb_printf("%s", buffer); 2765d5314d6SJason Wessel *cp = tmp; 2775d5314d6SJason Wessel } 2785d5314d6SJason Wessel break; 2795d5314d6SJason Wessel case 1: /* Home */ 2805d5314d6SJason Wessel if (cp > buffer) { 2815d5314d6SJason Wessel kdb_printf("\r"); 2825d5314d6SJason Wessel kdb_printf(kdb_prompt_str); 2835d5314d6SJason Wessel cp = buffer; 2845d5314d6SJason Wessel } 2855d5314d6SJason Wessel break; 2865d5314d6SJason Wessel case 5: /* End */ 2875d5314d6SJason Wessel if (cp < lastchar) { 2885d5314d6SJason Wessel kdb_printf("%s", cp); 2895d5314d6SJason Wessel cp = lastchar; 2905d5314d6SJason Wessel } 2915d5314d6SJason Wessel break; 2925d5314d6SJason Wessel case 2: /* Left */ 2935d5314d6SJason Wessel if (cp > buffer) { 2945d5314d6SJason Wessel kdb_printf("\b"); 2955d5314d6SJason Wessel --cp; 2965d5314d6SJason Wessel } 2975d5314d6SJason Wessel break; 2985d5314d6SJason Wessel case 14: /* Down */ 2995d5314d6SJason Wessel memset(tmpbuffer, ' ', 3005d5314d6SJason Wessel strlen(kdb_prompt_str) + (lastchar-buffer)); 3015d5314d6SJason Wessel *(tmpbuffer+strlen(kdb_prompt_str) + 3025d5314d6SJason Wessel (lastchar-buffer)) = '\0'; 3035d5314d6SJason Wessel kdb_printf("\r%s\r", tmpbuffer); 3045d5314d6SJason Wessel *lastchar = (char)key; 3055d5314d6SJason Wessel *(lastchar+1) = '\0'; 3065d5314d6SJason Wessel return lastchar; 3075d5314d6SJason Wessel case 6: /* Right */ 3085d5314d6SJason Wessel if (cp < lastchar) { 3095d5314d6SJason Wessel kdb_printf("%c", *cp); 3105d5314d6SJason Wessel ++cp; 3115d5314d6SJason Wessel } 3125d5314d6SJason Wessel break; 3135d5314d6SJason Wessel case 16: /* Up */ 3145d5314d6SJason Wessel memset(tmpbuffer, ' ', 3155d5314d6SJason Wessel strlen(kdb_prompt_str) + (lastchar-buffer)); 3165d5314d6SJason Wessel *(tmpbuffer+strlen(kdb_prompt_str) + 3175d5314d6SJason Wessel (lastchar-buffer)) = '\0'; 3185d5314d6SJason Wessel kdb_printf("\r%s\r", tmpbuffer); 3195d5314d6SJason Wessel *lastchar = (char)key; 3205d5314d6SJason Wessel *(lastchar+1) = '\0'; 3215d5314d6SJason Wessel return lastchar; 3225d5314d6SJason Wessel case 9: /* Tab */ 3235d5314d6SJason Wessel if (tab < 2) 3245d5314d6SJason Wessel ++tab; 3255d5314d6SJason Wessel p_tmp = buffer; 3265d5314d6SJason Wessel while (*p_tmp == ' ') 3275d5314d6SJason Wessel p_tmp++; 3285d5314d6SJason Wessel if (p_tmp > cp) 3295d5314d6SJason Wessel break; 3305d5314d6SJason Wessel memcpy(tmpbuffer, p_tmp, cp-p_tmp); 3315d5314d6SJason Wessel *(tmpbuffer + (cp-p_tmp)) = '\0'; 3325d5314d6SJason Wessel p_tmp = strrchr(tmpbuffer, ' '); 3335d5314d6SJason Wessel if (p_tmp) 3345d5314d6SJason Wessel ++p_tmp; 3355d5314d6SJason Wessel else 3365d5314d6SJason Wessel p_tmp = tmpbuffer; 3375d5314d6SJason Wessel len = strlen(p_tmp); 3385d5314d6SJason Wessel count = kallsyms_symbol_complete(p_tmp, 3395d5314d6SJason Wessel sizeof(tmpbuffer) - 3405d5314d6SJason Wessel (p_tmp - tmpbuffer)); 3415d5314d6SJason Wessel if (tab == 2 && count > 0) { 3425d5314d6SJason Wessel kdb_printf("\n%d symbols are found.", count); 3435d5314d6SJason Wessel if (count > dtab_count) { 3445d5314d6SJason Wessel count = dtab_count; 3455d5314d6SJason Wessel kdb_printf(" But only first %d symbols will" 3465d5314d6SJason Wessel " be printed.\nYou can change the" 3475d5314d6SJason Wessel " environment variable DTABCOUNT.", 3485d5314d6SJason Wessel count); 3495d5314d6SJason Wessel } 3505d5314d6SJason Wessel kdb_printf("\n"); 3515d5314d6SJason Wessel for (i = 0; i < count; i++) { 3525d5314d6SJason Wessel if (kallsyms_symbol_next(p_tmp, i) < 0) 3535d5314d6SJason Wessel break; 3545d5314d6SJason Wessel kdb_printf("%s ", p_tmp); 3555d5314d6SJason Wessel *(p_tmp + len) = '\0'; 3565d5314d6SJason Wessel } 3575d5314d6SJason Wessel if (i >= dtab_count) 3585d5314d6SJason Wessel kdb_printf("..."); 3595d5314d6SJason Wessel kdb_printf("\n"); 3605d5314d6SJason Wessel kdb_printf(kdb_prompt_str); 3615d5314d6SJason Wessel kdb_printf("%s", buffer); 3625d5314d6SJason Wessel } else if (tab != 2 && count > 0) { 3635d5314d6SJason Wessel len_tmp = strlen(p_tmp); 3645d5314d6SJason Wessel strncpy(p_tmp+len_tmp, cp, lastchar-cp+1); 3655d5314d6SJason Wessel len_tmp = strlen(p_tmp); 3665d5314d6SJason Wessel strncpy(cp, p_tmp+len, len_tmp-len + 1); 3675d5314d6SJason Wessel len = len_tmp - len; 3685d5314d6SJason Wessel kdb_printf("%s", cp); 3695d5314d6SJason Wessel cp += len; 3705d5314d6SJason Wessel lastchar += len; 3715d5314d6SJason Wessel } 3725d5314d6SJason Wessel kdb_nextline = 1; /* reset output line number */ 3735d5314d6SJason Wessel break; 3745d5314d6SJason Wessel default: 3755d5314d6SJason Wessel if (key >= 32 && lastchar < bufend) { 3765d5314d6SJason Wessel if (cp < lastchar) { 3775d5314d6SJason Wessel memcpy(tmpbuffer, cp, lastchar - cp); 3785d5314d6SJason Wessel memcpy(cp+1, tmpbuffer, lastchar - cp); 3795d5314d6SJason Wessel *++lastchar = '\0'; 3805d5314d6SJason Wessel *cp = key; 3815d5314d6SJason Wessel kdb_printf("%s\r", cp); 3825d5314d6SJason Wessel ++cp; 3835d5314d6SJason Wessel tmp = *cp; 3845d5314d6SJason Wessel *cp = '\0'; 3855d5314d6SJason Wessel kdb_printf(kdb_prompt_str); 3865d5314d6SJason Wessel kdb_printf("%s", buffer); 3875d5314d6SJason Wessel *cp = tmp; 3885d5314d6SJason Wessel } else { 3895d5314d6SJason Wessel *++lastchar = '\0'; 3905d5314d6SJason Wessel *cp++ = key; 3915d5314d6SJason Wessel /* The kgdb transition check will hide 3925d5314d6SJason Wessel * printed characters if we think that 3935d5314d6SJason Wessel * kgdb is connecting, until the check 3945d5314d6SJason Wessel * fails */ 39537f86b46SJason Wessel if (!KDB_STATE(KGDB_TRANS)) { 39637f86b46SJason Wessel if (kgdb_transition_check(buffer)) 39737f86b46SJason Wessel return buffer; 39837f86b46SJason Wessel } else { 3995d5314d6SJason Wessel kdb_printf("%c", key); 4005d5314d6SJason Wessel } 40137f86b46SJason Wessel } 4025d5314d6SJason Wessel /* Special escape to kgdb */ 4035d5314d6SJason Wessel if (lastchar - buffer >= 5 && 4045d5314d6SJason Wessel strcmp(lastchar - 5, "$?#3f") == 0) { 405f679c498SJason Wessel kdb_gdb_state_pass(lastchar - 5); 4065d5314d6SJason Wessel strcpy(buffer, "kgdb"); 4075d5314d6SJason Wessel KDB_STATE_SET(DOING_KGDB); 4085d5314d6SJason Wessel return buffer; 4095d5314d6SJason Wessel } 410f679c498SJason Wessel if (lastchar - buffer >= 11 && 411f679c498SJason Wessel strcmp(lastchar - 11, "$qSupported") == 0) { 412f679c498SJason Wessel kdb_gdb_state_pass(lastchar - 11); 4135d5314d6SJason Wessel strcpy(buffer, "kgdb"); 414d613d828SJason Wessel KDB_STATE_SET(DOING_KGDB); 4155d5314d6SJason Wessel return buffer; 4165d5314d6SJason Wessel } 4175d5314d6SJason Wessel } 4185d5314d6SJason Wessel break; 4195d5314d6SJason Wessel } 4205d5314d6SJason Wessel goto poll_again; 4215d5314d6SJason Wessel } 4225d5314d6SJason Wessel 4235d5314d6SJason Wessel /* 4245d5314d6SJason Wessel * kdb_getstr 4255d5314d6SJason Wessel * 4265d5314d6SJason Wessel * Print the prompt string and read a command from the 4275d5314d6SJason Wessel * input device. 4285d5314d6SJason Wessel * 4295d5314d6SJason Wessel * Parameters: 4305d5314d6SJason Wessel * buffer Address of buffer to receive command 4315d5314d6SJason Wessel * bufsize Size of buffer in bytes 4325d5314d6SJason Wessel * prompt Pointer to string to use as prompt string 4335d5314d6SJason Wessel * Returns: 4345d5314d6SJason Wessel * Pointer to command buffer. 4355d5314d6SJason Wessel * Locking: 4365d5314d6SJason Wessel * None. 4375d5314d6SJason Wessel * Remarks: 4385d5314d6SJason Wessel * For SMP kernels, the processor number will be 4395d5314d6SJason Wessel * substituted for %d, %x or %o in the prompt. 4405d5314d6SJason Wessel */ 4415d5314d6SJason Wessel 4425d5314d6SJason Wessel char *kdb_getstr(char *buffer, size_t bufsize, char *prompt) 4435d5314d6SJason Wessel { 4445d5314d6SJason Wessel if (prompt && kdb_prompt_str != prompt) 4455d5314d6SJason Wessel strncpy(kdb_prompt_str, prompt, CMD_BUFLEN); 4465d5314d6SJason Wessel kdb_printf(kdb_prompt_str); 4475d5314d6SJason Wessel kdb_nextline = 1; /* Prompt and input resets line number */ 4485d5314d6SJason Wessel return kdb_read(buffer, bufsize); 4495d5314d6SJason Wessel } 4505d5314d6SJason Wessel 4515d5314d6SJason Wessel /* 4525d5314d6SJason Wessel * kdb_input_flush 4535d5314d6SJason Wessel * 4545d5314d6SJason Wessel * Get rid of any buffered console input. 4555d5314d6SJason Wessel * 4565d5314d6SJason Wessel * Parameters: 4575d5314d6SJason Wessel * none 4585d5314d6SJason Wessel * Returns: 4595d5314d6SJason Wessel * nothing 4605d5314d6SJason Wessel * Locking: 4615d5314d6SJason Wessel * none 4625d5314d6SJason Wessel * Remarks: 4635d5314d6SJason Wessel * Call this function whenever you want to flush input. If there is any 4645d5314d6SJason Wessel * outstanding input, it ignores all characters until there has been no 4655d5314d6SJason Wessel * data for approximately 1ms. 4665d5314d6SJason Wessel */ 4675d5314d6SJason Wessel 4685d5314d6SJason Wessel static void kdb_input_flush(void) 4695d5314d6SJason Wessel { 4705d5314d6SJason Wessel get_char_func *f; 4715d5314d6SJason Wessel int res; 4725d5314d6SJason Wessel int flush_delay = 1; 4735d5314d6SJason Wessel while (flush_delay) { 4745d5314d6SJason Wessel flush_delay--; 4755d5314d6SJason Wessel empty: 4765d5314d6SJason Wessel touch_nmi_watchdog(); 4775d5314d6SJason Wessel for (f = &kdb_poll_funcs[0]; *f; ++f) { 4785d5314d6SJason Wessel res = (*f)(); 4795d5314d6SJason Wessel if (res != -1) { 4805d5314d6SJason Wessel flush_delay = 1; 4815d5314d6SJason Wessel goto empty; 4825d5314d6SJason Wessel } 4835d5314d6SJason Wessel } 4845d5314d6SJason Wessel if (flush_delay) 4855d5314d6SJason Wessel mdelay(1); 4865d5314d6SJason Wessel } 4875d5314d6SJason Wessel } 4885d5314d6SJason Wessel 4895d5314d6SJason Wessel /* 4905d5314d6SJason Wessel * kdb_printf 4915d5314d6SJason Wessel * 4925d5314d6SJason Wessel * Print a string to the output device(s). 4935d5314d6SJason Wessel * 4945d5314d6SJason Wessel * Parameters: 4955d5314d6SJason Wessel * printf-like format and optional args. 4965d5314d6SJason Wessel * Returns: 4975d5314d6SJason Wessel * 0 4985d5314d6SJason Wessel * Locking: 4995d5314d6SJason Wessel * None. 5005d5314d6SJason Wessel * Remarks: 5015d5314d6SJason Wessel * use 'kdbcons->write()' to avoid polluting 'log_buf' with 5025d5314d6SJason Wessel * kdb output. 5035d5314d6SJason Wessel * 5045d5314d6SJason Wessel * If the user is doing a cmd args | grep srch 5055d5314d6SJason Wessel * then kdb_grepping_flag is set. 5065d5314d6SJason Wessel * In that case we need to accumulate full lines (ending in \n) before 5075d5314d6SJason Wessel * searching for the pattern. 5085d5314d6SJason Wessel */ 5095d5314d6SJason Wessel 5105d5314d6SJason Wessel static char kdb_buffer[256]; /* A bit too big to go on stack */ 5115d5314d6SJason Wessel static char *next_avail = kdb_buffer; 5125d5314d6SJason Wessel static int size_avail; 5135d5314d6SJason Wessel static int suspend_grep; 5145d5314d6SJason Wessel 5155d5314d6SJason Wessel /* 5165d5314d6SJason Wessel * search arg1 to see if it contains arg2 5175d5314d6SJason Wessel * (kdmain.c provides flags for ^pat and pat$) 5185d5314d6SJason Wessel * 5195d5314d6SJason Wessel * return 1 for found, 0 for not found 5205d5314d6SJason Wessel */ 5215d5314d6SJason Wessel static int kdb_search_string(char *searched, char *searchfor) 5225d5314d6SJason Wessel { 5235d5314d6SJason Wessel char firstchar, *cp; 5245d5314d6SJason Wessel int len1, len2; 5255d5314d6SJason Wessel 5265d5314d6SJason Wessel /* not counting the newline at the end of "searched" */ 5275d5314d6SJason Wessel len1 = strlen(searched)-1; 5285d5314d6SJason Wessel len2 = strlen(searchfor); 5295d5314d6SJason Wessel if (len1 < len2) 5305d5314d6SJason Wessel return 0; 5315d5314d6SJason Wessel if (kdb_grep_leading && kdb_grep_trailing && len1 != len2) 5325d5314d6SJason Wessel return 0; 5335d5314d6SJason Wessel if (kdb_grep_leading) { 5345d5314d6SJason Wessel if (!strncmp(searched, searchfor, len2)) 5355d5314d6SJason Wessel return 1; 5365d5314d6SJason Wessel } else if (kdb_grep_trailing) { 5375d5314d6SJason Wessel if (!strncmp(searched+len1-len2, searchfor, len2)) 5385d5314d6SJason Wessel return 1; 5395d5314d6SJason Wessel } else { 5405d5314d6SJason Wessel firstchar = *searchfor; 5415d5314d6SJason Wessel cp = searched; 5425d5314d6SJason Wessel while ((cp = strchr(cp, firstchar))) { 5435d5314d6SJason Wessel if (!strncmp(cp, searchfor, len2)) 5445d5314d6SJason Wessel return 1; 5455d5314d6SJason Wessel cp++; 5465d5314d6SJason Wessel } 5475d5314d6SJason Wessel } 5485d5314d6SJason Wessel return 0; 5495d5314d6SJason Wessel } 5505d5314d6SJason Wessel 551d37d39aeSJason Wessel int vkdb_printf(const char *fmt, va_list ap) 5525d5314d6SJason Wessel { 5535d5314d6SJason Wessel int diag; 5545d5314d6SJason Wessel int linecount; 55517b572e8SJason Wessel int colcount; 5565d5314d6SJason Wessel int logging, saved_loglevel = 0; 557d37d39aeSJason Wessel int saved_trap_printk; 5585d5314d6SJason Wessel int got_printf_lock = 0; 5595d5314d6SJason Wessel int retlen = 0; 5605d5314d6SJason Wessel int fnd, len; 5615d5314d6SJason Wessel char *cp, *cp2, *cphold = NULL, replaced_byte = ' '; 5625d5314d6SJason Wessel char *moreprompt = "more> "; 5635d5314d6SJason Wessel struct console *c = console_drivers; 5645d5314d6SJason Wessel static DEFINE_SPINLOCK(kdb_printf_lock); 5655d5314d6SJason Wessel unsigned long uninitialized_var(flags); 5665d5314d6SJason Wessel 5675d5314d6SJason Wessel preempt_disable(); 568d37d39aeSJason Wessel saved_trap_printk = kdb_trap_printk; 569d37d39aeSJason Wessel kdb_trap_printk = 0; 570d37d39aeSJason Wessel 5715d5314d6SJason Wessel /* Serialize kdb_printf if multiple cpus try to write at once. 5725d5314d6SJason Wessel * But if any cpu goes recursive in kdb, just print the output, 5735d5314d6SJason Wessel * even if it is interleaved with any other text. 5745d5314d6SJason Wessel */ 5755d5314d6SJason Wessel if (!KDB_STATE(PRINTF_LOCK)) { 5765d5314d6SJason Wessel KDB_STATE_SET(PRINTF_LOCK); 5775d5314d6SJason Wessel spin_lock_irqsave(&kdb_printf_lock, flags); 5785d5314d6SJason Wessel got_printf_lock = 1; 5795d5314d6SJason Wessel atomic_inc(&kdb_event); 5805d5314d6SJason Wessel } else { 5815d5314d6SJason Wessel __acquire(kdb_printf_lock); 5825d5314d6SJason Wessel } 5835d5314d6SJason Wessel 5845d5314d6SJason Wessel diag = kdbgetintenv("LINES", &linecount); 5855d5314d6SJason Wessel if (diag || linecount <= 1) 5865d5314d6SJason Wessel linecount = 24; 5875d5314d6SJason Wessel 58817b572e8SJason Wessel diag = kdbgetintenv("COLUMNS", &colcount); 58917b572e8SJason Wessel if (diag || colcount <= 1) 59017b572e8SJason Wessel colcount = 80; 59117b572e8SJason Wessel 5925d5314d6SJason Wessel diag = kdbgetintenv("LOGGING", &logging); 5935d5314d6SJason Wessel if (diag) 5945d5314d6SJason Wessel logging = 0; 5955d5314d6SJason Wessel 5965d5314d6SJason Wessel if (!kdb_grepping_flag || suspend_grep) { 5975d5314d6SJason Wessel /* normally, every vsnprintf starts a new buffer */ 5985d5314d6SJason Wessel next_avail = kdb_buffer; 5995d5314d6SJason Wessel size_avail = sizeof(kdb_buffer); 6005d5314d6SJason Wessel } 6015d5314d6SJason Wessel vsnprintf(next_avail, size_avail, fmt, ap); 6025d5314d6SJason Wessel 6035d5314d6SJason Wessel /* 6045d5314d6SJason Wessel * If kdb_parse() found that the command was cmd xxx | grep yyy 6055d5314d6SJason Wessel * then kdb_grepping_flag is set, and kdb_grep_string contains yyy 6065d5314d6SJason Wessel * 6075d5314d6SJason Wessel * Accumulate the print data up to a newline before searching it. 6085d5314d6SJason Wessel * (vsnprintf does null-terminate the string that it generates) 6095d5314d6SJason Wessel */ 6105d5314d6SJason Wessel 6115d5314d6SJason Wessel /* skip the search if prints are temporarily unconditional */ 6125d5314d6SJason Wessel if (!suspend_grep && kdb_grepping_flag) { 6135d5314d6SJason Wessel cp = strchr(kdb_buffer, '\n'); 6145d5314d6SJason Wessel if (!cp) { 6155d5314d6SJason Wessel /* 6165d5314d6SJason Wessel * Special cases that don't end with newlines 6175d5314d6SJason Wessel * but should be written without one: 6185d5314d6SJason Wessel * The "[nn]kdb> " prompt should 6195d5314d6SJason Wessel * appear at the front of the buffer. 6205d5314d6SJason Wessel * 6215d5314d6SJason Wessel * The "[nn]more " prompt should also be 6225d5314d6SJason Wessel * (MOREPROMPT -> moreprompt) 6235d5314d6SJason Wessel * written * but we print that ourselves, 6245d5314d6SJason Wessel * we set the suspend_grep flag to make 6255d5314d6SJason Wessel * it unconditional. 6265d5314d6SJason Wessel * 6275d5314d6SJason Wessel */ 6285d5314d6SJason Wessel if (next_avail == kdb_buffer) { 6295d5314d6SJason Wessel /* 6305d5314d6SJason Wessel * these should occur after a newline, 6315d5314d6SJason Wessel * so they will be at the front of the 6325d5314d6SJason Wessel * buffer 6335d5314d6SJason Wessel */ 6345d5314d6SJason Wessel cp2 = kdb_buffer; 6355d5314d6SJason Wessel len = strlen(kdb_prompt_str); 6365d5314d6SJason Wessel if (!strncmp(cp2, kdb_prompt_str, len)) { 6375d5314d6SJason Wessel /* 6385d5314d6SJason Wessel * We're about to start a new 6395d5314d6SJason Wessel * command, so we can go back 6405d5314d6SJason Wessel * to normal mode. 6415d5314d6SJason Wessel */ 6425d5314d6SJason Wessel kdb_grepping_flag = 0; 6435d5314d6SJason Wessel goto kdb_printit; 6445d5314d6SJason Wessel } 6455d5314d6SJason Wessel } 6465d5314d6SJason Wessel /* no newline; don't search/write the buffer 6475d5314d6SJason Wessel until one is there */ 6485d5314d6SJason Wessel len = strlen(kdb_buffer); 6495d5314d6SJason Wessel next_avail = kdb_buffer + len; 6505d5314d6SJason Wessel size_avail = sizeof(kdb_buffer) - len; 6515d5314d6SJason Wessel goto kdb_print_out; 6525d5314d6SJason Wessel } 6535d5314d6SJason Wessel 6545d5314d6SJason Wessel /* 6555d5314d6SJason Wessel * The newline is present; print through it or discard 6565d5314d6SJason Wessel * it, depending on the results of the search. 6575d5314d6SJason Wessel */ 6585d5314d6SJason Wessel cp++; /* to byte after the newline */ 6595d5314d6SJason Wessel replaced_byte = *cp; /* remember what/where it was */ 6605d5314d6SJason Wessel cphold = cp; 6615d5314d6SJason Wessel *cp = '\0'; /* end the string for our search */ 6625d5314d6SJason Wessel 6635d5314d6SJason Wessel /* 6645d5314d6SJason Wessel * We now have a newline at the end of the string 6655d5314d6SJason Wessel * Only continue with this output if it contains the 6665d5314d6SJason Wessel * search string. 6675d5314d6SJason Wessel */ 6685d5314d6SJason Wessel fnd = kdb_search_string(kdb_buffer, kdb_grep_string); 6695d5314d6SJason Wessel if (!fnd) { 6705d5314d6SJason Wessel /* 6715d5314d6SJason Wessel * At this point the complete line at the start 6725d5314d6SJason Wessel * of kdb_buffer can be discarded, as it does 6735d5314d6SJason Wessel * not contain what the user is looking for. 6745d5314d6SJason Wessel * Shift the buffer left. 6755d5314d6SJason Wessel */ 6765d5314d6SJason Wessel *cphold = replaced_byte; 6775d5314d6SJason Wessel strcpy(kdb_buffer, cphold); 6785d5314d6SJason Wessel len = strlen(kdb_buffer); 6795d5314d6SJason Wessel next_avail = kdb_buffer + len; 6805d5314d6SJason Wessel size_avail = sizeof(kdb_buffer) - len; 6815d5314d6SJason Wessel goto kdb_print_out; 6825d5314d6SJason Wessel } 6835d5314d6SJason Wessel /* 6845d5314d6SJason Wessel * at this point the string is a full line and 6855d5314d6SJason Wessel * should be printed, up to the null. 6865d5314d6SJason Wessel */ 6875d5314d6SJason Wessel } 6885d5314d6SJason Wessel kdb_printit: 6895d5314d6SJason Wessel 6905d5314d6SJason Wessel /* 6915d5314d6SJason Wessel * Write to all consoles. 6925d5314d6SJason Wessel */ 6935d5314d6SJason Wessel retlen = strlen(kdb_buffer); 694a0de055cSJason Wessel if (!dbg_kdb_mode && kgdb_connected) { 695a0de055cSJason Wessel gdbstub_msg_write(kdb_buffer, retlen); 696a0de055cSJason Wessel } else { 697b8adde8dSTim Bird if (dbg_io_ops && !dbg_io_ops->is_console) { 69817b572e8SJason Wessel len = retlen; 699efe2f29eSJason Wessel cp = kdb_buffer; 700efe2f29eSJason Wessel while (len--) { 701efe2f29eSJason Wessel dbg_io_ops->write_char(*cp); 702efe2f29eSJason Wessel cp++; 703efe2f29eSJason Wessel } 704efe2f29eSJason Wessel } 7055d5314d6SJason Wessel while (c) { 7065d5314d6SJason Wessel c->write(c, kdb_buffer, retlen); 7075d5314d6SJason Wessel touch_nmi_watchdog(); 7085d5314d6SJason Wessel c = c->next; 7095d5314d6SJason Wessel } 710a0de055cSJason Wessel } 7115d5314d6SJason Wessel if (logging) { 7125d5314d6SJason Wessel saved_loglevel = console_loglevel; 713*a8fe19ebSBorislav Petkov console_loglevel = CONSOLE_LOGLEVEL_SILENT; 7145d5314d6SJason Wessel printk(KERN_INFO "%s", kdb_buffer); 7155d5314d6SJason Wessel } 7165d5314d6SJason Wessel 71717b572e8SJason Wessel if (KDB_STATE(PAGER)) { 71817b572e8SJason Wessel /* 71917b572e8SJason Wessel * Check printed string to decide how to bump the 72017b572e8SJason Wessel * kdb_nextline to control when the more prompt should 72117b572e8SJason Wessel * show up. 72217b572e8SJason Wessel */ 72317b572e8SJason Wessel int got = 0; 72417b572e8SJason Wessel len = retlen; 72517b572e8SJason Wessel while (len--) { 72617b572e8SJason Wessel if (kdb_buffer[len] == '\n') { 7275d5314d6SJason Wessel kdb_nextline++; 72817b572e8SJason Wessel got = 0; 72917b572e8SJason Wessel } else if (kdb_buffer[len] == '\r') { 73017b572e8SJason Wessel got = 0; 73117b572e8SJason Wessel } else { 73217b572e8SJason Wessel got++; 73317b572e8SJason Wessel } 73417b572e8SJason Wessel } 73517b572e8SJason Wessel kdb_nextline += got / (colcount + 1); 73617b572e8SJason Wessel } 7375d5314d6SJason Wessel 7385d5314d6SJason Wessel /* check for having reached the LINES number of printed lines */ 73917b572e8SJason Wessel if (kdb_nextline >= linecount) { 7405d5314d6SJason Wessel char buf1[16] = ""; 7415d5314d6SJason Wessel 7425d5314d6SJason Wessel /* Watch out for recursion here. Any routine that calls 7435d5314d6SJason Wessel * kdb_printf will come back through here. And kdb_read 7445d5314d6SJason Wessel * uses kdb_printf to echo on serial consoles ... 7455d5314d6SJason Wessel */ 7465d5314d6SJason Wessel kdb_nextline = 1; /* In case of recursion */ 7475d5314d6SJason Wessel 7485d5314d6SJason Wessel /* 7495d5314d6SJason Wessel * Pause until cr. 7505d5314d6SJason Wessel */ 7515d5314d6SJason Wessel moreprompt = kdbgetenv("MOREPROMPT"); 7525d5314d6SJason Wessel if (moreprompt == NULL) 7535d5314d6SJason Wessel moreprompt = "more> "; 7545d5314d6SJason Wessel 7555d5314d6SJason Wessel kdb_input_flush(); 7565d5314d6SJason Wessel c = console_drivers; 7575d5314d6SJason Wessel 75878724b8eSJason Wessel if (dbg_io_ops && !dbg_io_ops->is_console) { 759efe2f29eSJason Wessel len = strlen(moreprompt); 760efe2f29eSJason Wessel cp = moreprompt; 761efe2f29eSJason Wessel while (len--) { 762efe2f29eSJason Wessel dbg_io_ops->write_char(*cp); 763efe2f29eSJason Wessel cp++; 764efe2f29eSJason Wessel } 765efe2f29eSJason Wessel } 7665d5314d6SJason Wessel while (c) { 7675d5314d6SJason Wessel c->write(c, moreprompt, strlen(moreprompt)); 7685d5314d6SJason Wessel touch_nmi_watchdog(); 7695d5314d6SJason Wessel c = c->next; 7705d5314d6SJason Wessel } 7715d5314d6SJason Wessel 7725d5314d6SJason Wessel if (logging) 7735d5314d6SJason Wessel printk("%s", moreprompt); 7745d5314d6SJason Wessel 7755d5314d6SJason Wessel kdb_read(buf1, 2); /* '2' indicates to return 7765d5314d6SJason Wessel * immediately after getting one key. */ 7775d5314d6SJason Wessel kdb_nextline = 1; /* Really set output line 1 */ 7785d5314d6SJason Wessel 7795d5314d6SJason Wessel /* empty and reset the buffer: */ 7805d5314d6SJason Wessel kdb_buffer[0] = '\0'; 7815d5314d6SJason Wessel next_avail = kdb_buffer; 7825d5314d6SJason Wessel size_avail = sizeof(kdb_buffer); 7835d5314d6SJason Wessel if ((buf1[0] == 'q') || (buf1[0] == 'Q')) { 7845d5314d6SJason Wessel /* user hit q or Q */ 7855d5314d6SJason Wessel KDB_FLAG_SET(CMD_INTERRUPT); /* command interrupted */ 7865d5314d6SJason Wessel KDB_STATE_CLEAR(PAGER); 7875d5314d6SJason Wessel /* end of command output; back to normal mode */ 7885d5314d6SJason Wessel kdb_grepping_flag = 0; 7895d5314d6SJason Wessel kdb_printf("\n"); 7905d5314d6SJason Wessel } else if (buf1[0] == ' ') { 79117b572e8SJason Wessel kdb_printf("\r"); 7925d5314d6SJason Wessel suspend_grep = 1; /* for this recursion */ 7935d5314d6SJason Wessel } else if (buf1[0] == '\n') { 7945d5314d6SJason Wessel kdb_nextline = linecount - 1; 7955d5314d6SJason Wessel kdb_printf("\r"); 7965d5314d6SJason Wessel suspend_grep = 1; /* for this recursion */ 7975d5314d6SJason Wessel } else if (buf1[0] && buf1[0] != '\n') { 7985d5314d6SJason Wessel /* user hit something other than enter */ 7995d5314d6SJason Wessel suspend_grep = 1; /* for this recursion */ 8005d5314d6SJason Wessel kdb_printf("\nOnly 'q' or 'Q' are processed at more " 8015d5314d6SJason Wessel "prompt, input ignored\n"); 8025d5314d6SJason Wessel } else if (kdb_grepping_flag) { 8035d5314d6SJason Wessel /* user hit enter */ 8045d5314d6SJason Wessel suspend_grep = 1; /* for this recursion */ 8055d5314d6SJason Wessel kdb_printf("\n"); 8065d5314d6SJason Wessel } 8075d5314d6SJason Wessel kdb_input_flush(); 8085d5314d6SJason Wessel } 8095d5314d6SJason Wessel 8105d5314d6SJason Wessel /* 8115d5314d6SJason Wessel * For grep searches, shift the printed string left. 8125d5314d6SJason Wessel * replaced_byte contains the character that was overwritten with 8135d5314d6SJason Wessel * the terminating null, and cphold points to the null. 8145d5314d6SJason Wessel * Then adjust the notion of available space in the buffer. 8155d5314d6SJason Wessel */ 8165d5314d6SJason Wessel if (kdb_grepping_flag && !suspend_grep) { 8175d5314d6SJason Wessel *cphold = replaced_byte; 8185d5314d6SJason Wessel strcpy(kdb_buffer, cphold); 8195d5314d6SJason Wessel len = strlen(kdb_buffer); 8205d5314d6SJason Wessel next_avail = kdb_buffer + len; 8215d5314d6SJason Wessel size_avail = sizeof(kdb_buffer) - len; 8225d5314d6SJason Wessel } 8235d5314d6SJason Wessel 8245d5314d6SJason Wessel kdb_print_out: 8255d5314d6SJason Wessel suspend_grep = 0; /* end of what may have been a recursive call */ 8265d5314d6SJason Wessel if (logging) 8275d5314d6SJason Wessel console_loglevel = saved_loglevel; 8285d5314d6SJason Wessel if (KDB_STATE(PRINTF_LOCK) && got_printf_lock) { 8295d5314d6SJason Wessel got_printf_lock = 0; 8305d5314d6SJason Wessel spin_unlock_irqrestore(&kdb_printf_lock, flags); 8315d5314d6SJason Wessel KDB_STATE_CLEAR(PRINTF_LOCK); 8325d5314d6SJason Wessel atomic_dec(&kdb_event); 8335d5314d6SJason Wessel } else { 8345d5314d6SJason Wessel __release(kdb_printf_lock); 8355d5314d6SJason Wessel } 836d37d39aeSJason Wessel kdb_trap_printk = saved_trap_printk; 8375d5314d6SJason Wessel preempt_enable(); 8385d5314d6SJason Wessel return retlen; 8395d5314d6SJason Wessel } 840d37d39aeSJason Wessel 841d37d39aeSJason Wessel int kdb_printf(const char *fmt, ...) 842d37d39aeSJason Wessel { 843d37d39aeSJason Wessel va_list ap; 844d37d39aeSJason Wessel int r; 845d37d39aeSJason Wessel 846d37d39aeSJason Wessel va_start(ap, fmt); 847d37d39aeSJason Wessel r = vkdb_printf(fmt, ap); 848d37d39aeSJason Wessel va_end(ap); 849d37d39aeSJason Wessel 850d37d39aeSJason Wessel return r; 851d37d39aeSJason Wessel } 852f7030bbcSJason Wessel EXPORT_SYMBOL_GPL(kdb_printf); 853