Browse Source

Merge branch 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus

Pull MIPS fixes from Ralf Baechle:
 "The pending MIPS fixes for 3.19.  All across the field and nothing
  particularly severe or dramatic"

* 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus: (23 commits)
  IRQCHIP: mips-gic: Avoid rerouting timer IRQs for smp-cmp
  MIPS: Fix syscall_get_nr for the syscall exit tracing.
  MIPS: elf2ecoff: Ignore PT_MIPS_ABIFLAGS program headers.
  MIPS: elf2ecoff: Rewrite main processing loop to switch.
  MIPS: fork: Fix MSA/FPU/DSP context duplication race
  MIPS: Fix C0_Pagegrain[IEC] support.
  MIPS: traps: Fix inline asm ctc1 missing .set hardfloat
  MIPS: mipsregs.h: Add write_32bit_cp1_register()
  MIPS: Fix kernel lockup or crash after CPU offline/online
  MIPS: OCTEON: fix kernel crash when offlining a CPU
  MIPS: ARC: Fix build error.
  MIPS: IRQ: Fix disable_irq on CPU IRQs
  MIPS: smp-mt,smp-cmp: Enable all HW IRQs on secondary CPUs
  MIPS: Fix restart of indirect syscalls
  MIPS: ELF: fix loading o32 binaries on 64-bit kernels
  MIPS: mips-cm: Fix sparse warnings
  MIPS: Kconfig: Fix recursive dependency.
  MIPS: Compat: Fix build error if CONFIG_MIPS32_COMPAT but no compat ABI.
  MIPS: JZ4740: Fixup #include's (sparse)
  MIPS: Wire up execveat(2).
  ...
Linus Torvalds 10 năm trước cách đây
mục cha
commit
dbf3b7ddba

+ 10 - 13
arch/mips/Kconfig

@@ -2656,27 +2656,21 @@ config TRAD_SIGNALS
 	bool
 	bool
 
 
 config MIPS32_COMPAT
 config MIPS32_COMPAT
-	bool "Kernel support for Linux/MIPS 32-bit binary compatibility"
-	depends on 64BIT
-	help
-	  Select this option if you want Linux/MIPS 32-bit binary
-	  compatibility. Since all software available for Linux/MIPS is
-	  currently 32-bit you should say Y here.
+	bool
 
 
 config COMPAT
 config COMPAT
 	bool
 	bool
-	depends on MIPS32_COMPAT
-	select ARCH_WANT_OLD_COMPAT_IPC
-	default y
 
 
 config SYSVIPC_COMPAT
 config SYSVIPC_COMPAT
 	bool
 	bool
-	depends on COMPAT && SYSVIPC
-	default y
 
 
 config MIPS32_O32
 config MIPS32_O32
 	bool "Kernel support for o32 binaries"
 	bool "Kernel support for o32 binaries"
-	depends on MIPS32_COMPAT
+	depends on 64BIT
+	select ARCH_WANT_OLD_COMPAT_IPC
+	select COMPAT
+	select MIPS32_COMPAT
+	select SYSVIPC_COMPAT if SYSVIPC
 	help
 	help
 	  Select this option if you want to run o32 binaries.  These are pure
 	  Select this option if you want to run o32 binaries.  These are pure
 	  32-bit binaries as used by the 32-bit Linux/MIPS port.  Most of
 	  32-bit binaries as used by the 32-bit Linux/MIPS port.  Most of
@@ -2686,7 +2680,10 @@ config MIPS32_O32
 
 
 config MIPS32_N32
 config MIPS32_N32
 	bool "Kernel support for n32 binaries"
 	bool "Kernel support for n32 binaries"
-	depends on MIPS32_COMPAT
+	depends on 64BIT
+	select COMPAT
+	select MIPS32_COMPAT
+	select SYSVIPC_COMPAT if SYSVIPC
 	help
 	help
 	  Select this option if you want to run n32 binaries.  These are
 	  Select this option if you want to run n32 binaries.  These are
 	  64-bit binaries using 32-bit quantities for addressing and certain
 	  64-bit binaries using 32-bit quantities for addressing and certain

+ 36 - 28
arch/mips/boot/elf2ecoff.c

@@ -49,7 +49,8 @@
 /*
 /*
  * Some extra ELF definitions
  * Some extra ELF definitions
  */
  */
-#define PT_MIPS_REGINFO 0x70000000	/* Register usage information */
+#define PT_MIPS_REGINFO 	0x70000000	/* Register usage information */
+#define PT_MIPS_ABIFLAGS	0x70000003	/* Records ABI related flags  */
 
 
 /* -------------------------------------------------------------------- */
 /* -------------------------------------------------------------------- */
 
 
@@ -349,39 +350,46 @@ int main(int argc, char *argv[])
 
 
 	for (i = 0; i < ex.e_phnum; i++) {
 	for (i = 0; i < ex.e_phnum; i++) {
 		/* Section types we can ignore... */
 		/* Section types we can ignore... */
-		if (ph[i].p_type == PT_NULL || ph[i].p_type == PT_NOTE ||
-		    ph[i].p_type == PT_PHDR
-		    || ph[i].p_type == PT_MIPS_REGINFO)
+		switch (ph[i].p_type) {
+		case PT_NULL:
+		case PT_NOTE:
+		case PT_PHDR:
+		case PT_MIPS_REGINFO:
+		case PT_MIPS_ABIFLAGS:
 			continue;
 			continue;
-		/* Section types we can't handle... */
-		else if (ph[i].p_type != PT_LOAD) {
-			fprintf(stderr,
-				"Program header %d type %d can't be converted.\n",
-				ex.e_phnum, ph[i].p_type);
-			exit(1);
-		}
-		/* Writable (data) segment? */
-		if (ph[i].p_flags & PF_W) {
-			struct sect ndata, nbss;
 
 
-			ndata.vaddr = ph[i].p_vaddr;
-			ndata.len = ph[i].p_filesz;
-			nbss.vaddr = ph[i].p_vaddr + ph[i].p_filesz;
-			nbss.len = ph[i].p_memsz - ph[i].p_filesz;
+		case PT_LOAD:
+			/* Writable (data) segment? */
+			if (ph[i].p_flags & PF_W) {
+				struct sect ndata, nbss;
+
+				ndata.vaddr = ph[i].p_vaddr;
+				ndata.len = ph[i].p_filesz;
+				nbss.vaddr = ph[i].p_vaddr + ph[i].p_filesz;
+				nbss.len = ph[i].p_memsz - ph[i].p_filesz;
 
 
-			combine(&data, &ndata, 0);
-			combine(&bss, &nbss, 1);
-		} else {
-			struct sect ntxt;
+				combine(&data, &ndata, 0);
+				combine(&bss, &nbss, 1);
+			} else {
+				struct sect ntxt;
 
 
-			ntxt.vaddr = ph[i].p_vaddr;
-			ntxt.len = ph[i].p_filesz;
+				ntxt.vaddr = ph[i].p_vaddr;
+				ntxt.len = ph[i].p_filesz;
 
 
-			combine(&text, &ntxt, 0);
+				combine(&text, &ntxt, 0);
+			}
+			/* Remember the lowest segment start address. */
+			if (ph[i].p_vaddr < cur_vma)
+				cur_vma = ph[i].p_vaddr;
+			break;
+
+		default:
+			/* Section types we can't handle... */
+			fprintf(stderr,
+				"Program header %d type %d can't be converted.\n",
+				ex.e_phnum, ph[i].p_type);
+			exit(1);
 		}
 		}
-		/* Remember the lowest segment start address. */
-		if (ph[i].p_vaddr < cur_vma)
-			cur_vma = ph[i].p_vaddr;
 	}
 	}
 
 
 	/* Sections must be in order to be converted... */
 	/* Sections must be in order to be converted... */

+ 0 - 2
arch/mips/cavium-octeon/smp.c

@@ -240,9 +240,7 @@ static int octeon_cpu_disable(void)
 
 
 	set_cpu_online(cpu, false);
 	set_cpu_online(cpu, false);
 	cpu_clear(cpu, cpu_callin_map);
 	cpu_clear(cpu, cpu_callin_map);
-	local_irq_disable();
 	octeon_fixup_irqs();
 	octeon_fixup_irqs();
-	local_irq_enable();
 
 
 	flush_cache_all();
 	flush_cache_all();
 	local_flush_tlb_all();
 	local_flush_tlb_all();

+ 4 - 12
arch/mips/configs/malta_defconfig

@@ -132,7 +132,6 @@ CONFIG_IP_NF_MATCH_ECN=m
 CONFIG_IP_NF_MATCH_TTL=m
 CONFIG_IP_NF_MATCH_TTL=m
 CONFIG_IP_NF_FILTER=m
 CONFIG_IP_NF_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
 CONFIG_IP_NF_TARGET_REJECT=m
-CONFIG_IP_NF_TARGET_ULOG=m
 CONFIG_IP_NF_MANGLE=m
 CONFIG_IP_NF_MANGLE=m
 CONFIG_IP_NF_TARGET_CLUSTERIP=m
 CONFIG_IP_NF_TARGET_CLUSTERIP=m
 CONFIG_IP_NF_TARGET_ECN=m
 CONFIG_IP_NF_TARGET_ECN=m
@@ -175,7 +174,6 @@ CONFIG_BRIDGE_EBT_MARK_T=m
 CONFIG_BRIDGE_EBT_REDIRECT=m
 CONFIG_BRIDGE_EBT_REDIRECT=m
 CONFIG_BRIDGE_EBT_SNAT=m
 CONFIG_BRIDGE_EBT_SNAT=m
 CONFIG_BRIDGE_EBT_LOG=m
 CONFIG_BRIDGE_EBT_LOG=m
-CONFIG_BRIDGE_EBT_ULOG=m
 CONFIG_BRIDGE_EBT_NFLOG=m
 CONFIG_BRIDGE_EBT_NFLOG=m
 CONFIG_IP_SCTP=m
 CONFIG_IP_SCTP=m
 CONFIG_BRIDGE=m
 CONFIG_BRIDGE=m
@@ -220,8 +218,6 @@ CONFIG_NET_ACT_SKBEDIT=m
 CONFIG_NET_CLS_IND=y
 CONFIG_NET_CLS_IND=y
 CONFIG_CFG80211=m
 CONFIG_CFG80211=m
 CONFIG_MAC80211=m
 CONFIG_MAC80211=m
-CONFIG_MAC80211_RC_PID=y
-CONFIG_MAC80211_RC_DEFAULT_PID=y
 CONFIG_MAC80211_MESH=y
 CONFIG_MAC80211_MESH=y
 CONFIG_RFKILL=m
 CONFIG_RFKILL=m
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
@@ -248,19 +244,13 @@ CONFIG_ATA_OVER_ETH=m
 CONFIG_IDE=y
 CONFIG_IDE=y
 CONFIG_BLK_DEV_IDECD=y
 CONFIG_BLK_DEV_IDECD=y
 CONFIG_IDE_GENERIC=y
 CONFIG_IDE_GENERIC=y
-CONFIG_BLK_DEV_GENERIC=y
-CONFIG_BLK_DEV_PIIX=y
-CONFIG_BLK_DEV_IT8213=m
-CONFIG_BLK_DEV_TC86C001=m
 CONFIG_RAID_ATTRS=m
 CONFIG_RAID_ATTRS=m
-CONFIG_SCSI=m
-CONFIG_BLK_DEV_SD=m
+CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
 CONFIG_CHR_DEV_ST=m
 CONFIG_CHR_DEV_OSST=m
 CONFIG_CHR_DEV_OSST=m
 CONFIG_BLK_DEV_SR=m
 CONFIG_BLK_DEV_SR=m
 CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=m
 CONFIG_CHR_DEV_SG=m
-CONFIG_SCSI_MULTI_LUN=y
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_LOGGING=y
 CONFIG_SCSI_LOGGING=y
 CONFIG_SCSI_SCAN_ASYNC=y
 CONFIG_SCSI_SCAN_ASYNC=y
@@ -273,6 +263,8 @@ CONFIG_SCSI_AACRAID=m
 CONFIG_SCSI_AIC7XXX=m
 CONFIG_SCSI_AIC7XXX=m
 CONFIG_AIC7XXX_RESET_DELAY_MS=15000
 CONFIG_AIC7XXX_RESET_DELAY_MS=15000
 # CONFIG_AIC7XXX_DEBUG_ENABLE is not set
 # CONFIG_AIC7XXX_DEBUG_ENABLE is not set
+CONFIG_ATA=y
+CONFIG_ATA_PIIX=y
 CONFIG_MD=y
 CONFIG_MD=y
 CONFIG_BLK_DEV_MD=m
 CONFIG_BLK_DEV_MD=m
 CONFIG_MD_LINEAR=m
 CONFIG_MD_LINEAR=m
@@ -340,6 +332,7 @@ CONFIG_UIO=m
 CONFIG_UIO_CIF=m
 CONFIG_UIO_CIF=m
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS=y
 CONFIG_REISERFS_FS=m
 CONFIG_REISERFS_FS=m
 CONFIG_REISERFS_PROC_INFO=y
 CONFIG_REISERFS_PROC_INFO=y
 CONFIG_REISERFS_FS_XATTR=y
 CONFIG_REISERFS_FS_XATTR=y
@@ -441,4 +434,3 @@ CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_TWOFISH=m
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
-CONFIG_CRC16=m

+ 26 - 17
arch/mips/include/asm/fpu.h

@@ -64,7 +64,7 @@ static inline int __enable_fpu(enum fpu_mode mode)
 			return SIGFPE;
 			return SIGFPE;
 
 
 		/* set FRE */
 		/* set FRE */
-		write_c0_config5(read_c0_config5() | MIPS_CONF5_FRE);
+		set_c0_config5(MIPS_CONF5_FRE);
 		goto fr_common;
 		goto fr_common;
 
 
 	case FPU_64BIT:
 	case FPU_64BIT:
@@ -74,8 +74,10 @@ static inline int __enable_fpu(enum fpu_mode mode)
 #endif
 #endif
 		/* fall through */
 		/* fall through */
 	case FPU_32BIT:
 	case FPU_32BIT:
-		/* clear FRE */
-		write_c0_config5(read_c0_config5() & ~MIPS_CONF5_FRE);
+		if (cpu_has_fre) {
+			/* clear FRE */
+			clear_c0_config5(MIPS_CONF5_FRE);
+		}
 fr_common:
 fr_common:
 		/* set CU1 & change FR appropriately */
 		/* set CU1 & change FR appropriately */
 		fr = (int)mode & FPU_FR_MASK;
 		fr = (int)mode & FPU_FR_MASK;
@@ -182,25 +184,32 @@ static inline int init_fpu(void)
 	int ret = 0;
 	int ret = 0;
 
 
 	if (cpu_has_fpu) {
 	if (cpu_has_fpu) {
+		unsigned int config5;
+
 		ret = __own_fpu();
 		ret = __own_fpu();
-		if (!ret) {
-			unsigned int config5 = read_c0_config5();
-
-			/*
-			 * Ensure FRE is clear whilst running _init_fpu, since
-			 * single precision FP instructions are used. If FRE
-			 * was set then we'll just end up initialising all 32
-			 * 64b registers.
-			 */
-			write_c0_config5(config5 & ~MIPS_CONF5_FRE);
-			enable_fpu_hazard();
+		if (ret)
+			return ret;
 
 
+		if (!cpu_has_fre) {
 			_init_fpu();
 			_init_fpu();
 
 
-			/* Restore FRE */
-			write_c0_config5(config5);
-			enable_fpu_hazard();
+			return 0;
 		}
 		}
+
+		/*
+		 * Ensure FRE is clear whilst running _init_fpu, since
+		 * single precision FP instructions are used. If FRE
+		 * was set then we'll just end up initialising all 32
+		 * 64b registers.
+		 */
+		config5 = clear_c0_config5(MIPS_CONF5_FRE);
+		enable_fpu_hazard();
+
+		_init_fpu();
+
+		/* Restore FRE */
+		write_c0_config5(config5);
+		enable_fpu_hazard();
 	} else
 	} else
 		fpu_emulator_init_fpu();
 		fpu_emulator_init_fpu();
 
 

+ 3 - 3
arch/mips/include/asm/fw/arc/hinv.h

@@ -119,7 +119,7 @@ union key_u {
 #define SGI_ARCS_REV	10			/* rev .10, 3/04/92 */
 #define SGI_ARCS_REV	10			/* rev .10, 3/04/92 */
 #endif
 #endif
 
 
-typedef struct component {
+typedef struct {
 	CONFIGCLASS	Class;
 	CONFIGCLASS	Class;
 	CONFIGTYPE	Type;
 	CONFIGTYPE	Type;
 	IDENTIFIERFLAG	Flags;
 	IDENTIFIERFLAG	Flags;
@@ -140,7 +140,7 @@ struct cfgdata {
 };
 };
 
 
 /* System ID */
 /* System ID */
-typedef struct systemid {
+typedef struct {
 	CHAR VendorId[8];
 	CHAR VendorId[8];
 	CHAR ProductId[8];
 	CHAR ProductId[8];
 } SYSTEMID;
 } SYSTEMID;
@@ -166,7 +166,7 @@ typedef enum memorytype {
 #endif	/* _NT_PROM */
 #endif	/* _NT_PROM */
 } MEMORYTYPE;
 } MEMORYTYPE;
 
 
-typedef struct memorydescriptor {
+typedef struct {
 	MEMORYTYPE	Type;
 	MEMORYTYPE	Type;
 	LONG		BasePage;
 	LONG		BasePage;
 	LONG		PageCount;
 	LONG		PageCount;

+ 2 - 2
arch/mips/include/asm/mips-cm.h

@@ -89,9 +89,9 @@ static inline bool mips_cm_has_l2sync(void)
 
 
 /* Macros to ease the creation of register access functions */
 /* Macros to ease the creation of register access functions */
 #define BUILD_CM_R_(name, off)					\
 #define BUILD_CM_R_(name, off)					\
-static inline u32 *addr_gcr_##name(void)			\
+static inline u32 __iomem *addr_gcr_##name(void)		\
 {								\
 {								\
-	return (u32 *)(mips_cm_base + (off));			\
+	return (u32 __iomem *)(mips_cm_base + (off));		\
 }								\
 }								\
 								\
 								\
 static inline u32 read_gcr_##name(void)				\
 static inline u32 read_gcr_##name(void)				\

+ 15 - 0
arch/mips/include/asm/mipsregs.h

@@ -1386,12 +1386,27 @@ do {									\
 	__res;								\
 	__res;								\
 })
 })
 
 
+#define _write_32bit_cp1_register(dest, val, gas_hardfloat)		\
+do {									\
+	__asm__ __volatile__(						\
+	"	.set	push					\n"	\
+	"	.set	reorder					\n"	\
+	"	"STR(gas_hardfloat)"				\n"	\
+	"	ctc1	%0,"STR(dest)"				\n"	\
+	"	.set	pop					\n"	\
+	: : "r" (val));							\
+} while (0)
+
 #ifdef GAS_HAS_SET_HARDFLOAT
 #ifdef GAS_HAS_SET_HARDFLOAT
 #define read_32bit_cp1_register(source)					\
 #define read_32bit_cp1_register(source)					\
 	_read_32bit_cp1_register(source, .set hardfloat)
 	_read_32bit_cp1_register(source, .set hardfloat)
+#define write_32bit_cp1_register(dest, val)				\
+	_write_32bit_cp1_register(dest, val, .set hardfloat)
 #else
 #else
 #define read_32bit_cp1_register(source)					\
 #define read_32bit_cp1_register(source)					\
 	_read_32bit_cp1_register(source, )
 	_read_32bit_cp1_register(source, )
+#define write_32bit_cp1_register(dest, val)				\
+	_write_32bit_cp1_register(dest, val, )
 #endif
 #endif
 
 
 #ifdef HAVE_AS_DSP
 #ifdef HAVE_AS_DSP

+ 1 - 7
arch/mips/include/asm/syscall.h

@@ -29,13 +29,7 @@
 static inline long syscall_get_nr(struct task_struct *task,
 static inline long syscall_get_nr(struct task_struct *task,
 				  struct pt_regs *regs)
 				  struct pt_regs *regs)
 {
 {
-	/* O32 ABI syscall() - Either 64-bit with O32 or 32-bit */
-	if ((config_enabled(CONFIG_32BIT) ||
-	    test_tsk_thread_flag(task, TIF_32BIT_REGS)) &&
-	    (regs->regs[2] == __NR_syscall))
-		return regs->regs[4];
-	else
-		return regs->regs[2];
+	return current_thread_info()->syscall;
 }
 }
 
 
 static inline unsigned long mips_get_syscall_arg(unsigned long *arg,
 static inline unsigned long mips_get_syscall_arg(unsigned long *arg,

+ 1 - 0
arch/mips/include/asm/thread_info.h

@@ -36,6 +36,7 @@ struct thread_info {
 						 */
 						 */
 	struct restart_block	restart_block;
 	struct restart_block	restart_block;
 	struct pt_regs		*regs;
 	struct pt_regs		*regs;
+	long			syscall;	/* syscall number */
 };
 };
 
 
 /*
 /*

+ 9 - 6
arch/mips/include/uapi/asm/unistd.h

@@ -376,16 +376,17 @@
 #define __NR_getrandom			(__NR_Linux + 353)
 #define __NR_getrandom			(__NR_Linux + 353)
 #define __NR_memfd_create		(__NR_Linux + 354)
 #define __NR_memfd_create		(__NR_Linux + 354)
 #define __NR_bpf			(__NR_Linux + 355)
 #define __NR_bpf			(__NR_Linux + 355)
+#define __NR_execveat			(__NR_Linux + 356)
 
 
 /*
 /*
  * Offset of the last Linux o32 flavoured syscall
  * Offset of the last Linux o32 flavoured syscall
  */
  */
-#define __NR_Linux_syscalls		355
+#define __NR_Linux_syscalls		356
 
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
 
 
 #define __NR_O32_Linux			4000
 #define __NR_O32_Linux			4000
-#define __NR_O32_Linux_syscalls		355
+#define __NR_O32_Linux_syscalls		356
 
 
 #if _MIPS_SIM == _MIPS_SIM_ABI64
 #if _MIPS_SIM == _MIPS_SIM_ABI64
 
 
@@ -709,16 +710,17 @@
 #define __NR_getrandom			(__NR_Linux + 313)
 #define __NR_getrandom			(__NR_Linux + 313)
 #define __NR_memfd_create		(__NR_Linux + 314)
 #define __NR_memfd_create		(__NR_Linux + 314)
 #define __NR_bpf			(__NR_Linux + 315)
 #define __NR_bpf			(__NR_Linux + 315)
+#define __NR_execveat			(__NR_Linux + 316)
 
 
 /*
 /*
  * Offset of the last Linux 64-bit flavoured syscall
  * Offset of the last Linux 64-bit flavoured syscall
  */
  */
-#define __NR_Linux_syscalls		315
+#define __NR_Linux_syscalls		316
 
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */
 
 
 #define __NR_64_Linux			5000
 #define __NR_64_Linux			5000
-#define __NR_64_Linux_syscalls		315
+#define __NR_64_Linux_syscalls		316
 
 
 #if _MIPS_SIM == _MIPS_SIM_NABI32
 #if _MIPS_SIM == _MIPS_SIM_NABI32
 
 
@@ -1046,15 +1048,16 @@
 #define __NR_getrandom			(__NR_Linux + 317)
 #define __NR_getrandom			(__NR_Linux + 317)
 #define __NR_memfd_create		(__NR_Linux + 318)
 #define __NR_memfd_create		(__NR_Linux + 318)
 #define __NR_bpf			(__NR_Linux + 319)
 #define __NR_bpf			(__NR_Linux + 319)
+#define __NR_execveat			(__NR_Linux + 320)
 
 
 /*
 /*
  * Offset of the last N32 flavoured syscall
  * Offset of the last N32 flavoured syscall
  */
  */
-#define __NR_Linux_syscalls		319
+#define __NR_Linux_syscalls		320
 
 
 #endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */
 #endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */
 
 
 #define __NR_N32_Linux			6000
 #define __NR_N32_Linux			6000
-#define __NR_N32_Linux_syscalls		319
+#define __NR_N32_Linux_syscalls		320
 
 
 #endif /* _UAPI_ASM_UNISTD_H */
 #endif /* _UAPI_ASM_UNISTD_H */

+ 3 - 0
arch/mips/jz4740/irq.c

@@ -30,6 +30,9 @@
 #include <asm/irq_cpu.h>
 #include <asm/irq_cpu.h>
 
 
 #include <asm/mach-jz4740/base.h>
 #include <asm/mach-jz4740/base.h>
+#include <asm/mach-jz4740/irq.h>
+
+#include "irq.h"
 
 
 static void __iomem *jz_intc_base;
 static void __iomem *jz_intc_base;
 
 

+ 4 - 4
arch/mips/kernel/elf.c

@@ -19,8 +19,8 @@ enum {
 int arch_elf_pt_proc(void *_ehdr, void *_phdr, struct file *elf,
 int arch_elf_pt_proc(void *_ehdr, void *_phdr, struct file *elf,
 		     bool is_interp, struct arch_elf_state *state)
 		     bool is_interp, struct arch_elf_state *state)
 {
 {
-	struct elfhdr *ehdr = _ehdr;
-	struct elf_phdr *phdr = _phdr;
+	struct elf32_hdr *ehdr = _ehdr;
+	struct elf32_phdr *phdr = _phdr;
 	struct mips_elf_abiflags_v0 abiflags;
 	struct mips_elf_abiflags_v0 abiflags;
 	int ret;
 	int ret;
 
 
@@ -48,7 +48,7 @@ int arch_elf_pt_proc(void *_ehdr, void *_phdr, struct file *elf,
 	return 0;
 	return 0;
 }
 }
 
 
-static inline unsigned get_fp_abi(struct elfhdr *ehdr, int in_abi)
+static inline unsigned get_fp_abi(struct elf32_hdr *ehdr, int in_abi)
 {
 {
 	/* If the ABI requirement is provided, simply return that */
 	/* If the ABI requirement is provided, simply return that */
 	if (in_abi != -1)
 	if (in_abi != -1)
@@ -65,7 +65,7 @@ static inline unsigned get_fp_abi(struct elfhdr *ehdr, int in_abi)
 int arch_check_elf(void *_ehdr, bool has_interpreter,
 int arch_check_elf(void *_ehdr, bool has_interpreter,
 		   struct arch_elf_state *state)
 		   struct arch_elf_state *state)
 {
 {
-	struct elfhdr *ehdr = _ehdr;
+	struct elf32_hdr *ehdr = _ehdr;
 	unsigned fp_abi, interp_fp_abi, abi0, abi1;
 	unsigned fp_abi, interp_fp_abi, abi0, abi1;
 
 
 	/* Ignore non-O32 binaries */
 	/* Ignore non-O32 binaries */

+ 4 - 0
arch/mips/kernel/irq_cpu.c

@@ -57,6 +57,8 @@ static struct irq_chip mips_cpu_irq_controller = {
 	.irq_mask_ack	= mask_mips_irq,
 	.irq_mask_ack	= mask_mips_irq,
 	.irq_unmask	= unmask_mips_irq,
 	.irq_unmask	= unmask_mips_irq,
 	.irq_eoi	= unmask_mips_irq,
 	.irq_eoi	= unmask_mips_irq,
+	.irq_disable	= mask_mips_irq,
+	.irq_enable	= unmask_mips_irq,
 };
 };
 
 
 /*
 /*
@@ -93,6 +95,8 @@ static struct irq_chip mips_mt_cpu_irq_controller = {
 	.irq_mask_ack	= mips_mt_cpu_irq_ack,
 	.irq_mask_ack	= mips_mt_cpu_irq_ack,
 	.irq_unmask	= unmask_mips_irq,
 	.irq_unmask	= unmask_mips_irq,
 	.irq_eoi	= unmask_mips_irq,
 	.irq_eoi	= unmask_mips_irq,
+	.irq_disable	= mask_mips_irq,
+	.irq_enable	= unmask_mips_irq,
 };
 };
 
 
 asmlinkage void __weak plat_irq_dispatch(void)
 asmlinkage void __weak plat_irq_dispatch(void)

+ 24 - 12
arch/mips/kernel/process.c

@@ -82,6 +82,30 @@ void flush_thread(void)
 {
 {
 }
 }
 
 
+int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
+{
+	/*
+	 * Save any process state which is live in hardware registers to the
+	 * parent context prior to duplication. This prevents the new child
+	 * state becoming stale if the parent is preempted before copy_thread()
+	 * gets a chance to save the parent's live hardware registers to the
+	 * child context.
+	 */
+	preempt_disable();
+
+	if (is_msa_enabled())
+		save_msa(current);
+	else if (is_fpu_owner())
+		_save_fp(current);
+
+	save_dsp(current);
+
+	preempt_enable();
+
+	*dst = *src;
+	return 0;
+}
+
 int copy_thread(unsigned long clone_flags, unsigned long usp,
 int copy_thread(unsigned long clone_flags, unsigned long usp,
 	unsigned long arg, struct task_struct *p)
 	unsigned long arg, struct task_struct *p)
 {
 {
@@ -92,18 +116,6 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
 
 
 	childksp = (unsigned long)task_stack_page(p) + THREAD_SIZE - 32;
 	childksp = (unsigned long)task_stack_page(p) + THREAD_SIZE - 32;
 
 
-	preempt_disable();
-
-	if (is_msa_enabled())
-		save_msa(p);
-	else if (is_fpu_owner())
-		save_fp(p);
-
-	if (cpu_has_dsp)
-		save_dsp(p);
-
-	preempt_enable();
-
 	/* set up new TSS. */
 	/* set up new TSS. */
 	childregs = (struct pt_regs *) childksp - 1;
 	childregs = (struct pt_regs *) childksp - 1;
 	/*  Put the stack after the struct pt_regs.  */
 	/*  Put the stack after the struct pt_regs.  */

+ 2 - 0
arch/mips/kernel/ptrace.c

@@ -770,6 +770,8 @@ asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall)
 	long ret = 0;
 	long ret = 0;
 	user_exit();
 	user_exit();
 
 
+	current_thread_info()->syscall = syscall;
+
 	if (secure_computing() == -1)
 	if (secure_computing() == -1)
 		return -1;
 		return -1;
 
 

+ 2 - 0
arch/mips/kernel/scall32-o32.S

@@ -181,6 +181,7 @@ illegal_syscall:
 	sll	t1, t0, 2
 	sll	t1, t0, 2
 	beqz	v0, einval
 	beqz	v0, einval
 	lw	t2, sys_call_table(t1)		# syscall routine
 	lw	t2, sys_call_table(t1)		# syscall routine
+	sw	a0, PT_R2(sp)			# call routine directly on restart
 
 
 	/* Some syscalls like execve get their arguments from struct pt_regs
 	/* Some syscalls like execve get their arguments from struct pt_regs
 	   and claim zero arguments in the syscall table. Thus we have to
 	   and claim zero arguments in the syscall table. Thus we have to
@@ -580,3 +581,4 @@ EXPORT(sys_call_table)
 	PTR	sys_getrandom
 	PTR	sys_getrandom
 	PTR	sys_memfd_create
 	PTR	sys_memfd_create
 	PTR	sys_bpf				/* 4355 */
 	PTR	sys_bpf				/* 4355 */
+	PTR	sys_execveat

+ 1 - 0
arch/mips/kernel/scall64-64.S

@@ -435,4 +435,5 @@ EXPORT(sys_call_table)
 	PTR	sys_getrandom
 	PTR	sys_getrandom
 	PTR	sys_memfd_create
 	PTR	sys_memfd_create
 	PTR	sys_bpf				/* 5315 */
 	PTR	sys_bpf				/* 5315 */
+	PTR	sys_execveat
 	.size	sys_call_table,.-sys_call_table
 	.size	sys_call_table,.-sys_call_table

+ 1 - 0
arch/mips/kernel/scall64-n32.S

@@ -428,4 +428,5 @@ EXPORT(sysn32_call_table)
 	PTR	sys_getrandom
 	PTR	sys_getrandom
 	PTR	sys_memfd_create
 	PTR	sys_memfd_create
 	PTR	sys_bpf
 	PTR	sys_bpf
+	PTR	compat_sys_execveat		/* 6320 */
 	.size	sysn32_call_table,.-sysn32_call_table
 	.size	sysn32_call_table,.-sysn32_call_table

+ 2 - 0
arch/mips/kernel/scall64-o32.S

@@ -186,6 +186,7 @@ LEAF(sys32_syscall)
 	dsll	t1, t0, 3
 	dsll	t1, t0, 3
 	beqz	v0, einval
 	beqz	v0, einval
 	ld	t2, sys32_call_table(t1)		# syscall routine
 	ld	t2, sys32_call_table(t1)		# syscall routine
+	sd	a0, PT_R2(sp)		# call routine directly on restart
 
 
 	move	a0, a1			# shift argument registers
 	move	a0, a1			# shift argument registers
 	move	a1, a2
 	move	a1, a2
@@ -565,4 +566,5 @@ EXPORT(sys32_call_table)
 	PTR	sys_getrandom
 	PTR	sys_getrandom
 	PTR	sys_memfd_create
 	PTR	sys_memfd_create
 	PTR	sys_bpf				/* 4355 */
 	PTR	sys_bpf				/* 4355 */
+	PTR	compat_sys_execveat
 	.size	sys32_call_table,.-sys32_call_table
 	.size	sys32_call_table,.-sys32_call_table

+ 2 - 2
arch/mips/kernel/smp-cmp.c

@@ -44,8 +44,8 @@ static void cmp_init_secondary(void)
 	struct cpuinfo_mips *c __maybe_unused = &current_cpu_data;
 	struct cpuinfo_mips *c __maybe_unused = &current_cpu_data;
 
 
 	/* Assume GIC is present */
 	/* Assume GIC is present */
-	change_c0_status(ST0_IM, STATUSF_IP3 | STATUSF_IP4 | STATUSF_IP6 |
-				 STATUSF_IP7);
+	change_c0_status(ST0_IM, STATUSF_IP2 | STATUSF_IP3 | STATUSF_IP4 |
+				 STATUSF_IP5 | STATUSF_IP6 | STATUSF_IP7);
 
 
 	/* Enable per-cpu interrupts: platform specific */
 	/* Enable per-cpu interrupts: platform specific */
 
 

+ 2 - 1
arch/mips/kernel/smp-mt.c

@@ -161,7 +161,8 @@ static void vsmp_init_secondary(void)
 #ifdef CONFIG_MIPS_GIC
 #ifdef CONFIG_MIPS_GIC
 	/* This is Malta specific: IPI,performance and timer interrupts */
 	/* This is Malta specific: IPI,performance and timer interrupts */
 	if (gic_present)
 	if (gic_present)
-		change_c0_status(ST0_IM, STATUSF_IP3 | STATUSF_IP4 |
+		change_c0_status(ST0_IM, STATUSF_IP2 | STATUSF_IP3 |
+					 STATUSF_IP4 | STATUSF_IP5 |
 					 STATUSF_IP6 | STATUSF_IP7);
 					 STATUSF_IP6 | STATUSF_IP7);
 	else
 	else
 #endif
 #endif

+ 1 - 1
arch/mips/kernel/smp.c

@@ -123,10 +123,10 @@ asmlinkage void start_secondary(void)
 	unsigned int cpu;
 	unsigned int cpu;
 
 
 	cpu_probe();
 	cpu_probe();
-	cpu_report();
 	per_cpu_trap_init(false);
 	per_cpu_trap_init(false);
 	mips_clockevent_init();
 	mips_clockevent_init();
 	mp_ops->init_secondary();
 	mp_ops->init_secondary();
+	cpu_report();
 
 
 	/*
 	/*
 	 * XXX parity protection should be folded in here when it's converted
 	 * XXX parity protection should be folded in here when it's converted

+ 2 - 1
arch/mips/kernel/traps.c

@@ -1231,7 +1231,8 @@ static int enable_restore_fp_context(int msa)
 
 
 		/* Restore the scalar FP control & status register */
 		/* Restore the scalar FP control & status register */
 		if (!was_fpu_owner)
 		if (!was_fpu_owner)
-			asm volatile("ctc1 %0, $31" : : "r"(current->thread.fpu.fcr31));
+			write_32bit_cp1_register(CP1_STATUS,
+						 current->thread.fpu.fcr31);
 	}
 	}
 
 
 out:
 out:

+ 2 - 0
arch/mips/mm/tlb-r4k.c

@@ -489,6 +489,8 @@ static void r4k_tlb_configure(void)
 #ifdef CONFIG_64BIT
 #ifdef CONFIG_64BIT
 		pg |= PG_ELPA;
 		pg |= PG_ELPA;
 #endif
 #endif
+		if (cpu_has_rixiex)
+			pg |= PG_IEC;
 		write_c0_pagegrain(pg);
 		write_c0_pagegrain(pg);
 	}
 	}
 
 

+ 27 - 0
drivers/irqchip/irq-mips-gic.c

@@ -37,6 +37,7 @@ static struct irq_domain *gic_irq_domain;
 static int gic_shared_intrs;
 static int gic_shared_intrs;
 static int gic_vpes;
 static int gic_vpes;
 static unsigned int gic_cpu_pin;
 static unsigned int gic_cpu_pin;
+static unsigned int timer_cpu_pin;
 static struct irq_chip gic_level_irq_controller, gic_edge_irq_controller;
 static struct irq_chip gic_level_irq_controller, gic_edge_irq_controller;
 
 
 static void __gic_irq_dispatch(void);
 static void __gic_irq_dispatch(void);
@@ -616,6 +617,8 @@ static int gic_local_irq_domain_map(struct irq_domain *d, unsigned int virq,
 			gic_write(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE_MAP), val);
 			gic_write(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE_MAP), val);
 			break;
 			break;
 		case GIC_LOCAL_INT_TIMER:
 		case GIC_LOCAL_INT_TIMER:
+			/* CONFIG_MIPS_CMP workaround (see __gic_init) */
+			val = GIC_MAP_TO_PIN_MSK | timer_cpu_pin;
 			gic_write(GIC_REG(VPE_OTHER, GIC_VPE_TIMER_MAP), val);
 			gic_write(GIC_REG(VPE_OTHER, GIC_VPE_TIMER_MAP), val);
 			break;
 			break;
 		case GIC_LOCAL_INT_PERFCTR:
 		case GIC_LOCAL_INT_PERFCTR:
@@ -713,12 +716,36 @@ static void __init __gic_init(unsigned long gic_base_addr,
 	if (cpu_has_veic) {
 	if (cpu_has_veic) {
 		/* Always use vector 1 in EIC mode */
 		/* Always use vector 1 in EIC mode */
 		gic_cpu_pin = 0;
 		gic_cpu_pin = 0;
+		timer_cpu_pin = gic_cpu_pin;
 		set_vi_handler(gic_cpu_pin + GIC_PIN_TO_VEC_OFFSET,
 		set_vi_handler(gic_cpu_pin + GIC_PIN_TO_VEC_OFFSET,
 			       __gic_irq_dispatch);
 			       __gic_irq_dispatch);
 	} else {
 	} else {
 		gic_cpu_pin = cpu_vec - GIC_CPU_PIN_OFFSET;
 		gic_cpu_pin = cpu_vec - GIC_CPU_PIN_OFFSET;
 		irq_set_chained_handler(MIPS_CPU_IRQ_BASE + cpu_vec,
 		irq_set_chained_handler(MIPS_CPU_IRQ_BASE + cpu_vec,
 					gic_irq_dispatch);
 					gic_irq_dispatch);
+		/*
+		 * With the CMP implementation of SMP (deprecated), other CPUs
+		 * are started by the bootloader and put into a timer based
+		 * waiting poll loop. We must not re-route those CPU's local
+		 * timer interrupts as the wait instruction will never finish,
+		 * so just handle whatever CPU interrupt it is routed to by
+		 * default.
+		 *
+		 * This workaround should be removed when CMP support is
+		 * dropped.
+		 */
+		if (IS_ENABLED(CONFIG_MIPS_CMP) &&
+		    gic_local_irq_is_routable(GIC_LOCAL_INT_TIMER)) {
+			timer_cpu_pin = gic_read(GIC_REG(VPE_LOCAL,
+							 GIC_VPE_TIMER_MAP)) &
+					GIC_MAP_MSK;
+			irq_set_chained_handler(MIPS_CPU_IRQ_BASE +
+						GIC_CPU_PIN_OFFSET +
+						timer_cpu_pin,
+						gic_irq_dispatch);
+		} else {
+			timer_cpu_pin = gic_cpu_pin;
+		}
 	}
 	}
 
 
 	gic_irq_domain = irq_domain_add_simple(node, GIC_NUM_LOCAL_INTRS +
 	gic_irq_domain = irq_domain_add_simple(node, GIC_NUM_LOCAL_INTRS +