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); }
int or1k_save_context(struct target *target) { LOG_DEBUG(" - "); int retval, i, regs_read = 0; struct or1k_common *or1k = target_to_or1k(target); for (i = 0; i < OR1KNUMCOREREGS; i++) { if (!regs_read && !or1k->core_cache->reg_list[i].valid) { /* read all registers at once (but only one time in this loop) */ retval = or1k_jtag_read_regs(&or1k->jtag, or1k->core_regs); if (retval != ERROR_OK) return retval; /* prevent next reads in this loop */ regs_read = 1; } if (!or1k->core_cache->reg_list[i].valid) { /* 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_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_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_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_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size, enum target_register_class reg_class) { struct or1k_common *or1k = target_to_or1k(target); if (reg_class == REG_CLASS_GENERAL) { /* We will have this called whenever GDB connects. */ int retval = or1k_save_context(target); if (retval != ERROR_OK) { LOG_ERROR("Error while calling or1k_save_context"); return retval; } *reg_list_size = OR1KNUMCOREREGS; /* this is free()'d back in gdb_server.c's gdb_get_register_packet() */ *reg_list = malloc((*reg_list_size) * sizeof(struct reg *)); for (int i = 0; i < OR1KNUMCOREREGS; i++) (*reg_list)[i] = &or1k->core_cache->reg_list[i]; } else { *reg_list_size = or1k->nb_regs; *reg_list = malloc((*reg_list_size) * sizeof(struct reg *)); for (int i = 0; i < or1k->nb_regs; i++) (*reg_list)[i] = &or1k->core_cache->reg_list[i]; } 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 struct reg_cache *or1k_build_reg_cache(struct target *target) { int num_regs = OR1KNUMCOREREGS; struct or1k_common *or1k = target_to_or1k(target); struct reg_cache **cache_p = register_get_last_cache_p(&target->reg_cache); struct reg_cache *cache = malloc(sizeof(struct reg_cache)); struct reg *reg_list = malloc(sizeof(struct reg) * num_regs); struct or1k_core_reg *arch_info = malloc(sizeof(struct or1k_core_reg) * num_regs); int i; /* Build the process context cache */ cache->name = "openrisc 1000 registers"; cache->next = NULL; cache->reg_list = reg_list; cache->num_regs = num_regs; (*cache_p) = cache; or1k->core_cache = cache; for (i = 0; i < num_regs; i++) { arch_info[i] = or1k_core_reg_list_arch_info[i]; arch_info[i].target = target; arch_info[i].or1k_common = or1k; reg_list[i].name = or1k_core_reg_list[i]; reg_list[i].size = 32; reg_list[i].value = calloc(1, 4); reg_list[i].dirty = 0; reg_list[i].valid = 0; reg_list[i].type = &or1k_reg_type; reg_list[i].arch_info = &arch_info[i]; } return cache; }
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_remove_breakpoint(struct target *target, struct breakpoint *breakpoint) { LOG_DEBUG("Removing breakpoint: addr %08x, len %d, type %d, set: %d, id: %d", breakpoint->address, breakpoint->length, breakpoint->type, breakpoint->set, breakpoint->unique_id); struct or1k_common *or1k = target_to_or1k(target); /* 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 */ or1k_jtag_write_memory32(&or1k->jtag, breakpoint->address , 1, (uint32_t*)breakpoint->orig_instr); /* invalidate instruction cache */ or1k_jtag_write_cpu(&or1k->jtag, OR1K_ICBIR_CPU_REG_ADD, 1, &breakpoint->address); return ERROR_OK; }
static int or1k_examine(struct target *target) { uint32_t cpu_cr; struct or1k_common *or1k = target_to_or1k(target); if (!target_was_examined(target)) { target_set_examined(target); /* Do nothing special yet - Julius */ /* avr32_jtag_nexus_read(&ap7k->jtag, AVR32_OCDREG_DID, &devid); LOG_INFO("device id: %08x", devid); avr32_ocd_setbits(&ap7k->jtag, AVR32_OCDREG_DC,OCDREG_DC_DBE); avr32_jtag_nexus_read(&ap7k->jtag, AVR32_OCDREG_DS, &ds); */ /* check for processor halted */ /* Possible specific to Mohor debug interface - others may * have to do something different here. */ or1k_jtag_read_cpu_cr(&or1k->jtag, &cpu_cr); if (cpu_cr & OR1K_MOHORDBGIF_CPU_CR_STALL) { LOG_DEBUG("target is halted"); target->state = TARGET_HALTED; } else target->state = TARGET_RUNNING; } return ERROR_OK; }
static int or1k_add_breakpoint(struct target *target, struct breakpoint *breakpoint) { LOG_DEBUG("Adding breakpoint: addr %08x, len %d, type %d, set: %d, id: %d", breakpoint->address, breakpoint->length, breakpoint->type, breakpoint->set, breakpoint->unique_id); struct or1k_common *or1k = target_to_or1k(target); /* 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 */ or1k_jtag_read_memory32(&or1k->jtag, breakpoint->address , 1, (uint32_t*)breakpoint->orig_instr); /* Sub in the OR1K trap instruction */ uint32_t or1k_trap_insn; /* set correct endianess */ target_buffer_set_u32(target, (uint8_t*)&or1k_trap_insn, OR1K_TRAP_INSTR); or1k_jtag_write_memory32(&or1k->jtag, breakpoint->address , 1, (uint32_t*)&or1k_trap_insn); /* invalidate instruction cache */ or1k_jtag_write_cpu(&or1k->jtag, OR1K_ICBIR_CPU_REG_ADD, 1, &breakpoint->address); return ERROR_OK; }
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_init_target(struct command_context *cmd_ctx, struct target *target) { struct or1k_common *or1k = target_to_or1k(target); or1k->jtag.tap = target->tap; or1k_build_reg_cache(target); return ERROR_OK; }
static int or1k_is_cpu_running(struct target *target, int* running) { struct or1k_common *or1k = target_to_or1k(target); int retval; uint32_t cpu_cr; /* 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. */ int tries = 0; const int RETRIES_MAX = 5; while (tries < RETRIES_MAX) { tries++; /* Specific to Mohor debug interface - others may have to do * something different here. */ retval = or1k_jtag_read_cpu_cr(&or1k->jtag, &cpu_cr); 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."); or1k_jtag_init(&or1k->jtag); LOG_WARNING("attempt %d of %d",tries,RETRIES_MAX); /* TODO: perhaps some sort of time delay here. 1s? */ sleep(1); continue; } else { /* Specific to Mohor debug interface */ *running = !(cpu_cr & OR1K_MOHORDBGIF_CPU_CR_STALL); return retval; } } LOG_WARNING("Could not re-establish communication with target"); return retval; }
static int or1k_read_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) { struct or1k_common *or1k = target_to_or1k(target); LOG_DEBUG("address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" 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)) return ERROR_COMMAND_SYNTAX_ERROR; if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u))) return ERROR_TARGET_UNALIGNED_ACCESS; if (size == 4 && count > 1) return or1k_bulk_read_memory(target, address, count, buffer); switch (size) { case 4: return or1k_jtag_read_memory32(&or1k->jtag, address, count, (uint32_t*)(void *)buffer); break; case 2: return or1k_jtag_read_memory16(&or1k->jtag, address, count, (uint16_t*)(void *)buffer); break; case 1: return or1k_jtag_read_memory8(&or1k->jtag, address, count, buffer); break; default: break; } 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_add_reg(struct target *target, struct or1k_core_reg *new_reg) { struct or1k_common *or1k = target_to_or1k(target); int reg_list_size = or1k->nb_regs * sizeof(struct or1k_core_reg); or1k_core_reg_list_arch_info = realloc(or1k_core_reg_list_arch_info, reg_list_size + sizeof(struct or1k_core_reg)); memcpy(&or1k_core_reg_list_arch_info[or1k->nb_regs], new_reg, sizeof(struct or1k_core_reg)); or1k_core_reg_list_arch_info[or1k->nb_regs].list_num = or1k->nb_regs; or1k->nb_regs++; 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_write_core_reg(struct target *target, int num) { struct or1k_common *or1k = target_to_or1k(target); LOG_DEBUG("-"); if ((num < 0) || (num >= OR1KNUMCOREREGS)) return ERROR_COMMAND_SYNTAX_ERROR; uint32_t reg_value = buf_get_u32(or1k->core_cache->reg_list[num].value, 0, 32); or1k->core_regs[num] = reg_value; LOG_DEBUG("Write 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; return ERROR_OK; }
static int or1k_write_core_reg(struct target *target, int num) { uint32_t reg_value; /* get pointers to arch-specific information */ struct or1k_common *or1k = target_to_or1k(target); if ((num < 0) || (num >= OR1KNUMCOREREGS)) return ERROR_COMMAND_SYNTAX_ERROR; reg_value = buf_get_u32(or1k->core_cache->reg_list[num].value, 0, 32); or1k->core_regs[num] = reg_value; LOG_DEBUG("write core reg %i value 0x%" PRIx32 "", num , reg_value); or1k->core_cache->reg_list[num].valid = 1; or1k->core_cache->reg_list[num].dirty = 0; return ERROR_OK; }
static struct reg_cache *or1k_build_reg_cache(struct target *target) { struct or1k_common *or1k = target_to_or1k(target); struct reg_cache **cache_p = register_get_last_cache_p(&target->reg_cache); struct reg_cache *cache = malloc(sizeof(struct reg_cache)); struct reg *reg_list = calloc(or1k->nb_regs, sizeof(struct reg)); struct or1k_core_reg *arch_info = malloc((or1k->nb_regs) * sizeof(struct or1k_core_reg)); struct reg_feature *feature; LOG_DEBUG("-"); /* Build the process context cache */ cache->name = "OpenRISC 1000 registers"; cache->next = NULL; cache->reg_list = reg_list; cache->num_regs = or1k->nb_regs; (*cache_p) = cache; or1k->core_cache = cache; or1k->arch_info = arch_info; for (int i = 0; i < or1k->nb_regs; i++) { arch_info[i] = or1k_core_reg_list_arch_info[i]; arch_info[i].target = target; arch_info[i].or1k_common = or1k; reg_list[i].name = or1k_core_reg_list_arch_info[i].name; feature = malloc(sizeof(struct reg_feature)); feature->name = or1k_core_reg_list_arch_info[i].feature; reg_list[i].feature = feature; reg_list[i].group = or1k_core_reg_list_arch_info[i].group; reg_list[i].size = 32; reg_list[i].value = calloc(1, 4); reg_list[i].dirty = 0; reg_list[i].valid = 0; reg_list[i].type = &or1k_reg_type; reg_list[i].arch_info = &arch_info[i]; reg_list[i].number = i; reg_list[i].exist = true; } return cache; }
static int or1k_debug_entry(struct target *target) { LOG_DEBUG("-"); int retval = or1k_save_context(target); if (retval != ERROR_OK) { LOG_ERROR("Error while calling or1k_save_context"); return retval; } struct or1k_common *or1k = target_to_or1k(target); uint32_t addr = or1k->core_regs[OR1K_REG_NPC]; if (breakpoint_find(target, addr)) /* Halted on a breakpoint, step back to permit executing the instruction there */ retval = or1k_set_core_reg(&or1k->core_cache->reg_list[OR1K_REG_NPC], (uint8_t *)&addr); return retval; }
static int or1k_halt(struct target *target) { struct or1k_common *or1k = target_to_or1k(target); 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; } } /* Mohor debug unit-specific. */ or1k_jtag_write_cpu_cr(&or1k->jtag, 1, 0); target->debug_reason = DBG_REASON_DBGRQ; return ERROR_OK; }
int or1k_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size) { struct or1k_common *or1k = target_to_or1k(target); int i; LOG_DEBUG(" - "); /* We will have this called whenever GDB connects. */ or1k_save_context(target); *reg_list_size = OR1KNUMCOREREGS; /* this is free()'d back in gdb_server.c's gdb_get_register_packet() */ *reg_list = malloc(sizeof(struct reg*) * (*reg_list_size)); for (i = 0; i < OR1KNUMCOREREGS; i++) (*reg_list)[i] = &or1k->core_cache->reg_list[i]; return ERROR_OK; }
int or1k_restore_context(struct target *target) { int i; LOG_DEBUG(" - "); /* get pointers to arch-specific information */ struct or1k_common *or1k = target_to_or1k(target); for (i = 0; i < OR1KNUMCOREREGS; i++) { if (or1k->core_cache->reg_list[i].dirty) { or1k_write_core_reg(target, i); } } /* write core regs */ or1k_jtag_write_regs(&or1k->jtag, or1k->core_regs); return ERROR_OK; }
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; }