diff mbox

[v3,6/9] powerpc: Prepare for splitting giveup_{fpu, altivec, vsx} in two

Message ID 1453337749-15506-7-git-send-email-cyrilbur@gmail.com (mailing list archive)
State Changes Requested
Headers show

Commit Message

Cyril Bur Jan. 21, 2016, 12:55 a.m. UTC
This prepares for the decoupling of saving {fpu,altivec,vsx} registers and
marking {fpu,altivec,vsx} as being unused by a thread.

Currently giveup_{fpu,altivec,vsx}() does both however optimisations to
task switching can be made if these two operations are decoupled.
save_all() will permit the saving of registers to thread structs and leave
threads MSR with bits enabled.

This patch introduces no functional change.

Signed-off-by: Cyril Bur <cyrilbur@gmail.com>
---
 arch/powerpc/include/asm/switch_to.h |  7 +++++++
 arch/powerpc/kernel/process.c        | 39 +++++++++++++++++++++++++++++++++++-
 2 files changed, 45 insertions(+), 1 deletion(-)

Comments

Michael Ellerman Feb. 10, 2016, 7:51 a.m. UTC | #1
On Thu, 2016-21-01 at 00:55:46 UTC, Cyril Bur wrote:
> This prepares for the decoupling of saving {fpu,altivec,vsx} registers and
> marking {fpu,altivec,vsx} as being unused by a thread.
> 
> Currently giveup_{fpu,altivec,vsx}() does both however optimisations to
> task switching can be made if these two operations are decoupled.
> save_all() will permit the saving of registers to thread structs and leave
> threads MSR with bits enabled.
> 
> This patch introduces no functional change.

> diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
> index 0955b7c..45e37c0 100644
> --- a/arch/powerpc/kernel/process.c
> +++ b/arch/powerpc/kernel/process.c
> @@ -349,6 +349,14 @@ void flush_spe_to_thread(struct task_struct *tsk)
>  		preempt_enable();
>  	}
>  }
> +#else
> +/*
> + * save_all() is going to test MSR_SPE, rather than pull in all the
> + * booke definitions all the time on a books kernel just ensure it exists
> + * but acts as a nop.
> + */
> +
> +#define MSR_SPE 0
>  #endif /* CONFIG_SPE */


Building corenet32/64_defconfig this gives me:

  arch/powerpc/kernel/process.c:392:0: error: "MSR_SPE" redefined [-Werror]
   #define MSR_SPE 0
   ^
  In file included from ./arch/powerpc/include/asm/reg.h:18:0,
                   from ./arch/powerpc/include/asm/processor.h:13,
                   from ./arch/powerpc/include/asm/thread_info.h:33,
                   from include/linux/thread_info.h:54,
                   from include/asm-generic/preempt.h:4,
                   from arch/powerpc/include/generated/asm/preempt.h:1,
                   from include/linux/preempt.h:59,
                   from include/linux/spinlock.h:50,
                   from include/linux/seqlock.h:35,
                   from include/linux/time.h:5,
                   from include/uapi/linux/timex.h:56,
                   from include/linux/timex.h:56,
                   from include/linux/sched.h:19,
                   from arch/powerpc/kernel/process.c:18:
  ./arch/powerpc/include/asm/reg_booke.h:33:0: note: this is the location of the previous definition
   #define MSR_SPE  __MASK(MSR_SPE_LG)
   ^
  cc1: all warnings being treated as errors
  scripts/Makefile.build:258: recipe for target 'arch/powerpc/kernel/process.o' failed
  make[1]: *** [arch/powerpc/kernel/process.o] Error 1
  make[1]: *** Waiting for unfinished jobs....
  Makefile:950: recipe for target 'arch/powerpc/kernel' failed

cheers
diff mbox

Patch

diff --git a/arch/powerpc/include/asm/switch_to.h b/arch/powerpc/include/asm/switch_to.h
index 5b268b6..3690041 100644
--- a/arch/powerpc/include/asm/switch_to.h
+++ b/arch/powerpc/include/asm/switch_to.h
@@ -34,6 +34,7 @@  static inline void disable_kernel_fp(void)
 	msr_check_and_clear(MSR_FP);
 }
 #else
+static inline void __giveup_fpu(struct task_struct *t) { }
 static inline void flush_fp_to_thread(struct task_struct *t) { }
 #endif
 
@@ -46,6 +47,8 @@  static inline void disable_kernel_altivec(void)
 {
 	msr_check_and_clear(MSR_VEC);
 }
+#else
+static inline void __giveup_altivec(struct task_struct *t) { }
 #endif
 
 #ifdef CONFIG_VSX
@@ -57,6 +60,8 @@  static inline void disable_kernel_vsx(void)
 {
 	msr_check_and_clear(MSR_FP|MSR_VEC|MSR_VSX);
 }
+#else
+static inline void __giveup_vsx(struct task_struct *t) { }
 #endif
 
 #ifdef CONFIG_SPE
@@ -68,6 +73,8 @@  static inline void disable_kernel_spe(void)
 {
 	msr_check_and_clear(MSR_SPE);
 }
+#else
+static inline void __giveup_spe(struct task_struct *t) { }
 #endif
 
 static inline void clear_task_ebb(struct task_struct *t)
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 0955b7c..45e37c0 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -349,6 +349,14 @@  void flush_spe_to_thread(struct task_struct *tsk)
 		preempt_enable();
 	}
 }
+#else
+/*
+ * save_all() is going to test MSR_SPE, rather than pull in all the
+ * booke definitions all the time on a books kernel just ensure it exists
+ * but acts as a nop.
+ */
+
+#define MSR_SPE 0
 #endif /* CONFIG_SPE */
 
 static unsigned long msr_all_available;
@@ -440,12 +448,41 @@  void restore_math(struct pt_regs *regs)
 	regs->msr = msr;
 }
 
+void save_all(struct task_struct *tsk)
+{
+	unsigned long usermsr;
+
+	if (!tsk->thread.regs)
+		return;
+
+	usermsr = tsk->thread.regs->msr;
+
+	if ((usermsr & msr_all_available) == 0)
+		return;
+
+	msr_check_and_set(msr_all_available);
+
+	if (usermsr & MSR_FP)
+		__giveup_fpu(tsk);
+
+	if (usermsr & MSR_VEC)
+		__giveup_altivec(tsk);
+
+	if (usermsr & MSR_VSX)
+		__giveup_vsx(tsk);
+
+	if (usermsr & MSR_SPE)
+		__giveup_spe(tsk);
+
+	msr_check_and_clear(msr_all_available);
+}
+
 void flush_all_to_thread(struct task_struct *tsk)
 {
 	if (tsk->thread.regs) {
 		preempt_disable();
 		BUG_ON(tsk != current);
-		giveup_all(tsk);
+		save_all(tsk);
 
 #ifdef CONFIG_SPE
 		if (tsk->thread.regs->msr & MSR_SPE)