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

cmpxchg.h (2617B)


      1/* SPDX-License-Identifier: GPL-2.0 */
      2#ifndef TOOLS_ASM_X86_CMPXCHG_H
      3#define TOOLS_ASM_X86_CMPXCHG_H
      4
      5#include <linux/compiler.h>
      6
      7/*
      8 * Non-existant functions to indicate usage errors at link time
      9 * (or compile-time if the compiler implements __compiletime_error().
     10 */
     11extern void __cmpxchg_wrong_size(void)
     12	__compiletime_error("Bad argument size for cmpxchg");
     13
     14/*
     15 * Constants for operation sizes. On 32-bit, the 64-bit size it set to
     16 * -1 because sizeof will never return -1, thereby making those switch
     17 * case statements guaranteeed dead code which the compiler will
     18 * eliminate, and allowing the "missing symbol in the default case" to
     19 * indicate a usage error.
     20 */
     21#define __X86_CASE_B	1
     22#define __X86_CASE_W	2
     23#define __X86_CASE_L	4
     24#ifdef __x86_64__
     25#define __X86_CASE_Q	8
     26#else
     27#define	__X86_CASE_Q	-1		/* sizeof will never return -1 */
     28#endif
     29
     30/*
     31 * Atomic compare and exchange.  Compare OLD with MEM, if identical,
     32 * store NEW in MEM.  Return the initial value in MEM.  Success is
     33 * indicated by comparing RETURN with OLD.
     34 */
     35#define __raw_cmpxchg(ptr, old, new, size, lock)			\
     36({									\
     37	__typeof__(*(ptr)) __ret;					\
     38	__typeof__(*(ptr)) __old = (old);				\
     39	__typeof__(*(ptr)) __new = (new);				\
     40	switch (size) {							\
     41	case __X86_CASE_B:						\
     42	{								\
     43		volatile u8 *__ptr = (volatile u8 *)(ptr);		\
     44		asm volatile(lock "cmpxchgb %2,%1"			\
     45			     : "=a" (__ret), "+m" (*__ptr)		\
     46			     : "q" (__new), "0" (__old)			\
     47			     : "memory");				\
     48		break;							\
     49	}								\
     50	case __X86_CASE_W:						\
     51	{								\
     52		volatile u16 *__ptr = (volatile u16 *)(ptr);		\
     53		asm volatile(lock "cmpxchgw %2,%1"			\
     54			     : "=a" (__ret), "+m" (*__ptr)		\
     55			     : "r" (__new), "0" (__old)			\
     56			     : "memory");				\
     57		break;							\
     58	}								\
     59	case __X86_CASE_L:						\
     60	{								\
     61		volatile u32 *__ptr = (volatile u32 *)(ptr);		\
     62		asm volatile(lock "cmpxchgl %2,%1"			\
     63			     : "=a" (__ret), "+m" (*__ptr)		\
     64			     : "r" (__new), "0" (__old)			\
     65			     : "memory");				\
     66		break;							\
     67	}								\
     68	case __X86_CASE_Q:						\
     69	{								\
     70		volatile u64 *__ptr = (volatile u64 *)(ptr);		\
     71		asm volatile(lock "cmpxchgq %2,%1"			\
     72			     : "=a" (__ret), "+m" (*__ptr)		\
     73			     : "r" (__new), "0" (__old)			\
     74			     : "memory");				\
     75		break;							\
     76	}								\
     77	default:							\
     78		__cmpxchg_wrong_size();					\
     79	}								\
     80	__ret;								\
     81})
     82
     83#define __cmpxchg(ptr, old, new, size)					\
     84	__raw_cmpxchg((ptr), (old), (new), (size), LOCK_PREFIX)
     85
     86#define cmpxchg(ptr, old, new)						\
     87	__cmpxchg(ptr, old, new, sizeof(*(ptr)))
     88
     89
     90#endif	/* TOOLS_ASM_X86_CMPXCHG_H */