/* trap handler: main entry point */ int __trap_to_gdb(struct cpu_user_regs *regs, unsigned long cookie) { int rc = 0; unsigned long flags; if ( gdb_ctx->serhnd < 0 ) { printk("Debugging connection not set up.\n"); return -EBUSY; } /* We rely on our caller to ensure we're only on one processor * at a time... We should probably panic here, but given that * we're a debugger we should probably be a little tolerant of * things going wrong. */ /* We don't want to use a spin lock here, because we're doing two distinct things: 1 -- we don't want to run on more than one processor at a time, and 2 -- we want to do something sensible if we re-enter ourselves. Spin locks are good for 1, but useless for 2. */ if ( !atomic_dec_and_test(&gdb_ctx->running) ) { printk("WARNING WARNING WARNING: Avoiding recursive gdb.\n"); atomic_inc(&gdb_ctx->running); return -EBUSY; } if ( !gdb_ctx->connected ) { printk("GDB connection activated.\n"); gdb_arch_print_state(regs); gdb_ctx->connected = 1; } gdb_smp_pause(); local_irq_save(flags); watchdog_disable(); console_start_sync(); /* Shouldn't really do this, but otherwise we stop for no obvious reason, which is Bad */ printk("Waiting for GDB to attach...\n"); gdb_arch_enter(regs); gdb_ctx->signum = gdb_arch_signal_num(regs, cookie); /* If gdb is already attached, tell it we've stopped again. */ if ( gdb_ctx->currently_attached ) { gdb_start_packet(gdb_ctx); gdb_cmd_signum(gdb_ctx); } do { if ( receive_command(gdb_ctx) < 0 ) { dbg_printk("Error in GDB session...\n"); rc = -EIO; break; } } while ( process_command(regs, gdb_ctx) == 0 ); gdb_smp_resume(); gdb_arch_exit(regs); console_end_sync(); watchdog_enable(); atomic_inc(&gdb_ctx->running); local_irq_restore(flags); return rc; }
void gdb_enter(void) { if (!gdb_state.connected) gdb_init(); gdb_arch_enter(); }