From d17c11759fa0b183dd9a9837534e9d6849a8db14 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Fri, 16 Oct 2015 10:10:02 +0200 Subject: [PATCH] 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 --- src/target/armv7a_cache.c | 43 +++++++++------------------------------ src/target/armv7a_cache.h | 3 ++- src/target/cortex_a.c | 4 +++- 3 files changed, 15 insertions(+), 35 deletions(-) diff --git a/src/target/armv7a_cache.c b/src/target/armv7a_cache.c index 98474ecb4..da617b81b 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 81995ac3a..fbd158b4d 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 f9c927364..39e59ae7b 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; }