Commit 5f31a641 authored by Anton Blanchard's avatar Anton Blanchard Committed by Ben Hutchings

powerpc: Keep thread.dscr and thread.dscr_inherit in sync

commit 00ca0de0 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.cSigned-off-by: default avatarAnton Blanchard <anton@samba.org>
Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: default avatarBen Hutchings <ben@decadent.org.uk>
parent b32fef3b
......@@ -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,
......
......@@ -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
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment