From: David Brownell Date: Tue, 10 Nov 2009 19:58:31 +0000 (-0800) Subject: target: MMU-aware init for memory read/write X-Git-Tag: v0.4.0-rc1~843 X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=commitdiff_plain;h=61af6a681671eae69256dcc5b9e853cf9b161387 target: MMU-aware init for memory read/write Start switching MMU handling over to a more sensible scheme. Having an mmu() method enables MMU-aware behaviors. Not having one kicks in simpler ones, with no distinction between virtual and physical addresses. Currently only a handful of targets have methods to read/write physical memory: just arm720, arm920, and arm926. They should all initialize OK now, but the arm*20 parts don't do the "extra" stuff arm926 does (which should arguably be target-generic). Also simplify how target_init() loops over all targets by making it be a normal "for" loop, instead of scattering its three parts to the four winds. Signed-off-by: David Brownell --- diff --git a/doc/openocd.texi b/doc/openocd.texi index 8223ee9458..475482df9c 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -5051,9 +5051,11 @@ about what TAP is the current target, or about MMU configuration. Display contents of address @var{addr}, as 32-bit words (@command{mdw}), 16-bit halfwords (@command{mdh}), or 8-bit bytes (@command{mdb}). +When the current target has an MMU which is present and active, +@var{addr} is interpreted as a virtual address. +Otherwise, or if the optional @var{phys} flag is specified, +@var{addr} is interpreted as a physical address. If @var{count} is specified, displays that many units. -@var{phys} is an optional flag to indicate to use -physical address and bypass MMU (If you want to manipulate the data instead of displaying it, see the @code{mem2array} primitives.) @end deffn @@ -5062,10 +5064,12 @@ see the @code{mem2array} primitives.) @deffnx Command mwh [phys] addr halfword @deffnx Command mwb [phys] addr byte Writes the specified @var{word} (32 bits), -@var{halfword} (16 bits), or @var{byte} (8-bit) pattern, +@var{halfword} (16 bits), or @var{byte} (8-bit) value, at the specified address @var{addr}. -@var{phys} is an optional flag to indicate to use -physical address and bypass MMU +When the current target has an MMU which is present and active, +@var{addr} is interpreted as a virtual address. +Otherwise, or if the optional @var{phys} flag is specified, +@var{addr} is interpreted as a physical address. @end deffn diff --git a/src/target/target.c b/src/target/target.c index 5cdfa5dc00..1bf680d194 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -756,11 +756,12 @@ err_write_phys_memory(struct target_s *target, uint32_t address, int target_init(struct command_context_s *cmd_ctx) { - target_t *target = all_targets; + struct target_s *target; int retval; - while (target) - { + for (target = all_targets; target; target = target->next) { + struct target_type_s *type = target->type; + target_reset_examined(target); if (target->type->examine == NULL) { @@ -773,22 +774,6 @@ int target_init(struct command_context_s *cmd_ctx) return retval; } - /* Set up default functions if none are provided by target */ - if (target->type->virt2phys == NULL) - { - target->type->virt2phys = identity_virt2phys; - } - - if (target->type->read_phys_memory == NULL) - { - target->type->read_phys_memory = err_read_phys_memory; - } - - if (target->type->write_phys_memory == NULL) - { - target->type->write_phys_memory = err_write_phys_memory; - } - /** * @todo MCR/MRC are ARM-specific; don't require them in * all targets, or for ARMs without coprocessors. @@ -833,11 +818,45 @@ int target_init(struct command_context_s *cmd_ctx) target->type->run_algorithm_imp = target->type->run_algorithm; target->type->run_algorithm = target_run_algorithm_imp; - if (target->type->mmu == NULL) - { - target->type->mmu = no_mmu; + /* Sanity-check MMU support ... stub in what we must, to help + * implement it in stages, but warn if we need to do so. + */ + if (type->mmu) { + if (type->write_phys_memory == NULL) { + LOG_ERROR("type '%s' is missing %s", + type->name, + "write_phys_memory"); + type->write_phys_memory = err_write_phys_memory; + } + if (type->read_phys_memory == NULL) { + LOG_ERROR("type '%s' is missing %s", + type->name, + "read_phys_memory"); + type->read_phys_memory = err_read_phys_memory; + } + if (type->virt2phys == NULL) { + LOG_ERROR("type '%s' is missing %s", + type->name, + "virt2phys"); + type->virt2phys = identity_virt2phys; + } + + /* Make sure no-MMU targets all behave the same: make no + * distinction between physical and virtual addresses, and + * ensure that virt2phys() is always an identity mapping. + */ + } else { + if (type->write_phys_memory + || type->read_phys_memory + || type->virt2phys) + LOG_WARNING("type '%s' has broken MMU hooks", + type->name); + + type->mmu = no_mmu; + type->write_phys_memory = type->write_memory; + type->read_phys_memory = type->read_memory; + type->virt2phys = identity_virt2phys; } - target = target->next; } if (all_targets)