From: Matthias Welwarsky Date: Fri, 16 Oct 2015 08:10:02 +0000 (+0200) Subject: armv7a: rework automatic flush-on-write handling X-Git-Tag: v0.10.0-rc1~338 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=d17c11759fa0b183dd9a9837534e9d6849a8db14;p=openocd armv7a: rework automatic flush-on-write handling The following changes are implemented: - Clean&Invalidate the VA range to PoC *before* the write takes place - Remove SMP handling since DCCIMVA instruction already maintains SMP coherence. - Remove separate Invalidate step Change-Id: I19fd3cc226d8ecf2937276fc63258b6a26e369a7 Signed-off-by: Matthias Welwarsky Reviewed-on: http://openocd.zylin.com/3027 Reviewed-by: Paul Fertser Tested-by: jenkins --- diff --git a/src/target/armv7a_cache.c b/src/target/armv7a_cache.c index 98474ecb..da617b81 100644 --- a/src/target/armv7a_cache.c +++ b/src/target/armv7a_cache.c @@ -207,8 +207,7 @@ int armv7a_l1_d_cache_clean_virt(struct target *target, uint32_t virt, for (i = 0; i < size; i += linelen) { uint32_t offs = virt + i; - /* FIXME: do we need DCCVAC or DCCVAU */ - /* FIXME: in both cases it is not enough for i-cache */ + /* 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); if (retval != ERROR_OK) @@ -339,6 +338,14 @@ done: return retval; } +int armv7a_cache_flush_virt(struct target *target, uint32_t virt, + uint32_t size) +{ + armv7a_l1_d_cache_flush_virt(target, virt, size); + armv7a_l2x_cache_flush_virt(target, virt, size); + + return ERROR_OK; +} /* * We assume that target core was chosen correctly. It means if same data @@ -354,41 +361,11 @@ int armv7a_cache_auto_flush_on_write(struct target *target, uint32_t virt, uint32_t size) { struct armv7a_common *armv7a = target_to_armv7a(target); - int retval = ERROR_OK; if (!armv7a->armv7a_mmu.armv7a_cache.auto_cache_enabled) return ERROR_OK; - armv7a_l1_d_cache_clean_virt(target, virt, size); - armv7a_l2x_cache_flush_virt(target, virt, size); - - if (target->smp) { - struct target_list *head; - struct target *curr; - head = target->head; - while (head != (struct target_list *)NULL) { - curr = head->target; - if (curr->state == TARGET_HALTED) { - retval = armv7a_l1_i_cache_inval_all(curr); - if (retval != ERROR_OK) - return retval; - retval = armv7a_l1_d_cache_inval_virt(target, - virt, size); - if (retval != ERROR_OK) - return retval; - } - head = head->next; - } - } else { - retval = armv7a_l1_i_cache_inval_all(target); - if (retval != ERROR_OK) - return retval; - retval = armv7a_l1_d_cache_inval_virt(target, virt, size); - if (retval != ERROR_OK) - return retval; - } - - return retval; + return armv7a_cache_flush_virt(target, virt, size); } COMMAND_HANDLER(arm7a_l1_cache_info_cmd) diff --git a/src/target/armv7a_cache.h b/src/target/armv7a_cache.h index 81995ac3..fbd158b4 100644 --- a/src/target/armv7a_cache.h +++ b/src/target/armv7a_cache.h @@ -29,7 +29,8 @@ int armv7a_l1_i_cache_inval_virt(struct target *target, uint32_t virt, int armv7a_cache_auto_flush_on_write(struct target *target, uint32_t virt, uint32_t size); int armv7a_cache_auto_flush_all_data(struct target *target); - +int armv7a_cache_flush_virt(struct target *target, uint32_t virt, + uint32_t size); extern const struct command_registration arm7a_cache_command_handlers[]; /* CLIDR cache types */ diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c index f9c92736..39e59ae7 100644 --- a/src/target/cortex_a.c +++ b/src/target/cortex_a.c @@ -2754,10 +2754,12 @@ static int cortex_a_write_memory(struct target *target, uint32_t address, if (retval != ERROR_OK) return retval; } - retval = cortex_a_write_apb_ab_memory(target, address, size, count, buffer); + /* memory writes bypass the caches, must flush before writing */ armv7a_cache_auto_flush_on_write(target, address, size * count); + retval = cortex_a_write_apb_ab_memory(target, address, size, count, buffer); + return retval; }