MIPS: Support extended ASIDs
authorPaul Burton <paul.burton@imgtec.com>
Fri, 6 May 2016 13:36:24 +0000 (14:36 +0100)
committerRalf Baechle <ralf@linux-mips.org>
Fri, 13 May 2016 12:02:20 +0000 (14:02 +0200)
Add support for extended ASIDs as determined by the Config4.AE bit.
Since the only supported CPUs known to implement this are Netlogic XLP
and MIPS I6400, select this variable ASID support based upon
CONFIG_CPU_XLP and CONFIG_CPU_MIPSR6.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Jayachandran C. <jchandra@broadcom.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Radim Krčmář <rkrcmar@redhat.com>
Cc: linux-mips@linux-mips.org
Cc: kvm@vger.kernel.org
Patchwork: https://patchwork.linux-mips.org/patch/13211/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
arch/mips/Kconfig
arch/mips/include/asm/cpu-info.h
arch/mips/kernel/asm-offsets.c
arch/mips/kernel/cpu-probe.c
arch/mips/kernel/genex.S
arch/mips/kvm/locore.S

index 0cab0da2ab5594cd9f2d6a1d5df584b86c0c4eca..5cc5b621ae69e1ffc736cc838f3ee91bc1870135 100644 (file)
@@ -1706,6 +1706,7 @@ config CPU_XLP
        select CPU_HAS_PREFETCH
        select CPU_MIPSR2
        select CPU_SUPPORTS_HUGEPAGES
+       select MIPS_ASID_BITS_VARIABLE
        help
          Netlogic Microsystems XLP processors.
 endchoice
@@ -2001,6 +2002,7 @@ config CPU_MIPSR6
        bool
        default y if CPU_MIPS32_R6 || CPU_MIPS64_R6
        select HAVE_ARCH_BITREVERSE
+       select MIPS_ASID_BITS_VARIABLE
        select MIPS_SPRAM
 
 config EVA
@@ -2457,9 +2459,13 @@ config MIPS_ASID_SHIFT
 
 config MIPS_ASID_BITS
        int
+       default 0 if MIPS_ASID_BITS_VARIABLE
        default 6 if CPU_R3000 || CPU_TX39XX
        default 8
 
+config MIPS_ASID_BITS_VARIABLE
+       bool
+
 #
 # - Highmem only makes sense for the 32-bit kernel.
 # - The current highmem code will only work properly on physically indexed
index 1ae26a393153f2fd8c9075c770f399889f69e6ac..392da7e6fc720dd7228e685d75a582ff8578e34a 100644 (file)
@@ -40,6 +40,9 @@ struct cache_desc {
 
 struct cpuinfo_mips {
        unsigned long           asid_cache;
+#ifdef CONFIG_MIPS_ASID_BITS_VARIABLE
+       unsigned long           asid_mask;
+#endif
 
        /*
         * Capability and feature descriptor structure for MIPS CPU
@@ -139,7 +142,18 @@ static inline unsigned long cpu_asid_inc(void)
 
 static inline unsigned long cpu_asid_mask(struct cpuinfo_mips *cpuinfo)
 {
+#ifdef CONFIG_MIPS_ASID_BITS_VARIABLE
+       return cpuinfo->asid_mask;
+#endif
        return ((1 << CONFIG_MIPS_ASID_BITS) - 1) << CONFIG_MIPS_ASID_SHIFT;
 }
 
+static inline void set_cpu_asid_mask(struct cpuinfo_mips *cpuinfo,
+                                    unsigned long asid_mask)
+{
+#ifdef CONFIG_MIPS_ASID_BITS_VARIABLE
+       cpuinfo->asid_mask = asid_mask;
+#endif
+}
+
 #endif /* __ASM_CPU_INFO_H */
index 154e2039ea5ef13fe9ba8935eb01475031283913..1ea973b2abb1e0365db6ee4b867d3e32d355953c 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/mm.h>
 #include <linux/kbuild.h>
 #include <linux/suspend.h>
+#include <asm/cpu-info.h>
 #include <asm/pm.h>
 #include <asm/ptrace.h>
 #include <asm/processor.h>
@@ -338,6 +339,15 @@ void output_pm_defines(void)
 }
 #endif
 
+void output_cpuinfo_defines(void)
+{
+       COMMENT(" MIPS cpuinfo offsets. ");
+       DEFINE(CPUINFO_SIZE, sizeof(struct cpuinfo_mips));
+#ifdef CONFIG_MIPS_ASID_BITS_VARIABLE
+       OFFSET(CPUINFO_ASID_MASK, cpuinfo_mips, asid_mask);
+#endif
+}
+
 void output_kvm_defines(void)
 {
        COMMENT(" KVM/MIPS Specfic offsets. ");
index 064ab389e9643fc218e58f018f3fb3e7b92fc0b2..5ca4fefb13447f49e68032927e64cbd1e02e0de8 100644 (file)
@@ -732,6 +732,7 @@ static inline unsigned int decode_config4(struct cpuinfo_mips *c)
        unsigned int newcf4;
        unsigned int mmuextdef;
        unsigned int ftlb_page = MIPS_CONF4_FTLBPAGESIZE;
+       unsigned long asid_mask;
 
        config4 = read_c0_config4();
 
@@ -792,6 +793,18 @@ static inline unsigned int decode_config4(struct cpuinfo_mips *c)
 
        c->kscratch_mask = (config4 >> 16) & 0xff;
 
+       asid_mask = MIPS_ENTRYHI_ASID;
+       if (config4 & MIPS_CONF4_AE)
+               asid_mask |= MIPS_ENTRYHI_ASIDX;
+       set_cpu_asid_mask(c, asid_mask);
+
+       /*
+        * Warn if the computed ASID mask doesn't match the mask the kernel
+        * is built for. This may indicate either a serious problem or an
+        * easy optimisation opportunity, but either way should be addressed.
+        */
+       WARN_ON(asid_mask != cpu_asid_mask(c));
+
        return config4 & MIPS_CONF_M;
 }
 
index 17374aef6f00f83edac2aec3b8adca63a8cbe49a..bff9644b9ad1ae94d7fa4b935dd5fb72f3147073 100644 (file)
@@ -455,7 +455,7 @@ NESTED(nmi_handler, PT_SIZE, sp)
        .set    noreorder
        /* check if TLB contains a entry for EPC */
        MFC0    k1, CP0_ENTRYHI
-       andi    k1, MIPS_ENTRYHI_ASID
+       andi    k1, MIPS_ENTRYHI_ASID | MIPS_ENTRYHI_ASIDX
        MFC0    k0, CP0_EPC
        PTR_SRL k0, _PAGE_SHIFT + 1
        PTR_SLL k0, _PAGE_SHIFT + 1
index 1f2167bc847d72b197f292c8bfa3b3a784ff1ce4..3ef03009de5f65fa4807cac71bb9749baaa63ab7 100644 (file)
@@ -137,7 +137,14 @@ FEXPORT(__kvm_mips_load_asid)
        INT_SLL t2, t2, 2                   /* x4 */
        REG_ADDU t3, t1, t2
        LONG_L  k0, (t3)
+#ifdef CONFIG_MIPS_ASID_BITS_VARIABLE
+       li      t3, CPUINFO_SIZE/4
+       mul     t2, t2, t3              /* x sizeof(struct cpuinfo_mips)/4 */
+       LONG_L  t2, (cpu_data + CPUINFO_ASID_MASK)(t2)
+       and     k0, k0, t2
+#else
        andi    k0, k0, MIPS_ENTRYHI_ASID
+#endif
        mtc0    k0, CP0_ENTRYHI
        ehb
 
@@ -449,7 +456,14 @@ __kvm_mips_return_to_guest:
        INT_SLL t2, t2, 2               /* x4 */
        REG_ADDU t3, t1, t2
        LONG_L  k0, (t3)
+#ifdef CONFIG_MIPS_ASID_BITS_VARIABLE
+       li      t3, CPUINFO_SIZE/4
+       mul     t2, t2, t3              /* x sizeof(struct cpuinfo_mips)/4 */
+       LONG_L  t2, (cpu_data + CPUINFO_ASID_MASK)(t2)
+       and     k0, k0, t2
+#else
        andi    k0, k0, MIPS_ENTRYHI_ASID
+#endif
        mtc0    k0, CP0_ENTRYHI
        ehb