This is an automated email from Gerrit.

Matthias Welwarsky ([email protected]) just uploaded a new patch set to 
Gerrit, which you can find at http://openocd.zylin.com/3032

-- gerrit

commit 0e5ec36c8c8c326f02ae64076a8a105218944dcc
Author: Matthias Welwarsky <[email protected]>
Date:   Sun Oct 18 13:46:30 2015 +0200

    armv7a: add function to update i-cache after setting a soft breakpoint
    
    After updating the program code, e.g. placing a "BKPT" instruction into
    existing code, the instruction cache must be manually updated. This patch
    adds the function armv7a_di_cache_clean_inval_virt() which:
    - cleans the dcache at the breakpoint location to PoU
    - invalidates the icache
    - invalidates the branch predictor
    
    Note: cleaning outer caches is not required because they're beyond the PoU
    
    Change-Id: I9812afcaf5397c488aefffffbdffe5625a22de46
    Signed-off-by: Matthias Welwarsky <[email protected]>

diff --git a/src/target/armv7a_cache.c b/src/target/armv7a_cache.c
index ff9829f..baddb3e 100644
--- a/src/target/armv7a_cache.c
+++ b/src/target/armv7a_cache.c
@@ -322,6 +322,72 @@ done:
        return retval;
 }
 
+/* I-Cache Invalidate of virtual address range
+ * DDI0406C says in chapter G.5.2
+ * DCCMVAU to clean D-Cache to PoU, to make the change visible to the I-Cache
+ * ICIMVAU to invalidate the I-Cache to PoU
+ * BPIMVA to invalidate the changed location in the branch predictor
+ *
+ * This will work if the program change was written through the CPU, i.e. using
+ * the APB-AP, since it's then in the D-Cache. If the change was written 
through
+ * the AHB-AP, we will need a different sequence.
+ *
+ * AHB memory writes are like DMA, so we need to:
+ * - Invalidate the D-Cache location before writing the change
+ * - write the change
+ * - Invalidate the location in I-Cache
+ * - Invalidate the Branch Predictor
+ */
+int armv7a_di_cache_clean_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 linelen = armv7a_cache->iminline;
+       uint32_t va_line, va_end;
+       int retval;
+
+       retval = armv7a_l1_i_cache_sanity_check(target);
+       if (retval != ERROR_OK)
+               return retval;
+
+       retval = dpm->prepare(dpm);
+       if (retval != ERROR_OK)
+               goto done;
+
+       va_line = virt & (-linelen);
+       va_end = virt + size;
+
+       while (va_line < va_end) {
+               /* DCCMVAU */
+               retval = dpm->instr_write_data_r0(dpm,
+                               ARMV4_5_MCR(15, 0, 0, 7, 11, 1), va_line);
+               if (retval != ERROR_OK)
+                       goto done;
+               /* 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);
+               if (retval != ERROR_OK)
+                       goto done;
+               /* BPIMVA */
+               retval = dpm->instr_write_data_r0(dpm,
+                               ARMV4_5_MCR(15, 0, 0, 7, 5, 7), va_line);
+               if (retval != ERROR_OK)
+                       goto done;
+               va_line += linelen;
+       }
+       dpm->finish(dpm);
+       return retval;
+
+done:
+       LOG_ERROR("i-cache invalidate failed");
+       dpm->finish(dpm);
+
+       return retval;
+}
+
 
 /*
  * We assume that target core was chosen correctly. It means if same data
diff --git a/src/target/armv7a_cache.h b/src/target/armv7a_cache.h
index a83d4db..19ad9ab 100644
--- a/src/target/armv7a_cache.h
+++ b/src/target/armv7a_cache.h
@@ -22,6 +22,8 @@
 int armv7a_l1_d_cache_clean_virt(struct target *target, uint32_t virt,
                                        unsigned int size);
 int armv7a_l1_i_cache_inval_all(struct target *target);
+int armv7a_di_cache_clean_inval_virt(struct target *target, uint32_t virt,
+                                       unsigned int size);
 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);

-- 

------------------------------------------------------------------------------
_______________________________________________
OpenOCD-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/openocd-devel

Reply via email to