]> git.sur5r.net Git - openocd/blobdiff - src/target/cortex_a.c
cortex_a: force cache and tlb bypass when cpu is in debug state
[openocd] / src / target / cortex_a.c
index 39e59ae7b66819a9c40ac156e620d786ec75f545..61a5df38918b426447994d07bb8c71fba71004ce 100644 (file)
@@ -243,6 +243,18 @@ static int cortex_a_init_debug_access(struct target *target)
        if (retval != ERROR_OK)
                return retval;
 
+       /* Disable cacheline fills and force cache write-through in debug state */
+       retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap,
+                       armv7a->debug_base + CPUDBG_DSCCR, 0);
+       if (retval != ERROR_OK)
+               return retval;
+
+       /* Disable TLB lookup and refill/eviction in debug state */
+       retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap,
+                       armv7a->debug_base + CPUDBG_DSMCR, 0);
+       if (retval != ERROR_OK)
+               return retval;
+
        /* Enabling of instruction execution in debug mode is done in debug_entry code */
 
        /* Resync breakpoint registers */
@@ -1509,11 +1521,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 +1759,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 +1780,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;