diff options
author | Paul Mundt <lethal@linux-sh.org> | 2007-03-08 03:27:37 -0500 |
---|---|---|
committer | Paul Mundt <lethal@hera.kernel.org> | 2007-05-06 22:10:51 -0400 |
commit | fa5da2f7bdcf885efe65a37df13907c7d72296f6 (patch) | |
tree | 54104d5f660a1ec824505b28540eb2c5e4be390a /arch | |
parent | 15700770ef7c5d12e2f1659d2ddbeb3f658d9f37 (diff) |
sh: Bring kgdb back from the dead.
This code has suffered quite a bit of bitrot, do some basic
tidying to get it to a reasonably functional state again.
This gets the basic support and the console working again.
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/sh/Kconfig.debug | 15 | ||||
-rw-r--r-- | arch/sh/Makefile | 1 | ||||
-rw-r--r-- | arch/sh/boards/se/7751/setup.c | 148 | ||||
-rw-r--r-- | arch/sh/kernel/kgdb_stub.c | 106 | ||||
-rw-r--r-- | arch/sh/kernel/setup.c | 94 |
5 files changed, 62 insertions, 302 deletions
diff --git a/arch/sh/Kconfig.debug b/arch/sh/Kconfig.debug index 87902e0298e2..6be2385c1ad2 100644 --- a/arch/sh/Kconfig.debug +++ b/arch/sh/Kconfig.debug | |||
@@ -77,16 +77,17 @@ config 4KSTACKS | |||
77 | on the VM subsystem for higher order allocations. This option | 77 | on the VM subsystem for higher order allocations. This option |
78 | will also use IRQ stacks to compensate for the reduced stackspace. | 78 | will also use IRQ stacks to compensate for the reduced stackspace. |
79 | 79 | ||
80 | config KGDB | 80 | config SH_KGDB |
81 | bool "Include KGDB kernel debugger" | 81 | bool "Include KGDB kernel debugger" |
82 | select FRAME_POINTER | 82 | select FRAME_POINTER |
83 | select DEBUG_INFO | ||
83 | help | 84 | help |
84 | Include in-kernel hooks for kgdb, the Linux kernel source level | 85 | Include in-kernel hooks for kgdb, the Linux kernel source level |
85 | debugger. See <http://kgdb.sourceforge.net/> for more information. | 86 | debugger. See <http://kgdb.sourceforge.net/> for more information. |
86 | Unless you are intending to debug the kernel, say N here. | 87 | Unless you are intending to debug the kernel, say N here. |
87 | 88 | ||
88 | menu "KGDB configuration options" | 89 | menu "KGDB configuration options" |
89 | depends on KGDB | 90 | depends on SH_KGDB |
90 | 91 | ||
91 | config MORE_COMPILE_OPTIONS | 92 | config MORE_COMPILE_OPTIONS |
92 | bool "Add any additional compile options" | 93 | bool "Add any additional compile options" |
@@ -109,16 +110,14 @@ config KGDB_THREAD | |||
109 | 110 | ||
110 | config SH_KGDB_CONSOLE | 111 | config SH_KGDB_CONSOLE |
111 | bool "Console messages through GDB" | 112 | bool "Console messages through GDB" |
113 | depends on !SERIAL_SH_SCI_CONSOLE | ||
114 | select SERIAL_CORE_CONSOLE | ||
112 | default n | 115 | default n |
113 | 116 | ||
114 | config KGDB_SYSRQ | 117 | config KGDB_SYSRQ |
115 | bool "Allow SysRq 'G' to enter KGDB" | 118 | bool "Allow SysRq 'G' to enter KGDB" |
116 | default y | 119 | default y |
117 | 120 | ||
118 | config KGDB_KERNEL_ASSERTS | ||
119 | bool "Include KGDB kernel assertions" | ||
120 | default n | ||
121 | |||
122 | comment "Serial port setup" | 121 | comment "Serial port setup" |
123 | 122 | ||
124 | config KGDB_DEFPORT | 123 | config KGDB_DEFPORT |
@@ -131,7 +130,7 @@ config KGDB_DEFBAUD | |||
131 | 130 | ||
132 | choice | 131 | choice |
133 | prompt "Parity" | 132 | prompt "Parity" |
134 | depends on KGDB | 133 | depends on SH_KGDB |
135 | default KGDB_DEFPARITY_N | 134 | default KGDB_DEFPARITY_N |
136 | 135 | ||
137 | config KGDB_DEFPARITY_N | 136 | config KGDB_DEFPARITY_N |
@@ -147,7 +146,7 @@ endchoice | |||
147 | 146 | ||
148 | choice | 147 | choice |
149 | prompt "Data bits" | 148 | prompt "Data bits" |
150 | depends on KGDB | 149 | depends on SH_KGDB |
151 | default KGDB_DEFBITS_8 | 150 | default KGDB_DEFBITS_8 |
152 | 151 | ||
153 | config KGDB_DEFBITS_8 | 152 | config KGDB_DEFBITS_8 |
diff --git a/arch/sh/Makefile b/arch/sh/Makefile index bd9b1729f8b8..0fadde283368 100644 --- a/arch/sh/Makefile +++ b/arch/sh/Makefile | |||
@@ -47,7 +47,6 @@ cflags-$(CONFIG_CPU_LITTLE_ENDIAN) += -ml | |||
47 | cflags-y += $(call as-option,-Wa$(comma)-isa=$(isa-y),) -ffreestanding | 47 | cflags-y += $(call as-option,-Wa$(comma)-isa=$(isa-y),) -ffreestanding |
48 | 48 | ||
49 | cflags-$(CONFIG_SH_DSP) += -Wa,-dsp | 49 | cflags-$(CONFIG_SH_DSP) += -Wa,-dsp |
50 | cflags-$(CONFIG_SH_KGDB) += -g | ||
51 | 50 | ||
52 | cflags-$(CONFIG_MORE_COMPILE_OPTIONS) += \ | 51 | cflags-$(CONFIG_MORE_COMPILE_OPTIONS) += \ |
53 | $(shell echo $(CONFIG_COMPILE_OPTIONS) | sed -e 's/"//g') | 52 | $(shell echo $(CONFIG_COMPILE_OPTIONS) | sed -e 's/"//g') |
diff --git a/arch/sh/boards/se/7751/setup.c b/arch/sh/boards/se/7751/setup.c index e3feae6ec0bf..770defed9c4a 100644 --- a/arch/sh/boards/se/7751/setup.c +++ b/arch/sh/boards/se/7751/setup.c | |||
@@ -14,153 +14,6 @@ | |||
14 | #include <asm/se7751.h> | 14 | #include <asm/se7751.h> |
15 | #include <asm/io.h> | 15 | #include <asm/io.h> |
16 | 16 | ||
17 | void init_7751se_IRQ(void); | ||
18 | |||
19 | #ifdef CONFIG_SH_KGDB | ||
20 | #include <asm/kgdb.h> | ||
21 | static int kgdb_uart_setup(void); | ||
22 | static struct kgdb_sermap kgdb_uart_sermap = | ||
23 | { "ttyS", 0, kgdb_uart_setup, NULL }; | ||
24 | #endif | ||
25 | |||
26 | /* | ||
27 | * Initialize the board | ||
28 | */ | ||
29 | static void __init sh7751se_setup(char **cmdline_p) | ||
30 | { | ||
31 | /* Call init_smsc() replacement to set up SuperIO. */ | ||
32 | /* XXX: RTC setting comes here */ | ||
33 | #ifdef CONFIG_SH_KGDB | ||
34 | kgdb_register_sermap(&kgdb_uart_sermap); | ||
35 | #endif | ||
36 | } | ||
37 | |||
38 | /********************************************************************* | ||
39 | * Currently a hack (e.g. does not interact well w/serial.c, lots of * | ||
40 | * hardcoded stuff) but may be useful if SCI/F needs debugging. * | ||
41 | * Mostly copied from x86 code (see files asm-i386/kgdb_local.h and * | ||
42 | * arch/i386/lib/kgdb_serial.c). * | ||
43 | *********************************************************************/ | ||
44 | |||
45 | #ifdef CONFIG_SH_KGDB | ||
46 | #include <linux/types.h> | ||
47 | #include <linux/serial.h> | ||
48 | #include <linux/serialP.h> | ||
49 | #include <linux/serial_reg.h> | ||
50 | |||
51 | #define COM1_PORT 0x3f8 /* Base I/O address */ | ||
52 | #define COM1_IRQ 4 /* IRQ not used yet */ | ||
53 | #define COM2_PORT 0x2f8 /* Base I/O address */ | ||
54 | #define COM2_IRQ 3 /* IRQ not used yet */ | ||
55 | |||
56 | #define SB_CLOCK 1843200 /* Serial baud clock */ | ||
57 | #define SB_BASE (SB_CLOCK/16) | ||
58 | #define SB_MCR UART_MCR_OUT2 | UART_MCR_DTR | UART_MCR_RTS | ||
59 | |||
60 | struct uart_port { | ||
61 | int base; | ||
62 | }; | ||
63 | #define UART_NPORTS 2 | ||
64 | struct uart_port uart_ports[] = { | ||
65 | { COM1_PORT }, | ||
66 | { COM2_PORT }, | ||
67 | }; | ||
68 | struct uart_port *kgdb_uart_port; | ||
69 | |||
70 | #define UART_IN(reg) inb_p(kgdb_uart_port->base + reg) | ||
71 | #define UART_OUT(reg,v) outb_p((v), kgdb_uart_port->base + reg) | ||
72 | |||
73 | /* Basic read/write functions for the UART */ | ||
74 | #define UART_LSR_RXCERR (UART_LSR_BI | UART_LSR_FE | UART_LSR_PE) | ||
75 | static int kgdb_uart_getchar(void) | ||
76 | { | ||
77 | int lsr; | ||
78 | int c = -1; | ||
79 | |||
80 | while (c == -1) { | ||
81 | lsr = UART_IN(UART_LSR); | ||
82 | if (lsr & UART_LSR_DR) | ||
83 | c = UART_IN(UART_RX); | ||
84 | if ((lsr & UART_LSR_RXCERR)) | ||
85 | c = -1; | ||
86 | } | ||
87 | return c; | ||
88 | } | ||
89 | |||
90 | static void kgdb_uart_putchar(int c) | ||
91 | { | ||
92 | while ((UART_IN(UART_LSR) & UART_LSR_THRE) == 0) | ||
93 | ; | ||
94 | UART_OUT(UART_TX, c); | ||
95 | } | ||
96 | |||
97 | /* | ||
98 | * Initialize UART to configured/requested values. | ||
99 | * (But we don't interrupts yet, or interact w/serial.c) | ||
100 | */ | ||
101 | static int kgdb_uart_setup(void) | ||
102 | { | ||
103 | int port; | ||
104 | int lcr = 0; | ||
105 | int bdiv = 0; | ||
106 | |||
107 | if (kgdb_portnum >= UART_NPORTS) { | ||
108 | KGDB_PRINTK("uart port %d invalid.\n", kgdb_portnum); | ||
109 | return -1; | ||
110 | } | ||
111 | |||
112 | kgdb_uart_port = &uart_ports[kgdb_portnum]; | ||
113 | |||
114 | /* Init sequence from gdb_hook_interrupt */ | ||
115 | UART_IN(UART_RX); | ||
116 | UART_OUT(UART_IER, 0); | ||
117 | |||
118 | UART_IN(UART_RX); /* Serial driver comments say */ | ||
119 | UART_IN(UART_IIR); /* this clears interrupt regs */ | ||
120 | UART_IN(UART_MSR); | ||
121 | |||
122 | /* Figure basic LCR values */ | ||
123 | switch (kgdb_bits) { | ||
124 | case '7': | ||
125 | lcr |= UART_LCR_WLEN7; | ||
126 | break; | ||
127 | default: case '8': | ||
128 | lcr |= UART_LCR_WLEN8; | ||
129 | break; | ||
130 | } | ||
131 | switch (kgdb_parity) { | ||
132 | case 'O': | ||
133 | lcr |= UART_LCR_PARITY; | ||
134 | break; | ||
135 | case 'E': | ||
136 | lcr |= (UART_LCR_PARITY | UART_LCR_EPAR); | ||
137 | break; | ||
138 | default: break; | ||
139 | } | ||
140 | |||
141 | /* Figure the baud rate divisor */ | ||
142 | bdiv = (SB_BASE/kgdb_baud); | ||
143 | |||
144 | /* Set the baud rate and LCR values */ | ||
145 | UART_OUT(UART_LCR, (lcr | UART_LCR_DLAB)); | ||
146 | UART_OUT(UART_DLL, (bdiv & 0xff)); | ||
147 | UART_OUT(UART_DLM, ((bdiv >> 8) & 0xff)); | ||
148 | UART_OUT(UART_LCR, lcr); | ||
149 | |||
150 | /* Set the MCR */ | ||
151 | UART_OUT(UART_MCR, SB_MCR); | ||
152 | |||
153 | /* Turn off FIFOs for now */ | ||
154 | UART_OUT(UART_FCR, 0); | ||
155 | |||
156 | /* Setup complete: initialize function pointers */ | ||
157 | kgdb_getchar = kgdb_uart_getchar; | ||
158 | kgdb_putchar = kgdb_uart_putchar; | ||
159 | |||
160 | return 0; | ||
161 | } | ||
162 | #endif /* CONFIG_SH_KGDB */ | ||
163 | |||
164 | static unsigned char heartbeat_bit_pos[] = { 8, 9, 10, 11, 12, 13, 14, 15 }; | 17 | static unsigned char heartbeat_bit_pos[] = { 8, 9, 10, 11, 12, 13, 14, 15 }; |
165 | 18 | ||
166 | static struct resource heartbeat_resources[] = { | 19 | static struct resource heartbeat_resources[] = { |
@@ -197,7 +50,6 @@ __initcall(se7751_devices_setup); | |||
197 | */ | 50 | */ |
198 | struct sh_machine_vector mv_7751se __initmv = { | 51 | struct sh_machine_vector mv_7751se __initmv = { |
199 | .mv_name = "7751 SolutionEngine", | 52 | .mv_name = "7751 SolutionEngine", |
200 | .mv_setup = sh7751se_setup, | ||
201 | .mv_nr_irqs = 72, | 53 | .mv_nr_irqs = 72, |
202 | 54 | ||
203 | .mv_inb = sh7751se_inb, | 55 | .mv_inb = sh7751se_inb, |
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 */ | ||