X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Ftarget%2Ftarget.c;h=4708a1d626bb271a4a09826dfdc7cfcc29c21acc;hb=566faa17de575ff58beffbc4a8961bf3f8199b93;hp=03431560f57cd89724937794aa749a93ffef17a6;hpb=7d2bf8805df5ec9f108758188e85f2d355f720c4;p=openocd.git diff --git a/src/target/target.c b/src/target/target.c index 03431560f5..4708a1d626 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -348,6 +348,38 @@ static void target_buffer_set_u8(struct target *target, uint8_t *buffer, uint8_t *buffer = value; } +/* write a uint32_t array to a buffer in target memory endianness */ +void target_buffer_get_u32_array(struct target *target, const uint8_t *buffer, uint32_t count, uint32_t *dstbuf) +{ + uint32_t i; + for(i = 0; i < count; i ++) + dstbuf[i] = target_buffer_get_u32(target,&buffer[i*4]); +} + +/* write a uint16_t array to a buffer in target memory endianness */ +void target_buffer_get_u16_array(struct target *target, const uint8_t *buffer, uint32_t count, uint16_t *dstbuf) +{ + uint32_t i; + for(i = 0; i < count; i ++) + dstbuf[i] = target_buffer_get_u16(target,&buffer[i*2]); +} + +/* write a uint32_t array to a buffer in target memory endianness */ +void target_buffer_set_u32_array(struct target *target, uint8_t *buffer, uint32_t count, uint32_t *srcbuf) +{ + uint32_t i; + for(i = 0; i < count; i ++) + target_buffer_set_u32(target,&buffer[i*4],srcbuf[i]); +} + +/* write a uint16_t array to a buffer in target memory endianness */ +void target_buffer_set_u16_array(struct target *target, uint8_t *buffer, uint32_t count, uint16_t *srcbuf) +{ + uint32_t i; + for(i = 0; i < count; i ++) + target_buffer_set_u16(target,&buffer[i*2],srcbuf[i]); +} + /* return a pointer to a configured target; id is name or number */ struct target *get_target(const char *id) { @@ -700,6 +732,81 @@ done: return retval; } +/** + * Downloads a target-specific native code algorithm to the target, + * executes and leaves it running. + * + * @param target used to run the algorithm + * @param arch_info target-specific description of the algorithm. + */ +int target_start_algorithm(struct target *target, + int num_mem_params, struct mem_param *mem_params, + int num_reg_params, struct reg_param *reg_params, + uint32_t entry_point, uint32_t exit_point, + void *arch_info) +{ + int retval = ERROR_FAIL; + + if (!target_was_examined(target)) + { + LOG_ERROR("Target not examined yet"); + goto done; + } + if (!target->type->start_algorithm) { + LOG_ERROR("Target type '%s' does not support %s", + target_type_name(target), __func__); + goto done; + } + if (target->running_alg) { + LOG_ERROR("Target is already running an algorithm"); + goto done; + } + + target->running_alg = true; + retval = target->type->start_algorithm(target, + num_mem_params, mem_params, + num_reg_params, reg_params, + entry_point, exit_point, arch_info); + +done: + return retval; +} + +/** + * Waits for an algorithm started with target_start_algorithm() to complete. + * + * @param target used to run the algorithm + * @param arch_info target-specific description of the algorithm. + */ +int target_wait_algorithm(struct target *target, + int num_mem_params, struct mem_param *mem_params, + int num_reg_params, struct reg_param *reg_params, + uint32_t exit_point, int timeout_ms, + void *arch_info) +{ + int retval = ERROR_FAIL; + + if (!target->type->wait_algorithm) { + LOG_ERROR("Target type '%s' does not support %s", + target_type_name(target), __func__); + goto done; + } + if (!target->running_alg) { + LOG_ERROR("Target is not running an algorithm"); + goto done; + } + + retval = target->type->wait_algorithm(target, + num_mem_params, mem_params, + num_reg_params, reg_params, + exit_point, timeout_ms, arch_info); + if (retval != ERROR_TARGET_TIMEOUT) + target->running_alg = false; + +done: + return retval; +} + int target_read_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) @@ -740,6 +847,27 @@ int target_add_breakpoint(struct target *target, } return target->type->add_breakpoint(target, breakpoint); } + +int target_add_context_breakpoint(struct target *target, + struct breakpoint *breakpoint) +{ + if (target->state != TARGET_HALTED) { + LOG_WARNING("target %s is not halted", target->cmd_name); + return ERROR_TARGET_NOT_HALTED; + } + return target->type->add_context_breakpoint(target, breakpoint); +} + +int target_add_hybrid_breakpoint(struct target *target, + struct breakpoint *breakpoint) +{ + if (target->state != TARGET_HALTED) { + LOG_WARNING("target %s is not halted", target->cmd_name); + return ERROR_TARGET_NOT_HALTED; + } + return target->type->add_hybrid_breakpoint(target, breakpoint); +} + int target_remove_breakpoint(struct target *target, struct breakpoint *breakpoint) { @@ -1733,30 +1861,38 @@ int target_write_u8(struct target *target, uint32_t address, uint8_t value) return retval; } -COMMAND_HANDLER(handle_targets_command) +static int find_target(struct command_context *cmd_ctx, const char *name) { - struct target *target = all_targets; + struct target *target = get_target(name); + if (target == NULL) { + LOG_ERROR("Target: %s is unknown, try one of:\n", name); + return ERROR_FAIL; + } + if (!target->tap->enabled) { + LOG_USER("Target: TAP %s is disabled, " + "can't be the current target\n", + target->tap->dotted_name); + return ERROR_FAIL; + } + cmd_ctx->current_target = target->target_number; + return ERROR_OK; +} + + +COMMAND_HANDLER(handle_targets_command) +{ + int retval = ERROR_OK; if (CMD_ARGC == 1) { - target = get_target(CMD_ARGV[0]); - if (target == NULL) { - command_print(CMD_CTX,"Target: %s is unknown, try one of:\n", CMD_ARGV[0]); - goto DumpTargets; - } - if (!target->tap->enabled) { - command_print(CMD_CTX,"Target: TAP %s is disabled, " - "can't be the current target\n", - target->tap->dotted_name); - return ERROR_FAIL; + retval = find_target(CMD_CTX, CMD_ARGV[0]); + if (retval == ERROR_OK) { + /* we're done! */ + return retval; } - - CMD_CTX->current_target = target->target_number; - return ERROR_OK; } -DumpTargets: - target = all_targets; + struct target *target = all_targets; command_print(CMD_CTX, " TargetName Type Endian TapName State "); command_print(CMD_CTX, "-- ------------------ ---------- ------ ------------------ ------------"); while (target) @@ -1773,19 +1909,20 @@ DumpTargets: marker = '*'; /* keep columns lined up to match the headers above */ - command_print(CMD_CTX, "%2d%c %-18s %-10s %-6s %-18s %s", - target->target_number, - marker, - target_name(target), - target_type_name(target), - Jim_Nvp_value2name_simple(nvp_target_endian, - target->endianness)->name, - target->tap->dotted_name, - state); + command_print(CMD_CTX, + "%2d%c %-18s %-10s %-6s %-18s %s", + target->target_number, + marker, + target_name(target), + target_type_name(target), + Jim_Nvp_value2name_simple(nvp_target_endian, + target->endianness)->name, + target->tap->dotted_name, + state); target = target->next; } - return ERROR_OK; + return retval; } /* every 300ms we check for reset & powerdropout and issue a "reset halt" if so. */ @@ -2062,6 +2199,8 @@ COMMAND_HANDLER(handle_reg_command) } } + assert(reg != NULL); /* give clang a hint that we *know* reg is != NULL here */ + /* display a register */ if ((CMD_ARGC == 1) || ((CMD_ARGC == 2) && !((CMD_ARGV[1][0] >= '0') && (CMD_ARGV[1][0] <= '9')))) { @@ -2082,6 +2221,8 @@ COMMAND_HANDLER(handle_reg_command) if (CMD_ARGC == 2) { uint8_t *buf = malloc(DIV_ROUND_UP(reg->size, 8)); + if (buf == NULL) + return ERROR_FAIL; str_to_buf(CMD_ARGV[1], strlen(CMD_ARGV[1]), buf, reg->size, 0); reg->type->set(reg, buf); @@ -2887,7 +3028,7 @@ static int handle_bp_command_list(struct command_context *cmd_ctx) { char* buf = buf_to_str(breakpoint->orig_instr, breakpoint->length, 16); - command_print(cmd_ctx, "0x%8.8" PRIx32 ", 0x%x, %i, 0x%s", + command_print(cmd_ctx, "IVA breakpoint: 0x%8.8" PRIx32 ", 0x%x, %i, 0x%s", breakpoint->address, breakpoint->length, breakpoint->set, buf); @@ -2895,9 +3036,22 @@ static int handle_bp_command_list(struct command_context *cmd_ctx) } else { - command_print(cmd_ctx, "0x%8.8" PRIx32 ", 0x%x, %i", - breakpoint->address, - breakpoint->length, breakpoint->set); + if ((breakpoint->address == 0) && (breakpoint->asid != 0)) + command_print(cmd_ctx, "Context breakpoint: 0x%8.8" PRIx32 ", 0x%x, %i", + breakpoint->asid, + breakpoint->length, breakpoint->set); + else if ((breakpoint->address != 0) && (breakpoint->asid != 0)) + { + command_print(cmd_ctx, "Hybrid breakpoint(IVA): 0x%8.8" PRIx32 ", 0x%x, %i", + breakpoint->address, + breakpoint->length, breakpoint->set); + command_print(cmd_ctx, "\t|--->linked with ContextID: 0x%8.8" PRIx32, + breakpoint->asid); + } + else + command_print(cmd_ctx, "Breakpoint(IVA): 0x%8.8" PRIx32 ", 0x%x, %i", + breakpoint->address, + breakpoint->length, breakpoint->set); } breakpoint = breakpoint->next; @@ -2906,43 +3060,94 @@ static int handle_bp_command_list(struct command_context *cmd_ctx) } static int handle_bp_command_set(struct command_context *cmd_ctx, - uint32_t addr, uint32_t length, int hw) + uint32_t addr, uint32_t asid, uint32_t length, int hw) { struct target *target = get_current_target(cmd_ctx); - int retval = breakpoint_add(target, addr, length, hw); - if (ERROR_OK == retval) - command_print(cmd_ctx, "breakpoint set at 0x%8.8" PRIx32 "", addr); + + if (asid == 0) + { + int retval = breakpoint_add(target, addr, length, hw); + if (ERROR_OK == retval) + command_print(cmd_ctx, "breakpoint set at 0x%8.8" PRIx32 "", addr); + else + { + LOG_ERROR("Failure setting breakpoint, the same address(IVA) is already used"); + return retval; + } + } + else if (addr == 0) + { + int retval = context_breakpoint_add(target, asid, length, hw); + if (ERROR_OK == retval) + command_print(cmd_ctx, "Context breakpoint set at 0x%8.8" PRIx32 "", asid); + else + { + LOG_ERROR("Failure setting breakpoint, the same address(CONTEXTID) is already used"); + return retval; + } + } else - LOG_ERROR("Failure setting breakpoint"); - return retval; + { + int retval = hybrid_breakpoint_add(target, addr, asid, length, hw); + if(ERROR_OK == retval) + command_print(cmd_ctx, "Hybrid breakpoint set at 0x%8.8" PRIx32 "", asid); + else + { + LOG_ERROR("Failure setting breakpoint, the same address is already used"); + return retval; + } + } + return ERROR_OK; } COMMAND_HANDLER(handle_bp_command) { - if (CMD_ARGC == 0) - return handle_bp_command_list(CMD_CTX); - - if (CMD_ARGC < 2 || CMD_ARGC > 3) - { - command_print(CMD_CTX, "usage: bp
['hw']"); - return ERROR_COMMAND_SYNTAX_ERROR; - } - uint32_t addr; - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr); + uint32_t asid; uint32_t length; - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length); - int hw = BKPT_SOFT; - if (CMD_ARGC == 3) + switch(CMD_ARGC) { - if (strcmp(CMD_ARGV[2], "hw") == 0) + case 0: + return handle_bp_command_list(CMD_CTX); + + case 2: + asid = 0; + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr); + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length); + return handle_bp_command_set(CMD_CTX, addr, asid, length, hw); + + case 3: + if(strcmp(CMD_ARGV[2], "hw") == 0) + { + hw = BKPT_HARD; + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr); + + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length); + + asid = 0; + return handle_bp_command_set(CMD_CTX, addr, asid, length, hw); + } + else if(strcmp(CMD_ARGV[2], "hw_ctx") == 0) + { + hw = BKPT_HARD; + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], asid); + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length); + addr = 0; + return handle_bp_command_set(CMD_CTX, addr, asid, length, hw); + } + + case 4: hw = BKPT_HARD; - else + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr); + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], asid); + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], length); + return handle_bp_command_set(CMD_CTX, addr, asid, length, hw); + + default: + command_print(CMD_CTX, "usage: bp
[] ['hw'|'hw_ctx']"); return ERROR_COMMAND_SYNTAX_ERROR; } - - return handle_bp_command_set(CMD_CTX, addr, length, hw); } COMMAND_HANDLER(handle_rbp_command) @@ -3125,7 +3330,8 @@ static void writeGmon(uint32_t *samples, uint32_t sampleNum, const char *filenam } } - int addressSpace = (max-min + 1); + int addressSpace = (max - min + 1); + assert(addressSpace >= 2); static const uint32_t maxBuckets = 16 * 1024; /* maximum buckets. */ uint32_t length = addressSpace; @@ -3221,9 +3427,9 @@ COMMAND_HANDLER(handle_profile_command) /* hopefully it is safe to cache! We want to stop/restart as quickly as possible. */ struct reg *reg = register_get_by_name(target->reg_cache, "pc", 1); + int retval = ERROR_OK; for (;;) { - int retval; target_poll(target); if (target->state == TARGET_HALTED) { @@ -3276,7 +3482,7 @@ COMMAND_HANDLER(handle_profile_command) } free(samples); - return ERROR_OK; + return retval; } static int new_int_array_element(Jim_Interp * interp, const char *varname, int idx, uint32_t val) @@ -3441,7 +3647,7 @@ static int target_mem2array(Jim_Interp *interp, struct target *target, int argc, Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: cannot read memory", NULL); e = JIM_ERR; - len = 0; + break; } else { v = 0; /* shut up gcc */ for (i = 0 ;i < count ;i++, n++) { @@ -3466,7 +3672,7 @@ static int target_mem2array(Jim_Interp *interp, struct target *target, int argc, Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - return JIM_OK; + return e; } static int get_int_array_element(Jim_Interp * interp, const char *varname, int idx, uint32_t *val) @@ -3651,7 +3857,7 @@ static int target_array2mem(Jim_Interp *interp, struct target *target, Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); Jim_AppendStrings(interp, Jim_GetResult(interp), "array2mem: cannot read memory", NULL); e = JIM_ERR; - len = 0; + break; } } @@ -3659,7 +3865,7 @@ static int target_array2mem(Jim_Interp *interp, struct target *target, Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - return JIM_OK; + return e; } /* FIX? should we propagate errors here rather than printing them @@ -3971,6 +4177,8 @@ static int target_configure(Jim_GetOptInfo *goi, struct target *target) free((void *)(target->variant)); } e = Jim_GetOpt_String(goi, &cp, NULL); + if (e != JIM_OK) + return e; target->variant = strdup(cp); } else { if (goi->argc != 0) { @@ -4696,6 +4904,8 @@ static int target_create(Jim_GetOptInfo *goi) /* TYPE */ e = Jim_GetOpt_String(goi, &cp2, NULL); + if (e != JIM_OK) + return e; cp = cp2; /* now does target type exist */ for (x = 0 ; target_types[x] ; x++) { @@ -4905,15 +5115,14 @@ static int jim_target_smp(Jim_Interp *interp, int argc, Jim_Obj *const *argv) const char *targetname; int retval,len; struct target *target; - struct target_list *head, *curr, *new; + struct target_list *head, *curr; curr = (struct target_list*) NULL; head = (struct target_list*) NULL; - new = (struct target_list*) NULL; - + retval = 0; LOG_DEBUG("%d",argc); /* argv[1] = target to associate in smp - * argv[2] = target to assoicate in smp + * argv[2] = target to assoicate in smp * argv[3] ... */ @@ -4925,6 +5134,7 @@ static int jim_target_smp(Jim_Interp *interp, int argc, Jim_Obj *const *argv) LOG_DEBUG("%s ",targetname); if (target) { + struct target_list *new; new=malloc(sizeof(struct target_list)); new->target = target; new->next = (struct target_list*)NULL; @@ -4950,7 +5160,7 @@ static int jim_target_smp(Jim_Interp *interp, int argc, Jim_Obj *const *argv) target->head = head; curr=curr->next; } - return retval; + return retval; } @@ -5435,7 +5645,7 @@ static const struct command_registration target_exec_command_handlers[] = { .handler = handle_bp_command, .mode = COMMAND_EXEC, .help = "list or set hardware or software breakpoint", - .usage = "[address length ['hw']]", + .usage = "usage: bp
[] ['hw'|'hw_ctx']", }, { .name = "rbp",