atm920t : fix breakpoints and data cache handling
authorMarc Pignat <marc.pignat@hevs.ch>
Tue, 16 Feb 2010 09:08:18 +0000 (10:08 +0100)
committerØyvind Harboe <oyvind.harboe@zylin.com>
Fri, 19 Feb 2010 07:18:12 +0000 (08:18 +0100)
Breakpoints did not work because the data cache was not flushed
properly.

As a bonus add capability to write to memory marked as read only
by the MMU, which allows software breakpoints in such memory
regions.

src/target/arm920t.c

index 3b75ca9754164f60fb8b86d1c606ae176c5ad1e7..7cc228d06690e34a860b73a5a47ca997dc28c116 100644 (file)
@@ -559,34 +559,120 @@ static int arm920t_write_phys_memory(struct target *target,
 
 
 /** Writes a buffer, in the specified word size, with current MMU settings. */
-int arm920t_write_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
+int arm920t_write_memory(struct target *target, uint32_t address,
+               uint32_t size, uint32_t count, uint8_t *buffer)
 {
        int retval;
+       const uint32_t cache_mask = ~0x1f; /* cache line size : 32 byte */
+       struct arm920t_common *arm920t = target_to_arm920(target);
 
-       if ((retval = arm7_9_write_memory(target, address, size, count, buffer)) != ERROR_OK)
-               return retval;
-
-       /* This fn is used to write breakpoints, so we need to make sure
-        * that the data cache is flushed and the instruction cache is
-        * invalidated
-        */
-       if (((size == 4) || (size == 2)) && (count == 1))
+       /* FIX!!!! this should be cleaned up and made much more general. The
+        * plan is to write up and test on arm920t specifically and
+        * then generalize and clean up afterwards. */
+       if (arm920t->armv4_5_mmu.mmu_enabled && (count == 1) && ((size==2) || (size==4)))
        {
-               struct arm920t_common *arm920t = target_to_arm920(target);
+               /* special case the handling of single word writes to bypass MMU
+                * to allow implementation of breakpoints in memory marked read only
+                * by MMU */
+               int type;
+               uint32_t cb;
+               int domain;
+               uint32_t ap;
+               uint32_t pa;
+
+               /*
+                * We need physical address and cb
+                */
+               pa = armv4_5_mmu_translate_va(target, &arm920t->armv4_5_mmu, address, &type, &cb, &domain, &ap);
+               if (type == -1)
+               {
+                       return pa;
+               }
 
                if (arm920t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled)
                {
-                       LOG_DEBUG("D-Cache enabled, flush and invalidate cache line");
-                       /* MCR p15,0,Rd,c7,c10,2 */
-                       retval = arm920t_write_cp15_interpreted(target, 0xee070f5e, 0x0, address);
-                       if (retval != ERROR_OK)
-                               return retval;
+                       if (cb & 0x1)
+                       {
+                               LOG_DEBUG("D-Cache buffered, drain write buffer");
+                               /*
+                                * Buffered ?
+                                * Drain write buffer - MCR p15,0,Rd,c7,c10,4
+                                */
+
+                               retval = arm920t_write_cp15_interpreted(target, ARMV4_5_MCR(15, 0, 0, 7, 10, 4), 0x0, 0);
+                               if (retval != ERROR_OK)
+                                       return retval;
+                       }
+
+                       if (cb == 0x3)
+                       {
+                               /*
+                                * Write back memory ? -> clean cache
+                                *
+                                * There is no way for cleaning a data cache line using
+                                * cp15 scan chain, so copy the full cache line from
+                                * cache to physical memory.
+                                */
+                               uint8_t data[32];
+
+                               LOG_DEBUG("D-Cache in 'write back' mode, flush cache line");
+
+                               retval = target_read_memory(target, address & cache_mask, 1, sizeof(data), &data[0]);
+                               if (retval != ERROR_OK)
+                                       return retval;
+
+                               retval = armv4_5_mmu_write_physical(target, &arm920t->armv4_5_mmu, pa & cache_mask, 1, sizeof(data), &data[0]);
+                               if (retval != ERROR_OK)
+                                       return retval;
+                       }
+
+                       /* Cached ? */
+                       if (cb & 0x2)
+                       {
+                               /*
+                                * Cached ? -> Invalidate data cache using MVA
+                                *
+                                * MCR p15,0,Rd,c7,c6,1
+                                */
+                               LOG_DEBUG("D-Cache enabled, invalidate cache line");
+
+                               retval = arm920t_write_cp15_interpreted(target, ARMV4_5_MCR(15, 0, 0, 7, 6, 1), 0x0, address & cache_mask);
+                               if (retval != ERROR_OK)
+                                       return retval;
+                       }
                }
 
-               if (arm920t->armv4_5_mmu.armv4_5_cache.i_cache_enabled)
+               /* write directly to physical memory bypassing any read only MMU bits, etc. */
+               retval = armv4_5_mmu_write_physical(target, &arm920t->armv4_5_mmu, pa, size, count, buffer);
+               if (retval != ERROR_OK)
+                       return retval;
+       } else
+       {
+               if ((retval = arm7_9_write_memory(target, address, size, count, buffer)) != ERROR_OK)
+                       return retval;
+       }
+
+       /* If ICache is enabled, we have to invalidate affected ICache lines
+        * the DCache is forced to write-through, so we don't have to clean it here
+        */
+       if (arm920t->armv4_5_mmu.armv4_5_cache.i_cache_enabled)
+       {
+               if (count <= 1)
                {
+                       /* invalidate ICache single entry with MVA
+                        *      ee070f35        mcr     15, 0, r0, cr7, cr5, {1}
+                        */
                        LOG_DEBUG("I-Cache enabled, invalidating affected I-Cache line");
-                       retval = arm920t_write_cp15_interpreted(target, 0xee070f35, 0x0, address);
+                       retval = arm920t_write_cp15_interpreted(target, ARMV4_5_MCR(15, 0, 0, 7, 5, 1), 0x0, address & cache_mask);
+                       if (retval != ERROR_OK)
+                               return retval;
+               }
+               else
+               {
+                       /* invalidate ICache
+                        *   8: ee070f15        mcr     15, 0, r0, cr7, cr5, {0}
+                        * */
+                       retval = arm920t_write_cp15_interpreted(target, ARMV4_5_MCR(15, 0, 0, 7, 5, 0), 0x0, 0x0);
                        if (retval != ERROR_OK)
                                return retval;
                }

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)