Skip to contentSkip to conversation

Preserve the VFP state across the fork() call

PATCH New Catalin Marinas 3 participants 5 messages Feb 14, 2011

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

cover Preserve the VFP state across the fork() call

The VFP state should be copied to the child process during the fork() system call. This is important because the d16-d31 registers are callee saved and the compiler may use them for preserving data across function calls.

Catalin Marinas (2):
ARM: Introduce THREAD_NOTIFY_COPY for copy_thread() hooks
ARM: Preserve the VFP state during fork

 arch/arm/include/asm/thread_notify.h |    1 +
 arch/arm/kernel/process.c            |    2 ++
 arch/arm/vfp/vfpmodule.c             |   34 +++++++++++++++++++++++++++-------
 3 files changed, 30 insertions(+), 7 deletions(-)
Signature · 1 line
Catalin
#1 lore raw

PATCH 1/2 ARM: Introduce THREAD_NOTIFY_COPY for copy_thread() hooks

This patch adds THREAD_NOTIFY_COPY for colling registered handlers during the copy_thread() function call. It also changes the VFP handler to use a switch statement rather than if..else and ignore this event.

---
 arch/arm/include/asm/thread_notify.h |    1 +
 arch/arm/kernel/process.c            |    2 ++
 arch/arm/vfp/vfpmodule.c             |   22 +++++++++++++++-------
 3 files changed, 18 insertions(+), 7 deletions(-)
arch/arm/include/asm/thread_notify.h +1 -0
index c4391ba..1dc9806 100644
@@ -43,6 +43,7 @@ static inline void thread_notify(unsigned long rc, struct thread_info *thread)
 #define THREAD_NOTIFY_FLUSH	0
 #define THREAD_NOTIFY_EXIT	1
 #define THREAD_NOTIFY_SWITCH	2
+#define THREAD_NOTIFY_COPY	3
 
 #endif
 #endif
arch/arm/kernel/process.c +2 -0
index 94bbedb..5e1e541 100644
@@ -372,6 +372,8 @@ copy_thread(unsigned long clone_flags, unsigned long stack_start,
 	if (clone_flags & CLONE_SETTLS)
 		thread->tp_value = regs->ARM_r3;
 
+	thread_notify(THREAD_NOTIFY_COPY, thread);
+
 	return 0;
 }
 
arch/arm/vfp/vfpmodule.c +15 -7
index 0797cb5..5153135 100644
@@ -104,12 +104,17 @@ static void vfp_thread_exit(struct thread_info *thread)
 static int vfp_notifier(struct notifier_block *self, unsigned long cmd, void *v)
 {
 	struct thread_info *thread = v;
+	u32 fpexc;
+#ifdef CONFIG_SMP
+	unsigned int cpu;
+#endif
 
-	if (likely(cmd == THREAD_NOTIFY_SWITCH)) {
-		u32 fpexc = fmrx(FPEXC);
+	switch (cmd) {
+	case THREAD_NOTIFY_SWITCH:
+		fpexc = fmrx(FPEXC);
 
 #ifdef CONFIG_SMP
-		unsigned int cpu = thread->cpu;
+		cpu = thread->cpu;
 
 		/*
 		 * On SMP, if VFP is enabled, save the old state in
@@ -134,13 +139,16 @@ static int vfp_notifier(struct notifier_block *self, unsigned long cmd, void *v)
 		 * old state.
 		 */
 		fmxr(FPEXC, fpexc & ~FPEXC_EN);
-		return NOTIFY_DONE;
-	}
+		break;
 
-	if (cmd == THREAD_NOTIFY_FLUSH)
+	case THREAD_NOTIFY_FLUSH:
 		vfp_thread_flush(thread);
-	else
+		break;
+
+	case THREAD_NOTIFY_EXIT:
 		vfp_thread_exit(thread);
+		break;
+	}
 
 	return NOTIFY_DONE;
 }
#2 lore raw

PATCH 1/2 ARM: Introduce THREAD_NOTIFY_COPY for copy_thread() hooks

Hi Catalin,

Quoted 6 lines

Subject: [PATCH 1/2] ARM: Introduce THREAD_NOTIFY_COPY for copy_thread() hooks

This patch adds THREAD_NOTIFY_COPY for colling registered handlers during the copy_thread() function call. It also changes the VFP handler to use a switch statement rather than if..else and ignore this event.

Quoted 6 lines
---
 arch/arm/include/asm/thread_notify.h |    1 +
 arch/arm/kernel/process.c            |    2 ++
 arch/arm/vfp/vfpmodule.c             |   22 +++++++++++++++-------
 3 files changed, 18 insertions(+), 7 deletions(-)

This would be useful for the hw-breakpoint code, where we need to clear (memset 0) the breakpoint structures in the child so that they don't get unregistered later on.

However, we also need to flush (unregister) breakpoints in flush_thread so that they don't persist across an exec. Ideally, we'd have a single notifier block and act on THREAD_NOTIFY_{FLUSH,COPY} accordingly, but the problem is that THREAD_NOTIFY_FLUSH is only notified *after* zeroing most of the thread structure, so the call is currently inlined into flush_thread and we don't use a notifier.

This could be solved by either notifying the FLUSH before zeroing the various thread structures or by moving the zeroing of the debug struct into the hw-breakpoint notifier. The latter probably makes more sense once we've removed the single-step functionality from ptrace.

Will

#3 lore raw

PATCH 1/2 ARM: Introduce THREAD_NOTIFY_COPY for copy_thread() hooks

Quoted 19 lines · Will Deacon

Hi Catalin,

Quoted 6 lines

Subject: [PATCH 1/2] ARM: Introduce THREAD_NOTIFY_COPY for copy_thread() hooks

This patch adds THREAD_NOTIFY_COPY for colling registered handlers during the copy_thread() function call. It also changes the VFP handler to use a switch statement rather than if..else and ignore this event.

Quoted 6 lines
---
 arch/arm/include/asm/thread_notify.h |    1 +
 arch/arm/kernel/process.c            |    2 ++
 arch/arm/vfp/vfpmodule.c             |   22 +++++++++++++++-------
 3 files changed, 18 insertions(+), 7 deletions(-)

This would be useful for the hw-breakpoint code, where we need to clear (memset 0) the breakpoint structures in the child so that they don't get unregistered later on.

Quoted 6 lines

However, we also need to flush (unregister) breakpoints in flush_thread so that they don't persist across an exec. Ideally, we'd have a single notifier block and act on THREAD_NOTIFY_{FLUSH,COPY} accordingly, but the problem is that THREAD_NOTIFY_FLUSH is only notified *after* zeroing most of the thread structure, so the call is currently inlined into flush_thread and we don't use a notifier.

It's better to avoid the thread notifier if you don't need all the facilities it offers as it gets called for every thread switch. Every additional registration will add additional cycles to the thread switch.

#4 lore raw

PATCH 2/2 ARM: Preserve the VFP state during fork

In reply to Catalin Marinas

VFP registers d16-d31 are callee saved registers and must be preserved during function calls, including fork(). The VFP configuration should also be preserved. The patch copies the full VFP state to the child process.

---
 arch/arm/vfp/vfpmodule.c |   12 ++++++++++++
 1 files changed, 12 insertions(+), 0 deletions(-)
arch/arm/vfp/vfpmodule.c +12 -0
index 5153135..cb7a88c 100644
@@ -78,6 +78,14 @@ static void vfp_thread_exit(struct thread_info *thread)
 	put_cpu();
 }
 
+static void vfp_thread_copy(struct thread_info *thread)
+{
+	struct thread_info *parent = current_thread_info();
+
+	vfp_sync_hwstate(parent);
+	thread->vfpstate = parent->vfpstate;
+}
+
 /*
  * When this function is called with the following 'cmd's, the following
  * is true while this function is being run:
@@ -148,6 +156,10 @@ static int vfp_notifier(struct notifier_block *self, unsigned long cmd, void *v)
 	case THREAD_NOTIFY_EXIT:
 		vfp_thread_exit(thread);
 		break;
+
+	case THREAD_NOTIFY_COPY:
+		vfp_thread_copy(thread);
+		break;
 	}
 
 	return NOTIFY_DONE;