X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Ftarget%2Farmv7a_cache.c;h=7435aab951c28c934b4f3d68cb84df3f49b428ab;hp=89e85025a9429832812a052dd5c760329a3be592;hb=57e30102ea440d77aa001e26eb901d0cbb305a30;hpb=f3716894c6c2ab0e16bdb073d79e4df855897c10 diff --git a/src/target/armv7a_cache.c b/src/target/armv7a_cache.c index 89e85025a9..7435aab951 100644 --- a/src/target/armv7a_cache.c +++ b/src/target/armv7a_cache.c @@ -11,6 +11,9 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -67,6 +70,7 @@ static int armv7a_l1_d_cache_flush_level(struct arm_dpm *dpm, struct armv7a_cach LOG_DEBUG("cl %" PRId32, cl); do { + keep_alive(); c_way = size->way; do { uint32_t value = (c_index << size->index_shift) @@ -86,6 +90,7 @@ static int armv7a_l1_d_cache_flush_level(struct arm_dpm *dpm, struct armv7a_cach } while (c_index >= 0); done: + keep_alive(); return retval; } @@ -145,21 +150,23 @@ int armv7a_cache_auto_flush_all_data(struct target *target) } else retval = armv7a_l1_d_cache_clean_inval_all(target); - /* do outer cache flushing after inner caches have been flushed */ - retval = arm7a_l2x_flush_all_data(target); + if (retval != ERROR_OK) + return retval; - return retval; + /* do outer cache flushing after inner caches have been flushed */ + return arm7a_l2x_flush_all_data(target); } -static int armv7a_l1_d_cache_inval_virt(struct target *target, uint32_t virt, +int armv7a_l1_d_cache_inval_virt(struct target *target, uint32_t virt, uint32_t size) { struct armv7a_common *armv7a = target_to_armv7a(target); struct arm_dpm *dpm = armv7a->arm.dpm; struct armv7a_cache_common *armv7a_cache = &armv7a->armv7a_mmu.armv7a_cache; - uint32_t i, linelen = armv7a_cache->dminline; - int retval; + uint32_t linelen = armv7a_cache->dminline; + uint32_t va_line, va_end; + int retval, i = 0; retval = armv7a_l1_d_cache_sanity_check(target); if (retval != ERROR_OK) @@ -169,19 +176,47 @@ static int armv7a_l1_d_cache_inval_virt(struct target *target, uint32_t virt, if (retval != ERROR_OK) goto done; - for (i = 0; i < size; i += linelen) { - uint32_t offs = virt + i; + va_line = virt & (-linelen); + va_end = virt + size; - /* DCIMVAC - Clean and invalidate data cache line by VA to PoC. */ + /* handle unaligned start */ + if (virt != va_line) { + /* DCCIMVAC */ retval = dpm->instr_write_data_r0(dpm, - ARMV4_5_MCR(15, 0, 0, 7, 6, 1), offs); + ARMV4_5_MCR(15, 0, 0, 7, 14, 1), va_line); if (retval != ERROR_OK) goto done; + va_line += linelen; } + + /* handle unaligned end */ + if ((va_end & (linelen-1)) != 0) { + va_end &= (-linelen); + /* DCCIMVAC */ + retval = dpm->instr_write_data_r0(dpm, + ARMV4_5_MCR(15, 0, 0, 7, 14, 1), va_end); + if (retval != ERROR_OK) + goto done; + } + + while (va_line < va_end) { + if ((i++ & 0x3f) == 0) + keep_alive(); + /* DCIMVAC - Invalidate data cache line by VA to PoC. */ + retval = dpm->instr_write_data_r0(dpm, + ARMV4_5_MCR(15, 0, 0, 7, 6, 1), va_line); + if (retval != ERROR_OK) + goto done; + va_line += linelen; + } + + keep_alive(); + dpm->finish(dpm); return retval; done: LOG_ERROR("d-cache invalidate failed"); + keep_alive(); dpm->finish(dpm); return retval; @@ -193,8 +228,9 @@ int armv7a_l1_d_cache_clean_virt(struct target *target, uint32_t virt, struct armv7a_common *armv7a = target_to_armv7a(target); struct arm_dpm *dpm = armv7a->arm.dpm; struct armv7a_cache_common *armv7a_cache = &armv7a->armv7a_mmu.armv7a_cache; - uint32_t i, linelen = armv7a_cache->dminline; - int retval; + uint32_t linelen = armv7a_cache->dminline; + uint32_t va_line, va_end; + int retval, i = 0; retval = armv7a_l1_d_cache_sanity_check(target); if (retval != ERROR_OK) @@ -204,19 +240,27 @@ int armv7a_l1_d_cache_clean_virt(struct target *target, uint32_t virt, if (retval != ERROR_OK) goto done; - for (i = 0; i < size; i += linelen) { - uint32_t offs = virt + i; + va_line = virt & (-linelen); + va_end = virt + size; + while (va_line < va_end) { + if ((i++ & 0x3f) == 0) + keep_alive(); /* DCCMVAC - Data Cache Clean by MVA to PoC */ retval = dpm->instr_write_data_r0(dpm, - ARMV4_5_MCR(15, 0, 0, 7, 10, 1), offs); + ARMV4_5_MCR(15, 0, 0, 7, 10, 1), va_line); if (retval != ERROR_OK) goto done; + va_line += linelen; } + + keep_alive(); + dpm->finish(dpm); return retval; done: LOG_ERROR("d-cache invalidate failed"); + keep_alive(); dpm->finish(dpm); return retval; @@ -228,8 +272,9 @@ int armv7a_l1_d_cache_flush_virt(struct target *target, uint32_t virt, struct armv7a_common *armv7a = target_to_armv7a(target); struct arm_dpm *dpm = armv7a->arm.dpm; struct armv7a_cache_common *armv7a_cache = &armv7a->armv7a_mmu.armv7a_cache; - uint32_t i, linelen = armv7a_cache->dminline; - int retval; + uint32_t linelen = armv7a_cache->dminline; + uint32_t va_line, va_end; + int retval, i = 0; retval = armv7a_l1_d_cache_sanity_check(target); if (retval != ERROR_OK) @@ -239,19 +284,27 @@ int armv7a_l1_d_cache_flush_virt(struct target *target, uint32_t virt, if (retval != ERROR_OK) goto done; - for (i = 0; i < size; i += linelen) { - uint32_t offs = virt + i; + va_line = virt & (-linelen); + va_end = virt + size; + while (va_line < va_end) { + if ((i++ & 0x3f) == 0) + keep_alive(); /* DCCIMVAC */ retval = dpm->instr_write_data_r0(dpm, - ARMV4_5_MCR(15, 0, 0, 7, 14, 1), offs); + ARMV4_5_MCR(15, 0, 0, 7, 14, 1), va_line); if (retval != ERROR_OK) goto done; + va_line += linelen; } + + keep_alive(); + dpm->finish(dpm); return retval; done: LOG_ERROR("d-cache invalidate failed"); + keep_alive(); dpm->finish(dpm); return retval; @@ -303,7 +356,7 @@ int armv7a_l1_i_cache_inval_virt(struct target *target, uint32_t virt, &armv7a->armv7a_mmu.armv7a_cache; uint32_t linelen = armv7a_cache->iminline; uint32_t va_line, va_end; - int retval; + int retval, i = 0; retval = armv7a_l1_i_cache_sanity_check(target); if (retval != ERROR_OK) @@ -317,6 +370,8 @@ int armv7a_l1_i_cache_inval_virt(struct target *target, uint32_t virt, va_end = virt + size; while (va_line < va_end) { + if ((i++ & 0x3f) == 0) + keep_alive(); /* ICIMVAU - Invalidate instruction cache by VA to PoU. */ retval = dpm->instr_write_data_r0(dpm, ARMV4_5_MCR(15, 0, 0, 7, 5, 1), va_line); @@ -329,10 +384,13 @@ int armv7a_l1_i_cache_inval_virt(struct target *target, uint32_t virt, goto done; va_line += linelen; } + keep_alive(); + dpm->finish(dpm); return retval; done: LOG_ERROR("i-cache invalidate failed"); + keep_alive(); dpm->finish(dpm); return retval;