diff mbox series

[v6,21/24] arm64: Handle serror in NMI context

Message ID 1542023835-21446-22-git-send-email-julien.thierry@arm.com (mailing list archive)
State New, archived
Headers show
Series arm64: provide pseudo NMI with GICv3 | expand

Commit Message

Julien Thierry Nov. 12, 2018, 11:57 a.m. UTC
Per definition of the daifflags, Serrors can occur during any interrupt
context, that includes NMI contexts. Trying to nmi_enter in an nmi context
will crash.

Skip nmi_enter/nmi_exit when serror occurred during an NMI.

Suggested-by: James Morse <james.morse@arm.com>
Signed-off-by: Julien Thierry <julien.thierry@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Dave Martin <dave.martin@arm.com>
Cc: James Morse <james.morse@arm.com>
---
 arch/arm64/kernel/traps.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

Comments

Catalin Marinas Dec. 4, 2018, 6:09 p.m. UTC | #1
On Mon, Nov 12, 2018 at 11:57:12AM +0000, Julien Thierry wrote:
> diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
> index 5f4d9ac..66344cd 100644
> --- a/arch/arm64/kernel/traps.c
> +++ b/arch/arm64/kernel/traps.c
> @@ -897,13 +897,17 @@ bool arm64_is_fatal_ras_serror(struct pt_regs *regs, unsigned int esr)
>  
>  asmlinkage void do_serror(struct pt_regs *regs, unsigned int esr)
>  {
> -	nmi_enter();
> +	const bool was_in_nmi = in_nmi();
> +
> +	if (!was_in_nmi)
> +		nmi_enter();
>  
>  	/* non-RAS errors are not containable */
>  	if (!arm64_is_ras_serror(esr) || arm64_is_fatal_ras_serror(regs, esr))
>  		arm64_serror_panic(regs, esr);
>  
> -	nmi_exit();
> +	if (!was_in_nmi)
> +		nmi_exit();
>  }

Do we actually need nmi_enter/exit in the outer do_serror() function?
Could we just move it to arm64_serror_panic()?
James Morse Dec. 5, 2018, 1:02 p.m. UTC | #2
Hi Catalin,

On 04/12/2018 18:09, Catalin Marinas wrote:
> On Mon, Nov 12, 2018 at 11:57:12AM +0000, Julien Thierry wrote:
>> diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
>> index 5f4d9ac..66344cd 100644
>> --- a/arch/arm64/kernel/traps.c
>> +++ b/arch/arm64/kernel/traps.c
>> @@ -897,13 +897,17 @@ bool arm64_is_fatal_ras_serror(struct pt_regs *regs, unsigned int esr)
>>  
>>  asmlinkage void do_serror(struct pt_regs *regs, unsigned int esr)
>>  {
>> -	nmi_enter();
>> +	const bool was_in_nmi = in_nmi();
>> +
>> +	if (!was_in_nmi)
>> +		nmi_enter();
>>  
>>  	/* non-RAS errors are not containable */
>>  	if (!arm64_is_ras_serror(esr) || arm64_is_fatal_ras_serror(regs, esr))
>>  		arm64_serror_panic(regs, esr);
>>  
>> -	nmi_exit();
>> +	if (!was_in_nmi)
>> +		nmi_exit();
>>  }
> 
> Do we actually need nmi_enter/exit in the outer do_serror() function?
> Could we just move it to arm64_serror_panic()?

They might need to be here in the future: if we support kernel-first we would
have extra calls in here that need to be in_nmi(), the same if we call out to
APEI to support APCI's NOTIFY_SEI.


Thanks,

James
diff mbox series

Patch

diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index 5f4d9ac..66344cd 100644
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -897,13 +897,17 @@  bool arm64_is_fatal_ras_serror(struct pt_regs *regs, unsigned int esr)
 
 asmlinkage void do_serror(struct pt_regs *regs, unsigned int esr)
 {
-	nmi_enter();
+	const bool was_in_nmi = in_nmi();
+
+	if (!was_in_nmi)
+		nmi_enter();
 
 	/* non-RAS errors are not containable */
 	if (!arm64_is_ras_serror(esr) || arm64_is_fatal_ras_serror(regs, esr))
 		arm64_serror_panic(regs, esr);
 
-	nmi_exit();
+	if (!was_in_nmi)
+		nmi_exit();
 }
 
 void __pte_error(const char *file, int line, unsigned long val)