aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVijaya Kumar K <Vijaya.Kumar@caviumnetworks.com>2014-01-28 06:20:19 -0500
committerCatalin Marinas <catalin.marinas@arm.com>2014-02-26 06:16:25 -0500
commit44679a4f142b69ae0c68ed815a48bbd164827281 (patch)
tree643674a107d3fadd5b313d9709ae1f8dd40c8a5b
parentbcf5763b0d58d20e288ac52f96cbd7788e262cac (diff)
arm64: KGDB: Add step debugging support
Add KGDB software step debugging support for EL1 debug in AArch64 mode. KGDB registers step debug handler with debug monitor. On receiving 'step' command from GDB tool, target enables software step debugging and step address is updated in ELR. Software Step debugging is disabled when 'continue' command is received Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@caviumnetworks.com> Reviewed-by: Will Deacon <will.deacon@arm.com> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
-rw-r--r--arch/arm64/kernel/kgdb.c64
1 files changed, 56 insertions, 8 deletions
diff --git a/arch/arm64/kernel/kgdb.c b/arch/arm64/kernel/kgdb.c
index 4b7a5695175e..75c9cf1aafee 100644
--- a/arch/arm64/kernel/kgdb.c
+++ b/arch/arm64/kernel/kgdb.c
@@ -137,13 +137,26 @@ void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc)
137 137
138static int compiled_break; 138static int compiled_break;
139 139
140static void kgdb_arch_update_addr(struct pt_regs *regs,
141 char *remcom_in_buffer)
142{
143 unsigned long addr;
144 char *ptr;
145
146 ptr = &remcom_in_buffer[1];
147 if (kgdb_hex2long(&ptr, &addr))
148 kgdb_arch_set_pc(regs, addr);
149 else if (compiled_break == 1)
150 kgdb_arch_set_pc(regs, regs->pc + 4);
151
152 compiled_break = 0;
153}
154
140int kgdb_arch_handle_exception(int exception_vector, int signo, 155int kgdb_arch_handle_exception(int exception_vector, int signo,
141 int err_code, char *remcom_in_buffer, 156 int err_code, char *remcom_in_buffer,
142 char *remcom_out_buffer, 157 char *remcom_out_buffer,
143 struct pt_regs *linux_regs) 158 struct pt_regs *linux_regs)
144{ 159{
145 unsigned long addr;
146 char *ptr;
147 int err; 160 int err;
148 161
149 switch (remcom_in_buffer[0]) { 162 switch (remcom_in_buffer[0]) {
@@ -162,13 +175,36 @@ int kgdb_arch_handle_exception(int exception_vector, int signo,
162 * to the next instruction else we will just breakpoint 175 * to the next instruction else we will just breakpoint
163 * over and over again. 176 * over and over again.
164 */ 177 */
165 ptr = &remcom_in_buffer[1]; 178 kgdb_arch_update_addr(linux_regs, remcom_in_buffer);
166 if (kgdb_hex2long(&ptr, &addr)) 179 atomic_set(&kgdb_cpu_doing_single_step, -1);
167 kgdb_arch_set_pc(linux_regs, addr); 180 kgdb_single_step = 0;
168 else if (compiled_break == 1) 181
169 kgdb_arch_set_pc(linux_regs, linux_regs->pc + 4); 182 /*
183 * Received continue command, disable single step
184 */
185 if (kernel_active_single_step())
186 kernel_disable_single_step();
187
188 err = 0;
189 break;
190 case 's':
191 /*
192 * Update step address value with address passed
193 * with step packet.
194 * On debug exception return PC is copied to ELR
195 * So just update PC.
196 * If no step address is passed, resume from the address
197 * pointed by PC. Do not update PC
198 */
199 kgdb_arch_update_addr(linux_regs, remcom_in_buffer);
200 atomic_set(&kgdb_cpu_doing_single_step, raw_smp_processor_id());
201 kgdb_single_step = 1;
170 202
171 compiled_break = 0; 203 /*
204 * Enable single step handling
205 */
206 if (!kernel_active_single_step())
207 kernel_enable_single_step(linux_regs);
172 err = 0; 208 err = 0;
173 break; 209 break;
174 default: 210 default:
@@ -191,6 +227,12 @@ static int kgdb_compiled_brk_fn(struct pt_regs *regs, unsigned int esr)
191 return 0; 227 return 0;
192} 228}
193 229
230static int kgdb_step_brk_fn(struct pt_regs *regs, unsigned int esr)
231{
232 kgdb_handle_exception(1, SIGTRAP, 0, regs);
233 return 0;
234}
235
194static struct break_hook kgdb_brkpt_hook = { 236static struct break_hook kgdb_brkpt_hook = {
195 .esr_mask = 0xffffffff, 237 .esr_mask = 0xffffffff,
196 .esr_val = DBG_ESR_VAL_BRK(KGDB_DYN_DGB_BRK_IMM), 238 .esr_val = DBG_ESR_VAL_BRK(KGDB_DYN_DGB_BRK_IMM),
@@ -203,6 +245,10 @@ static struct break_hook kgdb_compiled_brkpt_hook = {
203 .fn = kgdb_compiled_brk_fn 245 .fn = kgdb_compiled_brk_fn
204}; 246};
205 247
248static struct step_hook kgdb_step_hook = {
249 .fn = kgdb_step_brk_fn
250};
251
206static void kgdb_call_nmi_hook(void *ignored) 252static void kgdb_call_nmi_hook(void *ignored)
207{ 253{
208 kgdb_nmicallback(raw_smp_processor_id(), get_irq_regs()); 254 kgdb_nmicallback(raw_smp_processor_id(), get_irq_regs());
@@ -259,6 +305,7 @@ int kgdb_arch_init(void)
259 305
260 register_break_hook(&kgdb_brkpt_hook); 306 register_break_hook(&kgdb_brkpt_hook);
261 register_break_hook(&kgdb_compiled_brkpt_hook); 307 register_break_hook(&kgdb_compiled_brkpt_hook);
308 register_step_hook(&kgdb_step_hook);
262 return 0; 309 return 0;
263} 310}
264 311
@@ -271,6 +318,7 @@ void kgdb_arch_exit(void)
271{ 318{
272 unregister_break_hook(&kgdb_brkpt_hook); 319 unregister_break_hook(&kgdb_brkpt_hook);
273 unregister_break_hook(&kgdb_compiled_brkpt_hook); 320 unregister_break_hook(&kgdb_compiled_brkpt_hook);
321 unregister_step_hook(&kgdb_step_hook);
274 unregister_die_notifier(&kgdb_notifier); 322 unregister_die_notifier(&kgdb_notifier);
275} 323}
276 324