All of lore.kernel.org
 help / color / mirror / Atom feed
From: u.kleine-koenig@pengutronix.de (Uwe Kleine-König)
To: linux-arm-kernel@lists.infradead.org
Subject: [RFC PATCH 10/11] Cortex-M3: Add VFP support
Date: Sun, 22 Jan 2012 12:13:36 +0100	[thread overview]
Message-ID: <1327230817-12855-10-git-send-email-u.kleine-koenig@pengutronix.de> (raw)
In-Reply-To: <20120122111230.GB14835@pengutronix.de>

From: Catalin Marinas <catalin.marinas@arm.com>

This patch adds support for the ARMv7-M VFP extension. It uses the lazy
state preservation mechanism available in hardware for the S0-S15
registers. The S16-S32 registers are saved at a context switch if the
thread being scheduled out ever used the VFP. Similarly, the S16-S31
registers are restored if the thread being scheduled in ever used the
VFP.

Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
---
 arch/arm/Kconfig               |    7 +++
 arch/arm/include/asm/fpstate.h |    3 +
 arch/arm/kernel/Makefile       |    2 +
 arch/arm/kernel/asm-offsets.c  |    3 +
 arch/arm/kernel/entry-header.S |   14 ++++++
 arch/arm/kernel/vfp-m.c        |  102 ++++++++++++++++++++++++++++++++++++++++
 6 files changed, 131 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/kernel/vfp-m.c

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index ca9b48c..c5caeee 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -2227,6 +2227,13 @@ config NEON
 	  Say Y to include support code for NEON, the ARMv7 Advanced SIMD
 	  Extension.
 
+config VFPM
+	bool "ARMv7-M VFP Extension support"
+	depends on CPU_V7M
+	help
+	  Say Y to include support for the ARMv7-M VFP Extension
+	  (single-precision floating point hardware).
+
 endmenu
 
 menu "Userspace binary formats"
diff --git a/arch/arm/include/asm/fpstate.h b/arch/arm/include/asm/fpstate.h
index 3ad4c10..e18c3d9 100644
--- a/arch/arm/include/asm/fpstate.h
+++ b/arch/arm/include/asm/fpstate.h
@@ -43,6 +43,9 @@ struct vfp_hard_struct {
 #ifdef CONFIG_SMP
 	__u32 cpu;
 #endif
+#ifdef CONFIG_VFPM
+	__u32 clean;
+#endif
 };
 
 union vfp_state {
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 32e96e6..66d6c92 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -81,6 +81,8 @@ obj-$(CONFIG_HW_PERF_EVENTS)	+= perf_event.o
 AFLAGS_iwmmxt.o			:= -Wa,-mcpu=iwmmxt
 obj-$(CONFIG_ARM_CPU_TOPOLOGY)  += topology.o
 
+obj-$(CONFIG_VFPM)		+= vfp-m.o
+
 ifneq ($(CONFIG_ARCH_EBSA110),y)
   obj-y		+= io.o
 endif
diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
index e861849..10ec416 100644
--- a/arch/arm/kernel/asm-offsets.c
+++ b/arch/arm/kernel/asm-offsets.c
@@ -60,6 +60,9 @@ int main(void)
   DEFINE(TI_TP_VALUE,		offsetof(struct thread_info, tp_value));
   DEFINE(TI_FPSTATE,		offsetof(struct thread_info, fpstate));
   DEFINE(TI_VFPSTATE,		offsetof(struct thread_info, vfpstate));
+#ifdef CONFIG_VFPM
+  DEFINE(TI_VFPSTATE_CLEAN,	offsetof(struct thread_info, vfpstate.hard.clean));
+#endif
 #ifdef CONFIG_SMP
   DEFINE(VFP_CPU,		offsetof(union vfp_state, hard.cpu));
 #endif
diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S
index 8050d9b..cb38aff 100644
--- a/arch/arm/kernel/entry-header.S
+++ b/arch/arm/kernel/entry-header.S
@@ -72,7 +72,15 @@
  */
 	.macro	v7m_exception_entry
 	cpsid	i
+#ifdef CONFIG_VFPM
+	get_thread_info r0
+	and	r1, lr, #1 << 4		@ VFP clean state
+	str	r1, [r0, #TI_VFPSTATE_CLEAN]
+#endif
 	cmp	lr, #0xfffffffd		@ check the return stack
+#ifdef CONFIG_VFPM
+	cmpne	lr, #0xffffffed
+#endif
 	beq	1f			@ exception on process stack
 	add	r12, sp, #32		@ MSP before exception
 	stmdb	sp!, {r4-r12, lr}	@ push unsaved registers
@@ -90,6 +98,9 @@
 	.macro	v7m_exception_fast_exit
 	ldmia	sp!, {r4-r12, lr}	@ restore previously saved state
 	cmp	lr, #0xfffffffd		@ check the return stack
+#ifdef CONFIG_VFPM
+	cmpne	lr, #0xffffffed
+#endif
 	addeq	sp, #32			@ returning to PSP, just restore MSP
 	cpsie	i
 	bx	lr
@@ -99,6 +110,9 @@
 	cpsid	i
 	ldr	lr, [sp, #S_EXC_LR]	@ read exception LR
 	cmp	lr, #0xfffffffd		@ check the return stack
+#ifdef CONFIG_VFPM
+	cmpne	lr, #0xffffffed
+#endif
 	beq	1f			@ returning to PSP
 	@ Prepare the MSP stack
 	ldmia	sp, {r4-r11}		@ restore previously saved state
diff --git a/arch/arm/kernel/vfp-m.c b/arch/arm/kernel/vfp-m.c
new file mode 100644
index 0000000..0528189
--- /dev/null
+++ b/arch/arm/kernel/vfp-m.c
@@ -0,0 +1,102 @@
+/*
+ * arch/arm/kernel/vfp-m.c
+ *
+ * Copyright (C) 2010 ARM Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/string.h>
+
+#include <asm/thread_notify.h>
+
+static union vfp_state *last_vfp_context;
+
+static void save_vfp_context(union vfp_state *vfp)
+{
+	/* vstmia %0!, {d8-d15} */
+	asm("	stc	p11, cr8, [%0], #16*4\n" : : "r" (vfp) : "cc");
+}
+
+static void load_vfp_context(union vfp_state *vfp)
+{
+	/* vldmia %0!, {d8-d15} */
+	asm("	ldc	p11, cr8, [%0], #16*4\n" : : "r" (vfp) : "cc");
+}
+
+static int vfpm_notifier(struct notifier_block *self, unsigned long cmd,
+			 void *t)
+{
+	struct thread_info *thread = t;
+	union vfp_state *vfp = &thread->vfpstate;
+	union vfp_state *old_vfp = &current_thread_info()->vfpstate;
+	u32 *fpccr = (u32 *)0xe000ef34;
+
+	switch (cmd) {
+	case THREAD_NOTIFY_FLUSH:
+		memset(vfp, 0, sizeof(*vfp));
+		vfp->hard.clean = 1;
+		/* fall through */
+
+	case THREAD_NOTIFY_EXIT:
+		if (last_vfp_context == vfp) {
+			/* disable lazy state saving */
+			*fpccr &= ~1;
+			last_vfp_context = NULL;
+		}
+		break;
+
+	case THREAD_NOTIFY_SWITCH:
+		if (!old_vfp->hard.clean) {
+			save_vfp_context(last_vfp_context);
+			last_vfp_context = old_vfp;
+		}
+		if (!vfp->hard.clean && last_vfp_context != vfp) {
+			load_vfp_context(vfp);
+			last_vfp_context = vfp;
+		}
+		break;
+	}
+
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block vfpm_notifier_block = {
+	.notifier_call	= vfpm_notifier,
+};
+
+static int __init vfpm_init(void)
+{
+	u32 *cpacr = (u32 *)0xe000ed88;
+	u32 *mvfr0 = (u32 *)0xe000ef40;
+	u32 *fpccr = (u32 *)0xe000ef34;
+
+	/* check for single-precision VFP operations */
+	if ((*mvfr0 & 0xf0) != 0x20)
+		return 0;
+
+	printk(KERN_INFO "ARMv7-M VFP Extension supported\n");
+
+	*cpacr |= 0xf << 20;		/* coprocessor access */
+	*fpccr |= 3 << 30;		/* automatic lazy state preservation */
+
+	elf_hwcap |= HWCAP_VFP;
+	thread_register_notifier(&vfpm_notifier_block);
+
+	return 0;
+}
+
+late_initcall(vfpm_init);
-- 
1.7.8.3

  parent reply	other threads:[~2012-01-22 11:13 UTC|newest]

Thread overview: 40+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-01-22 11:12 [RFC PATCH 00/11] Cortex-M3 support Uwe Kleine-König
2012-01-22 11:13 ` [RFC PATCH 01/11] ARM: only show modules in the memory layout for MODULES=y Uwe Kleine-König
2012-01-26  6:16   ` Linus Walleij
2012-01-22 11:13 ` [RFC PATCH 02/11] ARM: add device tree blobs to .gitignore Uwe Kleine-König
2012-01-22 11:13 ` [RFC PATCH 03/11] ARM: protect usage of cr_alignment by #ifdef CONFIG_CPU_CP15 Uwe Kleine-König
2012-01-23  5:43   ` Jean-Christophe PLAGNIOL-VILLARD
2012-01-23  8:14     ` Uwe Kleine-König
2012-01-22 11:13 ` [RFC PATCH 04/11] ARM: Add a printk loglevel modifier Uwe Kleine-König
2012-01-23  5:50   ` Jean-Christophe PLAGNIOL-VILLARD
2012-01-22 11:13 ` [RFC PATCH 05/11] ARM: provide XIP_VIRT_ADDR for no-MMU builds Uwe Kleine-König
2012-01-22 11:13 ` [RFC PATCH 06/11] Cortex-M3: Add base support for Cortex-M3 Uwe Kleine-König
2012-01-22 19:45   ` Michał Mirosław
2012-01-22 20:42     ` Uwe Kleine-König
2012-01-22 11:13 ` [RFC PATCH 07/11] Cortex-M3: Add support for exception handling Uwe Kleine-König
2012-01-22 11:13 ` [RFC PATCH 08/11] Cortex-M3: Add NVIC support Uwe Kleine-König
2012-01-31 19:39   ` Uwe Kleine-König
2012-01-22 11:13 ` [RFC PATCH 09/11] Cortex-M3: Allow the building of Cortex-M3 kernel port Uwe Kleine-König
2012-01-22 20:05   ` Michał Mirosław
2012-02-07 19:43     ` Uwe Kleine-König
2012-01-22 11:13 ` Uwe Kleine-König [this message]
2012-01-22 11:13 ` [RFC PATCH 11/11] HACK! ARM: no, we don't enter in ARM Uwe Kleine-König
2012-02-07 20:18 ` [RFC PATCH 00/11] Cortex-M3 support Uwe Kleine-König
2012-02-16 20:01   ` Uwe Kleine-König
2012-02-16 20:18     ` [PATCH 1/5] ARM: protect usage of cr_alignment by #ifdef CONFIG_CPU_CP15 Uwe Kleine-König
2012-02-16 20:18       ` [PATCH 2/5] ARM: Add a printk loglevel modifier Uwe Kleine-König
2012-02-16 20:18       ` [PATCH 3/5] ARM: force branch instructions to use long distance encoding Uwe Kleine-König
2012-02-16 20:18       ` [PATCH 4/5] ARM: Cortex-M3: Add base support for Cortex-M3 Uwe Kleine-König
2012-02-16 20:18       ` [PATCH 5/5] ARM: Cortex-M3: Add support for exception handling Uwe Kleine-König
2012-02-16 22:20         ` Russell King - ARM Linux
2012-02-24 22:01           ` Uwe Kleine-König
2012-02-24 22:12             ` Catalin Marinas
2012-02-24 22:43               ` Russell King - ARM Linux
2012-02-25  8:49                 ` Catalin Marinas
2012-02-25 14:07               ` Uwe Kleine-König
2012-03-05 17:04               ` [PATCH v2 4/5] Cortex-M3: Add base support for Cortex-M3 Uwe Kleine-König
2012-03-05 17:04                 ` [PATCH v2 5/5] Cortex-M3: Add support for exception handling Uwe Kleine-König
2012-03-09 17:10                   ` Catalin Marinas
2012-03-13 20:39                     ` Uwe Kleine-König
2012-03-08 10:52                 ` [PATCH v2 4/5] Cortex-M3: Add base support for Cortex-M3 Catalin Marinas
2012-02-17  0:28       ` [PATCH 1/5] ARM: protect usage of cr_alignment by #ifdef CONFIG_CPU_CP15 Ryan Mallon

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1327230817-12855-10-git-send-email-u.kleine-koenig@pengutronix.de \
    --to=u.kleine-koenig@pengutronix.de \
    --cc=linux-arm-kernel@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.