diff options
Diffstat (limited to 'arch/sh/kernel')
-rw-r--r-- | arch/sh/kernel/kgdb_stub.c | 106 | ||||
-rw-r--r-- | arch/sh/kernel/setup.c | 94 |
2 files changed, 55 insertions, 145 deletions
diff --git a/arch/sh/kernel/kgdb_stub.c b/arch/sh/kernel/kgdb_stub.c index d8927d85492e..737eadc8ce0f 100644 --- a/arch/sh/kernel/kgdb_stub.c +++ b/arch/sh/kernel/kgdb_stub.c | |||
@@ -6,11 +6,11 @@ | |||
6 | * David Grothe <dave@gcom.com>, Tigran Aivazian <tigran@sco.com>, | 6 | * David Grothe <dave@gcom.com>, Tigran Aivazian <tigran@sco.com>, |
7 | * Amit S. Kale <akale@veritas.com>, William Gatliff <bgat@open-widgets.com>, | 7 | * Amit S. Kale <akale@veritas.com>, William Gatliff <bgat@open-widgets.com>, |
8 | * Ben Lee, Steve Chamberlain and Benoit Miller <fulg@iname.com>. | 8 | * Ben Lee, Steve Chamberlain and Benoit Miller <fulg@iname.com>. |
9 | * | 9 | * |
10 | * This version by Henry Bell <henry.bell@st.com> | 10 | * This version by Henry Bell <henry.bell@st.com> |
11 | * Minor modifications by Jeremy Siegel <jsiegel@mvista.com> | 11 | * Minor modifications by Jeremy Siegel <jsiegel@mvista.com> |
12 | * | 12 | * |
13 | * Contains low-level support for remote debug using GDB. | 13 | * Contains low-level support for remote debug using GDB. |
14 | * | 14 | * |
15 | * To enable debugger support, two things need to happen. A call to | 15 | * To enable debugger support, two things need to happen. A call to |
16 | * set_debug_traps() is necessary in order to allow any breakpoints | 16 | * set_debug_traps() is necessary in order to allow any breakpoints |
@@ -48,7 +48,7 @@ | |||
48 | * k kill (Detach GDB) | 48 | * k kill (Detach GDB) |
49 | * | 49 | * |
50 | * d Toggle debug flag | 50 | * d Toggle debug flag |
51 | * D Detach GDB | 51 | * D Detach GDB |
52 | * | 52 | * |
53 | * Hct Set thread t for operations, OK or ENN | 53 | * Hct Set thread t for operations, OK or ENN |
54 | * c = 'c' (step, cont), c = 'g' (other | 54 | * c = 'c' (step, cont), c = 'g' (other |
@@ -58,7 +58,7 @@ | |||
58 | * qfThreadInfo Get list of current threads (first) m<id> | 58 | * qfThreadInfo Get list of current threads (first) m<id> |
59 | * qsThreadInfo " " " " " (subsequent) | 59 | * qsThreadInfo " " " " " (subsequent) |
60 | * qOffsets Get section offsets Text=x;Data=y;Bss=z | 60 | * qOffsets Get section offsets Text=x;Data=y;Bss=z |
61 | * | 61 | * |
62 | * TXX Find if thread XX is alive OK or ENN | 62 | * TXX Find if thread XX is alive OK or ENN |
63 | * ? What was the last sigval ? SNN (signal NN) | 63 | * ? What was the last sigval ? SNN (signal NN) |
64 | * O Output to GDB console | 64 | * O Output to GDB console |
@@ -74,7 +74,7 @@ | |||
74 | * '$' or '#'. If <data> starts with two characters followed by | 74 | * '$' or '#'. If <data> starts with two characters followed by |
75 | * ':', then the existing stubs interpret this as a sequence number. | 75 | * ':', then the existing stubs interpret this as a sequence number. |
76 | * | 76 | * |
77 | * CSUM1 and CSUM2 are ascii hex representation of an 8-bit | 77 | * CSUM1 and CSUM2 are ascii hex representation of an 8-bit |
78 | * checksum of <data>, the most significant nibble is sent first. | 78 | * checksum of <data>, the most significant nibble is sent first. |
79 | * the hex digits 0-9,a-f are used. | 79 | * the hex digits 0-9,a-f are used. |
80 | * | 80 | * |
@@ -86,8 +86,8 @@ | |||
86 | * Responses can be run-length encoded to save space. A '*' means that | 86 | * Responses can be run-length encoded to save space. A '*' means that |
87 | * the next character is an ASCII encoding giving a repeat count which | 87 | * the next character is an ASCII encoding giving a repeat count which |
88 | * stands for that many repititions of the character preceding the '*'. | 88 | * stands for that many repititions of the character preceding the '*'. |
89 | * The encoding is n+29, yielding a printable character where n >=3 | 89 | * The encoding is n+29, yielding a printable character where n >=3 |
90 | * (which is where RLE starts to win). Don't use an n > 126. | 90 | * (which is where RLE starts to win). Don't use an n > 126. |
91 | * | 91 | * |
92 | * So "0* " means the same as "0000". | 92 | * So "0* " means the same as "0000". |
93 | */ | 93 | */ |
@@ -100,12 +100,10 @@ | |||
100 | #include <linux/delay.h> | 100 | #include <linux/delay.h> |
101 | #include <linux/linkage.h> | 101 | #include <linux/linkage.h> |
102 | #include <linux/init.h> | 102 | #include <linux/init.h> |
103 | |||
104 | #ifdef CONFIG_SH_KGDB_CONSOLE | ||
105 | #include <linux/console.h> | 103 | #include <linux/console.h> |
106 | #endif | 104 | #include <linux/sysrq.h> |
107 | |||
108 | #include <asm/system.h> | 105 | #include <asm/system.h> |
106 | #include <asm/cacheflush.h> | ||
109 | #include <asm/current.h> | 107 | #include <asm/current.h> |
110 | #include <asm/signal.h> | 108 | #include <asm/signal.h> |
111 | #include <asm/pgtable.h> | 109 | #include <asm/pgtable.h> |
@@ -153,7 +151,6 @@ char kgdb_in_gdb_mode; | |||
153 | char in_nmi; /* Set during NMI to prevent reentry */ | 151 | char in_nmi; /* Set during NMI to prevent reentry */ |
154 | int kgdb_nofault; /* Boolean to ignore bus errs (i.e. in GDB) */ | 152 | int kgdb_nofault; /* Boolean to ignore bus errs (i.e. in GDB) */ |
155 | int kgdb_enabled = 1; /* Default to enabled, cmdline can disable */ | 153 | int kgdb_enabled = 1; /* Default to enabled, cmdline can disable */ |
156 | int kgdb_halt; | ||
157 | 154 | ||
158 | /* Exposed for user access */ | 155 | /* Exposed for user access */ |
159 | struct task_struct *kgdb_current; | 156 | struct task_struct *kgdb_current; |
@@ -328,7 +325,7 @@ static int hex_to_int(char **ptr, int *int_value) | |||
328 | } | 325 | } |
329 | 326 | ||
330 | /* Copy the binary array pointed to by buf into mem. Fix $, #, | 327 | /* Copy the binary array pointed to by buf into mem. Fix $, #, |
331 | and 0x7d escaped with 0x7d. Return a pointer to the character | 328 | and 0x7d escaped with 0x7d. Return a pointer to the character |
332 | after the last byte written. */ | 329 | after the last byte written. */ |
333 | static char *ebin_to_mem(const char *buf, char *mem, int count) | 330 | static char *ebin_to_mem(const char *buf, char *mem, int count) |
334 | { | 331 | { |
@@ -452,7 +449,7 @@ static void get_packet(char *buffer, int buflen) | |||
452 | /* Ack successful transfer */ | 449 | /* Ack successful transfer */ |
453 | put_debug_char('+'); | 450 | put_debug_char('+'); |
454 | 451 | ||
455 | /* If a sequence char is present, reply | 452 | /* If a sequence char is present, reply |
456 | the sequence ID */ | 453 | the sequence ID */ |
457 | if (buffer[2] == ':') { | 454 | if (buffer[2] == ':') { |
458 | put_debug_char(buffer[0]); | 455 | put_debug_char(buffer[0]); |
@@ -759,7 +756,7 @@ static short *get_step_address(void) | |||
759 | return (short *) addr; | 756 | return (short *) addr; |
760 | } | 757 | } |
761 | 758 | ||
762 | /* Set up a single-step. Replace the instruction immediately after the | 759 | /* Set up a single-step. Replace the instruction immediately after the |
763 | current instruction (i.e. next in the expected flow of control) with a | 760 | current instruction (i.e. next in the expected flow of control) with a |
764 | trap instruction, so that returning will cause only a single instruction | 761 | trap instruction, so that returning will cause only a single instruction |
765 | to be executed. Note that this model is slightly broken for instructions | 762 | to be executed. Note that this model is slightly broken for instructions |
@@ -1002,10 +999,8 @@ void set_thread_msg(void) | |||
1002 | char *ptr; | 999 | char *ptr; |
1003 | 1000 | ||
1004 | switch (in_buffer[1]) { | 1001 | switch (in_buffer[1]) { |
1005 | 1002 | /* To select which thread for gG etc messages, i.e. supported */ | |
1006 | /* To select which thread for gG etc messages, i.e. supported */ | ||
1007 | case 'g': | 1003 | case 'g': |
1008 | |||
1009 | ptr = &in_buffer[2]; | 1004 | ptr = &in_buffer[2]; |
1010 | hex_to_int(&ptr, &threadid); | 1005 | hex_to_int(&ptr, &threadid); |
1011 | thread = get_thread(threadid); | 1006 | thread = get_thread(threadid); |
@@ -1173,6 +1168,7 @@ static void query_msg(void) | |||
1173 | } | 1168 | } |
1174 | #endif /* CONFIG_KGDB_THREAD */ | 1169 | #endif /* CONFIG_KGDB_THREAD */ |
1175 | 1170 | ||
1171 | #ifdef CONFIG_SH_KGDB_CONSOLE | ||
1176 | /* | 1172 | /* |
1177 | * Bring up the ports.. | 1173 | * Bring up the ports.. |
1178 | */ | 1174 | */ |
@@ -1185,6 +1181,9 @@ static int kgdb_serial_setup(void) | |||
1185 | 1181 | ||
1186 | return 0; | 1182 | return 0; |
1187 | } | 1183 | } |
1184 | #else | ||
1185 | #define kgdb_serial_setup() 0 | ||
1186 | #endif | ||
1188 | 1187 | ||
1189 | /* The command loop, read and act on requests */ | 1188 | /* The command loop, read and act on requests */ |
1190 | static void kgdb_command_loop(const int excep_code, const int trapa_value) | 1189 | static void kgdb_command_loop(const int excep_code, const int trapa_value) |
@@ -1193,7 +1192,7 @@ static void kgdb_command_loop(const int excep_code, const int trapa_value) | |||
1193 | 1192 | ||
1194 | if (excep_code == NMI_VEC) { | 1193 | if (excep_code == NMI_VEC) { |
1195 | #ifndef CONFIG_KGDB_NMI | 1194 | #ifndef CONFIG_KGDB_NMI |
1196 | KGDB_PRINTK("Ignoring unexpected NMI?\n"); | 1195 | printk(KERN_NOTICE "KGDB: Ignoring unexpected NMI?\n"); |
1197 | return; | 1196 | return; |
1198 | #else /* CONFIG_KGDB_NMI */ | 1197 | #else /* CONFIG_KGDB_NMI */ |
1199 | if (!kgdb_enabled) { | 1198 | if (!kgdb_enabled) { |
@@ -1216,10 +1215,7 @@ static void kgdb_command_loop(const int excep_code, const int trapa_value) | |||
1216 | /* Enter GDB mode (e.g. after detach) */ | 1215 | /* Enter GDB mode (e.g. after detach) */ |
1217 | if (!kgdb_in_gdb_mode) { | 1216 | if (!kgdb_in_gdb_mode) { |
1218 | /* Do serial setup, notify user, issue preemptive ack */ | 1217 | /* Do serial setup, notify user, issue preemptive ack */ |
1219 | kgdb_serial_setup(); | 1218 | printk(KERN_NOTICE "KGDB: Waiting for GDB\n"); |
1220 | KGDB_PRINTK("Waiting for GDB (on %s%d at %d baud)\n", | ||
1221 | (kgdb_porttype ? kgdb_porttype->name : ""), | ||
1222 | kgdb_portnum, kgdb_baud); | ||
1223 | kgdb_in_gdb_mode = 1; | 1219 | kgdb_in_gdb_mode = 1; |
1224 | put_debug_char('+'); | 1220 | put_debug_char('+'); |
1225 | } | 1221 | } |
@@ -1233,21 +1229,18 @@ static void kgdb_command_loop(const int excep_code, const int trapa_value) | |||
1233 | will later be replaced by its original one. Do NOT do this for | 1229 | will later be replaced by its original one. Do NOT do this for |
1234 | trap 0xff, since that indicates a compiled-in breakpoint which | 1230 | trap 0xff, since that indicates a compiled-in breakpoint which |
1235 | will not be replaced (and we would retake the trap forever) */ | 1231 | will not be replaced (and we would retake the trap forever) */ |
1236 | if ((excep_code == TRAP_VEC) && (trapa_value != (0xff << 2))) { | 1232 | if ((excep_code == TRAP_VEC) && (trapa_value != (0x3c << 2))) |
1237 | trap_registers.pc -= 2; | 1233 | trap_registers.pc -= 2; |
1238 | } | ||
1239 | 1234 | ||
1240 | /* Undo any stepping we may have done */ | 1235 | /* Undo any stepping we may have done */ |
1241 | undo_single_step(); | 1236 | undo_single_step(); |
1242 | 1237 | ||
1243 | while (1) { | 1238 | while (1) { |
1244 | |||
1245 | out_buffer[0] = 0; | 1239 | out_buffer[0] = 0; |
1246 | get_packet(in_buffer, BUFMAX); | 1240 | get_packet(in_buffer, BUFMAX); |
1247 | 1241 | ||
1248 | /* Examine first char of buffer to see what we need to do */ | 1242 | /* Examine first char of buffer to see what we need to do */ |
1249 | switch (in_buffer[0]) { | 1243 | switch (in_buffer[0]) { |
1250 | |||
1251 | case '?': /* Send which signal we've received */ | 1244 | case '?': /* Send which signal we've received */ |
1252 | send_signal_msg(sigval); | 1245 | send_signal_msg(sigval); |
1253 | break; | 1246 | break; |
@@ -1323,11 +1316,8 @@ static void kgdb_command_loop(const int excep_code, const int trapa_value) | |||
1323 | } | 1316 | } |
1324 | 1317 | ||
1325 | /* There has been an exception, most likely a breakpoint. */ | 1318 | /* There has been an exception, most likely a breakpoint. */ |
1326 | asmlinkage void kgdb_handle_exception(unsigned long r4, unsigned long r5, | 1319 | static void handle_exception(struct pt_regs *regs) |
1327 | unsigned long r6, unsigned long r7, | ||
1328 | struct pt_regs __regs) | ||
1329 | { | 1320 | { |
1330 | struct pt_regs *regs = RELOC_HIDE(&__regs, 0); | ||
1331 | int excep_code, vbr_val; | 1321 | int excep_code, vbr_val; |
1332 | int count; | 1322 | int count; |
1333 | int trapa_value = ctrl_inl(TRA); | 1323 | int trapa_value = ctrl_inl(TRA); |
@@ -1355,7 +1345,7 @@ asmlinkage void kgdb_handle_exception(unsigned long r4, unsigned long r5, | |||
1355 | kgdb_trapa_val = trapa_value; | 1345 | kgdb_trapa_val = trapa_value; |
1356 | 1346 | ||
1357 | /* Act on the exception */ | 1347 | /* Act on the exception */ |
1358 | kgdb_command_loop(excep_code >> 5, trapa_value); | 1348 | kgdb_command_loop(excep_code, trapa_value); |
1359 | 1349 | ||
1360 | kgdb_current = NULL; | 1350 | kgdb_current = NULL; |
1361 | 1351 | ||
@@ -1373,14 +1363,12 @@ asmlinkage void kgdb_handle_exception(unsigned long r4, unsigned long r5, | |||
1373 | asm("ldc %0, vbr": :"r"(vbr_val)); | 1363 | asm("ldc %0, vbr": :"r"(vbr_val)); |
1374 | } | 1364 | } |
1375 | 1365 | ||
1376 | /* Trigger a breakpoint by function */ | 1366 | asmlinkage void kgdb_handle_exception(unsigned long r4, unsigned long r5, |
1377 | void breakpoint(void) | 1367 | unsigned long r6, unsigned long r7, |
1368 | struct pt_regs __regs) | ||
1378 | { | 1369 | { |
1379 | if (!kgdb_enabled) { | 1370 | struct pt_regs *regs = RELOC_HIDE(&__regs, 0); |
1380 | kgdb_enabled = 1; | 1371 | handle_exception(regs); |
1381 | kgdb_init(); | ||
1382 | } | ||
1383 | BREAKPOINT(); | ||
1384 | } | 1372 | } |
1385 | 1373 | ||
1386 | /* Initialise the KGDB data structures and serial configuration */ | 1374 | /* Initialise the KGDB data structures and serial configuration */ |
@@ -1395,24 +1383,16 @@ int kgdb_init(void) | |||
1395 | kgdb_in_gdb_mode = 0; | 1383 | kgdb_in_gdb_mode = 0; |
1396 | 1384 | ||
1397 | if (kgdb_serial_setup() != 0) { | 1385 | if (kgdb_serial_setup() != 0) { |
1398 | KGDB_PRINTK("serial setup error\n"); | 1386 | printk(KERN_NOTICE "KGDB: serial setup error\n"); |
1399 | return -1; | 1387 | return -1; |
1400 | } | 1388 | } |
1401 | 1389 | ||
1402 | /* Init ptr to exception handler */ | 1390 | /* Init ptr to exception handler */ |
1403 | kgdb_debug_hook = kgdb_handle_exception; | 1391 | kgdb_debug_hook = handle_exception; |
1404 | kgdb_bus_err_hook = kgdb_handle_bus_error; | 1392 | kgdb_bus_err_hook = kgdb_handle_bus_error; |
1405 | 1393 | ||
1406 | /* Enter kgdb now if requested, or just report init done */ | 1394 | /* Enter kgdb now if requested, or just report init done */ |
1407 | if (kgdb_halt) { | 1395 | printk(KERN_NOTICE "KGDB: stub is initialized.\n"); |
1408 | kgdb_in_gdb_mode = 1; | ||
1409 | put_debug_char('+'); | ||
1410 | breakpoint(); | ||
1411 | } | ||
1412 | else | ||
1413 | { | ||
1414 | KGDB_PRINTK("stub is initialized.\n"); | ||
1415 | } | ||
1416 | 1396 | ||
1417 | return 0; | 1397 | return 0; |
1418 | } | 1398 | } |
@@ -1437,7 +1417,7 @@ static void kgdb_msg_write(const char *s, unsigned count) | |||
1437 | 1417 | ||
1438 | /* Calculate how many this time */ | 1418 | /* Calculate how many this time */ |
1439 | wcount = (count > MAXOUT) ? MAXOUT : count; | 1419 | wcount = (count > MAXOUT) ? MAXOUT : count; |
1440 | 1420 | ||
1441 | /* Pack in hex chars */ | 1421 | /* Pack in hex chars */ |
1442 | for (i = 0; i < wcount; i++) | 1422 | for (i = 0; i < wcount; i++) |
1443 | bufptr = pack_hex_byte(bufptr, s[i]); | 1423 | bufptr = pack_hex_byte(bufptr, s[i]); |
@@ -1467,3 +1447,25 @@ void kgdb_console_write(struct console *co, const char *s, unsigned count) | |||
1467 | kgdb_msg_write(s, count); | 1447 | kgdb_msg_write(s, count); |
1468 | } | 1448 | } |
1469 | #endif | 1449 | #endif |
1450 | |||
1451 | #ifdef CONFIG_KGDB_SYSRQ | ||
1452 | static void sysrq_handle_gdb(int key, struct tty_struct *tty) | ||
1453 | { | ||
1454 | printk("Entering GDB stub\n"); | ||
1455 | breakpoint(); | ||
1456 | } | ||
1457 | |||
1458 | static struct sysrq_key_op sysrq_gdb_op = { | ||
1459 | .handler = sysrq_handle_gdb, | ||
1460 | .help_msg = "Gdb", | ||
1461 | .action_msg = "GDB", | ||
1462 | }; | ||
1463 | |||
1464 | static int gdb_register_sysrq(void) | ||
1465 | { | ||
1466 | printk("Registering GDB sysrq handler\n"); | ||
1467 | register_sysrq_key('g', &sysrq_gdb_op); | ||
1468 | return 0; | ||
1469 | } | ||
1470 | module_init(gdb_register_sysrq); | ||
1471 | #endif | ||
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index 98802ab28211..f96490419768 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c | |||
@@ -25,11 +25,8 @@ | |||
25 | #include <asm/setup.h> | 25 | #include <asm/setup.h> |
26 | #include <asm/clock.h> | 26 | #include <asm/clock.h> |
27 | 27 | ||
28 | #ifdef CONFIG_SH_KGDB | ||
29 | #include <asm/kgdb.h> | ||
30 | static int kgdb_parse_options(char *options); | ||
31 | #endif | ||
32 | extern void * __rd_start, * __rd_end; | 28 | extern void * __rd_start, * __rd_end; |
29 | |||
33 | /* | 30 | /* |
34 | * Machine setup.. | 31 | * Machine setup.. |
35 | */ | 32 | */ |
@@ -499,92 +496,3 @@ struct seq_operations cpuinfo_op = { | |||
499 | .show = show_cpuinfo, | 496 | .show = show_cpuinfo, |
500 | }; | 497 | }; |
501 | #endif /* CONFIG_PROC_FS */ | 498 | #endif /* CONFIG_PROC_FS */ |
502 | |||
503 | #ifdef CONFIG_SH_KGDB | ||
504 | /* | ||
505 | * Parse command-line kgdb options. By default KGDB is enabled, | ||
506 | * entered on error (or other action) using default serial info. | ||
507 | * The command-line option can include a serial port specification | ||
508 | * and an action to override default or configured behavior. | ||
509 | */ | ||
510 | struct kgdb_sermap kgdb_sci_sermap = | ||
511 | { "ttySC", 5, kgdb_sci_setup, NULL }; | ||
512 | |||
513 | struct kgdb_sermap *kgdb_serlist = &kgdb_sci_sermap; | ||
514 | struct kgdb_sermap *kgdb_porttype = &kgdb_sci_sermap; | ||
515 | |||
516 | void kgdb_register_sermap(struct kgdb_sermap *map) | ||
517 | { | ||
518 | struct kgdb_sermap *last; | ||
519 | |||
520 | for (last = kgdb_serlist; last->next; last = last->next) | ||
521 | ; | ||
522 | last->next = map; | ||
523 | if (!map->namelen) { | ||
524 | map->namelen = strlen(map->name); | ||
525 | } | ||
526 | } | ||
527 | |||
528 | static int __init kgdb_parse_options(char *options) | ||
529 | { | ||
530 | char c; | ||
531 | int baud; | ||
532 | |||
533 | /* Check for port spec (or use default) */ | ||
534 | |||
535 | /* Determine port type and instance */ | ||
536 | if (!memcmp(options, "tty", 3)) { | ||
537 | struct kgdb_sermap *map = kgdb_serlist; | ||
538 | |||
539 | while (map && memcmp(options, map->name, map->namelen)) | ||
540 | map = map->next; | ||
541 | |||
542 | if (!map) { | ||
543 | KGDB_PRINTK("unknown port spec in %s\n", options); | ||
544 | return -1; | ||
545 | } | ||
546 | |||
547 | kgdb_porttype = map; | ||
548 | kgdb_serial_setup = map->setup_fn; | ||
549 | kgdb_portnum = options[map->namelen] - '0'; | ||
550 | options += map->namelen + 1; | ||
551 | |||
552 | options = (*options == ',') ? options+1 : options; | ||
553 | |||
554 | /* Read optional parameters (baud/parity/bits) */ | ||
555 | baud = simple_strtoul(options, &options, 10); | ||
556 | if (baud != 0) { | ||
557 | kgdb_baud = baud; | ||
558 | |||
559 | c = toupper(*options); | ||
560 | if (c == 'E' || c == 'O' || c == 'N') { | ||
561 | kgdb_parity = c; | ||
562 | options++; | ||
563 | } | ||
564 | |||
565 | c = *options; | ||
566 | if (c == '7' || c == '8') { | ||
567 | kgdb_bits = c; | ||
568 | options++; | ||
569 | } | ||
570 | options = (*options == ',') ? options+1 : options; | ||
571 | } | ||
572 | } | ||
573 | |||
574 | /* Check for action specification */ | ||
575 | if (!memcmp(options, "halt", 4)) { | ||
576 | kgdb_halt = 1; | ||
577 | options += 4; | ||
578 | } else if (!memcmp(options, "disabled", 8)) { | ||
579 | kgdb_enabled = 0; | ||
580 | options += 8; | ||
581 | } | ||
582 | |||
583 | if (*options) { | ||
584 | KGDB_PRINTK("ignored unknown options: %s\n", options); | ||
585 | return 0; | ||
586 | } | ||
587 | return 1; | ||
588 | } | ||
589 | __setup("kgdb=", kgdb_parse_options); | ||
590 | #endif /* CONFIG_SH_KGDB */ | ||