diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-06-17 13:19:13 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-06-17 13:19:13 -0400 |
commit | 9cbbef4efb7cfb6962da57c9e17f5ce4280c14ca (patch) | |
tree | b9d2996b5e4bf11843dda0ac620819f609a097ab | |
parent | 8c2561557415a298965f50d4de2ca99c7d1f1b2c (diff) | |
parent | 0d15ef677839dab8313fbb86c007c3175b638d03 (diff) |
Merge tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux
Pull arm64 fixes from Will Deacon:
"The main things are getting kgdb up and running with upstream GDB
after a protocol change was reverted and fixing our spin_unlock_wait
and spin_is_locked implementations after doing some similar work with
PeterZ on the qspinlock code last week. Whilst we haven't seen any
failures in practice, it's still worth getting this fixed.
Summary:
- Plug the ongoing spin_unlock_wait/spin_is_locked mess
- KGDB protocol fix to sync w/ GDB
- Fix MIDR-based PMU probing for old 32-bit SMP systems
(OMAP4/Realview)
- Minor tweaks to the fault handling path"
* tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux:
arm64: kgdb: Match pstate size with gdbserver protocol
arm64: spinlock: Ensure forward-progress in spin_unlock_wait
arm64: spinlock: fix spin_unlock_wait for LSE atomics
arm64: spinlock: order spin_{is_locked,unlock_wait} against local locks
arm: pmu: Fix non-devicetree probing
arm64: mm: mark fault_info table const
arm64: fix dump_instr when PAN and UAO are in use
-rw-r--r-- | arch/arm64/include/asm/kgdb.h | 45 | ||||
-rw-r--r-- | arch/arm64/include/asm/spinlock.h | 42 | ||||
-rw-r--r-- | arch/arm64/kernel/kgdb.c | 14 | ||||
-rw-r--r-- | arch/arm64/kernel/traps.c | 26 | ||||
-rw-r--r-- | arch/arm64/mm/fault.c | 2 | ||||
-rw-r--r-- | drivers/perf/arm_pmu.c | 2 |
6 files changed, 102 insertions, 29 deletions
diff --git a/arch/arm64/include/asm/kgdb.h b/arch/arm64/include/asm/kgdb.h index f69f69c8120c..da84645525b9 100644 --- a/arch/arm64/include/asm/kgdb.h +++ b/arch/arm64/include/asm/kgdb.h | |||
@@ -38,25 +38,54 @@ extern int kgdb_fault_expected; | |||
38 | #endif /* !__ASSEMBLY__ */ | 38 | #endif /* !__ASSEMBLY__ */ |
39 | 39 | ||
40 | /* | 40 | /* |
41 | * gdb is expecting the following registers layout. | 41 | * gdb remote procotol (well most versions of it) expects the following |
42 | * register layout. | ||
42 | * | 43 | * |
43 | * General purpose regs: | 44 | * General purpose regs: |
44 | * r0-r30: 64 bit | 45 | * r0-r30: 64 bit |
45 | * sp,pc : 64 bit | 46 | * sp,pc : 64 bit |
46 | * pstate : 64 bit | 47 | * pstate : 32 bit |
47 | * Total: 34 | 48 | * Total: 33 + 1 |
48 | * FPU regs: | 49 | * FPU regs: |
49 | * f0-f31: 128 bit | 50 | * f0-f31: 128 bit |
50 | * Total: 32 | ||
51 | * Extra regs | ||
52 | * fpsr & fpcr: 32 bit | 51 | * fpsr & fpcr: 32 bit |
53 | * Total: 2 | 52 | * Total: 32 + 2 |
54 | * | 53 | * |
54 | * To expand a little on the "most versions of it"... when the gdb remote | ||
55 | * protocol for AArch64 was developed it depended on a statement in the | ||
56 | * Architecture Reference Manual that claimed "SPSR_ELx is a 32-bit register". | ||
57 | * and, as a result, allocated only 32-bits for the PSTATE in the remote | ||
58 | * protocol. In fact this statement is still present in ARM DDI 0487A.i. | ||
59 | * | ||
60 | * Unfortunately "is a 32-bit register" has a very special meaning for | ||
61 | * system registers. It means that "the upper bits, bits[63:32], are | ||
62 | * RES0.". RES0 is heavily used in the ARM architecture documents as a | ||
63 | * way to leave space for future architecture changes. So to translate a | ||
64 | * little for people who don't spend their spare time reading ARM architecture | ||
65 | * manuals, what "is a 32-bit register" actually means in this context is | ||
66 | * "is a 64-bit register but one with no meaning allocated to any of the | ||
67 | * upper 32-bits... *yet*". | ||
68 | * | ||
69 | * Perhaps then we should not be surprised that this has led to some | ||
70 | * confusion. Specifically a patch, influenced by the above translation, | ||
71 | * that extended PSTATE to 64-bit was accepted into gdb-7.7 but the patch | ||
72 | * was reverted in gdb-7.8.1 and all later releases, when this was | ||
73 | * discovered to be an undocumented protocol change. | ||
74 | * | ||
75 | * So... it is *not* wrong for us to only allocate 32-bits to PSTATE | ||
76 | * here even though the kernel itself allocates 64-bits for the same | ||
77 | * state. That is because this bit of code tells the kernel how the gdb | ||
78 | * remote protocol (well most versions of it) describes the register state. | ||
79 | * | ||
80 | * Note that if you are using one of the versions of gdb that supports | ||
81 | * the gdb-7.7 version of the protocol you cannot use kgdb directly | ||
82 | * without providing a custom register description (gdb can load new | ||
83 | * protocol descriptions at runtime). | ||
55 | */ | 84 | */ |
56 | 85 | ||
57 | #define _GP_REGS 34 | 86 | #define _GP_REGS 33 |
58 | #define _FP_REGS 32 | 87 | #define _FP_REGS 32 |
59 | #define _EXTRA_REGS 2 | 88 | #define _EXTRA_REGS 3 |
60 | /* | 89 | /* |
61 | * general purpose registers size in bytes. | 90 | * general purpose registers size in bytes. |
62 | * pstate is only 4 bytes. subtract 4 bytes | 91 | * pstate is only 4 bytes. subtract 4 bytes |
diff --git a/arch/arm64/include/asm/spinlock.h b/arch/arm64/include/asm/spinlock.h index fc9682bfe002..e875a5a551d7 100644 --- a/arch/arm64/include/asm/spinlock.h +++ b/arch/arm64/include/asm/spinlock.h | |||
@@ -30,22 +30,53 @@ static inline void arch_spin_unlock_wait(arch_spinlock_t *lock) | |||
30 | { | 30 | { |
31 | unsigned int tmp; | 31 | unsigned int tmp; |
32 | arch_spinlock_t lockval; | 32 | arch_spinlock_t lockval; |
33 | u32 owner; | ||
34 | |||
35 | /* | ||
36 | * Ensure prior spin_lock operations to other locks have completed | ||
37 | * on this CPU before we test whether "lock" is locked. | ||
38 | */ | ||
39 | smp_mb(); | ||
40 | owner = READ_ONCE(lock->owner) << 16; | ||
33 | 41 | ||
34 | asm volatile( | 42 | asm volatile( |
35 | " sevl\n" | 43 | " sevl\n" |
36 | "1: wfe\n" | 44 | "1: wfe\n" |
37 | "2: ldaxr %w0, %2\n" | 45 | "2: ldaxr %w0, %2\n" |
46 | /* Is the lock free? */ | ||
38 | " eor %w1, %w0, %w0, ror #16\n" | 47 | " eor %w1, %w0, %w0, ror #16\n" |
39 | " cbnz %w1, 1b\n" | 48 | " cbz %w1, 3f\n" |
49 | /* Lock taken -- has there been a subsequent unlock->lock transition? */ | ||
50 | " eor %w1, %w3, %w0, lsl #16\n" | ||
51 | " cbz %w1, 1b\n" | ||
52 | /* | ||
53 | * The owner has been updated, so there was an unlock->lock | ||
54 | * transition that we missed. That means we can rely on the | ||
55 | * store-release of the unlock operation paired with the | ||
56 | * load-acquire of the lock operation to publish any of our | ||
57 | * previous stores to the new lock owner and therefore don't | ||
58 | * need to bother with the writeback below. | ||
59 | */ | ||
60 | " b 4f\n" | ||
61 | "3:\n" | ||
62 | /* | ||
63 | * Serialise against any concurrent lockers by writing back the | ||
64 | * unlocked lock value | ||
65 | */ | ||
40 | ARM64_LSE_ATOMIC_INSN( | 66 | ARM64_LSE_ATOMIC_INSN( |
41 | /* LL/SC */ | 67 | /* LL/SC */ |
42 | " stxr %w1, %w0, %2\n" | 68 | " stxr %w1, %w0, %2\n" |
43 | " cbnz %w1, 2b\n", /* Serialise against any concurrent lockers */ | ||
44 | /* LSE atomics */ | ||
45 | " nop\n" | 69 | " nop\n" |
46 | " nop\n") | 70 | " nop\n", |
71 | /* LSE atomics */ | ||
72 | " mov %w1, %w0\n" | ||
73 | " cas %w0, %w0, %2\n" | ||
74 | " eor %w1, %w1, %w0\n") | ||
75 | /* Somebody else wrote to the lock, GOTO 10 and reload the value */ | ||
76 | " cbnz %w1, 2b\n" | ||
77 | "4:" | ||
47 | : "=&r" (lockval), "=&r" (tmp), "+Q" (*lock) | 78 | : "=&r" (lockval), "=&r" (tmp), "+Q" (*lock) |
48 | : | 79 | : "r" (owner) |
49 | : "memory"); | 80 | : "memory"); |
50 | } | 81 | } |
51 | 82 | ||
@@ -148,6 +179,7 @@ static inline int arch_spin_value_unlocked(arch_spinlock_t lock) | |||
148 | 179 | ||
149 | static inline int arch_spin_is_locked(arch_spinlock_t *lock) | 180 | static inline int arch_spin_is_locked(arch_spinlock_t *lock) |
150 | { | 181 | { |
182 | smp_mb(); /* See arch_spin_unlock_wait */ | ||
151 | return !arch_spin_value_unlocked(READ_ONCE(*lock)); | 183 | return !arch_spin_value_unlocked(READ_ONCE(*lock)); |
152 | } | 184 | } |
153 | 185 | ||
diff --git a/arch/arm64/kernel/kgdb.c b/arch/arm64/kernel/kgdb.c index b67531a13136..b5f063e5eff7 100644 --- a/arch/arm64/kernel/kgdb.c +++ b/arch/arm64/kernel/kgdb.c | |||
@@ -58,7 +58,17 @@ struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] = { | |||
58 | { "x30", 8, offsetof(struct pt_regs, regs[30])}, | 58 | { "x30", 8, offsetof(struct pt_regs, regs[30])}, |
59 | { "sp", 8, offsetof(struct pt_regs, sp)}, | 59 | { "sp", 8, offsetof(struct pt_regs, sp)}, |
60 | { "pc", 8, offsetof(struct pt_regs, pc)}, | 60 | { "pc", 8, offsetof(struct pt_regs, pc)}, |
61 | { "pstate", 8, offsetof(struct pt_regs, pstate)}, | 61 | /* |
62 | * struct pt_regs thinks PSTATE is 64-bits wide but gdb remote | ||
63 | * protocol disagrees. Therefore we must extract only the lower | ||
64 | * 32-bits. Look for the big comment in asm/kgdb.h for more | ||
65 | * detail. | ||
66 | */ | ||
67 | { "pstate", 4, offsetof(struct pt_regs, pstate) | ||
68 | #ifdef CONFIG_CPU_BIG_ENDIAN | ||
69 | + 4 | ||
70 | #endif | ||
71 | }, | ||
62 | { "v0", 16, -1 }, | 72 | { "v0", 16, -1 }, |
63 | { "v1", 16, -1 }, | 73 | { "v1", 16, -1 }, |
64 | { "v2", 16, -1 }, | 74 | { "v2", 16, -1 }, |
@@ -128,6 +138,8 @@ sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *task) | |||
128 | memset((char *)gdb_regs, 0, NUMREGBYTES); | 138 | memset((char *)gdb_regs, 0, NUMREGBYTES); |
129 | thread_regs = task_pt_regs(task); | 139 | thread_regs = task_pt_regs(task); |
130 | memcpy((void *)gdb_regs, (void *)thread_regs->regs, GP_REG_BYTES); | 140 | memcpy((void *)gdb_regs, (void *)thread_regs->regs, GP_REG_BYTES); |
141 | /* Special case for PSTATE (check comments in asm/kgdb.h for details) */ | ||
142 | dbg_get_reg(33, gdb_regs + GP_REG_BYTES, thread_regs); | ||
131 | } | 143 | } |
132 | 144 | ||
133 | void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc) | 145 | void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc) |
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c index f7cf463107df..2a43012616b7 100644 --- a/arch/arm64/kernel/traps.c +++ b/arch/arm64/kernel/traps.c | |||
@@ -64,8 +64,7 @@ static void dump_mem(const char *lvl, const char *str, unsigned long bottom, | |||
64 | 64 | ||
65 | /* | 65 | /* |
66 | * We need to switch to kernel mode so that we can use __get_user | 66 | * We need to switch to kernel mode so that we can use __get_user |
67 | * to safely read from kernel space. Note that we now dump the | 67 | * to safely read from kernel space. |
68 | * code first, just in case the backtrace kills us. | ||
69 | */ | 68 | */ |
70 | fs = get_fs(); | 69 | fs = get_fs(); |
71 | set_fs(KERNEL_DS); | 70 | set_fs(KERNEL_DS); |
@@ -111,21 +110,12 @@ static void dump_backtrace_entry(unsigned long where) | |||
111 | print_ip_sym(where); | 110 | print_ip_sym(where); |
112 | } | 111 | } |
113 | 112 | ||
114 | static void dump_instr(const char *lvl, struct pt_regs *regs) | 113 | static void __dump_instr(const char *lvl, struct pt_regs *regs) |
115 | { | 114 | { |
116 | unsigned long addr = instruction_pointer(regs); | 115 | unsigned long addr = instruction_pointer(regs); |
117 | mm_segment_t fs; | ||
118 | char str[sizeof("00000000 ") * 5 + 2 + 1], *p = str; | 116 | char str[sizeof("00000000 ") * 5 + 2 + 1], *p = str; |
119 | int i; | 117 | int i; |
120 | 118 | ||
121 | /* | ||
122 | * We need to switch to kernel mode so that we can use __get_user | ||
123 | * to safely read from kernel space. Note that we now dump the | ||
124 | * code first, just in case the backtrace kills us. | ||
125 | */ | ||
126 | fs = get_fs(); | ||
127 | set_fs(KERNEL_DS); | ||
128 | |||
129 | for (i = -4; i < 1; i++) { | 119 | for (i = -4; i < 1; i++) { |
130 | unsigned int val, bad; | 120 | unsigned int val, bad; |
131 | 121 | ||
@@ -139,8 +129,18 @@ static void dump_instr(const char *lvl, struct pt_regs *regs) | |||
139 | } | 129 | } |
140 | } | 130 | } |
141 | printk("%sCode: %s\n", lvl, str); | 131 | printk("%sCode: %s\n", lvl, str); |
132 | } | ||
142 | 133 | ||
143 | set_fs(fs); | 134 | static void dump_instr(const char *lvl, struct pt_regs *regs) |
135 | { | ||
136 | if (!user_mode(regs)) { | ||
137 | mm_segment_t fs = get_fs(); | ||
138 | set_fs(KERNEL_DS); | ||
139 | __dump_instr(lvl, regs); | ||
140 | set_fs(fs); | ||
141 | } else { | ||
142 | __dump_instr(lvl, regs); | ||
143 | } | ||
144 | } | 144 | } |
145 | 145 | ||
146 | static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) | 146 | static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) |
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index ba3fc12bd272..013e2cbe7924 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c | |||
@@ -441,7 +441,7 @@ static int do_bad(unsigned long addr, unsigned int esr, struct pt_regs *regs) | |||
441 | return 1; | 441 | return 1; |
442 | } | 442 | } |
443 | 443 | ||
444 | static struct fault_info { | 444 | static const struct fault_info { |
445 | int (*fn)(unsigned long addr, unsigned int esr, struct pt_regs *regs); | 445 | int (*fn)(unsigned long addr, unsigned int esr, struct pt_regs *regs); |
446 | int sig; | 446 | int sig; |
447 | int code; | 447 | int code; |
diff --git a/drivers/perf/arm_pmu.c b/drivers/perf/arm_pmu.c index 1b8304e1efaa..140436a046c0 100644 --- a/drivers/perf/arm_pmu.c +++ b/drivers/perf/arm_pmu.c | |||
@@ -1010,8 +1010,8 @@ int arm_pmu_device_probe(struct platform_device *pdev, | |||
1010 | if (!ret) | 1010 | if (!ret) |
1011 | ret = init_fn(pmu); | 1011 | ret = init_fn(pmu); |
1012 | } else { | 1012 | } else { |
1013 | ret = probe_current_pmu(pmu, probe_table); | ||
1014 | cpumask_setall(&pmu->supported_cpus); | 1013 | cpumask_setall(&pmu->supported_cpus); |
1014 | ret = probe_current_pmu(pmu, probe_table); | ||
1015 | } | 1015 | } |
1016 | 1016 | ||
1017 | if (ret) { | 1017 | if (ret) { |