powerpc/64: Optimise set/clear of CTRL[RUN] (runlatch)
authorNicholas Piggin <npiggin@gmail.com>
Fri, 11 Aug 2017 16:39:07 +0000 (02:39 +1000)
committerMichael Ellerman <mpe@ellerman.id.au>
Wed, 23 Aug 2017 13:48:38 +0000 (23:48 +1000)
On modern CPUs the CTRL register is read-only except bit 63 which is
the run latch control. This means it can be updated with a mtspr
rather than mfspr/mtspr.

To accomodate older CPUs (Cell at least), where there are other bits
in the register, we still do a read/modify/write on pre 2.06 CPUs.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
[mpe: Update change log to mention 2.06 workaround]
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
arch/powerpc/kernel/process.c

index 34bd94b090e2b8142d59822b7b1308d5c8aa38e7..0a00d59df53747745ea7c63de3560b291a1105a4 100644 (file)
@@ -1979,11 +1979,25 @@ void show_stack(struct task_struct *tsk, unsigned long *stack)
 void notrace __ppc64_runlatch_on(void)
 {
        struct thread_info *ti = current_thread_info();
-       unsigned long ctrl;
 
-       ctrl = mfspr(SPRN_CTRLF);
-       ctrl |= CTRL_RUNLATCH;
-       mtspr(SPRN_CTRLT, ctrl);
+       if (cpu_has_feature(CPU_FTR_ARCH_206)) {
+               /*
+                * Least significant bit (RUN) is the only writable bit of
+                * the CTRL register, so we can avoid mfspr. 2.06 is not the
+                * earliest ISA where this is the case, but it's convenient.
+                */
+               mtspr(SPRN_CTRLT, CTRL_RUNLATCH);
+       } else {
+               unsigned long ctrl;
+
+               /*
+                * Some architectures (e.g., Cell) have writable fields other
+                * than RUN, so do the read-modify-write.
+                */
+               ctrl = mfspr(SPRN_CTRLF);
+               ctrl |= CTRL_RUNLATCH;
+               mtspr(SPRN_CTRLT, ctrl);
+       }
 
        ti->local_flags |= _TLF_RUNLATCH;
 }
@@ -1992,13 +2006,18 @@ void notrace __ppc64_runlatch_on(void)
 void notrace __ppc64_runlatch_off(void)
 {
        struct thread_info *ti = current_thread_info();
-       unsigned long ctrl;
 
        ti->local_flags &= ~_TLF_RUNLATCH;
 
-       ctrl = mfspr(SPRN_CTRLF);
-       ctrl &= ~CTRL_RUNLATCH;
-       mtspr(SPRN_CTRLT, ctrl);
+       if (cpu_has_feature(CPU_FTR_ARCH_206)) {
+               mtspr(SPRN_CTRLT, 0);
+       } else {
+               unsigned long ctrl;
+
+               ctrl = mfspr(SPRN_CTRLF);
+               ctrl &= ~CTRL_RUNLATCH;
+               mtspr(SPRN_CTRLT, ctrl);
+       }
 }
 #endif /* CONFIG_PPC64 */