blob: 561489c20b058d3a2ab4755013507842f2a65457 [file] [log] [blame]
// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef LIB_C_THREADS_ZXR_TLS_H_
#define LIB_C_THREADS_ZXR_TLS_H_
#include <zircon/compiler.h>
#include <zircon/syscalls.h>
#include <zircon/syscalls/object.h>
__BEGIN_CDECLS
// Set the thread pointer.
static inline void zxr_tp_set(zx_handle_t self, void* tp);
// These are used in very early and low-level places where most kinds
// of instrumentation are not safe.
#ifdef __clang__
#define ZXR_NO_SANITIZERS __attribute__((no_sanitize("all")))
#else
#define ZXR_NO_SANITIZERS
#endif
// These are tiny functions meant to be inlined, where a call would often
// actually take more instruction bytes than just inlining it. However,
// Clang avoids inlining across functions with differing attributes and the
// necessary `no_sanitize` attribute trips that logic. So tell the
// compiler to force inlining here.
#define ZXR_TLS_INLINE ZXR_NO_SANITIZERS __attribute__((always_inline))
#if defined(__aarch64__)
ZXR_TLS_INLINE static inline void zxr_tp_set(zx_handle_t self, void* tp) {
__asm__ volatile("msr tpidr_el0, %0" : : "r"(tp));
}
#elif defined(__x86_64__)
ZXR_TLS_INLINE static inline void zxr_tp_set(zx_handle_t self, void* tp) {
zx_status_t status =
_zx_object_set_property(self, ZX_PROP_REGISTER_FS, (uintptr_t*)&tp, sizeof(uintptr_t));
if (status != ZX_OK)
__builtin_trap();
}
#elif defined(__riscv)
ZXR_TLS_INLINE static inline void zxr_tp_set(zx_handle_t self, void* tp) {
__asm__ volatile("mv tp, %0" : : "r"(tp));
}
#else
#error Unsupported architecture
#endif
__END_CDECLS
#endif // LIB_C_THREADS_ZXR_TLS_H_