[RFC PATCH] ARM: fiq: Refactor {get,set}_fiq_regs() for Thumb-2
Dave Martin
dave.martin at linaro.org
Wed Apr 6 06:55:26 EDT 2011
On Wed, Apr 6, 2011 at 11:29 AM, Dave Martin <dave.martin at 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 at 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(®s->ARM_r8);
> +}
> +
> +static inline void get_fiq_regs(struct pt_regs *regs)
> +{
> + __get_fiq_regs(®s->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" (®s->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" (®s->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 at 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
More information about the linux-arm-kernel
mailing list