Files
xen/tools/include/xen-tools/common-macros.h
T
Roger Pau Monne 188d530529 xen/numa: fix setup of non-aligned memory affinity ranges
The logic to populate memnodemap in populate_memnodemap() assumes that all
ranges are aligned to the hash shift, this however is only true for the
first address in a memory affinity node.  Any subsequent ranges belonging
to the same node might not be aligned to the hash shift value.

Such lack of alignment causes issues to the logic in populate_memnodemap(),
as then the tail of the range might not be properly accounted for and setup
in memnodemap.  Fix this by forcing the start address of all regions to
be aligned to the hash shift; if such alignment causes a region overlap it
would always be between regions on the same node, and hence will never
cause setup issues of the memnodemap array.

Introduce two additional test cases to the user-space NUMA setup unit
testing, first test case is the native memory affinity and memory map of
the system where this issue was found, second test case is a simplification
to demonstrate the original problem more clearly.

Fixes: 1666086b00 ("x86/NUMA: improve memnode_shift calculation for multi node system")
Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
Release-Acked-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
2026-06-05 19:13:47 +02:00

119 lines
3.5 KiB
C

#ifndef __XEN_TOOLS_COMMON_MACROS__
#define __XEN_TOOLS_COMMON_MACROS__
/*
* Caution:
*
* This header must be completely self-contained. There are no external
* references to variables or functions allowed, as the file might be included
* for different runtime environments, such as firmware or target and build
* host programs.
*/
#ifndef BUILD_BUG_ON
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
#define BUILD_BUG_ON(p) ({ _Static_assert(!(p), "!(" #p ")"); })
#else
#define BUILD_BUG_ON(p) ((void)sizeof(char[1 - 2 * !!(p)]))
#endif
#endif
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*a))
#endif
#ifndef MAX
#define MAX(x, y) ((x) > (y) ? (x) : (y))
#endif
#ifndef MIN
#define MIN(x, y) ((x) < (y) ? (x) : (y))
#endif
#ifndef min
#define min(x, y) \
({ \
const typeof(x) _x = (x); \
const typeof(y) _y = (y); \
(void) (&_x == &_y); \
(_x < _y) ? _x : _y; \
})
#endif
#ifndef max
#define max(x, y) \
({ \
const typeof(x) _x = (x); \
const typeof(y) _y = (y); \
(void)(&_x == &_y); \
(_x > _y) ? _x : _y; \
})
#endif
#ifndef min_t
#define min_t(type, x, y) \
({ \
const type _x = (x); \
const type _y = (y); \
(_x < _y) ? _x: _y; \
})
#endif
#ifndef max_t
#define max_t(type, x, y) \
({ \
const type _x = (x); \
const type _y = (y); \
(_x > _y) ? _x: _y; \
})
#endif
#define ROUNDUP(x, a) (((x) + (a) - 1) & ~((a) - 1))
#define ROUNDDOWN(x, a) ((x) & ~((a) - 1))
#define MASK_EXTR(v, m) (((v) & (m)) / ((m) & -(m)))
#define MASK_INSR(v, m) (((v) * ((m) & -(m))) & (m))
#ifndef __must_check
#define __must_check __attribute__((__warn_unused_result__))
#endif
#ifndef __packed
#define __packed __attribute__((__packed__))
#endif
#define sizeof_field(type, member) sizeof(((type *)NULL)->member)
#define endof_field(type, member) \
(offsetof(type, member) + sizeof_field(type, member))
#define container_of(ptr, type, member) ({ \
typeof(((type *)0)->member) *mptr__ = (ptr); \
(type *)((char *)mptr__ - offsetof(type, member)); \
})
#define __STR(...) #__VA_ARGS__
#define STR(...) __STR(__VA_ARGS__)
#define __AC(X, Y) (X ## Y)
#define _AC(X, Y) __AC(X, Y)
/* Size macros. */
#define MB(_mb) (_AC(_mb, ULL) << 20)
#define GB(_gb) (_AC(_gb, ULL) << 30)
#define get_unaligned_t(type, ptr) ({ \
const struct { type x; } __packed *ptr_ = (typeof(ptr_))(ptr); \
ptr_->x; \
})
#define put_unaligned_t(type, val, ptr) do { \
struct { type x; } __packed *ptr_ = (typeof(ptr_))(ptr); \
ptr_->x = (val); \
} while (0)
#define get_unaligned(ptr) get_unaligned_t(typeof(*(ptr)), ptr)
#define put_unaligned(val, ptr) put_unaligned_t(typeof(*(ptr)), val, ptr)
#endif /* __XEN_TOOLS_COMMON_MACROS__ */