123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- /*
- * Copyright (c) 2006-2024 RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2024-07-04 rcitach init ver.
- */
- #ifndef ASM_VDSO_SYS_H
- #define ASM_VDSO_SYS_H
- #include <time.h>
- #include <unistd.h>
- #include <sys/types.h>
- #include <vdso_config.h>
- #include <vdso_datapage.h>
- #define __always_unused __attribute__((__unused__))
- #define __maybe_unused __attribute__((__unused__))
- #define likely(x) __builtin_expect(!!(x), 1)
- #define unlikely(x) __builtin_expect(!!(x), 0)
- #define arch_counter_enforce_ordering(val) do { \
- uint64_t tmp, _val = (val); \
- \
- asm volatile( \
- " eor %0, %1, %1\n" \
- " add %0, sp, %0\n" \
- " ldr xzr, [%0]" \
- : "=r" (tmp) : "r" (_val)); \
- } while (0)
- static inline uint64_t __arch_get_hw_counter()
- {
- uint64_t res;
- __asm__ volatile("mrs %0, CNTVCT_EL0":"=r"(res));
- arch_counter_enforce_ordering(res);
- return res;
- }
- static inline uint64_t __arch_get_hw_frq()
- {
- uint64_t res;
- __asm__ volatile("mrs %0, CNTFRQ_EL0":"=r"(res));
- arch_counter_enforce_ordering(res);
- return res;
- }
- static inline uint32_t
- __iter_div_u64_rem(uint64_t dividend, uint32_t divisor, uint64_t *remainder)
- {
- uint32_t ret = 0;
- while (dividend >= divisor) {
- /* The following asm() prevents the compiler from
- optimising this loop into a modulo operation. */
- __asm__("" : "+rm"(dividend));
- dividend -= divisor;
- ret++;
- }
- *remainder = dividend;
- return ret;
- }
- #define __RT_STRINGIFY(x...) #x
- #define RT_STRINGIFY(x...) __RT_STRINGIFY(x)
- #define rt_hw_barrier(cmd, ...) \
- __asm__ volatile (RT_STRINGIFY(cmd) " "RT_STRINGIFY(__VA_ARGS__):::"memory")
- #define rt_hw_isb() rt_hw_barrier(isb)
- #define rt_hw_dmb() rt_hw_barrier(dmb, ish)
- #define rt_hw_wmb() rt_hw_barrier(dmb, ishst)
- #define rt_hw_rmb() rt_hw_barrier(dmb, ishld)
- #define rt_hw_dsb() rt_hw_barrier(dsb, ish)
- #ifndef barrier
- /* The "volatile" is due to gcc bugs */
- # define barrier() __asm__ __volatile__("": : :"memory")
- #endif
- static inline void cpu_relax(void)
- {
- __asm__ volatile("yield" ::: "memory");
- }
- #define __READ_ONCE_SIZE \
- ({ \
- switch (size) { \
- case 1: *(__u8 *)res = *(volatile __u8 *)p; break; \
- case 2: *(__u16 *)res = *(volatile __u16 *)p; break; \
- case 4: *(__u32 *)res = *(volatile __u32 *)p; break; \
- case 8: *(__u64 *)res = *(volatile __u64 *)p; break; \
- default: \
- barrier(); \
- __builtin_memcpy((void *)res, (const void *)p, size); \
- barrier(); \
- } \
- })
- static inline
- void __read_once_size(const volatile void *p, void *res, int size)
- {
- __READ_ONCE_SIZE;
- }
- #define __READ_ONCE(x, check) \
- ({ \
- union { typeof(x) __val; char __c[1]; } __u; \
- if (check) \
- __read_once_size(&(x), __u.__c, sizeof(x)); \
- smp_read_barrier_depends(); /* Enforce dependency ordering from x */ \
- __u.__val; \
- })
- #define READ_ONCE(x) __READ_ONCE(x, 1)
- extern struct vdso_data _vdso_data[CS_BASES] __attribute__((visibility("hidden")));
- static inline struct vdso_data *__arch_get_vdso_data(void)
- {
- return _vdso_data;
- }
- static inline uint32_t rt_vdso_read_begin(const struct vdso_data *vd)
- {
- uint32_t seq;
- while (unlikely((seq = READ_ONCE(vd->seq)) & 1))
- cpu_relax();
- rt_hw_rmb();
- return seq;
- }
- static inline uint32_t rt_vdso_read_retry(const struct vdso_data *vd,
- uint32_t start)
- {
- uint32_t seq;
- rt_hw_rmb();
- seq = READ_ONCE(vd->seq);
- return seq != start;
- }
- #endif
|