Commit 4fe1da4ebc18c4c42fa56c228447f68033fce5f0

Authored by Jason Wessel
1 parent 61eaf539b9

echi-dbgp: Add kernel debugger support for the usb debug port

This patch adds the capability to use the usb debug port with the
kernel debugger.  It is also still possible to use this functionality
with or without the earlyprintk=dbgpX.  It is possible to use the
kgdbwait boot argument to debug very early in the kernel start up code.

There are two ways to use this driver extension with a kernel boot argument.

1) kgdbdbgp=#   -- Where # is the number of the usb debug controller

   You must use sysrq-g to break into the kernel debugger on another
   connection type other than the dbgp.

2) kgdbdbgp=#debugControlNum#,#Seconds#

   In this mode, the usb debug port is polled every #Seconds# for
   character input.  It is possible to use gdb or press control-c to
   break into the kernel debugger.

From the implementation perspective there are 3 high level changes.

1) Allow variable retries for the the hardware via dbgp_bulk_read().

   The amount of retries for the dbgp_bulk_read() needed to be
   variable instead of fixed.  We do not want to poll at all when the
   kernel is operating in interrupt driven mode.  The polling only
   occurs if the kernel was booted when specifying some number of
   seconds via the kgdbdbgp boot argument (IE kgdbdbgp=0,1).  In this
   case the loop count is reduced to 1 so as introduce the smallest
   amount of latency as possible.

2) Save the bulk IN endpoint address for use by the kgdb code.

3) The addition of the kgdb interface code.

   This consisted of adding in a character read function for the dbgp
   as well as a polling thread to allow the dbgp to interrupt the
   kernel execution.  The rest is the typical kgdb I/O api.

CC: Eric Biederman <ebiederm@xmission.com>
CC: Yinghai Lu <yhlu.kernel@gmail.com>
CC: linux-usb@vger.kernel.org
Signed-off-by: Jason Wessel <jason.wessel@windriver.com>
Acked-by: Greg Kroah-Hartman <gregkh@suse.de>

Showing 2 changed files with 122 additions and 9 deletions Side-by-side Diff

Documentation/kernel-parameters.txt
... ... @@ -1127,6 +1127,17 @@
1127 1127 use the HighMem zone if it exists, and the Normal
1128 1128 zone if it does not.
1129 1129  
  1130 + kgdbdbgp= [KGDB,HW] kgdb over EHCI usb debug port.
  1131 + Format: <Controller#>[,poll interval]
  1132 + The controller # is the number of the ehci usb debug
  1133 + port as it is probed via PCI. The poll interval is
  1134 + optional and is the number seconds in between
  1135 + each poll cycle to the debug port in case you need
  1136 + the functionality for interrupting the kernel with
  1137 + gdb or control-c on the dbgp connection. When
  1138 + not using this parameter you use sysrq-g to break into
  1139 + the kernel debugger.
  1140 +
1130 1141 kgdboc= [KGDB,HW] kgdb over consoles.
1131 1142 Requires a tty driver that supports console polling,
1132 1143 or a supported polling keyboard driver (non-usb).
drivers/usb/early/ehci-dbgp.c
... ... @@ -19,6 +19,9 @@
19 19 #include <linux/usb/ch9.h>
20 20 #include <linux/usb/ehci_def.h>
21 21 #include <linux/delay.h>
  22 +#include <linux/serial_core.h>
  23 +#include <linux/kgdb.h>
  24 +#include <linux/kthread.h>
22 25 #include <asm/io.h>
23 26 #include <asm/pci-direct.h>
24 27 #include <asm/fixmap.h>
... ... @@ -55,6 +58,7 @@
55 58 static struct ehci_dbg_port __iomem *ehci_debug;
56 59 static int dbgp_not_safe; /* Cannot use debug device during ehci reset */
57 60 static unsigned int dbgp_endpoint_out;
  61 +static unsigned int dbgp_endpoint_in;
58 62  
59 63 struct ehci_dev {
60 64 u32 bus;
... ... @@ -91,6 +95,13 @@
91 95 return (x & ~0x0f) | (len & 0x0f);
92 96 }
93 97  
  98 +#ifdef CONFIG_KGDB
  99 +static struct kgdb_io kgdbdbgp_io_ops;
  100 +#define dbgp_kgdb_mode (dbg_io_ops == &kgdbdbgp_io_ops)
  101 +#else
  102 +#define dbgp_kgdb_mode (0)
  103 +#endif
  104 +
94 105 /*
95 106 * USB Packet IDs (PIDs)
96 107 */
97 108  
... ... @@ -182,11 +193,10 @@
182 193 /* Sleep to give the debug port a chance to breathe */
183 194 }
184 195  
185   -static int dbgp_wait_until_done(unsigned ctrl)
  196 +static int dbgp_wait_until_done(unsigned ctrl, int loop)
186 197 {
187 198 u32 pids, lpid;
188 199 int ret;
189   - int loop = DBGP_LOOPS;
190 200  
191 201 retry:
192 202 writel(ctrl | DBGP_GO, &ehci_debug->control);
193 203  
... ... @@ -276,13 +286,13 @@
276 286 dbgp_set_data(bytes, size);
277 287 writel(addr, &ehci_debug->address);
278 288 writel(pids, &ehci_debug->pids);
279   - ret = dbgp_wait_until_done(ctrl);
  289 + ret = dbgp_wait_until_done(ctrl, DBGP_LOOPS);
280 290  
281 291 return ret;
282 292 }
283 293  
284 294 static int dbgp_bulk_read(unsigned devnum, unsigned endpoint, void *data,
285   - int size)
  295 + int size, int loops)
286 296 {
287 297 u32 pids, addr, ctrl;
288 298 int ret;
... ... @@ -302,7 +312,7 @@
302 312  
303 313 writel(addr, &ehci_debug->address);
304 314 writel(pids, &ehci_debug->pids);
305   - ret = dbgp_wait_until_done(ctrl);
  315 + ret = dbgp_wait_until_done(ctrl, loops);
306 316 if (ret < 0)
307 317 return ret;
308 318  
309 319  
... ... @@ -343,12 +353,12 @@
343 353 dbgp_set_data(&req, sizeof(req));
344 354 writel(addr, &ehci_debug->address);
345 355 writel(pids, &ehci_debug->pids);
346   - ret = dbgp_wait_until_done(ctrl);
  356 + ret = dbgp_wait_until_done(ctrl, DBGP_LOOPS);
347 357 if (ret < 0)
348 358 return ret;
349 359  
350 360 /* Read the result */
351   - return dbgp_bulk_read(devnum, 0, data, size);
  361 + return dbgp_bulk_read(devnum, 0, data, size, DBGP_LOOPS);
352 362 }
353 363  
354 364 /* Find a PCI capability */
... ... @@ -559,6 +569,7 @@
559 569 goto err;
560 570 }
561 571 dbgp_endpoint_out = dbgp_desc.bDebugOutEndpoint;
  572 + dbgp_endpoint_in = dbgp_desc.bDebugInEndpoint;
562 573  
563 574 /* Move the device to 127 if it isn't already there */
564 575 if (devnum != USB_DEBUG_DEVNUM) {
... ... @@ -968,8 +979,9 @@
968 979 if (!ehci_debug)
969 980 return 0;
970 981  
971   - if (early_dbgp_console.index != -1 &&
972   - !(early_dbgp_console.flags & CON_BOOT))
  982 + if ((early_dbgp_console.index != -1 &&
  983 + !(early_dbgp_console.flags & CON_BOOT)) ||
  984 + dbgp_kgdb_mode)
973 985 return 1;
974 986 /* This means the console is not initialized, or should get
975 987 * shutdown so as to allow for reuse of the usb device, which
... ... @@ -982,4 +994,94 @@
982 994 return 0;
983 995 }
984 996 EXPORT_SYMBOL_GPL(dbgp_reset_prep);
  997 +
  998 +#ifdef CONFIG_KGDB
  999 +
  1000 +static char kgdbdbgp_buf[DBGP_MAX_PACKET];
  1001 +static int kgdbdbgp_buf_sz;
  1002 +static int kgdbdbgp_buf_idx;
  1003 +static int kgdbdbgp_loop_cnt = DBGP_LOOPS;
  1004 +
  1005 +static int kgdbdbgp_read_char(void)
  1006 +{
  1007 + int ret;
  1008 +
  1009 + if (kgdbdbgp_buf_idx < kgdbdbgp_buf_sz) {
  1010 + char ch = kgdbdbgp_buf[kgdbdbgp_buf_idx++];
  1011 + return ch;
  1012 + }
  1013 +
  1014 + ret = dbgp_bulk_read(USB_DEBUG_DEVNUM, dbgp_endpoint_in,
  1015 + &kgdbdbgp_buf, DBGP_MAX_PACKET,
  1016 + kgdbdbgp_loop_cnt);
  1017 + if (ret <= 0)
  1018 + return NO_POLL_CHAR;
  1019 + kgdbdbgp_buf_sz = ret;
  1020 + kgdbdbgp_buf_idx = 1;
  1021 + return kgdbdbgp_buf[0];
  1022 +}
  1023 +
  1024 +static void kgdbdbgp_write_char(u8 chr)
  1025 +{
  1026 + early_dbgp_write(NULL, &chr, 1);
  1027 +}
  1028 +
  1029 +static struct kgdb_io kgdbdbgp_io_ops = {
  1030 + .name = "kgdbdbgp",
  1031 + .read_char = kgdbdbgp_read_char,
  1032 + .write_char = kgdbdbgp_write_char,
  1033 +};
  1034 +
  1035 +static int kgdbdbgp_wait_time;
  1036 +
  1037 +static int __init kgdbdbgp_parse_config(char *str)
  1038 +{
  1039 + char *ptr;
  1040 +
  1041 + if (!ehci_debug) {
  1042 + if (early_dbgp_init(str))
  1043 + return -1;
  1044 + }
  1045 + ptr = strchr(str, ',');
  1046 + if (ptr) {
  1047 + ptr++;
  1048 + kgdbdbgp_wait_time = simple_strtoul(ptr, &ptr, 10);
  1049 + }
  1050 + kgdb_register_io_module(&kgdbdbgp_io_ops);
  1051 + kgdbdbgp_io_ops.is_console = early_dbgp_console.index != -1;
  1052 +
  1053 + return 0;
  1054 +}
  1055 +early_param("kgdbdbgp", kgdbdbgp_parse_config);
  1056 +
  1057 +static int kgdbdbgp_reader_thread(void *ptr)
  1058 +{
  1059 + int ret;
  1060 +
  1061 + while (readl(&ehci_debug->control) & DBGP_ENABLED) {
  1062 + kgdbdbgp_loop_cnt = 1;
  1063 + ret = kgdbdbgp_read_char();
  1064 + kgdbdbgp_loop_cnt = DBGP_LOOPS;
  1065 + if (ret != NO_POLL_CHAR) {
  1066 + if (ret == 0x3 || ret == '$') {
  1067 + if (ret == '$')
  1068 + kgdbdbgp_buf_idx--;
  1069 + kgdb_breakpoint();
  1070 + }
  1071 + continue;
  1072 + }
  1073 + schedule_timeout_interruptible(kgdbdbgp_wait_time * HZ);
  1074 + }
  1075 + return 0;
  1076 +}
  1077 +
  1078 +static int __init kgdbdbgp_start_thread(void)
  1079 +{
  1080 + if (dbgp_kgdb_mode && kgdbdbgp_wait_time)
  1081 + kthread_run(kgdbdbgp_reader_thread, NULL, "%s", "dbgp");
  1082 +
  1083 + return 0;
  1084 +}
  1085 +module_init(kgdbdbgp_start_thread);
  1086 +#endif /* CONFIG_KGDB */