tests: provide a word-at-a-time test implementation
Commit Message
Add some basic tests to test the correctness of has_zero() and
find_zero().
Signed-off-by: Sven Schnelle <svens@linux.ibm.com>
---
lib/Kconfig.debug | 11 +++++++
lib/Makefile | 1 +
lib/test_word-at-a-time.c | 62 +++++++++++++++++++++++++++++++++++++++
3 files changed, 74 insertions(+)
create mode 100644 lib/test_word-at-a-time.c
Comments
On Mon, Oct 09, 2023 at 02:04:55PM +0200, Sven Schnelle wrote:
> Add some basic tests to test the correctness of has_zero() and
> find_zero().
>
> Signed-off-by: Sven Schnelle <svens@linux.ibm.com>
Yay tests! :)
Reviewed-by: Kees Cook <keescook@chromium.org>
@@ -2791,6 +2791,17 @@ config SIPHASH_KUNIT_TEST
This is intended to help people writing architecture-specific
optimized versions. If unsure, say N.
+config WORDATATIME_KUNIT_TEST
+ tristate "KUnit test word-at-a-time implementation at runtime" if !KUNIT_ALL_TESTS
+ depends on KUNIT
+ default KUNIT_ALL_TESTS
+ help
+ Enable this option to test the kernel's word-at-a-time (<asm/word-at-a-time.h>)
+ functions on boot (or module load).
+
+ This is intended to help people writing architecture-specific
+ optimized versions. If unsure, say N.
+
config TEST_UDELAY
tristate "udelay test driver"
help
@@ -402,6 +402,7 @@ obj-$(CONFIG_FORTIFY_KUNIT_TEST) += fortify_kunit.o
obj-$(CONFIG_STRCAT_KUNIT_TEST) += strcat_kunit.o
obj-$(CONFIG_STRSCPY_KUNIT_TEST) += strscpy_kunit.o
obj-$(CONFIG_SIPHASH_KUNIT_TEST) += siphash_kunit.o
+obj-$(CONFIG_WORDATATIME_KUNIT_TEST) += test_word-at-a-time.o
obj-$(CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED) += devmem_is_allowed.o
new file mode 100644
@@ -0,0 +1,62 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#include <linux/module.h>
+#include <linux/printk.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <kunit/test.h>
+#include <asm/word-at-a-time.h>
+
+static void test_wordatatime_has_zero(struct kunit *test)
+{
+ const struct word_at_a_time constants = WORD_AT_A_TIME_CONSTANTS;
+ unsigned long val, data;
+
+ val = -1UL;
+ KUNIT_ASSERT_FALSE(test, has_zero(val, &data, &constants));
+
+ for (int i = 0; i < BITS_PER_LONG; i += 8) {
+ val = ~(0xffUL << i);
+ KUNIT_ASSERT_TRUE(test, has_zero(val, &data, &constants));
+ }
+
+ for (int i = 0; i < BITS_PER_LONG; i++) {
+ val = ~(0x1UL << i);
+ KUNIT_ASSERT_FALSE(test, has_zero(val, &data, &constants));
+ }
+
+ for (int i = 0; i < BITS_PER_LONG; i++) {
+ val = 0x1UL << i;
+ KUNIT_ASSERT_TRUE(test, has_zero(val, &data, &constants));
+ }
+}
+
+static void test_wordatatime_find_zero(struct kunit *test)
+{
+ const struct word_at_a_time constants = WORD_AT_A_TIME_CONSTANTS;
+ unsigned long val, data;
+
+ for (int i = 0; i < BITS_PER_LONG; i += 8) {
+ val = ~(0xffUL << i);
+ KUNIT_ASSERT_TRUE(test, has_zero(val, &data, &constants));
+ data = prep_zero_mask(val, data, &constants);
+ data = create_zero_mask(data);
+#ifdef CONFIG_CPU_BIG_ENDIAN
+ KUNIT_ASSERT_EQ(test, find_zero(data), (BITS_PER_LONG / 8 - 1) - (i / 8));
+#else
+ KUNIT_ASSERT_EQ(test, find_zero(data), i / 8);
+#endif
+ }
+}
+static struct kunit_case wordatatime_test_cases[] = {
+ KUNIT_CASE(test_wordatatime_has_zero),
+ KUNIT_CASE(test_wordatatime_find_zero),
+ {}
+};
+
+static struct kunit_suite wordatatime_test_suite = {
+ .name = "wordatatime_test",
+ .test_cases = wordatatime_test_cases,
+};
+
+kunit_test_suites(&wordatatime_test_suite);
+MODULE_LICENSE("GPL");