1 /*- 2 * Copyright (c) 2006 Sam Leffler 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 /* 28 * Support for redirecting console msgs to gdb. We register 29 * a pseudo console to hook cnputc and send stuff to the gdb 30 * port. The only trickiness here is buffering output so this 31 * isn't dog slow. 32 */ 33 34 #include <sys/cdefs.h> 35 __FBSDID("$FreeBSD$"); 36 37 #include <sys/param.h> 38 #include <sys/systm.h> 39 #include <sys/cons.h> 40 #include <sys/kdb.h> 41 #include <sys/kernel.h> 42 #include <sys/malloc.h> 43 #include <sys/reboot.h> 44 #include <sys/sysctl.h> 45 46 #include <machine/gdb_machdep.h> 47 #include <machine/kdb.h> 48 49 #include <gdb/gdb.h> 50 #include <gdb/gdb_int.h> 51 52 struct gdbcons { 53 int npending; 54 /* /2 for hex conversion, -6 for protocol glue */ 55 char buf[GDB_BUFSZ/2 - 6]; 56 struct callout flush; 57 }; 58 static struct gdbcons state = { -1 }; 59 60 static int gdbcons_enable = 0; 61 SYSCTL_INT(_debug, OID_AUTO, gdbcons, CTLFLAG_RW, &gdbcons_enable, 62 0, "copy console messages to gdb"); 63 TUNABLE_INT("debug.gdbcons", &gdbcons_enable); 64 65 static void 66 gdb_cnprobe(struct consdev *cp) 67 { 68 sprintf(cp->cn_name, "gdb"); 69 cp->cn_pri = CN_LOW; /* XXX no way to say "write only" */ 70 } 71 72 static void 73 gdb_cninit(struct consdev *cp) 74 { 75 struct gdbcons *c = &state; 76 77 /* setup tx buffer and callout */ 78 if (c->npending == -1) { 79 c->npending = 0; 80 callout_init(&c->flush, CALLOUT_MPSAFE); 81 cp->cn_arg = c; 82 } 83 } 84 85 static void 86 gdb_cnterm(struct consdev *cp) 87 { 88 } 89 90 static void 91 gdb_cngrab(struct consdev *cp) 92 { 93 } 94 95 static void 96 gdb_cnungrab(struct consdev *cp) 97 { 98 } 99 100 static int 101 gdb_cngetc(struct consdev *cp) 102 { 103 return -1; 104 } 105 106 static void 107 gdb_tx_puthex(int c) 108 { 109 const char *hex = "0123456789abcdef"; 110 111 gdb_tx_char(hex[(c>>4)&0xf]); 112 gdb_tx_char(hex[(c>>0)&0xf]); 113 } 114 115 static void 116 gdb_cnflush(void *arg) 117 { 118 struct gdbcons *gc = arg; 119 int i; 120 121 gdb_tx_begin('O'); 122 for (i = 0; i < gc->npending; i++) 123 gdb_tx_puthex(gc->buf[i]); 124 gdb_tx_end(); 125 gc->npending = 0; 126 } 127 128 /* 129 * This glop is to figure out when it's safe to use callouts 130 * to defer buffer flushing. There's probably a better way 131 * and/or an earlier point in the boot process when it's ok. 132 */ 133 static int calloutok = 0; 134 static void 135 oktousecallout(void *data __unused) 136 { 137 calloutok = 1; 138 } 139 SYSINIT(gdbhack, SI_SUB_LAST, SI_ORDER_MIDDLE, oktousecallout, NULL); 140 141 static void 142 gdb_cnputc(struct consdev *cp, int c) 143 { 144 struct gdbcons *gc; 145 146 if (gdbcons_enable && gdb_cur != NULL && gdb_listening) { 147 gc = cp->cn_arg; 148 if (gc->npending != 0) { 149 /* 150 * Cancel any pending callout and flush the 151 * buffer if there's no space for this byte. 152 */ 153 if (calloutok) 154 callout_stop(&gc->flush); 155 if (gc->npending == sizeof(gc->buf)) 156 gdb_cnflush(gc); 157 } 158 gc->buf[gc->npending++] = c; 159 /* 160 * Flush on end of line; this is especially helpful 161 * during boot when we don't have callouts to flush 162 * the buffer. Otherwise we defer flushing; a 1/4 163 * second is a guess. 164 */ 165 if (c == '\n') 166 gdb_cnflush(gc); 167 else if (calloutok) 168 callout_reset(&gc->flush, hz/4, gdb_cnflush, gc); 169 } 170 } 171 172 CONSOLE_DRIVER(gdb); 173 174 /* 175 * Our console device only gets attached if the system is booted 176 * with RB_MULTIPLE set so gdb_init also calls us to attach the 177 * console so we're setup regardless. 178 */ 179 void 180 gdb_consinit(void) 181 { 182 gdb_cnprobe(&gdb_consdev); 183 gdb_cninit(&gdb_consdev); 184 cnadd(&gdb_consdev); 185 } 186