powerpc: Snapshot thread flags
Some thread flags can be set remotely, and so even when IRQs are disabled, the flags can change under our feet. Generally this is unlikely to cause a problem in practice, but it is somewhat unsound, and KCSAN will legitimately warn that there is a data race. To avoid such issues, a snapshot of the flags has to be taken prior to using them. Some places already use READ_ONCE() for that, others do not. Convert them all to the new flag accessor helpers. Signed-off-by: Mark Rutland <mark.rutland@arm.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Acked-by: Paul E. McKenney <paulmck@kernel.org> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Michael Ellerman <mpe@ellerman.id.au> Cc: Paul Mackerras <paulus@samba.org> Link: https://lore.kernel.org/r/20211129130653.2037928-11-mark.rutland@arm.com
This commit is contained in:
parent
08b0af5b2a
commit
985faa7868
@ -181,7 +181,7 @@ notrace long system_call_exception(long r3, long r4, long r5,
|
||||
|
||||
local_irq_enable();
|
||||
|
||||
if (unlikely(current_thread_info()->flags & _TIF_SYSCALL_DOTRACE)) {
|
||||
if (unlikely(read_thread_flags() & _TIF_SYSCALL_DOTRACE)) {
|
||||
if (unlikely(trap_is_unsupported_scv(regs))) {
|
||||
/* Unsupported scv vector */
|
||||
_exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
|
||||
@ -343,7 +343,7 @@ interrupt_exit_user_prepare_main(unsigned long ret, struct pt_regs *regs)
|
||||
unsigned long ti_flags;
|
||||
|
||||
again:
|
||||
ti_flags = READ_ONCE(current_thread_info()->flags);
|
||||
ti_flags = read_thread_flags();
|
||||
while (unlikely(ti_flags & (_TIF_USER_WORK_MASK & ~_TIF_RESTORE_TM))) {
|
||||
local_irq_enable();
|
||||
if (ti_flags & _TIF_NEED_RESCHED) {
|
||||
@ -359,7 +359,7 @@ again:
|
||||
do_notify_resume(regs, ti_flags);
|
||||
}
|
||||
local_irq_disable();
|
||||
ti_flags = READ_ONCE(current_thread_info()->flags);
|
||||
ti_flags = read_thread_flags();
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_PPC_BOOK3S_64) && IS_ENABLED(CONFIG_PPC_FPU)) {
|
||||
@ -437,7 +437,7 @@ notrace unsigned long syscall_exit_prepare(unsigned long r3,
|
||||
/* Check whether the syscall is issued inside a restartable sequence */
|
||||
rseq_syscall(regs);
|
||||
|
||||
ti_flags = current_thread_info()->flags;
|
||||
ti_flags = read_thread_flags();
|
||||
|
||||
if (unlikely(r3 >= (unsigned long)-MAX_ERRNO) && is_not_scv) {
|
||||
if (likely(!(ti_flags & (_TIF_NOERROR | _TIF_RESTOREALL)))) {
|
||||
@ -532,8 +532,7 @@ notrace unsigned long interrupt_exit_kernel_prepare(struct pt_regs *regs)
|
||||
unsigned long flags;
|
||||
unsigned long ret = 0;
|
||||
unsigned long kuap;
|
||||
bool stack_store = current_thread_info()->flags &
|
||||
_TIF_EMULATE_STACK_STORE;
|
||||
bool stack_store = read_thread_flags() & _TIF_EMULATE_STACK_STORE;
|
||||
|
||||
if (regs_is_unrecoverable(regs))
|
||||
unrecoverable_exception(regs);
|
||||
@ -554,7 +553,7 @@ notrace unsigned long interrupt_exit_kernel_prepare(struct pt_regs *regs)
|
||||
again:
|
||||
if (IS_ENABLED(CONFIG_PREEMPT)) {
|
||||
/* Return to preemptible kernel context */
|
||||
if (unlikely(current_thread_info()->flags & _TIF_NEED_RESCHED)) {
|
||||
if (unlikely(read_thread_flags() & _TIF_NEED_RESCHED)) {
|
||||
if (preempt_count() == 0)
|
||||
preempt_schedule_irq();
|
||||
}
|
||||
|
@ -260,8 +260,7 @@ long do_syscall_trace_enter(struct pt_regs *regs)
|
||||
{
|
||||
u32 flags;
|
||||
|
||||
flags = READ_ONCE(current_thread_info()->flags) &
|
||||
(_TIF_SYSCALL_EMU | _TIF_SYSCALL_TRACE);
|
||||
flags = read_thread_flags() & (_TIF_SYSCALL_EMU | _TIF_SYSCALL_TRACE);
|
||||
|
||||
if (flags) {
|
||||
int rc = tracehook_report_syscall_entry(regs);
|
||||
|
Loading…
Reference in New Issue
Block a user