diff mbox

powerpc: Hande page faults for bad paste and bad AMO

Message ID 1499830007.2865.36.camel@kernel.crashing.org (mailing list archive)
State Changes Requested
Headers show

Commit Message

Benjamin Herrenschmidt July 12, 2017, 3:26 a.m. UTC
On POWER9 and bad paste instruction (targeting the wrong memory
type) or an invalid opcode in an AMO (atomic memory operation)
will result in specific DSISR bits to be set.

We currently don't understand those bits and thus just "hang"
the process taking constant page faults.

Additionally in the case of paste, it appears that we don't
always get a valid DAR value when the error is a wrong memory
type.

So we need to test those errors early in do_page_fault(),
I chose to generate a SIGBUS which is more correct than a SIGSEGV.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---

Comments

Aneesh Kumar K.V July 12, 2017, 6:07 a.m. UTC | #1
Benjamin Herrenschmidt <benh@kernel.crashing.org> writes:

> On POWER9 and bad paste instruction (targeting the wrong memory
> type) or an invalid opcode in an AMO (atomic memory operation)
> will result in specific DSISR bits to be set.
>
> We currently don't understand those bits and thus just "hang"
> the process taking constant page faults.
>
> Additionally in the case of paste, it appears that we don't
> always get a valid DAR value when the error is a wrong memory
> type.
>
> So we need to test those errors early in do_page_fault(),
> I chose to generate a SIGBUS which is more correct than a SIGSEGV.

This is true even for hash right ? If so do we want to update
do_hash_page:
#ifdef CONFIG_PPC_STD_MMU_64
	andis.	r0,r4,0xa450		/* weird error? */
	bne-	handle_page_fault	/* if not, try to insert a HPTE */

that 0xa450 such that we add these errors and call hand_page_fault in
case of these DSISR values ?


>
> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> ---
>
> diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
> index 0266c664014a..5dfce2022f74 100644
> --- a/arch/powerpc/mm/fault.c
> +++ b/arch/powerpc/mm/fault.c
> @@ -337,6 +337,21 @@ int do_page_fault(struct pt_regs *regs, unsigned long address,
>  	}
>  #endif /* CONFIG_PPC_ICSWX */
>  
> +#ifdef CONFIG_PPC_STD_MMU_64
> +	/*
> +	 * These faults indicate a copy/paste on an invalid memory type
> +	 * or an incorrect AMO operation. They have been observed as not
> +	 * properly updating the DAR, so handle them early
> +	 */
> +	if (error_code & (DSISR_BAD_COPYPASTE | DSISR_BAD_AMO)) {
> +		if (user_mode(regs))
> +			_exception(SIGBUS, regs, BUS_OBJERR, address);
> +		else
> +			rc = SIGBUS;
> +		goto bail;
> +	}
> +#endif /* CONFIG_PPC_STD_MMU_64 */
> +
>  	if (notify_page_fault(regs))
>  		goto bail;
>  
> diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
> index 7e50e47375d6..71f524f2b109 100644
> --- a/arch/powerpc/include/asm/reg.h
> +++ b/arch/powerpc/include/asm/reg.h
> @@ -282,6 +282,8 @@
>  #define   DSISR_UNSUPP_MMU	0x00080000	/* Unsupported MMU config */
>  #define   DSISR_SET_RC		0x00040000	/* Failed setting of R/C bits */
>  #define   DSISR_PGDIRFAULT      0x00020000      /* Fault on page directory */
> +#define   DSISR_BAD_COPYPASTE   0x00000008      /* Copy/Paste on wrong mem type */
> +#define   DSISR_BAD_AMO		0x00000004	/* Incorrect AMO opcode */
>  #define SPRN_TBRL	0x10C	/* Time Base Read Lower Register (user, R/O) */
>  #define SPRN_TBRU	0x10D	/* Time Base Read Upper Register (user, R/O) */
>  #define SPRN_CIR	0x11B	/* Chip Information Register (hyper, R/0) */

-aneesh
Benjamin Herrenschmidt July 12, 2017, 6:46 a.m. UTC | #2
On Wed, 2017-07-12 at 11:37 +0530, Aneesh Kumar K.V wrote:
> > So we need to test those errors early in do_page_fault(),
> > I chose to generate a SIGBUS which is more correct than a SIGSEGV.
> 
> This is true even for hash right ? If so do we want to update
> do_hash_page:
> #ifdef CONFIG_PPC_STD_MMU_64
>         andis.  r0,r4,0xa450            /* weird error? */
>         bne-    handle_page_fault       /* if not, try to insert a HPTE */
> 
> that 0xa450 such that we add these errors and call hand_page_fault in
> case of these DSISR values ?

Correct, I forgot about that one. I'll respin.

Cheers,
Ben.
diff mbox

Patch

diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
index 0266c664014a..5dfce2022f74 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -337,6 +337,21 @@  int do_page_fault(struct pt_regs *regs, unsigned long address,
 	}
 #endif /* CONFIG_PPC_ICSWX */
 
+#ifdef CONFIG_PPC_STD_MMU_64
+	/*
+	 * These faults indicate a copy/paste on an invalid memory type
+	 * or an incorrect AMO operation. They have been observed as not
+	 * properly updating the DAR, so handle them early
+	 */
+	if (error_code & (DSISR_BAD_COPYPASTE | DSISR_BAD_AMO)) {
+		if (user_mode(regs))
+			_exception(SIGBUS, regs, BUS_OBJERR, address);
+		else
+			rc = SIGBUS;
+		goto bail;
+	}
+#endif /* CONFIG_PPC_STD_MMU_64 */
+
 	if (notify_page_fault(regs))
 		goto bail;
 
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index 7e50e47375d6..71f524f2b109 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -282,6 +282,8 @@ 
 #define   DSISR_UNSUPP_MMU	0x00080000	/* Unsupported MMU config */
 #define   DSISR_SET_RC		0x00040000	/* Failed setting of R/C bits */
 #define   DSISR_PGDIRFAULT      0x00020000      /* Fault on page directory */
+#define   DSISR_BAD_COPYPASTE   0x00000008      /* Copy/Paste on wrong mem type */
+#define   DSISR_BAD_AMO		0x00000004	/* Incorrect AMO opcode */
 #define SPRN_TBRL	0x10C	/* Time Base Read Lower Register (user, R/O) */
 #define SPRN_TBRU	0x10D	/* Time Base Read Upper Register (user, R/O) */
 #define SPRN_CIR	0x11B	/* Chip Information Register (hyper, R/0) */