cortex_a: Update instruction cache after setting a soft breakpoint 33/3033/10
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;
 

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)