Commit ae5e387c authored by Andrea Parri's avatar Andrea Parri Committed by Wen Zhiwei
Browse files

membarrier: riscv: Add full memory barrier in switch_mm()

stable inclusion
from stable-v6.6.51
commit a2977c0ca3e97dc4c1665f27117810902fdeb0a9
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/IAYRVR

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=a2977c0ca3e97dc4c1665f27117810902fdeb0a9



--------------------------------

commit d6cfd1770f20392d7009ae1fdb04733794514fa9 upstream.

The membarrier system call requires a full memory barrier after storing
to rq->curr, before going back to user-space.  The barrier is only
needed when switching between processes: the barrier is implied by
mmdrop() when switching from kernel to userspace, and it's not needed
when switching from userspace to kernel.

Rely on the feature/mechanism ARCH_HAS_MEMBARRIER_CALLBACKS and on the
primitive membarrier_arch_switch_mm(), already adopted by the PowerPC
architecture, to insert the required barrier.

Fixes: fab957c1 ("RISC-V: Atomic and Locking Code")
Signed-off-by: default avatarAndrea Parri <parri.andrea@gmail.com>
Reviewed-by: default avatarMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Link: https://lore.kernel.org/r/20240131144936.29190-2-parri.andrea@gmail.com


Signed-off-by: default avatarPalmer Dabbelt <palmer@rivosinc.com>
Signed-off-by: default avatarWangYuli <wangyuli@uniontech.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarWen Zhiwei <wenzhiwei@kylinos.cn>
parent fe916da9
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -13751,7 +13751,7 @@ M: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
M:	"Paul E. McKenney" <paulmck@kernel.org>
L:	linux-kernel@vger.kernel.org
S:	Supported
F:	arch/powerpc/include/asm/membarrier.h
F:	arch/*/include/asm/membarrier.h
F:	include/uapi/linux/membarrier.h
F:	kernel/sched/membarrier.c
+1 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ config RISCV
	select ARCH_HAS_GCOV_PROFILE_ALL
	select ARCH_HAS_GIGANTIC_PAGE
	select ARCH_HAS_KCOV
	select ARCH_HAS_MEMBARRIER_CALLBACKS
	select ARCH_HAS_MMIOWB
	select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
	select ARCH_HAS_PMEM_API
+31 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef _ASM_RISCV_MEMBARRIER_H
#define _ASM_RISCV_MEMBARRIER_H

static inline void membarrier_arch_switch_mm(struct mm_struct *prev,
					     struct mm_struct *next,
					     struct task_struct *tsk)
{
	/*
	 * Only need the full barrier when switching between processes.
	 * Barrier when switching from kernel to userspace is not
	 * required here, given that it is implied by mmdrop(). Barrier
	 * when switching from userspace to kernel is not needed after
	 * store to rq->curr.
	 */
	if (IS_ENABLED(CONFIG_SMP) &&
	    likely(!(atomic_read(&next->membarrier_state) &
		     (MEMBARRIER_STATE_PRIVATE_EXPEDITED |
		      MEMBARRIER_STATE_GLOBAL_EXPEDITED)) || !prev))
		return;

	/*
	 * The membarrier system call requires a full memory barrier
	 * after storing to rq->curr, before going back to user-space.
	 * Matches a full barrier in the proximity of the membarrier
	 * system call entry.
	 */
	smp_mb();
}

#endif /* _ASM_RISCV_MEMBARRIER_H */
+2 −0
Original line number Diff line number Diff line
@@ -323,6 +323,8 @@ void switch_mm(struct mm_struct *prev, struct mm_struct *next,
	if (unlikely(prev == next))
		return;

	membarrier_arch_switch_mm(prev, next, task);

	/*
	 * Mark the current MM context as inactive, and the next as
	 * active.  This is at least used by the icache flushing
+3 −2
Original line number Diff line number Diff line
@@ -6733,8 +6733,9 @@ static void __sched notrace __schedule(unsigned int sched_mode)
		 *
		 * Here are the schemes providing that barrier on the
		 * various architectures:
		 * - mm ? switch_mm() : mmdrop() for x86, s390, sparc, PowerPC.
		 *   switch_mm() rely on membarrier_arch_switch_mm() on PowerPC.
		 * - mm ? switch_mm() : mmdrop() for x86, s390, sparc, PowerPC,
		 *   RISC-V.  switch_mm() relies on membarrier_arch_switch_mm()
		 *   on PowerPC and on RISC-V.
		 * - finish_lock_switch() for weakly-ordered
		 *   architectures where spin_unlock is a full barrier,
		 * - switch_to() for arm64 (weakly-ordered, spin_unlock