[SRU,Artful,1/1] powerpc/64s: Initialize ISAv3 MMU registers before setting partition table

Message ID 5483779b6786a6845e3a7dede301a6697d4c018e.1517850000.git.joseph.salisbury@canonical.com
State New
Headers show
Series
  • [SRU,Artful,1/1] powerpc/64s: Initialize ISAv3 MMU registers before setting partition table
Related show

Commit Message

Joseph Salisbury Feb. 5, 2018, 8:50 p.m.
From: Nicholas Piggin <npiggin@gmail.com>

BugLink: http://bugs.launchpad.net/bugs/1736145

kexec can leave MMU registers set when booting into a new kernel,
the PIDR (Process Identification Register) 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 (aka userspace addresses), which will
result in cached translations and PWC (Page Walk Cache) for that
process, on a CPU which is not in the mm_cpumask and so they will not
be 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 quadrant 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.

Fixes: 7e381c0ff618 ("powerpc/mm/radix: Add mmu context handling callback for radix")
Cc: stable@vger.kernel.org # v4.7+
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
(cherry picked from commit 371b80447ff33ddac392c189cf884a5a3e18faeb)
Signed-off-by: Joseph Salisbury <joseph.salisbury@canonical.com>
---
 arch/powerpc/kernel/cpu_setup_power.S | 2 ++
 1 file changed, 2 insertions(+)

Comments

Colin King Feb. 5, 2018, 8:54 p.m. | #1
On 05/02/18 20:50, Joseph Salisbury wrote:
> From: Nicholas Piggin <npiggin@gmail.com>
> 
> BugLink: http://bugs.launchpad.net/bugs/1736145
> 
> kexec can leave MMU registers set when booting into a new kernel,
> the PIDR (Process Identification Register) 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 (aka userspace addresses), which will
> result in cached translations and PWC (Page Walk Cache) for that
> process, on a CPU which is not in the mm_cpumask and so they will not
> be 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 quadrant 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.
> 
> Fixes: 7e381c0ff618 ("powerpc/mm/radix: Add mmu context handling callback for radix")
> Cc: stable@vger.kernel.org # v4.7+
> Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
> (cherry picked from commit 371b80447ff33ddac392c189cf884a5a3e18faeb)
> Signed-off-by: Joseph Salisbury <joseph.salisbury@canonical.com>
> ---
>  arch/powerpc/kernel/cpu_setup_power.S | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/arch/powerpc/kernel/cpu_setup_power.S b/arch/powerpc/kernel/cpu_setup_power.S
> index 610955f..679bbe7 100644
> --- a/arch/powerpc/kernel/cpu_setup_power.S
> +++ b/arch/powerpc/kernel/cpu_setup_power.S
> @@ -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
> 
Positive test results. Clean upstream cherry pick, does what it says, so..

Acked-by: Colin Ian King <colin.king@canonical.com>
Khaled Elmously Feb. 8, 2018, 7:53 p.m. | #2
On 2018-02-05 15:50:38 , Joseph Salisbury wrote:
> From: Nicholas Piggin <npiggin@gmail.com>
> 
> BugLink: http://bugs.launchpad.net/bugs/1736145
> 
> kexec can leave MMU registers set when booting into a new kernel,
> the PIDR (Process Identification Register) 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 (aka userspace addresses), which will
> result in cached translations and PWC (Page Walk Cache) for that
> process, on a CPU which is not in the mm_cpumask and so they will not
> be 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 quadrant 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.
> 
> Fixes: 7e381c0ff618 ("powerpc/mm/radix: Add mmu context handling callback for radix")
> Cc: stable@vger.kernel.org # v4.7+
> Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
> (cherry picked from commit 371b80447ff33ddac392c189cf884a5a3e18faeb)
> Signed-off-by: Joseph Salisbury <joseph.salisbury@canonical.com>
> ---
>  arch/powerpc/kernel/cpu_setup_power.S | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/arch/powerpc/kernel/cpu_setup_power.S b/arch/powerpc/kernel/cpu_setup_power.S
> index 610955f..679bbe7 100644
> --- a/arch/powerpc/kernel/cpu_setup_power.S
> +++ b/arch/powerpc/kernel/cpu_setup_power.S
> @@ -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

Acked-by: Khalid Elmously <khalid.elmously@canonical.com>
Kleber Souza Feb. 28, 2018, 4:07 p.m. | #3
On 02/05/18 21:50, Joseph Salisbury wrote:
> From: Nicholas Piggin <npiggin@gmail.com>
> 
> BugLink: http://bugs.launchpad.net/bugs/1736145
> 
> kexec can leave MMU registers set when booting into a new kernel,
> the PIDR (Process Identification Register) 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 (aka userspace addresses), which will
> result in cached translations and PWC (Page Walk Cache) for that
> process, on a CPU which is not in the mm_cpumask and so they will not
> be 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 quadrant 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.
> 
> Fixes: 7e381c0ff618 ("powerpc/mm/radix: Add mmu context handling callback for radix")
> Cc: stable@vger.kernel.org # v4.7+
> Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
> (cherry picked from commit 371b80447ff33ddac392c189cf884a5a3e18faeb)
> Signed-off-by: Joseph Salisbury <joseph.salisbury@canonical.com>
> ---
>  arch/powerpc/kernel/cpu_setup_power.S | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/arch/powerpc/kernel/cpu_setup_power.S b/arch/powerpc/kernel/cpu_setup_power.S
> index 610955f..679bbe7 100644
> --- a/arch/powerpc/kernel/cpu_setup_power.S
> +++ b/arch/powerpc/kernel/cpu_setup_power.S
> @@ -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
> 

Applied to artful/master-next-backlog branch.

Thanks,
Kleber

Patch

diff --git a/arch/powerpc/kernel/cpu_setup_power.S b/arch/powerpc/kernel/cpu_setup_power.S
index 610955f..679bbe7 100644
--- a/arch/powerpc/kernel/cpu_setup_power.S
+++ b/arch/powerpc/kernel/cpu_setup_power.S
@@ -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