This is an automated email from Gerrit. Andreas Fritiofson ([email protected]) just uploaded a new patch set to Gerrit, which you can find at http://openocd.zylin.com/1685
-- gerrit commit 7bff20291d3f9938bce58c3741a5b7d5ace05d00 Author: Andreas Fritiofson <[email protected]> Date: Sat Oct 5 00:19:08 2013 +0200 arm7_9: Avoid infinite loops in bulk write dispatching Add a mandatory field in struct arm7_9_common for regular, non-optimized memory writes. Together with the existing bulk_memory_write field, this allows variants to select any combination of implementations for regular and bulk writes, without risking infinite loops from accidentally using bulk writes for implementing bulk writes. ARM 7/9 targets may now select arm7_9_memory_write_opt as their target.write_memory implementation, which will dispatch to arm7_9_common.bulk_write_memory if possible, or fallback to arm7_9_common.write_memory otherwise. To avoid loops, bulk write implementations mustn't call any other functions than arm7_9_write_memory_no_opt() to write memory; it will unconditionally call arm7_9_common.write_memory. If they fail, they should simply return error to allow the caller to fallback to regular writes. Tested on a regular ARM7TDMI only. Change-Id: Iae42a6e093e2df68c4823c927d757ae8f42ef388 Signed-off-by: Andreas Fritiofson <[email protected]> diff --git a/src/target/arm7_9_common.c b/src/target/arm7_9_common.c index 6eade96..7687466 100644 --- a/src/target/arm7_9_common.c +++ b/src/target/arm7_9_common.c @@ -2476,11 +2476,28 @@ int arm7_9_write_memory_opt(struct target *target, const uint8_t *buffer) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); + int retval; - if (size == 4 && count > 32 && arm7_9->bulk_write_memory) - return arm7_9->bulk_write_memory(target, address, count, buffer); - else - return arm7_9_write_memory(target, address, size, count, buffer); + if (size == 4 && count > 32 && arm7_9->bulk_write_memory) { + /* Attempt to do a bulk write */ + retval = arm7_9->bulk_write_memory(target, address, count, buffer); + + if (retval == ERROR_OK) + return ERROR_OK; + } + + return arm7_9->write_memory(target, address, size, count, buffer); +} + +int arm7_9_write_memory_no_opt(struct target *target, + uint32_t address, + uint32_t size, + uint32_t count, + const uint8_t *buffer) +{ + struct arm7_9_common *arm7_9 = target_to_arm7_9(target); + + return arm7_9->write_memory(target, address, size, count, buffer); } static int dcc_count; @@ -2561,8 +2578,11 @@ int arm7_9_bulk_write_memory(struct target *target, struct arm7_9_common *arm7_9 = target_to_arm7_9(target); int i; + if (address % 4 != 0) + return ERROR_TARGET_UNALIGNED_ACCESS; + if (!arm7_9->dcc_downloads) - return target_write_memory(target, address, 4, count, buffer); + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; /* regrab previously allocated working_area, or allocate a new one */ if (!arm7_9->dcc_working_area) { @@ -2571,15 +2591,16 @@ int arm7_9_bulk_write_memory(struct target *target, /* make sure we have a working area */ if (target_alloc_working_area(target, 24, &arm7_9->dcc_working_area) != ERROR_OK) { LOG_INFO("no working area available, falling back to memory writes"); - return target_write_memory(target, address, 4, count, buffer); + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } /* copy target instructions to target endianness */ for (i = 0; i < 6; i++) target_buffer_set_u32(target, dcc_code_buf + i*4, dcc_code[i]); - /* write DCC code to working area */ - retval = target_write_memory(target, + /* write DCC code to working area, using the non-optimized + * memory write to avoid ending up here again */ + retval = arm7_9_write_memory_no_opt(target, arm7_9->dcc_working_area->address, 4, 6, dcc_code_buf); if (retval != ERROR_OK) return retval; diff --git a/src/target/arm7_9_common.h b/src/target/arm7_9_common.h index 85e5ac0..5821e13 100644 --- a/src/target/arm7_9_common.h +++ b/src/target/arm7_9_common.h @@ -120,6 +120,13 @@ struct arm7_9_common { /**< Callback function called before restoring the processor context */ /** + * Variant specific memory write function that does not dispatch to bulk_write_memory. + * Used as a fallback when bulk writes are unavailable, or for writing data needed to + * do the bulk writes. + */ + int (*write_memory)(struct target *target, uint32_t address, + uint32_t size, uint32_t count, const uint8_t *buffer); + /** * Write target memory in multiples of 4 bytes, optimized for * writing large quantities of data. */ @@ -160,6 +167,8 @@ int arm7_9_write_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer); int arm7_9_write_memory_opt(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer); +int arm7_9_write_memory_no_opt(struct target *target, uint32_t address, + uint32_t size, uint32_t count, const uint8_t *buffer); int arm7_9_bulk_write_memory(struct target *target, uint32_t address, uint32_t count, const uint8_t *buffer); diff --git a/src/target/arm7tdmi.c b/src/target/arm7tdmi.c index 4c7cce1..3dc0013 100644 --- a/src/target/arm7tdmi.c +++ b/src/target/arm7tdmi.c @@ -648,6 +648,7 @@ int arm7tdmi_init_arch_info(struct target *target, arm7_9->enable_single_step = arm7_9_enable_eice_step; arm7_9->disable_single_step = arm7_9_disable_eice_step; + arm7_9->write_memory = arm7_9_write_memory; arm7_9->bulk_write_memory = arm7_9_bulk_write_memory; arm7_9->post_debug_entry = NULL; diff --git a/src/target/arm920t.c b/src/target/arm920t.c index 98bd12f..fbfa170 100644 --- a/src/target/arm920t.c +++ b/src/target/arm920t.c @@ -740,17 +740,6 @@ int arm920t_write_memory(struct target *target, uint32_t address, return ERROR_OK; } -int arm920t_write_memory_opt(struct target *target, uint32_t address, - uint32_t size, uint32_t count, const uint8_t *buffer) -{ - struct arm7_9_common *arm7_9 = target_to_arm7_9(target); - - if (size == 4 && count > 32 && arm7_9->bulk_write_memory) - return arm7_9->bulk_write_memory(target, address, count, buffer); - else - return arm920t_write_memory(target, address, size, count, buffer); -} - /* EXPORTED to FA256 */ int arm920t_soft_reset_halt(struct target *target) { @@ -1708,7 +1697,7 @@ struct target_type arm920t_target = { .get_gdb_reg_list = arm_get_gdb_reg_list, .read_memory = arm920t_read_memory, - .write_memory = arm920t_write_memory_opt, + .write_memory = arm7_9_write_memory_opt, .read_phys_memory = arm920t_read_phys_memory, .write_phys_memory = arm920t_write_phys_memory, .mmu = arm920_mmu, diff --git a/src/target/arm920t.h b/src/target/arm920t.h index 3774513..71876a6 100644 --- a/src/target/arm920t.h +++ b/src/target/arm920t.h @@ -60,8 +60,6 @@ int arm920t_read_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer); int arm920t_write_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer); -int arm920t_write_memory_opt(struct target *target, - uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer); int arm920t_post_debug_entry(struct target *target); void arm920t_pre_restore_context(struct target *target); int arm920t_get_ttb(struct target *target, uint32_t *result); diff --git a/src/target/arm926ejs.c b/src/target/arm926ejs.c index 1e0a579..af80613 100644 --- a/src/target/arm926ejs.c +++ b/src/target/arm926ejs.c @@ -656,17 +656,6 @@ int arm926ejs_write_memory(struct target *target, uint32_t address, return retval; } -int arm926ejs_write_memory_opt(struct target *target, uint32_t address, - uint32_t size, uint32_t count, const uint8_t *buffer) -{ - struct arm7_9_common *arm7_9 = target_to_arm7_9(target); - - if (size == 4 && count > 32 && arm7_9->bulk_write_memory) - return arm7_9->bulk_write_memory(target, address, count, buffer); - else - return arm926ejs_write_memory(target, address, size, count, buffer); -} - static int arm926ejs_write_phys_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer) @@ -819,7 +808,7 @@ struct target_type arm926ejs_target = { .get_gdb_reg_list = arm_get_gdb_reg_list, .read_memory = arm7_9_read_memory, - .write_memory = arm926ejs_write_memory_opt, + .write_memory = arm7_9_write_memory_opt, .checksum_memory = arm_checksum_memory, .blank_check_memory = arm_blank_check_memory, diff --git a/src/target/arm926ejs.h b/src/target/arm926ejs.h index 6dde4c6..cc19c9f 100644 --- a/src/target/arm926ejs.h +++ b/src/target/arm926ejs.h @@ -50,8 +50,6 @@ int arm926ejs_init_arch_info(struct target *target, int arm926ejs_arch_state(struct target *target); int arm926ejs_write_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer); -int arm926ejs_write_memory_opt(struct target *target, - uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer); int arm926ejs_soft_reset_halt(struct target *target); extern const struct command_registration arm926ejs_command_handlers[]; diff --git a/src/target/arm9tdmi.c b/src/target/arm9tdmi.c index d93c15f..ac07534 100644 --- a/src/target/arm9tdmi.c +++ b/src/target/arm9tdmi.c @@ -752,6 +752,7 @@ int arm9tdmi_init_arch_info(struct target *target, arm7_9->enable_single_step = arm9tdmi_enable_single_step; arm7_9->disable_single_step = arm9tdmi_disable_single_step; + arm7_9->write_memory = arm7_9_write_memory; arm7_9->bulk_write_memory = arm7_9_bulk_write_memory; arm7_9->post_debug_entry = NULL; diff --git a/src/target/fa526.c b/src/target/fa526.c index a33b4a1..dfb29b8 100644 --- a/src/target/fa526.c +++ b/src/target/fa526.c @@ -284,6 +284,7 @@ static int fa526_init_arch_info_2(struct target *target, arm7_9->enable_single_step = arm9tdmi_enable_single_step; arm7_9->disable_single_step = arm9tdmi_disable_single_step; + arm7_9->write_memory = arm920t_write_memory; arm7_9->bulk_write_memory = arm7_9_bulk_write_memory; arm7_9->post_debug_entry = NULL; @@ -368,7 +369,7 @@ struct target_type fa526_target = { .get_gdb_reg_list = arm_get_gdb_reg_list, .read_memory = arm920t_read_memory, - .write_memory = arm920t_write_memory_opt, + .write_memory = arm7_9_write_memory_opt, .checksum_memory = arm_checksum_memory, .blank_check_memory = arm_blank_check_memory, diff --git a/src/target/feroceon.c b/src/target/feroceon.c index d3037c5..acaa1b3 100644 --- a/src/target/feroceon.c +++ b/src/target/feroceon.c @@ -493,8 +493,11 @@ static int feroceon_bulk_write_memory(struct target *target, uint32_t dcc_size = sizeof(dcc_code); + if (address % 4 != 0) + return ERROR_TARGET_UNALIGNED_ACCESS; + if (!arm7_9->dcc_downloads) - return target_write_memory(target, address, 4, count, buffer); + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; /* regrab previously allocated working_area, or allocate a new one */ if (!arm7_9->dcc_working_area) { @@ -503,15 +506,16 @@ static int feroceon_bulk_write_memory(struct target *target, /* make sure we have a working area */ if (target_alloc_working_area(target, dcc_size, &arm7_9->dcc_working_area) != ERROR_OK) { LOG_INFO("no working area available, falling back to memory writes"); - return target_write_memory(target, address, 4, count, buffer); + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } /* copy target instructions to target endianness */ for (i = 0; i < dcc_size/4; i++) target_buffer_set_u32(target, dcc_code_buf + i*4, dcc_code[i]); - /* write DCC code to working area */ - retval = target_write_memory(target, + /* write DCC code to working area, using the non-optimized + * memory write to avoid ending up here again */ + retval = arm7_9_write_memory_no_opt(target, arm7_9->dcc_working_area->address, 4, dcc_size/4, dcc_code_buf); if (retval != ERROR_OK) return retval; @@ -627,6 +631,10 @@ static int feroceon_target_create(struct target *target, Jim_Interp *interp) arm926ejs_init_arch_info(target, arm926ejs, target->tap); feroceon_common_setup(target); + struct arm *arm = target->arch_info; + struct arm7_9_common *arm7_9 = arm->arch_info; + arm7_9->write_memory = arm926ejs_write_memory; + /* the standard ARM926 methods don't always work (don't ask...) */ arm926ejs->read_cp15 = feroceon_read_cp15; arm926ejs->write_cp15 = feroceon_write_cp15; @@ -641,6 +649,10 @@ static int dragonite_target_create(struct target *target, Jim_Interp *interp) arm966e_init_arch_info(target, arm966e, target->tap); feroceon_common_setup(target); + struct arm *arm = target->arch_info; + struct arm7_9_common *arm7_9 = arm->arch_info; + arm7_9->write_memory = arm7_9_write_memory; + return ERROR_OK; } @@ -697,7 +709,7 @@ struct target_type feroceon_target = { .get_gdb_reg_list = arm_get_gdb_reg_list, .read_memory = arm7_9_read_memory, - .write_memory = arm926ejs_write_memory_opt, + .write_memory = arm7_9_write_memory_opt, .checksum_memory = arm_checksum_memory, .blank_check_memory = arm_blank_check_memory, -- ------------------------------------------------------------------------------ October Webinars: Code for Performance Free Intel webinars can help you accelerate application performance. Explore tips for MPI, OpenMP, advanced profiling, and more. Get the most from the latest Intel processors and coprocessors. See abstracts and register > http://pubads.g.doubleclick.net/gampad/clk?id=60134791&iu=/4140/ostg.clktrk _______________________________________________ OpenOCD-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/openocd-devel
