static int or1k_set_core_reg(struct reg *reg, uint8_t *buf) { struct or1k_core_reg *or1k_reg = reg->arch_info; struct target *target = or1k_reg->target; struct or1k_common *or1k = target_to_or1k(target); struct or1k_du *du_core = or1k_to_du(or1k); uint32_t value = buf_get_u32(buf, 0, 32); LOG_DEBUG("-"); if (target->state != TARGET_HALTED) return ERROR_TARGET_NOT_HALTED; if (or1k_reg->list_num < OR1KNUMCOREREGS) { buf_set_u32(reg->value, 0, 32, value); reg->dirty = 1; reg->valid = 1; } else { /* This is an spr, write it to the HW */ int retval = du_core->or1k_jtag_write_cpu(&or1k->jtag, or1k_reg->spr_num, 1, &value); if (retval != ERROR_OK) { LOG_ERROR("Error while writing spr 0x%08" PRIx32, or1k_reg->spr_num); return retval; } } return ERROR_OK; }
static int or1k_examine(struct target *target) { struct or1k_common *or1k = target_to_or1k(target); struct or1k_du *du_core = or1k_to_du(or1k); if (!target_was_examined(target)) { target_set_examined(target); int running; int retval = du_core->or1k_is_cpu_running(&or1k->jtag, &running); if (retval != ERROR_OK) { LOG_ERROR("Couldn't read the CPU state"); return retval; } else { if (running) target->state = TARGET_RUNNING; else { LOG_DEBUG("Target is halted"); /* This is the first time we examine the target, * it is stalled and we don't know why. Let's * assume this is because of a debug reason. */ if (target->state == TARGET_UNKNOWN) target->debug_reason = DBG_REASON_DBGRQ; target->state = TARGET_HALTED; } } } return ERROR_OK; }
static int or1k_read_core_reg(struct target *target, int num) { struct or1k_common *or1k = target_to_or1k(target); struct or1k_du *du_core = or1k_to_du(or1k); uint32_t reg_value; LOG_DEBUG("-"); if ((num < 0) || (num >= or1k->nb_regs)) return ERROR_COMMAND_SYNTAX_ERROR; if ((num >= 0) && (num < OR1KNUMCOREREGS)) { reg_value = or1k->core_regs[num]; buf_set_u32(or1k->core_cache->reg_list[num].value, 0, 32, reg_value); LOG_DEBUG("Read core reg %i value 0x%08" PRIx32, num , reg_value); or1k->core_cache->reg_list[num].valid = 1; or1k->core_cache->reg_list[num].dirty = 0; } else { /* This is an spr, always read value from HW */ int retval = du_core->or1k_jtag_read_cpu(&or1k->jtag, or1k->arch_info[num].spr_num, 1, ®_value); if (retval != ERROR_OK) { LOG_ERROR("Error while reading spr 0x%08" PRIx32, or1k->arch_info[num].spr_num); return retval; } buf_set_u32(or1k->core_cache->reg_list[num].value, 0, 32, reg_value); LOG_DEBUG("Read spr reg %i value 0x%08" PRIx32, num , reg_value); } return ERROR_OK; }
static int or1k_save_context(struct target *target) { struct or1k_common *or1k = target_to_or1k(target); struct or1k_du *du_core = or1k_to_du(or1k); int regs_read = 0; int retval; LOG_DEBUG("-"); for (int i = 0; i < OR1KNUMCOREREGS; i++) { if (!or1k->core_cache->reg_list[i].valid) { if (i == OR1K_REG_PPC || i == OR1K_REG_NPC || i == OR1K_REG_SR) { retval = du_core->or1k_jtag_read_cpu(&or1k->jtag, or1k->arch_info[i].spr_num, 1, &or1k->core_regs[i]); if (retval != ERROR_OK) return retval; } else if (!regs_read) { /* read gpr registers at once (but only one time in this loop) */ retval = or1k_jtag_read_regs(or1k, or1k->core_regs); if (retval != ERROR_OK) return retval; /* prevent next reads in this loop */ regs_read = 1; } /* We've just updated the core_reg[i], now update the core cache */ or1k_read_core_reg(target, i); } } return ERROR_OK; }
static int or1k_init_target(struct command_context *cmd_ctx, struct target *target) { struct or1k_common *or1k = target_to_or1k(target); struct or1k_du *du_core = or1k_to_du(or1k); struct or1k_jtag *jtag = &or1k->jtag; if (du_core == NULL) { LOG_ERROR("No debug unit selected"); return ERROR_FAIL; } if (jtag->tap_ip == NULL) { LOG_ERROR("No tap selected"); return ERROR_FAIL; } or1k->jtag.tap = target->tap; or1k->jtag.or1k_jtag_inited = 0; or1k->jtag.or1k_jtag_module_selected = -1; or1k->jtag.target = target; or1k_build_reg_cache(target); return ERROR_OK; }
static int or1k_write_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { struct or1k_common *or1k = target_to_or1k(target); struct or1k_du *du_core = or1k_to_du(or1k); LOG_DEBUG("Write memory at 0x%08" PRIx32 ", size: %" PRIu32 ", count: 0x%08" PRIx32, address, size, count); if (target->state != TARGET_HALTED) { LOG_WARNING("Target not halted"); return ERROR_TARGET_NOT_HALTED; } /* Sanitize arguments */ if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !buffer) { LOG_ERROR("Bad arguments"); return ERROR_COMMAND_SYNTAX_ERROR; } if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u))) { LOG_ERROR("Can't handle unaligned memory access"); return ERROR_TARGET_UNALIGNED_ACCESS; } return du_core->or1k_jtag_write_memory(&or1k->jtag, address, size, count, buffer); }
static int or1k_add_breakpoint(struct target *target, struct breakpoint *breakpoint) { struct or1k_common *or1k = target_to_or1k(target); struct or1k_du *du_core = or1k_to_du(or1k); uint8_t data; LOG_DEBUG("Adding breakpoint: addr 0x%08" TARGET_PRIxADDR ", len %d, type %d, set: %d, id: %" PRId32, breakpoint->address, breakpoint->length, breakpoint->type, breakpoint->set, breakpoint->unique_id); /* Only support SW breakpoints for now. */ if (breakpoint->type == BKPT_HARD) LOG_ERROR("HW breakpoints not supported for now. Doing SW breakpoint."); /* Read and save the instruction */ int retval = du_core->or1k_jtag_read_memory(&or1k->jtag, breakpoint->address, 4, 1, &data); if (retval != ERROR_OK) { LOG_ERROR("Error while reading the instruction at 0x%08" TARGET_PRIxADDR, breakpoint->address); return retval; } if (breakpoint->orig_instr != NULL) free(breakpoint->orig_instr); breakpoint->orig_instr = malloc(breakpoint->length); memcpy(breakpoint->orig_instr, &data, breakpoint->length); /* Sub in the OR1K trap instruction */ uint8_t or1k_trap_insn[4]; target_buffer_set_u32(target, or1k_trap_insn, OR1K_TRAP_INSTR); retval = du_core->or1k_jtag_write_memory(&or1k->jtag, breakpoint->address, 4, 1, or1k_trap_insn); if (retval != ERROR_OK) { LOG_ERROR("Error while writing OR1K_TRAP_INSTR at 0x%08" TARGET_PRIxADDR, breakpoint->address); return retval; } /* invalidate instruction cache */ uint32_t addr = breakpoint->address; retval = du_core->or1k_jtag_write_cpu(&or1k->jtag, OR1K_ICBIR_CPU_REG_ADD, 1, &addr); if (retval != ERROR_OK) { LOG_ERROR("Error while invalidating the ICACHE"); return retval; } return ERROR_OK; }
static int or1k_deassert_reset(struct target *target) { struct or1k_common *or1k = target_to_or1k(target); struct or1k_du *du_core = or1k_to_du(or1k); LOG_DEBUG("-"); int retval = du_core->or1k_cpu_reset(&or1k->jtag, CPU_NOT_RESET); if (retval != ERROR_OK) { LOG_ERROR("Error while desasserting RESET"); return retval; } return ERROR_OK; }
static int or1k_profiling(struct target *target, uint32_t *samples, uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds) { struct timeval timeout, now; struct or1k_common *or1k = target_to_or1k(target); struct or1k_du *du_core = or1k_to_du(or1k); int retval = ERROR_OK; gettimeofday(&timeout, NULL); timeval_add_time(&timeout, seconds, 0); LOG_INFO("Starting or1k profiling. Sampling npc as fast as we can..."); /* Make sure the target is running */ target_poll(target); if (target->state == TARGET_HALTED) retval = target_resume(target, 1, 0, 0, 0); if (retval != ERROR_OK) { LOG_ERROR("Error while resuming target"); return retval; } uint32_t sample_count = 0; for (;;) { uint32_t reg_value; retval = du_core->or1k_jtag_read_cpu(&or1k->jtag, GROUP0 + 16 /* NPC */, 1, ®_value); if (retval != ERROR_OK) { LOG_ERROR("Error while reading NPC"); return retval; } samples[sample_count++] = reg_value; gettimeofday(&now, NULL); if ((sample_count >= max_num_samples) || ((now.tv_sec >= timeout.tv_sec) && (now.tv_usec >= timeout.tv_usec))) { LOG_INFO("Profiling completed. %" PRIu32 " samples.", sample_count); break; } } *num_samples = sample_count; return retval; }
static int or1k_remove_breakpoint(struct target *target, struct breakpoint *breakpoint) { struct or1k_common *or1k = target_to_or1k(target); struct or1k_du *du_core = or1k_to_du(or1k); LOG_DEBUG("Removing breakpoint: addr 0x%08" TARGET_PRIxADDR ", len %d, type %d, set: %d, id: %" PRId32, breakpoint->address, breakpoint->length, breakpoint->type, breakpoint->set, breakpoint->unique_id); /* Only support SW breakpoints for now. */ if (breakpoint->type == BKPT_HARD) LOG_ERROR("HW breakpoints not supported for now. Doing SW breakpoint."); /* Replace the removed instruction */ int retval = du_core->or1k_jtag_write_memory(&or1k->jtag, breakpoint->address, 4, 1, breakpoint->orig_instr); if (retval != ERROR_OK) { LOG_ERROR("Error while writing back the instruction at 0x%08" TARGET_PRIxADDR, breakpoint->address); return retval; } /* invalidate instruction cache */ uint32_t addr = breakpoint->address; retval = du_core->or1k_jtag_write_cpu(&or1k->jtag, OR1K_ICBIR_CPU_REG_ADD, 1, &addr); if (retval != ERROR_OK) { LOG_ERROR("Error while invalidating the ICACHE"); return retval; } return ERROR_OK; }
static int or1k_soft_reset_halt(struct target *target) { struct or1k_common *or1k = target_to_or1k(target); struct or1k_du *du_core = or1k_to_du(or1k); LOG_DEBUG("-"); int retval = du_core->or1k_cpu_stall(&or1k->jtag, CPU_STALL); if (retval != ERROR_OK) { LOG_ERROR("Error while stalling the CPU"); return retval; } retval = or1k_assert_reset(target); if (retval != ERROR_OK) return retval; retval = or1k_deassert_reset(target); if (retval != ERROR_OK) return retval; return ERROR_OK; }
static int or1k_halt(struct target *target) { struct or1k_common *or1k = target_to_or1k(target); struct or1k_du *du_core = or1k_to_du(or1k); LOG_DEBUG("target->state: %s", target_state_name(target)); if (target->state == TARGET_HALTED) { LOG_DEBUG("Target was already halted"); return ERROR_OK; } if (target->state == TARGET_UNKNOWN) LOG_WARNING("Target was in unknown state when halt was requested"); if (target->state == TARGET_RESET) { if ((jtag_get_reset_config() & RESET_SRST_PULLS_TRST) && jtag_get_srst()) { LOG_ERROR("Can't request a halt while in reset if nSRST pulls nTRST"); return ERROR_TARGET_FAILURE; } else { target->debug_reason = DBG_REASON_DBGRQ; return ERROR_OK; } } int retval = du_core->or1k_cpu_stall(&or1k->jtag, CPU_STALL); if (retval != ERROR_OK) { LOG_ERROR("Impossible to stall the CPU"); return retval; } target->debug_reason = DBG_REASON_DBGRQ; return ERROR_OK; }
static int or1k_restore_context(struct target *target) { struct or1k_common *or1k = target_to_or1k(target); struct or1k_du *du_core = or1k_to_du(or1k); int reg_write = 0; int retval; LOG_DEBUG("-"); for (int i = 0; i < OR1KNUMCOREREGS; i++) { if (or1k->core_cache->reg_list[i].dirty) { or1k_write_core_reg(target, i); if (i == OR1K_REG_PPC || i == OR1K_REG_NPC || i == OR1K_REG_SR) { retval = du_core->or1k_jtag_write_cpu(&or1k->jtag, or1k->arch_info[i].spr_num, 1, &or1k->core_regs[i]); if (retval != ERROR_OK) { LOG_ERROR("Error while restoring context"); return retval; } } else reg_write = 1; } } if (reg_write) { /* read gpr registers at once (but only one time in this loop) */ retval = or1k_jtag_write_regs(or1k, or1k->core_regs); if (retval != ERROR_OK) { LOG_ERROR("Error while restoring context"); return retval; } } return ERROR_OK; }
static int or1k_is_cpu_running(struct target *target, int *running) { struct or1k_common *or1k = target_to_or1k(target); struct or1k_du *du_core = or1k_to_du(or1k); int retval; int tries = 0; const int RETRIES_MAX = 5; /* Have a retry loop to determine of the CPU is running. If target has been hard reset for any reason, it might take a couple of goes before it's ready again. */ while (tries < RETRIES_MAX) { tries++; retval = du_core->or1k_is_cpu_running(&or1k->jtag, running); if (retval != ERROR_OK) { LOG_WARNING("Debug IF CPU control reg read failure."); /* Try once to restart the JTAG infrastructure - quite possibly the board has just been reset. */ LOG_WARNING("Resetting JTAG TAP state and reconnectiong to debug IF."); du_core->or1k_jtag_init(&or1k->jtag); LOG_WARNING("...attempt %d of %d", tries, RETRIES_MAX); alive_sleep(2); continue; } else return ERROR_OK; } LOG_ERROR("Could not re-establish communication with target"); return retval; }
static int or1k_resume_or_step(struct target *target, int current, uint32_t address, int handle_breakpoints, int debug_execution, int step) { struct or1k_common *or1k = target_to_or1k(target); struct or1k_du *du_core = or1k_to_du(or1k); struct breakpoint *breakpoint = NULL; uint32_t resume_pc; uint32_t debug_reg_list[OR1K_DEBUG_REG_NUM]; LOG_DEBUG("Addr: 0x%" PRIx32 ", stepping: %s, handle breakpoints %s\n", address, step ? "yes" : "no", handle_breakpoints ? "yes" : "no"); if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } if (!debug_execution) target_free_all_working_areas(target); /* current ? continue on current pc : continue at <address> */ if (!current) buf_set_u32(or1k->core_cache->reg_list[OR1K_REG_NPC].value, 0, 32, address); int retval = or1k_restore_context(target); if (retval != ERROR_OK) { LOG_ERROR("Error while calling or1k_restore_context"); return retval; } /* read debug registers (starting from DMR1 register) */ retval = du_core->or1k_jtag_read_cpu(&or1k->jtag, OR1K_DMR1_CPU_REG_ADD, OR1K_DEBUG_REG_NUM, debug_reg_list); if (retval != ERROR_OK) { LOG_ERROR("Error while reading debug registers"); return retval; } /* Clear Debug Reason Register (DRR) */ debug_reg_list[OR1K_DEBUG_REG_DRR] = 0; /* Clear watchpoint break generation in Debug Mode Register 2 (DMR2) */ debug_reg_list[OR1K_DEBUG_REG_DMR2] &= ~OR1K_DMR2_WGB; if (step) /* Set the single step trigger in Debug Mode Register 1 (DMR1) */ debug_reg_list[OR1K_DEBUG_REG_DMR1] |= OR1K_DMR1_ST | OR1K_DMR1_BT; else /* Clear the single step trigger in Debug Mode Register 1 (DMR1) */ debug_reg_list[OR1K_DEBUG_REG_DMR1] &= ~(OR1K_DMR1_ST | OR1K_DMR1_BT); /* Set traps to be handled by the debug unit in the Debug Stop Register (DSR). Check if we have any software breakpoints in place before setting this value - the kernel, for instance, relies on l.trap instructions not stalling the processor ! */ if (is_any_soft_breakpoint(target) == true) debug_reg_list[OR1K_DEBUG_REG_DSR] |= OR1K_DSR_TE; /* Write debug registers (starting from DMR1 register) */ retval = du_core->or1k_jtag_write_cpu(&or1k->jtag, OR1K_DMR1_CPU_REG_ADD, OR1K_DEBUG_REG_NUM, debug_reg_list); if (retval != ERROR_OK) { LOG_ERROR("Error while writing back debug registers"); return retval; } resume_pc = buf_get_u32(or1k->core_cache->reg_list[OR1K_REG_NPC].value, 0, 32); /* The front-end may request us not to handle breakpoints */ if (handle_breakpoints) { /* Single step past breakpoint at current address */ breakpoint = breakpoint_find(target, resume_pc); if (breakpoint) { LOG_DEBUG("Unset breakpoint at 0x%08" PRIx32, breakpoint->address); retval = or1k_remove_breakpoint(target, breakpoint); if (retval != ERROR_OK) return retval; } } /* Unstall time */ retval = du_core->or1k_cpu_stall(&or1k->jtag, CPU_UNSTALL); if (retval != ERROR_OK) { LOG_ERROR("Error while unstalling the CPU"); return retval; } if (step) target->debug_reason = DBG_REASON_SINGLESTEP; else target->debug_reason = DBG_REASON_NOTHALTED; /* Registers are now invalid */ register_cache_invalidate(or1k->core_cache); if (!debug_execution) { target->state = TARGET_RUNNING; target_call_event_callbacks(target, TARGET_EVENT_RESUMED); LOG_DEBUG("Target resumed at 0x%08" PRIx32, resume_pc); } else { target->state = TARGET_DEBUG_RUNNING; target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED); LOG_DEBUG("Target debug resumed at 0x%08" PRIx32, resume_pc); } return ERROR_OK; }