All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kees Cook <kees@kernel.org>
To: Milan Tripkovic <milant2002@gmail.com>
Cc: Paul Walmsley <pjw@kernel.org>,
	Palmer Dabbelt <palmer@dabbelt.com>,
	Albert Ou <aou@eecs.berkeley.edu>,
	Alexandre Ghiti <alex@ghiti.fr>,
	Andy Shevchenko <andy@kernel.org>,
	Nathan Chancellor <nathan@kernel.org>,
	Nick Desaulniers <nick.desaulniers+lkml@gmail.com>,
	Bill Wendling <morbo@google.com>,
	Justin Stitt <justinstitt@google.com>,
	linux-riscv@lists.infradead.org, linux-kernel@vger.kernel.org,
	linux-hardening@vger.kernel.org, llvm@lists.linux.dev,
	Dusan Stojkovic <Dusan.Stojkovic@rt-rk.com>,
	Milan Tripkovic <Milan.Tripkovic@rt-rk.com>,
	kernel test robot <lkp@intel.com>
Subject: Re: [PATCH v2 2/2] lib/string_kunit: extend benchmarks and unit test to memcmp()
Date: Thu, 14 May 2026 09:19:11 -0700	[thread overview]
Message-ID: <202605140916.09FBB1A4@keescook> (raw)
In-Reply-To: <20260514121359.931999-3-milant2002@gmail.com>

On Thu, May 14, 2026 at 02:13:58PM +0200, Milan Tripkovic wrote:
> From: Milan Tripkovic <Milan.Tripkovic@rt-rk.com>
> 
> Extend the string benchmarking suite to include memcmp().
> Extend the string unit test to include memcmp().
> 
> Reported-by: kernel test robot <lkp@intel.com>
> Closes: https://lore.kernel.org/oe-kbuild-all/202605140827.Qg1DZpcB-lkp@intel.com/
> Signed-off-by: Milan Tripkovic <Milan.Tripkovic@rt-rk.com>
> ---
>  lib/tests/string_kunit.c | 106 +++++++++++++++++++++++++++++++++++++++
>  1 file changed, 106 insertions(+)
> 
> diff --git a/lib/tests/string_kunit.c b/lib/tests/string_kunit.c
> index 0819ace5b027..d0bad40a719a 100644
> --- a/lib/tests/string_kunit.c
> +++ b/lib/tests/string_kunit.c
> @@ -881,6 +881,110 @@ static void string_bench_strrchr(struct kunit *test)
>  	STRING_BENCH_BUF(test, buf, len, strrchr, buf, '\0');
>  }
>  
> +static void string_test_memcmp(struct kunit *test)
> +{
> +	const int max_offset = 16;
> +	const int max_len = 32;
> +	const int buf_size = max_offset + max_len + 32;
> +	u8 *buf1, *buf2;
> +	int i, j, len, k;
> +
> +	buf1 = kunit_kzalloc(test, buf_size, GFP_KERNEL);
> +	buf2 = kunit_kzalloc(test, buf_size, GFP_KERNEL);
> +	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf1);
> +	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf2);
> +
> +	for (i = 0; i < max_offset; i++) {
> +		for (j = 0; j < max_offset; j++) {
> +			for (len = 0; len <= max_len; len++) {
> +				memset(buf1, 'A', buf_size);
> +				memset(buf2, 'A', buf_size);
> +				KUNIT_EXPECT_EQ_MSG(test, memcmp(buf1 + i, buf2 + j, len), 0,
> +						    "Should be equal: i:%d j:%d len:%d", i, j, len);
> +				for (k = 0; k < len; k++) {
> +					memset(buf1, 'A', buf_size);
> +					memset(buf2, 'A', buf_size);
> +					buf2[j + k] = 'B';
> +					int res = memcmp(buf1 + i, buf2 + j, len);
> +
> +					KUNIT_EXPECT_NE_MSG(test, res, 0,
> +							    "Should detect difference at k:%d (i:%d j:%d len:%d)",
> +						k, i, j, len);
> +
> +					if (buf1[i + k] < buf2[j + k])
> +						KUNIT_EXPECT_LT(test, res, 0);
> +					else
> +						KUNIT_EXPECT_GT(test, res, 0);
> +				}
> +			}
> +		}
> +	}
> +}

This looks good, thanks!

> +#if IS_ENABLED(CONFIG_STRING_KUNIT_BENCH)
> +static void string_bench_memcmp(struct kunit *test)
> +{
> +	char *buf1, *buf2;
> +	size_t lengths[] = { 1, 7, 8, 16, 32, 64, 128, 512, 1024, 4096};
> +	int offsets[] = {0, 1, 3, 7};
> +	const size_t max_len = 4096 + 64;

I think I'd prefer, instead of a ifdef stub, to do:

        if (!IS_ENABLED(CONFIG_STRING_KUNIT_BENCH))
	        kunit_skip(test, "CONFIG_STRING_KUNIT_BENCH not enabled")

here.

> +
> +	buf1 = vmalloc(max_len);
> +	buf2 = vmalloc(max_len);
> +
> +	if (!buf1 || !buf2) {
> +		vfree(buf1);
> +		vfree(buf2);
> +		kunit_err(test, "vmalloc failed\n");
> +		return;
> +	}
> +
> +	memset(buf1, 'A', max_len);
> +	memset(buf2, 'A', max_len);
> +
> +	for (int i = 0; i < 100000; i++)
> +		(void)memcmp(buf1, buf2, 4096);
> +
> +	for (int o = 0; o < ARRAY_SIZE(offsets); o++) {
> +		int off = offsets[o];
> +
> +		for (int i = 0; i < ARRAY_SIZE(lengths); i++) {
> +			size_t len = lengths[i];
> +			char *p1 = buf1;
> +			char *p2 = buf2 + off;
> +
> +			u32 iterations = (len < 512) ? 100000 : 10000;
> +
> +			for (u32 j = 0; j < iterations; j++) {
> +				(void)memcmp(p1, p2, len);
> +				barrier();
> +			}
> +
> +			u64 elapsed = STRING_BENCH(iterations, memcmp, p1, p2, len);
> +			u64 ns_per_call = div_u64(elapsed, iterations);
> +			u64 mbps = len ? div_u64((u64)len * iterations * 1000,
> +									 elapsed) : 0;
> +
> +			if (off == 0) {
> +				kunit_info(test, "bench_memcmp_aligned: len=%-4zu: %llu MB/s (%llu ns/call)\n",
> +					   len, mbps, ns_per_call);
> +			} else {
> +				kunit_info(test, "bench_memcmp_unaligned(off=%d): len=%-4zu: %llu MB/s (%llu ns/call)\n",
> +					   off, len, mbps, ns_per_call);
> +			}
> +		}
> +	}
> +
> +	vfree(buf1);
> +	vfree(buf2);
> +}
> +#else
> +static void string_bench_memcmp(struct kunit *test)
> +{
> +	kunit_skip(test, "not enabled");
> +}
> +#endif
> +
>  static struct kunit_case string_test_cases[] = {
>  	KUNIT_CASE(string_test_memset16),
>  	KUNIT_CASE(string_test_memset32),
> @@ -910,6 +1014,8 @@ static struct kunit_case string_test_cases[] = {
>  	KUNIT_CASE(string_bench_strnlen),
>  	KUNIT_CASE(string_bench_strchr),
>  	KUNIT_CASE(string_bench_strrchr),
> +	KUNIT_CASE(string_test_memcmp),
> +	KUNIT_CASE_SLOW(string_bench_memcmp),
>  	{}
>  };
>  
> -- 
> 2.43.0
> 

-- 
Kees Cook

WARNING: multiple messages have this Message-ID (diff)
From: Kees Cook <kees@kernel.org>
To: Milan Tripkovic <milant2002@gmail.com>
Cc: Paul Walmsley <pjw@kernel.org>,
	Palmer Dabbelt <palmer@dabbelt.com>,
	Albert Ou <aou@eecs.berkeley.edu>,
	Alexandre Ghiti <alex@ghiti.fr>,
	Andy Shevchenko <andy@kernel.org>,
	Nathan Chancellor <nathan@kernel.org>,
	Nick Desaulniers <nick.desaulniers+lkml@gmail.com>,
	Bill Wendling <morbo@google.com>,
	Justin Stitt <justinstitt@google.com>,
	linux-riscv@lists.infradead.org, linux-kernel@vger.kernel.org,
	linux-hardening@vger.kernel.org, llvm@lists.linux.dev,
	Dusan Stojkovic <Dusan.Stojkovic@rt-rk.com>,
	Milan Tripkovic <Milan.Tripkovic@rt-rk.com>,
	kernel test robot <lkp@intel.com>
Subject: Re: [PATCH v2 2/2] lib/string_kunit: extend benchmarks and unit test to memcmp()
Date: Thu, 14 May 2026 09:19:11 -0700	[thread overview]
Message-ID: <202605140916.09FBB1A4@keescook> (raw)
In-Reply-To: <20260514121359.931999-3-milant2002@gmail.com>

On Thu, May 14, 2026 at 02:13:58PM +0200, Milan Tripkovic wrote:
> From: Milan Tripkovic <Milan.Tripkovic@rt-rk.com>
> 
> Extend the string benchmarking suite to include memcmp().
> Extend the string unit test to include memcmp().
> 
> Reported-by: kernel test robot <lkp@intel.com>
> Closes: https://lore.kernel.org/oe-kbuild-all/202605140827.Qg1DZpcB-lkp@intel.com/
> Signed-off-by: Milan Tripkovic <Milan.Tripkovic@rt-rk.com>
> ---
>  lib/tests/string_kunit.c | 106 +++++++++++++++++++++++++++++++++++++++
>  1 file changed, 106 insertions(+)
> 
> diff --git a/lib/tests/string_kunit.c b/lib/tests/string_kunit.c
> index 0819ace5b027..d0bad40a719a 100644
> --- a/lib/tests/string_kunit.c
> +++ b/lib/tests/string_kunit.c
> @@ -881,6 +881,110 @@ static void string_bench_strrchr(struct kunit *test)
>  	STRING_BENCH_BUF(test, buf, len, strrchr, buf, '\0');
>  }
>  
> +static void string_test_memcmp(struct kunit *test)
> +{
> +	const int max_offset = 16;
> +	const int max_len = 32;
> +	const int buf_size = max_offset + max_len + 32;
> +	u8 *buf1, *buf2;
> +	int i, j, len, k;
> +
> +	buf1 = kunit_kzalloc(test, buf_size, GFP_KERNEL);
> +	buf2 = kunit_kzalloc(test, buf_size, GFP_KERNEL);
> +	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf1);
> +	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf2);
> +
> +	for (i = 0; i < max_offset; i++) {
> +		for (j = 0; j < max_offset; j++) {
> +			for (len = 0; len <= max_len; len++) {
> +				memset(buf1, 'A', buf_size);
> +				memset(buf2, 'A', buf_size);
> +				KUNIT_EXPECT_EQ_MSG(test, memcmp(buf1 + i, buf2 + j, len), 0,
> +						    "Should be equal: i:%d j:%d len:%d", i, j, len);
> +				for (k = 0; k < len; k++) {
> +					memset(buf1, 'A', buf_size);
> +					memset(buf2, 'A', buf_size);
> +					buf2[j + k] = 'B';
> +					int res = memcmp(buf1 + i, buf2 + j, len);
> +
> +					KUNIT_EXPECT_NE_MSG(test, res, 0,
> +							    "Should detect difference at k:%d (i:%d j:%d len:%d)",
> +						k, i, j, len);
> +
> +					if (buf1[i + k] < buf2[j + k])
> +						KUNIT_EXPECT_LT(test, res, 0);
> +					else
> +						KUNIT_EXPECT_GT(test, res, 0);
> +				}
> +			}
> +		}
> +	}
> +}

This looks good, thanks!

> +#if IS_ENABLED(CONFIG_STRING_KUNIT_BENCH)
> +static void string_bench_memcmp(struct kunit *test)
> +{
> +	char *buf1, *buf2;
> +	size_t lengths[] = { 1, 7, 8, 16, 32, 64, 128, 512, 1024, 4096};
> +	int offsets[] = {0, 1, 3, 7};
> +	const size_t max_len = 4096 + 64;

I think I'd prefer, instead of a ifdef stub, to do:

        if (!IS_ENABLED(CONFIG_STRING_KUNIT_BENCH))
	        kunit_skip(test, "CONFIG_STRING_KUNIT_BENCH not enabled")

here.

> +
> +	buf1 = vmalloc(max_len);
> +	buf2 = vmalloc(max_len);
> +
> +	if (!buf1 || !buf2) {
> +		vfree(buf1);
> +		vfree(buf2);
> +		kunit_err(test, "vmalloc failed\n");
> +		return;
> +	}
> +
> +	memset(buf1, 'A', max_len);
> +	memset(buf2, 'A', max_len);
> +
> +	for (int i = 0; i < 100000; i++)
> +		(void)memcmp(buf1, buf2, 4096);
> +
> +	for (int o = 0; o < ARRAY_SIZE(offsets); o++) {
> +		int off = offsets[o];
> +
> +		for (int i = 0; i < ARRAY_SIZE(lengths); i++) {
> +			size_t len = lengths[i];
> +			char *p1 = buf1;
> +			char *p2 = buf2 + off;
> +
> +			u32 iterations = (len < 512) ? 100000 : 10000;
> +
> +			for (u32 j = 0; j < iterations; j++) {
> +				(void)memcmp(p1, p2, len);
> +				barrier();
> +			}
> +
> +			u64 elapsed = STRING_BENCH(iterations, memcmp, p1, p2, len);
> +			u64 ns_per_call = div_u64(elapsed, iterations);
> +			u64 mbps = len ? div_u64((u64)len * iterations * 1000,
> +									 elapsed) : 0;
> +
> +			if (off == 0) {
> +				kunit_info(test, "bench_memcmp_aligned: len=%-4zu: %llu MB/s (%llu ns/call)\n",
> +					   len, mbps, ns_per_call);
> +			} else {
> +				kunit_info(test, "bench_memcmp_unaligned(off=%d): len=%-4zu: %llu MB/s (%llu ns/call)\n",
> +					   off, len, mbps, ns_per_call);
> +			}
> +		}
> +	}
> +
> +	vfree(buf1);
> +	vfree(buf2);
> +}
> +#else
> +static void string_bench_memcmp(struct kunit *test)
> +{
> +	kunit_skip(test, "not enabled");
> +}
> +#endif
> +
>  static struct kunit_case string_test_cases[] = {
>  	KUNIT_CASE(string_test_memset16),
>  	KUNIT_CASE(string_test_memset32),
> @@ -910,6 +1014,8 @@ static struct kunit_case string_test_cases[] = {
>  	KUNIT_CASE(string_bench_strnlen),
>  	KUNIT_CASE(string_bench_strchr),
>  	KUNIT_CASE(string_bench_strrchr),
> +	KUNIT_CASE(string_test_memcmp),
> +	KUNIT_CASE_SLOW(string_bench_memcmp),
>  	{}
>  };
>  
> -- 
> 2.43.0
> 

-- 
Kees Cook

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

  reply	other threads:[~2026-05-14 16:19 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-14 12:13 [PATCH v2 0/2] riscv: lib: add optimized memcmp() and extend KUnit tests Milan Tripkovic
2026-05-14 12:13 ` Milan Tripkovic
2026-05-14 12:13 ` [PATCH v2 1/2] riscv: lib: add memcmp() implementation Milan Tripkovic
2026-05-14 12:13   ` Milan Tripkovic
2026-05-14 12:13 ` [PATCH v2 2/2] lib/string_kunit: extend benchmarks and unit test to memcmp() Milan Tripkovic
2026-05-14 12:13   ` Milan Tripkovic
2026-05-14 16:19   ` Kees Cook [this message]
2026-05-14 16:19     ` Kees Cook
2026-05-15  6:36     ` Andy Shevchenko
2026-05-15  6:36       ` Andy Shevchenko

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=202605140916.09FBB1A4@keescook \
    --to=kees@kernel.org \
    --cc=Dusan.Stojkovic@rt-rk.com \
    --cc=Milan.Tripkovic@rt-rk.com \
    --cc=alex@ghiti.fr \
    --cc=andy@kernel.org \
    --cc=aou@eecs.berkeley.edu \
    --cc=justinstitt@google.com \
    --cc=linux-hardening@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-riscv@lists.infradead.org \
    --cc=lkp@intel.com \
    --cc=llvm@lists.linux.dev \
    --cc=milant2002@gmail.com \
    --cc=morbo@google.com \
    --cc=nathan@kernel.org \
    --cc=nick.desaulniers+lkml@gmail.com \
    --cc=palmer@dabbelt.com \
    --cc=pjw@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.