diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-10-13 14:39:28 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-10-13 14:39:28 -0400 |
commit | e18e884445aacb319a7b607a5813b02bcaeca834 (patch) | |
tree | b88f30399d5cdd6391ea824f0e27eddcab94470f | |
parent | 3be5f884f60e9ac66f38c11d92929ba367a86cdb (diff) | |
parent | 0d8ba16278ec30a262d931875018abee332f926f (diff) |
Merge tag 'powerpc-4.14-5' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux
Pull powerpc fixes from Michael Ellerman:
"A fix for a bad bug (written by me) in our livepatch handler. Removal
of an over-zealous lockdep_assert_cpus_held() in our topology code. A
fix to the recently added emulation of cntlz[wd]. And three small
fixes to the recently added IMC PMU driver.
Thanks to: Anju T Sudhakar, Balbir Singh, Kamalesh Babulal, Naveen N.
Rao, Sandipan Das, Santosh Sivaraj, Thiago Jung Bauermann"
* tag 'powerpc-4.14-5' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux:
powerpc/perf: Fix IMC initialization crash
powerpc/perf: Add ___GFP_NOWARN flag to alloc_pages_node()
powerpc/perf: Fix for core/nest imc call trace on cpuhotplug
powerpc: Don't call lockdep_assert_cpus_held() from arch_update_cpu_topology()
powerpc/lib/sstep: Fix count leading zeros instructions
powerpc/livepatch: Fix livepatch stack access
-rw-r--r-- | arch/powerpc/kernel/trace/ftrace_64_mprofile.S | 45 | ||||
-rw-r--r-- | arch/powerpc/lib/sstep.c | 6 | ||||
-rw-r--r-- | arch/powerpc/mm/numa.c | 1 | ||||
-rw-r--r-- | arch/powerpc/perf/imc-pmu.c | 39 |
4 files changed, 53 insertions, 38 deletions
diff --git a/arch/powerpc/kernel/trace/ftrace_64_mprofile.S b/arch/powerpc/kernel/trace/ftrace_64_mprofile.S index c98e90b4ea7b..b4e2b7165f79 100644 --- a/arch/powerpc/kernel/trace/ftrace_64_mprofile.S +++ b/arch/powerpc/kernel/trace/ftrace_64_mprofile.S | |||
@@ -181,34 +181,25 @@ _GLOBAL(ftrace_stub) | |||
181 | * - we have no stack frame and can not allocate one | 181 | * - we have no stack frame and can not allocate one |
182 | * - LR points back to the original caller (in A) | 182 | * - LR points back to the original caller (in A) |
183 | * - CTR holds the new NIP in C | 183 | * - CTR holds the new NIP in C |
184 | * - r0 & r12 are free | 184 | * - r0, r11 & r12 are free |
185 | * | ||
186 | * r0 can't be used as the base register for a DS-form load or store, so | ||
187 | * we temporarily shuffle r1 (stack pointer) into r0 and then put it back. | ||
188 | */ | 185 | */ |
189 | livepatch_handler: | 186 | livepatch_handler: |
190 | CURRENT_THREAD_INFO(r12, r1) | 187 | CURRENT_THREAD_INFO(r12, r1) |
191 | 188 | ||
192 | /* Save stack pointer into r0 */ | ||
193 | mr r0, r1 | ||
194 | |||
195 | /* Allocate 3 x 8 bytes */ | 189 | /* Allocate 3 x 8 bytes */ |
196 | ld r1, TI_livepatch_sp(r12) | 190 | ld r11, TI_livepatch_sp(r12) |
197 | addi r1, r1, 24 | 191 | addi r11, r11, 24 |
198 | std r1, TI_livepatch_sp(r12) | 192 | std r11, TI_livepatch_sp(r12) |
199 | 193 | ||
200 | /* Save toc & real LR on livepatch stack */ | 194 | /* Save toc & real LR on livepatch stack */ |
201 | std r2, -24(r1) | 195 | std r2, -24(r11) |
202 | mflr r12 | 196 | mflr r12 |
203 | std r12, -16(r1) | 197 | std r12, -16(r11) |
204 | 198 | ||
205 | /* Store stack end marker */ | 199 | /* Store stack end marker */ |
206 | lis r12, STACK_END_MAGIC@h | 200 | lis r12, STACK_END_MAGIC@h |
207 | ori r12, r12, STACK_END_MAGIC@l | 201 | ori r12, r12, STACK_END_MAGIC@l |
208 | std r12, -8(r1) | 202 | std r12, -8(r11) |
209 | |||
210 | /* Restore real stack pointer */ | ||
211 | mr r1, r0 | ||
212 | 203 | ||
213 | /* Put ctr in r12 for global entry and branch there */ | 204 | /* Put ctr in r12 for global entry and branch there */ |
214 | mfctr r12 | 205 | mfctr r12 |
@@ -216,36 +207,30 @@ livepatch_handler: | |||
216 | 207 | ||
217 | /* | 208 | /* |
218 | * Now we are returning from the patched function to the original | 209 | * Now we are returning from the patched function to the original |
219 | * caller A. We are free to use r0 and r12, and we can use r2 until we | 210 | * caller A. We are free to use r11, r12 and we can use r2 until we |
220 | * restore it. | 211 | * restore it. |
221 | */ | 212 | */ |
222 | 213 | ||
223 | CURRENT_THREAD_INFO(r12, r1) | 214 | CURRENT_THREAD_INFO(r12, r1) |
224 | 215 | ||
225 | /* Save stack pointer into r0 */ | 216 | ld r11, TI_livepatch_sp(r12) |
226 | mr r0, r1 | ||
227 | |||
228 | ld r1, TI_livepatch_sp(r12) | ||
229 | 217 | ||
230 | /* Check stack marker hasn't been trashed */ | 218 | /* Check stack marker hasn't been trashed */ |
231 | lis r2, STACK_END_MAGIC@h | 219 | lis r2, STACK_END_MAGIC@h |
232 | ori r2, r2, STACK_END_MAGIC@l | 220 | ori r2, r2, STACK_END_MAGIC@l |
233 | ld r12, -8(r1) | 221 | ld r12, -8(r11) |
234 | 1: tdne r12, r2 | 222 | 1: tdne r12, r2 |
235 | EMIT_BUG_ENTRY 1b, __FILE__, __LINE__ - 1, 0 | 223 | EMIT_BUG_ENTRY 1b, __FILE__, __LINE__ - 1, 0 |
236 | 224 | ||
237 | /* Restore LR & toc from livepatch stack */ | 225 | /* Restore LR & toc from livepatch stack */ |
238 | ld r12, -16(r1) | 226 | ld r12, -16(r11) |
239 | mtlr r12 | 227 | mtlr r12 |
240 | ld r2, -24(r1) | 228 | ld r2, -24(r11) |
241 | 229 | ||
242 | /* Pop livepatch stack frame */ | 230 | /* Pop livepatch stack frame */ |
243 | CURRENT_THREAD_INFO(r12, r0) | 231 | CURRENT_THREAD_INFO(r12, r1) |
244 | subi r1, r1, 24 | 232 | subi r11, r11, 24 |
245 | std r1, TI_livepatch_sp(r12) | 233 | std r11, TI_livepatch_sp(r12) |
246 | |||
247 | /* Restore real stack pointer */ | ||
248 | mr r1, r0 | ||
249 | 234 | ||
250 | /* Return to original caller of live patched function */ | 235 | /* Return to original caller of live patched function */ |
251 | blr | 236 | blr |
diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c index 5e8418c28bd8..f208f560aecd 100644 --- a/arch/powerpc/lib/sstep.c +++ b/arch/powerpc/lib/sstep.c | |||
@@ -1684,11 +1684,13 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, | |||
1684 | * Logical instructions | 1684 | * Logical instructions |
1685 | */ | 1685 | */ |
1686 | case 26: /* cntlzw */ | 1686 | case 26: /* cntlzw */ |
1687 | op->val = __builtin_clz((unsigned int) regs->gpr[rd]); | 1687 | val = (unsigned int) regs->gpr[rd]; |
1688 | op->val = ( val ? __builtin_clz(val) : 32 ); | ||
1688 | goto logical_done; | 1689 | goto logical_done; |
1689 | #ifdef __powerpc64__ | 1690 | #ifdef __powerpc64__ |
1690 | case 58: /* cntlzd */ | 1691 | case 58: /* cntlzd */ |
1691 | op->val = __builtin_clzl(regs->gpr[rd]); | 1692 | val = regs->gpr[rd]; |
1693 | op->val = ( val ? __builtin_clzl(val) : 64 ); | ||
1692 | goto logical_done; | 1694 | goto logical_done; |
1693 | #endif | 1695 | #endif |
1694 | case 28: /* and */ | 1696 | case 28: /* and */ |
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index b95c584ce19d..a51df9ef529d 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c | |||
@@ -1438,7 +1438,6 @@ out: | |||
1438 | 1438 | ||
1439 | int arch_update_cpu_topology(void) | 1439 | int arch_update_cpu_topology(void) |
1440 | { | 1440 | { |
1441 | lockdep_assert_cpus_held(); | ||
1442 | return numa_update_cpu_topology(true); | 1441 | return numa_update_cpu_topology(true); |
1443 | } | 1442 | } |
1444 | 1443 | ||
diff --git a/arch/powerpc/perf/imc-pmu.c b/arch/powerpc/perf/imc-pmu.c index 9ccac86f3463..88126245881b 100644 --- a/arch/powerpc/perf/imc-pmu.c +++ b/arch/powerpc/perf/imc-pmu.c | |||
@@ -399,6 +399,20 @@ static void nest_imc_counters_release(struct perf_event *event) | |||
399 | 399 | ||
400 | /* Take the mutex lock for this node and then decrement the reference count */ | 400 | /* Take the mutex lock for this node and then decrement the reference count */ |
401 | mutex_lock(&ref->lock); | 401 | mutex_lock(&ref->lock); |
402 | if (ref->refc == 0) { | ||
403 | /* | ||
404 | * The scenario where this is true is, when perf session is | ||
405 | * started, followed by offlining of all cpus in a given node. | ||
406 | * | ||
407 | * In the cpuhotplug offline path, ppc_nest_imc_cpu_offline() | ||
408 | * function set the ref->count to zero, if the cpu which is | ||
409 | * about to offline is the last cpu in a given node and make | ||
410 | * an OPAL call to disable the engine in that node. | ||
411 | * | ||
412 | */ | ||
413 | mutex_unlock(&ref->lock); | ||
414 | return; | ||
415 | } | ||
402 | ref->refc--; | 416 | ref->refc--; |
403 | if (ref->refc == 0) { | 417 | if (ref->refc == 0) { |
404 | rc = opal_imc_counters_stop(OPAL_IMC_COUNTERS_NEST, | 418 | rc = opal_imc_counters_stop(OPAL_IMC_COUNTERS_NEST, |
@@ -523,8 +537,8 @@ static int core_imc_mem_init(int cpu, int size) | |||
523 | 537 | ||
524 | /* We need only vbase for core counters */ | 538 | /* We need only vbase for core counters */ |
525 | mem_info->vbase = page_address(alloc_pages_node(phys_id, | 539 | mem_info->vbase = page_address(alloc_pages_node(phys_id, |
526 | GFP_KERNEL | __GFP_ZERO | __GFP_THISNODE, | 540 | GFP_KERNEL | __GFP_ZERO | __GFP_THISNODE | |
527 | get_order(size))); | 541 | __GFP_NOWARN, get_order(size))); |
528 | if (!mem_info->vbase) | 542 | if (!mem_info->vbase) |
529 | return -ENOMEM; | 543 | return -ENOMEM; |
530 | 544 | ||
@@ -646,6 +660,20 @@ static void core_imc_counters_release(struct perf_event *event) | |||
646 | return; | 660 | return; |
647 | 661 | ||
648 | mutex_lock(&ref->lock); | 662 | mutex_lock(&ref->lock); |
663 | if (ref->refc == 0) { | ||
664 | /* | ||
665 | * The scenario where this is true is, when perf session is | ||
666 | * started, followed by offlining of all cpus in a given core. | ||
667 | * | ||
668 | * In the cpuhotplug offline path, ppc_core_imc_cpu_offline() | ||
669 | * function set the ref->count to zero, if the cpu which is | ||
670 | * about to offline is the last cpu in a given core and make | ||
671 | * an OPAL call to disable the engine in that core. | ||
672 | * | ||
673 | */ | ||
674 | mutex_unlock(&ref->lock); | ||
675 | return; | ||
676 | } | ||
649 | ref->refc--; | 677 | ref->refc--; |
650 | if (ref->refc == 0) { | 678 | if (ref->refc == 0) { |
651 | rc = opal_imc_counters_stop(OPAL_IMC_COUNTERS_CORE, | 679 | rc = opal_imc_counters_stop(OPAL_IMC_COUNTERS_CORE, |
@@ -763,8 +791,8 @@ static int thread_imc_mem_alloc(int cpu_id, int size) | |||
763 | * free the memory in cpu offline path. | 791 | * free the memory in cpu offline path. |
764 | */ | 792 | */ |
765 | local_mem = page_address(alloc_pages_node(phys_id, | 793 | local_mem = page_address(alloc_pages_node(phys_id, |
766 | GFP_KERNEL | __GFP_ZERO | __GFP_THISNODE, | 794 | GFP_KERNEL | __GFP_ZERO | __GFP_THISNODE | |
767 | get_order(size))); | 795 | __GFP_NOWARN, get_order(size))); |
768 | if (!local_mem) | 796 | if (!local_mem) |
769 | return -ENOMEM; | 797 | return -ENOMEM; |
770 | 798 | ||
@@ -1148,7 +1176,8 @@ static void imc_common_cpuhp_mem_free(struct imc_pmu *pmu_ptr) | |||
1148 | } | 1176 | } |
1149 | 1177 | ||
1150 | /* Only free the attr_groups which are dynamically allocated */ | 1178 | /* Only free the attr_groups which are dynamically allocated */ |
1151 | kfree(pmu_ptr->attr_groups[IMC_EVENT_ATTR]->attrs); | 1179 | if (pmu_ptr->attr_groups[IMC_EVENT_ATTR]) |
1180 | kfree(pmu_ptr->attr_groups[IMC_EVENT_ATTR]->attrs); | ||
1152 | kfree(pmu_ptr->attr_groups[IMC_EVENT_ATTR]); | 1181 | kfree(pmu_ptr->attr_groups[IMC_EVENT_ATTR]); |
1153 | kfree(pmu_ptr); | 1182 | kfree(pmu_ptr); |
1154 | return; | 1183 | return; |