From patchwork Thu May 19 13:59:38 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dave Martin X-Patchwork-Id: 1540 Return-Path: Delivered-To: unknown Received: from imap.gmail.com (74.125.159.109) by localhost6.localdomain6 with IMAP4-SSL; 08 Jun 2011 14:52:51 -0000 Delivered-To: patches@linaro.org Received: by 10.224.54.134 with SMTP id q6cs115855qag; Thu, 19 May 2011 06:59:51 -0700 (PDT) Received: by 10.227.207.144 with SMTP id fy16mr3236268wbb.46.1305813590024; Thu, 19 May 2011 06:59:50 -0700 (PDT) Received: from mail-wy0-f178.google.com (mail-wy0-f178.google.com [74.125.82.178]) by mx.google.com with ESMTPS id u45si5247848weo.43.2011.05.19.06.59.49 (version=TLSv1/SSLv3 cipher=OTHER); Thu, 19 May 2011 06:59:50 -0700 (PDT) Received-SPF: neutral (google.com: 74.125.82.178 is neither permitted nor denied by best guess record for domain of dave.martin@linaro.org) client-ip=74.125.82.178; Authentication-Results: mx.google.com; spf=neutral (google.com: 74.125.82.178 is neither permitted nor denied by best guess record for domain of dave.martin@linaro.org) smtp.mail=dave.martin@linaro.org Received: by wyb33 with SMTP id 33so2426945wyb.37 for ; Thu, 19 May 2011 06:59:49 -0700 (PDT) Received: by 10.216.144.166 with SMTP id n38mr5789792wej.75.1305813588801; Thu, 19 May 2011 06:59:48 -0700 (PDT) Received: from e200948.peterhouse.linaro.org (fw-lnat.cambridge.arm.com [217.140.96.63]) by mx.google.com with ESMTPS id s20sm1636668wbh.57.2011.05.19.06.59.46 (version=SSLv3 cipher=OTHER); Thu, 19 May 2011 06:59:47 -0700 (PDT) From: Dave Martin To: linux-arm-kernel@lists.infradead.org Cc: patches@linaro.org, Russell King - ARM Linux , Nicolas Pitre , Vadim Bendebury Subject: [PATCH v2] ARM: fiq: Refactor {get,set}_fiq_regs() for Thumb-2 Date: Thu, 19 May 2011 14:59:38 +0100 Message-Id: <1305813578-8113-1-git-send-email-dave.martin@linaro.org> X-Mailer: git-send-email 1.7.4.1 * 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. Tested on omap4 using explicit calls to get_fiq_regs() and set_fiq_regs(). Signed-off-by: Dave Martin Reviewed-by: Nicolas Pitre --- If anyone else feels able to test/ack this patch, it would be much appreciated. 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..207f9d6 --- /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 , 1998. + * + * FIQ support re-written by Russell King to be more generic + * + * v7/Thumb-2 compatibility modifications by Linaro Limited, 2011. + */ + +#include +#include + +/* + * 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)