[ARM] armv7: add support for asid-tagged VIVT I-cache
authorCatalin Marinas <catalin.marinas@arm.com>
Wed, 9 May 2007 08:50:23 +0000 (09:50 +0100)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Wed, 9 May 2007 08:50:23 +0000 (09:50 +0100)
ARMv7 can have VIPT, PIPT or ASID-tagged VIVT I-cache. This patch
adds the necessary invalidation of the I-cache when the ASID numbers
are re-used.

Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
arch/arm/mm/context.c
include/asm-arm/cacheflush.h

index 9da43a0..c9e9a55 100644 (file)
@@ -47,6 +47,13 @@ void __new_context(struct mm_struct *mm)
                    : "r" (0));
                isb();
                flush_tlb_all();
+               if (icache_is_vivt_asid_tagged()) {
+                       asm("mcr        p15, 0, %0, c7, c5, 0   @ invalidate I-cache\n"
+                           "mcr        p15, 0, %0, c7, c5, 6   @ flush BTAC/BTB\n"
+                           :
+                           : "r" (0));
+                       dsb();
+               }
        }
 
        mm->context.id = asid;
index 6832ef9..d1294a4 100644 (file)
@@ -438,6 +438,7 @@ static inline void flush_anon_page(struct vm_area_struct *vma,
 #define __cacheid_vipt(val)                    (__cacheid_type_v7(val) ? 1 : __cacheid_vipt_prev7(val))
 #define __cacheid_vipt_nonaliasing(val)                (__cacheid_type_v7(val) ? 1 : __cacheid_vipt_nonaliasing_prev7(val))
 #define __cacheid_vipt_aliasing(val)           (__cacheid_type_v7(val) ? 0 : __cacheid_vipt_aliasing_prev7(val))
+#define __cacheid_vivt_asid_tagged_instr(val)  (__cacheid_type_v7(val) ? ((val & (3 << 14)) == (1 << 14)) : 0)
 
 #if defined(CONFIG_CPU_CACHE_VIVT) && !defined(CONFIG_CPU_CACHE_VIPT)
 
@@ -445,6 +446,7 @@ static inline void flush_anon_page(struct vm_area_struct *vma,
 #define cache_is_vipt()                        0
 #define cache_is_vipt_nonaliasing()    0
 #define cache_is_vipt_aliasing()       0
+#define icache_is_vivt_asid_tagged()   0
 
 #elif defined(CONFIG_CPU_CACHE_VIPT)
 
@@ -462,6 +464,12 @@ static inline void flush_anon_page(struct vm_area_struct *vma,
                __cacheid_vipt_aliasing(__val);                         \
        })
 
+#define icache_is_vivt_asid_tagged()                                   \
+       ({                                                              \
+               unsigned int __val = read_cpuid(CPUID_CACHETYPE);       \
+               __cacheid_vivt_asid_tagged_instr(__val);                \
+       })
+
 #else
 
 #define cache_is_vivt()                                                        \
@@ -490,6 +498,13 @@ static inline void flush_anon_page(struct vm_area_struct *vma,
                 __cacheid_vipt_aliasing(__val);                        \
        })
 
+#define icache_is_vivt_asid_tagged()                                   \
+       ({                                                              \
+               unsigned int __val = read_cpuid(CPUID_CACHETYPE);       \
+               __cacheid_present(__val) &&                             \
+                __cacheid_vivt_asid_tagged_instr(__val);               \
+       })
+
 #endif
 
 #endif