blob: 74c87d5fbf8ba9a317bd5f3755ed94bc19770fb2 [file]
// Copyright 2026 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT
#include <lib/syscalls/forward.h>
#include <zircon/types.h>
#include <kernel/mp.h>
namespace {
void DataIpiTask(void* context) { arch::ThreadMemoryBarrier(); }
void InstructionIpiTask(void* context) {
// All architectures require a memory barrier before serializing the instruction stream.
arch::ThreadMemoryBarrier();
// The intrinsics for serializing the instruction stream vary by architecture.
// TODO(https://fxbug.dev/42126965): Rationalize these.
#if defined(__aarch64__)
__isb(ARM_MB_SY);
#elif defined(__x86_64__)
arch::SerializeInstructions();
#elif defined(__riscv)
__asm__ volatile("fence.i");
#else
#error Unknown architecture.
#endif
}
} // namespace
void sys_membarrier_sync_process_data() {
// The membarrier operations are defined to operate on at least all running threads in
// the calling process (specifically the calling thread's futex context). For now, just
// issue a barrier to all running CPUs.
mp_sync_exec(mp_ipi_target::ALL, 0u, DataIpiTask, nullptr);
}
void sys_membarrier_sync_process_insn() {
// The membarrier operations are defined to operate on at least all running threads in
// the calling process (specifically the calling thread's futex context). For now, just
// issue a barrier to all running CPUs.
mp_sync_exec(mp_ipi_target::ALL, 0u, InstructionIpiTask, nullptr);
}