powerpc/64s: ISAv3 initialize MMU registers before setting partition table
Nicholas Piggin
reviewerPATCH v3 1/1 powerpc/64s: ISAv3 initialize MMU registers before setting partition table
kexec can leave MMU registers set when booting into a new kernel, PIDR in particular. The boot sequence does not zero PIDR, so it only gets set when CPUs first switch to a userspace processes (until then it's running a kernel thread with effective PID = 0).
This leaves a window where a process table entry and page tables are set up due to user processes running on other CPUs, that happen to match with a stale PID. The CPU with that PID may cause speculative accesses that address quadrant 0, which will result in cached translations and PWC for that process, on a CPU which is not in the mm_cpumask and so they will not get invalidated properly.
The most common result is the kernel hanging in infinite page fault loops soon after kexec (usually in schedule_tail, which is usually the first non-speculative quardant 0 access to a new PID) due to a stale PWC. However being a stale translation error, it could result in anything up to security and data corruption problems.
Fix this by zeroing out PIDR at boot and kexec.
---
v3: do the register clearing in the early CPU setup code, suggested by
Michael Ellerman, which already clears LPID.
arch/powerpc/kernel/cpu_setup_power.S | 2 ++ 1 file changed, 2 insertions(+)
arch/powerpc/kernel/cpu_setup_power.S +2 -0
@@ -102,6 +102,7 @@ _GLOBAL(__setup_cpu_power9) li r0,0 mtspr SPRN_PSSCR,r0 mtspr SPRN_LPID,r0 + mtspr SPRN_PID,r0 mfspr r3,SPRN_LPCR LOAD_REG_IMMEDIATE(r4, LPCR_PECEDH | LPCR_PECE_HVEE | LPCR_HVICE | LPCR_HEIC) or r3, r3, r4
@@ -126,6 +127,7 @@ _GLOBAL(__restore_cpu_power9) li r0,0 mtspr SPRN_PSSCR,r0 mtspr SPRN_LPID,r0 + mtspr SPRN_PID,r0 mfspr r3,SPRN_LPCR LOAD_REG_IMMEDIATE(r4, LPCR_PECEDH | LPCR_PECE_HVEE | LPCR_HVICE | LPCR_HEIC) or r3, r3, r4
Signature · 1 line
2.15.0
Michael Ellerman
AppliedQuoted 18 lines · Nicholas Piggin
kexec can leave MMU registers set when booting into a new kernel, PIDR in particular. The boot sequence does not zero PIDR, so it only gets set when CPUs first switch to a userspace processes (until then it's running a kernel thread with effective PID = 0).
This leaves a window where a process table entry and page tables are set up due to user processes running on other CPUs, that happen to match with a stale PID. The CPU with that PID may cause speculative accesses that address quadrant 0, which will result in cached translations and PWC for that process, on a CPU which is not in the
mm_cpumaskand so they will not get invalidated properly.The most common result is the kernel hanging in infinite page fault loops soon after kexec (usually in
schedule_tail, which is usually the first non-speculative quardant 0 access to a new PID) due to a stale PWC. However being a stale translation error, it could result in anything up to security and data corruption problems.
Quoted 3 lines
Fix this by zeroing out PIDR at boot and kexec.
Signed-off-by Nicholas Piggin <[email protected]>
Applied to powerpc fixes, thanks.
https://git.kernel.org/powerpc/c/371b80447ff33ddac392c189cf884a
cheers