199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
299a2dd95SBruce Richardson * Copyright(c) 2010-2014 Intel Corporation.
399a2dd95SBruce Richardson */
499a2dd95SBruce Richardson
599a2dd95SBruce Richardson /*
699a2dd95SBruce Richardson * Inspired from FreeBSD src/sys/amd64/include/atomic.h
799a2dd95SBruce Richardson * Copyright (c) 1998 Doug Rabson
899a2dd95SBruce Richardson * Copyright (c) 2019 Intel Corporation
999a2dd95SBruce Richardson * All rights reserved.
1099a2dd95SBruce Richardson */
1199a2dd95SBruce Richardson
1299a2dd95SBruce Richardson #ifndef _RTE_ATOMIC_X86_H_
1399a2dd95SBruce Richardson #error do not include this file directly, use <rte_atomic.h> instead
1499a2dd95SBruce Richardson #endif
1599a2dd95SBruce Richardson
1699a2dd95SBruce Richardson #ifndef _RTE_ATOMIC_X86_64_H_
1799a2dd95SBruce Richardson #define _RTE_ATOMIC_X86_64_H_
1899a2dd95SBruce Richardson
1999a2dd95SBruce Richardson #include <stdint.h>
20*558f0357SStephen Hemminger
2199a2dd95SBruce Richardson #include <rte_common.h>
2299a2dd95SBruce Richardson
2399a2dd95SBruce Richardson /*------------------------- 64 bit atomic operations -------------------------*/
2499a2dd95SBruce Richardson
2599a2dd95SBruce Richardson #ifndef RTE_FORCE_INTRINSICS
2699a2dd95SBruce Richardson static inline int
rte_atomic64_cmpset(volatile uint64_t * dst,uint64_t exp,uint64_t src)2799a2dd95SBruce Richardson rte_atomic64_cmpset(volatile uint64_t *dst, uint64_t exp, uint64_t src)
2899a2dd95SBruce Richardson {
2999a2dd95SBruce Richardson uint8_t res;
3099a2dd95SBruce Richardson
3199a2dd95SBruce Richardson
3299a2dd95SBruce Richardson asm volatile(
3399a2dd95SBruce Richardson MPLOCKED
3499a2dd95SBruce Richardson "cmpxchgq %[src], %[dst];"
3599a2dd95SBruce Richardson "sete %[res];"
3699a2dd95SBruce Richardson : [res] "=a" (res), /* output */
3799a2dd95SBruce Richardson [dst] "=m" (*dst)
3899a2dd95SBruce Richardson : [src] "r" (src), /* input */
3999a2dd95SBruce Richardson "a" (exp),
4099a2dd95SBruce Richardson "m" (*dst)
4199a2dd95SBruce Richardson : "memory"); /* no-clobber list */
4299a2dd95SBruce Richardson
4399a2dd95SBruce Richardson return res;
4499a2dd95SBruce Richardson }
4599a2dd95SBruce Richardson
4699a2dd95SBruce Richardson static inline uint64_t
rte_atomic64_exchange(volatile uint64_t * dst,uint64_t val)4799a2dd95SBruce Richardson rte_atomic64_exchange(volatile uint64_t *dst, uint64_t val)
4899a2dd95SBruce Richardson {
4999a2dd95SBruce Richardson asm volatile(
5099a2dd95SBruce Richardson MPLOCKED
5199a2dd95SBruce Richardson "xchgq %0, %1;"
5299a2dd95SBruce Richardson : "=r" (val), "=m" (*dst)
5399a2dd95SBruce Richardson : "0" (val), "m" (*dst)
5499a2dd95SBruce Richardson : "memory"); /* no-clobber list */
5599a2dd95SBruce Richardson return val;
5699a2dd95SBruce Richardson }
5799a2dd95SBruce Richardson
5899a2dd95SBruce Richardson static inline void
rte_atomic64_init(rte_atomic64_t * v)5999a2dd95SBruce Richardson rte_atomic64_init(rte_atomic64_t *v)
6099a2dd95SBruce Richardson {
6199a2dd95SBruce Richardson v->cnt = 0;
6299a2dd95SBruce Richardson }
6399a2dd95SBruce Richardson
6499a2dd95SBruce Richardson static inline int64_t
rte_atomic64_read(rte_atomic64_t * v)6599a2dd95SBruce Richardson rte_atomic64_read(rte_atomic64_t *v)
6699a2dd95SBruce Richardson {
6799a2dd95SBruce Richardson return v->cnt;
6899a2dd95SBruce Richardson }
6999a2dd95SBruce Richardson
7099a2dd95SBruce Richardson static inline void
rte_atomic64_set(rte_atomic64_t * v,int64_t new_value)7199a2dd95SBruce Richardson rte_atomic64_set(rte_atomic64_t *v, int64_t new_value)
7299a2dd95SBruce Richardson {
7399a2dd95SBruce Richardson v->cnt = new_value;
7499a2dd95SBruce Richardson }
7599a2dd95SBruce Richardson
7699a2dd95SBruce Richardson static inline void
rte_atomic64_add(rte_atomic64_t * v,int64_t inc)7799a2dd95SBruce Richardson rte_atomic64_add(rte_atomic64_t *v, int64_t inc)
7899a2dd95SBruce Richardson {
7999a2dd95SBruce Richardson asm volatile(
8099a2dd95SBruce Richardson MPLOCKED
8199a2dd95SBruce Richardson "addq %[inc], %[cnt]"
8299a2dd95SBruce Richardson : [cnt] "=m" (v->cnt) /* output */
8399a2dd95SBruce Richardson : [inc] "ir" (inc), /* input */
8499a2dd95SBruce Richardson "m" (v->cnt)
8599a2dd95SBruce Richardson );
8699a2dd95SBruce Richardson }
8799a2dd95SBruce Richardson
8899a2dd95SBruce Richardson static inline void
rte_atomic64_sub(rte_atomic64_t * v,int64_t dec)8999a2dd95SBruce Richardson rte_atomic64_sub(rte_atomic64_t *v, int64_t dec)
9099a2dd95SBruce Richardson {
9199a2dd95SBruce Richardson asm volatile(
9299a2dd95SBruce Richardson MPLOCKED
9399a2dd95SBruce Richardson "subq %[dec], %[cnt]"
9499a2dd95SBruce Richardson : [cnt] "=m" (v->cnt) /* output */
9599a2dd95SBruce Richardson : [dec] "ir" (dec), /* input */
9699a2dd95SBruce Richardson "m" (v->cnt)
9799a2dd95SBruce Richardson );
9899a2dd95SBruce Richardson }
9999a2dd95SBruce Richardson
10099a2dd95SBruce Richardson static inline void
rte_atomic64_inc(rte_atomic64_t * v)10199a2dd95SBruce Richardson rte_atomic64_inc(rte_atomic64_t *v)
10299a2dd95SBruce Richardson {
10399a2dd95SBruce Richardson asm volatile(
10499a2dd95SBruce Richardson MPLOCKED
10599a2dd95SBruce Richardson "incq %[cnt]"
10699a2dd95SBruce Richardson : [cnt] "=m" (v->cnt) /* output */
10799a2dd95SBruce Richardson : "m" (v->cnt) /* input */
10899a2dd95SBruce Richardson );
10999a2dd95SBruce Richardson }
11099a2dd95SBruce Richardson
11199a2dd95SBruce Richardson static inline void
rte_atomic64_dec(rte_atomic64_t * v)11299a2dd95SBruce Richardson rte_atomic64_dec(rte_atomic64_t *v)
11399a2dd95SBruce Richardson {
11499a2dd95SBruce Richardson asm volatile(
11599a2dd95SBruce Richardson MPLOCKED
11699a2dd95SBruce Richardson "decq %[cnt]"
11799a2dd95SBruce Richardson : [cnt] "=m" (v->cnt) /* output */
11899a2dd95SBruce Richardson : "m" (v->cnt) /* input */
11999a2dd95SBruce Richardson );
12099a2dd95SBruce Richardson }
12199a2dd95SBruce Richardson
12299a2dd95SBruce Richardson static inline int64_t
rte_atomic64_add_return(rte_atomic64_t * v,int64_t inc)12399a2dd95SBruce Richardson rte_atomic64_add_return(rte_atomic64_t *v, int64_t inc)
12499a2dd95SBruce Richardson {
12599a2dd95SBruce Richardson int64_t prev = inc;
12699a2dd95SBruce Richardson
12799a2dd95SBruce Richardson asm volatile(
12899a2dd95SBruce Richardson MPLOCKED
12999a2dd95SBruce Richardson "xaddq %[prev], %[cnt]"
13099a2dd95SBruce Richardson : [prev] "+r" (prev), /* output */
13199a2dd95SBruce Richardson [cnt] "=m" (v->cnt)
13299a2dd95SBruce Richardson : "m" (v->cnt) /* input */
13399a2dd95SBruce Richardson );
13499a2dd95SBruce Richardson return prev + inc;
13599a2dd95SBruce Richardson }
13699a2dd95SBruce Richardson
13799a2dd95SBruce Richardson static inline int64_t
rte_atomic64_sub_return(rte_atomic64_t * v,int64_t dec)13899a2dd95SBruce Richardson rte_atomic64_sub_return(rte_atomic64_t *v, int64_t dec)
13999a2dd95SBruce Richardson {
14099a2dd95SBruce Richardson return rte_atomic64_add_return(v, -dec);
14199a2dd95SBruce Richardson }
14299a2dd95SBruce Richardson
rte_atomic64_inc_and_test(rte_atomic64_t * v)14399a2dd95SBruce Richardson static inline int rte_atomic64_inc_and_test(rte_atomic64_t *v)
14499a2dd95SBruce Richardson {
14599a2dd95SBruce Richardson uint8_t ret;
14699a2dd95SBruce Richardson
14799a2dd95SBruce Richardson asm volatile(
14899a2dd95SBruce Richardson MPLOCKED
14999a2dd95SBruce Richardson "incq %[cnt] ; "
15099a2dd95SBruce Richardson "sete %[ret]"
15199a2dd95SBruce Richardson : [cnt] "+m" (v->cnt), /* output */
15299a2dd95SBruce Richardson [ret] "=qm" (ret)
15399a2dd95SBruce Richardson );
15499a2dd95SBruce Richardson
15599a2dd95SBruce Richardson return ret != 0;
15699a2dd95SBruce Richardson }
15799a2dd95SBruce Richardson
rte_atomic64_dec_and_test(rte_atomic64_t * v)15899a2dd95SBruce Richardson static inline int rte_atomic64_dec_and_test(rte_atomic64_t *v)
15999a2dd95SBruce Richardson {
16099a2dd95SBruce Richardson uint8_t ret;
16199a2dd95SBruce Richardson
16299a2dd95SBruce Richardson asm volatile(
16399a2dd95SBruce Richardson MPLOCKED
16499a2dd95SBruce Richardson "decq %[cnt] ; "
16599a2dd95SBruce Richardson "sete %[ret]"
16699a2dd95SBruce Richardson : [cnt] "+m" (v->cnt), /* output */
16799a2dd95SBruce Richardson [ret] "=qm" (ret)
16899a2dd95SBruce Richardson );
16999a2dd95SBruce Richardson return ret != 0;
17099a2dd95SBruce Richardson }
17199a2dd95SBruce Richardson
rte_atomic64_test_and_set(rte_atomic64_t * v)17299a2dd95SBruce Richardson static inline int rte_atomic64_test_and_set(rte_atomic64_t *v)
17399a2dd95SBruce Richardson {
17499a2dd95SBruce Richardson return rte_atomic64_cmpset((volatile uint64_t *)&v->cnt, 0, 1);
17599a2dd95SBruce Richardson }
17699a2dd95SBruce Richardson
rte_atomic64_clear(rte_atomic64_t * v)17799a2dd95SBruce Richardson static inline void rte_atomic64_clear(rte_atomic64_t *v)
17899a2dd95SBruce Richardson {
17999a2dd95SBruce Richardson v->cnt = 0;
18099a2dd95SBruce Richardson }
18199a2dd95SBruce Richardson #endif
18299a2dd95SBruce Richardson
18399a2dd95SBruce Richardson /*------------------------ 128 bit atomic operations -------------------------*/
18499a2dd95SBruce Richardson
18599a2dd95SBruce Richardson static inline int
rte_atomic128_cmp_exchange(rte_int128_t * dst,rte_int128_t * exp,const rte_int128_t * src,unsigned int weak,int success,int failure)18699a2dd95SBruce Richardson rte_atomic128_cmp_exchange(rte_int128_t *dst,
18799a2dd95SBruce Richardson rte_int128_t *exp,
18899a2dd95SBruce Richardson const rte_int128_t *src,
18999a2dd95SBruce Richardson unsigned int weak,
19099a2dd95SBruce Richardson int success,
19199a2dd95SBruce Richardson int failure)
19299a2dd95SBruce Richardson {
19399a2dd95SBruce Richardson RTE_SET_USED(weak);
19499a2dd95SBruce Richardson RTE_SET_USED(success);
19599a2dd95SBruce Richardson RTE_SET_USED(failure);
19699a2dd95SBruce Richardson uint8_t res;
19799a2dd95SBruce Richardson
19899a2dd95SBruce Richardson asm volatile (
19999a2dd95SBruce Richardson MPLOCKED
20099a2dd95SBruce Richardson "cmpxchg16b %[dst];"
20199a2dd95SBruce Richardson " sete %[res]"
20299a2dd95SBruce Richardson : [dst] "=m" (dst->val[0]),
20399a2dd95SBruce Richardson "=a" (exp->val[0]),
20499a2dd95SBruce Richardson "=d" (exp->val[1]),
20599a2dd95SBruce Richardson [res] "=r" (res)
20699a2dd95SBruce Richardson : "b" (src->val[0]),
20799a2dd95SBruce Richardson "c" (src->val[1]),
20899a2dd95SBruce Richardson "a" (exp->val[0]),
20999a2dd95SBruce Richardson "d" (exp->val[1]),
21099a2dd95SBruce Richardson "m" (dst->val[0])
21199a2dd95SBruce Richardson : "memory");
21299a2dd95SBruce Richardson
21399a2dd95SBruce Richardson return res;
21499a2dd95SBruce Richardson }
21599a2dd95SBruce Richardson
21699a2dd95SBruce Richardson #endif /* _RTE_ATOMIC_X86_64_H_ */
217