MIPS: Add Kconfig variable for CPUs with unaligned load/store instructions
authorYasha Cherikovsky <yasha.che3@gmail.com>
Wed, 26 Sep 2018 11:16:15 +0000 (14:16 +0300)
committerPaul Burton <paul.burton@mips.com>
Wed, 26 Sep 2018 20:38:18 +0000 (13:38 -0700)
MIPSR6 CPUs do not support unaligned load/store instructions
(LWL, LWR, SWL, SWR and LDL, LDR, SDL, SDR for 64bit).

Currently the MIPS tree has some special cases to avoid these
instructions, and the code is testing for !CONFIG_CPU_MIPSR6.

This patch declares a new Kconfig variable:
CONFIG_CPU_HAS_LOAD_STORE_LR.
This variable indicates that the CPU supports these instructions.

Then, the patch does the following:
- Carefully selects this option on all CPUs except MIPSR6.
- Switches all the special cases to test for the new variable,
  and inverts the logic:
    '#ifndef CONFIG_CPU_MIPSR6' turns into
    '#ifdef CONFIG_CPU_HAS_LOAD_STORE_LR'
    and vice-versa.

Also, when this variable is NOT selected (e.g. MIPSR6),
CONFIG_GENERIC_CSUM will default to 'y', to compile generic
C checksum code (instead of special assembly code that uses the
unsupported instructions).

This commit should not affect any existing CPU, and is required
for future Lexra CPU support, that misses these instructions too.

Signed-off-by: Yasha Cherikovsky <yasha.che3@gmail.com>
Signed-off-by: Paul Burton <paul.burton@mips.com>
Patchwork: https://patchwork.linux-mips.org/patch/20808/
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Paul Burton <paul.burton@mips.com>
Cc: James Hogan <jhogan@kernel.org>
Cc: linux-mips@linux-mips.org
Cc: linux-kernel@vger.kernel.org
arch/mips/Kconfig
arch/mips/kernel/unaligned.c
arch/mips/lib/memcpy.S
arch/mips/lib/memset.S

index ce55c3c2d10d224b6002e4fb1f340edd6da92548..f0655427de939ad1ba4704ccb718483e3773bac5 100644 (file)
@@ -1150,6 +1150,7 @@ config NO_IOPORT_MAP
 
 config GENERIC_CSUM
        bool
+       default y if !CPU_HAS_LOAD_STORE_LR
 
 config GENERIC_ISA_DMA
        bool
@@ -1368,6 +1369,7 @@ config CPU_LOONGSON3
        select CPU_SUPPORTS_64BIT_KERNEL
        select CPU_SUPPORTS_HIGHMEM
        select CPU_SUPPORTS_HUGEPAGES
+       select CPU_HAS_LOAD_STORE_LR
        select WEAK_ORDERING
        select WEAK_REORDERING_BEYOND_LLSC
        select MIPS_PGD_C0_CONTEXT
@@ -1444,6 +1446,7 @@ config CPU_MIPS32_R1
        bool "MIPS32 Release 1"
        depends on SYS_HAS_CPU_MIPS32_R1
        select CPU_HAS_PREFETCH
+       select CPU_HAS_LOAD_STORE_LR
        select CPU_SUPPORTS_32BIT_KERNEL
        select CPU_SUPPORTS_HIGHMEM
        help
@@ -1461,6 +1464,7 @@ config CPU_MIPS32_R2
        bool "MIPS32 Release 2"
        depends on SYS_HAS_CPU_MIPS32_R2
        select CPU_HAS_PREFETCH
+       select CPU_HAS_LOAD_STORE_LR
        select CPU_SUPPORTS_32BIT_KERNEL
        select CPU_SUPPORTS_HIGHMEM
        select CPU_SUPPORTS_MSA
@@ -1479,7 +1483,6 @@ config CPU_MIPS32_R6
        select CPU_SUPPORTS_32BIT_KERNEL
        select CPU_SUPPORTS_HIGHMEM
        select CPU_SUPPORTS_MSA
-       select GENERIC_CSUM
        select HAVE_KVM
        select MIPS_O32_FP64_SUPPORT
        help
@@ -1492,6 +1495,7 @@ config CPU_MIPS64_R1
        bool "MIPS64 Release 1"
        depends on SYS_HAS_CPU_MIPS64_R1
        select CPU_HAS_PREFETCH
+       select CPU_HAS_LOAD_STORE_LR
        select CPU_SUPPORTS_32BIT_KERNEL
        select CPU_SUPPORTS_64BIT_KERNEL
        select CPU_SUPPORTS_HIGHMEM
@@ -1511,6 +1515,7 @@ config CPU_MIPS64_R2
        bool "MIPS64 Release 2"
        depends on SYS_HAS_CPU_MIPS64_R2
        select CPU_HAS_PREFETCH
+       select CPU_HAS_LOAD_STORE_LR
        select CPU_SUPPORTS_32BIT_KERNEL
        select CPU_SUPPORTS_64BIT_KERNEL
        select CPU_SUPPORTS_HIGHMEM
@@ -1532,7 +1537,6 @@ config CPU_MIPS64_R6
        select CPU_SUPPORTS_64BIT_KERNEL
        select CPU_SUPPORTS_HIGHMEM
        select CPU_SUPPORTS_MSA
-       select GENERIC_CSUM
        select MIPS_O32_FP64_SUPPORT if 32BIT || MIPS32_O32
        select HAVE_KVM
        help
@@ -1545,6 +1549,7 @@ config CPU_R3000
        bool "R3000"
        depends on SYS_HAS_CPU_R3000
        select CPU_HAS_WB
+       select CPU_HAS_LOAD_STORE_LR
        select CPU_SUPPORTS_32BIT_KERNEL
        select CPU_SUPPORTS_HIGHMEM
        help
@@ -1559,12 +1564,14 @@ config CPU_TX39XX
        bool "R39XX"
        depends on SYS_HAS_CPU_TX39XX
        select CPU_SUPPORTS_32BIT_KERNEL
+       select CPU_HAS_LOAD_STORE_LR
 
 config CPU_VR41XX
        bool "R41xx"
        depends on SYS_HAS_CPU_VR41XX
        select CPU_SUPPORTS_32BIT_KERNEL
        select CPU_SUPPORTS_64BIT_KERNEL
+       select CPU_HAS_LOAD_STORE_LR
        help
          The options selects support for the NEC VR4100 series of processors.
          Only choose this option if you have one of these processors as a
@@ -1576,6 +1583,7 @@ config CPU_R4300
        depends on SYS_HAS_CPU_R4300
        select CPU_SUPPORTS_32BIT_KERNEL
        select CPU_SUPPORTS_64BIT_KERNEL
+       select CPU_HAS_LOAD_STORE_LR
        help
          MIPS Technologies R4300-series processors.
 
@@ -1585,6 +1593,7 @@ config CPU_R4X00
        select CPU_SUPPORTS_32BIT_KERNEL
        select CPU_SUPPORTS_64BIT_KERNEL
        select CPU_SUPPORTS_HUGEPAGES
+       select CPU_HAS_LOAD_STORE_LR
        help
          MIPS Technologies R4000-series processors other than 4300, including
          the R4000, R4400, R4600, and 4700.
@@ -1593,6 +1602,7 @@ config CPU_TX49XX
        bool "R49XX"
        depends on SYS_HAS_CPU_TX49XX
        select CPU_HAS_PREFETCH
+       select CPU_HAS_LOAD_STORE_LR
        select CPU_SUPPORTS_32BIT_KERNEL
        select CPU_SUPPORTS_64BIT_KERNEL
        select CPU_SUPPORTS_HUGEPAGES
@@ -1603,6 +1613,7 @@ config CPU_R5000
        select CPU_SUPPORTS_32BIT_KERNEL
        select CPU_SUPPORTS_64BIT_KERNEL
        select CPU_SUPPORTS_HUGEPAGES
+       select CPU_HAS_LOAD_STORE_LR
        help
          MIPS Technologies R5000-series processors other than the Nevada.
 
@@ -1612,6 +1623,7 @@ config CPU_R5432
        select CPU_SUPPORTS_32BIT_KERNEL
        select CPU_SUPPORTS_64BIT_KERNEL
        select CPU_SUPPORTS_HUGEPAGES
+       select CPU_HAS_LOAD_STORE_LR
 
 config CPU_R5500
        bool "R5500"
@@ -1619,6 +1631,7 @@ config CPU_R5500
        select CPU_SUPPORTS_32BIT_KERNEL
        select CPU_SUPPORTS_64BIT_KERNEL
        select CPU_SUPPORTS_HUGEPAGES
+       select CPU_HAS_LOAD_STORE_LR
        help
          NEC VR5500 and VR5500A series processors implement 64-bit MIPS IV
          instruction set.
@@ -1629,6 +1642,7 @@ config CPU_NEVADA
        select CPU_SUPPORTS_32BIT_KERNEL
        select CPU_SUPPORTS_64BIT_KERNEL
        select CPU_SUPPORTS_HUGEPAGES
+       select CPU_HAS_LOAD_STORE_LR
        help
          QED / PMC-Sierra RM52xx-series ("Nevada") processors.
 
@@ -1636,6 +1650,7 @@ config CPU_R8000
        bool "R8000"
        depends on SYS_HAS_CPU_R8000
        select CPU_HAS_PREFETCH
+       select CPU_HAS_LOAD_STORE_LR
        select CPU_SUPPORTS_64BIT_KERNEL
        help
          MIPS Technologies R8000 processors.  Note these processors are
@@ -1645,6 +1660,7 @@ config CPU_R10000
        bool "R10000"
        depends on SYS_HAS_CPU_R10000
        select CPU_HAS_PREFETCH
+       select CPU_HAS_LOAD_STORE_LR
        select CPU_SUPPORTS_32BIT_KERNEL
        select CPU_SUPPORTS_64BIT_KERNEL
        select CPU_SUPPORTS_HIGHMEM
@@ -1656,6 +1672,7 @@ config CPU_RM7000
        bool "RM7000"
        depends on SYS_HAS_CPU_RM7000
        select CPU_HAS_PREFETCH
+       select CPU_HAS_LOAD_STORE_LR
        select CPU_SUPPORTS_32BIT_KERNEL
        select CPU_SUPPORTS_64BIT_KERNEL
        select CPU_SUPPORTS_HIGHMEM
@@ -1664,6 +1681,7 @@ config CPU_RM7000
 config CPU_SB1
        bool "SB1"
        depends on SYS_HAS_CPU_SB1
+       select CPU_HAS_LOAD_STORE_LR
        select CPU_SUPPORTS_32BIT_KERNEL
        select CPU_SUPPORTS_64BIT_KERNEL
        select CPU_SUPPORTS_HIGHMEM
@@ -1674,6 +1692,7 @@ config CPU_CAVIUM_OCTEON
        bool "Cavium Octeon processor"
        depends on SYS_HAS_CPU_CAVIUM_OCTEON
        select CPU_HAS_PREFETCH
+       select CPU_HAS_LOAD_STORE_LR
        select CPU_SUPPORTS_64BIT_KERNEL
        select WEAK_ORDERING
        select CPU_SUPPORTS_HIGHMEM
@@ -1703,6 +1722,7 @@ config CPU_BMIPS
        select WEAK_ORDERING
        select CPU_SUPPORTS_HIGHMEM
        select CPU_HAS_PREFETCH
+       select CPU_HAS_LOAD_STORE_LR
        select CPU_SUPPORTS_CPUFREQ
        select MIPS_EXTERNAL_TIMER
        help
@@ -1711,6 +1731,7 @@ config CPU_BMIPS
 config CPU_XLR
        bool "Netlogic XLR SoC"
        depends on SYS_HAS_CPU_XLR
+       select CPU_HAS_LOAD_STORE_LR
        select CPU_SUPPORTS_32BIT_KERNEL
        select CPU_SUPPORTS_64BIT_KERNEL
        select CPU_SUPPORTS_HIGHMEM
@@ -1729,6 +1750,7 @@ config CPU_XLP
        select WEAK_ORDERING
        select WEAK_REORDERING_BEYOND_LLSC
        select CPU_HAS_PREFETCH
+       select CPU_HAS_LOAD_STORE_LR
        select CPU_MIPSR2
        select CPU_SUPPORTS_HUGEPAGES
        select MIPS_ASID_BITS_VARIABLE
@@ -1834,12 +1856,14 @@ config CPU_LOONGSON2
        select CPU_SUPPORTS_HIGHMEM
        select CPU_SUPPORTS_HUGEPAGES
        select ARCH_HAS_PHYS_TO_DMA
+       select CPU_HAS_LOAD_STORE_LR
 
 config CPU_LOONGSON1
        bool
        select CPU_MIPS32
        select CPU_MIPSR1
        select CPU_HAS_PREFETCH
+       select CPU_HAS_LOAD_STORE_LR
        select CPU_SUPPORTS_32BIT_KERNEL
        select CPU_SUPPORTS_HIGHMEM
        select CPU_SUPPORTS_CPUFREQ
@@ -2453,6 +2477,13 @@ config XKS01
 config CPU_HAS_RIXI
        bool
 
+config CPU_HAS_LOAD_STORE_LR
+       bool
+       help
+         CPU has support for unaligned load and store instructions:
+         LWL, LWR, SWL, SWR (Load/store word left/right).
+         LDL, LDR, SDL, SDR (Load/store doubleword left/right, for 64bit systems).
+
 #
 # Vectored interrupt mode is an R2 feature
 #
index 2d0b912f9e3e40a987a5a481c7066bf46dcf4acb..ce446eed62d28eb969fd217624ccab9cc6ae068d 100644 (file)
@@ -130,7 +130,7 @@ do {                                                        \
                        : "r" (addr), "i" (-EFAULT));       \
 } while(0)
 
-#ifndef CONFIG_CPU_MIPSR6
+#ifdef CONFIG_CPU_HAS_LOAD_STORE_LR
 #define     _LoadW(addr, value, res, type)   \
 do {                                                        \
                __asm__ __volatile__ (                      \
@@ -151,8 +151,8 @@ do {                                                        \
                        : "r" (addr), "i" (-EFAULT));       \
 } while(0)
 
-#else
-/* MIPSR6 has no lwl instruction */
+#else /* !CONFIG_CPU_HAS_LOAD_STORE_LR */
+/* For CPUs without lwl instruction */
 #define     _LoadW(addr, value, res, type) \
 do {                                                        \
                __asm__ __volatile__ (                      \
@@ -186,7 +186,7 @@ do {                                                        \
                        : "r" (addr), "i" (-EFAULT));       \
 } while(0)
 
-#endif /* CONFIG_CPU_MIPSR6 */
+#endif /* !CONFIG_CPU_HAS_LOAD_STORE_LR */
 
 #define     _LoadHWU(addr, value, res, type) \
 do {                                                        \
@@ -212,7 +212,7 @@ do {                                                        \
                        : "r" (addr), "i" (-EFAULT));       \
 } while(0)
 
-#ifndef CONFIG_CPU_MIPSR6
+#ifdef CONFIG_CPU_HAS_LOAD_STORE_LR
 #define     _LoadWU(addr, value, res, type)  \
 do {                                                        \
                __asm__ __volatile__ (                      \
@@ -255,8 +255,8 @@ do {                                                        \
                        : "r" (addr), "i" (-EFAULT));       \
 } while(0)
 
-#else
-/* MIPSR6 has not lwl and ldl instructions */
+#else /* !CONFIG_CPU_HAS_LOAD_STORE_LR */
+/* For CPUs without lwl and ldl instructions */
 #define            _LoadWU(addr, value, res, type) \
 do {                                                        \
                __asm__ __volatile__ (                      \
@@ -339,7 +339,7 @@ do {                                                        \
                        : "r" (addr), "i" (-EFAULT));       \
 } while(0)
 
-#endif /* CONFIG_CPU_MIPSR6 */
+#endif /* !CONFIG_CPU_HAS_LOAD_STORE_LR */
 
 
 #define     _StoreHW(addr, value, res, type) \
@@ -365,7 +365,7 @@ do {                                                        \
                        : "r" (value), "r" (addr), "i" (-EFAULT));\
 } while(0)
 
-#ifndef CONFIG_CPU_MIPSR6
+#ifdef CONFIG_CPU_HAS_LOAD_STORE_LR
 #define     _StoreW(addr, value, res, type)  \
 do {                                                        \
                __asm__ __volatile__ (                      \
@@ -406,8 +406,7 @@ do {                                                        \
                : "r" (value), "r" (addr), "i" (-EFAULT));  \
 } while(0)
 
-#else
-/* MIPSR6 has no swl and sdl instructions */
+#else /* !CONFIG_CPU_HAS_LOAD_STORE_LR */
 #define     _StoreW(addr, value, res, type)  \
 do {                                                        \
                __asm__ __volatile__ (                      \
@@ -483,7 +482,7 @@ do {                                                        \
                : "memory");                                \
 } while(0)
 
-#endif /* CONFIG_CPU_MIPSR6 */
+#endif /* !CONFIG_CPU_HAS_LOAD_STORE_LR */
 
 #else /* __BIG_ENDIAN */
 
@@ -509,7 +508,7 @@ do {                                                        \
                        : "r" (addr), "i" (-EFAULT));       \
 } while(0)
 
-#ifndef CONFIG_CPU_MIPSR6
+#ifdef CONFIG_CPU_HAS_LOAD_STORE_LR
 #define     _LoadW(addr, value, res, type)   \
 do {                                                        \
                __asm__ __volatile__ (                      \
@@ -530,8 +529,8 @@ do {                                                        \
                        : "r" (addr), "i" (-EFAULT));       \
 } while(0)
 
-#else
-/* MIPSR6 has no lwl instruction */
+#else  /* !CONFIG_CPU_HAS_LOAD_STORE_LR */
+/* For CPUs without lwl instruction */
 #define     _LoadW(addr, value, res, type) \
 do {                                                        \
                __asm__ __volatile__ (                      \
@@ -565,7 +564,7 @@ do {                                                        \
                        : "r" (addr), "i" (-EFAULT));       \
 } while(0)
 
-#endif /* CONFIG_CPU_MIPSR6 */
+#endif /* !CONFIG_CPU_HAS_LOAD_STORE_LR */
 
 
 #define     _LoadHWU(addr, value, res, type) \
@@ -592,7 +591,7 @@ do {                                                        \
                        : "r" (addr), "i" (-EFAULT));       \
 } while(0)
 
-#ifndef CONFIG_CPU_MIPSR6
+#ifdef CONFIG_CPU_HAS_LOAD_STORE_LR
 #define     _LoadWU(addr, value, res, type)  \
 do {                                                        \
                __asm__ __volatile__ (                      \
@@ -635,8 +634,8 @@ do {                                                        \
                        : "r" (addr), "i" (-EFAULT));       \
 } while(0)
 
-#else
-/* MIPSR6 has not lwl and ldl instructions */
+#else /* !CONFIG_CPU_HAS_LOAD_STORE_LR */
+/* For CPUs without lwl and ldl instructions */
 #define            _LoadWU(addr, value, res, type) \
 do {                                                        \
                __asm__ __volatile__ (                      \
@@ -718,7 +717,7 @@ do {                                                        \
                        : "=&r" (value), "=r" (res)         \
                        : "r" (addr), "i" (-EFAULT));       \
 } while(0)
-#endif /* CONFIG_CPU_MIPSR6 */
+#endif /* !CONFIG_CPU_HAS_LOAD_STORE_LR */
 
 #define     _StoreHW(addr, value, res, type) \
 do {                                                        \
@@ -743,7 +742,7 @@ do {                                                        \
                        : "r" (value), "r" (addr), "i" (-EFAULT));\
 } while(0)
 
-#ifndef CONFIG_CPU_MIPSR6
+#ifdef CONFIG_CPU_HAS_LOAD_STORE_LR
 #define     _StoreW(addr, value, res, type)  \
 do {                                                        \
                __asm__ __volatile__ (                      \
@@ -784,8 +783,8 @@ do {                                                        \
                : "r" (value), "r" (addr), "i" (-EFAULT));  \
 } while(0)
 
-#else
-/* MIPSR6 has no swl and sdl instructions */
+#else /* !CONFIG_CPU_HAS_LOAD_STORE_LR */
+/* For CPUs without swl and sdl instructions */
 #define     _StoreW(addr, value, res, type)  \
 do {                                                        \
                __asm__ __volatile__ (                      \
@@ -861,7 +860,7 @@ do {                                                        \
                : "memory");                                \
 } while(0)
 
-#endif /* CONFIG_CPU_MIPSR6 */
+#endif /* !CONFIG_CPU_HAS_LOAD_STORE_LR */
 #endif
 
 #define LoadHWU(addr, value, res)      _LoadHWU(addr, value, res, kernel)
index 03e3304d6ae58b23b238652cd9cf796018d0355b..207b320aa81dd0c05e0560a37a5b19e13a6e65f5 100644 (file)
         and    t0, src, ADDRMASK
        PREFS(  0, 2*32(src) )
        PREFD(  1, 2*32(dst) )
-#ifndef CONFIG_CPU_MIPSR6
+#ifdef CONFIG_CPU_HAS_LOAD_STORE_LR
        bnez    t1, .Ldst_unaligned\@
         nop
        bnez    t0, .Lsrc_unaligned_dst_aligned\@
        bne     rem, len, 1b
        .set    noreorder
 
-#ifndef CONFIG_CPU_MIPSR6
+#ifdef CONFIG_CPU_HAS_LOAD_STORE_LR
        /*
         * src and dst are aligned, need to copy rem bytes (rem < NBYTES)
         * A loop would do only a byte at a time with possible branch
        bne     len, rem, 1b
        .set    noreorder
 
-#endif /* !CONFIG_CPU_MIPSR6 */
+#endif /* CONFIG_CPU_HAS_LOAD_STORE_LR */
 .Lcopy_bytes_checklen\@:
        beqz    len, .Ldone\@
         nop
        jr      ra
         nop
 
-#ifdef CONFIG_CPU_MIPSR6
+#ifndef CONFIG_CPU_HAS_LOAD_STORE_LR
 .Lcopy_unaligned_bytes\@:
 1:
        COPY_BYTE(0)
        ADD     src, src, 8
        b       1b
         ADD    dst, dst, 8
-#endif /* CONFIG_CPU_MIPSR6 */
+#endif /* !CONFIG_CPU_HAS_LOAD_STORE_LR */
        .if __memcpy == 1
        END(memcpy)
        .set __memcpy, 0
index 3a6f34ef5ffc38edf71fe616b2888af9b6dc6f30..fd37f718bb1fb9ec3032dfcf3d8b29d969211b2b 100644 (file)
        .set            at
 #endif
 
-#ifndef CONFIG_CPU_MIPSR6
+#ifdef CONFIG_CPU_HAS_LOAD_STORE_LR
        R10KCBARRIER(0(ra))
 #ifdef __MIPSEB__
        EX(LONG_S_L, a1, (a0), .Lfirst_fixup\@) /* make word/dword aligned */
        PTR_SUBU        a0, t0                  /* long align ptr */
        PTR_ADDU        a2, t0                  /* correct size */
 
-#else /* CONFIG_CPU_MIPSR6 */
+#else /* !CONFIG_CPU_HAS_LOAD_STORE_LR */
 #define STORE_BYTE(N)                          \
        EX(sb, a1, N(a0), .Lbyte_fixup\@);      \
        beqz            t0, 0f;                 \
        ori             a0, STORMASK
        xori            a0, STORMASK
        PTR_ADDIU       a0, STORSIZE
-#endif /* CONFIG_CPU_MIPSR6 */
+#endif /* !CONFIG_CPU_HAS_LOAD_STORE_LR */
 1:     ori             t1, a2, 0x3f            /* # of full blocks */
        xori            t1, 0x3f
        beqz            t1, .Lmemset_partial\@  /* no block to fill */
        andi            a2, STORMASK            /* At most one long to go */
 
        beqz            a2, 1f
-#ifndef CONFIG_CPU_MIPSR6
+#ifdef CONFIG_CPU_HAS_LOAD_STORE_LR
         PTR_ADDU       a0, a2                  /* What's left */
        R10KCBARRIER(0(ra))
 #ifdef __MIPSEB__
        .hidden __memset
        .endif
 
-#ifdef CONFIG_CPU_MIPSR6
+#ifndef CONFIG_CPU_HAS_LOAD_STORE_LR
 .Lbyte_fixup\@:
        /*
         * unset_bytes = (#bytes - (#unaligned bytes)) - (-#unaligned bytes remaining + 1) + 1
        PTR_SUBU        a2, t0
        jr              ra
         PTR_ADDIU      a2, 1
-#endif /* CONFIG_CPU_MIPSR6 */
+#endif /* !CONFIG_CPU_HAS_LOAD_STORE_LR */
 
 .Lfirst_fixup\@:
        /* unset_bytes already in a2 */