blob: 59d9618c396e90cfd41616a9301bf33a536ca9b2 [file] [log] [blame]
// Copyright Microsoft and CHERIoT Contributors.
// SPDX-License-Identifier: MIT
#ifndef _CHERI_BUILTINS_
#define _CHERI_BUILTINS_
#define CHERI_PERM_GLOBAL (1U << 0)
#define CHERI_PERM_LOAD_GLOBAL (1U << 1)
#define CHERI_PERM_STORE (1U << 2)
#define CHERI_PERM_LOAD_MUTABLE (1U << 3)
#define CHERI_PERM_STORE_LOCAL (1U << 4)
#define CHERI_PERM_LOAD (1U << 5)
#define CHERI_PERM_LOAD_STORE_CAP (1U << 6)
#define CHERI_PERM_ACCESS_SYS (1U << 7)
#define CHERI_PERM_EXECUTE (1U << 8)
#define CHERI_PERM_UNSEAL (1U << 9)
#define CHERI_PERM_SEAL (1U << 10)
#define CHERI_PERM_USER0 (1U << 11)
#define CHERI_OTYPE_BITS 3
#ifndef __cplusplus
# ifndef __ASSEMBLER__
# include <stddef.h>
# include <stdint.h>
# define cr_read(name) \
({ \
void *val; \
__asm __volatile("cmove %0, " #name : "=C"(val)); \
val; \
})
# define cr_write(name, val) \
({ __asm __volatile("cmove " #name ", %0" ::"C"(val)); })
static inline void mem_cpy64(volatile uint64_t *dst, volatile uint64_t *p)
{
volatile void **_dst = (volatile void **)dst;
volatile void **_p = (volatile void **)p;
*_dst = *_p;
}
# define cgetlen(foo) __builtin_cheri_length_get(foo)
# define cgetperms(foo) __builtin_cheri_perms_get(foo)
# define cgettype(foo) __builtin_cheri_type_get(foo)
# define cgettag(foo) __builtin_cheri_tag_get(foo)
# define cgetoffset(foo) __builtin_cheri_offset_get(foo)
# define csetoffset(a, b) __builtin_cheri_offset_set((a), (b))
# define cincoffset(a, b) __builtin_cheri_offset_increment((a), (b))
# define cgetaddr(a) __builtin_cheri_address_get(a)
# define csetaddr(a, b) __builtin_cheri_address_set((a), (b))
# define cgetbase(foo) __builtin_cheri_base_get(foo)
# define candperms(a, b) __builtin_cheri_perms_and((a), (b))
# define cseal(a, b) __builtin_cheri_seal((a), (b))
# ifdef FLUTE
# define cunseal(a, b) \
({ \
__auto_type __a = (a); \
__auto_type __b = (b); \
__auto_type __ret = __builtin_cheri_tag_clear(__a); \
if (__builtin_cheri_tag_get(__a) && \
__builtin_cheri_tag_get(__b) && \
__builtin_cheri_type_get(__a) && \
!__builtin_cheri_type_get(__b)) \
{ \
__auto_type __type = __builtin_cheri_type_get(__a); \
__auto_type __base = __builtin_cheri_base_get(__b); \
if ((__type >= __base) && \
(__type < \
(__base + __builtin_cheri_length_get(__b)))) \
{ \
__ret = __builtin_cheri_unseal((a), (b)); \
} \
} \
__ret; \
})
# else
# define cunseal(a, b) __builtin_cheri_unseal((a), (b))
# endif
# define csetbounds(a, b) __builtin_cheri_bounds_set((a), (b))
# define csetboundsext(a, b) __builtin_cheri_bounds_set_exact((a), (b))
# define ccheckperms(a, b) __builtin_cheri_perms_check((a), (b))
# define cchecktype(a, b) __builtin_cheri_type_check((a), (b))
# define cbuildcap(a, b) __builtin_cheri_cap_build((a), (b))
# define ccopytype(a, b) __builtin_cheri_cap_type_copy((a), (b))
# define ccseal(a, b) __builtin_cheri_conditional_seal((a), (b))
# define cequalexact(a, b) __builtin_cheri_equal_exact((a), (b))
static inline size_t ctestsubset(void *a, void *b)
{
size_t val;
__asm volatile("ctestsubset %0, %1, %2 " : "=r"(val) : "C"(a), "C"(b));
return val;
}
static inline size_t creplenalignmask(size_t len)
{
size_t ret;
__asm volatile("cram %0, %1" : "=r"(ret) : "r"(len));
return ret;
}
static inline size_t croundreplen(size_t len)
{
size_t ret;
__asm volatile("crrl %0, %1" : "=r"(ret) : "r"(len));
return ret;
}
# define cspecial_write(csr, val) \
({ __asm __volatile("cspecialw " #csr ", %0" ::"C"(val)); })
# define cspecial_read(csr) \
({ \
void *val; \
__asm __volatile("cspecialr %0, " #csr : "=C"(val)); \
val; \
})
# endif // __ASSEMBLER__
#endif
#endif // _CHERI_BUILTINS_