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

tagptr.h (2984B)


      1/* SPDX-License-Identifier: GPL-2.0-only */
      2/*
      3 * A tagged pointer implementation
      4 */
      5#ifndef __EROFS_FS_TAGPTR_H
      6#define __EROFS_FS_TAGPTR_H
      7
      8#include <linux/types.h>
      9#include <linux/build_bug.h>
     10
     11/*
     12 * the name of tagged pointer types are tagptr{1, 2, 3...}_t
     13 * avoid directly using the internal structs __tagptr{1, 2, 3...}
     14 */
     15#define __MAKE_TAGPTR(n) \
     16typedef struct __tagptr##n {	\
     17	uintptr_t v;	\
     18} tagptr##n##_t;
     19
     20__MAKE_TAGPTR(1)
     21__MAKE_TAGPTR(2)
     22__MAKE_TAGPTR(3)
     23__MAKE_TAGPTR(4)
     24
     25#undef __MAKE_TAGPTR
     26
     27extern void __compiletime_error("bad tagptr tags")
     28	__bad_tagptr_tags(void);
     29
     30extern void __compiletime_error("bad tagptr type")
     31	__bad_tagptr_type(void);
     32
     33/* fix the broken usage of "#define tagptr2_t tagptr3_t" by users */
     34#define __tagptr_mask_1(ptr, n)	\
     35	__builtin_types_compatible_p(typeof(ptr), struct __tagptr##n) ? \
     36		(1UL << (n)) - 1 :
     37
     38#define __tagptr_mask(ptr)	(\
     39	__tagptr_mask_1(ptr, 1) ( \
     40	__tagptr_mask_1(ptr, 2) ( \
     41	__tagptr_mask_1(ptr, 3) ( \
     42	__tagptr_mask_1(ptr, 4) ( \
     43	__bad_tagptr_type(), 0)))))
     44
     45/* generate a tagged pointer from a raw value */
     46#define tagptr_init(type, val) \
     47	((typeof(type)){ .v = (uintptr_t)(val) })
     48
     49/*
     50 * directly cast a tagged pointer to the native pointer type, which
     51 * could be used for backward compatibility of existing code.
     52 */
     53#define tagptr_cast_ptr(tptr) ((void *)(tptr).v)
     54
     55/* encode tagged pointers */
     56#define tagptr_fold(type, ptr, _tags) ({ \
     57	const typeof(_tags) tags = (_tags); \
     58	if (__builtin_constant_p(tags) && (tags & ~__tagptr_mask(type))) \
     59		__bad_tagptr_tags(); \
     60tagptr_init(type, (uintptr_t)(ptr) | tags); })
     61
     62/* decode tagged pointers */
     63#define tagptr_unfold_ptr(tptr) \
     64	((void *)((tptr).v & ~__tagptr_mask(tptr)))
     65
     66#define tagptr_unfold_tags(tptr) \
     67	((tptr).v & __tagptr_mask(tptr))
     68
     69/* operations for the tagger pointer */
     70#define tagptr_eq(_tptr1, _tptr2) ({ \
     71	typeof(_tptr1) tptr1 = (_tptr1); \
     72	typeof(_tptr2) tptr2 = (_tptr2); \
     73	(void)(&tptr1 == &tptr2); \
     74(tptr1).v == (tptr2).v; })
     75
     76/* lock-free CAS operation */
     77#define tagptr_cmpxchg(_ptptr, _o, _n) ({ \
     78	typeof(_ptptr) ptptr = (_ptptr); \
     79	typeof(_o) o = (_o); \
     80	typeof(_n) n = (_n); \
     81	(void)(&o == &n); \
     82	(void)(&o == ptptr); \
     83tagptr_init(o, cmpxchg(&ptptr->v, o.v, n.v)); })
     84
     85/* wrap WRITE_ONCE if atomic update is needed */
     86#define tagptr_replace_tags(_ptptr, tags) ({ \
     87	typeof(_ptptr) ptptr = (_ptptr); \
     88	*ptptr = tagptr_fold(*ptptr, tagptr_unfold_ptr(*ptptr), tags); \
     89*ptptr; })
     90
     91#define tagptr_set_tags(_ptptr, _tags) ({ \
     92	typeof(_ptptr) ptptr = (_ptptr); \
     93	const typeof(_tags) tags = (_tags); \
     94	if (__builtin_constant_p(tags) && (tags & ~__tagptr_mask(*ptptr))) \
     95		__bad_tagptr_tags(); \
     96	ptptr->v |= tags; \
     97*ptptr; })
     98
     99#define tagptr_clear_tags(_ptptr, _tags) ({ \
    100	typeof(_ptptr) ptptr = (_ptptr); \
    101	const typeof(_tags) tags = (_tags); \
    102	if (__builtin_constant_p(tags) && (tags & ~__tagptr_mask(*ptptr))) \
    103		__bad_tagptr_tags(); \
    104	ptptr->v &= ~tags; \
    105*ptptr; })
    106
    107#endif	/* __EROFS_FS_TAGPTR_H */