Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+14 −2
Original line number Diff line number Diff line
@@ -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
+1 −1
Original line number Diff line number Diff line
@@ -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
+2 −43
Original line number Diff line number Diff line
@@ -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);
+49 −0
Original line number Diff line number Diff line
/*
 *  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)