This is an automated email from Gerrit.

Alexander Osipenko ([email protected]) just uploaded a new patch set to Gerrit, 
which you can find at http://openocd.zylin.com/693

-- gerrit

commit 3437b5fd81e39c968209f819db5bf0d1c5057ab4
Author: Alexander Osipenko <[email protected]>
Date:   Fri Jun 8 23:18:04 2012 +0400

    arm946e: cleanup C0.C cache type reg access
    
    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 <[email protected]>

diff --git a/src/target/arm946e.c b/src/target/arm946e.c
index d6c5a10..efdfbe1 100644
--- a/src/target/arm946e.c
+++ b/src/target/arm946e.c
@@ -210,43 +210,55 @@ int arm946e_write_cp15(struct target *target, int 
reg_addr, uint32_t value)
        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)
-               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) */
+       uint32_t seg;
        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) */
-                       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 */
+                       uint32_t dtag;
                        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)
 {
-       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$");
-
        /**
         *  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;
@@ -366,8 +380,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 csize = 0x0;
-       uint32_t shift = 0;
        uint32_t cur_addr = 0x0;
        uint32_t cp15_idx, set, way, dtag;
        uint32_t i = 0;
@@ -376,18 +388,6 @@ uint32_t arm946e_invalidate_dcache(struct target *target, 
uint32_t address,
        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 */
 
diff --git a/src/target/arm946e.h b/src/target/arm946e.h
index 1837bad..64750af 100644
--- a/src/target/arm946e.h
+++ b/src/target/arm946e.h
@@ -35,6 +35,7 @@ struct arm946e_common {
        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)

-- 

------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
OpenOCD-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/openocd-devel

Reply via email to