提交 73a6fdc4 编写于 作者: W Will Deacon

ARM: spinlock: use inner-shareable dsb variant prior to sev instruction

When unlocking a spinlock, we use the sev instruction to signal other
CPUs waiting on the lock. Since sev is not a memory access instruction,
we require a dsb in order to ensure that the sev is not issued ahead
of the store placing the lock in an unlocked state.

However, as sev is only concerned with other processors in a
multiprocessor system, we can restrict the scope of the preceding dsb
to the inner-shareable domain. Furthermore, we can restrict the scope to
consider only stores, since there are no independent loads on the unlock
path.

A side-effect of this change is that a spin_unlock operation no longer
forces completion of pending TLB invalidation, something which we rely
on when unlocking runqueues to ensure that CPU migration during TLB
maintenance routines doesn't cause us to continue before the operation
has completed.

This patch adds the -ishst suffix to the ARMv7 definition of dsb_sev()
and adds an inner-shareable dsb to the context-switch path when running
a preemptible, SMP, v7 kernel.
Reviewed-by: NCatalin Marinas <catalin.marinas@arm.com>
Signed-off-by: NWill Deacon <will.deacon@arm.com>
上级 6abdd491
...@@ -46,7 +46,7 @@ static inline void dsb_sev(void) ...@@ -46,7 +46,7 @@ static inline void dsb_sev(void)
{ {
#if __LINUX_ARM_ARCH__ >= 7 #if __LINUX_ARM_ARCH__ >= 7
__asm__ __volatile__ ( __asm__ __volatile__ (
"dsb\n" "dsb ishst\n"
SEV SEV
); );
#else #else
......
...@@ -3,6 +3,16 @@ ...@@ -3,6 +3,16 @@
#include <linux/thread_info.h> #include <linux/thread_info.h>
/*
* For v7 SMP cores running a preemptible kernel we may be pre-empted
* during a TLB maintenance operation, so execute an inner-shareable dsb
* to ensure that the maintenance completes in case we migrate to another
* CPU.
*/
#if defined(CONFIG_PREEMPT) && defined(CONFIG_SMP) && defined(CONFIG_CPU_V7)
#define finish_arch_switch(prev) dsb(ish)
#endif
/* /*
* switch_to(prev, next) should switch from task `prev' to `next' * switch_to(prev, next) should switch from task `prev' to `next'
* `prev' will never be the same as `next'. schedule() itself * `prev' will never be the same as `next'. schedule() itself
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册