]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/4.16.4/powerpc-64s-fix-dt_cpu_ftrs-to-have-restore_cpu-clear-unwanted-lpcr-bits.patch
Fixes for 4.19
[thirdparty/kernel/stable-queue.git] / releases / 4.16.4 / powerpc-64s-fix-dt_cpu_ftrs-to-have-restore_cpu-clear-unwanted-lpcr-bits.patch
1 From a57ac411832384eb93df4bfed2bf644c4089720e Mon Sep 17 00:00:00 2001
2 From: Nicholas Piggin <npiggin@gmail.com>
3 Date: Thu, 5 Apr 2018 15:50:49 +1000
4 Subject: powerpc/64s: Fix dt_cpu_ftrs to have restore_cpu clear unwanted LPCR bits
5
6 From: Nicholas Piggin <npiggin@gmail.com>
7
8 commit a57ac411832384eb93df4bfed2bf644c4089720e upstream.
9
10 Presently the dt_cpu_ftrs restore_cpu will only add bits to the LPCR
11 for secondaries, but some bits must be removed (e.g., UPRT for HPT).
12 Not clearing these bits on secondaries causes checkstops when booting
13 with disable_radix.
14
15 restore_cpu can not just set LPCR, because it is also called by the
16 idle wakeup code which relies on opal_slw_set_reg to restore the value
17 of LPCR, at least on P8 which does not save LPCR to stack in the idle
18 code.
19
20 Fix this by including a mask of bits to clear from LPCR as well, which
21 is used by restore_cpu.
22
23 This is a little messy now, but it's a minimal fix that can be
24 backported. Longer term, the idle SPR save/restore code can be
25 reworked to completely avoid calls to restore_cpu, then restore_cpu
26 would be able to unconditionally set LPCR to match boot processor
27 environment.
28
29 Fixes: 5a61ef74f269f ("powerpc/64s: Support new device tree binding for discovering CPU features")
30 Cc: stable@vger.kernel.org # v4.12+
31 Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
32 Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
33 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
34
35 ---
36 arch/powerpc/kernel/dt_cpu_ftrs.c | 12 +++++++++---
37 1 file changed, 9 insertions(+), 3 deletions(-)
38
39 --- a/arch/powerpc/kernel/dt_cpu_ftrs.c
40 +++ b/arch/powerpc/kernel/dt_cpu_ftrs.c
41 @@ -84,6 +84,7 @@ static int hv_mode;
42
43 static struct {
44 u64 lpcr;
45 + u64 lpcr_clear;
46 u64 hfscr;
47 u64 fscr;
48 } system_registers;
49 @@ -92,6 +93,8 @@ static void (*init_pmu_registers)(void);
50
51 static void __restore_cpu_cpufeatures(void)
52 {
53 + u64 lpcr;
54 +
55 /*
56 * LPCR is restored by the power on engine already. It can be changed
57 * after early init e.g., by radix enable, and we have no unified API
58 @@ -104,8 +107,10 @@ static void __restore_cpu_cpufeatures(vo
59 * The best we can do to accommodate secondary boot and idle restore
60 * for now is "or" LPCR with existing.
61 */
62 -
63 - mtspr(SPRN_LPCR, system_registers.lpcr | mfspr(SPRN_LPCR));
64 + lpcr = mfspr(SPRN_LPCR);
65 + lpcr |= system_registers.lpcr;
66 + lpcr &= ~system_registers.lpcr_clear;
67 + mtspr(SPRN_LPCR, lpcr);
68 if (hv_mode) {
69 mtspr(SPRN_LPID, 0);
70 mtspr(SPRN_HFSCR, system_registers.hfscr);
71 @@ -325,8 +330,9 @@ static int __init feat_enable_mmu_hash_v
72 {
73 u64 lpcr;
74
75 + system_registers.lpcr_clear |= (LPCR_ISL | LPCR_UPRT | LPCR_HR);
76 lpcr = mfspr(SPRN_LPCR);
77 - lpcr &= ~LPCR_ISL;
78 + lpcr &= ~(LPCR_ISL | LPCR_UPRT | LPCR_HR);
79 mtspr(SPRN_LPCR, lpcr);
80
81 cur_cpu_spec->mmu_features |= MMU_FTRS_HASH_BASE;