aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-07-14 18:33:15 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2017-07-14 18:33:15 -0400
commitdeed9deb62f9121ea16f06351d1e968685a74863 (patch)
tree124b1282c78c4aba97f53694ba0bc0489c014a8c
parentccd5d1b91f22351b55feb6fdee504cb84d97752f (diff)
parent01e6a61aceb82e13bec29502a8eb70d9574f97ad (diff)
Merge tag 'powerpc-4.13-2' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux
Pull powerpc fixes from Michael Ellerman: "Nothing that really stands out, just a bunch of fixes that have come in in the last couple of weeks. None of these are actually fixes for code that is new in 4.13. It's roughly half older bugs, with fixes going to stable, and half fixes/updates for Power9. Thanks to: Aneesh Kumar K.V, Anton Blanchard, Balbir Singh, Benjamin Herrenschmidt, Madhavan Srinivasan, Michael Neuling, Nicholas Piggin, Oliver O'Halloran" * tag 'powerpc-4.13-2' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux: powerpc/64: Fix atomic64_inc_not_zero() to return an int powerpc: Fix emulation of mfocrf in emulate_step() powerpc: Fix emulation of mcrf in emulate_step() powerpc/perf: Add POWER9 alternate PM_RUN_CYC and PM_RUN_INST_CMPL events powerpc/perf: Fix SDAR_MODE value for continous sampling on Power9 powerpc/asm: Mark cr0 as clobbered in mftb() powerpc/powernv: Fix local TLB flush for boot and MCE on POWER9 powerpc/mm/radix: Synchronize updates to the process table powerpc/mm/radix: Properly clear process table entry powerpc/powernv: Tell OPAL about our MMU mode on POWER9 powerpc/kexec: Fix radix to hash kexec due to IAMR/AMOR
-rw-r--r--arch/powerpc/include/asm/atomic.h4
-rw-r--r--arch/powerpc/include/asm/opal-api.h9
-rw-r--r--arch/powerpc/include/asm/reg.h2
-rw-r--r--arch/powerpc/kernel/cpu_setup_power.S13
-rw-r--r--arch/powerpc/kernel/dt_cpu_ftrs.c16
-rw-r--r--arch/powerpc/kernel/mce_power.c56
-rw-r--r--arch/powerpc/kernel/misc_64.S12
-rw-r--r--arch/powerpc/lib/sstep.c19
-rw-r--r--arch/powerpc/mm/mmu_context_book3s64.c20
-rw-r--r--arch/powerpc/perf/isa207-common.c6
-rw-r--r--arch/powerpc/perf/power9-events-list.h4
-rw-r--r--arch/powerpc/perf/power9-pmu.c2
-rw-r--r--arch/powerpc/platforms/powernv/opal.c19
-rw-r--r--arch/powerpc/platforms/powernv/setup.c11
14 files changed, 162 insertions, 31 deletions
diff --git a/arch/powerpc/include/asm/atomic.h b/arch/powerpc/include/asm/atomic.h
index 2b90335194a7..a2cc8010cd72 100644
--- a/arch/powerpc/include/asm/atomic.h
+++ b/arch/powerpc/include/asm/atomic.h
@@ -560,7 +560,7 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
560 * Atomically increments @v by 1, so long as @v is non-zero. 560 * Atomically increments @v by 1, so long as @v is non-zero.
561 * Returns non-zero if @v was non-zero, and zero otherwise. 561 * Returns non-zero if @v was non-zero, and zero otherwise.
562 */ 562 */
563static __inline__ long atomic64_inc_not_zero(atomic64_t *v) 563static __inline__ int atomic64_inc_not_zero(atomic64_t *v)
564{ 564{
565 long t1, t2; 565 long t1, t2;
566 566
@@ -579,7 +579,7 @@ static __inline__ long atomic64_inc_not_zero(atomic64_t *v)
579 : "r" (&v->counter) 579 : "r" (&v->counter)
580 : "cc", "xer", "memory"); 580 : "cc", "xer", "memory");
581 581
582 return t1; 582 return t1 != 0;
583} 583}
584 584
585#endif /* __powerpc64__ */ 585#endif /* __powerpc64__ */
diff --git a/arch/powerpc/include/asm/opal-api.h b/arch/powerpc/include/asm/opal-api.h
index ef930ba500f9..3130a73652c7 100644
--- a/arch/powerpc/include/asm/opal-api.h
+++ b/arch/powerpc/include/asm/opal-api.h
@@ -876,6 +876,15 @@ struct OpalIoPhb4ErrorData {
876enum { 876enum {
877 OPAL_REINIT_CPUS_HILE_BE = (1 << 0), 877 OPAL_REINIT_CPUS_HILE_BE = (1 << 0),
878 OPAL_REINIT_CPUS_HILE_LE = (1 << 1), 878 OPAL_REINIT_CPUS_HILE_LE = (1 << 1),
879
880 /* These two define the base MMU mode of the host on P9
881 *
882 * On P9 Nimbus DD2.0 and Cumlus (and later), KVM can still
883 * create hash guests in "radix" mode with care (full core
884 * switch only).
885 */
886 OPAL_REINIT_CPUS_MMU_HASH = (1 << 2),
887 OPAL_REINIT_CPUS_MMU_RADIX = (1 << 3),
879}; 888};
880 889
881typedef struct oppanel_line { 890typedef struct oppanel_line {
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index 7e50e47375d6..a3b6575c7842 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -1303,7 +1303,7 @@ static inline void msr_check_and_clear(unsigned long bits)
1303 " .llong 0\n" \ 1303 " .llong 0\n" \
1304 ".previous" \ 1304 ".previous" \
1305 : "=r" (rval) \ 1305 : "=r" (rval) \
1306 : "i" (CPU_FTR_CELL_TB_BUG), "i" (SPRN_TBRL)); \ 1306 : "i" (CPU_FTR_CELL_TB_BUG), "i" (SPRN_TBRL) : "cr0"); \
1307 rval;}) 1307 rval;})
1308#else 1308#else
1309#define mftb() ({unsigned long rval; \ 1309#define mftb() ({unsigned long rval; \
diff --git a/arch/powerpc/kernel/cpu_setup_power.S b/arch/powerpc/kernel/cpu_setup_power.S
index 10cb2896b2ae..610955fe8b81 100644
--- a/arch/powerpc/kernel/cpu_setup_power.S
+++ b/arch/powerpc/kernel/cpu_setup_power.S
@@ -218,13 +218,20 @@ __init_tlb_power8:
218 ptesync 218 ptesync
2191: blr 2191: blr
220 220
221/*
222 * Flush the TLB in hash mode. Hash must flush with RIC=2 once for process
223 * and one for partition scope to clear process and partition table entries.
224 */
221__init_tlb_power9: 225__init_tlb_power9:
222 li r6,POWER9_TLB_SETS_HASH 226 li r6,POWER9_TLB_SETS_HASH - 1
223 mtctr r6 227 mtctr r6
224 li r7,0xc00 /* IS field = 0b11 */ 228 li r7,0xc00 /* IS field = 0b11 */
229 li r8,0
225 ptesync 230 ptesync
2262: tlbiel r7 231 PPC_TLBIEL(7, 8, 2, 1, 0)
227 addi r7,r7,0x1000 232 PPC_TLBIEL(7, 8, 2, 0, 0)
2332: addi r7,r7,0x1000
234 PPC_TLBIEL(7, 8, 0, 0, 0)
228 bdnz 2b 235 bdnz 2b
229 ptesync 236 ptesync
2301: blr 2371: blr
diff --git a/arch/powerpc/kernel/dt_cpu_ftrs.c b/arch/powerpc/kernel/dt_cpu_ftrs.c
index 4c7656dc4e04..1df770e8cbe0 100644
--- a/arch/powerpc/kernel/dt_cpu_ftrs.c
+++ b/arch/powerpc/kernel/dt_cpu_ftrs.c
@@ -94,9 +94,6 @@ static void (*init_pmu_registers)(void);
94 94
95static void cpufeatures_flush_tlb(void) 95static void cpufeatures_flush_tlb(void)
96{ 96{
97 unsigned long rb;
98 unsigned int i, num_sets;
99
100 /* 97 /*
101 * This is a temporary measure to keep equivalent TLB flush as the 98 * This is a temporary measure to keep equivalent TLB flush as the
102 * cputable based setup code. 99 * cputable based setup code.
@@ -105,24 +102,15 @@ static void cpufeatures_flush_tlb(void)
105 case PVR_POWER8: 102 case PVR_POWER8:
106 case PVR_POWER8E: 103 case PVR_POWER8E:
107 case PVR_POWER8NVL: 104 case PVR_POWER8NVL:
108 num_sets = POWER8_TLB_SETS; 105 __flush_tlb_power8(POWER8_TLB_SETS);
109 break; 106 break;
110 case PVR_POWER9: 107 case PVR_POWER9:
111 num_sets = POWER9_TLB_SETS_HASH; 108 __flush_tlb_power9(POWER9_TLB_SETS_HASH);
112 break; 109 break;
113 default: 110 default:
114 num_sets = 1;
115 pr_err("unknown CPU version for boot TLB flush\n"); 111 pr_err("unknown CPU version for boot TLB flush\n");
116 break; 112 break;
117 } 113 }
118
119 asm volatile("ptesync" : : : "memory");
120 rb = TLBIEL_INVAL_SET;
121 for (i = 0; i < num_sets; i++) {
122 asm volatile("tlbiel %0" : : "r" (rb));
123 rb += 1 << TLBIEL_INVAL_SET_SHIFT;
124 }
125 asm volatile("ptesync" : : : "memory");
126} 114}
127 115
128static void __restore_cpu_cpufeatures(void) 116static void __restore_cpu_cpufeatures(void)
diff --git a/arch/powerpc/kernel/mce_power.c b/arch/powerpc/kernel/mce_power.c
index d24e689e893f..b76ca198e09c 100644
--- a/arch/powerpc/kernel/mce_power.c
+++ b/arch/powerpc/kernel/mce_power.c
@@ -53,6 +53,60 @@ static void flush_tlb_206(unsigned int num_sets, unsigned int action)
53 asm volatile("ptesync" : : : "memory"); 53 asm volatile("ptesync" : : : "memory");
54} 54}
55 55
56static void flush_tlb_300(unsigned int num_sets, unsigned int action)
57{
58 unsigned long rb;
59 unsigned int i;
60 unsigned int r;
61
62 switch (action) {
63 case TLB_INVAL_SCOPE_GLOBAL:
64 rb = TLBIEL_INVAL_SET;
65 break;
66 case TLB_INVAL_SCOPE_LPID:
67 rb = TLBIEL_INVAL_SET_LPID;
68 break;
69 default:
70 BUG();
71 break;
72 }
73
74 asm volatile("ptesync" : : : "memory");
75
76 if (early_radix_enabled())
77 r = 1;
78 else
79 r = 0;
80
81 /*
82 * First flush table/PWC caches with set 0, then flush the
83 * rest of the sets, partition scope. Radix must then do it
84 * all again with process scope. Hash just has to flush
85 * process table.
86 */
87 asm volatile(PPC_TLBIEL(%0, %1, %2, %3, %4) : :
88 "r"(rb), "r"(0), "i"(2), "i"(0), "r"(r));
89 for (i = 1; i < num_sets; i++) {
90 unsigned long set = i * (1<<TLBIEL_INVAL_SET_SHIFT);
91
92 asm volatile(PPC_TLBIEL(%0, %1, %2, %3, %4) : :
93 "r"(rb+set), "r"(0), "i"(2), "i"(0), "r"(r));
94 }
95
96 asm volatile(PPC_TLBIEL(%0, %1, %2, %3, %4) : :
97 "r"(rb), "r"(0), "i"(2), "i"(1), "r"(r));
98 if (early_radix_enabled()) {
99 for (i = 1; i < num_sets; i++) {
100 unsigned long set = i * (1<<TLBIEL_INVAL_SET_SHIFT);
101
102 asm volatile(PPC_TLBIEL(%0, %1, %2, %3, %4) : :
103 "r"(rb+set), "r"(0), "i"(2), "i"(1), "r"(r));
104 }
105 }
106
107 asm volatile("ptesync" : : : "memory");
108}
109
56/* 110/*
57 * Generic routines to flush TLB on POWER processors. These routines 111 * Generic routines to flush TLB on POWER processors. These routines
58 * are used as flush_tlb hook in the cpu_spec. 112 * are used as flush_tlb hook in the cpu_spec.
@@ -79,7 +133,7 @@ void __flush_tlb_power9(unsigned int action)
79 else 133 else
80 num_sets = POWER9_TLB_SETS_HASH; 134 num_sets = POWER9_TLB_SETS_HASH;
81 135
82 flush_tlb_206(num_sets, action); 136 flush_tlb_300(num_sets, action);
83} 137}
84 138
85 139
diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S
index c119044cad0d..8ac0bd2bddb0 100644
--- a/arch/powerpc/kernel/misc_64.S
+++ b/arch/powerpc/kernel/misc_64.S
@@ -614,6 +614,18 @@ _GLOBAL(kexec_sequence)
614 li r0,0 614 li r0,0
615 std r0,16(r1) 615 std r0,16(r1)
616 616
617BEGIN_FTR_SECTION
618 /*
619 * This is the best time to turn AMR/IAMR off.
620 * key 0 is used in radix for supervisor<->user
621 * protection, but on hash key 0 is reserved
622 * ideally we want to enter with a clean state.
623 * NOTE, we rely on r0 being 0 from above.
624 */
625 mtspr SPRN_IAMR,r0
626 mtspr SPRN_AMOR,r0
627END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
628
617 /* save regs for local vars on new stack. 629 /* save regs for local vars on new stack.
618 * yes, we won't go back, but ... 630 * yes, we won't go back, but ...
619 */ 631 */
diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
index 33117f8a0882..ee33327686ae 100644
--- a/arch/powerpc/lib/sstep.c
+++ b/arch/powerpc/lib/sstep.c
@@ -683,8 +683,10 @@ int analyse_instr(struct instruction_op *op, struct pt_regs *regs,
683 case 19: 683 case 19:
684 switch ((instr >> 1) & 0x3ff) { 684 switch ((instr >> 1) & 0x3ff) {
685 case 0: /* mcrf */ 685 case 0: /* mcrf */
686 rd = (instr >> 21) & 0x1c; 686 rd = 7 - ((instr >> 23) & 0x7);
687 ra = (instr >> 16) & 0x1c; 687 ra = 7 - ((instr >> 18) & 0x7);
688 rd *= 4;
689 ra *= 4;
688 val = (regs->ccr >> ra) & 0xf; 690 val = (regs->ccr >> ra) & 0xf;
689 regs->ccr = (regs->ccr & ~(0xfUL << rd)) | (val << rd); 691 regs->ccr = (regs->ccr & ~(0xfUL << rd)) | (val << rd);
690 goto instr_done; 692 goto instr_done;
@@ -964,6 +966,19 @@ int analyse_instr(struct instruction_op *op, struct pt_regs *regs,
964#endif 966#endif
965 967
966 case 19: /* mfcr */ 968 case 19: /* mfcr */
969 if ((instr >> 20) & 1) {
970 imm = 0xf0000000UL;
971 for (sh = 0; sh < 8; ++sh) {
972 if (instr & (0x80000 >> sh)) {
973 regs->gpr[rd] = regs->ccr & imm;
974 break;
975 }
976 imm >>= 4;
977 }
978
979 goto instr_done;
980 }
981
967 regs->gpr[rd] = regs->ccr; 982 regs->gpr[rd] = regs->ccr;
968 regs->gpr[rd] &= 0xffffffffUL; 983 regs->gpr[rd] &= 0xffffffffUL;
969 goto instr_done; 984 goto instr_done;
diff --git a/arch/powerpc/mm/mmu_context_book3s64.c b/arch/powerpc/mm/mmu_context_book3s64.c
index 71de2c6d88f3..abed1fe6992f 100644
--- a/arch/powerpc/mm/mmu_context_book3s64.c
+++ b/arch/powerpc/mm/mmu_context_book3s64.c
@@ -138,6 +138,14 @@ static int radix__init_new_context(struct mm_struct *mm)
138 rts_field = radix__get_tree_size(); 138 rts_field = radix__get_tree_size();
139 process_tb[index].prtb0 = cpu_to_be64(rts_field | __pa(mm->pgd) | RADIX_PGD_INDEX_SIZE); 139 process_tb[index].prtb0 = cpu_to_be64(rts_field | __pa(mm->pgd) | RADIX_PGD_INDEX_SIZE);
140 140
141 /*
142 * Order the above store with subsequent update of the PID
143 * register (at which point HW can start loading/caching
144 * the entry) and the corresponding load by the MMU from
145 * the L2 cache.
146 */
147 asm volatile("ptesync;isync" : : : "memory");
148
141 mm->context.npu_context = NULL; 149 mm->context.npu_context = NULL;
142 150
143 return index; 151 return index;
@@ -223,9 +231,15 @@ void destroy_context(struct mm_struct *mm)
223 mm->context.cop_lockp = NULL; 231 mm->context.cop_lockp = NULL;
224#endif /* CONFIG_PPC_ICSWX */ 232#endif /* CONFIG_PPC_ICSWX */
225 233
226 if (radix_enabled()) 234 if (radix_enabled()) {
227 process_tb[mm->context.id].prtb1 = 0; 235 /*
228 else 236 * Radix doesn't have a valid bit in the process table
237 * entries. However we know that at least P9 implementation
238 * will avoid caching an entry with an invalid RTS field,
239 * and 0 is invalid. So this will do.
240 */
241 process_tb[mm->context.id].prtb0 = 0;
242 } else
229 subpage_prot_free(mm); 243 subpage_prot_free(mm);
230 destroy_pagetable_page(mm); 244 destroy_pagetable_page(mm);
231 __destroy_context(mm->context.id); 245 __destroy_context(mm->context.id);
diff --git a/arch/powerpc/perf/isa207-common.c b/arch/powerpc/perf/isa207-common.c
index 8125160be7bc..3f3aa9a7063a 100644
--- a/arch/powerpc/perf/isa207-common.c
+++ b/arch/powerpc/perf/isa207-common.c
@@ -90,13 +90,15 @@ static void mmcra_sdar_mode(u64 event, unsigned long *mmcra)
90 * MMCRA[SDAR_MODE] will be set to 0b01 90 * MMCRA[SDAR_MODE] will be set to 0b01
91 * For rest 91 * For rest
92 * MMCRA[SDAR_MODE] will be set from event code. 92 * MMCRA[SDAR_MODE] will be set from event code.
93 * If sdar_mode from event is zero, default to 0b01. Hardware
94 * requires that we set a non-zero value.
93 */ 95 */
94 if (cpu_has_feature(CPU_FTR_ARCH_300)) { 96 if (cpu_has_feature(CPU_FTR_ARCH_300)) {
95 if (is_event_marked(event) || (*mmcra & MMCRA_SAMPLE_ENABLE)) 97 if (is_event_marked(event) || (*mmcra & MMCRA_SAMPLE_ENABLE))
96 *mmcra &= MMCRA_SDAR_MODE_NO_UPDATES; 98 *mmcra &= MMCRA_SDAR_MODE_NO_UPDATES;
97 else if (!cpu_has_feature(CPU_FTR_POWER9_DD1)) 99 else if (!cpu_has_feature(CPU_FTR_POWER9_DD1) && p9_SDAR_MODE(event))
98 *mmcra |= p9_SDAR_MODE(event) << MMCRA_SDAR_MODE_SHIFT; 100 *mmcra |= p9_SDAR_MODE(event) << MMCRA_SDAR_MODE_SHIFT;
99 else if (cpu_has_feature(CPU_FTR_POWER9_DD1)) 101 else
100 *mmcra |= MMCRA_SDAR_MODE_TLB; 102 *mmcra |= MMCRA_SDAR_MODE_TLB;
101 } else 103 } else
102 *mmcra |= MMCRA_SDAR_MODE_TLB; 104 *mmcra |= MMCRA_SDAR_MODE_TLB;
diff --git a/arch/powerpc/perf/power9-events-list.h b/arch/powerpc/perf/power9-events-list.h
index 80204e064362..50689180a6c1 100644
--- a/arch/powerpc/perf/power9-events-list.h
+++ b/arch/powerpc/perf/power9-events-list.h
@@ -51,8 +51,12 @@ EVENT(PM_DTLB_MISS, 0x300fc)
51EVENT(PM_ITLB_MISS, 0x400fc) 51EVENT(PM_ITLB_MISS, 0x400fc)
52/* Run_Instructions */ 52/* Run_Instructions */
53EVENT(PM_RUN_INST_CMPL, 0x500fa) 53EVENT(PM_RUN_INST_CMPL, 0x500fa)
54/* Alternate event code for PM_RUN_INST_CMPL */
55EVENT(PM_RUN_INST_CMPL_ALT, 0x400fa)
54/* Run_cycles */ 56/* Run_cycles */
55EVENT(PM_RUN_CYC, 0x600f4) 57EVENT(PM_RUN_CYC, 0x600f4)
58/* Alternate event code for Run_cycles */
59EVENT(PM_RUN_CYC_ALT, 0x200f4)
56/* Instruction Dispatched */ 60/* Instruction Dispatched */
57EVENT(PM_INST_DISP, 0x200f2) 61EVENT(PM_INST_DISP, 0x200f2)
58EVENT(PM_INST_DISP_ALT, 0x300f2) 62EVENT(PM_INST_DISP_ALT, 0x300f2)
diff --git a/arch/powerpc/perf/power9-pmu.c b/arch/powerpc/perf/power9-pmu.c
index f17435e4a489..2280cf87ff9c 100644
--- a/arch/powerpc/perf/power9-pmu.c
+++ b/arch/powerpc/perf/power9-pmu.c
@@ -107,6 +107,8 @@ extern struct attribute_group isa207_pmu_format_group;
107/* Table of alternatives, sorted by column 0 */ 107/* Table of alternatives, sorted by column 0 */
108static const unsigned int power9_event_alternatives[][MAX_ALT] = { 108static const unsigned int power9_event_alternatives[][MAX_ALT] = {
109 { PM_INST_DISP, PM_INST_DISP_ALT }, 109 { PM_INST_DISP, PM_INST_DISP_ALT },
110 { PM_RUN_CYC_ALT, PM_RUN_CYC },
111 { PM_RUN_INST_CMPL_ALT, PM_RUN_INST_CMPL },
110}; 112};
111 113
112static int power9_get_alternatives(u64 event, unsigned int flags, u64 alt[]) 114static int power9_get_alternatives(u64 event, unsigned int flags, u64 alt[])
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
index 59684b4af4d1..9b87abb178f0 100644
--- a/arch/powerpc/platforms/powernv/opal.c
+++ b/arch/powerpc/platforms/powernv/opal.c
@@ -59,6 +59,8 @@ static struct task_struct *kopald_tsk;
59 59
60void opal_configure_cores(void) 60void opal_configure_cores(void)
61{ 61{
62 u64 reinit_flags = 0;
63
62 /* Do the actual re-init, This will clobber all FPRs, VRs, etc... 64 /* Do the actual re-init, This will clobber all FPRs, VRs, etc...
63 * 65 *
64 * It will preserve non volatile GPRs and HSPRG0/1. It will 66 * It will preserve non volatile GPRs and HSPRG0/1. It will
@@ -66,11 +68,24 @@ void opal_configure_cores(void)
66 * but it might clobber a bunch. 68 * but it might clobber a bunch.
67 */ 69 */
68#ifdef __BIG_ENDIAN__ 70#ifdef __BIG_ENDIAN__
69 opal_reinit_cpus(OPAL_REINIT_CPUS_HILE_BE); 71 reinit_flags |= OPAL_REINIT_CPUS_HILE_BE;
70#else 72#else
71 opal_reinit_cpus(OPAL_REINIT_CPUS_HILE_LE); 73 reinit_flags |= OPAL_REINIT_CPUS_HILE_LE;
72#endif 74#endif
73 75
76 /*
77 * POWER9 always support running hash:
78 * ie. Host hash supports hash guests
79 * Host radix supports hash/radix guests
80 */
81 if (cpu_has_feature(CPU_FTR_ARCH_300)) {
82 reinit_flags |= OPAL_REINIT_CPUS_MMU_HASH;
83 if (early_radix_enabled())
84 reinit_flags |= OPAL_REINIT_CPUS_MMU_RADIX;
85 }
86
87 opal_reinit_cpus(reinit_flags);
88
74 /* Restore some bits */ 89 /* Restore some bits */
75 if (cur_cpu_spec->cpu_restore) 90 if (cur_cpu_spec->cpu_restore)
76 cur_cpu_spec->cpu_restore(); 91 cur_cpu_spec->cpu_restore();
diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c
index 2dc7e5fb86c3..897aa1400eb8 100644
--- a/arch/powerpc/platforms/powernv/setup.c
+++ b/arch/powerpc/platforms/powernv/setup.c
@@ -225,6 +225,8 @@ static void pnv_kexec_wait_secondaries_down(void)
225 225
226static void pnv_kexec_cpu_down(int crash_shutdown, int secondary) 226static void pnv_kexec_cpu_down(int crash_shutdown, int secondary)
227{ 227{
228 u64 reinit_flags;
229
228 if (xive_enabled()) 230 if (xive_enabled())
229 xive_kexec_teardown_cpu(secondary); 231 xive_kexec_teardown_cpu(secondary);
230 else 232 else
@@ -254,8 +256,15 @@ static void pnv_kexec_cpu_down(int crash_shutdown, int secondary)
254 * We might be running as little-endian - now that interrupts 256 * We might be running as little-endian - now that interrupts
255 * are disabled, reset the HILE bit to big-endian so we don't 257 * are disabled, reset the HILE bit to big-endian so we don't
256 * take interrupts in the wrong endian later 258 * take interrupts in the wrong endian later
259 *
260 * We reinit to enable both radix and hash on P9 to ensure
261 * the mode used by the next kernel is always supported.
257 */ 262 */
258 opal_reinit_cpus(OPAL_REINIT_CPUS_HILE_BE); 263 reinit_flags = OPAL_REINIT_CPUS_HILE_BE;
264 if (cpu_has_feature(CPU_FTR_ARCH_300))
265 reinit_flags |= OPAL_REINIT_CPUS_MMU_RADIX |
266 OPAL_REINIT_CPUS_MMU_HASH;
267 opal_reinit_cpus(reinit_flags);
259 } 268 }
260} 269}
261#endif /* CONFIG_KEXEC_CORE */ 270#endif /* CONFIG_KEXEC_CORE */