From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from out30-118.freemail.mail.aliyun.com (out30-118.freemail.mail.aliyun.com [115.124.30.118]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 257893C4562 for ; Mon, 18 May 2026 08:50:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=115.124.30.118 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779094231; cv=none; b=F7gZR0IM5krcalfx2O00ZAJq5GM06IGYGPRELsKdT4O0EYo9zHiQENgH8+Ked7yRWvtFuN5Feu8FEsLOVqiCDZ9+5JoseTZ1laHlwmuqu7ZkaAMRcg/3gmtB5jD02L0CGhMrJ5WNDvM/zwZqYMim2NtibOHOx+iH4gAioXO48jk= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779094231; c=relaxed/simple; bh=DOVBnHCxu7YKSTfrlpBII4fuOvBLEdzNgSVfMLDoGRs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=HJGbsD0fzN6cF37K1zxQ0XOwaibn+62RHmMpIFGYkyBH32lxBSulD4w24mT1BClEr1o+BFayvR8hqytzmx/1ccsYbbHu9zlUcoUxzqWAWbPE+3GWQYvyOW3uWHP4jJWzA2OACpADk6Ii2e26XHyED9uziTyB5YOd2tk00Z1HqSY= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.alibaba.com; spf=pass smtp.mailfrom=linux.alibaba.com; dkim=pass (1024-bit key) header.d=linux.alibaba.com header.i=@linux.alibaba.com header.b=uJoZGfGR; arc=none smtp.client-ip=115.124.30.118 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.alibaba.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.alibaba.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.alibaba.com header.i=@linux.alibaba.com header.b="uJoZGfGR" DKIM-Signature:v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.alibaba.com; s=default; t=1779094227; h=From:To:Subject:Date:Message-ID:MIME-Version; bh=4ZlFlL/ldqFxlJ/mCuoKEqDloBHgz/6+XLcrhP5/h8w=; b=uJoZGfGR2uabJ0rfA3C8SFKfpGjjGGUQuFOZlnA8fZcspelZrbuRcVnJ3RI4zeamr2LYLH4AZPW9DSJxXcUoTjCtT4R+pCcSI0S/l1pcw2eJji3+Y9Tu5YbsprOcziR2kj0GcU6QxNoOz00AGfukC30ObrQeOy9GdvzLa4pctV8= X-Alimail-AntiSpam:AC=PASS;BC=-1|-1;BR=01201311R211e4;CH=green;DM=||false|;DS=||;FP=0|-1|-1|-1|0|-1|-1|-1;HT=maildocker-contentspam033037009110;MF=tianruidong@linux.alibaba.com;NM=1;PH=DS;RN=28;SR=0;TI=SMTPD_---0X365dBE_1779094223; Received: from localhost(mailfrom:tianruidong@linux.alibaba.com fp:SMTPD_---0X365dBE_1779094223 cluster:ay36) by smtp.aliyun-inc.com; Mon, 18 May 2026 16:50:25 +0800 From: Ruidong Tian To: catalin.marinas@arm.com, will@kernel.org, rafael@kernel.org, tony.luck@intel.com, guohanjun@huawei.com, mchehab@kernel.org, xueshuai@linux.alibaba.com, tongtiangen@huawei.com, james.morse@arm.com, robin.murphy@arm.com, andreyknvl@gmail.com, dvyukov@google.com, vincenzo.frascino@arm.com, mpe@ellerman.id.au, npiggin@gmail.com, ryabinin.a.a@gmail.com, glider@google.com, christophe.leroy@csgroup.eu, aneesh.kumar@kernel.org, naveen.n.rao@linux.ibm.com, tglx@linutronix.de, mingo@redhat.com Cc: linux-arm-kernel@lists.infradead.org, linux-mm@kvack.org, linuxppc-dev@lists.ozlabs.org, linux-kernel@vger.kernel.org, kasan-dev@googlegroups.com, tianruidong@linux.alibaba.com Subject: [PATCH v14 8/8] lib/tests: memcpy_kunit: add memcpy_mc() and memcpy_mc_large() test Date: Mon, 18 May 2026 16:49:52 +0800 Message-ID: <20260518084956.2538442-9-tianruidong@linux.alibaba.com> X-Mailer: git-send-email 2.43.7 In-Reply-To: <20260518084956.2538442-1-tianruidong@linux.alibaba.com> References: <20260518084956.2538442-1-tianruidong@linux.alibaba.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit memcpy_mc() is the Machine-Check safe memcpy variant that returns the number of bytes NOT copied on a hardware memory error, or 0 on success. Add two test cases modeled after the existing memcpy_test() and memcpy_large_test() implementations: Signed-off-by: Ruidong Tian --- lib/tests/memcpy_kunit.c | 113 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 112 insertions(+), 1 deletion(-) diff --git a/lib/tests/memcpy_kunit.c b/lib/tests/memcpy_kunit.c index 85df53ccfb0c..b4b2dafb50f1 100644 --- a/lib/tests/memcpy_kunit.c +++ b/lib/tests/memcpy_kunit.c @@ -552,6 +552,115 @@ static void copy_mc_page_test(struct kunit *test) memcmp(page_dst + PAGE_SIZE, page_zero, PAGE_SIZE), 0, "copy_mc_page overflow into adjacent page"); } +/* + * memcpy_mc() is a Machine-Check safe memcpy variant. + * Signature: int memcpy_mc(void *dst, const void *src, size_t len) + * Returns: 0 on success, or number of bytes NOT copied on MC error. + * + * In the normal (no-poison) path it must behave identically to memcpy() + * and always return 0. + */ +static void memcpy_mc_test(struct kunit *test) +{ +#define TEST_OP "memcpy_mc" + struct some_bytes control = { + .data = { 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + }, + }; + struct some_bytes zero = { }; + struct some_bytes middle = { + .data = { 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + }, + }; + struct some_bytes three = { + .data = { 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + }, + }; + struct some_bytes dest = { }; + int ret, count; + u8 *ptr; + + /* Verify static initializers. */ + check(control, 0x20); + check(zero, 0); + compare("static initializers", dest, zero); + + /* Verify assignment. */ + dest = control; + compare("direct assignment", dest, control); + + /* Verify complete overwrite. */ + ret = memcpy_mc(dest.data, control.data, sizeof(dest.data)); + KUNIT_ASSERT_EQ(test, ret, 0); + compare("complete overwrite", dest, control); + + /* Verify middle overwrite: 7 bytes at offset 12. */ + dest = control; + ret = memcpy_mc(dest.data + 12, zero.data, 7); + KUNIT_ASSERT_EQ(test, ret, 0); + compare("middle overwrite", dest, middle); + + /* Verify zero-length copy is a no-op. */ + dest = control; + ret = memcpy_mc(dest.data, zero.data, 0); + KUNIT_ASSERT_EQ(test, ret, 0); + compare("zero length", dest, control); + + /* Verify argument side-effects aren't repeated. */ + dest = control; + ptr = dest.data; + count = 1; + memcpy(ptr++, zero.data, count++); + ptr += 8; + memcpy(ptr++, zero.data, count++); + compare("argument side-effects", dest, three); +#undef TEST_OP +} + +static void memcpy_mc_large_test(struct kunit *test) +{ + init_large(test); + + /* Sweep 1..1024 bytes x shifting offset to cover all template paths. */ + for (int bytes = 1; bytes <= ARRAY_SIZE(large_src); bytes++) { + for (int offset = 0; offset < ARRAY_SIZE(large_src); offset++) { + int right_zero_pos = offset + bytes; + int right_zero_size = ARRAY_SIZE(large_dst) - right_zero_pos; + int ret; + + ret = memcpy_mc(large_dst + offset, large_src, bytes); + KUNIT_ASSERT_EQ_MSG(test, ret, 0, + "memcpy_mc returned %d with size %d at offset %d", + ret, bytes, offset); + + /* No write before copy area. */ + KUNIT_ASSERT_EQ_MSG(test, + memcmp(large_dst, large_zero, offset), 0, + "with size %d at offset %d", bytes, offset); + /* No write after copy area. */ + KUNIT_ASSERT_EQ_MSG(test, + memcmp(&large_dst[right_zero_pos], large_zero, + right_zero_size), 0, + "with size %d at offset %d", bytes, offset); + /* Byte-for-byte exact. */ + KUNIT_ASSERT_EQ_MSG(test, + memcmp(large_dst + offset, large_src, bytes), 0, + "with size %d at offset %d", bytes, offset); + + memset(large_dst + offset, 0, bytes); + } + cond_resched(); + } +} #endif /* CONFIG_ARCH_HAS_COPY_MC */ static struct kunit_case memcpy_test_cases[] = { @@ -564,6 +673,8 @@ static struct kunit_case memcpy_test_cases[] = { KUNIT_CASE(copy_page_test), #ifdef CONFIG_ARCH_HAS_COPY_MC KUNIT_CASE(copy_mc_page_test), + KUNIT_CASE(memcpy_mc_test), + KUNIT_CASE_SLOW(memcpy_mc_large_test), #endif {} }; @@ -575,5 +686,5 @@ static struct kunit_suite memcpy_test_suite = { kunit_test_suite(memcpy_test_suite); -MODULE_DESCRIPTION("test cases for memcpy(), memmove(), memset() and copy_page()"); +MODULE_DESCRIPTION("test cases for memcpy(), memmove(), memset(), copy_page() and memcpy_mc()"); MODULE_LICENSE("GPL"); -- 2.39.3