1313006Scem/*
2313006Scem * Copyright (c) 2017 Conrad Meyer <cem@FreeBSD.org>
3313006Scem * All rights reserved.
4313006Scem *
5313006Scem * Redistribution and use in source and binary forms, with or without
6313006Scem * modification, are permitted provided that the following conditions
7313006Scem * are met:
8313006Scem * 1. Redistributions of source code must retain the above copyright
9313006Scem *    notice, this list of conditions and the following disclaimer.
10313006Scem * 2. Redistributions in binary form must reproduce the above copyright
11313006Scem *    notice, this list of conditions and the following disclaimer in the
12313006Scem *    documentation and/or other materials provided with the distribution.
13313006Scem *
14313006Scem * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15313006Scem * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16313006Scem * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17313006Scem * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18313006Scem * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19313006Scem * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20313006Scem * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21313006Scem * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22313006Scem * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23313006Scem * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24313006Scem * SUCH DAMAGE.
25313006Scem *
26313006Scem * $FreeBSD: stable/11/tests/sys/kern/libkern_crc32.c 319404 2017-06-01 09:00:38Z tuexen $
27313006Scem */
28313006Scem
29313006Scem#include <sys/param.h>
30313006Scem
31313006Scem#include <stdint.h>
32313006Scem
33313006Scem#include <atf-c.h>
34313006Scem
35319404Stuexen#if defined(__amd64__) || defined(__i386__)
36313006Scemextern uint32_t sse42_crc32c(uint32_t, const unsigned char *, unsigned);
37319404Stuexen#elif defined(__aarch64__)
38319404Stuexenextern uint32_t armv8_crc32c(uint32_t, const unsigned char *, unsigned);
39319404Stuexen#else
40319404Stuexen#error These tests are not supported on this platform
41319404Stuexen#endif
42313006Scem
43313006ScemATF_TC_WITHOUT_HEAD(crc32c_basic_correctness);
44313006ScemATF_TC_BODY(crc32c_basic_correctness, tc)
45313006Scem{
46313006Scem	const uint64_t inputs[] = {
47313006Scem		0xf408c634b3a9142,
48313006Scem		0x80539e8c7c352e2b,
49313006Scem		0x62e9121db6e4d649,
50313006Scem		0x899345850ed0a286,
51313006Scem		0x2302df11b4a43b15,
52313006Scem		0xe943de7b3d35d70,
53313006Scem		0xdf1ff2bf41abf56b,
54313006Scem		0x9bc138abae315de2,
55313006Scem		0x31cc82e56234f0ff,
56313006Scem		0xce63c0cd6988e847,
57313006Scem		0x3e42f6b78ee352fa,
58313006Scem		0xfa4085436078cfa6,
59313006Scem		0x53349558bf670a4b,
60313006Scem		0x2714e10e7d722c61,
61313006Scem		0xc0d3261addfc6908,
62313006Scem		0xd1567c3181d3a1bf,
63313006Scem	};
64313006Scem	const uint32_t results[] = {
65313006Scem		0x2ce33ede,
66313006Scem		0xc49cc573,
67313006Scem		0xb8683c96,
68313006Scem		0x6918660d,
69313006Scem		0xa904e522,
70313006Scem		0x52dbc42c,
71313006Scem		0x98863c22,
72313006Scem		0x894d5d2c,
73313006Scem		0xb003745d,
74313006Scem		0xfc496dbd,
75313006Scem		0x97d2fbb5,
76313006Scem		0x3c062ef1,
77313006Scem		0xcc2eff18,
78313006Scem		0x6a9b09f6,
79313006Scem		0x420242c1,
80313006Scem		0xfd562dc3,
81313006Scem	};
82313006Scem	size_t i;
83313006Scem	uint32_t act;
84313006Scem
85313006Scem	ATF_REQUIRE(nitems(inputs) == nitems(results));
86313006Scem
87313006Scem	for (i = 0; i < nitems(inputs); i++) {
88319404Stuexen#if defined(__amd64__) || defined(__i386__)
89313006Scem		act = sse42_crc32c(~0, (const void *)&inputs[i],
90313006Scem		    sizeof(inputs[0]));
91319404Stuexen#else
92319404Stuexen		act = armv8_crc32c(~0, (const void *)&inputs[i],
93319404Stuexen		    sizeof(inputs[0]));
94319404Stuexen#endif
95313006Scem		ATF_REQUIRE_MSG(act == results[i],
96313006Scem		    "crc32c(0x%jx) = 0x%08x, got 0x%08x", (uintmax_t)inputs[i],
97313006Scem		    results[i], act);
98313006Scem	}
99313006Scem}
100313006Scem
101313006ScemATF_TC_WITHOUT_HEAD(crc32c_alignment);
102313006ScemATF_TC_BODY(crc32c_alignment, tc)
103313006Scem{
104313006Scem	const uint64_t input = 0xf408c634b3a9142;
105313006Scem	const uint32_t result = 0x2ce33ede;
106313006Scem	unsigned char buf[15];
107313006Scem	size_t i;
108313006Scem	uint32_t act;
109313006Scem
110313006Scem
111313006Scem	for (i = 1; i < 8; i++) {
112313006Scem		memcpy(&buf[i], &input, sizeof(input));
113313006Scem
114319404Stuexen#if defined(__amd64__) || defined(__i386__)
115313006Scem		act = sse42_crc32c(~0, (const void *)&buf[i], sizeof(input));
116319404Stuexen#else
117319404Stuexen		act = armv8_crc32c(~0, (const void *)&buf[i], sizeof(input));
118319404Stuexen#endif
119313006Scem		ATF_REQUIRE_MSG(act == result,
120313006Scem		    "crc32c(0x%jx) = 0x%08x, got 0x%08x", (uintmax_t)input,
121313006Scem		    result, act);
122313006Scem	}
123313006Scem}
124313006Scem
125313006ScemATF_TC_WITHOUT_HEAD(crc32c_trailing_bytes);
126313006ScemATF_TC_BODY(crc32c_trailing_bytes, tc)
127313006Scem{
128313006Scem	const unsigned char input[] = {
129313006Scem		0x87, 0x54, 0x74, 0xd2, 0xb, 0x9b, 0xdd, 0xf6, 0x68, 0x37,
130313006Scem		0xd4, 0x4, 0x5e, 0xa9, 0xb3
131313006Scem	};
132313006Scem	const uint32_t result = 0xec638d62;
133313006Scem	uint32_t act;
134313006Scem
135319404Stuexen#if defined(__amd64__) || defined(__i386__)
136313006Scem	act = sse42_crc32c(~0, input, sizeof(input));
137319404Stuexen#else
138319404Stuexen	act = armv8_crc32c(~0, input, sizeof(input));
139319404Stuexen#endif
140313006Scem	ATF_REQUIRE_MSG(act == result, "expected 0x%08x, got 0x%08x", result,
141313006Scem	    act);
142313006Scem}
143313006Scem
144313006ScemATF_TP_ADD_TCS(tp)
145313006Scem{
146313006Scem
147313006Scem	ATF_TP_ADD_TC(tp, crc32c_basic_correctness);
148313006Scem	ATF_TP_ADD_TC(tp, crc32c_alignment);
149313006Scem	ATF_TP_ADD_TC(tp, crc32c_trailing_bytes);
150313006Scem	return (atf_no_error());
151313006Scem}
152