[PATCH v3 11/15] powerpc/64s: machine check interrupt update NMI accounting

Christophe Leroy christophe.leroy at c-s.fr
Tue Apr 7 15:37:02 AEST 2020



Le 07/04/2020 à 07:16, Nicholas Piggin a écrit :
> machine_check_early is taken as an NMI, so nmi_enter is used there.
> machine_check_exception is no longer taken as an NMI (it's invoked
> via irq_work in the case a machine check hits in kernel mode), so
> remove the nmi_enter from that case.

Euh ... Is that also the case for PPC32 ?

AFAIK machine_check_exception() is called as an NMI on PPC32.

Christophe

> 
> In NMI context, hash faults don't try to refill the hash table, which
> can lead to crashes accessing non-pinned kernel pages. System reset
> still has this potential problem.
> 
> Signed-off-by: Nicholas Piggin <npiggin at gmail.com>
> ---
>   arch/powerpc/kernel/mce.c     |  7 +++++++
>   arch/powerpc/kernel/process.c |  2 +-
>   arch/powerpc/kernel/traps.c   | 13 +------------
>   3 files changed, 9 insertions(+), 13 deletions(-)
> 
> diff --git a/arch/powerpc/kernel/mce.c b/arch/powerpc/kernel/mce.c
> index 8077b5fb18a7..be7e3f92a7b5 100644
> --- a/arch/powerpc/kernel/mce.c
> +++ b/arch/powerpc/kernel/mce.c
> @@ -574,6 +574,9 @@ EXPORT_SYMBOL_GPL(machine_check_print_event_info);
>   long machine_check_early(struct pt_regs *regs)
>   {
>   	long handled = 0;
> +	bool nested = in_nmi();
> +	if (!nested)
> +		nmi_enter();
>   
>   	hv_nmi_check_nonrecoverable(regs);
>   
> @@ -582,6 +585,10 @@ long machine_check_early(struct pt_regs *regs)
>   	 */
>   	if (ppc_md.machine_check_early)
>   		handled = ppc_md.machine_check_early(regs);
> +
> +	if (!nested)
> +		nmi_exit();
> +
>   	return handled;
>   }
>   
> diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
> index 9c21288f8645..44410dd3029f 100644
> --- a/arch/powerpc/kernel/process.c
> +++ b/arch/powerpc/kernel/process.c
> @@ -1421,7 +1421,7 @@ void show_regs(struct pt_regs * regs)
>   		pr_cont("DAR: "REG" DSISR: %08lx ", regs->dar, regs->dsisr);
>   #endif
>   #ifdef CONFIG_PPC64
> -	pr_cont("IRQMASK: %lx ", regs->softe);
> +	pr_cont("IRQMASK: %lx IN_NMI:%d IN_MCE:%d", regs->softe, (int)get_paca()->in_nmi, (int)get_paca()->in_mce);
>   #endif
>   #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
>   	if (MSR_TM_ACTIVE(regs->msr))
> diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
> index 3fca22276bb1..9f221772eb73 100644
> --- a/arch/powerpc/kernel/traps.c
> +++ b/arch/powerpc/kernel/traps.c
> @@ -823,9 +823,6 @@ int machine_check_generic(struct pt_regs *regs)
>   void machine_check_exception(struct pt_regs *regs)
>   {
>   	int recover = 0;
> -	bool nested = in_nmi();
> -	if (!nested)
> -		nmi_enter();
>   
>   	__this_cpu_inc(irq_stat.mce_exceptions);
>   
> @@ -851,20 +848,12 @@ void machine_check_exception(struct pt_regs *regs)
>   	if (check_io_access(regs))
>   		goto bail;
>   
> -	if (!nested)
> -		nmi_exit();
> -
>   	die("Machine check", regs, SIGBUS);
>   
> +bail:
>   	/* Must die if the interrupt is not recoverable */
>   	if (!(regs->msr & MSR_RI))
>   		nmi_panic(regs, "Unrecoverable Machine check");
> -
> -	return;
> -
> -bail:
> -	if (!nested)
> -		nmi_exit();
>   }
>   
>   void SMIException(struct pt_regs *regs)
> 


More information about the Linuxppc-dev mailing list