]> git.sur5r.net Git - openocd/blobdiff - src/target/target.c
cortex_a hybrid & context breakpoints
[openocd] / src / target / target.c
index 3a6c6bb42129d5c0f9b9bce86403347cb4f5f74b..be9742f5c2d0dc9d5f9967b899a456e85dfba2b7 100644 (file)
  *   Copyright (C) 2008 by Rick Altherr                                    *
  *   kc8apf@kc8apf.net>                                                    *
  *                                                                         *
+ *   Copyright (C) 2011 by Broadcom Corporation                            *
+ *   Evan Hunter - ehunter@broadcom.com                                    *
+ *                                                                         *
+ *   Copyright (C) ST-Ericsson SA 2011                                     *
+ *   michel.jaouen@stericsson.com : smp minimum support                    *
+ *                                                                         *
  *   This program is free software; you can redistribute it and/or modify  *
  *   it under the terms of the GNU General Public License as published by  *
  *   the Free Software Foundation; either version 2 of the License, or     *
 #include "register.h"
 #include "trace.h"
 #include "image.h"
+#include "rtos/rtos.h"
 
 
+static int target_read_buffer_default(struct target *target, uint32_t address,
+               uint32_t size, uint8_t *buffer);
+static int target_write_buffer_default(struct target *target, uint32_t address,
+               uint32_t size, const uint8_t *buffer);
 static int target_array2mem(Jim_Interp *interp, struct target *target,
                int argc, Jim_Obj *const *argv);
 static int target_mem2array(Jim_Interp *interp, struct target *target,
@@ -66,11 +77,11 @@ extern struct target_type dragonite_target;
 extern struct target_type xscale_target;
 extern struct target_type cortexm3_target;
 extern struct target_type cortexa8_target;
-extern struct target_type cortexa9_target;
 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 testee_target;
 extern struct target_type avr32_ap7k_target;
 
@@ -89,11 +100,11 @@ static struct target_type *target_types[] =
        &xscale_target,
        &cortexm3_target,
        &cortexa8_target,
-       &cortexa9_target,
        &arm11_target,
        &mips_m4k_target,
        &avr_target,
        &dsp563xx_target,
+       &dsp5680xx_target,
        &testee_target,
        &avr32_ap7k_target,
        NULL,
@@ -337,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)
 {
@@ -613,7 +656,7 @@ const char *target_type_name(struct target *target)
        return target->type->name;
 }
 
-static int target_write_memory_imp(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
+static int target_write_memory_imp(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer)
 {
        if (!target_was_examined(target))
        {
@@ -703,19 +746,19 @@ static int target_read_phys_memory(struct target *target,
 }
 
 int target_write_memory(struct target *target,
-               uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
+               uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer)
 {
        return target->type->write_memory(target, address, size, count, buffer);
 }
 
 static int target_write_phys_memory(struct target *target,
-               uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
+               uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer)
 {
        return target->type->write_phys_memory(target, address, size, count, buffer);
 }
 
 int target_bulk_write_memory(struct target *target,
-               uint32_t address, uint32_t count, uint8_t *buffer)
+               uint32_t address, uint32_t count, const uint8_t *buffer)
 {
        return target->type->bulk_write_memory(target, address, count, buffer);
 }
@@ -723,12 +766,33 @@ int target_bulk_write_memory(struct target *target,
 int target_add_breakpoint(struct target *target,
                struct breakpoint *breakpoint)
 {
-       if (target->state != TARGET_HALTED) {
+       if ((target->state != TARGET_HALTED)&&(breakpoint->type!=BKPT_HARD)) {
                LOG_WARNING("target %s is not halted", target->cmd_name);
                return ERROR_TARGET_NOT_HALTED;
        }
        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)
 {
@@ -781,7 +845,7 @@ err_read_phys_memory(struct target *target, uint32_t address,
 
 static int
 err_write_phys_memory(struct target *target, uint32_t address,
-               uint32_t size, uint32_t count, uint8_t *buffer)
+               uint32_t size, uint32_t count, const uint8_t *buffer)
 {
        LOG_ERROR("Not implemented: %s", __func__);
        return ERROR_FAIL;
@@ -865,6 +929,13 @@ static int target_init_one(struct command_context *cmd_ctx,
                type->read_phys_memory = type->read_memory;
                type->virt2phys = identity_virt2phys;
        }
+
+       if (target->type->read_buffer == NULL)
+               target->type->read_buffer = target_read_buffer_default;
+
+       if (target->type->write_buffer == NULL)
+               target->type->write_buffer = target_write_buffer_default;
+
        return ERROR_OK;
 }
 
@@ -1331,9 +1402,8 @@ int target_arch_state(struct target *target)
  * mode respectively, otherwise data is handled as quickly as
  * possible
  */
-int target_write_buffer(struct target *target, uint32_t address, uint32_t size, uint8_t *buffer)
+int target_write_buffer(struct target *target, uint32_t address, uint32_t size, const uint8_t *buffer)
 {
-       int retval;
        LOG_DEBUG("writing buffer of %i byte at 0x%8.8x",
                  (int)size, (unsigned)address);
 
@@ -1356,6 +1426,13 @@ int target_write_buffer(struct target *target, uint32_t address, uint32_t size,
                return ERROR_FAIL;
        }
 
+       return target->type->write_buffer(target, address, size, buffer);
+}
+
+static int target_write_buffer_default(struct target *target, uint32_t address, uint32_t size, const uint8_t *buffer)
+{
+       int retval = ERROR_OK;
+
        if (((address % 2) == 0) && (size == 2))
        {
                return target_write_memory(target, address, 2, 1, buffer);
@@ -1406,7 +1483,7 @@ int target_write_buffer(struct target *target, uint32_t address, uint32_t size,
                        return retval;
        }
 
-       return ERROR_OK;
+       return retval;
 }
 
 /* Single aligned words are guaranteed to use 16 or 32 bit access
@@ -1415,7 +1492,6 @@ int target_write_buffer(struct target *target, uint32_t address, uint32_t size,
  */
 int target_read_buffer(struct target *target, uint32_t address, uint32_t size, uint8_t *buffer)
 {
-       int retval;
        LOG_DEBUG("reading buffer of %i byte at 0x%8.8x",
                          (int)size, (unsigned)address);
 
@@ -1438,6 +1514,13 @@ int target_read_buffer(struct target *target, uint32_t address, uint32_t size, u
                return ERROR_FAIL;
        }
 
+       return target->type->read_buffer(target, address, size, buffer);
+}
+
+static int target_read_buffer_default(struct target *target, uint32_t address, uint32_t size, uint8_t *buffer)
+{
+       int retval = ERROR_OK;
+
        if (((address % 2) == 0) && (size == 2))
        {
                return target_read_memory(target, address, 2, 1, buffer);
@@ -1522,7 +1605,7 @@ int target_checksum_memory(struct target *target, uint32_t address, uint32_t siz
                        return retval;
                }
 
-               /* convert to target endianess */
+               /* convert to target endianness */
                for (i = 0; i < (size/sizeof(uint32_t)); i++)
                {
                        uint32_t target_data;
@@ -2369,10 +2452,10 @@ COMMAND_HANDLER(handle_md_command)
 }
 
 typedef int (*target_write_fn)(struct target *target,
-               uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer);
+               uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer);
 
 static int target_write_memory_fast(struct target *target,
-               uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
+               uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer)
 {
        return target_write_buffer(target, address, size * count, buffer);
 }
@@ -2857,7 +2940,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);
@@ -2865,9 +2948,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;
@@ -2876,43 +2972,90 @@ 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);
-       else
-               LOG_ERROR("Failure setting breakpoint");
-       return retval;
+       
+               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
+               {       
+                       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 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)
@@ -3682,6 +3825,8 @@ enum target_cfg_param {
        TCFG_VARIANT,
        TCFG_COREID,
        TCFG_CHAIN_POSITION,
+       TCFG_DBGBASE,
+       TCFG_RTOS,
 };
 
 static Jim_Nvp nvp_config_opts[] = {
@@ -3695,7 +3840,8 @@ static Jim_Nvp nvp_config_opts[] = {
        { .name = "-variant",          .value = TCFG_VARIANT },
        { .name = "-coreid",           .value = TCFG_COREID },
        { .name = "-chain-position",   .value = TCFG_CHAIN_POSITION },
-
+       { .name = "-dbgbase",          .value = TCFG_DBGBASE },
+       { .name = "-rtos",             .value = TCFG_RTOS },
        { .name = NULL, .value = -1 }
 };
 
@@ -3903,6 +4049,7 @@ static int target_configure(Jim_GetOptInfo *goi, struct target *target)
                        /* loop for more e*/
                        break;
 
+
                case TCFG_ENDIAN:
                        if (goi->isconfigure) {
                                e = Jim_GetOpt_Nvp(goi, nvp_target_endian, &n);
@@ -3953,7 +4100,7 @@ static int target_configure(Jim_GetOptInfo *goi, struct target *target)
                                if (e != JIM_OK) {
                                        return e;
                                }
-                               target->coreid = (int)w;
+                               target->coreid = (int32_t)w;
                        } else {
                                if (goi->argc != 0) {
                                        goto no_params;
@@ -3986,6 +4133,34 @@ static int target_configure(Jim_GetOptInfo *goi, struct target *target)
                        Jim_SetResultString(goi->interp, target->tap->dotted_name, -1);
                        /* loop for more e*/
                        break;
+               case TCFG_DBGBASE:
+                       if (goi->isconfigure) {
+                               e = Jim_GetOpt_Wide(goi, &w);
+                               if (e != JIM_OK) {
+                                       return e;
+                               }
+                               target->dbgbase = (uint32_t)w;
+                               target->dbgbase_set = true;
+                       } else {
+                               if (goi->argc != 0) {
+                                       goto no_params;
+                               }
+                       }
+                       Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->dbgbase));
+                       /* loop for more */
+                       break;
+
+               case TCFG_RTOS:
+                       /* RTOS */
+                       {
+                               int result = rtos_create( goi, target );
+                               if ( result != JIM_OK )
+                               {
+                                       return result;
+                               }
+                       }
+                       /* loop for more */
+                       break;
                }
        } /* while (goi->argc) */
 
@@ -4708,6 +4883,9 @@ static int target_create(Jim_GetOptInfo *goi)
 
        target->endianness = TARGET_ENDIAN_UNKNOWN;
 
+       target->rtos = NULL;
+       target->rtos_auto_detect = false;
+
        /* Do the rest as "configure" options */
        goi->isconfigure = 1;
        e = target_configure(goi, target);
@@ -4834,6 +5012,61 @@ static int jim_target_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
        return JIM_OK;
 }
 
+static int jim_target_smp(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+       int i;
+       const char *targetname;
+       int retval,len;
+       struct target *target;
+       struct target_list *head, *curr, *new;
+    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[3] ...
+        */
+
+       for(i=1;i<argc;i++)
+       {
+
+               targetname = Jim_GetString(argv[i], &len);
+               target = get_target(targetname);
+               LOG_DEBUG("%s ",targetname);
+               if (target)
+               {
+                       new=malloc(sizeof(struct target_list));
+                       new->target = target;
+                       new->next = (struct target_list*)NULL;
+                       if (head == (struct target_list*)NULL)
+                       {
+                               head = new;
+                               curr = head;
+                       }
+                       else
+                       {
+                               curr->next = new;
+                               curr = new;
+                       }
+               }
+       }
+    /*  now parse the list of cpu and put the target in smp mode*/
+       curr=head;
+
+    while(curr!=(struct target_list *)NULL)
+       {
+    target=curr->target;
+       target->smp = 1;
+       target->head = head;
+       curr=curr->next;
+       }
+       return retval; 
+}
+
+
 static int jim_target_create(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
 {
        Jim_GetOptInfo goi;
@@ -4949,6 +5182,14 @@ static const struct command_registration target_subcommand_handlers[] = {
                .help = "Returns the number of targets as an integer "
                        "(DEPRECATED)",
        },
+       {
+               .name = "smp",
+               .mode = COMMAND_ANY,
+               .jim_handler = jim_target_smp,
+               .usage = "targetname1 targetname2 ...",
+               .help = "gather several target in a smp list"
+       },
+
        COMMAND_REGISTRATION_DONE
 };
 
@@ -5307,7 +5548,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 <address> [<asid>]<length> ['hw'|'hw_ctx']",
        },
        {
                .name = "rbp",