blob: 267f8b13b4049fe7647d20165edee234013750f2 [file] [log] [blame]
/*
* SPDX-License-Identifier: BSD-3-Clause
* SPDX-FileCopyrightText: Copyright TF-RMM Contributors.
* SPDX-FileCopyrightText: Copyright NVIDIA Corporation.
*/
#ifndef UTILS_DEF_H
#define UTILS_DEF_H
#if !(defined(__ASSEMBLER__) || defined(__LINKER__))
#include <stdint.h>
#endif
/*
* For those constants to be shared between C and other sources, apply a 'U',
* 'UL', 'ULL', 'L' or 'LL' suffix to the argument only in C, to avoid
* undefined or unintended behaviour.
*
* The GNU assembler and linker do not support these suffixes (it causes the
* build process to fail) therefore the suffix is omitted when used in linker
* scripts and assembler files.
*/
#if defined(__ASSEMBLER__) || defined(__LINKER__)
# define U(_x) (_x)
# define UL(_x) (_x)
# define ULL(_x) (_x)
# define L(_x) (_x)
# define LL(_x) (_x)
#else
# define U_(_x) (_x##U)
# define U(_x) U_(_x)
# define UL(_x) (_x##UL)
# define ULL(_x) (_x##ULL)
# define L(_x) (_x##L)
# define LL(_x) (_x##LL)
#endif /* __ASSEMBLER__ */
/* Short forms for commonly used attributes */
#define __dead2 __attribute__((__noreturn__))
#define __deprecated __attribute__((__deprecated__))
#define __packed __attribute__((__packed__))
#define __used __attribute__((__used__))
#define __unused __attribute__((__unused__))
#define __aligned(x) __attribute__((__aligned__(x)))
#define __section(x) __attribute__((__section__(x)))
#define __printflike(fmtarg, firstvararg) \
__attribute__((__format__ (__printf__, fmtarg, firstvararg)))
/*
* The round_up() macro rounds up a value to the given boundary in a
* type-agnostic yet type-safe manner. The boundary must be a power of two.
* In other words, it computes the smallest multiple of boundary which is
* greater than or equal to value.
*
* round_down() is similar but rounds the value down instead.
*/
#define round_boundary(value, boundary) \
((__typeof__(value))((boundary) - 1))
#define round_up(value, boundary) \
((((value) - 1) | round_boundary(value, boundary)) + 1)
#define round_down(value, boundary) \
((value) & ~round_boundary(value, boundary))
/* Compute the number of elements in the given array */
#define ARRAY_SIZE(a) \
(sizeof(a) / sizeof((a)[0]))
#define ARRAY_LEN(_a) \
((sizeof(_a) / sizeof(_a[0])) + CHECK_TYPE_IS_ARRAY(_a))
/*
* Macro checks types of array and variable/value to write
* and reports compilation error if they mismatch.
*/
#define CHECK_ARRAY_TYPE(_a, _v) \
_Static_assert(__builtin_types_compatible_p(typeof(_a[0]), typeof(_v)), \
"array type mismatch")
/*
* Array read/write macros with boundary and types checks
* _a: name of array
* _i: index
* _v: variable/value to write
*/
#define SAFE_ARRAY_READ(_a, _i, _v) \
({ \
CHECK_ARRAY_TYPE(_a, _v); \
if (_i >= ARRAY_SIZE(_a)) { \
panic(); \
} \
_v = _a[_i]; \
})
#define SAFE_ARRAY_WRITE(_a, _i, _v) \
({ \
CHECK_ARRAY_TYPE(_a, _v); \
if (_i >= ARRAY_SIZE(_a)) { \
panic(); \
} \
_a[_i] = _v; \
})
#define COMPILER_ASSERT(_condition) \
extern char compiler_assert[(_condition) ? 1 : -1]
/*
* If _expr is false, this will result in a compile time error as it tries to
* define a bitfield of size -1 in that case. Otherwise, it will define a
* bitfield of size 0, which is valid, and not create a compiler warning.
*
* The return value is only relevant when the compilation succeeds, and by
* subtracting the size of the same struct, this should always return 0 as a
* value and can be included in other expressions.
*/
#define COMPILER_ASSERT_ZERO(_expr) (sizeof(struct { char: (-!(_expr)); }) \
- sizeof(struct { char: 0; }))
#define CHECK_TYPE_IS_ARRAY(_v) \
COMPILER_ASSERT_ZERO(!__builtin_types_compatible_p(typeof(_v), \
typeof(&(_v[0]))))
#define IS_POWER_OF_TWO(x) \
((((x) + UL(0)) & ((x) - UL(1))) == UL(0))
#define COMPILER_BARRIER() __asm__ volatile ("" ::: "memory")
#define ALIGNED(_size, _alignment) \
(((unsigned long)(_size) % (_alignment)) == UL(0))
#define GRANULE_ALIGNED(_addr) ALIGNED((void *)(_addr), GRANULE_SIZE)
#define ALIGNED_TO_ARRAY(_addr, _array) \
(((uintptr_t)_addr >= (uintptr_t)&_array[0]) && \
((((uintptr_t)_addr - (uintptr_t)&_array[0]) % \
sizeof(_array[0])) == UL(0)))
#define GRANULE_SHIFT (U(12))
#define GRANULE_MASK (~0xfffUL)
#define HAS_MPAM 0
#if HAS_MPAM
#define MPAM(_x...) _x
#else
#define MPAM(_x...)
#endif
#define HAS_SPE 0
#if HAS_SPE
#define SPE(_x...) _x
#else
#define SPE(_x...)
#endif
#if !(defined(__ASSEMBLER__) || defined(__LINKER__))
/*
* System register field definitions.
*
* For any register field we define:
* - <register>_<field>_SHIFT
* The bit offset of the LSB of the field.
* - <register>_<field>_WIDTH
* The width of the field in bits.
*
* For single bit fields, we define:
* - <register>_<field>_BIT
* The in-place value of the field with the bit set.
*
* For multi-bit fields, we define:
* - <register>_<field>_<enum>
* The in-place value of the field set to the value corresponding to the
* enumeration name.
*
* For any register field, we define:
* - INPLACE(<register>_<field>, val)
* The in-place value of the field set to val, handling any necessary type
* promotion to avoid truncation of val.
* - MASK(<register>_<field)
* An in-place bitmask covering all bits of the field.
* - EXTRACT(<register_field> <register_value>)
* A macro to extract the value of a register field shifted down so the
* value can be evaluated directly.
* - EXTRACT_BIT(<register_field> <register_value>)
* A macro to extract the value of a register bit shifted down so the
* value can be evaluated directly.
*/
#define INPLACE(regfield, val) \
(((val) + UL(0)) << (regfield##_SHIFT))
#define MASK(regfield) \
((~0UL >> (64UL - (regfield##_WIDTH))) << (regfield##_SHIFT))
#define EXTRACT(regfield, reg) \
(((reg) & MASK(regfield)) >> (regfield##_SHIFT))
#define EXTRACT_BIT(regfield, reg) \
(((reg) >> (regfield##_SHIFT)) & UL(1))
/*
* Generates an unsigned long long (64-bit) value where the bits @_msb
* through @_lsb (inclusive) are set to one and all other bits are zero. The
* parameters can hold values from 0 through 63 and if _msb == _lsb a single
* bit is set at that location.
*/
#define BIT_MASK_ULL(_msb, _lsb) \
((~ULL(0) >> (63UL - (_msb))) & (~ULL(0) << (_lsb)))
/*
* Stringify the result of expansion of a macro argument
*/
#ifndef __XSTRING
#define __STRING(x) #x
#define __XSTRING(x) __STRING(x)
#endif
/*
* Defines member of structure and reserves space
* for the next member with specified offset.
*/
#define SET_MEMBER(member, start, end) \
union { \
member; \
unsigned char reserved##end[(end) - (start)]; \
}
#define FALLTHROUGH __attribute__((fallthrough))
#endif /* !(defined(__ASSEMBLER__) || defined(__LINKER__)) */
#endif /* UTILS_DEF_H */