Unverified Commit 932afdee authored by Yasha Cherikovsky's avatar Yasha Cherikovsky Committed by Paul Burton
Browse files

MIPS: Add Kconfig variable for CPUs with unaligned load/store instructions



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: default avatarYasha Cherikovsky <yasha.che3@gmail.com>
Signed-off-by: default avatarPaul 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
parent d9df9fb9
Loading
Loading
Loading
Loading
+33 −2
Original line number Diff line number Diff line
@@ -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
#
+23 −24
Original line number Diff line number Diff line
@@ -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)
+5 −5
Original line number Diff line number Diff line
@@ -297,7 +297,7 @@
	 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\@
@@ -385,7 +385,7 @@
	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
@@ -487,7 +487,7 @@
	bne	len, rem, 1b
	.set	noreorder

#endif /* !CONFIG_CPU_MIPSR6 */
#endif /* CONFIG_CPU_HAS_LOAD_STORE_LR */
.Lcopy_bytes_checklen\@:
	beqz	len, .Ldone\@
	 nop
@@ -516,7 +516,7 @@
	jr	ra
	 nop

#ifdef CONFIG_CPU_MIPSR6
#ifndef CONFIG_CPU_HAS_LOAD_STORE_LR
.Lcopy_unaligned_bytes\@:
1:
	COPY_BYTE(0)
@@ -530,7 +530,7 @@
	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
+6 −6
Original line number Diff line number Diff line
@@ -112,7 +112,7 @@
	.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 */
@@ -122,7 +122,7 @@
	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;			\
@@ -145,7 +145,7 @@
	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 */
@@ -185,7 +185,7 @@
	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__
@@ -230,7 +230,7 @@
	.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
@@ -239,7 +239,7 @@
	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 */