blob: 8e871e86446f92967cb6b81b9a2192c8554a504f [file] [log] [blame]
Joel Stanley83360db2018-04-11 15:11:59 +09301From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2From: Michael Ellerman <mpe@ellerman.id.au>
3Date: Thu, 12 Apr 2018 15:53:52 +1000
4Subject: [PATCH 3/4] powerpc/mm/radix: Fix checkstops caused by invalid tlbiel
5
6In tlbiel_radix_set_isa300() we use the PPC_TLBIEL() macro to
7construct tlbiel instructions. The instruction takes 5 fields, two of
8which are registers, and the others are constants. But because it's
9constructed with inline asm the compiler doesn't know that.
10
11We got the constraint wrong on the 'r' field, using "r" tells the
12compiler to put the value in a register. The value we then get in the
13macro is the *register number*, not the value of the field.
14
15That means when we mask the register number with 0x1 we get 0 or 1
16depending on which register the compiler happens to put the constant
17in, eg:
18
19 li r10,1
20 tlbiel r8,r9,2,0,0
21
22 li r7,1
23 tlbiel r10,r6,0,0,1
24
25If we're unlucky we might generate an invalid instruction form, for
26example RIC=0, PRS=1 and R=0, tlbiel r8,r7,0,1,0, this has been
27observed to cause machine checks:
28
29 Oops: Machine check, sig: 7 [#1]
30 CPU: 24 PID: 0 Comm: swapper
31 NIP: 00000000000385f4 LR: 000000000100ed00 CTR: 000000000000007f
32 REGS: c00000000110bb40 TRAP: 0200
33 MSR: 9000000000201003 <SF,HV,ME,RI,LE> CR: 48002222 XER: 20040000
34 CFAR: 00000000000385d0 DAR: 0000000000001c00 DSISR: 00000200 SOFTE: 1
35
36If the machine check happens early in boot while we have MSR_ME=0 it
37will escalate into a checkstop and kill the box entirely.
38
39To fix it we could change the inline asm constraint to "i" which
40tells the compiler the value is a constant. But a better fix is to just
41pass a literal 1 into the macro, which bypasses any problems with inline
42asm constraints.
43
44Fixes: d4748276ae14 ("powerpc/64s: Improve local TLB flush for boot and MCE on POWER9")
45Cc: stable@vger.kernel.org # v4.16+
46Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
47Signed-off-by: Joel Stanley <joel@jms.id.au>
48---
49 arch/powerpc/mm/tlb-radix.c | 5 ++---
50 1 file changed, 2 insertions(+), 3 deletions(-)
51
52diff --git a/arch/powerpc/mm/tlb-radix.c b/arch/powerpc/mm/tlb-radix.c
53index a07f5372a4bf..9ab051155af3 100644
54--- a/arch/powerpc/mm/tlb-radix.c
55+++ b/arch/powerpc/mm/tlb-radix.c
56@@ -33,13 +33,12 @@ static inline void tlbiel_radix_set_isa300(unsigned int set, unsigned int is,
57 {
58 unsigned long rb;
59 unsigned long rs;
60- unsigned int r = 1; /* radix format */
61
62 rb = (set << PPC_BITLSHIFT(51)) | (is << PPC_BITLSHIFT(53));
63 rs = ((unsigned long)pid << PPC_BITLSHIFT(31));
64
65- asm volatile(PPC_TLBIEL(%0, %1, %2, %3, %4)
66- : : "r"(rb), "r"(rs), "i"(ric), "i"(prs), "r"(r)
67+ asm volatile(PPC_TLBIEL(%0, %1, %2, %3, 1)
68+ : : "r"(rb), "r"(rs), "i"(ric), "i"(prs)
69 : "memory");
70 }
71