Commit 1901d8bb authored by Michael Ellerman's avatar Michael Ellerman

Merge tag 'powerpc-4.4-3' into next

Merge the two TM fixes we merged in 4.4. We are about to merge selftests
for these, and without the fixes the selftests will oops.

powerpc fixes for 4.4 #2

 - tm: Block signal return from setting invalid MSR state from Michael Neuling
 - tm: Check for already reclaimed tasks from Michael Neuling
parents 801c0b2c 7f821fc9
...@@ -108,6 +108,7 @@ ...@@ -108,6 +108,7 @@
#define MSR_TS_T __MASK(MSR_TS_T_LG) /* Transaction Transactional */ #define MSR_TS_T __MASK(MSR_TS_T_LG) /* Transaction Transactional */
#define MSR_TS_MASK (MSR_TS_T | MSR_TS_S) /* Transaction State bits */ #define MSR_TS_MASK (MSR_TS_T | MSR_TS_S) /* Transaction State bits */
#define MSR_TM_ACTIVE(x) (((x) & MSR_TS_MASK) != 0) /* Transaction active? */ #define MSR_TM_ACTIVE(x) (((x) & MSR_TS_MASK) != 0) /* Transaction active? */
#define MSR_TM_RESV(x) (((x) & MSR_TS_MASK) == MSR_TS_MASK) /* Reserved */
#define MSR_TM_TRANSACTIONAL(x) (((x) & MSR_TS_MASK) == MSR_TS_T) #define MSR_TM_TRANSACTIONAL(x) (((x) & MSR_TS_MASK) == MSR_TS_T)
#define MSR_TM_SUSPENDED(x) (((x) & MSR_TS_MASK) == MSR_TS_S) #define MSR_TM_SUSPENDED(x) (((x) & MSR_TS_MASK) == MSR_TS_S)
......
...@@ -640,6 +640,24 @@ static void tm_reclaim_thread(struct thread_struct *thr, ...@@ -640,6 +640,24 @@ static void tm_reclaim_thread(struct thread_struct *thr,
msr_diff &= MSR_FP | MSR_VEC | MSR_VSX | MSR_FE0 | MSR_FE1; msr_diff &= MSR_FP | MSR_VEC | MSR_VSX | MSR_FE0 | MSR_FE1;
} }
/*
* Use the current MSR TM suspended bit to track if we have
* checkpointed state outstanding.
* On signal delivery, we'd normally reclaim the checkpointed
* state to obtain stack pointer (see:get_tm_stackpointer()).
* This will then directly return to userspace without going
* through __switch_to(). However, if the stack frame is bad,
* we need to exit this thread which calls __switch_to() which
* will again attempt to reclaim the already saved tm state.
* Hence we need to check that we've not already reclaimed
* this state.
* We do this using the current MSR, rather tracking it in
* some specific thread_struct bit, as it has the additional
* benifit of checking for a potential TM bad thing exception.
*/
if (!MSR_TM_SUSPENDED(mfmsr()))
return;
tm_reclaim(thr, thr->regs->msr, cause); tm_reclaim(thr, thr->regs->msr, cause);
/* Having done the reclaim, we now have the checkpointed /* Having done the reclaim, we now have the checkpointed
......
...@@ -857,6 +857,15 @@ static long restore_tm_user_regs(struct pt_regs *regs, ...@@ -857,6 +857,15 @@ static long restore_tm_user_regs(struct pt_regs *regs,
return 1; return 1;
#endif /* CONFIG_SPE */ #endif /* CONFIG_SPE */
/* Get the top half of the MSR from the user context */
if (__get_user(msr_hi, &tm_sr->mc_gregs[PT_MSR]))
return 1;
msr_hi <<= 32;
/* If TM bits are set to the reserved value, it's an invalid context */
if (MSR_TM_RESV(msr_hi))
return 1;
/* Pull in the MSR TM bits from the user context */
regs->msr = (regs->msr & ~MSR_TS_MASK) | (msr_hi & MSR_TS_MASK);
/* Now, recheckpoint. This loads up all of the checkpointed (older) /* Now, recheckpoint. This loads up all of the checkpointed (older)
* registers, including FP and V[S]Rs. After recheckpointing, the * registers, including FP and V[S]Rs. After recheckpointing, the
* transactional versions should be loaded. * transactional versions should be loaded.
...@@ -866,11 +875,6 @@ static long restore_tm_user_regs(struct pt_regs *regs, ...@@ -866,11 +875,6 @@ static long restore_tm_user_regs(struct pt_regs *regs,
current->thread.tm_texasr |= TEXASR_FS; current->thread.tm_texasr |= TEXASR_FS;
/* This loads the checkpointed FP/VEC state, if used */ /* This loads the checkpointed FP/VEC state, if used */
tm_recheckpoint(&current->thread, msr); tm_recheckpoint(&current->thread, msr);
/* Get the top half of the MSR */
if (__get_user(msr_hi, &tm_sr->mc_gregs[PT_MSR]))
return 1;
/* Pull in MSR TM from user context */
regs->msr = (regs->msr & ~MSR_TS_MASK) | ((msr_hi<<32) & MSR_TS_MASK);
/* This loads the speculative FP/VEC state, if used */ /* This loads the speculative FP/VEC state, if used */
if (msr & MSR_FP) { if (msr & MSR_FP) {
......
...@@ -429,6 +429,10 @@ static long restore_tm_sigcontexts(struct pt_regs *regs, ...@@ -429,6 +429,10 @@ static long restore_tm_sigcontexts(struct pt_regs *regs,
/* get MSR separately, transfer the LE bit if doing signal return */ /* get MSR separately, transfer the LE bit if doing signal return */
err |= __get_user(msr, &sc->gp_regs[PT_MSR]); err |= __get_user(msr, &sc->gp_regs[PT_MSR]);
/* Don't allow reserved mode. */
if (MSR_TM_RESV(msr))
return -EINVAL;
/* pull in MSR TM from user context */ /* pull in MSR TM from user context */
regs->msr = (regs->msr & ~MSR_TS_MASK) | (msr & MSR_TS_MASK); regs->msr = (regs->msr & ~MSR_TS_MASK) | (msr & MSR_TS_MASK);
......
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