summaryrefslogtreecommitdiff
path: root/arch/powerpc
diff options
context:
space:
mode:
authorMichael Neuling <mikey@neuling.org>2016-06-09 05:31:08 +0300
committerMichael Ellerman <mpe@ellerman.id.au>2016-06-21 08:30:50 +0300
commitb57bd2de8c6c9aa03f1b899edd6f5582cc8b5b08 (patch)
treed1842bca1241f401b1ccc538e00d5f2dd9215df5 /arch/powerpc
parent103b7827d977ea34c982e6a9d2f960f731f7ee76 (diff)
downloadlinux-b57bd2de8c6c9aa03f1b899edd6f5582cc8b5b08.tar.xz
powerpc: Improve FSCR init and context switching
This fixes a few issues with FSCR init and switching. In commit 152d523e6307 ("powerpc: Create context switch helpers save_sprs() and restore_sprs()") we moved the setting of the FSCR register from inside an CPU_FTR_ARCH_207S section to inside just a CPU_FTR_ARCH_DSCR section. Hence we are setting FSCR on POWER6/7 where the FSCR doesn't exist. This is harmless but we shouldn't do it. Also, we can simplify the FSCR context switch. We don't need to go through the calculation involving dscr_inherit. We can just restore what we saved last time. We also set an initial value in INIT_THREAD, so that pid 1 which is cloned from that gets a sane value. Based on patch by Jack Miller. Signed-off-by: Michael Neuling <mikey@neuling.org> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/include/asm/processor.h1
-rw-r--r--arch/powerpc/kernel/process.c12
-rw-r--r--arch/powerpc/kernel/traps.c3
3 files changed, 7 insertions, 9 deletions
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
index c0c27bdbb069..f6b1a5f51d05 100644
--- a/arch/powerpc/include/asm/processor.h
+++ b/arch/powerpc/include/asm/processor.h
@@ -347,6 +347,7 @@ struct thread_struct {
.fs = KERNEL_DS, \
.fpexc_mode = 0, \
.ppr = INIT_PPR, \
+ .fscr = FSCR_TAR | FSCR_EBB \
}
#endif
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index c5c3ae2ef3c1..6d0a831bc7d8 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -1031,18 +1031,11 @@ static inline void restore_sprs(struct thread_struct *old_thread,
#ifdef CONFIG_PPC_BOOK3S_64
if (cpu_has_feature(CPU_FTR_DSCR)) {
u64 dscr = get_paca()->dscr_default;
- u64 fscr = old_thread->fscr & ~FSCR_DSCR;
-
- if (new_thread->dscr_inherit) {
+ if (new_thread->dscr_inherit)
dscr = new_thread->dscr;
- fscr |= FSCR_DSCR;
- }
if (old_thread->dscr != dscr)
mtspr(SPRN_DSCR, dscr);
-
- if (old_thread->fscr != fscr)
- mtspr(SPRN_FSCR, fscr);
}
if (cpu_has_feature(CPU_FTR_ARCH_207S)) {
@@ -1053,6 +1046,9 @@ static inline void restore_sprs(struct thread_struct *old_thread,
if (old_thread->ebbrr != new_thread->ebbrr)
mtspr(SPRN_EBBRR, new_thread->ebbrr);
+ if (old_thread->fscr != new_thread->fscr)
+ mtspr(SPRN_FSCR, new_thread->fscr);
+
if (old_thread->tar != new_thread->tar)
mtspr(SPRN_TAR, new_thread->tar);
}
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 11d15e7270e0..d2518c3cbf04 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -1419,7 +1419,8 @@ void facility_unavailable_exception(struct pt_regs *regs)
rd = (instword >> 21) & 0x1f;
current->thread.dscr = regs->gpr[rd];
current->thread.dscr_inherit = 1;
- mtspr(SPRN_FSCR, value | FSCR_DSCR);
+ current->thread.fscr |= FSCR_DSCR;
+ mtspr(SPRN_FSCR, current->thread.fscr);
}
/* Read from DSCR (mfspr RT, 0x03) */