]> git.sur5r.net Git - openocd/commitdiff
cortex_a: Update instruction cache after setting a soft breakpoint
authorMatthias Welwarsky <matthias@welwarsky.de>
Sun, 18 Oct 2015 11:50:58 +0000 (13:50 +0200)
committerPaul Fertser <fercerpav@gmail.com>
Mon, 30 Nov 2015 05:43:03 +0000 (05:43 +0000)
Call armv7a_l1_d_cache_flush_virt() before writing the breakpoint,
to make sure the d-cache is clean and invalid at the breakpoint
location down to PoC.

Call armv7a_l1_d_cache_inval_virt() after writing the breakpoint
again, so that d-cache will pick up the modified code.
Call armv7a_l1_i_cache_inval_virt() after writing the breakpoint
to memory to make the change visible to the CPU.

Change-Id: I24fc27058d99cb00d7f6002ccb623cab66b0d234
Signed-off-by: Matthias Welwarsky <matthias@welwarsky.de>
Reviewed-on: http://openocd.zylin.com/3033
Reviewed-by: Paul Fertser <fercerpav@gmail.com>
Tested-by: jenkins
src/target/armv7a_cache.c
src/target/armv7a_cache.h
src/target/cortex_a.c

index a049174cbe85b65c028ba351fac34ba8c9f541bf..acc388a273d6b3cb0d27b8df15baf34b56150c75 100644 (file)
@@ -152,7 +152,7 @@ int armv7a_cache_auto_flush_all_data(struct target *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);
index fbd158b4d5ebe812efe179e6bdbfb4598e77d54a..e0ebb618b472fa2e0f092b293d6cd3f605dd2bda 100644 (file)
@@ -21,6 +21,8 @@
 
 int armv7a_l1_d_cache_clean_virt(struct target *target, uint32_t virt,
                                        unsigned int size);
+int armv7a_l1_d_cache_inval_virt(struct target *target, uint32_t virt,
+                                       unsigned int size);
 int armv7a_l1_d_cache_flush_virt(struct target *target, uint32_t virt,
                                        unsigned int size);
 int armv7a_l1_i_cache_inval_all(struct target *target);
index 39e59ae7b66819a9c40ac156e620d786ec75f545..5268cf2164586ed7888cb8b7ccf47c55c62b3695 100644 (file)
@@ -1509,11 +1509,25 @@ static int cortex_a_set_breakpoint(struct target *target,
                                breakpoint->orig_instr);
                if (retval != ERROR_OK)
                        return retval;
+
+               /* make sure data cache is cleaned & invalidated down to PoC */
+               if (!armv7a->armv7a_mmu.armv7a_cache.auto_cache_enabled) {
+                       armv7a_cache_flush_virt(target, breakpoint->address,
+                                               breakpoint->length);
+               }
+
                retval = target_write_memory(target,
                                breakpoint->address & 0xFFFFFFFE,
                                breakpoint->length, 1, code);
                if (retval != ERROR_OK)
                        return retval;
+
+               /* update i-cache at breakpoint location */
+               armv7a_l1_d_cache_inval_virt(target, breakpoint->address,
+                                       breakpoint->length);
+               armv7a_l1_i_cache_inval_virt(target, breakpoint->address,
+                                                breakpoint->length);
+
                breakpoint->set = 0x11; /* Any nice value but 0 */
        }
 
@@ -1733,6 +1747,13 @@ static int cortex_a_unset_breakpoint(struct target *target, struct breakpoint *b
                        return ERROR_OK;
                }
        } else {
+
+               /* make sure data cache is cleaned & invalidated down to PoC */
+               if (!armv7a->armv7a_mmu.armv7a_cache.auto_cache_enabled) {
+                       armv7a_cache_flush_virt(target, breakpoint->address,
+                                               breakpoint->length);
+               }
+
                /* restore original instruction (kept in target endianness) */
                if (breakpoint->length == 4) {
                        retval = target_write_memory(target,
@@ -1747,6 +1768,12 @@ static int cortex_a_unset_breakpoint(struct target *target, struct breakpoint *b
                        if (retval != ERROR_OK)
                                return retval;
                }
+
+               /* update i-cache at breakpoint location */
+               armv7a_l1_d_cache_inval_virt(target, breakpoint->address,
+                                                breakpoint->length);
+               armv7a_l1_i_cache_inval_virt(target, breakpoint->address,
+                                                breakpoint->length);
        }
        breakpoint->set = 0;