diff options
Diffstat (limited to 'arch')
| -rw-r--r-- | arch/arm/Kconfig | 10 | ||||
| -rw-r--r-- | arch/arm/Kconfig.debug | 12 | ||||
| -rw-r--r-- | arch/arm/common/bL_switcher.c | 6 | ||||
| -rw-r--r-- | arch/arm/common/mcpm_entry.c | 5 | ||||
| -rw-r--r-- | arch/arm/include/asm/div64.h | 2 | ||||
| -rw-r--r-- | arch/arm/include/asm/mcpm.h | 7 | ||||
| -rw-r--r-- | arch/arm/include/uapi/asm/unistd.h | 1 | ||||
| -rw-r--r-- | arch/arm/kernel/calls.S | 1 | ||||
| -rw-r--r-- | arch/arm/kernel/head.S | 2 | ||||
| -rw-r--r-- | arch/arm/kernel/machine_kexec.c | 7 | ||||
| -rw-r--r-- | arch/arm/mm/Kconfig | 8 | ||||
| -rw-r--r-- | arch/arm/vfp/vfpdouble.c | 2 | ||||
| -rw-r--r-- | arch/arm/vfp/vfpsingle.c | 2 | ||||
| -rw-r--r-- | arch/um/include/shared/os.h | 1 | ||||
| -rw-r--r-- | arch/um/kernel/physmem.c | 1 | ||||
| -rw-r--r-- | arch/um/os-Linux/file.c | 6 | ||||
| -rw-r--r-- | arch/um/os-Linux/main.c | 1 | ||||
| -rw-r--r-- | arch/um/os-Linux/mem.c | 372 | ||||
| -rw-r--r-- | arch/x86/vdso/vdso-layout.lds.S | 19 | 
19 files changed, 136 insertions, 329 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index ab438cb5af55..53e99eb543d9 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -30,9 +30,9 @@ config ARM  	select HAVE_ARCH_SECCOMP_FILTER if (AEABI && !OABI_COMPAT)  	select HAVE_ARCH_TRACEHOOK  	select HAVE_BPF_JIT +	select HAVE_CC_STACKPROTECTOR  	select HAVE_CONTEXT_TRACKING  	select HAVE_C_RECORDMCOUNT -	select HAVE_CC_STACKPROTECTOR  	select HAVE_DEBUG_KMEMLEAK  	select HAVE_DMA_API_DEBUG  	select HAVE_DMA_ATTRS @@ -422,8 +422,8 @@ config ARCH_EFM32  	bool "Energy Micro efm32"  	depends on !MMU  	select ARCH_REQUIRE_GPIOLIB -	select AUTO_ZRELADDR  	select ARM_NVIC +	select AUTO_ZRELADDR  	select CLKSRC_OF  	select COMMON_CLK  	select CPU_V7M @@ -511,8 +511,8 @@ config ARCH_IXP4XX  	bool "IXP4xx-based"  	depends on MMU  	select ARCH_HAS_DMA_SET_COHERENT_MASK -	select ARCH_SUPPORTS_BIG_ENDIAN  	select ARCH_REQUIRE_GPIOLIB +	select ARCH_SUPPORTS_BIG_ENDIAN  	select CLKSRC_MMIO  	select CPU_XSCALE  	select DMABOUNCE if PCI @@ -1575,8 +1575,8 @@ config BIG_LITTLE  config BL_SWITCHER  	bool "big.LITTLE switcher support"  	depends on BIG_LITTLE && MCPM && HOTPLUG_CPU -	select CPU_PM  	select ARM_CPU_SUSPEND +	select CPU_PM  	help  	  The big.LITTLE "switcher" provides the core functionality to  	  transparently handle transition between a cluster of A15's @@ -1920,9 +1920,9 @@ config XEN  	depends on CPU_V7 && !CPU_V6  	depends on !GENERIC_ATOMIC64  	depends on MMU +	select ARCH_DMA_ADDR_T_64BIT  	select ARM_PSCI  	select SWIOTLB_XEN -	select ARCH_DMA_ADDR_T_64BIT  	help  	  Say Y if you want to run Linux in a Virtual Machine on Xen on ARM. diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index 4a2fc0bf6fc9..eab8ecbe69c1 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -1030,9 +1030,9 @@ config DEBUG_UART_PHYS  	default 0x40100000 if DEBUG_PXA_UART1  	default 0x42000000 if ARCH_GEMINI  	default 0x7c0003f8 if FOOTBRIDGE -	default 0x80230000 if DEBUG_PICOXCELL_UART  	default 0x80070000 if DEBUG_IMX23_UART  	default 0x80074000 if DEBUG_IMX28_UART +	default 0x80230000 if DEBUG_PICOXCELL_UART  	default 0x808c0000 if ARCH_EP93XX  	default 0x90020000 if DEBUG_NSPIRE_CLASSIC_UART || DEBUG_NSPIRE_CX_UART  	default 0xb0090000 if DEBUG_VEXPRESS_UART0_CRX @@ -1096,22 +1096,22 @@ config DEBUG_UART_VIRT  	default 0xfeb26000 if DEBUG_RK3X_UART1  	default 0xfeb30c00 if DEBUG_KEYSTONE_UART0  	default 0xfeb31000 if DEBUG_KEYSTONE_UART1 -	default 0xfec12000 if DEBUG_MVEBU_UART || DEBUG_MVEBU_UART_ALTERNATE -	default 0xfed60000 if DEBUG_RK29_UART0 -	default 0xfed64000 if DEBUG_RK29_UART1 || DEBUG_RK3X_UART2 -	default 0xfed68000 if DEBUG_RK29_UART2 || DEBUG_RK3X_UART3  	default 0xfec02000 if DEBUG_SOCFPGA_UART +	default 0xfec12000 if DEBUG_MVEBU_UART || DEBUG_MVEBU_UART_ALTERNATE  	default 0xfec20000 if DEBUG_DAVINCI_DMx_UART0  	default 0xfed0c000 if DEBUG_DAVINCI_DA8XX_UART1  	default 0xfed0d000 if DEBUG_DAVINCI_DA8XX_UART2  	default 0xfed12000 if ARCH_KIRKWOOD +	default 0xfed60000 if DEBUG_RK29_UART0 +	default 0xfed64000 if DEBUG_RK29_UART1 || DEBUG_RK3X_UART2 +	default 0xfed68000 if DEBUG_RK29_UART2 || DEBUG_RK3X_UART3  	default 0xfedc0000 if ARCH_EP93XX  	default 0xfee003f8 if FOOTBRIDGE  	default 0xfee20000 if DEBUG_NSPIRE_CLASSIC_UART || DEBUG_NSPIRE_CX_UART -	default 0xfef36000 if DEBUG_HIGHBANK_UART  	default 0xfee82340 if ARCH_IOP13XX  	default 0xfef00000 if ARCH_IXP4XX && !CPU_BIG_ENDIAN  	default 0xfef00003 if ARCH_IXP4XX && CPU_BIG_ENDIAN +	default 0xfef36000 if DEBUG_HIGHBANK_UART  	default 0xfefff700 if ARCH_IOP33X  	default 0xff003000 if DEBUG_U300_UART  	default DEBUG_UART_PHYS if !MMU diff --git a/arch/arm/common/bL_switcher.c b/arch/arm/common/bL_switcher.c index 5774b6ea7ad5..f01c0ee0c87e 100644 --- a/arch/arm/common/bL_switcher.c +++ b/arch/arm/common/bL_switcher.c @@ -797,10 +797,8 @@ static int __init bL_switcher_init(void)  {  	int ret; -	if (MAX_NR_CLUSTERS != 2) { -		pr_err("%s: only dual cluster systems are supported\n", __func__); -		return -EINVAL; -	} +	if (!mcpm_is_available()) +		return -ENODEV;  	cpu_notifier(bL_switcher_hotplug_callback, 0); diff --git a/arch/arm/common/mcpm_entry.c b/arch/arm/common/mcpm_entry.c index 1e361abc29eb..86fd60fefbc9 100644 --- a/arch/arm/common/mcpm_entry.c +++ b/arch/arm/common/mcpm_entry.c @@ -48,6 +48,11 @@ int __init mcpm_platform_register(const struct mcpm_platform_ops *ops)  	return 0;  } +bool mcpm_is_available(void) +{ +	return (platform_ops) ? true : false; +} +  int mcpm_cpu_power_up(unsigned int cpu, unsigned int cluster)  {  	if (!platform_ops) diff --git a/arch/arm/include/asm/div64.h b/arch/arm/include/asm/div64.h index 191ada6e4d2d..662c7bd06108 100644 --- a/arch/arm/include/asm/div64.h +++ b/arch/arm/include/asm/div64.h @@ -156,7 +156,7 @@  		/* Select the best insn combination to perform the   */	\  		/* actual __m * __n / (__p << 64) operation.         */	\  		if (!__c) {						\ -			asm (	"umull	%Q0, %R0, %1, %Q2\n\t"		\ +			asm (	"umull	%Q0, %R0, %Q1, %Q2\n\t"		\  				"mov	%Q0, #0"			\  				: "=&r" (__res)				\  				: "r" (__m), "r" (__n)			\ diff --git a/arch/arm/include/asm/mcpm.h b/arch/arm/include/asm/mcpm.h index 608516ebabfe..a5ff410dcdb6 100644 --- a/arch/arm/include/asm/mcpm.h +++ b/arch/arm/include/asm/mcpm.h @@ -54,6 +54,13 @@ void mcpm_set_early_poke(unsigned cpu, unsigned cluster,   */  /** + * mcpm_is_available - returns whether MCPM is initialized and available + * + * This returns true or false accordingly. + */ +bool mcpm_is_available(void); + +/**   * mcpm_cpu_power_up - make given CPU in given cluster runable   *   * @cpu: CPU number within given cluster diff --git a/arch/arm/include/uapi/asm/unistd.h b/arch/arm/include/uapi/asm/unistd.h index fb5584d0cc05..ba94446c72d9 100644 --- a/arch/arm/include/uapi/asm/unistd.h +++ b/arch/arm/include/uapi/asm/unistd.h @@ -408,6 +408,7 @@  #define __NR_finit_module		(__NR_SYSCALL_BASE+379)  #define __NR_sched_setattr		(__NR_SYSCALL_BASE+380)  #define __NR_sched_getattr		(__NR_SYSCALL_BASE+381) +#define __NR_renameat2			(__NR_SYSCALL_BASE+382)  /*   * This may need to be greater than __NR_last_syscall+1 in order to diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S index 166e945de832..8f51bdcdacbb 100644 --- a/arch/arm/kernel/calls.S +++ b/arch/arm/kernel/calls.S @@ -391,6 +391,7 @@  		CALL(sys_finit_module)  /* 380 */	CALL(sys_sched_setattr)  		CALL(sys_sched_getattr) +		CALL(sys_renameat2)  #ifndef syscalls_counted  .equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls  #define syscalls_counted diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index f8c08839edf3..591d6e4a6492 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S @@ -587,7 +587,7 @@ __fixup_pv_table:  	add	r6, r6, r3	@ adjust __pv_phys_pfn_offset address  	add	r7, r7, r3	@ adjust __pv_offset address  	mov	r0, r8, lsr #12	@ convert to PFN -	str	r0, [r6, #LOW_OFFSET]	@ save computed PHYS_OFFSET to __pv_phys_pfn_offset +	str	r0, [r6]	@ save computed PHYS_OFFSET to __pv_phys_pfn_offset  	strcc	ip, [r7, #HIGH_OFFSET]	@ save to __pv_offset high bits  	mov	r6, r3, lsr #24	@ constant for add/sub instructions  	teq	r3, r6, lsl #24 @ must be 16MiB aligned diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c index f0d180d8b29f..8cf0996aa1a8 100644 --- a/arch/arm/kernel/machine_kexec.c +++ b/arch/arm/kernel/machine_kexec.c @@ -184,3 +184,10 @@ void machine_kexec(struct kimage *image)  	soft_restart(reboot_entry_phys);  } + +void arch_crash_save_vmcoreinfo(void) +{ +#ifdef CONFIG_ARM_LPAE +	VMCOREINFO_CONFIG(ARM_LPAE); +#endif +} diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index f5ad9ee70426..5bf7c3c3b301 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -420,29 +420,29 @@ config CPU_32v3  	bool  	select CPU_USE_DOMAINS if MMU  	select NEEDS_SYSCALL_FOR_CMPXCHG if SMP -	select TLS_REG_EMUL if SMP || !MMU  	select NEED_KUSER_HELPERS +	select TLS_REG_EMUL if SMP || !MMU  config CPU_32v4  	bool  	select CPU_USE_DOMAINS if MMU  	select NEEDS_SYSCALL_FOR_CMPXCHG if SMP -	select TLS_REG_EMUL if SMP || !MMU  	select NEED_KUSER_HELPERS +	select TLS_REG_EMUL if SMP || !MMU  config CPU_32v4T  	bool  	select CPU_USE_DOMAINS if MMU  	select NEEDS_SYSCALL_FOR_CMPXCHG if SMP -	select TLS_REG_EMUL if SMP || !MMU  	select NEED_KUSER_HELPERS +	select TLS_REG_EMUL if SMP || !MMU  config CPU_32v5  	bool  	select CPU_USE_DOMAINS if MMU  	select NEEDS_SYSCALL_FOR_CMPXCHG if SMP -	select TLS_REG_EMUL if SMP || !MMU  	select NEED_KUSER_HELPERS +	select TLS_REG_EMUL if SMP || !MMU  config CPU_32v6  	bool diff --git a/arch/arm/vfp/vfpdouble.c b/arch/arm/vfp/vfpdouble.c index 6cac43bd1d86..423f56dd4028 100644 --- a/arch/arm/vfp/vfpdouble.c +++ b/arch/arm/vfp/vfpdouble.c @@ -866,6 +866,8 @@ vfp_double_multiply_accumulate(int dd, int dn, int dm, u32 fpscr, u32 negate, ch  		vdp.sign = vfp_sign_negate(vdp.sign);  	vfp_double_unpack(&vdn, vfp_get_double(dd)); +	if (vdn.exponent == 0 && vdn.significand) +		vfp_double_normalise_denormal(&vdn);  	if (negate & NEG_SUBTRACT)  		vdn.sign = vfp_sign_negate(vdn.sign); diff --git a/arch/arm/vfp/vfpsingle.c b/arch/arm/vfp/vfpsingle.c index b252631b406b..4f96c1617aae 100644 --- a/arch/arm/vfp/vfpsingle.c +++ b/arch/arm/vfp/vfpsingle.c @@ -915,6 +915,8 @@ vfp_single_multiply_accumulate(int sd, int sn, s32 m, u32 fpscr, u32 negate, cha  	v = vfp_get_float(sd);  	pr_debug("VFP: s%u = %08x\n", sd, v);  	vfp_single_unpack(&vsn, v); +	if (vsn.exponent == 0 && vsn.significand) +		vfp_single_normalise_denormal(&vsn);  	if (negate & NEG_SUBTRACT)  		vsn.sign = vfp_sign_negate(vsn.sign); diff --git a/arch/um/include/shared/os.h b/arch/um/include/shared/os.h index 75298d3358e7..08eec0b691b0 100644 --- a/arch/um/include/shared/os.h +++ b/arch/um/include/shared/os.h @@ -136,6 +136,7 @@ extern int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg);  extern int os_get_ifname(int fd, char *namebuf);  extern int os_set_slip(int fd);  extern int os_mode_fd(int fd, int mode); +extern int os_fsync_file(int fd);  extern int os_seek_file(int fd, unsigned long long offset);  extern int os_open_file(const char *file, struct openflags flags, int mode); diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c index f116db15d402..30fdd5d0067b 100644 --- a/arch/um/kernel/physmem.c +++ b/arch/um/kernel/physmem.c @@ -103,6 +103,7 @@ void __init setup_physmem(unsigned long start, unsigned long reserve_end,  	 */  	os_seek_file(physmem_fd, __pa(&__syscall_stub_start));  	os_write_file(physmem_fd, &__syscall_stub_start, PAGE_SIZE); +	os_fsync_file(physmem_fd);  	bootmap_size = init_bootmem(pfn, pfn + delta);  	free_bootmem(__pa(reserve_end) + bootmap_size, diff --git a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c index 07a750197bb0..08d90fba952c 100644 --- a/arch/um/os-Linux/file.c +++ b/arch/um/os-Linux/file.c @@ -237,6 +237,12 @@ void os_close_file(int fd)  {  	close(fd);  } +int os_fsync_file(int fd) +{ +	if (fsync(fd) < 0) +	    return -errno; +	return 0; +}  int os_seek_file(int fd, unsigned long long offset)  { diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c index e1704ff600ff..df9191acd926 100644 --- a/arch/um/os-Linux/main.c +++ b/arch/um/os-Linux/main.c @@ -151,6 +151,7 @@ int __init main(int argc, char **argv, char **envp)  #endif  	do_uml_initcalls(); +	change_sig(SIGPIPE, 0);  	ret = linux_main(argc, argv);  	/* diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c index 3c4af77e51a2..897e9ad0c108 100644 --- a/arch/um/os-Linux/mem.c +++ b/arch/um/os-Linux/mem.c @@ -12,337 +12,117 @@  #include <string.h>  #include <sys/stat.h>  #include <sys/mman.h> -#include <sys/param.h> +#include <sys/vfs.h> +#include <linux/magic.h>  #include <init.h>  #include <os.h> -/* Modified by which_tmpdir, which is called during early boot */ -static char *default_tmpdir = "/tmp"; - -/* - *  Modified when creating the physical memory file and when checking - * the tmp filesystem for usability, both happening during early boot. - */ +/* Set by make_tempfile() during early boot. */  static char *tempdir = NULL; -static void __init find_tempdir(void) +/* Check if dir is on tmpfs. Return 0 if yes, -1 if no or error. */ +static int __init check_tmpfs(const char *dir)  { -	const char *dirs[] = { "TMP", "TEMP", "TMPDIR", NULL }; -	int i; -	char *dir = NULL; - -	if (tempdir != NULL) -		/* We've already been called */ -		return; -	for (i = 0; dirs[i]; i++) { -		dir = getenv(dirs[i]); -		if ((dir != NULL) && (*dir != '\0')) -			break; -	} -	if ((dir == NULL) || (*dir == '\0')) -		dir = default_tmpdir; +	struct statfs st; -	tempdir = malloc(strlen(dir) + 2); -	if (tempdir == NULL) { -		fprintf(stderr, "Failed to malloc tempdir, " -			"errno = %d\n", errno); -		return; -	} -	strcpy(tempdir, dir); -	strcat(tempdir, "/"); -} - -/* - * Remove bytes from the front of the buffer and refill it so that if there's a - * partial string that we care about, it will be completed, and we can recognize - * it. - */ -static int pop(int fd, char *buf, size_t size, size_t npop) -{ -	ssize_t n; -	size_t len = strlen(&buf[npop]); - -	memmove(buf, &buf[npop], len + 1); -	n = read(fd, &buf[len], size - len - 1); -	if (n < 0) -		return -errno; - -	buf[len + n] = '\0'; -	return 1; -} - -/* - * This will return 1, with the first character in buf being the - * character following the next instance of c in the file.  This will - * read the file as needed.  If there's an error, -errno is returned; - * if the end of the file is reached, 0 is returned. - */ -static int next(int fd, char *buf, size_t size, char c) -{ -	ssize_t n; -	char *ptr; - -	while ((ptr = strchr(buf, c)) == NULL) { -		n = read(fd, buf, size - 1); -		if (n == 0) -			return 0; -		else if (n < 0) -			return -errno; - -		buf[n] = '\0'; +	printf("Checking if %s is on tmpfs...", dir); +	if (statfs(dir, &st) < 0) { +		printf("%s\n", strerror(errno)); +	} else if (st.f_type != TMPFS_MAGIC) { +		printf("no\n"); +	} else { +		printf("OK\n"); +		return 0;  	} - -	return pop(fd, buf, size, ptr - buf + 1); +	return -1;  }  /* - * Decode an octal-escaped and space-terminated path of the form used by - * /proc/mounts. May be used to decode a path in-place. "out" must be at least - * as large as the input. The output is always null-terminated. "len" gets the - * length of the output, excluding the trailing null. Returns 0 if a full path - * was successfully decoded, otherwise an error. + * Choose the tempdir to use. We want something on tmpfs so that our memory is + * not subject to the host's vm.dirty_ratio. If a tempdir is specified in the + * environment, we use that even if it's not on tmpfs, but we warn the user. + * Otherwise, we try common tmpfs locations, and if no tmpfs directory is found + * then we fall back to /tmp.   */ -static int decode_path(const char *in, char *out, size_t *len) +static char * __init choose_tempdir(void)  { -	char *first = out; -	int c; +	static const char * const vars[] = { +		"TMPDIR", +		"TMP", +		"TEMP", +		NULL +	}; +	static const char fallback_dir[] = "/tmp"; +	static const char * const tmpfs_dirs[] = { +		"/dev/shm", +		fallback_dir, +		NULL +	};  	int i; -	int ret = -EINVAL; -	while (1) { -		switch (*in) { -		case '\0': -			goto out; - -		case ' ': -			ret = 0; -			goto out; - -		case '\\': -			in++; -			c = 0; -			for (i = 0; i < 3; i++) { -				if (*in < '0' || *in > '7') -					goto out; -				c = (c << 3) | (*in++ - '0'); -			} -			*(unsigned char *)out++ = (unsigned char) c; -			break; - -		default: -			*out++ = *in++; -			break; +	const char *dir; + +	printf("Checking environment variables for a tempdir..."); +	for (i = 0; vars[i]; i++) { +		dir = getenv(vars[i]); +		if ((dir != NULL) && (*dir != '\0')) { +			printf("%s\n", dir); +			if (check_tmpfs(dir) >= 0) +				goto done; +			else +				goto warn;  		}  	} +	printf("none found\n"); -out: -	*out = '\0'; -	*len = out - first; -	return ret; -} - -/* - * Computes the length of s when encoded with three-digit octal escape sequences - * for the characters in chars. - */ -static size_t octal_encoded_length(const char *s, const char *chars) -{ -	size_t len = strlen(s); -	while ((s = strpbrk(s, chars)) != NULL) { -		len += 3; -		s++; -	} - -	return len; -} - -enum { -	OUTCOME_NOTHING_MOUNTED, -	OUTCOME_TMPFS_MOUNT, -	OUTCOME_NON_TMPFS_MOUNT, -}; - -/* Read a line of /proc/mounts data looking for a tmpfs mount at "path". */ -static int read_mount(int fd, char *buf, size_t bufsize, const char *path, -		      int *outcome) -{ -	int found; -	int match; -	char *space; -	size_t len; - -	enum { -		MATCH_NONE, -		MATCH_EXACT, -		MATCH_PARENT, -	}; - -	found = next(fd, buf, bufsize, ' '); -	if (found != 1) -		return found; - -	/* -	 * If there's no following space in the buffer, then this path is -	 * truncated, so it can't be the one we're looking for. -	 */ -	space = strchr(buf, ' '); -	if (space) { -		match = MATCH_NONE; -		if (!decode_path(buf, buf, &len)) { -			if (!strcmp(buf, path)) -				match = MATCH_EXACT; -			else if (!strncmp(buf, path, len) -				 && (path[len] == '/' || !strcmp(buf, "/"))) -				match = MATCH_PARENT; -		} - -		found = pop(fd, buf, bufsize, space - buf + 1); -		if (found != 1) -			return found; - -		switch (match) { -		case MATCH_EXACT: -			if (!strncmp(buf, "tmpfs", strlen("tmpfs"))) -				*outcome = OUTCOME_TMPFS_MOUNT; -			else -				*outcome = OUTCOME_NON_TMPFS_MOUNT; -			break; - -		case MATCH_PARENT: -			/* This mount obscures any previous ones. */ -			*outcome = OUTCOME_NOTHING_MOUNTED; -			break; -		} +	for (i = 0; tmpfs_dirs[i]; i++) { +		dir = tmpfs_dirs[i]; +		if (check_tmpfs(dir) >= 0) +			goto done;  	} -	return next(fd, buf, bufsize, '\n'); +	dir = fallback_dir; +warn: +	printf("Warning: tempdir %s is not on tmpfs\n", dir); +done: +	/* Make a copy since getenv results may not remain valid forever. */ +	return strdup(dir);  } -/* which_tmpdir is called only during early boot */ -static int checked_tmpdir = 0; -  /* - * Look for a tmpfs mounted at /dev/shm.  I couldn't find a cleaner - * way to do this than to parse /proc/mounts.  statfs will return the - * same filesystem magic number and fs id for both /dev and /dev/shm - * when they are both tmpfs, so you can't tell if they are different - * filesystems.  Also, there seems to be no other way of finding the - * mount point of a filesystem from within it. - * - * If a /dev/shm tmpfs entry is found, then we switch to using it. - * Otherwise, we stay with the default /tmp. + * Create an unlinked tempfile in a suitable tempdir. template must be the + * basename part of the template with a leading '/'.   */ -static void which_tmpdir(void) +static int __init make_tempfile(const char *template)  { +	char *tempname;  	int fd; -	int found; -	int outcome; -	char *path; -	char *buf; -	size_t bufsize; -	if (checked_tmpdir) -		return; - -	checked_tmpdir = 1; - -	printf("Checking for tmpfs mount on /dev/shm..."); - -	path = realpath("/dev/shm", NULL); -	if (!path) { -		printf("failed to check real path, errno = %d\n", errno); -		return; -	} -	printf("%s...", path); - -	/* -	 * The buffer needs to be able to fit the full octal-escaped path, a -	 * space, and a trailing null in order to successfully decode it. -	 */ -	bufsize = octal_encoded_length(path, " \t\n\\") + 2; - -	if (bufsize < 128) -		bufsize = 128; - -	buf = malloc(bufsize); -	if (!buf) { -		printf("malloc failed, errno = %d\n", errno); -		goto out; -	} -	buf[0] = '\0'; - -	fd = open("/proc/mounts", O_RDONLY); -	if (fd < 0) { -		printf("failed to open /proc/mounts, errno = %d\n", errno); -		goto out1; -	} - -	outcome = OUTCOME_NOTHING_MOUNTED; -	while (1) { -		found = read_mount(fd, buf, bufsize, path, &outcome); -		if (found != 1) -			break; -	} - -	if (found < 0) { -		printf("read returned errno %d\n", -found); -	} else { -		switch (outcome) { -		case OUTCOME_TMPFS_MOUNT: -			printf("OK\n"); -			default_tmpdir = "/dev/shm"; -			break; - -		case OUTCOME_NON_TMPFS_MOUNT: -			printf("not tmpfs\n"); -			break; - -		default: -			printf("nothing mounted on /dev/shm\n"); -			break; +	if (tempdir == NULL) { +		tempdir = choose_tempdir(); +		if (tempdir == NULL) { +			fprintf(stderr, "Failed to choose tempdir: %s\n", +				strerror(errno)); +			return -1;  		}  	} -	close(fd); -out1: -	free(buf); -out: -	free(path); -} - -static int __init make_tempfile(const char *template, char **out_tempname, -				int do_unlink) -{ -	char *tempname; -	int fd; - -	which_tmpdir(); -	tempname = malloc(MAXPATHLEN); +	tempname = malloc(strlen(tempdir) + strlen(template) + 1);  	if (tempname == NULL)  		return -1; -	find_tempdir(); -	if ((tempdir == NULL) || (strlen(tempdir) >= MAXPATHLEN)) -		goto out; - -	if (template[0] != '/') -		strcpy(tempname, tempdir); -	else -		tempname[0] = '\0'; -	strncat(tempname, template, MAXPATHLEN-1-strlen(tempname)); +	strcpy(tempname, tempdir); +	strcat(tempname, template);  	fd = mkstemp(tempname);  	if (fd < 0) {  		fprintf(stderr, "open - cannot create %s: %s\n", tempname,  			strerror(errno));  		goto out;  	} -	if (do_unlink && (unlink(tempname) < 0)) { +	if (unlink(tempname) < 0) {  		perror("unlink");  		goto close;  	} -	if (out_tempname) { -		*out_tempname = tempname; -	} else -		free(tempname); +	free(tempname);  	return fd;  close:  	close(fd); @@ -351,14 +131,14 @@ out:  	return -1;  } -#define TEMPNAME_TEMPLATE "vm_file-XXXXXX" +#define TEMPNAME_TEMPLATE "/vm_file-XXXXXX"  static int __init create_tmp_file(unsigned long long len)  {  	int fd, err;  	char zero; -	fd = make_tempfile(TEMPNAME_TEMPLATE, NULL, 1); +	fd = make_tempfile(TEMPNAME_TEMPLATE);  	if (fd < 0)  		exit(1); @@ -402,7 +182,6 @@ int __init create_mem_file(unsigned long long len)  	return fd;  } -  void __init check_tmpexec(void)  {  	void *addr; @@ -410,14 +189,13 @@ void __init check_tmpexec(void)  	addr = mmap(NULL, UM_KERN_PAGE_SIZE,  		    PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd, 0); -	printf("Checking PROT_EXEC mmap in %s...",tempdir); -	fflush(stdout); +	printf("Checking PROT_EXEC mmap in %s...", tempdir);  	if (addr == MAP_FAILED) {  		err = errno; -		perror("failed"); +		printf("%s\n", strerror(err));  		close(fd);  		if (err == EPERM) -			printf("%s must be not mounted noexec\n",tempdir); +			printf("%s must be not mounted noexec\n", tempdir);  		exit(1);  	}  	printf("OK\n"); diff --git a/arch/x86/vdso/vdso-layout.lds.S b/arch/x86/vdso/vdso-layout.lds.S index 2e263f367b13..9df017ab2285 100644 --- a/arch/x86/vdso/vdso-layout.lds.S +++ b/arch/x86/vdso/vdso-layout.lds.S @@ -9,12 +9,9 @@ SECTIONS  #ifdef BUILD_VDSO32  #include <asm/vdso32.h> -	.hpet_sect : { -		hpet_page = . - VDSO_OFFSET(VDSO_HPET_PAGE); -	} :text :hpet_sect +	hpet_page = . - VDSO_OFFSET(VDSO_HPET_PAGE); -	.vvar_sect : { -		vvar = . - VDSO_OFFSET(VDSO_VVAR_PAGE); +	vvar = . - VDSO_OFFSET(VDSO_VVAR_PAGE);  	/* Place all vvars at the offsets in asm/vvar.h. */  #define EMIT_VVAR(name, offset) vvar_ ## name = vvar + offset; @@ -22,7 +19,6 @@ SECTIONS  #include <asm/vvar.h>  #undef __VVAR_KERNEL_LDS  #undef EMIT_VVAR -	} :text :vvar_sect  #endif  	. = SIZEOF_HEADERS; @@ -61,7 +57,12 @@ SECTIONS  	 */  	. = ALIGN(0x100); -	.text		: { *(.text*) }			:text	=0x90909090 +	.text		: { *(.text*) }			:text	=0x90909090, + +	/* +	 * The comma above works around a bug in gold: +	 * https://sourceware.org/bugzilla/show_bug.cgi?id=16804 +	 */  	/DISCARD/ : {  		*(.discard) @@ -84,8 +85,4 @@ PHDRS  	dynamic		PT_DYNAMIC	FLAGS(4);		/* PF_R */  	note		PT_NOTE		FLAGS(4);		/* PF_R */  	eh_frame_hdr	PT_GNU_EH_FRAME; -#ifdef BUILD_VDSO32 -	vvar_sect	PT_NULL		FLAGS(4);		/* PF_R */ -	hpet_sect	PT_NULL		FLAGS(4);		/* PF_R */ -#endif  }  |