Skip to content

Commit a2977c0

Browse files
andrea-parrigregkh
authored andcommitted
membarrier: riscv: Add full memory barrier in switch_mm()
commit d6cfd17 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: fab957c ("RISC-V: Atomic and Locking Code") Signed-off-by: Andrea Parri <[email protected]> Reviewed-by: Mathieu Desnoyers <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Palmer Dabbelt <[email protected]> Signed-off-by: WangYuli <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 136a29d commit a2977c0

File tree

5 files changed

+38
-3
lines changed

5 files changed

+38
-3
lines changed

MAINTAINERS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13702,7 +13702,7 @@ M: Mathieu Desnoyers <[email protected]>
1370213702
M: "Paul E. McKenney" <[email protected]>
1370313703
1370413704
S: Supported
13705-
F: arch/powerpc/include/asm/membarrier.h
13705+
F: arch/*/include/asm/membarrier.h
1370613706
F: include/uapi/linux/membarrier.h
1370713707
F: kernel/sched/membarrier.c
1370813708

arch/riscv/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ config RISCV
2727
select ARCH_HAS_GCOV_PROFILE_ALL
2828
select ARCH_HAS_GIGANTIC_PAGE
2929
select ARCH_HAS_KCOV
30+
select ARCH_HAS_MEMBARRIER_CALLBACKS
3031
select ARCH_HAS_MMIOWB
3132
select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
3233
select ARCH_HAS_PMEM_API

arch/riscv/include/asm/membarrier.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/* SPDX-License-Identifier: GPL-2.0-only */
2+
#ifndef _ASM_RISCV_MEMBARRIER_H
3+
#define _ASM_RISCV_MEMBARRIER_H
4+
5+
static inline void membarrier_arch_switch_mm(struct mm_struct *prev,
6+
struct mm_struct *next,
7+
struct task_struct *tsk)
8+
{
9+
/*
10+
* Only need the full barrier when switching between processes.
11+
* Barrier when switching from kernel to userspace is not
12+
* required here, given that it is implied by mmdrop(). Barrier
13+
* when switching from userspace to kernel is not needed after
14+
* store to rq->curr.
15+
*/
16+
if (IS_ENABLED(CONFIG_SMP) &&
17+
likely(!(atomic_read(&next->membarrier_state) &
18+
(MEMBARRIER_STATE_PRIVATE_EXPEDITED |
19+
MEMBARRIER_STATE_GLOBAL_EXPEDITED)) || !prev))
20+
return;
21+
22+
/*
23+
* The membarrier system call requires a full memory barrier
24+
* after storing to rq->curr, before going back to user-space.
25+
* Matches a full barrier in the proximity of the membarrier
26+
* system call entry.
27+
*/
28+
smp_mb();
29+
}
30+
31+
#endif /* _ASM_RISCV_MEMBARRIER_H */

arch/riscv/mm/context.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,8 @@ void switch_mm(struct mm_struct *prev, struct mm_struct *next,
323323
if (unlikely(prev == next))
324324
return;
325325

326+
membarrier_arch_switch_mm(prev, next, task);
327+
326328
/*
327329
* Mark the current MM context as inactive, and the next as
328330
* active. This is at least used by the icache flushing

kernel/sched/core.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6679,8 +6679,9 @@ static void __sched notrace __schedule(unsigned int sched_mode)
66796679
*
66806680
* Here are the schemes providing that barrier on the
66816681
* various architectures:
6682-
* - mm ? switch_mm() : mmdrop() for x86, s390, sparc, PowerPC.
6683-
* switch_mm() rely on membarrier_arch_switch_mm() on PowerPC.
6682+
* - mm ? switch_mm() : mmdrop() for x86, s390, sparc, PowerPC,
6683+
* RISC-V. switch_mm() relies on membarrier_arch_switch_mm()
6684+
* on PowerPC and on RISC-V.
66846685
* - finish_lock_switch() for weakly-ordered
66856686
* architectures where spin_unlock is a full barrier,
66866687
* - switch_to() for arm64 (weakly-ordered, spin_unlock

0 commit comments

Comments
 (0)