From 5c0e8efa051f4e266add8b3685020970fe394a4c Mon Sep 17 00:00:00 2001 From: ntfreak Date: Tue, 19 Feb 2008 19:26:17 +0000 Subject: =?UTF-8?q?-=20Fixed=20bug=20in=20pathmove=20for=20XScale=20-=20ad?= =?UTF-8?q?ded=20virtual=20address=20to=20working=5Farea.=20-=20Improved?= =?UTF-8?q?=20error=20messages=20in=20a=20number=20of=20places=20-=20Added?= =?UTF-8?q?=20ERROR=5FCOMMAND=5FSYNTAX=5FERROR=20that=20commands=20can=20r?= =?UTF-8?q?eturn=20to=20have=20syntax=20printed=20-=20Added=20help=20for?= =?UTF-8?q?=20some=20config=20commands=20-=20Added=20verification=20of=20s?= =?UTF-8?q?w=20breakpoints=20with=20ERROR()=20message=20-=20Removed=20a=20?= =?UTF-8?q?couple=20of=20exit()'s=20and=20replaced=20with=20error=20messag?= =?UTF-8?q?e=20-=20cosmetic=20fix=20to=20armv4=5F5.c,=20easier=20to=20read?= =?UTF-8?q?=20-=20added=20polymorphic(with=20default)=20virt2phys=20and=20?= =?UTF-8?q?mmu=20enable=20query=20function=20to=20target.h=20-=20added=20v?= =?UTF-8?q?irt2phys=20command=20that=20uses=20target->type->virt2phys()=20?= =?UTF-8?q?fn=20Thanks=20to=20=C3=98yvind=20Harboe?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: svn://svn.berlios.de/openocd/trunk@310 b42882b7-edfa-0310-969c-e2dbd0fdcd60 --- src/target/arm7_9_common.c | 22 ++++++++++-- src/target/armv4_5.c | 16 ++++----- src/target/armv4_5_mmu.c | 4 +++ src/target/target.c | 89 ++++++++++++++++++++++++++++++++++++++++++---- src/target/target.h | 9 ++++- src/target/xscale.c | 70 +++++++++++++++++++++--------------- 6 files changed, 164 insertions(+), 46 deletions(-) (limited to 'src/target') diff --git a/src/target/arm7_9_common.c b/src/target/arm7_9_common.c index 825f7fa..45411c1 100644 --- a/src/target/arm7_9_common.c +++ b/src/target/arm7_9_common.c @@ -186,17 +186,33 @@ int arm7_9_set_breakpoint(struct target_s *target, breakpoint_t *breakpoint) { if (breakpoint->length == 4) { + u32 verify = 0xffffffff; /* keep the original instruction in target endianness */ target->type->read_memory(target, breakpoint->address, 4, 1, breakpoint->orig_instr); /* write the breakpoint instruction in target endianness (arm7_9->arm_bkpt is host endian) */ target_write_u32(target, breakpoint->address, arm7_9->arm_bkpt); + + target->type->read_memory(target, breakpoint->address, 4, 1, (u8 *)&verify); + if (verify != arm7_9->arm_bkpt) + { + ERROR("Unable to set 32 bit software breakpoint at address %08x", breakpoint->address); + return ERROR_OK; + } } else { + u16 verify = 0xffff; /* keep the original instruction in target endianness */ target->type->read_memory(target, breakpoint->address, 2, 1, breakpoint->orig_instr); /* write the breakpoint instruction in target endianness (arm7_9->thumb_bkpt is host endian) */ target_write_u16(target, breakpoint->address, arm7_9->thumb_bkpt); + + target->type->read_memory(target, breakpoint->address, 2, 1, (u8 *)&verify); + if (verify != arm7_9->thumb_bkpt) + { + ERROR("Unable to set thumb software breakpoint at address %08x", breakpoint->address); + return ERROR_OK; + } } breakpoint->set = 1; } @@ -1914,7 +1930,7 @@ int arm7_9_read_memory(struct target_s *target, u32 address, u32 size, u32 count if ((retval = jtag_execute_queue()) != ERROR_OK) { ERROR("JTAG error while reading cpsr"); - exit(-1); + return ERROR_TARGET_DATA_ABORT; } if (((cpsr & 0x1f) == ARMV4_5_MODE_ABT) && (armv4_5->core_mode != ARMV4_5_MODE_ABT)) @@ -1943,7 +1959,9 @@ int arm7_9_write_memory(struct target_s *target, u32 address, u32 size, u32 coun int retval; int last_reg = 0; +#ifdef _DEBUG_ARM7_9_ DEBUG("address: 0x%8.8x, size: 0x%8.8x, count: 0x%8.8x", address, size, count); +#endif if (target->state != TARGET_HALTED) { @@ -2079,7 +2097,7 @@ int arm7_9_write_memory(struct target_s *target, u32 address, u32 size, u32 coun if ((retval = jtag_execute_queue()) != ERROR_OK) { ERROR("JTAG error while reading cpsr"); - exit(-1); + return ERROR_TARGET_DATA_ABORT; } if (((cpsr & 0x1f) == ARMV4_5_MODE_ABT) && (armv4_5->core_mode != ARMV4_5_MODE_ABT)) diff --git a/src/target/armv4_5.c b/src/target/armv4_5.c index 2d73a53..02a731c 100644 --- a/src/target/armv4_5.c +++ b/src/target/armv4_5.c @@ -174,14 +174,14 @@ int armv4_5_mode_to_number(enum armv4_5_mode mode) { switch (mode) { - case 16: return 0; break; - case 17: return 1; break; - case 18: return 2; break; - case 19: return 3; break; - case 23: return 4; break; - case 27: return 5; break; - case 31: return 6; break; - case -1: return 0; break; /* map MODE_ANY to user mode */ + case ARMV4_5_MODE_USR: return 0; break; + case ARMV4_5_MODE_FIQ: return 1; break; + case ARMV4_5_MODE_IRQ: return 2; break; + case ARMV4_5_MODE_SVC: return 3; break; + case ARMV4_5_MODE_ABT: return 4; break; + case ARMV4_5_MODE_UND: return 5; break; + case ARMV4_5_MODE_SYS: return 6; break; + case ARMV4_5_MODE_ANY: return 0; break; /* map MODE_ANY to user mode */ default: ERROR("invalid mode value encountered"); return -1; diff --git a/src/target/armv4_5_mmu.c b/src/target/armv4_5_mmu.c index b888933..9c6d12e 100644 --- a/src/target/armv4_5_mmu.c +++ b/src/target/armv4_5_mmu.c @@ -54,12 +54,14 @@ u32 armv4_5_mmu_translate_va(target_t *target, armv4_5_mmu_common_t *armv4_5_mmu if ((first_lvl_descriptor & 0x3) == 0) { *type = -1; + ERROR("Address translation failure"); return ERROR_TARGET_TRANSLATION_FAULT; } if (!armv4_5_mmu->has_tiny_pages && ((first_lvl_descriptor & 0x3) == 3)) { *type = -1; + ERROR("Address translation failure"); return ERROR_TARGET_TRANSLATION_FAULT; } @@ -97,6 +99,7 @@ u32 armv4_5_mmu_translate_va(target_t *target, armv4_5_mmu_common_t *armv4_5_mmu if ((second_lvl_descriptor & 0x3) == 0) { *type = -1; + ERROR("Address translation failure"); return ERROR_TARGET_TRANSLATION_FAULT; } @@ -129,6 +132,7 @@ u32 armv4_5_mmu_translate_va(target_t *target, armv4_5_mmu_common_t *armv4_5_mmu /* should not happen */ *type = -1; + ERROR("Address translation failure"); return ERROR_TARGET_TRANSLATION_FAULT; } diff --git a/src/target/target.c b/src/target/target.c index a606376..4d6ffe3 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -74,6 +74,7 @@ int handle_bp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int handle_rbp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); int handle_wp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); int handle_rwp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); +int handle_virt2phys_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc); /* targets */ @@ -376,6 +377,19 @@ int target_process_reset(struct command_context_s *cmd_ctx) return retval; } +static int default_virt2phys(struct target_s *target, u32 virtual, u32 *physical) +{ + *physical = virtual; + return ERROR_OK; +} + +static int default_mmu(struct target_s *target, int *enabled) +{ + USER("No MMU present"); + *enabled = 0; + return ERROR_OK; +} + int target_init(struct command_context_s *cmd_ctx) { target_t *target = targets; @@ -387,6 +401,16 @@ int target_init(struct command_context_s *cmd_ctx) ERROR("target '%s' init failed", target->type->name); exit(-1); } + + /* Set up default functions if none are provided by target */ + if (target->type->virt2phys == NULL) + { + target->type->virt2phys = default_virt2phys; + } + if (target->type->mmu == NULL) + { + target->type->mmu = default_mmu; + } target = target->next; } @@ -583,6 +607,26 @@ int target_alloc_working_area(struct target_s *target, u32 size, working_area_t working_area_t *c = target->working_areas; working_area_t *new_wa = NULL; + /* Reevaluate working area address based on MMU state*/ + if (target->working_areas == NULL) + { + int retval; + int enabled; + retval = target->type->mmu(target, &enabled); + if (retval != ERROR_OK) + { + return retval; + } + if (enabled) + { + target->working_area = target->working_area_virt; + } + else + { + target->working_area = target->working_area_phys; + } + } + /* only allocate multiples of 4 byte */ if (size % 4) { @@ -621,7 +665,7 @@ int target_alloc_working_area(struct target_s *target, u32 size, working_area_t if (free_size < size) { - WARNING("not enough working area available"); + WARNING("not enough working area available(requested %d, free %d)", size, free_size); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } @@ -700,7 +744,8 @@ int target_register_commands(struct command_context_s *cmd_ctx) register_command(cmd_ctx, NULL, "daemon_startup", handle_daemon_startup_command, COMMAND_CONFIG, NULL); register_command(cmd_ctx, NULL, "target_script", handle_target_script_command, COMMAND_CONFIG, NULL); register_command(cmd_ctx, NULL, "run_and_halt_time", handle_run_and_halt_time_command, COMMAND_CONFIG, NULL); - register_command(cmd_ctx, NULL, "working_area", handle_working_area_command, COMMAND_ANY, NULL); + register_command(cmd_ctx, NULL, "working_area", handle_working_area_command, COMMAND_ANY, "working_area
<'backup'|'nobackup'> [virtual address]"); + register_command(cmd_ctx, NULL, "virt2phys", handle_virt2phys_command, COMMAND_ANY, "virt2phys "); return ERROR_OK; } @@ -1221,10 +1266,9 @@ int handle_working_area_command(struct command_context_s *cmd_ctx, char *cmd, ch { target_t *target = NULL; - if (argc < 4) + if ((argc < 4) || (argc > 5)) { - ERROR("incomplete working_area command. usage: working_area
<'backup'|'nobackup'>"); - exit(-1); + return ERROR_COMMAND_SYNTAX_ERROR; } target = get_target_by_num(strtoul(args[0], NULL, 0)); @@ -1236,7 +1280,11 @@ int handle_working_area_command(struct command_context_s *cmd_ctx, char *cmd, ch } target_free_all_working_areas(target); - target->working_area = strtoul(args[1], NULL, 0); + target->working_area_phys = target->working_area_virt = strtoul(args[1], NULL, 0); + if (argc == 5) + { + target->working_area_virt = strtoul(args[4], NULL, 0); + } target->working_area_size = strtoul(args[2], NULL, 0); if (strcmp(args[3], "backup") == 0) @@ -1250,7 +1298,7 @@ int handle_working_area_command(struct command_context_s *cmd_ctx, char *cmd, ch else { ERROR("unrecognized argument (%s)", args[3]); - exit(-1); + return ERROR_COMMAND_SYNTAX_ERROR; } return ERROR_OK; @@ -2247,3 +2295,30 @@ int handle_rwp_command(struct command_context_s *cmd_ctx, char *cmd, char **args return ERROR_OK; } + +int handle_virt2phys_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc) +{ + int retval; + target_t *target = get_current_target(cmd_ctx); + u32 va; + u32 pa; + + if (argc != 1) + { + return ERROR_COMMAND_SYNTAX_ERROR; + } + va = strtoul(args[0], NULL, 0); + + retval = target->type->virt2phys(target, va, &pa); + if (retval == ERROR_OK) + { + command_print(cmd_ctx, "Physical address 0x%08x", pa); + } + else + { + /* lower levels will have logged a detailed error which is + * forwarded to telnet/GDB session. + */ + } + return retval; +} diff --git a/src/target/target.h b/src/target/target.h index 46ae505..29de1e9 100644 --- a/src/target/target.h +++ b/src/target/target.h @@ -147,6 +147,9 @@ typedef struct target_type_s int (*init_target)(struct command_context_s *cmd_ctx, struct target_s *target); int (*quit)(void); + int (*virt2phys)(struct target_s *target, u32 address, u32 *physical); + int (*mmu)(struct target_s *target, int *enabled); + } target_type_t; typedef struct target_s @@ -158,7 +161,11 @@ typedef struct target_s char *post_halt_script; /* script file to execute after the target halted */ char *pre_resume_script; /* script file to execute before the target resumed */ char *gdb_program_script; /* script file to execute before programming vis gdb */ - u32 working_area; /* working area (initialized RAM) */ + u32 working_area; /* working area (initialized RAM). Evaluated + upon first allocation from virtual/physical address. + */ + u32 working_area_virt; /* virtual address */ + u32 working_area_phys; /* physical address */ u32 working_area_size; /* size in bytes */ u32 backup_working_area; /* whether the content of the working area has to be preserved */ struct working_area_s *working_areas;/* list of allocated working areas */ diff --git a/src/target/xscale.c b/src/target/xscale.c index 03b922d..6a5aabb 100644 --- a/src/target/xscale.c +++ b/src/target/xscale.c @@ -84,6 +84,8 @@ int xscale_add_watchpoint(struct target_s *target, watchpoint_t *watchpoint); int xscale_remove_watchpoint(struct target_s *target, watchpoint_t *watchpoint); void xscale_enable_watchpoints(struct target_s *target); void xscale_enable_breakpoints(struct target_s *target); +static int xscale_virt2phys(struct target_s *target, u32 virtual, u32 *physical); +static int xscale_mmu(struct target_s *target, int *enabled); int xscale_read_trace(target_t *target); @@ -122,7 +124,10 @@ target_type_t xscale_target = .register_commands = xscale_register_commands, .target_command = xscale_target_command, .init_target = xscale_init_target, - .quit = xscale_quit + .quit = xscale_quit, + + .virt2phys = xscale_virt2phys, + .mmu = xscale_mmu }; char* xscale_reg_list[] = @@ -189,11 +194,13 @@ int xscale_get_arch_pointers(target_t *target, armv4_5_common_t **armv4_5_p, xsc if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC) { + ERROR("target isn't an XScale target"); return -1; } if (xscale->common_magic != XSCALE_COMMON_MAGIC) { + ERROR("target isn't an XScale target"); return -1; } @@ -436,7 +443,7 @@ int xscale_read_tx(target_t *target, int consume) armv4_5_common_t *armv4_5 = target->arch_info; xscale_common_t *xscale = armv4_5->arch_info; enum tap_state path[3]; - enum tap_state noconsume_path[7]; + enum tap_state noconsume_path[9]; int retval; struct timeval timeout, now; @@ -461,8 +468,10 @@ int xscale_read_tx(target_t *target, int consume) noconsume_path[2] = TAP_E1D; noconsume_path[3] = TAP_PD; noconsume_path[4] = TAP_E2D; - noconsume_path[5] = TAP_CD; - noconsume_path[6] = TAP_SD; + noconsume_path[5] = TAP_UD; + noconsume_path[6] = TAP_SDS; + noconsume_path[7] = TAP_CD; + noconsume_path[8] = TAP_SD; fields[0].device = xscale->jtag_info.chain_pos; fields[0].num_bits = 3; @@ -502,7 +511,7 @@ int xscale_read_tx(target_t *target, int consume) if (consume) jtag_add_pathmove(3, path); else - jtag_add_pathmove(7, noconsume_path); + jtag_add_pathmove(sizeof(noconsume_path)/sizeof(*noconsume_path), noconsume_path); jtag_add_dr_scan(3, fields, TAP_RTI, NULL); @@ -3142,7 +3151,6 @@ int xscale_handle_debug_handler_command(struct command_context_s *cmd_ctx, char if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK) { - command_print(cmd_ctx, "target isn't an ARM920t target"); return ERROR_OK; } @@ -3183,7 +3191,6 @@ int xscale_handle_cache_clean_address_command(struct command_context_s *cmd_ctx, if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK) { - command_print(cmd_ctx, "target isn't an XScale target"); return ERROR_OK; } @@ -3209,32 +3216,49 @@ int xscale_handle_cache_info_command(struct command_context_s *cmd_ctx, char *cm if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK) { - command_print(cmd_ctx, "target isn't an XScale target"); return ERROR_OK; } return armv4_5_handle_cache_info_command(cmd_ctx, &xscale->armv4_5_mmu.armv4_5_cache); } -int xscale_handle_virt2phys_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc) +static int xscale_virt2phys(struct target_s *target, u32 virtual, u32 *physical) { - target_t *target = get_current_target(cmd_ctx); armv4_5_common_t *armv4_5; xscale_common_t *xscale; - - if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK) + int retval; + int type; + u32 cb; + int domain; + u32 ap; + + if ((retval = xscale_get_arch_pointers(target, &armv4_5, &xscale)) != ERROR_OK) { - command_print(cmd_ctx, "target isn't an XScale target"); - return ERROR_OK; + return retval; + } + u32 ret = armv4_5_mmu_translate_va(target, &xscale->armv4_5_mmu, virtual, &type, &cb, &domain, &ap); + if (type == -1) + { + return ret; } + + *physical = ret; + return ERROR_OK; +} + +static int xscale_mmu(struct target_s *target, int *enabled) +{ + armv4_5_common_t *armv4_5 = target->arch_info; + xscale_common_t *xscale = armv4_5->arch_info; if (target->state != TARGET_HALTED) { - command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd); - return ERROR_OK; + ERROR("Target not halted"); + return ERROR_TARGET_INVALID; } - - return armv4_5_mmu_handle_virt2phys_command(cmd_ctx, cmd, args, argc, target, &xscale->armv4_5_mmu); + + *enabled = xscale->armv4_5_mmu.mmu_enabled; + return ERROR_OK; } int xscale_handle_mmu_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc) @@ -3245,7 +3269,6 @@ int xscale_handle_mmu_command(command_context_t *cmd_ctx, char *cmd, char **args if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK) { - command_print(cmd_ctx, "target isn't an XScale target"); return ERROR_OK; } @@ -3283,7 +3306,6 @@ int xscale_handle_idcache_command(command_context_t *cmd_ctx, char *cmd, char ** if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK) { - command_print(cmd_ctx, "target isn't an XScale target"); return ERROR_OK; } @@ -3337,7 +3359,6 @@ int xscale_handle_vector_catch_command(command_context_t *cmd_ctx, char *cmd, ch if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK) { - command_print(cmd_ctx, "target isn't an XScale target"); return ERROR_OK; } @@ -3365,7 +3386,6 @@ int xscale_handle_force_hw_bkpts_command(struct command_context_s *cmd_ctx, char if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK) { - command_print(cmd_ctx, "target isn't an XScale target"); return ERROR_OK; } @@ -3396,7 +3416,6 @@ int xscale_handle_trace_buffer_command(struct command_context_s *cmd_ctx, char * if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK) { - command_print(cmd_ctx, "target isn't an XScale target"); return ERROR_OK; } @@ -3483,7 +3502,6 @@ int xscale_handle_trace_image_command(struct command_context_s *cmd_ctx, char *c if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK) { - command_print(cmd_ctx, "target isn't an XScale target"); return ERROR_OK; } @@ -3530,7 +3548,6 @@ int xscale_handle_dump_trace_command(struct command_context_s *cmd_ctx, char *cm if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK) { - command_print(cmd_ctx, "target isn't an XScale target"); return ERROR_OK; } @@ -3588,7 +3605,6 @@ int xscale_handle_analyze_trace_buffer_command(struct command_context_s *cmd_ctx if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK) { - command_print(cmd_ctx, "target isn't an XScale target"); return ERROR_OK; } @@ -3605,7 +3621,6 @@ int xscale_handle_cp15(command_context_t *cmd_ctx, char *cmd, char **args, int a if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK) { - command_print(cmd_ctx, "target isn't an XScale target"); return ERROR_OK; } @@ -3697,7 +3712,6 @@ int xscale_register_commands(struct command_context_s *cmd_ctx) register_command(cmd_ctx, xscale_cmd, "cache_clean_address", xscale_handle_cache_clean_address_command, COMMAND_ANY, NULL); register_command(cmd_ctx, xscale_cmd, "cache_info", xscale_handle_cache_info_command, COMMAND_EXEC, NULL); - register_command(cmd_ctx, xscale_cmd, "virt2phys", xscale_handle_virt2phys_command, COMMAND_EXEC, NULL); register_command(cmd_ctx, xscale_cmd, "mmu", xscale_handle_mmu_command, COMMAND_EXEC, "['enable'|'disable'] the MMU"); register_command(cmd_ctx, xscale_cmd, "icache", xscale_handle_idcache_command, COMMAND_EXEC, "['enable'|'disable'] the ICache"); register_command(cmd_ctx, xscale_cmd, "dcache", xscale_handle_idcache_command, COMMAND_EXEC, "['enable'|'disable'] the DCache"); -- cgit v1.1