cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

atomic-spinlock.h (2569B)


      1/* SPDX-License-Identifier: GPL-2.0-only */
      2
      3#ifndef _ASM_ARC_ATOMIC_SPLOCK_H
      4#define _ASM_ARC_ATOMIC_SPLOCK_H
      5
      6/*
      7 * Non hardware assisted Atomic-R-M-W
      8 * Locking would change to irq-disabling only (UP) and spinlocks (SMP)
      9 */
     10
     11static inline void arch_atomic_set(atomic_t *v, int i)
     12{
     13	/*
     14	 * Independent of hardware support, all of the atomic_xxx() APIs need
     15	 * to follow the same locking rules to make sure that a "hardware"
     16	 * atomic insn (e.g. LD) doesn't clobber an "emulated" atomic insn
     17	 * sequence
     18	 *
     19	 * Thus atomic_set() despite being 1 insn (and seemingly atomic)
     20	 * requires the locking.
     21	 */
     22	unsigned long flags;
     23
     24	atomic_ops_lock(flags);
     25	WRITE_ONCE(v->counter, i);
     26	atomic_ops_unlock(flags);
     27}
     28
     29#define arch_atomic_set_release(v, i)	arch_atomic_set((v), (i))
     30
     31#define ATOMIC_OP(op, c_op, asm_op)					\
     32static inline void arch_atomic_##op(int i, atomic_t *v)			\
     33{									\
     34	unsigned long flags;						\
     35									\
     36	atomic_ops_lock(flags);						\
     37	v->counter c_op i;						\
     38	atomic_ops_unlock(flags);					\
     39}
     40
     41#define ATOMIC_OP_RETURN(op, c_op, asm_op)				\
     42static inline int arch_atomic_##op##_return(int i, atomic_t *v)		\
     43{									\
     44	unsigned long flags;						\
     45	unsigned int temp;						\
     46									\
     47	/*								\
     48	 * spin lock/unlock provides the needed smp_mb() before/after	\
     49	 */								\
     50	atomic_ops_lock(flags);						\
     51	temp = v->counter;						\
     52	temp c_op i;							\
     53	v->counter = temp;						\
     54	atomic_ops_unlock(flags);					\
     55									\
     56	return temp;							\
     57}
     58
     59#define ATOMIC_FETCH_OP(op, c_op, asm_op)				\
     60static inline int arch_atomic_fetch_##op(int i, atomic_t *v)		\
     61{									\
     62	unsigned long flags;						\
     63	unsigned int orig;						\
     64									\
     65	/*								\
     66	 * spin lock/unlock provides the needed smp_mb() before/after	\
     67	 */								\
     68	atomic_ops_lock(flags);						\
     69	orig = v->counter;						\
     70	v->counter c_op i;						\
     71	atomic_ops_unlock(flags);					\
     72									\
     73	return orig;							\
     74}
     75
     76#define ATOMIC_OPS(op, c_op, asm_op)					\
     77	ATOMIC_OP(op, c_op, asm_op)					\
     78	ATOMIC_OP_RETURN(op, c_op, asm_op)				\
     79	ATOMIC_FETCH_OP(op, c_op, asm_op)
     80
     81ATOMIC_OPS(add, +=, add)
     82ATOMIC_OPS(sub, -=, sub)
     83
     84#undef ATOMIC_OPS
     85#define ATOMIC_OPS(op, c_op, asm_op)					\
     86	ATOMIC_OP(op, c_op, asm_op)					\
     87	ATOMIC_FETCH_OP(op, c_op, asm_op)
     88
     89ATOMIC_OPS(and, &=, and)
     90ATOMIC_OPS(andnot, &= ~, bic)
     91ATOMIC_OPS(or, |=, or)
     92ATOMIC_OPS(xor, ^=, xor)
     93
     94#define arch_atomic_andnot		arch_atomic_andnot
     95#define arch_atomic_fetch_andnot	arch_atomic_fetch_andnot
     96
     97#undef ATOMIC_OPS
     98#undef ATOMIC_FETCH_OP
     99#undef ATOMIC_OP_RETURN
    100#undef ATOMIC_OP
    101
    102#endif