ARM: 7062/1: cache: detect PIPT I-cache using CTR
authorWill Deacon <will.deacon@arm.com>
Tue, 23 Aug 2011 21:22:11 +0000 (22:22 +0100)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Mon, 17 Oct 2011 08:13:41 +0000 (09:13 +0100)
The Cache Type Register L1Ip field identifies I-caches with a PIPT
policy using the encoding 11b.

This patch extends the cache policy parsing to identify PIPT I-caches
correctly and prevent them from being treated as VIPT aliasing in cases
where they are sufficiently large.

Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
arch/arm/include/asm/cachetype.h
arch/arm/kernel/setup.c

index c023db09fcc14ced27ec4bacaca40b44c48005ad..7ea78144ae22ec61ae7623b07c9d22f08ef69e87 100644 (file)
@@ -7,6 +7,7 @@
 #define CACHEID_VIPT                   (CACHEID_VIPT_ALIASING|CACHEID_VIPT_NONALIASING)
 #define CACHEID_ASID_TAGGED            (1 << 3)
 #define CACHEID_VIPT_I_ALIASING                (1 << 4)
+#define CACHEID_PIPT                   (1 << 5)
 
 extern unsigned int cacheid;
 
@@ -16,6 +17,7 @@ extern unsigned int cacheid;
 #define cache_is_vipt_aliasing()       cacheid_is(CACHEID_VIPT_ALIASING)
 #define icache_is_vivt_asid_tagged()   cacheid_is(CACHEID_ASID_TAGGED)
 #define icache_is_vipt_aliasing()      cacheid_is(CACHEID_VIPT_I_ALIASING)
+#define icache_is_pipt()               cacheid_is(CACHEID_PIPT)
 
 /*
  * __LINUX_ARM_ARCH__ is the minimum supported CPU architecture
@@ -26,7 +28,8 @@ extern unsigned int cacheid;
 #if __LINUX_ARM_ARCH__ >= 7
 #define __CACHEID_ARCH_MIN     (CACHEID_VIPT_NONALIASING |\
                                 CACHEID_ASID_TAGGED |\
-                                CACHEID_VIPT_I_ALIASING)
+                                CACHEID_VIPT_I_ALIASING |\
+                                CACHEID_PIPT)
 #elif __LINUX_ARM_ARCH__ >= 6
 #define        __CACHEID_ARCH_MIN      (~CACHEID_VIVT)
 #else
index 93e39a3d2c1efd63cc89f33cb5d43e030135cb30..3fe93f75b55a4be2438bd258cbca189106078645 100644 (file)
@@ -265,6 +265,10 @@ static int cpu_has_aliasing_icache(unsigned int arch)
        int aliasing_icache;
        unsigned int id_reg, num_sets, line_size;
 
+       /* PIPT caches never alias. */
+       if (icache_is_pipt())
+               return 0;
+
        /* arch specifies the register format */
        switch (arch) {
        case CPU_ARCH_ARMv7:
@@ -299,8 +303,14 @@ static void __init cacheid_init(void)
                        /* ARMv7 register format */
                        arch = CPU_ARCH_ARMv7;
                        cacheid = CACHEID_VIPT_NONALIASING;
-                       if ((cachetype & (3 << 14)) == 1 << 14)
+                       switch (cachetype & (3 << 14)) {
+                       case (1 << 14):
                                cacheid |= CACHEID_ASID_TAGGED;
+                               break;
+                       case (3 << 14):
+                               cacheid |= CACHEID_PIPT;
+                               break;
+                       }
                } else {
                        arch = CPU_ARCH_ARMv6;
                        if (cachetype & (1 << 23))
@@ -317,10 +327,11 @@ static void __init cacheid_init(void)
        printk("CPU: %s data cache, %s instruction cache\n",
                cache_is_vivt() ? "VIVT" :
                cache_is_vipt_aliasing() ? "VIPT aliasing" :
-               cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown",
+               cache_is_vipt_nonaliasing() ? "PIPT / VIPT nonaliasing" : "unknown",
                cache_is_vivt() ? "VIVT" :
                icache_is_vivt_asid_tagged() ? "VIVT ASID tagged" :
                icache_is_vipt_aliasing() ? "VIPT aliasing" :
+               icache_is_pipt() ? "PIPT" :
                cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown");
 }