mirror of
https://github.com/freebsd/freebsd-src
synced 2024-09-06 17:18:32 +00:00
tests/sys/kern/crc32: Check for SSE4.2 before using it
This avoids a SIGILL when running these tests on QEMU (which defaults to a basic amd64 CPU without SSE4.2). This commit also tests the table-based implementations in addition to testing the hw-accelerated crc32 versions. Reviewed By: cem, kib, markj Differential Revision: https://reviews.freebsd.org/D28395
This commit is contained in:
parent
c69047ca75
commit
83c20b8a2d
|
@ -46,11 +46,11 @@
|
|||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/gsb_crc32.h>
|
||||
|
||||
#ifdef _KERNEL
|
||||
#include <sys/libkern.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/gsb_crc32.h>
|
||||
|
||||
#if defined(__amd64__) || defined(__i386__)
|
||||
#include <machine/md_var.h>
|
||||
|
@ -216,7 +216,10 @@ static const uint32_t crc32Table[256] = {
|
|||
0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L
|
||||
};
|
||||
|
||||
static uint32_t
|
||||
#ifndef TESTING
|
||||
static
|
||||
#endif
|
||||
uint32_t
|
||||
singletable_crc32c(uint32_t crc, const void *buf, size_t size)
|
||||
{
|
||||
const uint8_t *p = buf;
|
||||
|
@ -730,10 +733,13 @@ crc32c_sb8_64_bit(uint32_t crc,
|
|||
return crc;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
#ifndef TESTING
|
||||
static
|
||||
#endif
|
||||
uint32_t
|
||||
multitable_crc32c(uint32_t crc32c,
|
||||
const unsigned char *buffer,
|
||||
unsigned int length)
|
||||
const void *buffer,
|
||||
size_t length)
|
||||
{
|
||||
uint32_t to_even_word;
|
||||
|
||||
|
|
|
@ -32,10 +32,10 @@ crc32(const void *buf, size_t size)
|
|||
crc = crc32_raw(buf, size, ~0U);
|
||||
return (crc ^ ~0U);
|
||||
}
|
||||
#endif
|
||||
|
||||
uint32_t calculate_crc32c(uint32_t crc32c, const unsigned char *buffer,
|
||||
unsigned int length);
|
||||
#endif
|
||||
|
||||
#if defined(__amd64__) || defined(__i386__)
|
||||
uint32_t sse42_crc32c(uint32_t, const unsigned char *, unsigned);
|
||||
|
@ -44,4 +44,9 @@ uint32_t sse42_crc32c(uint32_t, const unsigned char *, unsigned);
|
|||
uint32_t armv8_crc32c(uint32_t, const unsigned char *, unsigned int);
|
||||
#endif
|
||||
|
||||
#ifdef TESTING
|
||||
uint32_t singletable_crc32c(uint32_t, const void *, size_t);
|
||||
uint32_t multitable_crc32c(uint32_t, const void *, size_t);
|
||||
#endif
|
||||
|
||||
#endif /* !_SYS_GSB_CRC32_H_ */
|
||||
|
|
|
@ -56,15 +56,15 @@ NETBSD_ATF_TESTS_C+= sysv_test
|
|||
CFLAGS.mqueue_test+= -I${SRCTOP}/tests
|
||||
LIBADD.mqueue_test+= rt
|
||||
|
||||
.if ${MACHINE_ARCH} == "amd64" || \
|
||||
${MACHINE_ARCH} == "i386" || \
|
||||
${MACHINE_CPUARCH} == "aarch64"
|
||||
ATF_TESTS_C+= libkern_crc32
|
||||
SRCS.libkern_crc32+= libkern_crc32.c
|
||||
.PATH: ${SRCTOP}/sys/libkern
|
||||
SRCS.libkern_crc32+= gsb_crc32.c
|
||||
CFLAGS.libkern_crc32+= -DTESTING
|
||||
.if ${MACHINE_ARCH} == "amd64" || ${MACHINE_ARCH} == "i386"
|
||||
LDADD.libkern_crc32+= ${SRCTOP}/sys/libkern/x86/crc32_sse42.c
|
||||
.else
|
||||
LDADD.libkern_crc32+= ${SRCTOP}/sys/libkern/arm64/crc32c_armv8.S
|
||||
.endif
|
||||
SRCS.libkern_crc32+= ${SRCTOP}/sys/libkern/x86/crc32_sse42.c
|
||||
.elif ${MACHINE_CPUARCH} == "aarch64"
|
||||
SRCS.libkern_crc32+= ${SRCTOP}/sys/libkern/arm64/crc32c_armv8.S
|
||||
.endif
|
||||
|
||||
# subr_unit.c contains functions whose prototypes lie in headers that cannot be
|
||||
|
|
|
@ -33,10 +33,46 @@
|
|||
|
||||
#include <atf-c.h>
|
||||
|
||||
#if !defined(__amd64__) && !defined(__i386__) && !defined(__aarch64__)
|
||||
#error These tests are not supported on this platform
|
||||
#if defined(__amd64__) || defined(__i386__)
|
||||
#include <machine/cpufunc.h>
|
||||
#include <machine/specialreg.h>
|
||||
|
||||
static bool
|
||||
have_sse42(void)
|
||||
{
|
||||
u_int cpu_registers[4];
|
||||
|
||||
do_cpuid(1, cpu_registers);
|
||||
|
||||
return ((cpu_registers[2] & CPUID2_SSE42) != 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
check_crc32c(uint32_t expected, uint32_t crc32c, const void *buffer,
|
||||
size_t length)
|
||||
{
|
||||
uint32_t act;
|
||||
|
||||
#if defined(__amd64__) || defined(__i386__)
|
||||
if (have_sse42()) {
|
||||
act = sse42_crc32c(crc32c, buffer, length);
|
||||
ATF_CHECK_EQ_MSG(expected, act,
|
||||
"sse42_crc32c expected 0x%08x, got 0x%08x", expected, act);
|
||||
}
|
||||
#elif defined(__aarch64__)
|
||||
act = armv8_crc32c(crc32c, buffer, length);
|
||||
ATF_CHECK_EQ_MSG(expected, act,
|
||||
"armv8_crc32c expected 0x%08x, got 0x%08x", expected, act);
|
||||
#endif
|
||||
act = singletable_crc32c(crc32c, buffer, length);
|
||||
ATF_CHECK_EQ_MSG(expected, act,
|
||||
"singletable_crc32c expected 0x%08x, got 0x%08x", expected, act);
|
||||
act = multitable_crc32c(crc32c, buffer, length);
|
||||
ATF_CHECK_EQ_MSG(expected, act,
|
||||
"multitable_crc32c expected 0x%08x, got 0x%08x", expected, act);
|
||||
}
|
||||
|
||||
ATF_TC_WITHOUT_HEAD(crc32c_basic_correctness);
|
||||
ATF_TC_BODY(crc32c_basic_correctness, tc)
|
||||
{
|
||||
|
@ -77,21 +113,11 @@ ATF_TC_BODY(crc32c_basic_correctness, tc)
|
|||
0xfd562dc3,
|
||||
};
|
||||
size_t i;
|
||||
uint32_t act;
|
||||
|
||||
ATF_REQUIRE(nitems(inputs) == nitems(results));
|
||||
|
||||
for (i = 0; i < nitems(inputs); i++) {
|
||||
#if defined(__amd64__) || defined(__i386__)
|
||||
act = sse42_crc32c(~0, (const void *)&inputs[i],
|
||||
sizeof(inputs[0]));
|
||||
#else
|
||||
act = armv8_crc32c(~0, (const void *)&inputs[i],
|
||||
sizeof(inputs[0]));
|
||||
#endif
|
||||
ATF_REQUIRE_MSG(act == results[i],
|
||||
"crc32c(0x%jx) = 0x%08x, got 0x%08x", (uintmax_t)inputs[i],
|
||||
results[i], act);
|
||||
check_crc32c(results[i], ~0u, &inputs[i], sizeof(inputs[0]));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -102,20 +128,10 @@ ATF_TC_BODY(crc32c_alignment, tc)
|
|||
const uint32_t result = 0x2ce33ede;
|
||||
unsigned char buf[15];
|
||||
size_t i;
|
||||
uint32_t act;
|
||||
|
||||
|
||||
for (i = 1; i < 8; i++) {
|
||||
memcpy(&buf[i], &input, sizeof(input));
|
||||
|
||||
#if defined(__amd64__) || defined(__i386__)
|
||||
act = sse42_crc32c(~0, (const void *)&buf[i], sizeof(input));
|
||||
#else
|
||||
act = armv8_crc32c(~0, (const void *)&buf[i], sizeof(input));
|
||||
#endif
|
||||
ATF_REQUIRE_MSG(act == result,
|
||||
"crc32c(0x%jx) = 0x%08x, got 0x%08x", (uintmax_t)input,
|
||||
result, act);
|
||||
check_crc32c(result, ~0u, &buf[i], sizeof(input));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -127,15 +143,8 @@ ATF_TC_BODY(crc32c_trailing_bytes, tc)
|
|||
0xd4, 0x4, 0x5e, 0xa9, 0xb3
|
||||
};
|
||||
const uint32_t result = 0xec638d62;
|
||||
uint32_t act;
|
||||
|
||||
#if defined(__amd64__) || defined(__i386__)
|
||||
act = sse42_crc32c(~0, input, sizeof(input));
|
||||
#else
|
||||
act = armv8_crc32c(~0, input, sizeof(input));
|
||||
#endif
|
||||
ATF_REQUIRE_MSG(act == result, "expected 0x%08x, got 0x%08x", result,
|
||||
act);
|
||||
check_crc32c(result, ~0u, input, sizeof(input));
|
||||
}
|
||||
|
||||
ATF_TP_ADD_TCS(tp)
|
||||
|
|
Loading…
Reference in a new issue