----- On Jun 15, 2021, at 11:21 PM, Andy Lutomirski luto@xxxxxxxxxx wrote: > The old sync_core_before_usermode() comments suggested that a non-icache-syncing > return-to-usermode instruction is x86-specific and that all other > architectures automatically notice cross-modified code on return to > userspace. > > This is misleading. The incantation needed to modify code from one > CPU and execute it on another CPU is highly architecture dependent. > On x86, according to the SDM, one must modify the code, issue SFENCE > if the modification was WC or nontemporal, and then issue a "serializing > instruction" on the CPU that will execute the code. membarrier() can do > the latter. > > On arm64 and powerpc, one must flush the icache and then flush the pipeline > on the target CPU, although the CPU manuals don't necessarily use this > language. > > So let's drop any pretense that we can have a generic way to define or > implement membarrier's SYNC_CORE operation and instead require all > architectures to define the helper and supply their own documentation as to > how to use it. Agreed. Documentation of the sequence of operations that need to be performed when cross-modifying code on SMP should be per-architecture. The documentation of the architectural effects of membarrier sync-core should be per-arch as well. > This means x86, arm64, and powerpc for now. And also arm32, as discussed in the other leg of the patchset's email thread. > Let's also > rename the function from sync_core_before_usermode() to > membarrier_sync_core_before_usermode() because the precise flushing details > may very well be specific to membarrier, and even the concept of > "sync_core" in the kernel is mostly an x86-ism. OK > [...] > > static void ipi_rseq(void *info) > { > @@ -368,12 +373,14 @@ static int membarrier_private_expedited(int flags, int > cpu_id) > smp_call_func_t ipi_func = ipi_mb; > > if (flags == MEMBARRIER_FLAG_SYNC_CORE) { > - if (!IS_ENABLED(CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE)) > +#ifndef CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE > return -EINVAL; > +#else > if (!(atomic_read(&mm->membarrier_state) & > MEMBARRIER_STATE_PRIVATE_EXPEDITED_SYNC_CORE_READY)) > return -EPERM; > ipi_func = ipi_sync_core; > +#endif Please change back this #ifndef / #else / #endif within function for if (!IS_ENABLED(CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE)) { ... } else { ... } I don't think mixing up preprocessor and code logic makes it more readable. Thanks, Mathieu > } else if (flags == MEMBARRIER_FLAG_RSEQ) { > if (!IS_ENABLED(CONFIG_RSEQ)) > return -EINVAL; > -- > 2.31.1 -- Mathieu Desnoyers EfficiOS Inc. http://www.efficios.com