aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Ellerman <mpe@ellerman.id.au>2017-11-14 22:25:42 -0500
committerMichael Ellerman <mpe@ellerman.id.au>2017-11-14 22:25:42 -0500
commit3ffa9d9e2a7c10127d8cbf91ea2be15390b450ed (patch)
tree74d987fa2dd8385612041e49f80a36d17bf5a433
parent475b581ff57bc01437cbc680e281869918447763 (diff)
powerpc/64s: Fix Power9 DD2.0 workarounds by adding DD2.1 feature
Recently we added a CPU feature for Power9 DD2.0, to capture the fact that some workarounds are required only on Power9 DD1 and DD2.0 but not DD2.1 or later. Then in commit 9d2f510a66ec ("powerpc/64s/idle: avoid POWER9 DD1 and DD2.0 ERAT workaround on DD2.1") and commit e3646330cf66 "powerpc/64s/idle: avoid POWER9 DD1 and DD2.0 PMU workaround on DD2.1") we changed CPU_FTR_SECTIONs to check for DD1 or DD20, eg: BEGIN_FTR_SECTION PPC_INVALIDATE_ERAT END_FTR_SECTION_IFSET(CPU_FTR_POWER9_DD1 | CPU_FTR_POWER9_DD20) Unfortunately although this reads as "if set DD1 or DD2.0", the or is a bitwise or and actually generates a mask of both bits. The code that does the feature patching then checks that the value of the CPU features masked with that mask are equal to the mask. So the end result is we're checking for DD1 and DD20 being set, which never happens. Yes the API is terrible. Removing the ERAT workaround on DD2.0 results in random SEGVs, the system tends to boot, but things randomly die including sometimes dhclient, udev etc. To fix the problem and hopefully avoid it in future, we remove the DD2.0 CPU feature and instead add a DD2.1 (or later) feature. This allows us to easily express that the workarounds are required if DD2.1 is not set. At some point we will drop the DD1 workarounds entirely and some of this can be cleaned up. Fixes: 9d2f510a66ec ("powerpc/64s/idle: avoid POWER9 DD1 and DD2.0 ERAT workaround on DD2.1") Fixes: e3646330cf66 ("powerpc/64s/idle: avoid POWER9 DD1 and DD2.0 PMU workaround on DD2.1") Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
-rw-r--r--arch/powerpc/include/asm/cputable.h7
-rw-r--r--arch/powerpc/kernel/cputable.c6
-rw-r--r--arch/powerpc/kernel/dt_cpu_ftrs.c2
-rw-r--r--arch/powerpc/kernel/idle_book3s.S8
4 files changed, 12 insertions, 11 deletions
diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h
index 1ca26ca85ec6..04c31db5e7c3 100644
--- a/arch/powerpc/include/asm/cputable.h
+++ b/arch/powerpc/include/asm/cputable.h
@@ -215,7 +215,7 @@ enum {
215#define CPU_FTR_DABRX LONG_ASM_CONST(0x0800000000000000) 215#define CPU_FTR_DABRX LONG_ASM_CONST(0x0800000000000000)
216#define CPU_FTR_PMAO_BUG LONG_ASM_CONST(0x1000000000000000) 216#define CPU_FTR_PMAO_BUG LONG_ASM_CONST(0x1000000000000000)
217#define CPU_FTR_POWER9_DD1 LONG_ASM_CONST(0x4000000000000000) 217#define CPU_FTR_POWER9_DD1 LONG_ASM_CONST(0x4000000000000000)
218#define CPU_FTR_POWER9_DD20 LONG_ASM_CONST(0x8000000000000000) 218#define CPU_FTR_POWER9_DD2_1 LONG_ASM_CONST(0x8000000000000000)
219 219
220#ifndef __ASSEMBLY__ 220#ifndef __ASSEMBLY__
221 221
@@ -478,7 +478,8 @@ enum {
478 CPU_FTR_ARCH_207S | CPU_FTR_TM_COMP | CPU_FTR_ARCH_300) 478 CPU_FTR_ARCH_207S | CPU_FTR_TM_COMP | CPU_FTR_ARCH_300)
479#define CPU_FTRS_POWER9_DD1 ((CPU_FTRS_POWER9 | CPU_FTR_POWER9_DD1) & \ 479#define CPU_FTRS_POWER9_DD1 ((CPU_FTRS_POWER9 | CPU_FTR_POWER9_DD1) & \
480 (~CPU_FTR_SAO)) 480 (~CPU_FTR_SAO))
481#define CPU_FTRS_POWER9_DD20 (CPU_FTRS_POWER9 | CPU_FTR_POWER9_DD20) 481#define CPU_FTRS_POWER9_DD2_0 CPU_FTRS_POWER9
482#define CPU_FTRS_POWER9_DD2_1 (CPU_FTRS_POWER9 | CPU_FTR_POWER9_DD2_1)
482#define CPU_FTRS_CELL (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \ 483#define CPU_FTRS_CELL (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
483 CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ 484 CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
484 CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \ 485 CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \
@@ -498,7 +499,7 @@ enum {
498 CPU_FTRS_POWER6 | CPU_FTRS_POWER7 | CPU_FTRS_POWER8E | \ 499 CPU_FTRS_POWER6 | CPU_FTRS_POWER7 | CPU_FTRS_POWER8E | \
499 CPU_FTRS_POWER8 | CPU_FTRS_POWER8_DD1 | CPU_FTRS_CELL | \ 500 CPU_FTRS_POWER8 | CPU_FTRS_POWER8_DD1 | CPU_FTRS_CELL | \
500 CPU_FTRS_PA6T | CPU_FTR_VSX | CPU_FTRS_POWER9 | \ 501 CPU_FTRS_PA6T | CPU_FTR_VSX | CPU_FTRS_POWER9 | \
501 CPU_FTRS_POWER9_DD1 | CPU_FTRS_POWER9_DD20) 502 CPU_FTRS_POWER9_DD1 | CPU_FTRS_POWER9_DD2_1)
502#endif 503#endif
503#else 504#else
504enum { 505enum {
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index 171820190de7..1350f49d81a8 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -551,7 +551,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
551 .pvr_mask = 0xffffefff, 551 .pvr_mask = 0xffffefff,
552 .pvr_value = 0x004e0200, 552 .pvr_value = 0x004e0200,
553 .cpu_name = "POWER9 (raw)", 553 .cpu_name = "POWER9 (raw)",
554 .cpu_features = CPU_FTRS_POWER9_DD20, 554 .cpu_features = CPU_FTRS_POWER9_DD2_0,
555 .cpu_user_features = COMMON_USER_POWER9, 555 .cpu_user_features = COMMON_USER_POWER9,
556 .cpu_user_features2 = COMMON_USER2_POWER9, 556 .cpu_user_features2 = COMMON_USER2_POWER9,
557 .mmu_features = MMU_FTRS_POWER9, 557 .mmu_features = MMU_FTRS_POWER9,
@@ -567,11 +567,11 @@ static struct cpu_spec __initdata cpu_specs[] = {
567 .machine_check_early = __machine_check_early_realmode_p9, 567 .machine_check_early = __machine_check_early_realmode_p9,
568 .platform = "power9", 568 .platform = "power9",
569 }, 569 },
570 { /* Power9 */ 570 { /* Power9 DD 2.1 or later (see DD2.0 above) */
571 .pvr_mask = 0xffff0000, 571 .pvr_mask = 0xffff0000,
572 .pvr_value = 0x004e0000, 572 .pvr_value = 0x004e0000,
573 .cpu_name = "POWER9 (raw)", 573 .cpu_name = "POWER9 (raw)",
574 .cpu_features = CPU_FTRS_POWER9, 574 .cpu_features = CPU_FTRS_POWER9_DD2_1,
575 .cpu_user_features = COMMON_USER_POWER9, 575 .cpu_user_features = COMMON_USER_POWER9,
576 .cpu_user_features2 = COMMON_USER2_POWER9, 576 .cpu_user_features2 = COMMON_USER2_POWER9,
577 .mmu_features = MMU_FTRS_POWER9, 577 .mmu_features = MMU_FTRS_POWER9,
diff --git a/arch/powerpc/kernel/dt_cpu_ftrs.c b/arch/powerpc/kernel/dt_cpu_ftrs.c
index 58e3b51de31c..602e0fde19b4 100644
--- a/arch/powerpc/kernel/dt_cpu_ftrs.c
+++ b/arch/powerpc/kernel/dt_cpu_ftrs.c
@@ -736,7 +736,7 @@ static __init void cpufeatures_cpu_quirks(void)
736 if ((version & 0xffffff00) == 0x004e0100) 736 if ((version & 0xffffff00) == 0x004e0100)
737 cur_cpu_spec->cpu_features |= CPU_FTR_POWER9_DD1; 737 cur_cpu_spec->cpu_features |= CPU_FTR_POWER9_DD1;
738 else if ((version & 0xffffefff) == 0x004e0200) 738 else if ((version & 0xffffefff) == 0x004e0200)
739 cur_cpu_spec->cpu_features |= CPU_FTR_POWER9_DD20; 739 cur_cpu_spec->cpu_features &= ~CPU_FTR_POWER9_DD2_1;
740} 740}
741 741
742static void __init cpufeatures_setup_finished(void) 742static void __init cpufeatures_setup_finished(void)
diff --git a/arch/powerpc/kernel/idle_book3s.S b/arch/powerpc/kernel/idle_book3s.S
index 59657783d1d5..01e1c1997893 100644
--- a/arch/powerpc/kernel/idle_book3s.S
+++ b/arch/powerpc/kernel/idle_book3s.S
@@ -357,13 +357,13 @@ power_enter_stop:
357.Lhandle_esl_ec_set: 357.Lhandle_esl_ec_set:
358BEGIN_FTR_SECTION 358BEGIN_FTR_SECTION
359 /* 359 /*
360 * POWER9 DD2 can incorrectly set PMAO when waking up after a 360 * POWER9 DD2.0 or earlier can incorrectly set PMAO when waking up after
361 * state-loss idle. Saving and restoring MMCR0 over idle is a 361 * a state-loss idle. Saving and restoring MMCR0 over idle is a
362 * workaround. 362 * workaround.
363 */ 363 */
364 mfspr r4,SPRN_MMCR0 364 mfspr r4,SPRN_MMCR0
365 std r4,_MMCR0(r1) 365 std r4,_MMCR0(r1)
366END_FTR_SECTION_IFSET(CPU_FTR_POWER9_DD1 | CPU_FTR_POWER9_DD20) 366END_FTR_SECTION_IFCLR(CPU_FTR_POWER9_DD2_1)
367 367
368/* 368/*
369 * Check if the requested state is a deep idle state. 369 * Check if the requested state is a deep idle state.
@@ -554,7 +554,7 @@ BEGIN_FTR_SECTION
554 ld r1,PACAR1(r13) 554 ld r1,PACAR1(r13)
555 ld r4,_MMCR0(r1) 555 ld r4,_MMCR0(r1)
556 mtspr SPRN_MMCR0,r4 556 mtspr SPRN_MMCR0,r4
557END_FTR_SECTION_IFSET(CPU_FTR_POWER9_DD1 | CPU_FTR_POWER9_DD20) 557END_FTR_SECTION_IFCLR(CPU_FTR_POWER9_DD2_1)
558 mfspr r4,SPRN_MMCRA 558 mfspr r4,SPRN_MMCRA
559 ori r4,r4,(1 << (63-60)) 559 ori r4,r4,(1 << (63-60))
560 mtspr SPRN_MMCRA,r4 560 mtspr SPRN_MMCRA,r4