xref: /freebsd/tests/sys/kern/libkern_crc32.c (revision b3e7694832e81d7a904a10f525f8797b753bf0d3)
16be2ff7dSConrad Meyer /*
26be2ff7dSConrad Meyer  * Copyright (c) 2017 Conrad Meyer <cem@FreeBSD.org>
36be2ff7dSConrad Meyer  * All rights reserved.
46be2ff7dSConrad Meyer  *
56be2ff7dSConrad Meyer  * Redistribution and use in source and binary forms, with or without
66be2ff7dSConrad Meyer  * modification, are permitted provided that the following conditions
76be2ff7dSConrad Meyer  * are met:
86be2ff7dSConrad Meyer  * 1. Redistributions of source code must retain the above copyright
96be2ff7dSConrad Meyer  *    notice, this list of conditions and the following disclaimer.
106be2ff7dSConrad Meyer  * 2. Redistributions in binary form must reproduce the above copyright
116be2ff7dSConrad Meyer  *    notice, this list of conditions and the following disclaimer in the
126be2ff7dSConrad Meyer  *    documentation and/or other materials provided with the distribution.
136be2ff7dSConrad Meyer  *
146be2ff7dSConrad Meyer  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
156be2ff7dSConrad Meyer  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
166be2ff7dSConrad Meyer  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
176be2ff7dSConrad Meyer  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
186be2ff7dSConrad Meyer  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
196be2ff7dSConrad Meyer  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
206be2ff7dSConrad Meyer  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
216be2ff7dSConrad Meyer  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
226be2ff7dSConrad Meyer  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
236be2ff7dSConrad Meyer  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
246be2ff7dSConrad Meyer  * SUCH DAMAGE.
256be2ff7dSConrad Meyer  */
266be2ff7dSConrad Meyer 
276be2ff7dSConrad Meyer #include <sys/param.h>
28f89d2072SXin LI #include <sys/gsb_crc32.h>
296be2ff7dSConrad Meyer 
306be2ff7dSConrad Meyer #include <stdint.h>
316be2ff7dSConrad Meyer 
326be2ff7dSConrad Meyer #include <atf-c.h>
336be2ff7dSConrad Meyer 
34*83c20b8aSAlex Richardson #if defined(__amd64__) || defined(__i386__)
35*83c20b8aSAlex Richardson #include <machine/cpufunc.h>
36*83c20b8aSAlex Richardson #include <machine/specialreg.h>
37*83c20b8aSAlex Richardson 
38*83c20b8aSAlex Richardson static bool
have_sse42(void)39*83c20b8aSAlex Richardson have_sse42(void)
40*83c20b8aSAlex Richardson {
41*83c20b8aSAlex Richardson 	u_int cpu_registers[4];
42*83c20b8aSAlex Richardson 
43*83c20b8aSAlex Richardson 	do_cpuid(1, cpu_registers);
44*83c20b8aSAlex Richardson 
45*83c20b8aSAlex Richardson 	return ((cpu_registers[2] & CPUID2_SSE42) != 0);
46*83c20b8aSAlex Richardson }
47d7f27102SMichael Tuexen #endif
486be2ff7dSConrad Meyer 
49*83c20b8aSAlex Richardson static void
check_crc32c(uint32_t expected,uint32_t crc32c,const void * buffer,size_t length)50*83c20b8aSAlex Richardson check_crc32c(uint32_t expected, uint32_t crc32c, const void *buffer,
51*83c20b8aSAlex Richardson     size_t length)
52*83c20b8aSAlex Richardson {
53*83c20b8aSAlex Richardson 	uint32_t act;
54*83c20b8aSAlex Richardson 
55*83c20b8aSAlex Richardson #if defined(__amd64__) || defined(__i386__)
56*83c20b8aSAlex Richardson 	if (have_sse42()) {
57*83c20b8aSAlex Richardson 		act = sse42_crc32c(crc32c, buffer, length);
58*83c20b8aSAlex Richardson 		ATF_CHECK_EQ_MSG(expected, act,
59*83c20b8aSAlex Richardson 		    "sse42_crc32c expected 0x%08x, got 0x%08x", expected, act);
60*83c20b8aSAlex Richardson 	}
61*83c20b8aSAlex Richardson #elif defined(__aarch64__)
62*83c20b8aSAlex Richardson 	act = armv8_crc32c(crc32c, buffer, length);
63*83c20b8aSAlex Richardson 	ATF_CHECK_EQ_MSG(expected, act,
64*83c20b8aSAlex Richardson 	    "armv8_crc32c expected 0x%08x, got 0x%08x", expected, act);
65*83c20b8aSAlex Richardson #endif
66*83c20b8aSAlex Richardson 	act = singletable_crc32c(crc32c, buffer, length);
67*83c20b8aSAlex Richardson 	ATF_CHECK_EQ_MSG(expected, act,
68*83c20b8aSAlex Richardson 	    "singletable_crc32c expected 0x%08x, got 0x%08x", expected, act);
69*83c20b8aSAlex Richardson 	act = multitable_crc32c(crc32c, buffer, length);
70*83c20b8aSAlex Richardson 	ATF_CHECK_EQ_MSG(expected, act,
71*83c20b8aSAlex Richardson 	    "multitable_crc32c expected 0x%08x, got 0x%08x", expected, act);
72*83c20b8aSAlex Richardson }
73*83c20b8aSAlex Richardson 
746be2ff7dSConrad Meyer ATF_TC_WITHOUT_HEAD(crc32c_basic_correctness);
ATF_TC_BODY(crc32c_basic_correctness,tc)756be2ff7dSConrad Meyer ATF_TC_BODY(crc32c_basic_correctness, tc)
766be2ff7dSConrad Meyer {
776be2ff7dSConrad Meyer 	const uint64_t inputs[] = {
786be2ff7dSConrad Meyer 		0xf408c634b3a9142,
796be2ff7dSConrad Meyer 		0x80539e8c7c352e2b,
806be2ff7dSConrad Meyer 		0x62e9121db6e4d649,
816be2ff7dSConrad Meyer 		0x899345850ed0a286,
826be2ff7dSConrad Meyer 		0x2302df11b4a43b15,
836be2ff7dSConrad Meyer 		0xe943de7b3d35d70,
846be2ff7dSConrad Meyer 		0xdf1ff2bf41abf56b,
856be2ff7dSConrad Meyer 		0x9bc138abae315de2,
866be2ff7dSConrad Meyer 		0x31cc82e56234f0ff,
876be2ff7dSConrad Meyer 		0xce63c0cd6988e847,
886be2ff7dSConrad Meyer 		0x3e42f6b78ee352fa,
896be2ff7dSConrad Meyer 		0xfa4085436078cfa6,
906be2ff7dSConrad Meyer 		0x53349558bf670a4b,
916be2ff7dSConrad Meyer 		0x2714e10e7d722c61,
926be2ff7dSConrad Meyer 		0xc0d3261addfc6908,
936be2ff7dSConrad Meyer 		0xd1567c3181d3a1bf,
946be2ff7dSConrad Meyer 	};
956be2ff7dSConrad Meyer 	const uint32_t results[] = {
966be2ff7dSConrad Meyer 		0x2ce33ede,
976be2ff7dSConrad Meyer 		0xc49cc573,
986be2ff7dSConrad Meyer 		0xb8683c96,
996be2ff7dSConrad Meyer 		0x6918660d,
1006be2ff7dSConrad Meyer 		0xa904e522,
1016be2ff7dSConrad Meyer 		0x52dbc42c,
1026be2ff7dSConrad Meyer 		0x98863c22,
1036be2ff7dSConrad Meyer 		0x894d5d2c,
1046be2ff7dSConrad Meyer 		0xb003745d,
1056be2ff7dSConrad Meyer 		0xfc496dbd,
1066be2ff7dSConrad Meyer 		0x97d2fbb5,
1076be2ff7dSConrad Meyer 		0x3c062ef1,
1086be2ff7dSConrad Meyer 		0xcc2eff18,
1096be2ff7dSConrad Meyer 		0x6a9b09f6,
1106be2ff7dSConrad Meyer 		0x420242c1,
1116be2ff7dSConrad Meyer 		0xfd562dc3,
1126be2ff7dSConrad Meyer 	};
1136be2ff7dSConrad Meyer 	size_t i;
1146be2ff7dSConrad Meyer 
1156be2ff7dSConrad Meyer 	ATF_REQUIRE(nitems(inputs) == nitems(results));
1166be2ff7dSConrad Meyer 
1176be2ff7dSConrad Meyer 	for (i = 0; i < nitems(inputs); i++) {
118*83c20b8aSAlex Richardson 		check_crc32c(results[i], ~0u, &inputs[i], sizeof(inputs[0]));
1196be2ff7dSConrad Meyer 	}
1206be2ff7dSConrad Meyer }
1216be2ff7dSConrad Meyer 
1226be2ff7dSConrad Meyer ATF_TC_WITHOUT_HEAD(crc32c_alignment);
ATF_TC_BODY(crc32c_alignment,tc)1236be2ff7dSConrad Meyer ATF_TC_BODY(crc32c_alignment, tc)
1246be2ff7dSConrad Meyer {
1256be2ff7dSConrad Meyer 	const uint64_t input = 0xf408c634b3a9142;
1266be2ff7dSConrad Meyer 	const uint32_t result = 0x2ce33ede;
1276be2ff7dSConrad Meyer 	unsigned char buf[15];
1286be2ff7dSConrad Meyer 	size_t i;
1296be2ff7dSConrad Meyer 
1306be2ff7dSConrad Meyer 	for (i = 1; i < 8; i++) {
1316be2ff7dSConrad Meyer 		memcpy(&buf[i], &input, sizeof(input));
132*83c20b8aSAlex Richardson 		check_crc32c(result, ~0u, &buf[i], sizeof(input));
1336be2ff7dSConrad Meyer 	}
1346be2ff7dSConrad Meyer }
1356be2ff7dSConrad Meyer 
1366be2ff7dSConrad Meyer ATF_TC_WITHOUT_HEAD(crc32c_trailing_bytes);
ATF_TC_BODY(crc32c_trailing_bytes,tc)1376be2ff7dSConrad Meyer ATF_TC_BODY(crc32c_trailing_bytes, tc)
1386be2ff7dSConrad Meyer {
1396be2ff7dSConrad Meyer 	const unsigned char input[] = {
1406be2ff7dSConrad Meyer 		0x87, 0x54, 0x74, 0xd2, 0xb, 0x9b, 0xdd, 0xf6, 0x68, 0x37,
1416be2ff7dSConrad Meyer 		0xd4, 0x4, 0x5e, 0xa9, 0xb3
1426be2ff7dSConrad Meyer 	};
1436be2ff7dSConrad Meyer 	const uint32_t result = 0xec638d62;
1446be2ff7dSConrad Meyer 
145*83c20b8aSAlex Richardson 	check_crc32c(result, ~0u, input, sizeof(input));
1466be2ff7dSConrad Meyer }
1476be2ff7dSConrad Meyer 
ATF_TP_ADD_TCS(tp)1486be2ff7dSConrad Meyer ATF_TP_ADD_TCS(tp)
1496be2ff7dSConrad Meyer {
1506be2ff7dSConrad Meyer 
1516be2ff7dSConrad Meyer 	ATF_TP_ADD_TC(tp, crc32c_basic_correctness);
1526be2ff7dSConrad Meyer 	ATF_TP_ADD_TC(tp, crc32c_alignment);
1536be2ff7dSConrad Meyer 	ATF_TP_ADD_TC(tp, crc32c_trailing_bytes);
1546be2ff7dSConrad Meyer 	return (atf_no_error());
1556be2ff7dSConrad Meyer }
156