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

bitset.c (22780B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2
      3#include <linux/ethtool_netlink.h>
      4#include <linux/bitmap.h>
      5#include "netlink.h"
      6#include "bitset.h"
      7
      8/* Some bitmaps are internally represented as an array of unsigned long, some
      9 * as an array of u32 (some even as single u32 for now). To avoid the need of
     10 * wrappers on caller side, we provide two set of functions: those with "32"
     11 * suffix in their names expect u32 based bitmaps, those without it expect
     12 * unsigned long bitmaps.
     13 */
     14
     15static u32 ethnl_lower_bits(unsigned int n)
     16{
     17	return ~(u32)0 >> (32 - n % 32);
     18}
     19
     20static u32 ethnl_upper_bits(unsigned int n)
     21{
     22	return ~(u32)0 << (n % 32);
     23}
     24
     25/**
     26 * ethnl_bitmap32_clear() - Clear u32 based bitmap
     27 * @dst:   bitmap to clear
     28 * @start: beginning of the interval
     29 * @end:   end of the interval
     30 * @mod:   set if bitmap was modified
     31 *
     32 * Clear @nbits bits of a bitmap with indices @start <= i < @end
     33 */
     34static void ethnl_bitmap32_clear(u32 *dst, unsigned int start, unsigned int end,
     35				 bool *mod)
     36{
     37	unsigned int start_word = start / 32;
     38	unsigned int end_word = end / 32;
     39	unsigned int i;
     40	u32 mask;
     41
     42	if (end <= start)
     43		return;
     44
     45	if (start % 32) {
     46		mask = ethnl_upper_bits(start);
     47		if (end_word == start_word) {
     48			mask &= ethnl_lower_bits(end);
     49			if (dst[start_word] & mask) {
     50				dst[start_word] &= ~mask;
     51				*mod = true;
     52			}
     53			return;
     54		}
     55		if (dst[start_word] & mask) {
     56			dst[start_word] &= ~mask;
     57			*mod = true;
     58		}
     59		start_word++;
     60	}
     61
     62	for (i = start_word; i < end_word; i++) {
     63		if (dst[i]) {
     64			dst[i] = 0;
     65			*mod = true;
     66		}
     67	}
     68	if (end % 32) {
     69		mask = ethnl_lower_bits(end);
     70		if (dst[end_word] & mask) {
     71			dst[end_word] &= ~mask;
     72			*mod = true;
     73		}
     74	}
     75}
     76
     77/**
     78 * ethnl_bitmap32_not_zero() - Check if any bit is set in an interval
     79 * @map:   bitmap to test
     80 * @start: beginning of the interval
     81 * @end:   end of the interval
     82 *
     83 * Return: true if there is non-zero bit with  index @start <= i < @end,
     84 *         false if the whole interval is zero
     85 */
     86static bool ethnl_bitmap32_not_zero(const u32 *map, unsigned int start,
     87				    unsigned int end)
     88{
     89	unsigned int start_word = start / 32;
     90	unsigned int end_word = end / 32;
     91	u32 mask;
     92
     93	if (end <= start)
     94		return true;
     95
     96	if (start % 32) {
     97		mask = ethnl_upper_bits(start);
     98		if (end_word == start_word) {
     99			mask &= ethnl_lower_bits(end);
    100			return map[start_word] & mask;
    101		}
    102		if (map[start_word] & mask)
    103			return true;
    104		start_word++;
    105	}
    106
    107	if (!memchr_inv(map + start_word, '\0',
    108			(end_word - start_word) * sizeof(u32)))
    109		return true;
    110	if (end % 32 == 0)
    111		return true;
    112	return map[end_word] & ethnl_lower_bits(end);
    113}
    114
    115/**
    116 * ethnl_bitmap32_update() - Modify u32 based bitmap according to value/mask
    117 *			     pair
    118 * @dst:   bitmap to update
    119 * @nbits: bit size of the bitmap
    120 * @value: values to set
    121 * @mask:  mask of bits to set
    122 * @mod:   set to true if bitmap is modified, preserve if not
    123 *
    124 * Set bits in @dst bitmap which are set in @mask to values from @value, leave
    125 * the rest untouched. If destination bitmap was modified, set @mod to true,
    126 * leave as it is if not.
    127 */
    128static void ethnl_bitmap32_update(u32 *dst, unsigned int nbits,
    129				  const u32 *value, const u32 *mask, bool *mod)
    130{
    131	while (nbits > 0) {
    132		u32 real_mask = mask ? *mask : ~(u32)0;
    133		u32 new_value;
    134
    135		if (nbits < 32)
    136			real_mask &= ethnl_lower_bits(nbits);
    137		new_value = (*dst & ~real_mask) | (*value & real_mask);
    138		if (new_value != *dst) {
    139			*dst = new_value;
    140			*mod = true;
    141		}
    142
    143		if (nbits <= 32)
    144			break;
    145		dst++;
    146		nbits -= 32;
    147		value++;
    148		if (mask)
    149			mask++;
    150	}
    151}
    152
    153static bool ethnl_bitmap32_test_bit(const u32 *map, unsigned int index)
    154{
    155	return map[index / 32] & (1U << (index % 32));
    156}
    157
    158/**
    159 * ethnl_bitset32_size() - Calculate size of bitset nested attribute
    160 * @val:     value bitmap (u32 based)
    161 * @mask:    mask bitmap (u32 based, optional)
    162 * @nbits:   bit length of the bitset
    163 * @names:   array of bit names (optional)
    164 * @compact: assume compact format for output
    165 *
    166 * Estimate length of netlink attribute composed by a later call to
    167 * ethnl_put_bitset32() call with the same arguments.
    168 *
    169 * Return: negative error code or attribute length estimate
    170 */
    171int ethnl_bitset32_size(const u32 *val, const u32 *mask, unsigned int nbits,
    172			ethnl_string_array_t names, bool compact)
    173{
    174	unsigned int len = 0;
    175
    176	/* list flag */
    177	if (!mask)
    178		len += nla_total_size(sizeof(u32));
    179	/* size */
    180	len += nla_total_size(sizeof(u32));
    181
    182	if (compact) {
    183		unsigned int nwords = DIV_ROUND_UP(nbits, 32);
    184
    185		/* value, mask */
    186		len += (mask ? 2 : 1) * nla_total_size(nwords * sizeof(u32));
    187	} else {
    188		unsigned int bits_len = 0;
    189		unsigned int bit_len, i;
    190
    191		for (i = 0; i < nbits; i++) {
    192			const char *name = names ? names[i] : NULL;
    193
    194			if (!ethnl_bitmap32_test_bit(mask ?: val, i))
    195				continue;
    196			/* index */
    197			bit_len = nla_total_size(sizeof(u32));
    198			/* name */
    199			if (name)
    200				bit_len += ethnl_strz_size(name);
    201			/* value */
    202			if (mask && ethnl_bitmap32_test_bit(val, i))
    203				bit_len += nla_total_size(0);
    204
    205			/* bit nest */
    206			bits_len += nla_total_size(bit_len);
    207		}
    208		/* bits nest */
    209		len += nla_total_size(bits_len);
    210	}
    211
    212	/* outermost nest */
    213	return nla_total_size(len);
    214}
    215
    216/**
    217 * ethnl_put_bitset32() - Put a bitset nest into a message
    218 * @skb:      skb with the message
    219 * @attrtype: attribute type for the bitset nest
    220 * @val:      value bitmap (u32 based)
    221 * @mask:     mask bitmap (u32 based, optional)
    222 * @nbits:    bit length of the bitset
    223 * @names:    array of bit names (optional)
    224 * @compact:  use compact format for the output
    225 *
    226 * Compose a nested attribute representing a bitset. If @mask is null, simple
    227 * bitmap (bit list) is created, if @mask is provided, represent a value/mask
    228 * pair. Bit names are only used in verbose mode and when provided by calller.
    229 *
    230 * Return: 0 on success, negative error value on error
    231 */
    232int ethnl_put_bitset32(struct sk_buff *skb, int attrtype, const u32 *val,
    233		       const u32 *mask, unsigned int nbits,
    234		       ethnl_string_array_t names, bool compact)
    235{
    236	struct nlattr *nest;
    237	struct nlattr *attr;
    238
    239	nest = nla_nest_start(skb, attrtype);
    240	if (!nest)
    241		return -EMSGSIZE;
    242
    243	if (!mask && nla_put_flag(skb, ETHTOOL_A_BITSET_NOMASK))
    244		goto nla_put_failure;
    245	if (nla_put_u32(skb, ETHTOOL_A_BITSET_SIZE, nbits))
    246		goto nla_put_failure;
    247	if (compact) {
    248		unsigned int nwords = DIV_ROUND_UP(nbits, 32);
    249		unsigned int nbytes = nwords * sizeof(u32);
    250		u32 *dst;
    251
    252		attr = nla_reserve(skb, ETHTOOL_A_BITSET_VALUE, nbytes);
    253		if (!attr)
    254			goto nla_put_failure;
    255		dst = nla_data(attr);
    256		memcpy(dst, val, nbytes);
    257		if (nbits % 32)
    258			dst[nwords - 1] &= ethnl_lower_bits(nbits);
    259
    260		if (mask) {
    261			attr = nla_reserve(skb, ETHTOOL_A_BITSET_MASK, nbytes);
    262			if (!attr)
    263				goto nla_put_failure;
    264			dst = nla_data(attr);
    265			memcpy(dst, mask, nbytes);
    266			if (nbits % 32)
    267				dst[nwords - 1] &= ethnl_lower_bits(nbits);
    268		}
    269	} else {
    270		struct nlattr *bits;
    271		unsigned int i;
    272
    273		bits = nla_nest_start(skb, ETHTOOL_A_BITSET_BITS);
    274		if (!bits)
    275			goto nla_put_failure;
    276		for (i = 0; i < nbits; i++) {
    277			const char *name = names ? names[i] : NULL;
    278
    279			if (!ethnl_bitmap32_test_bit(mask ?: val, i))
    280				continue;
    281			attr = nla_nest_start(skb, ETHTOOL_A_BITSET_BITS_BIT);
    282			if (!attr)
    283				goto nla_put_failure;
    284			if (nla_put_u32(skb, ETHTOOL_A_BITSET_BIT_INDEX, i))
    285				goto nla_put_failure;
    286			if (name &&
    287			    ethnl_put_strz(skb, ETHTOOL_A_BITSET_BIT_NAME, name))
    288				goto nla_put_failure;
    289			if (mask && ethnl_bitmap32_test_bit(val, i) &&
    290			    nla_put_flag(skb, ETHTOOL_A_BITSET_BIT_VALUE))
    291				goto nla_put_failure;
    292			nla_nest_end(skb, attr);
    293		}
    294		nla_nest_end(skb, bits);
    295	}
    296
    297	nla_nest_end(skb, nest);
    298	return 0;
    299
    300nla_put_failure:
    301	nla_nest_cancel(skb, nest);
    302	return -EMSGSIZE;
    303}
    304
    305static const struct nla_policy bitset_policy[] = {
    306	[ETHTOOL_A_BITSET_NOMASK]	= { .type = NLA_FLAG },
    307	[ETHTOOL_A_BITSET_SIZE]		= NLA_POLICY_MAX(NLA_U32,
    308							 ETHNL_MAX_BITSET_SIZE),
    309	[ETHTOOL_A_BITSET_BITS]		= { .type = NLA_NESTED },
    310	[ETHTOOL_A_BITSET_VALUE]	= { .type = NLA_BINARY },
    311	[ETHTOOL_A_BITSET_MASK]		= { .type = NLA_BINARY },
    312};
    313
    314static const struct nla_policy bit_policy[] = {
    315	[ETHTOOL_A_BITSET_BIT_INDEX]	= { .type = NLA_U32 },
    316	[ETHTOOL_A_BITSET_BIT_NAME]	= { .type = NLA_NUL_STRING },
    317	[ETHTOOL_A_BITSET_BIT_VALUE]	= { .type = NLA_FLAG },
    318};
    319
    320/**
    321 * ethnl_bitset_is_compact() - check if bitset attribute represents a compact
    322 *			       bitset
    323 * @bitset:  nested attribute representing a bitset
    324 * @compact: pointer for return value
    325 *
    326 * Return: 0 on success, negative error code on failure
    327 */
    328int ethnl_bitset_is_compact(const struct nlattr *bitset, bool *compact)
    329{
    330	struct nlattr *tb[ARRAY_SIZE(bitset_policy)];
    331	int ret;
    332
    333	ret = nla_parse_nested(tb, ARRAY_SIZE(bitset_policy) - 1, bitset,
    334			       bitset_policy, NULL);
    335	if (ret < 0)
    336		return ret;
    337
    338	if (tb[ETHTOOL_A_BITSET_BITS]) {
    339		if (tb[ETHTOOL_A_BITSET_VALUE] || tb[ETHTOOL_A_BITSET_MASK])
    340			return -EINVAL;
    341		*compact = false;
    342		return 0;
    343	}
    344	if (!tb[ETHTOOL_A_BITSET_SIZE] || !tb[ETHTOOL_A_BITSET_VALUE])
    345		return -EINVAL;
    346
    347	*compact = true;
    348	return 0;
    349}
    350
    351/**
    352 * ethnl_name_to_idx() - look up string index for a name
    353 * @names:   array of ETH_GSTRING_LEN sized strings
    354 * @n_names: number of strings in the array
    355 * @name:    name to look up
    356 *
    357 * Return: index of the string if found, -ENOENT if not found
    358 */
    359static int ethnl_name_to_idx(ethnl_string_array_t names, unsigned int n_names,
    360			     const char *name)
    361{
    362	unsigned int i;
    363
    364	if (!names)
    365		return -ENOENT;
    366
    367	for (i = 0; i < n_names; i++) {
    368		/* names[i] may not be null terminated */
    369		if (!strncmp(names[i], name, ETH_GSTRING_LEN) &&
    370		    strlen(name) <= ETH_GSTRING_LEN)
    371			return i;
    372	}
    373
    374	return -ENOENT;
    375}
    376
    377static int ethnl_parse_bit(unsigned int *index, bool *val, unsigned int nbits,
    378			   const struct nlattr *bit_attr, bool no_mask,
    379			   ethnl_string_array_t names,
    380			   struct netlink_ext_ack *extack)
    381{
    382	struct nlattr *tb[ARRAY_SIZE(bit_policy)];
    383	int ret, idx;
    384
    385	ret = nla_parse_nested(tb, ARRAY_SIZE(bit_policy) - 1, bit_attr,
    386			       bit_policy, extack);
    387	if (ret < 0)
    388		return ret;
    389
    390	if (tb[ETHTOOL_A_BITSET_BIT_INDEX]) {
    391		const char *name;
    392
    393		idx = nla_get_u32(tb[ETHTOOL_A_BITSET_BIT_INDEX]);
    394		if (idx >= nbits) {
    395			NL_SET_ERR_MSG_ATTR(extack,
    396					    tb[ETHTOOL_A_BITSET_BIT_INDEX],
    397					    "bit index too high");
    398			return -EOPNOTSUPP;
    399		}
    400		name = names ? names[idx] : NULL;
    401		if (tb[ETHTOOL_A_BITSET_BIT_NAME] && name &&
    402		    strncmp(nla_data(tb[ETHTOOL_A_BITSET_BIT_NAME]), name,
    403			    nla_len(tb[ETHTOOL_A_BITSET_BIT_NAME]))) {
    404			NL_SET_ERR_MSG_ATTR(extack, bit_attr,
    405					    "bit index and name mismatch");
    406			return -EINVAL;
    407		}
    408	} else if (tb[ETHTOOL_A_BITSET_BIT_NAME]) {
    409		idx = ethnl_name_to_idx(names, nbits,
    410					nla_data(tb[ETHTOOL_A_BITSET_BIT_NAME]));
    411		if (idx < 0) {
    412			NL_SET_ERR_MSG_ATTR(extack,
    413					    tb[ETHTOOL_A_BITSET_BIT_NAME],
    414					    "bit name not found");
    415			return -EOPNOTSUPP;
    416		}
    417	} else {
    418		NL_SET_ERR_MSG_ATTR(extack, bit_attr,
    419				    "neither bit index nor name specified");
    420		return -EINVAL;
    421	}
    422
    423	*index = idx;
    424	*val = no_mask || tb[ETHTOOL_A_BITSET_BIT_VALUE];
    425	return 0;
    426}
    427
    428static int
    429ethnl_update_bitset32_verbose(u32 *bitmap, unsigned int nbits,
    430			      const struct nlattr *attr, struct nlattr **tb,
    431			      ethnl_string_array_t names,
    432			      struct netlink_ext_ack *extack, bool *mod)
    433{
    434	struct nlattr *bit_attr;
    435	bool no_mask;
    436	int rem;
    437	int ret;
    438
    439	if (tb[ETHTOOL_A_BITSET_VALUE]) {
    440		NL_SET_ERR_MSG_ATTR(extack, tb[ETHTOOL_A_BITSET_VALUE],
    441				    "value only allowed in compact bitset");
    442		return -EINVAL;
    443	}
    444	if (tb[ETHTOOL_A_BITSET_MASK]) {
    445		NL_SET_ERR_MSG_ATTR(extack, tb[ETHTOOL_A_BITSET_MASK],
    446				    "mask only allowed in compact bitset");
    447		return -EINVAL;
    448	}
    449
    450	no_mask = tb[ETHTOOL_A_BITSET_NOMASK];
    451	if (no_mask)
    452		ethnl_bitmap32_clear(bitmap, 0, nbits, mod);
    453
    454	nla_for_each_nested(bit_attr, tb[ETHTOOL_A_BITSET_BITS], rem) {
    455		bool old_val, new_val;
    456		unsigned int idx;
    457
    458		if (nla_type(bit_attr) != ETHTOOL_A_BITSET_BITS_BIT) {
    459			NL_SET_ERR_MSG_ATTR(extack, bit_attr,
    460					    "only ETHTOOL_A_BITSET_BITS_BIT allowed in ETHTOOL_A_BITSET_BITS");
    461			return -EINVAL;
    462		}
    463		ret = ethnl_parse_bit(&idx, &new_val, nbits, bit_attr, no_mask,
    464				      names, extack);
    465		if (ret < 0)
    466			return ret;
    467		old_val = bitmap[idx / 32] & ((u32)1 << (idx % 32));
    468		if (new_val != old_val) {
    469			if (new_val)
    470				bitmap[idx / 32] |= ((u32)1 << (idx % 32));
    471			else
    472				bitmap[idx / 32] &= ~((u32)1 << (idx % 32));
    473			*mod = true;
    474		}
    475	}
    476
    477	return 0;
    478}
    479
    480static int ethnl_compact_sanity_checks(unsigned int nbits,
    481				       const struct nlattr *nest,
    482				       struct nlattr **tb,
    483				       struct netlink_ext_ack *extack)
    484{
    485	bool no_mask = tb[ETHTOOL_A_BITSET_NOMASK];
    486	unsigned int attr_nbits, attr_nwords;
    487	const struct nlattr *test_attr;
    488
    489	if (no_mask && tb[ETHTOOL_A_BITSET_MASK]) {
    490		NL_SET_ERR_MSG_ATTR(extack, tb[ETHTOOL_A_BITSET_MASK],
    491				    "mask not allowed in list bitset");
    492		return -EINVAL;
    493	}
    494	if (!tb[ETHTOOL_A_BITSET_SIZE]) {
    495		NL_SET_ERR_MSG_ATTR(extack, nest,
    496				    "missing size in compact bitset");
    497		return -EINVAL;
    498	}
    499	if (!tb[ETHTOOL_A_BITSET_VALUE]) {
    500		NL_SET_ERR_MSG_ATTR(extack, nest,
    501				    "missing value in compact bitset");
    502		return -EINVAL;
    503	}
    504	if (!no_mask && !tb[ETHTOOL_A_BITSET_MASK]) {
    505		NL_SET_ERR_MSG_ATTR(extack, nest,
    506				    "missing mask in compact nonlist bitset");
    507		return -EINVAL;
    508	}
    509
    510	attr_nbits = nla_get_u32(tb[ETHTOOL_A_BITSET_SIZE]);
    511	attr_nwords = DIV_ROUND_UP(attr_nbits, 32);
    512	if (nla_len(tb[ETHTOOL_A_BITSET_VALUE]) != attr_nwords * sizeof(u32)) {
    513		NL_SET_ERR_MSG_ATTR(extack, tb[ETHTOOL_A_BITSET_VALUE],
    514				    "bitset value length does not match size");
    515		return -EINVAL;
    516	}
    517	if (tb[ETHTOOL_A_BITSET_MASK] &&
    518	    nla_len(tb[ETHTOOL_A_BITSET_MASK]) != attr_nwords * sizeof(u32)) {
    519		NL_SET_ERR_MSG_ATTR(extack, tb[ETHTOOL_A_BITSET_MASK],
    520				    "bitset mask length does not match size");
    521		return -EINVAL;
    522	}
    523	if (attr_nbits <= nbits)
    524		return 0;
    525
    526	test_attr = no_mask ? tb[ETHTOOL_A_BITSET_VALUE] :
    527			      tb[ETHTOOL_A_BITSET_MASK];
    528	if (ethnl_bitmap32_not_zero(nla_data(test_attr), nbits, attr_nbits)) {
    529		NL_SET_ERR_MSG_ATTR(extack, test_attr,
    530				    "cannot modify bits past kernel bitset size");
    531		return -EINVAL;
    532	}
    533	return 0;
    534}
    535
    536/**
    537 * ethnl_update_bitset32() - Apply a bitset nest to a u32 based bitmap
    538 * @bitmap:  bitmap to update
    539 * @nbits:   size of the updated bitmap in bits
    540 * @attr:    nest attribute to parse and apply
    541 * @names:   array of bit names; may be null for compact format
    542 * @extack:  extack for error reporting
    543 * @mod:     set this to true if bitmap is modified, leave as it is if not
    544 *
    545 * Apply bitset netsted attribute to a bitmap. If the attribute represents
    546 * a bit list, @bitmap is set to its contents; otherwise, bits in mask are
    547 * set to values from value. Bitmaps in the attribute may be longer than
    548 * @nbits but the message must not request modifying any bits past @nbits.
    549 *
    550 * Return: negative error code on failure, 0 on success
    551 */
    552int ethnl_update_bitset32(u32 *bitmap, unsigned int nbits,
    553			  const struct nlattr *attr, ethnl_string_array_t names,
    554			  struct netlink_ext_ack *extack, bool *mod)
    555{
    556	struct nlattr *tb[ARRAY_SIZE(bitset_policy)];
    557	unsigned int change_bits;
    558	bool no_mask;
    559	int ret;
    560
    561	if (!attr)
    562		return 0;
    563	ret = nla_parse_nested(tb, ARRAY_SIZE(bitset_policy) - 1, attr,
    564			       bitset_policy, extack);
    565	if (ret < 0)
    566		return ret;
    567
    568	if (tb[ETHTOOL_A_BITSET_BITS])
    569		return ethnl_update_bitset32_verbose(bitmap, nbits, attr, tb,
    570						     names, extack, mod);
    571	ret = ethnl_compact_sanity_checks(nbits, attr, tb, extack);
    572	if (ret < 0)
    573		return ret;
    574
    575	no_mask = tb[ETHTOOL_A_BITSET_NOMASK];
    576	change_bits = min_t(unsigned int,
    577			    nla_get_u32(tb[ETHTOOL_A_BITSET_SIZE]), nbits);
    578	ethnl_bitmap32_update(bitmap, change_bits,
    579			      nla_data(tb[ETHTOOL_A_BITSET_VALUE]),
    580			      no_mask ? NULL :
    581					nla_data(tb[ETHTOOL_A_BITSET_MASK]),
    582			      mod);
    583	if (no_mask && change_bits < nbits)
    584		ethnl_bitmap32_clear(bitmap, change_bits, nbits, mod);
    585
    586	return 0;
    587}
    588
    589/**
    590 * ethnl_parse_bitset() - Compute effective value and mask from bitset nest
    591 * @val:     unsigned long based bitmap to put value into
    592 * @mask:    unsigned long based bitmap to put mask into
    593 * @nbits:   size of @val and @mask bitmaps
    594 * @attr:    nest attribute to parse and apply
    595 * @names:   array of bit names; may be null for compact format
    596 * @extack:  extack for error reporting
    597 *
    598 * Provide @nbits size long bitmaps for value and mask so that
    599 * x = (val & mask) | (x & ~mask) would modify any @nbits sized bitmap x
    600 * the same way ethnl_update_bitset() with the same bitset attribute would.
    601 *
    602 * Return:   negative error code on failure, 0 on success
    603 */
    604int ethnl_parse_bitset(unsigned long *val, unsigned long *mask,
    605		       unsigned int nbits, const struct nlattr *attr,
    606		       ethnl_string_array_t names,
    607		       struct netlink_ext_ack *extack)
    608{
    609	struct nlattr *tb[ARRAY_SIZE(bitset_policy)];
    610	const struct nlattr *bit_attr;
    611	bool no_mask;
    612	int rem;
    613	int ret;
    614
    615	if (!attr)
    616		return 0;
    617	ret = nla_parse_nested(tb, ARRAY_SIZE(bitset_policy) - 1, attr,
    618			       bitset_policy, extack);
    619	if (ret < 0)
    620		return ret;
    621	no_mask = tb[ETHTOOL_A_BITSET_NOMASK];
    622
    623	if (!tb[ETHTOOL_A_BITSET_BITS]) {
    624		unsigned int change_bits;
    625
    626		ret = ethnl_compact_sanity_checks(nbits, attr, tb, extack);
    627		if (ret < 0)
    628			return ret;
    629
    630		change_bits = nla_get_u32(tb[ETHTOOL_A_BITSET_SIZE]);
    631		if (change_bits > nbits)
    632			change_bits = nbits;
    633		bitmap_from_arr32(val, nla_data(tb[ETHTOOL_A_BITSET_VALUE]),
    634				  change_bits);
    635		if (change_bits < nbits)
    636			bitmap_clear(val, change_bits, nbits - change_bits);
    637		if (no_mask) {
    638			bitmap_fill(mask, nbits);
    639		} else {
    640			bitmap_from_arr32(mask,
    641					  nla_data(tb[ETHTOOL_A_BITSET_MASK]),
    642					  change_bits);
    643			if (change_bits < nbits)
    644				bitmap_clear(mask, change_bits,
    645					     nbits - change_bits);
    646		}
    647
    648		return 0;
    649	}
    650
    651	if (tb[ETHTOOL_A_BITSET_VALUE]) {
    652		NL_SET_ERR_MSG_ATTR(extack, tb[ETHTOOL_A_BITSET_VALUE],
    653				    "value only allowed in compact bitset");
    654		return -EINVAL;
    655	}
    656	if (tb[ETHTOOL_A_BITSET_MASK]) {
    657		NL_SET_ERR_MSG_ATTR(extack, tb[ETHTOOL_A_BITSET_MASK],
    658				    "mask only allowed in compact bitset");
    659		return -EINVAL;
    660	}
    661
    662	bitmap_zero(val, nbits);
    663	if (no_mask)
    664		bitmap_fill(mask, nbits);
    665	else
    666		bitmap_zero(mask, nbits);
    667
    668	nla_for_each_nested(bit_attr, tb[ETHTOOL_A_BITSET_BITS], rem) {
    669		unsigned int idx;
    670		bool bit_val;
    671
    672		ret = ethnl_parse_bit(&idx, &bit_val, nbits, bit_attr, no_mask,
    673				      names, extack);
    674		if (ret < 0)
    675			return ret;
    676		if (bit_val)
    677			__set_bit(idx, val);
    678		if (!no_mask)
    679			__set_bit(idx, mask);
    680	}
    681
    682	return 0;
    683}
    684
    685#if BITS_PER_LONG == 64 && defined(__BIG_ENDIAN)
    686
    687/* 64-bit big endian architectures are the only case when u32 based bitmaps
    688 * and unsigned long based bitmaps have different memory layout so that we
    689 * cannot simply cast the latter to the former and need actual wrappers
    690 * converting the latter to the former.
    691 *
    692 * To reduce the number of slab allocations, the wrappers use fixed size local
    693 * variables for bitmaps up to ETHNL_SMALL_BITMAP_BITS bits which is the
    694 * majority of bitmaps used by ethtool.
    695 */
    696#define ETHNL_SMALL_BITMAP_BITS 128
    697#define ETHNL_SMALL_BITMAP_WORDS DIV_ROUND_UP(ETHNL_SMALL_BITMAP_BITS, 32)
    698
    699int ethnl_bitset_size(const unsigned long *val, const unsigned long *mask,
    700		      unsigned int nbits, ethnl_string_array_t names,
    701		      bool compact)
    702{
    703	u32 small_mask32[ETHNL_SMALL_BITMAP_WORDS];
    704	u32 small_val32[ETHNL_SMALL_BITMAP_WORDS];
    705	u32 *mask32;
    706	u32 *val32;
    707	int ret;
    708
    709	if (nbits > ETHNL_SMALL_BITMAP_BITS) {
    710		unsigned int nwords = DIV_ROUND_UP(nbits, 32);
    711
    712		val32 = kmalloc_array(2 * nwords, sizeof(u32), GFP_KERNEL);
    713		if (!val32)
    714			return -ENOMEM;
    715		mask32 = val32 + nwords;
    716	} else {
    717		val32 = small_val32;
    718		mask32 = small_mask32;
    719	}
    720
    721	bitmap_to_arr32(val32, val, nbits);
    722	if (mask)
    723		bitmap_to_arr32(mask32, mask, nbits);
    724	else
    725		mask32 = NULL;
    726	ret = ethnl_bitset32_size(val32, mask32, nbits, names, compact);
    727
    728	if (nbits > ETHNL_SMALL_BITMAP_BITS)
    729		kfree(val32);
    730
    731	return ret;
    732}
    733
    734int ethnl_put_bitset(struct sk_buff *skb, int attrtype,
    735		     const unsigned long *val, const unsigned long *mask,
    736		     unsigned int nbits, ethnl_string_array_t names,
    737		     bool compact)
    738{
    739	u32 small_mask32[ETHNL_SMALL_BITMAP_WORDS];
    740	u32 small_val32[ETHNL_SMALL_BITMAP_WORDS];
    741	u32 *mask32;
    742	u32 *val32;
    743	int ret;
    744
    745	if (nbits > ETHNL_SMALL_BITMAP_BITS) {
    746		unsigned int nwords = DIV_ROUND_UP(nbits, 32);
    747
    748		val32 = kmalloc_array(2 * nwords, sizeof(u32), GFP_KERNEL);
    749		if (!val32)
    750			return -ENOMEM;
    751		mask32 = val32 + nwords;
    752	} else {
    753		val32 = small_val32;
    754		mask32 = small_mask32;
    755	}
    756
    757	bitmap_to_arr32(val32, val, nbits);
    758	if (mask)
    759		bitmap_to_arr32(mask32, mask, nbits);
    760	else
    761		mask32 = NULL;
    762	ret = ethnl_put_bitset32(skb, attrtype, val32, mask32, nbits, names,
    763				 compact);
    764
    765	if (nbits > ETHNL_SMALL_BITMAP_BITS)
    766		kfree(val32);
    767
    768	return ret;
    769}
    770
    771int ethnl_update_bitset(unsigned long *bitmap, unsigned int nbits,
    772			const struct nlattr *attr, ethnl_string_array_t names,
    773			struct netlink_ext_ack *extack, bool *mod)
    774{
    775	u32 small_bitmap32[ETHNL_SMALL_BITMAP_WORDS];
    776	u32 *bitmap32 = small_bitmap32;
    777	bool u32_mod = false;
    778	int ret;
    779
    780	if (nbits > ETHNL_SMALL_BITMAP_BITS) {
    781		unsigned int dst_words = DIV_ROUND_UP(nbits, 32);
    782
    783		bitmap32 = kmalloc_array(dst_words, sizeof(u32), GFP_KERNEL);
    784		if (!bitmap32)
    785			return -ENOMEM;
    786	}
    787
    788	bitmap_to_arr32(bitmap32, bitmap, nbits);
    789	ret = ethnl_update_bitset32(bitmap32, nbits, attr, names, extack,
    790				    &u32_mod);
    791	if (u32_mod) {
    792		bitmap_from_arr32(bitmap, bitmap32, nbits);
    793		*mod = true;
    794	}
    795
    796	if (nbits > ETHNL_SMALL_BITMAP_BITS)
    797		kfree(bitmap32);
    798
    799	return ret;
    800}
    801
    802#else
    803
    804/* On little endian 64-bit and all 32-bit architectures, an unsigned long
    805 * based bitmap can be interpreted as u32 based one using a simple cast.
    806 */
    807
    808int ethnl_bitset_size(const unsigned long *val, const unsigned long *mask,
    809		      unsigned int nbits, ethnl_string_array_t names,
    810		      bool compact)
    811{
    812	return ethnl_bitset32_size((const u32 *)val, (const u32 *)mask, nbits,
    813				   names, compact);
    814}
    815
    816int ethnl_put_bitset(struct sk_buff *skb, int attrtype,
    817		     const unsigned long *val, const unsigned long *mask,
    818		     unsigned int nbits, ethnl_string_array_t names,
    819		     bool compact)
    820{
    821	return ethnl_put_bitset32(skb, attrtype, (const u32 *)val,
    822				  (const u32 *)mask, nbits, names, compact);
    823}
    824
    825int ethnl_update_bitset(unsigned long *bitmap, unsigned int nbits,
    826			const struct nlattr *attr, ethnl_string_array_t names,
    827			struct netlink_ext_ack *extack, bool *mod)
    828{
    829	return ethnl_update_bitset32((u32 *)bitmap, nbits, attr, names, extack,
    830				     mod);
    831}
    832
    833#endif /* BITS_PER_LONG == 64 && defined(__BIG_ENDIAN) */