diff mbox

[RFC] ARM: fiq: Refactor {get,set}_fiq_regs() for Thumb-2

Message ID 1302085787-15069-1-git-send-email-dave.martin@linaro.org
State Accepted
Headers show

Commit Message

Dave Martin April 6, 2011, 10:29 a.m. UTC
* To remove the risk of inconvenient register allocation decisions
   by the compiler, these functions are separated out as pure
   assembler.

 * The apcs frame manipulation code is not applicable for Thumb-2
   (and also not easily compatible).  Since it's not essential to
   have a full frame on these leaf assembler functions, the frame
   manipulation is removed, in the interests of simplicity.

 * Split up ldm/stm instructions to be compatible with Thumb-2,
   as well as avoiding instruction forms deprecated on >= ARMv7.

Signed-off-by: Dave Martin <dave.martin@linaro.org>
---

 arch/arm/include/asm/fiq.h |   16 ++++++++++++-
 arch/arm/kernel/Makefile   |    2 +-
 arch/arm/kernel/fiq.c      |   45 +--------------------------------------
 arch/arm/kernel/fiqasm.S   |   49 ++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 66 insertions(+), 46 deletions(-)
 create mode 100644 arch/arm/kernel/fiqasm.S

Comments

Dave Martin April 6, 2011, 10:55 a.m. UTC | #1
On Wed, Apr 6, 2011 at 11:29 AM, Dave Martin <dave.martin@linaro.org> wrote:
>  * To remove the risk of inconvenient register allocation decisions
>   by the compiler, these functions are separated out as pure
>   assembler.
>
>  * The apcs frame manipulation code is not applicable for Thumb-2
>   (and also not easily compatible).  Since it's not essential to
>   have a full frame on these leaf assembler functions, the frame
>   manipulation is removed, in the interests of simplicity.
>
>  * Split up ldm/stm instructions to be compatible with Thumb-2,
>   as well as avoiding instruction forms deprecated on >= ARMv7.
>
> Signed-off-by: Dave Martin <dave.martin@linaro.org>
> ---
>
>  arch/arm/include/asm/fiq.h |   16 ++++++++++++-
>  arch/arm/kernel/Makefile   |    2 +-
>  arch/arm/kernel/fiq.c      |   45 +--------------------------------------
>  arch/arm/kernel/fiqasm.S   |   49 ++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 66 insertions(+), 46 deletions(-)
>  create mode 100644 arch/arm/kernel/fiqasm.S
>
> diff --git a/arch/arm/include/asm/fiq.h b/arch/arm/include/asm/fiq.h
> index 2242ce2..45bb3ee 100644
> --- a/arch/arm/include/asm/fiq.h
> +++ b/arch/arm/include/asm/fiq.h
> @@ -29,9 +29,21 @@ struct fiq_handler {
>  extern int claim_fiq(struct fiq_handler *f);
>  extern void release_fiq(struct fiq_handler *f);
>  extern void set_fiq_handler(void *start, unsigned int length);
> -extern void set_fiq_regs(struct pt_regs *regs);
> -extern void get_fiq_regs(struct pt_regs *regs);
>  extern void enable_fiq(int fiq);
>  extern void disable_fiq(int fiq);
>
> +/* helpers defined in fiqasm.S: */
> +extern void __set_fiq_regs(unsigned long const *regs);
> +extern void __get_fiq_regs(unsigned long *regs);
> +
> +static inline void set_fiq_regs(struct pt_regs const *regs)
> +{
> +       __set_fiq_regs(&regs->ARM_r8);
> +}
> +
> +static inline void get_fiq_regs(struct pt_regs *regs)
> +{
> +       __get_fiq_regs(&regs->ARM_r8);
> +}
> +
>  #endif
> diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
> index 74554f1..689f4d9 100644
> --- a/arch/arm/kernel/Makefile
> +++ b/arch/arm/kernel/Makefile
> @@ -24,7 +24,7 @@ obj-$(CONFIG_OC_ETM)          += etm.o
>
>  obj-$(CONFIG_ISA_DMA_API)      += dma.o
>  obj-$(CONFIG_ARCH_ACORN)       += ecard.o
> -obj-$(CONFIG_FIQ)              += fiq.o
> +obj-$(CONFIG_FIQ)              += fiq.o fiqasm.o
>  obj-$(CONFIG_MODULES)          += armksyms.o module.o
>  obj-$(CONFIG_ARTHUR)           += arthur.o
>  obj-$(CONFIG_ISA_DMA)          += dma-isa.o
> diff --git a/arch/arm/kernel/fiq.c b/arch/arm/kernel/fiq.c
> index e72dc34..4c164ec 100644
> --- a/arch/arm/kernel/fiq.c
> +++ b/arch/arm/kernel/fiq.c
> @@ -89,47 +89,6 @@ void set_fiq_handler(void *start, unsigned int length)
>                flush_icache_range(0x1c, 0x1c + length);
>  }
>
> -/*
> - * Taking an interrupt in FIQ mode is death, so both these functions
> - * disable irqs for the duration.  Note - these functions are almost
> - * entirely coded in assembly.
> - */
> -void __naked set_fiq_regs(struct pt_regs *regs)
> -{
> -       register unsigned long tmp;
> -       asm volatile (
> -       "mov    ip, sp\n\
> -       stmfd   sp!, {fp, ip, lr, pc}\n\
> -       sub     fp, ip, #4\n\
> -       mrs     %0, cpsr\n\
> -       msr     cpsr_c, %2      @ select FIQ mode\n\
> -       mov     r0, r0\n\
> -       ldmia   %1, {r8 - r14}\n\
> -       msr     cpsr_c, %0      @ return to SVC mode\n\
> -       mov     r0, r0\n\
> -       ldmfd   sp, {fp, sp, pc}"
> -       : "=&r" (tmp)
> -       : "r" (&regs->ARM_r8), "I" (PSR_I_BIT | PSR_F_BIT | FIQ_MODE));
> -}
> -
> -void __naked get_fiq_regs(struct pt_regs *regs)
> -{
> -       register unsigned long tmp;
> -       asm volatile (
> -       "mov    ip, sp\n\
> -       stmfd   sp!, {fp, ip, lr, pc}\n\
> -       sub     fp, ip, #4\n\
> -       mrs     %0, cpsr\n\
> -       msr     cpsr_c, %2      @ select FIQ mode\n\
> -       mov     r0, r0\n\
> -       stmia   %1, {r8 - r14}\n\
> -       msr     cpsr_c, %0      @ return to SVC mode\n\
> -       mov     r0, r0\n\
> -       ldmfd   sp, {fp, sp, pc}"
> -       : "=&r" (tmp)
> -       : "r" (&regs->ARM_r8), "I" (PSR_I_BIT | PSR_F_BIT | FIQ_MODE));
> -}
> -
>  int claim_fiq(struct fiq_handler *f)
>  {
>        int ret = 0;
> @@ -174,8 +133,8 @@ void disable_fiq(int fiq)
>  }
>
>  EXPORT_SYMBOL(set_fiq_handler);
> -EXPORT_SYMBOL(set_fiq_regs);
> -EXPORT_SYMBOL(get_fiq_regs);
> +EXPORT_SYMBOL(__set_fiq_regs); /* defined in fiqasm.S */
> +EXPORT_SYMBOL(__get_fiq_regs); /* defined in fiqasm.S */
>  EXPORT_SYMBOL(claim_fiq);
>  EXPORT_SYMBOL(release_fiq);
>  EXPORT_SYMBOL(enable_fiq);
> diff --git a/arch/arm/kernel/fiqasm.S b/arch/arm/kernel/fiqasm.S
> new file mode 100644
> index 0000000..0504bb8
> --- /dev/null
> +++ b/arch/arm/kernel/fiqasm.S
> @@ -0,0 +1,49 @@
> +/*
> + *  linux/arch/arm/kernel/fiqasm.S
> + *
> + *  Derived from code originally in linux/arch/arm/kernel/fiq.c:
> + *
> + *  Copyright (C) 1998 Russell King
> + *  Copyright (C) 1998, 1999 Phil Blundell
> + *  Copyright (C) 2011, Linaro Limited
> + *
> + *  FIQ support written by Philip Blundell <philb@gnu.org>, 1998.
> + *
> + *  FIQ support re-written by Russell King to be more generic
> + *
> + *  v7/Thumb-2 compatibility modifications by Linaro Limited, 2011.
> + */
> +
> +#include <arm/assembler.h>
> +
> +/*
> + * Taking an interrupt in FIQ mode is death, so both these functions
> + * disable irqs for the duration.  Note - these functions are almost
> + * entirely coded in assembly.
> + */
> +
> +ENTRY(__set_fiq_regs)
> +       mov     r2, #PSR_I_BIT | PSR_F_BIT | FIQ_MODE
> +       mrs     r1, cpsr
> +       msr     cpsr_c, r2      @ select FIQ mode
> +       mov     r0, r0          @ avoid hazard prior to ARMv4
> +       ldmia   r0!, {r8 - r12}
> +       ldr     sp, [r0], #4
> +       ldr     lr, [r0]
> +       msr     cpsr_c, r1      @ return to SVC mode
> +       mov     r0, r0          @ avoid hazard prior to ARMv4
> +       mov     pc, lr
> +ENDPROC(__set_fiq_regs)
> +
> +ENTRY(__get_fiq_regs)
> +       mov     r2, #PSR_I_BIT | PSR_F_BIT | FIQ_MODE
> +       mrs     r1, cpsr
> +       msr     cpsr_c, r2      @ select FIQ mode
> +       mov     r0, r0          @ avoid hazard prior to ARMv4
> +       stmia   r0!, {r8 - r12}
> +       str     sp, [r0], #4
> +       str     lr, [r0]
> +       msr     cpsr_c, r1      @ return to SVC mode
> +       mov     r0, r0          @ avoid hazard prior to ARMv4
> +       mov     pc, lr
> +ENDPROC(__get_fiq_regs)
> --
> 1.7.1
>
>

Note -- this patch contains some minor errors, but I'm more interested
in feedback on the general idea for now.

Cheers
---Dave
Nicolas Pitre April 6, 2011, 5:37 p.m. UTC | #2
On Wed, 6 Apr 2011, Dave Martin wrote:

>  * To remove the risk of inconvenient register allocation decisions
>    by the compiler, these functions are separated out as pure
>    assembler.
> 
>  * The apcs frame manipulation code is not applicable for Thumb-2
>    (and also not easily compatible).  Since it's not essential to
>    have a full frame on these leaf assembler functions, the frame
>    manipulation is removed, in the interests of simplicity.
> 
>  * Split up ldm/stm instructions to be compatible with Thumb-2,
>    as well as avoiding instruction forms deprecated on >= ARMv7.
> 
> Signed-off-by: Dave Martin <dave.martin@linaro.org>

I like.  Minor nit:

> +/*
> + * Taking an interrupt in FIQ mode is death, so both these functions
> + * disable irqs for the duration.  Note - these functions are almost
> + * entirely coded in assembly.
> + */

I think it is obvious the last sentence may go, especially since 
"almost" is not exactly true anymore.

Other than that:

Reviewed-by: Nicolas Pitre <nicolas.pitre@linaro.org>


Nicolas
Dave Martin April 7, 2011, 9:36 a.m. UTC | #3
On Wed, Apr 6, 2011 at 6:37 PM, Nicolas Pitre <nicolas.pitre@linaro.org> wrote:
> On Wed, 6 Apr 2011, Dave Martin wrote:
>
>>  * To remove the risk of inconvenient register allocation decisions
>>    by the compiler, these functions are separated out as pure
>>    assembler.
>>
>>  * The apcs frame manipulation code is not applicable for Thumb-2
>>    (and also not easily compatible).  Since it's not essential to
>>    have a full frame on these leaf assembler functions, the frame
>>    manipulation is removed, in the interests of simplicity.
>>
>>  * Split up ldm/stm instructions to be compatible with Thumb-2,
>>    as well as avoiding instruction forms deprecated on >= ARMv7.
>>
>> Signed-off-by: Dave Martin <dave.martin@linaro.org>
>
> I like.  Minor nit:
>
>> +/*
>> + * Taking an interrupt in FIQ mode is death, so both these functions
>> + * disable irqs for the duration.  Note - these functions are almost
>> + * entirely coded in assembly.
>> + */
>
> I think it is obvious the last sentence may go, especially since
> "almost" is not exactly true anymore.

Actually, my local fixes tidied that away too... I'll repost, since
there are other errors too...

>
> Other than that:
>
> Reviewed-by: Nicolas Pitre <nicolas.pitre@linaro.org>

Thanks

---Dave
diff mbox

Patch

diff --git a/arch/arm/include/asm/fiq.h b/arch/arm/include/asm/fiq.h
index 2242ce2..45bb3ee 100644
--- a/arch/arm/include/asm/fiq.h
+++ b/arch/arm/include/asm/fiq.h
@@ -29,9 +29,21 @@  struct fiq_handler {
 extern int claim_fiq(struct fiq_handler *f);
 extern void release_fiq(struct fiq_handler *f);
 extern void set_fiq_handler(void *start, unsigned int length);
-extern void set_fiq_regs(struct pt_regs *regs);
-extern void get_fiq_regs(struct pt_regs *regs);
 extern void enable_fiq(int fiq);
 extern void disable_fiq(int fiq);
 
+/* helpers defined in fiqasm.S: */
+extern void __set_fiq_regs(unsigned long const *regs);
+extern void __get_fiq_regs(unsigned long *regs);
+
+static inline void set_fiq_regs(struct pt_regs const *regs)
+{
+	__set_fiq_regs(&regs->ARM_r8);
+}
+
+static inline void get_fiq_regs(struct pt_regs *regs)
+{
+	__get_fiq_regs(&regs->ARM_r8);
+}
+
 #endif
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 74554f1..689f4d9 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -24,7 +24,7 @@  obj-$(CONFIG_OC_ETM)		+= etm.o
 
 obj-$(CONFIG_ISA_DMA_API)	+= dma.o
 obj-$(CONFIG_ARCH_ACORN)	+= ecard.o 
-obj-$(CONFIG_FIQ)		+= fiq.o
+obj-$(CONFIG_FIQ)		+= fiq.o fiqasm.o
 obj-$(CONFIG_MODULES)		+= armksyms.o module.o
 obj-$(CONFIG_ARTHUR)		+= arthur.o
 obj-$(CONFIG_ISA_DMA)		+= dma-isa.o
diff --git a/arch/arm/kernel/fiq.c b/arch/arm/kernel/fiq.c
index e72dc34..4c164ec 100644
--- a/arch/arm/kernel/fiq.c
+++ b/arch/arm/kernel/fiq.c
@@ -89,47 +89,6 @@  void set_fiq_handler(void *start, unsigned int length)
 		flush_icache_range(0x1c, 0x1c + length);
 }
 
-/*
- * Taking an interrupt in FIQ mode is death, so both these functions
- * disable irqs for the duration.  Note - these functions are almost
- * entirely coded in assembly.
- */
-void __naked set_fiq_regs(struct pt_regs *regs)
-{
-	register unsigned long tmp;
-	asm volatile (
-	"mov	ip, sp\n\
-	stmfd	sp!, {fp, ip, lr, pc}\n\
-	sub	fp, ip, #4\n\
-	mrs	%0, cpsr\n\
-	msr	cpsr_c, %2	@ select FIQ mode\n\
-	mov	r0, r0\n\
-	ldmia	%1, {r8 - r14}\n\
-	msr	cpsr_c, %0	@ return to SVC mode\n\
-	mov	r0, r0\n\
-	ldmfd	sp, {fp, sp, pc}"
-	: "=&r" (tmp)
-	: "r" (&regs->ARM_r8), "I" (PSR_I_BIT | PSR_F_BIT | FIQ_MODE));
-}
-
-void __naked get_fiq_regs(struct pt_regs *regs)
-{
-	register unsigned long tmp;
-	asm volatile (
-	"mov	ip, sp\n\
-	stmfd	sp!, {fp, ip, lr, pc}\n\
-	sub	fp, ip, #4\n\
-	mrs	%0, cpsr\n\
-	msr	cpsr_c, %2	@ select FIQ mode\n\
-	mov	r0, r0\n\
-	stmia	%1, {r8 - r14}\n\
-	msr	cpsr_c, %0	@ return to SVC mode\n\
-	mov	r0, r0\n\
-	ldmfd	sp, {fp, sp, pc}"
-	: "=&r" (tmp)
-	: "r" (&regs->ARM_r8), "I" (PSR_I_BIT | PSR_F_BIT | FIQ_MODE));
-}
-
 int claim_fiq(struct fiq_handler *f)
 {
 	int ret = 0;
@@ -174,8 +133,8 @@  void disable_fiq(int fiq)
 }
 
 EXPORT_SYMBOL(set_fiq_handler);
-EXPORT_SYMBOL(set_fiq_regs);
-EXPORT_SYMBOL(get_fiq_regs);
+EXPORT_SYMBOL(__set_fiq_regs);	/* defined in fiqasm.S */
+EXPORT_SYMBOL(__get_fiq_regs);	/* defined in fiqasm.S */
 EXPORT_SYMBOL(claim_fiq);
 EXPORT_SYMBOL(release_fiq);
 EXPORT_SYMBOL(enable_fiq);
diff --git a/arch/arm/kernel/fiqasm.S b/arch/arm/kernel/fiqasm.S
new file mode 100644
index 0000000..0504bb8
--- /dev/null
+++ b/arch/arm/kernel/fiqasm.S
@@ -0,0 +1,49 @@ 
+/*
+ *  linux/arch/arm/kernel/fiqasm.S
+ *
+ *  Derived from code originally in linux/arch/arm/kernel/fiq.c:
+ *
+ *  Copyright (C) 1998 Russell King
+ *  Copyright (C) 1998, 1999 Phil Blundell
+ *  Copyright (C) 2011, Linaro Limited
+ *
+ *  FIQ support written by Philip Blundell <philb@gnu.org>, 1998.
+ *
+ *  FIQ support re-written by Russell King to be more generic
+ *
+ *  v7/Thumb-2 compatibility modifications by Linaro Limited, 2011.
+ */
+	
+#include <arm/assembler.h>
+
+/*
+ * Taking an interrupt in FIQ mode is death, so both these functions
+ * disable irqs for the duration.  Note - these functions are almost
+ * entirely coded in assembly.
+ */
+
+ENTRY(__set_fiq_regs)
+	mov	r2, #PSR_I_BIT | PSR_F_BIT | FIQ_MODE
+	mrs	r1, cpsr
+	msr	cpsr_c, r2	@ select FIQ mode
+	mov	r0, r0		@ avoid hazard prior to ARMv4
+	ldmia	r0!, {r8 - r12}
+	ldr	sp, [r0], #4
+	ldr	lr, [r0]
+	msr	cpsr_c, r1	@ return to SVC mode
+	mov	r0, r0		@ avoid hazard prior to ARMv4
+	mov	pc, lr
+ENDPROC(__set_fiq_regs)
+
+ENTRY(__get_fiq_regs)
+	mov	r2, #PSR_I_BIT | PSR_F_BIT | FIQ_MODE
+	mrs	r1, cpsr
+	msr	cpsr_c, r2	@ select FIQ mode
+	mov	r0, r0		@ avoid hazard prior to ARMv4
+	stmia	r0!, {r8 - r12}
+	str	sp, [r0], #4
+	str	lr, [r0]
+	msr	cpsr_c, r1	@ return to SVC mode
+	mov	r0, r0		@ avoid hazard prior to ARMv4
+	mov	pc, lr
+ENDPROC(__get_fiq_regs)