int kgdb_arch_handle_exception(int exception_vector, int signo, int err_code, char *remcom_in_buffer, char *remcom_out_buffer, struct pt_regs *linux_regs) { int err; switch (remcom_in_buffer[0]) { case 'D': case 'k': /* * Packet D (Detach), k (kill). No special handling * is required here. Handle same as c packet. */ case 'c': /* * Packet c (Continue) to continue executing. * Set pc to required address. * Try to read optional parameter and set pc. * If this was a compiled breakpoint, we need to move * to the next instruction else we will just breakpoint * over and over again. */ kgdb_arch_update_addr(linux_regs, remcom_in_buffer); atomic_set(&kgdb_cpu_doing_single_step, -1); kgdb_single_step = 0; /* * Received continue command, disable single step */ if (kernel_active_single_step()) kernel_disable_single_step(); err = 0; break; case 's': /* * Update step address value with address passed * with step packet. * On debug exception return PC is copied to ELR * So just update PC. * If no step address is passed, resume from the address * pointed by PC. Do not update PC */ kgdb_arch_update_addr(linux_regs, remcom_in_buffer); atomic_set(&kgdb_cpu_doing_single_step, raw_smp_processor_id()); kgdb_single_step = 1; /* * Enable single step handling */ if (!kernel_active_single_step()) kernel_enable_single_step(linux_regs); err = 0; break; default: err = -1; } return err; }
/* * Handle single-step exception. */ int reinstall_suspended_bps(struct pt_regs *regs) { struct debug_info *debug_info = ¤t->thread.debug; int handled_exception = 0, *kernel_step; kernel_step = this_cpu_ptr(&stepping_kernel_bp); /* * Called from single-step exception handler. * Return 0 if execution can resume, 1 if a SIGTRAP should be * reported. */ if (user_mode(regs)) { if (debug_info->bps_disabled) { debug_info->bps_disabled = 0; toggle_bp_registers(AARCH64_DBG_REG_BCR, DBG_ACTIVE_EL0, 1); handled_exception = 1; } if (debug_info->wps_disabled) { debug_info->wps_disabled = 0; toggle_bp_registers(AARCH64_DBG_REG_WCR, DBG_ACTIVE_EL0, 1); handled_exception = 1; } if (handled_exception) { if (debug_info->suspended_step) { debug_info->suspended_step = 0; /* Allow exception handling to fall-through. */ handled_exception = 0; } else { user_disable_single_step(current); } } } else if (*kernel_step != ARM_KERNEL_STEP_NONE) { toggle_bp_registers(AARCH64_DBG_REG_BCR, DBG_ACTIVE_EL1, 1); toggle_bp_registers(AARCH64_DBG_REG_WCR, DBG_ACTIVE_EL1, 1); if (!debug_info->wps_disabled) toggle_bp_registers(AARCH64_DBG_REG_WCR, DBG_ACTIVE_EL0, 1); if (*kernel_step != ARM_KERNEL_STEP_SUSPEND) { kernel_disable_single_step(); handled_exception = 1; } else { handled_exception = 0; } *kernel_step = ARM_KERNEL_STEP_NONE; } return !handled_exception; }