From: Øyvind H. <go...@us...> - 2010-02-19 08:18:04
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via 3f30563c88fcf02a8a8e671d817299adfda628ec (commit) from aa8db989b90766f4aefe72f96c1c0a37d27d1369 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 3f30563c88fcf02a8a8e671d817299adfda628ec Author: Marc Pignat <mar...@he...> Date: Tue Feb 16 10:08:18 2010 +0100 atm920t : fix breakpoints and data cache handling Breakpoints did not work because the data cache was not flushed properly. As a bonus add capability to write to memory marked as read only by the MMU, which allows software breakpoints in such memory regions. diff --git a/src/target/arm920t.c b/src/target/arm920t.c index 3b75ca9..7cc228d 100644 --- a/src/target/arm920t.c +++ b/src/target/arm920t.c @@ -559,34 +559,120 @@ static int arm920t_write_phys_memory(struct target *target, /** Writes a buffer, in the specified word size, with current MMU settings. */ -int arm920t_write_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, uint8_t *buffer) { int retval; + const uint32_t cache_mask = ~0x1f; /* cache line size : 32 byte */ + struct arm920t_common *arm920t = target_to_arm920(target); - if ((retval = arm7_9_write_memory(target, address, size, count, buffer)) != ERROR_OK) - return retval; - - /* This fn is used to write breakpoints, so we need to make sure - * that the data cache is flushed and the instruction cache is - * invalidated - */ - if (((size == 4) || (size == 2)) && (count == 1)) + /* FIX!!!! this should be cleaned up and made much more general. The + * plan is to write up and test on arm920t specifically and + * then generalize and clean up afterwards. */ + if (arm920t->armv4_5_mmu.mmu_enabled && (count == 1) && ((size==2) || (size==4))) { - struct arm920t_common *arm920t = target_to_arm920(target); + /* special case the handling of single word writes to bypass MMU + * to allow implementation of breakpoints in memory marked read only + * by MMU */ + int type; + uint32_t cb; + int domain; + uint32_t ap; + uint32_t pa; + + /* + * We need physical address and cb + */ + pa = armv4_5_mmu_translate_va(target, &arm920t->armv4_5_mmu, address, &type, &cb, &domain, &ap); + if (type == -1) + { + return pa; + } if (arm920t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled) { - LOG_DEBUG("D-Cache enabled, flush and invalidate cache line"); - /* MCR p15,0,Rd,c7,c10,2 */ - retval = arm920t_write_cp15_interpreted(target, 0xee070f5e, 0x0, address); - if (retval != ERROR_OK) - return retval; + if (cb & 0x1) + { + LOG_DEBUG("D-Cache buffered, drain write buffer"); + /* + * Buffered ? + * Drain write buffer - MCR p15,0,Rd,c7,c10,4 + */ + + retval = arm920t_write_cp15_interpreted(target, ARMV4_5_MCR(15, 0, 0, 7, 10, 4), 0x0, 0); + if (retval != ERROR_OK) + return retval; + } + + if (cb == 0x3) + { + /* + * Write back memory ? -> clean cache + * + * There is no way for cleaning a data cache line using + * cp15 scan chain, so copy the full cache line from + * cache to physical memory. + */ + uint8_t data[32]; + + LOG_DEBUG("D-Cache in 'write back' mode, flush cache line"); + + retval = target_read_memory(target, address & cache_mask, 1, sizeof(data), &data[0]); + if (retval != ERROR_OK) + return retval; + + retval = armv4_5_mmu_write_physical(target, &arm920t->armv4_5_mmu, pa & cache_mask, 1, sizeof(data), &data[0]); + if (retval != ERROR_OK) + return retval; + } + + /* Cached ? */ + if (cb & 0x2) + { + /* + * Cached ? -> Invalidate data cache using MVA + * + * MCR p15,0,Rd,c7,c6,1 + */ + LOG_DEBUG("D-Cache enabled, invalidate cache line"); + + retval = arm920t_write_cp15_interpreted(target, ARMV4_5_MCR(15, 0, 0, 7, 6, 1), 0x0, address & cache_mask); + if (retval != ERROR_OK) + return retval; + } } - if (arm920t->armv4_5_mmu.armv4_5_cache.i_cache_enabled) + /* write directly to physical memory bypassing any read only MMU bits, etc. */ + retval = armv4_5_mmu_write_physical(target, &arm920t->armv4_5_mmu, pa, size, count, buffer); + if (retval != ERROR_OK) + return retval; + } else + { + if ((retval = arm7_9_write_memory(target, address, size, count, buffer)) != ERROR_OK) + return retval; + } + + /* If ICache is enabled, we have to invalidate affected ICache lines + * the DCache is forced to write-through, so we don't have to clean it here + */ + if (arm920t->armv4_5_mmu.armv4_5_cache.i_cache_enabled) + { + if (count <= 1) { + /* invalidate ICache single entry with MVA + * ee070f35 mcr 15, 0, r0, cr7, cr5, {1} + */ LOG_DEBUG("I-Cache enabled, invalidating affected I-Cache line"); - retval = arm920t_write_cp15_interpreted(target, 0xee070f35, 0x0, address); + retval = arm920t_write_cp15_interpreted(target, ARMV4_5_MCR(15, 0, 0, 7, 5, 1), 0x0, address & cache_mask); + if (retval != ERROR_OK) + return retval; + } + else + { + /* invalidate ICache + * 8: ee070f15 mcr 15, 0, r0, cr7, cr5, {0} + * */ + retval = arm920t_write_cp15_interpreted(target, ARMV4_5_MCR(15, 0, 0, 7, 5, 0), 0x0, 0x0); if (retval != ERROR_OK) return retval; } ----------------------------------------------------------------------- Summary of changes: src/target/arm920t.c | 120 +++++++++++++++++++++++++++++++++++++++++++------- 1 files changed, 103 insertions(+), 17 deletions(-) hooks/post-receive -- Main OpenOCD repository |