summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Blanchard <anton@samba.org>2012-09-03 16:48:46 +0000
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-09-14 10:00:22 -0700
commit59d0622a07571c6344f0e3c71e7a1a71eb8db9e9 (patch)
treeb7e27ef692a8a19da9d42d60cd4301394fc8c3bb
parent652f43702b224351b790fd9182744d7946d4cdf6 (diff)
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: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-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 d4cbbd1fa75f..8302af649219 100644
--- a/arch/powerpc/kernel/sysfs.c
+++ b/arch/powerpc/kernel/sysfs.c
@@ -196,8 +196,10 @@ static ssize_t show_dscr_default(struct device *dev,
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 device *dev,
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 158972341a2d..ae0843fa7a61 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -972,8 +972,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