summaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel
diff options
context:
space:
mode:
authorAnton Blanchard <anton@samba.org>2012-09-03 16:48:46 +0000
committerBen Hutchings <ben@decadent.org.uk>2012-09-19 15:04:41 +0100
commit5f31a641ff0e76081cf4ae1f72799cd59c20baea (patch)
tree15924f534cdd7048822cb1e798642b656bd37846 /arch/powerpc/kernel
parentb32fef3b4df0e254fb4d0fd3122a2668a5f11581 (diff)
downloadlinux-stable-5f31a641ff0e76081cf4ae1f72799cd59c20baea.tar.gz
linux-stable-5f31a641ff0e76081cf4ae1f72799cd59c20baea.tar.bz2
linux-stable-5f31a641ff0e76081cf4ae1f72799cd59c20baea.zip
powerpc: Keep thread.dscr and thread.dscr_inherit in sync
commit 00ca0de02f80924dfff6b4f630e1dff3db005e35 upstream. When we update the DSCR either via emulation of mtspr(DSCR) or via a change to dscr_default in sysfs we don't update thread.dscr. We will eventually update it at context switch time but there is a period where thread.dscr is incorrect. If we fork at this point we will copy the old value of thread.dscr into the child. To avoid this, always keep thread.dscr in sync with reality. This issue was found with the following testcase: http://ozlabs.org/~anton/junkcode/dscr_inherit_test.c Signed-off-by: Anton Blanchard <anton@samba.org> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Diffstat (limited to 'arch/powerpc/kernel')
-rw-r--r--arch/powerpc/kernel/sysfs.c4
-rw-r--r--arch/powerpc/kernel/traps.c3
2 files changed, 5 insertions, 2 deletions
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c
index 0c3f94919574..55be64db0ae0 100644
--- a/arch/powerpc/kernel/sysfs.c
+++ b/arch/powerpc/kernel/sysfs.c
@@ -194,8 +194,10 @@ static ssize_t show_dscr_default(struct sysdev_class *class,
static void update_dscr(void *dummy)
{
- if (!current->thread.dscr_inherit)
+ if (!current->thread.dscr_inherit) {
+ current->thread.dscr = dscr_default;
mtspr(SPRN_DSCR, dscr_default);
+ }
}
static ssize_t __used store_dscr_default(struct sysdev_class *class,
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 5459d148a0f6..82dcd4d8b4eb 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -942,8 +942,9 @@ static int emulate_instruction(struct pt_regs *regs)
cpu_has_feature(CPU_FTR_DSCR)) {
PPC_WARN_EMULATED(mtdscr, regs);
rd = (instword >> 21) & 0x1f;
- mtspr(SPRN_DSCR, regs->gpr[rd]);
+ current->thread.dscr = regs->gpr[rd];
current->thread.dscr_inherit = 1;
+ mtspr(SPRN_DSCR, current->thread.dscr);
return 0;
}
#endif