diff mbox series

[07/17] arm64: entry: convert error entry to C

Message ID 20200108185634.1163-8-mark.rutland@arm.com (mailing list archive)
State New, archived
Headers show
Series arm64: entry deasmification and cleanup | expand

Commit Message

Mark Rutland Jan. 8, 2020, 6:56 p.m. UTC
Portions of our error entry logic are handled in C while other parts are
handled in assembly. Let's migrate the bulk of it to C so that it's
easier to follow and maintain.

Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: James Morse <james.morse@arm.com>
Cc: Will Deacon <will@kernel.org>
---
 arch/arm64/include/asm/exception.h |  1 +
 arch/arm64/kernel/entry-common.c   | 26 ++++++++++++++++++++++++++
 arch/arm64/kernel/entry.S          | 19 ++++++-------------
 arch/arm64/kernel/traps.c          |  2 +-
 4 files changed, 34 insertions(+), 14 deletions(-)

Comments

Anshuman Khandual Jan. 9, 2020, 9:12 a.m. UTC | #1
On 01/09/2020 12:26 AM, Mark Rutland wrote:
> Portions of our error entry logic are handled in C while other parts are
> handled in assembly. Let's migrate the bulk of it to C so that it's
> easier to follow and maintain.
> 
> Signed-off-by: Mark Rutland <mark.rutland@arm.com>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: James Morse <james.morse@arm.com>
> Cc: Will Deacon <will@kernel.org>
> ---
>  arch/arm64/include/asm/exception.h |  1 +
>  arch/arm64/kernel/entry-common.c   | 26 ++++++++++++++++++++++++++
>  arch/arm64/kernel/entry.S          | 19 ++++++-------------
>  arch/arm64/kernel/traps.c          |  2 +-
>  4 files changed, 34 insertions(+), 14 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/exception.h b/arch/arm64/include/asm/exception.h
> index a49038fa4faf..220a7c3971d8 100644
> --- a/arch/arm64/include/asm/exception.h
> +++ b/arch/arm64/include/asm/exception.h
> @@ -51,5 +51,6 @@ void do_el0_svc(struct pt_regs *regs);
>  void do_el0_svc_compat(struct pt_regs *regs);
>  void do_el0_ia_bp_hardening(unsigned long addr,  unsigned int esr,
>  			    struct pt_regs *regs);
> +void do_serror(struct pt_regs *regs, unsigned int esr);
>  
>  #endif	/* __ASM_EXCEPTION_H */
> diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
> index 45155d9f72da..bf9d497e620c 100644
> --- a/arch/arm64/kernel/entry-common.c
> +++ b/arch/arm64/kernel/entry-common.c
> @@ -442,3 +442,29 @@ asmlinkage void notrace el0_irq_handler(struct pt_regs *regs)
>  	trace_hardirqs_on();
>  }
>  NOKPROBE_SYMBOL(el0_irq_handler);
> +
> +asmlinkage void el1_error_handler(struct pt_regs *regs)
> +{
> +	unsigned long esr = read_sysreg(esr_el1);
> +
> +	if (system_uses_irq_prio_masking())
> +		gic_write_pmr(GIC_PRIO_IRQON | GIC_PRIO_PSR_I_SET);
> +
> +	local_daif_restore(DAIF_ERRCTX);
> +	do_serror(regs, esr);
> +}
> +NOKPROBE_SYMBOL(el1_error_handler);
> +
> +asmlinkage void el0_error_handler(struct pt_regs *regs)
> +{
> +	unsigned long esr = read_sysreg(esr_el1);
> +
> +	if (system_uses_irq_prio_masking())
> +		gic_write_pmr(GIC_PRIO_IRQON | GIC_PRIO_PSR_I_SET);
> +
> +	user_exit_irqoff();
> +	local_daif_restore(DAIF_ERRCTX);

Just being curious. local_daif_restore(DAIF_ERRCTX) has the same
effect as enable_dbg asm macro previously ?


> +	do_serror(regs, esr);
> +	local_daif_restore(DAIF_PROCCTX_NOIRQ);
> +}
> +NOKPROBE_SYMBOL(el0_error_handler);
> diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
> index 55c4be1e996a..0c5117ef7c3c 100644
> --- a/arch/arm64/kernel/entry.S
> +++ b/arch/arm64/kernel/entry.S
> @@ -559,7 +559,10 @@ ENDPROC(el0_irq_compat)
>  
>  el0_error_compat:
>  	kernel_entry 0, 32
> -	b	el0_error_naked
> +	mov	x0, sp
> +	bl	el0_error_handler
> +	b	ret_to_user
> +ENDPROC(el0_error_compat)
>  #endif
>  
>  	.align	6
> @@ -572,25 +575,15 @@ ENDPROC(el0_irq)
>  
>  el1_error:
>  	kernel_entry 1
> -	mrs	x1, esr_el1
> -	gic_prio_kentry_setup tmp=x2
> -	enable_dbg
>  	mov	x0, sp
> -	bl	do_serror
> +	bl	el1_error_handler
>  	kernel_exit 1
>  ENDPROC(el1_error)
>  
>  el0_error:
>  	kernel_entry 0
> -el0_error_naked:
> -	mrs	x25, esr_el1
> -	gic_prio_kentry_setup tmp=x2
> -	ct_user_exit_irqoff
> -	enable_dbg
>  	mov	x0, sp
> -	mov	x1, x25
> -	bl	do_serror
> -	enable_da_f
> +	bl	el0_error_handler
>  	b	ret_to_user
>  ENDPROC(el0_error)

Macros enable_da_f and ct_user_exit_irqoff can be removed here itself
although it is eventually getting dropped off in a later patch.

>  
> diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
> index 73caf35c2262..170e637bb87b 100644
> --- a/arch/arm64/kernel/traps.c
> +++ b/arch/arm64/kernel/traps.c
> @@ -901,7 +901,7 @@ bool arm64_is_fatal_ras_serror(struct pt_regs *regs, unsigned int esr)
>  	}
>  }
>  
> -asmlinkage void do_serror(struct pt_regs *regs, unsigned int esr)
> +void do_serror(struct pt_regs *regs, unsigned int esr)
>  {
>  	const bool was_in_nmi = in_nmi();
>  
> 

Should not we add NOKPROBE_SYMBOL() for the symbol.
Mark Rutland Jan. 9, 2020, 12:49 p.m. UTC | #2
On Thu, Jan 09, 2020 at 02:42:23PM +0530, Anshuman Khandual wrote:
> 
> 
> On 01/09/2020 12:26 AM, Mark Rutland wrote:
> > Portions of our error entry logic are handled in C while other parts are
> > handled in assembly. Let's migrate the bulk of it to C so that it's
> > easier to follow and maintain.
> > 
> > Signed-off-by: Mark Rutland <mark.rutland@arm.com>
> > Cc: Catalin Marinas <catalin.marinas@arm.com>
> > Cc: James Morse <james.morse@arm.com>
> > Cc: Will Deacon <will@kernel.org>
> > ---
> >  arch/arm64/include/asm/exception.h |  1 +
> >  arch/arm64/kernel/entry-common.c   | 26 ++++++++++++++++++++++++++
> >  arch/arm64/kernel/entry.S          | 19 ++++++-------------
> >  arch/arm64/kernel/traps.c          |  2 +-
> >  4 files changed, 34 insertions(+), 14 deletions(-)
> > 
> > diff --git a/arch/arm64/include/asm/exception.h b/arch/arm64/include/asm/exception.h
> > index a49038fa4faf..220a7c3971d8 100644
> > --- a/arch/arm64/include/asm/exception.h
> > +++ b/arch/arm64/include/asm/exception.h
> > @@ -51,5 +51,6 @@ void do_el0_svc(struct pt_regs *regs);
> >  void do_el0_svc_compat(struct pt_regs *regs);
> >  void do_el0_ia_bp_hardening(unsigned long addr,  unsigned int esr,
> >  			    struct pt_regs *regs);
> > +void do_serror(struct pt_regs *regs, unsigned int esr);
> >  
> >  #endif	/* __ASM_EXCEPTION_H */
> > diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
> > index 45155d9f72da..bf9d497e620c 100644
> > --- a/arch/arm64/kernel/entry-common.c
> > +++ b/arch/arm64/kernel/entry-common.c
> > @@ -442,3 +442,29 @@ asmlinkage void notrace el0_irq_handler(struct pt_regs *regs)
> >  	trace_hardirqs_on();
> >  }
> >  NOKPROBE_SYMBOL(el0_irq_handler);
> > +
> > +asmlinkage void el1_error_handler(struct pt_regs *regs)
> > +{
> > +	unsigned long esr = read_sysreg(esr_el1);
> > +
> > +	if (system_uses_irq_prio_masking())
> > +		gic_write_pmr(GIC_PRIO_IRQON | GIC_PRIO_PSR_I_SET);
> > +
> > +	local_daif_restore(DAIF_ERRCTX);
> > +	do_serror(regs, esr);
> > +}
> > +NOKPROBE_SYMBOL(el1_error_handler);
> > +
> > +asmlinkage void el0_error_handler(struct pt_regs *regs)
> > +{
> > +	unsigned long esr = read_sysreg(esr_el1);
> > +
> > +	if (system_uses_irq_prio_masking())
> > +		gic_write_pmr(GIC_PRIO_IRQON | GIC_PRIO_PSR_I_SET);
> > +
> > +	user_exit_irqoff();
> > +	local_daif_restore(DAIF_ERRCTX);
> 
> Just being curious. local_daif_restore(DAIF_ERRCTX) has the same
> effect as enable_dbg asm macro previously ?

Not quite, DAIF_ERRCTX unmasks debug and FIQ, but I beleive that was an
oversight when we tightened up the DAIF nesting rules bask in commit:

  65be7a1b799f11ff ("arm64: introduce an order for exceptions")

... where the commit message says:

| FIQ is never expected, but we mask it when we mask debug exceptions,
| and unmask it at all other times.

I'll call that out explicitly in the commit message.

> > +	do_serror(regs, esr);
> > +	local_daif_restore(DAIF_PROCCTX_NOIRQ);
> > +}
> > +NOKPROBE_SYMBOL(el0_error_handler);
> > diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
> > index 55c4be1e996a..0c5117ef7c3c 100644
> > --- a/arch/arm64/kernel/entry.S
> > +++ b/arch/arm64/kernel/entry.S
> > @@ -559,7 +559,10 @@ ENDPROC(el0_irq_compat)
> >  
> >  el0_error_compat:
> >  	kernel_entry 0, 32
> > -	b	el0_error_naked
> > +	mov	x0, sp
> > +	bl	el0_error_handler
> > +	b	ret_to_user
> > +ENDPROC(el0_error_compat)
> >  #endif
> >  
> >  	.align	6
> > @@ -572,25 +575,15 @@ ENDPROC(el0_irq)
> >  
> >  el1_error:
> >  	kernel_entry 1
> > -	mrs	x1, esr_el1
> > -	gic_prio_kentry_setup tmp=x2
> > -	enable_dbg
> >  	mov	x0, sp
> > -	bl	do_serror
> > +	bl	el1_error_handler
> >  	kernel_exit 1
> >  ENDPROC(el1_error)
> >  
> >  el0_error:
> >  	kernel_entry 0
> > -el0_error_naked:
> > -	mrs	x25, esr_el1
> > -	gic_prio_kentry_setup tmp=x2
> > -	ct_user_exit_irqoff
> > -	enable_dbg
> >  	mov	x0, sp
> > -	mov	x1, x25
> > -	bl	do_serror
> > -	enable_da_f
> > +	bl	el0_error_handler
> >  	b	ret_to_user
> >  ENDPROC(el0_error)
> 
> Macros enable_da_f and ct_user_exit_irqoff can be removed here itself
> although it is eventually getting dropped off in a later patch.

True. I'll fold those removals here.

I'll prepend a patch to remove inherit_daif, too.

> > diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
> > index 73caf35c2262..170e637bb87b 100644
> > --- a/arch/arm64/kernel/traps.c
> > +++ b/arch/arm64/kernel/traps.c
> > @@ -901,7 +901,7 @@ bool arm64_is_fatal_ras_serror(struct pt_regs *regs, unsigned int esr)
> >  	}
> >  }
> >  
> > -asmlinkage void do_serror(struct pt_regs *regs, unsigned int esr)
> > +void do_serror(struct pt_regs *regs, unsigned int esr)
> >  {
> >  	const bool was_in_nmi = in_nmi();
> >  
> > 
> 
> Should not we add NOKPROBE_SYMBOL() for the symbol.

At this point we've already sampled the exception registers and balanced
the IRQ flags, so we don't need to do so for the sames reasons as for
functions in entry-common.c.

If that needs to change, I think that should be a separate patch, as
nothing has changed from the PoV of do_serror() other than asmlinkage.

Thanks,
Mark.
diff mbox series

Patch

diff --git a/arch/arm64/include/asm/exception.h b/arch/arm64/include/asm/exception.h
index a49038fa4faf..220a7c3971d8 100644
--- a/arch/arm64/include/asm/exception.h
+++ b/arch/arm64/include/asm/exception.h
@@ -51,5 +51,6 @@  void do_el0_svc(struct pt_regs *regs);
 void do_el0_svc_compat(struct pt_regs *regs);
 void do_el0_ia_bp_hardening(unsigned long addr,  unsigned int esr,
 			    struct pt_regs *regs);
+void do_serror(struct pt_regs *regs, unsigned int esr);
 
 #endif	/* __ASM_EXCEPTION_H */
diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
index 45155d9f72da..bf9d497e620c 100644
--- a/arch/arm64/kernel/entry-common.c
+++ b/arch/arm64/kernel/entry-common.c
@@ -442,3 +442,29 @@  asmlinkage void notrace el0_irq_handler(struct pt_regs *regs)
 	trace_hardirqs_on();
 }
 NOKPROBE_SYMBOL(el0_irq_handler);
+
+asmlinkage void el1_error_handler(struct pt_regs *regs)
+{
+	unsigned long esr = read_sysreg(esr_el1);
+
+	if (system_uses_irq_prio_masking())
+		gic_write_pmr(GIC_PRIO_IRQON | GIC_PRIO_PSR_I_SET);
+
+	local_daif_restore(DAIF_ERRCTX);
+	do_serror(regs, esr);
+}
+NOKPROBE_SYMBOL(el1_error_handler);
+
+asmlinkage void el0_error_handler(struct pt_regs *regs)
+{
+	unsigned long esr = read_sysreg(esr_el1);
+
+	if (system_uses_irq_prio_masking())
+		gic_write_pmr(GIC_PRIO_IRQON | GIC_PRIO_PSR_I_SET);
+
+	user_exit_irqoff();
+	local_daif_restore(DAIF_ERRCTX);
+	do_serror(regs, esr);
+	local_daif_restore(DAIF_PROCCTX_NOIRQ);
+}
+NOKPROBE_SYMBOL(el0_error_handler);
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index 55c4be1e996a..0c5117ef7c3c 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -559,7 +559,10 @@  ENDPROC(el0_irq_compat)
 
 el0_error_compat:
 	kernel_entry 0, 32
-	b	el0_error_naked
+	mov	x0, sp
+	bl	el0_error_handler
+	b	ret_to_user
+ENDPROC(el0_error_compat)
 #endif
 
 	.align	6
@@ -572,25 +575,15 @@  ENDPROC(el0_irq)
 
 el1_error:
 	kernel_entry 1
-	mrs	x1, esr_el1
-	gic_prio_kentry_setup tmp=x2
-	enable_dbg
 	mov	x0, sp
-	bl	do_serror
+	bl	el1_error_handler
 	kernel_exit 1
 ENDPROC(el1_error)
 
 el0_error:
 	kernel_entry 0
-el0_error_naked:
-	mrs	x25, esr_el1
-	gic_prio_kentry_setup tmp=x2
-	ct_user_exit_irqoff
-	enable_dbg
 	mov	x0, sp
-	mov	x1, x25
-	bl	do_serror
-	enable_da_f
+	bl	el0_error_handler
 	b	ret_to_user
 ENDPROC(el0_error)
 
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index 73caf35c2262..170e637bb87b 100644
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -901,7 +901,7 @@  bool arm64_is_fatal_ras_serror(struct pt_regs *regs, unsigned int esr)
 	}
 }
 
-asmlinkage void do_serror(struct pt_regs *regs, unsigned int esr)
+void do_serror(struct pt_regs *regs, unsigned int esr)
 {
 	const bool was_in_nmi = in_nmi();