Commit a3961f82 authored by Mahesh Salgaonkar's avatar Mahesh Salgaonkar Committed by Michael Ellerman

powerpc/powernv: Fix kexec crashes caused by tlbie tracing

Rebooting into a new kernel with kexec fails in trace_tlbie() which is
called from native_hpte_clear(). This happens if the running kernel
has CONFIG_LOCKDEP enabled. With lockdep enabled, the tracepoints
always execute few RCU checks regardless of whether tracing is on or
off. We are already in the last phase of kexec sequence in real mode
with HILE_BE set. At this point the RCU check ends up in
RCU_LOCKDEP_WARN and causes kexec to fail.

Fix this by not calling trace_tlbie() from native_hpte_clear().

mpe: It's not safe to call trace points at this point in the kexec
path, even if we could avoid the RCU checks/warnings. The only
solution is to not call them.

Fixes: 0428491c ("powerpc/mm: Trace tlbie(l) instructions")
Cc: stable@vger.kernel.org # v4.13+
Signed-off-by: default avatarMahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
Reported-by: default avatarAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Suggested-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Acked-by: default avatarNaveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent 12841f87
...@@ -47,7 +47,8 @@ ...@@ -47,7 +47,8 @@
DEFINE_RAW_SPINLOCK(native_tlbie_lock); DEFINE_RAW_SPINLOCK(native_tlbie_lock);
static inline void __tlbie(unsigned long vpn, int psize, int apsize, int ssize) static inline unsigned long ___tlbie(unsigned long vpn, int psize,
int apsize, int ssize)
{ {
unsigned long va; unsigned long va;
unsigned int penc; unsigned int penc;
...@@ -100,7 +101,15 @@ static inline void __tlbie(unsigned long vpn, int psize, int apsize, int ssize) ...@@ -100,7 +101,15 @@ static inline void __tlbie(unsigned long vpn, int psize, int apsize, int ssize)
: "memory"); : "memory");
break; break;
} }
trace_tlbie(0, 0, va, 0, 0, 0, 0); return va;
}
static inline void __tlbie(unsigned long vpn, int psize, int apsize, int ssize)
{
unsigned long rb;
rb = ___tlbie(vpn, psize, apsize, ssize);
trace_tlbie(0, 0, rb, 0, 0, 0, 0);
} }
static inline void __tlbiel(unsigned long vpn, int psize, int apsize, int ssize) static inline void __tlbiel(unsigned long vpn, int psize, int apsize, int ssize)
...@@ -652,7 +661,7 @@ static void native_hpte_clear(void) ...@@ -652,7 +661,7 @@ static void native_hpte_clear(void)
if (hpte_v & HPTE_V_VALID) { if (hpte_v & HPTE_V_VALID) {
hpte_decode(hptep, slot, &psize, &apsize, &ssize, &vpn); hpte_decode(hptep, slot, &psize, &apsize, &ssize, &vpn);
hptep->v = 0; hptep->v = 0;
__tlbie(vpn, psize, apsize, ssize); ___tlbie(vpn, psize, apsize, ssize);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment