arm946e: cleanup C0.C cache type reg access
authorAlexander Osipenko <sipych@gmail.com>
Fri, 8 Jun 2012 19:18:04 +0000 (23:18 +0400)
committerFreddie Chopin <freddie.chopin@gmail.com>
Wed, 1 Aug 2012 21:18:37 +0000 (21:18 +0000)
Cache type register C0.C is read-only, and display
hard core configuration information.
This information is unlikely be changed in runtime.

 - removed C0.C access when result is not used in
   arm946e_invalidate_dcache()
 - access C0.C only once per target, store result
   in cp15_cache_info field of target structure
 - fix cache index count calculation

Change-Id: I12bc4c967fdf07f54d755f2f2f42406c0ababc1a
Signed-off-by: Alexander Osipenko <sipych@gmail.com>
Reviewed-on: http://openocd.zylin.com/693
Tested-by: jenkins
Reviewed-by: Freddie Chopin <freddie.chopin@gmail.com>
src/target/arm946e.c
src/target/arm946e.h

index bd3eceb5951ef480c10a596b55e204c5269c48e4..2a71f2d3501d6011190cb316acbe04c120008ea4 100644 (file)
@@ -210,43 +210,55 @@ int arm946e_write_cp15(struct target *target, int reg_addr, uint32_t value)
        return ERROR_OK;
 }
 
        return ERROR_OK;
 }
 
-uint32_t arm946e_invalidate_whole_dcache(struct target *target)
-{
-
-       uint32_t csize = 0;
-       uint32_t shift = 0;
-       uint32_t cp15_idx, seg, dtag;
-       int nb_idx, idx = 0;
-       int retval;
-
-       /* Get cache type */
-       arm946e_read_cp15(target, 0x01, (uint32_t *) &csize);
+#define GET_ICACHE_SIZE  6
+#define GET_DCACHE_SIZE 18
 
 
-       csize = (csize >> 18) & 0x0F;
+/*
+ * \param target struct target pointer
+ * \param idsel  select GET_ICACHE_SIZE or GET_DCACHE_SIZE
+ * \returns      cache size, given in bytes
+ */
+static uint32_t arm946e_cp15_get_csize(struct target *target, int idsel)
+{
+       struct arm946e_common *arm946e = target_to_arm946(target);
+       uint32_t csize = arm946e->cp15_cache_info;
+       if (csize == 0) {
+               if (arm946e_read_cp15(target, 0x01, &csize) == ERROR_OK)
+                       arm946e->cp15_cache_info = csize;
+       }
+       if (csize & (1<<(idsel-4)))     /* cache absent */
+               return 0;
+       csize = (csize >> idsel) & 0x0F;
+       return csize ? 1 << (12 + (csize-3)) : 0;
+}
 
 
+uint32_t arm946e_invalidate_whole_dcache(struct target *target)
+{
+       uint32_t csize = arm946e_cp15_get_csize(target, GET_DCACHE_SIZE);
        if (csize == 0)
        if (csize == 0)
-               shift = 0;
-       else
-               shift = csize - 0x3;    /* Now 0 = 4KB, 1 = 8KB, ... */
+               return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
 
 
-       /* Cache size, given in bytes */
-       csize = 1 << (12 + shift);
-       /* One line (index) is 32 bytes (8 words) long */
-       nb_idx = (csize / 32);  /* gives nb of lines (indexes) in the cache */
+       /* One line (index) is 32 bytes (8 words) long, 4-way assoc
+        * ARM DDI 0201D, Section 3.3.5
+        */
+       int nb_idx = (csize / (4*8*NB_CACHE_WAYS));     /* gives nb of lines (indexes) in the cache */
 
        /* Loop for all segmentde (i.e. ways) */
 
        /* Loop for all segmentde (i.e. ways) */
+       uint32_t seg;
        for (seg = 0; seg < NB_CACHE_WAYS; seg++) {
                /* Loop for all indexes */
        for (seg = 0; seg < NB_CACHE_WAYS; seg++) {
                /* Loop for all indexes */
+               int idx;
                for (idx = 0; idx < nb_idx; idx++) {
                        /* Form and write cp15 index (segment + line idx) */
                for (idx = 0; idx < nb_idx; idx++) {
                        /* Form and write cp15 index (segment + line idx) */
-                       cp15_idx = seg << 30 | idx << 5;
-                       retval = arm946e_write_cp15(target, 0x3a, cp15_idx);
+                       uint32_t cp15_idx = seg << 30 | idx << 5;
+                       int retval = arm946e_write_cp15(target, 0x3a, cp15_idx);
                        if (retval != ERROR_OK) {
                                LOG_DEBUG("ERROR writing index");
                                return retval;
                        }
 
                        /* Read dtag */
                        if (retval != ERROR_OK) {
                                LOG_DEBUG("ERROR writing index");
                                return retval;
                        }
 
                        /* Read dtag */
+                       uint32_t dtag;
                        arm946e_read_cp15(target, 0x16, (uint32_t *) &dtag);
 
                        /* Check cache line VALID bit */
                        arm946e_read_cp15(target, 0x16, (uint32_t *) &dtag);
 
                        /* Check cache line VALID bit */
@@ -274,15 +286,17 @@ uint32_t arm946e_invalidate_whole_dcache(struct target *target)
 
 uint32_t arm946e_invalidate_whole_icache(struct target *target)
 {
 
 uint32_t arm946e_invalidate_whole_icache(struct target *target)
 {
-       int retval;
+       /* Check cache presence before flushing - avoid undefined behavior */
+       uint32_t csize = arm946e_cp15_get_csize(target, GET_ICACHE_SIZE);
+       if (csize == 0)
+               return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
 
        LOG_DEBUG("FLUSHING I$");
 
        LOG_DEBUG("FLUSHING I$");
-
        /**
         *  Invalidate (flush) I$
         *  mcr 15, 0, r0, cr7, cr5, {0}
         */
        /**
         *  Invalidate (flush) I$
         *  mcr 15, 0, r0, cr7, cr5, {0}
         */
-       retval = arm946e_write_cp15(target, 0x0f, 0x1);
+       int retval = arm946e_write_cp15(target, 0x0f, 0x1);
        if (retval != ERROR_OK) {
                LOG_DEBUG("ERROR flushing I$");
                return retval;
        if (retval != ERROR_OK) {
                LOG_DEBUG("ERROR flushing I$");
                return retval;
@@ -360,8 +374,6 @@ void arm946e_pre_restore_context(struct target *target)
 uint32_t arm946e_invalidate_dcache(struct target *target, uint32_t address,
        uint32_t size, uint32_t count)
 {
 uint32_t arm946e_invalidate_dcache(struct target *target, uint32_t address,
        uint32_t size, uint32_t count)
 {
-       uint32_t csize = 0x0;
-       uint32_t shift = 0;
        uint32_t cur_addr = 0x0;
        uint32_t cp15_idx, set, way, dtag;
        uint32_t i = 0;
        uint32_t cur_addr = 0x0;
        uint32_t cp15_idx, set, way, dtag;
        uint32_t i = 0;
@@ -370,18 +382,6 @@ uint32_t arm946e_invalidate_dcache(struct target *target, uint32_t address,
        for (i = 0; i < count*size; i++) {
                cur_addr = address + i;
 
        for (i = 0; i < count*size; i++) {
                cur_addr = address + i;
 
-               /* Get cache type */
-               arm946e_read_cp15(target, 0x01, (uint32_t *) &csize);
-
-               /* Conclude cache size to find number of lines */
-               csize = (csize >> 18) & 0x0F;
-
-               if (csize == 0)
-                       shift = 0;
-               else
-                       shift = csize - 0x3;    /* Now 0 = 4KB, 1 = 8KB, ... */
-
-               csize = 1 << (12 + shift);
 
                set = (cur_addr >> 5) & 0xff;   /* set field is 8 bits long */
 
 
                set = (cur_addr >> 5) & 0xff;   /* set field is 8 bits long */
 
index 1837bad77b5b1422438c72f709b76280a4be4a17..64750af19ed642f37fbed548afe3b5c3b90c1f3a 100644 (file)
@@ -35,6 +35,7 @@ struct arm946e_common {
        struct arm7_9_common arm7_9_common;
        int common_magic;
        uint32_t cp15_control_reg;
        struct arm7_9_common arm7_9_common;
        int common_magic;
        uint32_t cp15_control_reg;
+       uint32_t cp15_cache_info;
 };
 
 static inline struct arm946e_common *target_to_arm946(struct target *target)
 };
 
 static inline struct arm946e_common *target_to_arm946(struct target *target)

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)