Skip to content

Commit f4eff13

Browse files
npiggingregkh
authored andcommitted
powerpc/64s: Fix dt_cpu_ftrs to have restore_cpu clear unwanted LPCR bits
commit a57ac41 upstream. Presently the dt_cpu_ftrs restore_cpu will only add bits to the LPCR for secondaries, but some bits must be removed (e.g., UPRT for HPT). Not clearing these bits on secondaries causes checkstops when booting with disable_radix. restore_cpu can not just set LPCR, because it is also called by the idle wakeup code which relies on opal_slw_set_reg to restore the value of LPCR, at least on P8 which does not save LPCR to stack in the idle code. Fix this by including a mask of bits to clear from LPCR as well, which is used by restore_cpu. This is a little messy now, but it's a minimal fix that can be backported. Longer term, the idle SPR save/restore code can be reworked to completely avoid calls to restore_cpu, then restore_cpu would be able to unconditionally set LPCR to match boot processor environment. Fixes: 5a61ef7 ("powerpc/64s: Support new device tree binding for discovering CPU features") Cc: [email protected] # v4.12+ Signed-off-by: Nicholas Piggin <[email protected]> Signed-off-by: Michael Ellerman <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent c3baeca commit f4eff13

File tree

1 file changed

+9
-3
lines changed

1 file changed

+9
-3
lines changed

arch/powerpc/kernel/dt_cpu_ftrs.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ static int hv_mode;
8686

8787
static struct {
8888
u64 lpcr;
89+
u64 lpcr_clear;
8990
u64 hfscr;
9091
u64 fscr;
9192
} system_registers;
@@ -115,6 +116,8 @@ static void cpufeatures_flush_tlb(void)
115116

116117
static void __restore_cpu_cpufeatures(void)
117118
{
119+
u64 lpcr;
120+
118121
/*
119122
* LPCR is restored by the power on engine already. It can be changed
120123
* after early init e.g., by radix enable, and we have no unified API
@@ -127,8 +130,10 @@ static void __restore_cpu_cpufeatures(void)
127130
* The best we can do to accommodate secondary boot and idle restore
128131
* for now is "or" LPCR with existing.
129132
*/
130-
131-
mtspr(SPRN_LPCR, system_registers.lpcr | mfspr(SPRN_LPCR));
133+
lpcr = mfspr(SPRN_LPCR);
134+
lpcr |= system_registers.lpcr;
135+
lpcr &= ~system_registers.lpcr_clear;
136+
mtspr(SPRN_LPCR, lpcr);
132137
if (hv_mode) {
133138
mtspr(SPRN_LPID, 0);
134139
mtspr(SPRN_HFSCR, system_registers.hfscr);
@@ -351,8 +356,9 @@ static int __init feat_enable_mmu_hash_v3(struct dt_cpu_feature *f)
351356
{
352357
u64 lpcr;
353358

359+
system_registers.lpcr_clear |= (LPCR_ISL | LPCR_UPRT | LPCR_HR);
354360
lpcr = mfspr(SPRN_LPCR);
355-
lpcr &= ~LPCR_ISL;
361+
lpcr &= ~(LPCR_ISL | LPCR_UPRT | LPCR_HR);
356362
mtspr(SPRN_LPCR, lpcr);
357363

358364
cur_cpu_spec->mmu_features |= MMU_FTRS_HASH_BASE;

0 commit comments

Comments
 (0)