Commit dc2eb928 authored by Dave Martin's avatar Dave Martin Committed by Russell King

ARM: 6938/1: fiq: Refactor {get,set}_fiq_regs() for Thumb-2

 * 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: default avatarDave Martin <dave.martin@linaro.org>
Reviewed-by: default avatarNicolas Pitre <nicolas.pitre@linaro.org>
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent 4db70f73
...@@ -29,9 +29,21 @@ struct fiq_handler { ...@@ -29,9 +29,21 @@ struct fiq_handler {
extern int claim_fiq(struct fiq_handler *f); extern int claim_fiq(struct fiq_handler *f);
extern void release_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_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 enable_fiq(int fiq);
extern void disable_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 #endif
...@@ -24,7 +24,7 @@ obj-$(CONFIG_OC_ETM) += etm.o ...@@ -24,7 +24,7 @@ obj-$(CONFIG_OC_ETM) += etm.o
obj-$(CONFIG_ISA_DMA_API) += dma.o obj-$(CONFIG_ISA_DMA_API) += dma.o
obj-$(CONFIG_ARCH_ACORN) += ecard.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_MODULES) += armksyms.o module.o
obj-$(CONFIG_ARTHUR) += arthur.o obj-$(CONFIG_ARTHUR) += arthur.o
obj-$(CONFIG_ISA_DMA) += dma-isa.o obj-$(CONFIG_ISA_DMA) += dma-isa.o
......
...@@ -89,47 +89,6 @@ void set_fiq_handler(void *start, unsigned int length) ...@@ -89,47 +89,6 @@ void set_fiq_handler(void *start, unsigned int length)
flush_icache_range(0x1c, 0x1c + 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 claim_fiq(struct fiq_handler *f)
{ {
int ret = 0; int ret = 0;
...@@ -174,8 +133,8 @@ void disable_fiq(int fiq) ...@@ -174,8 +133,8 @@ void disable_fiq(int fiq)
} }
EXPORT_SYMBOL(set_fiq_handler); EXPORT_SYMBOL(set_fiq_handler);
EXPORT_SYMBOL(set_fiq_regs); EXPORT_SYMBOL(__set_fiq_regs); /* defined in fiqasm.S */
EXPORT_SYMBOL(get_fiq_regs); EXPORT_SYMBOL(__get_fiq_regs); /* defined in fiqasm.S */
EXPORT_SYMBOL(claim_fiq); EXPORT_SYMBOL(claim_fiq);
EXPORT_SYMBOL(release_fiq); EXPORT_SYMBOL(release_fiq);
EXPORT_SYMBOL(enable_fiq); EXPORT_SYMBOL(enable_fiq);
......
/*
* 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 <linux/linkage.h>
#include <asm/assembler.h>
/*
* Taking an interrupt in FIQ mode is death, so both these functions
* disable irqs for the duration.
*/
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)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment