Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dae0af78 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull ARM fixes from Russell King:
 "Fixes for ARM, the most notable being the fix from Nathan Lynch to fix
  the state of various registers during execve, to ensure that data
  can't be leaked between two executables.

  Fixes from Victor Kamensky for get_user() on big endian platforms,
  since the addition of 8-byte get_user() support broke these fairly
  badly.

  A fix from Sudeep Holla for affinity setting when hotplugging CPU 0.

  A fix from Stephen Boyd for a perf-induced sleep attempt while atomic.

  Lastly, a correctness fix for emulation of the SWP instruction on
  ARMv7+, and a fix for wrong carry handling when updating the
  translation table base address on LPAE platforms"

* 'fixes' of git://ftp.arm.linux.org.uk/~rmk/linux-arm:
  ARM: 8149/1: perf: Don't sleep while atomic when enabling per-cpu interrupts
  ARM: 8148/1: flush TLS and thumbee register state during exec
  ARM: 8151/1: add missing exports for asm functions required by get_user macro
  ARM: 8137/1: fix get_user BE behavior for target variable with size of 8 bytes
  ARM: 8135/1: Fix in-correct barrier usage in SWP{B} emulation
  ARM: 8133/1: use irq_set_affinity with force=false when migrating irqs
  ARM: 8132/1: LPAE: drop wrong carry flag correction after adding TTBR1_OFFSET
parents c1f03b48 505013bc
Loading
Loading
Loading
Loading
+62 −0
Original line number Diff line number Diff line
#ifndef __ASMARM_TLS_H
#define __ASMARM_TLS_H

#include <linux/compiler.h>
#include <asm/thread_info.h>

#ifdef __ASSEMBLY__
#include <asm/asm-offsets.h>
	.macro switch_tls_none, base, tp, tpuser, tmp1, tmp2
@@ -50,6 +53,47 @@
#endif

#ifndef __ASSEMBLY__

static inline void set_tls(unsigned long val)
{
	struct thread_info *thread;

	thread = current_thread_info();

	thread->tp_value[0] = val;

	/*
	 * This code runs with preemption enabled and therefore must
	 * be reentrant with respect to switch_tls.
	 *
	 * We need to ensure ordering between the shadow state and the
	 * hardware state, so that we don't corrupt the hardware state
	 * with a stale shadow state during context switch.
	 *
	 * If we're preempted here, switch_tls will load TPIDRURO from
	 * thread_info upon resuming execution and the following mcr
	 * is merely redundant.
	 */
	barrier();

	if (!tls_emu) {
		if (has_tls_reg) {
			asm("mcr p15, 0, %0, c13, c0, 3"
			    : : "r" (val));
		} else {
			/*
			 * User space must never try to access this
			 * directly.  Expect your app to break
			 * eventually if you do so.  The user helper
			 * at 0xffff0fe0 must be used instead.  (see
			 * entry-armv.S for details)
			 */
			*((unsigned int *)0xffff0ff0) = val;
		}

	}
}

static inline unsigned long get_tpuser(void)
{
	unsigned long reg = 0;
@@ -59,5 +103,23 @@ static inline unsigned long get_tpuser(void)

	return reg;
}

static inline void set_tpuser(unsigned long val)
{
	/* Since TPIDRURW is fully context-switched (unlike TPIDRURO),
	 * we need not update thread_info.
	 */
	if (has_tls_reg && !tls_emu) {
		asm("mcr p15, 0, %0, c13, c0, 2"
		    : : "r" (val));
	}
}

static inline void flush_tls(void)
{
	set_tls(0);
	set_tpuser(0);
}

#endif
#endif	/* __ASMARM_TLS_H */
+39 −9
Original line number Diff line number Diff line
@@ -107,8 +107,11 @@ static inline void set_fs(mm_segment_t fs)
extern int __get_user_1(void *);
extern int __get_user_2(void *);
extern int __get_user_4(void *);
extern int __get_user_lo8(void *);
extern int __get_user_32t_8(void *);
extern int __get_user_8(void *);
extern int __get_user_64t_1(void *);
extern int __get_user_64t_2(void *);
extern int __get_user_64t_4(void *);

#define __GUP_CLOBBER_1	"lr", "cc"
#ifdef CONFIG_CPU_USE_DOMAINS
@@ -117,7 +120,7 @@ extern int __get_user_8(void *);
#define __GUP_CLOBBER_2 "lr", "cc"
#endif
#define __GUP_CLOBBER_4	"lr", "cc"
#define __GUP_CLOBBER_lo8 "lr", "cc"
#define __GUP_CLOBBER_32t_8 "lr", "cc"
#define __GUP_CLOBBER_8	"lr", "cc"

#define __get_user_x(__r2,__p,__e,__l,__s)				\
@@ -131,12 +134,30 @@ extern int __get_user_8(void *);

/* narrowing a double-word get into a single 32bit word register: */
#ifdef __ARMEB__
#define __get_user_xb(__r2, __p, __e, __l, __s)				\
	__get_user_x(__r2, __p, __e, __l, lo8)
#define __get_user_x_32t(__r2, __p, __e, __l, __s)				\
	__get_user_x(__r2, __p, __e, __l, 32t_8)
#else
#define __get_user_xb __get_user_x
#define __get_user_x_32t __get_user_x
#endif

/*
 * storing result into proper least significant word of 64bit target var,
 * different only for big endian case where 64 bit __r2 lsw is r3:
 */
#ifdef __ARMEB__
#define __get_user_x_64t(__r2, __p, __e, __l, __s)		        \
	   __asm__ __volatile__ (					\
		__asmeq("%0", "r0") __asmeq("%1", "r2")			\
		__asmeq("%3", "r1")					\
		"bl	__get_user_64t_" #__s				\
		: "=&r" (__e), "=r" (__r2)				\
		: "0" (__p), "r" (__l)					\
		: __GUP_CLOBBER_##__s)
#else
#define __get_user_x_64t __get_user_x
#endif


#define __get_user_check(x,p)							\
	({								\
		unsigned long __limit = current_thread_info()->addr_limit - 1; \
@@ -146,17 +167,26 @@ extern int __get_user_8(void *);
		register int __e asm("r0");				\
		switch (sizeof(*(__p))) {				\
		case 1:							\
			if (sizeof((x)) >= 8)				\
				__get_user_x_64t(__r2, __p, __e, __l, 1); \
			else						\
				__get_user_x(__r2, __p, __e, __l, 1);	\
			break;						\
		case 2:							\
			if (sizeof((x)) >= 8)				\
				__get_user_x_64t(__r2, __p, __e, __l, 2); \
			else						\
				__get_user_x(__r2, __p, __e, __l, 2);	\
			break;						\
		case 4:							\
			if (sizeof((x)) >= 8)				\
				__get_user_x_64t(__r2, __p, __e, __l, 4); \
			else						\
				__get_user_x(__r2, __p, __e, __l, 4);	\
			break;						\
		case 8:							\
			if (sizeof((x)) < 8)				\
				__get_user_xb(__r2, __p, __e, __l, 4);	\
				__get_user_x_32t(__r2, __p, __e, __l, 4); \
			else						\
				__get_user_x(__r2, __p, __e, __l, 8);	\
			break;						\
+8 −0
Original line number Diff line number Diff line
@@ -98,6 +98,14 @@ EXPORT_SYMBOL(__clear_user);
EXPORT_SYMBOL(__get_user_1);
EXPORT_SYMBOL(__get_user_2);
EXPORT_SYMBOL(__get_user_4);
EXPORT_SYMBOL(__get_user_8);

#ifdef __ARMEB__
EXPORT_SYMBOL(__get_user_64t_1);
EXPORT_SYMBOL(__get_user_64t_2);
EXPORT_SYMBOL(__get_user_64t_4);
EXPORT_SYMBOL(__get_user_32t_8);
#endif

EXPORT_SYMBOL(__put_user_1);
EXPORT_SYMBOL(__put_user_2);
+1 −1
Original line number Diff line number Diff line
@@ -175,7 +175,7 @@ static bool migrate_one_irq(struct irq_desc *desc)
	c = irq_data_get_irq_chip(d);
	if (!c->irq_set_affinity)
		pr_debug("IRQ%u: unable to set affinity\n", d->irq);
	else if (c->irq_set_affinity(d, affinity, true) == IRQ_SET_MASK_OK && ret)
	else if (c->irq_set_affinity(d, affinity, false) == IRQ_SET_MASK_OK && ret)
		cpumask_copy(d->affinity, affinity);

	return ret;
+4 −10
Original line number Diff line number Diff line
@@ -76,21 +76,15 @@ static struct pmu_hw_events *cpu_pmu_get_cpu_events(void)

static void cpu_pmu_enable_percpu_irq(void *data)
{
	struct arm_pmu *cpu_pmu = data;
	struct platform_device *pmu_device = cpu_pmu->plat_device;
	int irq = platform_get_irq(pmu_device, 0);
	int irq = *(int *)data;

	enable_percpu_irq(irq, IRQ_TYPE_NONE);
	cpumask_set_cpu(smp_processor_id(), &cpu_pmu->active_irqs);
}

static void cpu_pmu_disable_percpu_irq(void *data)
{
	struct arm_pmu *cpu_pmu = data;
	struct platform_device *pmu_device = cpu_pmu->plat_device;
	int irq = platform_get_irq(pmu_device, 0);
	int irq = *(int *)data;

	cpumask_clear_cpu(smp_processor_id(), &cpu_pmu->active_irqs);
	disable_percpu_irq(irq);
}

@@ -103,7 +97,7 @@ static void cpu_pmu_free_irq(struct arm_pmu *cpu_pmu)

	irq = platform_get_irq(pmu_device, 0);
	if (irq >= 0 && irq_is_percpu(irq)) {
		on_each_cpu(cpu_pmu_disable_percpu_irq, cpu_pmu, 1);
		on_each_cpu(cpu_pmu_disable_percpu_irq, &irq, 1);
		free_percpu_irq(irq, &percpu_pmu);
	} else {
		for (i = 0; i < irqs; ++i) {
@@ -138,7 +132,7 @@ static int cpu_pmu_request_irq(struct arm_pmu *cpu_pmu, irq_handler_t handler)
				irq);
			return err;
		}
		on_each_cpu(cpu_pmu_enable_percpu_irq, cpu_pmu, 1);
		on_each_cpu(cpu_pmu_enable_percpu_irq, &irq, 1);
	} else {
		for (i = 0; i < irqs; ++i) {
			err = 0;
Loading