retire ERROR_INVALID_ARGUMENTS and replace with ERROR_COMMAND_SYNTAX_ERROR
[fw/openocd] / src / target / target.c
index f62915ef35ebb21240160786706c849bebb888b0..eca69cf68629386effe2cc408c53a8b290baf737 100644 (file)
@@ -81,9 +81,10 @@ extern struct target_type arm11_target;
 extern struct target_type mips_m4k_target;
 extern struct target_type avr_target;
 extern struct target_type dsp563xx_target;
-//extern struct target_type dsp5680xx_target;
+extern struct target_type dsp5680xx_target;
 extern struct target_type testee_target;
 extern struct target_type avr32_ap7k_target;
+extern struct target_type stm32_stlink_target;
 
 static struct target_type *target_types[] =
 {
@@ -104,10 +105,10 @@ static struct target_type *target_types[] =
        &mips_m4k_target,
        &avr_target,
        &dsp563xx_target,
-// Disabled for now, it generates warnings
-//     &dsp5680xx_target,
+       &dsp5680xx_target,
        &testee_target,
        &avr32_ap7k_target,
+       &stm32_stlink_target,
        NULL,
 };
 
@@ -349,6 +350,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)
 {
@@ -701,6 +734,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)
@@ -741,6 +849,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)
 {
@@ -813,6 +942,8 @@ static int target_init_one(struct command_context *cmd_ctx,
        if (type->check_reset== NULL)
                type->check_reset = default_check_reset;
 
+       assert(type->init_target != NULL);
+
        int retval = type->init_target(cmd_ctx, target);
        if (ERROR_OK != retval)
        {
@@ -916,6 +1047,8 @@ static int target_init(struct command_context *cmd_ctx)
 
 COMMAND_HANDLER(handle_target_init_command)
 {
+       int retval;
+
        if (CMD_ARGC != 0)
                return ERROR_COMMAND_SYNTAX_ERROR;
 
@@ -927,6 +1060,10 @@ COMMAND_HANDLER(handle_target_init_command)
        }
        target_initialized = true;
 
+       retval = command_run_line(CMD_CTX, "init_targets");
+       if (ERROR_OK != retval)
+               return retval;
+
        LOG_DEBUG("Initializing targets...");
        return target_init(CMD_CTX);
 }
@@ -937,7 +1074,7 @@ int target_register_event_callback(int (*callback)(struct target *target, enum t
 
        if (callback == NULL)
        {
-               return ERROR_INVALID_ARGUMENTS;
+               return ERROR_COMMAND_SYNTAX_ERROR;
        }
 
        if (*callbacks_p)
@@ -962,7 +1099,7 @@ int target_register_timer_callback(int (*callback)(void *priv), int time_ms, int
 
        if (callback == NULL)
        {
-               return ERROR_INVALID_ARGUMENTS;
+               return ERROR_COMMAND_SYNTAX_ERROR;
        }
 
        if (*callbacks_p)
@@ -1000,7 +1137,7 @@ int target_unregister_event_callback(int (*callback)(struct target *target, enum
 
        if (callback == NULL)
        {
-               return ERROR_INVALID_ARGUMENTS;
+               return ERROR_COMMAND_SYNTAX_ERROR;
        }
 
        while (c)
@@ -1027,7 +1164,7 @@ static int target_unregister_timer_callback(int (*callback)(void *priv), void *p
 
        if (callback == NULL)
        {
-               return ERROR_INVALID_ARGUMENTS;
+               return ERROR_COMMAND_SYNTAX_ERROR;
        }
 
        while (c)
@@ -1544,7 +1681,7 @@ int target_checksum_memory(struct target *target, uint32_t address, uint32_t siz
                if (buffer == NULL)
                {
                        LOG_ERROR("error allocating buffer for section (%d bytes)", (int)size);
-                       return ERROR_INVALID_ARGUMENTS;
+                       return ERROR_COMMAND_SYNTAX_ERROR;
                }
                retval = target_read_buffer(target, address, size, buffer);
                if (retval != ERROR_OK)
@@ -1734,30 +1871,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)
@@ -1774,19 +1919,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. */
@@ -2063,6 +2209,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'))))
        {
@@ -2083,6 +2231,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);
@@ -2888,7 +3038,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);
@@ -2896,9 +3046,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;
@@ -2907,43 +3070,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 <address> <length> ['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 <address> [<asid>]<length> ['hw'|'hw_ctx']");
                        return ERROR_COMMAND_SYNTAX_ERROR;
        }
-
-       return handle_bp_command_set(CMD_CTX, addr, length, hw);
 }
 
 COMMAND_HANDLER(handle_rbp_command)
@@ -3126,7 +3340,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;
@@ -3222,9 +3437,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)
                {
@@ -3277,7 +3492,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)
@@ -3442,7 +3657,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++) {
@@ -3467,7 +3682,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)
@@ -3652,7 +3867,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;
                }
        }
 
@@ -3660,7 +3875,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
@@ -3972,6 +4187,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) {
@@ -4697,6 +4914,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++) {
@@ -4906,15 +5125,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] ...
         */
 
@@ -4926,6 +5144,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;
@@ -4951,7 +5170,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;
 }
 
 
@@ -5315,11 +5534,13 @@ static const struct command_registration target_exec_command_handlers[] = {
                .mode = COMMAND_EXEC,
                .help = "loads active fast load image to current target "
                        "- mainly for profiling purposes",
+               .usage = "",
        },
        {
                .name = "profile",
                .handler = handle_profile_command,
                .mode = COMMAND_EXEC,
+               .usage = "seconds filename",
                .help = "profiling samples the CPU PC",
        },
        /** @todo don't register virt2phys() unless target supports it */
@@ -5380,6 +5601,7 @@ static const struct command_registration target_exec_command_handlers[] = {
                .name = "soft_reset_halt",
                .handler = handle_soft_reset_halt_command,
                .mode = COMMAND_EXEC,
+               .usage = "",
                .help = "halt the target and do a soft reset",
        },
        {
@@ -5436,7 +5658,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 = "<address> [<asid>]<length> ['hw'|'hw_ctx']",
        },
        {
                .name = "rbp",