Skip to contentSkip to conversation

Modify bitmap_set_value() to suppress compiler warning

PATCH In review Syed Nayyar Waris 3 participants 6 messages Dec 12, 2020 – Dec 13, 2020

Subsystems (6)
lore
Share & tools
lore
#0 lore raw

v2 cover Modify bitmap_set_value() to suppress compiler warning

Hi All,

The purpose of this patchset is to suppress the compiler warning (-Wtype-limits).

In function bitmap_set_value(), add explicit check to see if the value being written into the bitmap does not fall outside the bitmap.
The situation that it is falling outside is never possible in the code because the boundaries are required to be correct before the function is called. The responsibility is on the caller for ensuring the boundaries are correct.
The code change is simply to silence the GCC warning messages because GCC is not aware that the boundaries have already been checked. As such, we're better off using __builtin_unreachable() here because we can avoid the latency of the conditional check entirely.

Michal,
What do you think of [PATCH 2/2]? Is the conditional check needed, and also does returning -EINVAL look good?

Changes in v2:
- [Patch 1/2]: Squashed earlier three patches into one.

Syed Nayyar Waris (2):
bitmap: Modify bitmap_set_value() to check bitmap length
gpio: xilinx: Add extra check if sum of widths exceed 64

 drivers/gpio/gpio-xilinx.c | 18 ++++++++++++------
 include/linux/bitmap.h     | 35 +++++++++++++++++++++--------------
 lib/test_bitmap.c          |  4 ++--
 3 files changed, 35 insertions(+), 22 deletions(-)

base-commit: b640c4e12bbe1f0b6383c3ef788a89e5427c763f

Signature · 7 lines
2.29.0


_______________________________________________
linux-arm-kernel mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
#1 lore raw

PATCH v2 1/2 bitmap: Modify bitmap_set_value() to check bitmap length

Add explicit check to see if the value being written into the bitmap does not fall outside the bitmap.
The situation that it is falling outside would never be possible in the code because the boundaries are required to be correct before the function is called. The responsibility is on the caller for ensuring the boundaries are correct.
The code change is simply to silence the GCC warning messages because GCC is not aware that the boundaries have already been checked. As such, we're better off using __builtin_unreachable() here because we can avoid the latency of the conditional check entirely.

lib/test_bitmap.c: Modify for_each_set_clump test

Modify the test where bitmap_set_value() is called. bitmap_set_value() now takes an extra bitmap-width as second argument and the width of value is now present as the fourth argument.

gpio: xilinx: Modify bitmap_set_value() calls

Modify the bitmap_set_value() calls. bitmap_set_value() now takes an extra bitmap width as second argument and the width of value is now present as the fourth argument.

---
 drivers/gpio/gpio-xilinx.c | 12 ++++++------
 include/linux/bitmap.h     | 35 +++++++++++++++++++++--------------
 lib/test_bitmap.c          |  4 ++--
 3 files changed, 29 insertions(+), 22 deletions(-)
drivers/gpio/gpio-xilinx.c +6 -6
index ad4ee4145db4..05dae086c4d0 100644
@@ -151,16 +151,16 @@ static void xgpio_set_multiple(struct gpio_chip *gc, unsigned long *mask,
 	spin_lock_irqsave(&chip->gpio_lock[0], flags);
 	spin_lock(&chip->gpio_lock[1]);
 
-	bitmap_set_value(old, state[0], 0, width[0]);
-	bitmap_set_value(old, state[1], width[0], width[1]);
+	bitmap_set_value(old, 64, state[0], width[0], 0);
+	bitmap_set_value(old, 64, state[1], width[1], width[0]);
 	bitmap_replace(new, old, bits, mask, gc->ngpio);
 
-	bitmap_set_value(old, state[0], 0, 32);
-	bitmap_set_value(old, state[1], 32, 32);
+	bitmap_set_value(old, 64, state[0], 32, 0);
+	bitmap_set_value(old, 64, state[1], 32, 32);
 	state[0] = bitmap_get_value(new, 0, width[0]);
 	state[1] = bitmap_get_value(new, width[0], width[1]);
-	bitmap_set_value(new, state[0], 0, 32);
-	bitmap_set_value(new, state[1], 32, 32);
+	bitmap_set_value(new, 64, state[0], 32, 0);
+	bitmap_set_value(new, 64, state[1], 32, 32);
 	bitmap_xor(changed, old, new, 64);
 
 	if (((u32 *)changed)[0])
include/linux/bitmap.h +21 -14
index 386d08777342..efb6199ea1e7 100644
@@ -78,8 +78,9 @@
  *  bitmap_get_value(map, start, nbits)		Get bit value of size
  *                                              'nbits' from map at start
  *  bitmap_set_value8(map, value, start)        Set 8bit value to map at start
- *  bitmap_set_value(map, value, start, nbits)	Set bit value of size 'nbits'
- *                                              of map at start
+ *  bitmap_set_value(map, nbits, value, value_width, start)
+ *                                              Set bit value of size value_width
+ *                                              to map at start
  *
  * Note, bitmap_zero() and bitmap_fill() operate over the region of
  * unsigned longs, that is, bits behind bitmap till the unsigned long
@@ -610,30 +611,36 @@ static inline void bitmap_set_value8(unsigned long *map, unsigned long value,
 }
 
 /**
- * bitmap_set_value - set n-bit value within a memory region
+ * bitmap_set_value - set value within a memory region
  * @map: address to the bitmap memory region
- * @value: value of nbits
- * @start: bit offset of the n-bit value
- * @nbits: size of value in bits (must be between 1 and BITS_PER_LONG inclusive).
+ * @nbits: size of map in bits
+ * @value: value of clump
+ * @value_width: size of value in bits (must be between 1 and BITS_PER_LONG inclusive)
+ * @start: bit offset of the value
  */
-static inline void bitmap_set_value(unsigned long *map,
-				    unsigned long value,
-				    unsigned long start, unsigned long nbits)
+static inline void bitmap_set_value(unsigned long *map, unsigned long nbits,
+				    unsigned long value, unsigned long value_width,
+				    unsigned long start)
 {
-	const size_t index = BIT_WORD(start);
+	const unsigned long index = BIT_WORD(start);
+	const unsigned long length = BIT_WORD(nbits);
 	const unsigned long offset = start % BITS_PER_LONG;
 	const unsigned long ceiling = round_up(start + 1, BITS_PER_LONG);
 	const unsigned long space = ceiling - start;
 
-	value &= GENMASK(nbits - 1, 0);
+	value &= GENMASK(value_width - 1, 0);
 
-	if (space >= nbits) {
-		map[index] &= ~(GENMASK(nbits - 1, 0) << offset);
+	if (space >= value_width) {
+		map[index] &= ~(GENMASK(value_width - 1, 0) << offset);
 		map[index] |= value << offset;
 	} else {
 		map[index + 0] &= ~BITMAP_FIRST_WORD_MASK(start);
 		map[index + 0] |= value << offset;
-		map[index + 1] &= ~BITMAP_LAST_WORD_MASK(start + nbits);
+
+		if (index + 1 >= length)
+			__builtin_unreachable();
+
+		map[index + 1] &= ~BITMAP_LAST_WORD_MASK(start + value_width);
 		map[index + 1] |= value >> space;
 	}
 }
lib/test_bitmap.c +2 -2
index 1c5791ff02cb..7fafe6a0bc08 100644
@@ -656,8 +656,8 @@ static void __init prepare_test_data(unsigned int index)
 	unsigned long width = 0;
 
 	for (i = 0; i < clump_test_data[index].count; i++) {
-		bitmap_set_value(clump_test_data[index].data,
-			clump_bitmap_data[(clump_test_data[index].offset)++], width, 32);
+		bitmap_set_value(clump_test_data[index].data, 256,
+			clump_bitmap_data[(clump_test_data[index].offset)++], 32, width);
 		width += 32;
 	}
 }
Signature · 7 lines
2.29.0


_______________________________________________
linux-arm-kernel mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
#2 lore raw

Re: [PATCH v2 1/2] bitmap: Modify bitmap_set_value() to check bitmap length

I love your patch! Perhaps something to improve:

Hi Syed,

I love your patch! Perhaps something to improve:

[auto build test WARNING on b640c4e12bbe1f0b6383c3ef788a89e5427c763f]

url:    https://github.com/0day-ci/linux/commits/Syed-Nayyar-Waris/Modify-bitmap_set_value-to-suppress-compiler-warning/20201212-180653
base:    b640c4e12bbe1f0b6383c3ef788a89e5427c763f
config: x86_64-allyesconfig (attached as .config)
compiler: gcc-9 (Debian 9.3.0-15) 9.3.0
reproduce (this is a W=1 build):
        # https://github.com/0day-ci/linux/commit/2e22a418a9bc47b3ad67dcd531a7d46192c1f4d4
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Syed-Nayyar-Waris/Modify-bitmap_set_value-to-suppress-compiler-warning/20201212-180653
        git checkout 2e22a418a9bc47b3ad67dcd531a7d46192c1f4d4
        # save the attached .config to linux build tree
        make W=1 ARCH=x86_64 

If you fix the issue, kindly add following tag as appropriate

All warnings (new ones prefixed by >>):

>> drivers/gpio/gpio-xilinx.o: warning: objtool: .text.unlikely: unexpected end of section

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

#3 lore raw

Re: [PATCH v2 1/2] bitmap: Modify bitmap_set_value() to check bitmap length

In reply to Syed Nayyar Waris
I love your patch! Perhaps something to improve:

Hi Syed,

I love your patch! Perhaps something to improve:

[auto build test WARNING on b640c4e12bbe1f0b6383c3ef788a89e5427c763f]

url:    https://github.com/0day-ci/linux/commits/Syed-Nayyar-Waris/Modify-bitmap_set_value-to-suppress-compiler-warning/20201212-180653
base:    b640c4e12bbe1f0b6383c3ef788a89e5427c763f
config: x86_64-randconfig-a016-20201209 (attached as .config)
compiler: gcc-9 (Debian 9.3.0-15) 9.3.0
reproduce (this is a W=1 build):
        # https://github.com/0day-ci/linux/commit/2e22a418a9bc47b3ad67dcd531a7d46192c1f4d4
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Syed-Nayyar-Waris/Modify-bitmap_set_value-to-suppress-compiler-warning/20201212-180653
        git checkout 2e22a418a9bc47b3ad67dcd531a7d46192c1f4d4
        # save the attached .config to linux build tree
        make W=1 ARCH=x86_64 

If you fix the issue, kindly add following tag as appropriate

All warnings (new ones prefixed by >>):

>> drivers/gpio/gpio-xilinx.o: warning: objtool: bitmap_set_value.constprop.0() falls through to next function xgpio_set_multiple()

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

#4 lore raw

Re: [PATCH v2 1/2] bitmap: Modify bitmap_set_value() to check bitmap length

In reply to Syed Nayyar Waris
Quoted 24 lines · Syed Nayyar Waris

Add explicit check to see if the value being written into the bitmap does not fall outside the bitmap.
The situation that it is falling outside would never be possible in the code because the boundaries are required to be correct before the function is called. The responsibility is on the caller for ensuring the boundaries are correct.
The code change is simply to silence the GCC warning messages because GCC is not aware that the boundaries have already been checked. As such, we're better off using __builtin_unreachable() here because we can avoid the latency of the conditional check entirely.

lib/test_bitmap.c: Modify for_each_set_clump test

Modify the test where bitmap_set_value() is called. bitmap_set_value() now takes an extra bitmap-width as second argument and the width of value is now present as the fourth argument.

Quoted 8 lines

gpio: xilinx: Modify bitmap_set_value() calls

Modify the bitmap_set_value() calls. bitmap_set_value() now takes an extra bitmap width as second argument and the width of value is now present as the fourth argument.

Commit message here definitely needs more work.
First of all, it's now quite awkward to see this squashed stuff like this. Second, it misses the warning examples it's talking about. Third, it repeats some tags.
Fourth, it misses the Fixes tag.

Please, redone it correctly (one commit message with clear purpose and example of warnings followed by Fixes tag) and resend a v3.

You may mention in the cover letter that this is squashed of three patches from v1 (and give a link to lore.kernel.org).

Signature · 2 lines
With Best Regards,
Andy Shevchenko
#5 lore raw

PATCH v2 2/2 gpio: xilinx: Add extra check if sum of widths exceed 64

In reply to Syed Nayyar Waris

Add extra check to see if sum of widths does not exceed 64. If it exceeds then return -EINVAL alongwith appropriate error message.

---
 drivers/gpio/gpio-xilinx.c | 6 ++++++
 1 file changed, 6 insertions(+)
drivers/gpio/gpio-xilinx.c +6 -0
index 05dae086c4d0..a2e92a1cf50b 100644
@@ -340,6 +340,12 @@ static int xgpio_probe(struct platform_device *pdev)
 
 	chip->gc.base = -1;
 	chip->gc.ngpio = chip->gpio_width[0] + chip->gpio_width[1];
+
+	if (chip->gc.ngpio > 64) {
+		dev_err(&pdev->dev, "invalid configuration: number of GPIO is greater than 64");
+		return -EINVAL;
+	}
+
 	chip->gc.parent = &pdev->dev;
 	chip->gc.direction_input = xgpio_dir_in;
 	chip->gc.direction_output = xgpio_dir_out;
Signature · 7 lines
2.29.0


_______________________________________________
linux-arm-kernel mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel