Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'powerpc-4.4-3' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux

Pull powerpc fixes from Michael Ellerman:

- tm: Block signal return from setting invalid MSR state from Michael
Neuling

- tm: Check for already reclaimed tasks from Michael Neuling

* tag 'powerpc-4.4-3' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux:
powerpc/tm: Check for already reclaimed tasks
powerpc/tm: Block signal return setting invalid MSR state

+32 -5
+1
arch/powerpc/include/asm/reg.h
··· 108 108 #define MSR_TS_T __MASK(MSR_TS_T_LG) /* Transaction Transactional */ 109 109 #define MSR_TS_MASK (MSR_TS_T | MSR_TS_S) /* Transaction State bits */ 110 110 #define MSR_TM_ACTIVE(x) (((x) & MSR_TS_MASK) != 0) /* Transaction active? */ 111 + #define MSR_TM_RESV(x) (((x) & MSR_TS_MASK) == MSR_TS_MASK) /* Reserved */ 111 112 #define MSR_TM_TRANSACTIONAL(x) (((x) & MSR_TS_MASK) == MSR_TS_T) 112 113 #define MSR_TM_SUSPENDED(x) (((x) & MSR_TS_MASK) == MSR_TS_S) 113 114
+18
arch/powerpc/kernel/process.c
··· 551 551 msr_diff &= MSR_FP | MSR_VEC | MSR_VSX | MSR_FE0 | MSR_FE1; 552 552 } 553 553 554 + /* 555 + * Use the current MSR TM suspended bit to track if we have 556 + * checkpointed state outstanding. 557 + * On signal delivery, we'd normally reclaim the checkpointed 558 + * state to obtain stack pointer (see:get_tm_stackpointer()). 559 + * This will then directly return to userspace without going 560 + * through __switch_to(). However, if the stack frame is bad, 561 + * we need to exit this thread which calls __switch_to() which 562 + * will again attempt to reclaim the already saved tm state. 563 + * Hence we need to check that we've not already reclaimed 564 + * this state. 565 + * We do this using the current MSR, rather tracking it in 566 + * some specific thread_struct bit, as it has the additional 567 + * benifit of checking for a potential TM bad thing exception. 568 + */ 569 + if (!MSR_TM_SUSPENDED(mfmsr())) 570 + return; 571 + 554 572 tm_reclaim(thr, thr->regs->msr, cause); 555 573 556 574 /* Having done the reclaim, we now have the checkpointed
+9 -5
arch/powerpc/kernel/signal_32.c
··· 875 875 return 1; 876 876 #endif /* CONFIG_SPE */ 877 877 878 + /* Get the top half of the MSR from the user context */ 879 + if (__get_user(msr_hi, &tm_sr->mc_gregs[PT_MSR])) 880 + return 1; 881 + msr_hi <<= 32; 882 + /* If TM bits are set to the reserved value, it's an invalid context */ 883 + if (MSR_TM_RESV(msr_hi)) 884 + return 1; 885 + /* Pull in the MSR TM bits from the user context */ 886 + regs->msr = (regs->msr & ~MSR_TS_MASK) | (msr_hi & MSR_TS_MASK); 878 887 /* Now, recheckpoint. This loads up all of the checkpointed (older) 879 888 * registers, including FP and V[S]Rs. After recheckpointing, the 880 889 * transactional versions should be loaded. ··· 893 884 current->thread.tm_texasr |= TEXASR_FS; 894 885 /* This loads the checkpointed FP/VEC state, if used */ 895 886 tm_recheckpoint(&current->thread, msr); 896 - /* Get the top half of the MSR */ 897 - if (__get_user(msr_hi, &tm_sr->mc_gregs[PT_MSR])) 898 - return 1; 899 - /* Pull in MSR TM from user context */ 900 - regs->msr = (regs->msr & ~MSR_TS_MASK) | ((msr_hi<<32) & MSR_TS_MASK); 901 887 902 888 /* This loads the speculative FP/VEC state, if used */ 903 889 if (msr & MSR_FP) {
+4
arch/powerpc/kernel/signal_64.c
··· 438 438 439 439 /* get MSR separately, transfer the LE bit if doing signal return */ 440 440 err |= __get_user(msr, &sc->gp_regs[PT_MSR]); 441 + /* Don't allow reserved mode. */ 442 + if (MSR_TM_RESV(msr)) 443 + return -EINVAL; 444 + 441 445 /* pull in MSR TM from user context */ 442 446 regs->msr = (regs->msr & ~MSR_TS_MASK) | (msr & MSR_TS_MASK); 443 447