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 | ||
