mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-06 16:40:47 +00:00
Switch to an ifunc in the kernel for crc32c
There is no need to read the same variable to check if the CPU supports crc32c instructions. Reviewed by: arichardson, kib, markj Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D31274
This commit is contained in:
parent
4d15976919
commit
a93941b439
|
@ -55,11 +55,12 @@ __FBSDID("$FreeBSD$");
|
|||
#if defined(__amd64__) || defined(__i386__)
|
||||
#include <machine/md_var.h>
|
||||
#include <machine/specialreg.h>
|
||||
#include <x86/ifunc.h>
|
||||
#endif
|
||||
|
||||
#if defined(__aarch64__)
|
||||
#include <machine/elf.h>
|
||||
#include <machine/md_var.h>
|
||||
#include <machine/armreg.h>
|
||||
#include <machine/ifunc.h>
|
||||
#endif
|
||||
#endif /* _KERNEL */
|
||||
|
||||
|
@ -750,29 +751,48 @@ multitable_crc32c(uint32_t crc32c,
|
|||
return (crc32c_sb8_64_bit(crc32c, buffer, length, to_even_word));
|
||||
}
|
||||
|
||||
uint32_t
|
||||
calculate_crc32c(uint32_t crc32c,
|
||||
const unsigned char *buffer,
|
||||
unsigned int length)
|
||||
static uint32_t
|
||||
table_crc32c(uint32_t crc32c, const unsigned char *buffer, unsigned int length)
|
||||
{
|
||||
#ifdef _KERNEL
|
||||
#if defined(__amd64__) || defined(__i386__)
|
||||
if ((cpu_feature2 & CPUID2_SSE42) != 0) {
|
||||
return (sse42_crc32c(crc32c, buffer, length));
|
||||
} else
|
||||
#endif
|
||||
#if defined(__aarch64__)
|
||||
if ((elf_hwcap & HWCAP_CRC32) != 0) {
|
||||
return (armv8_crc32c(crc32c, buffer, length));
|
||||
} else
|
||||
#endif
|
||||
#endif /* _KERNEL */
|
||||
if (length < 4) {
|
||||
return (singletable_crc32c(crc32c, buffer, length));
|
||||
} else {
|
||||
return (multitable_crc32c(crc32c, buffer, length));
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(_KERNEL) && defined(__aarch64__)
|
||||
DEFINE_IFUNC(, uint32_t, calculate_crc32c,
|
||||
(uint32_t crc32c, const unsigned char *buffer, unsigned int length))
|
||||
{
|
||||
uint64_t reg;
|
||||
|
||||
if (get_kernel_reg(ID_AA64ISAR0_EL1, ®)) {
|
||||
if (ID_AA64ISAR0_CRC32_VAL(reg) >= ID_AA64ISAR0_CRC32_BASE)
|
||||
return (armv8_crc32c);
|
||||
}
|
||||
|
||||
return (table_crc32c);
|
||||
}
|
||||
#elif defined(_KERNEL) && (defined(__amd64__) || defined(__i386__))
|
||||
DEFINE_IFUNC(, uint32_t, calculate_crc32c,
|
||||
(uint32_t crc32c, const unsigned char *buffer, unsigned int length))
|
||||
{
|
||||
if ((cpu_feature2 & CPUID2_SSE42) != 0)
|
||||
return (sse42_crc32c);
|
||||
|
||||
return (table_crc32c);
|
||||
}
|
||||
#else
|
||||
uint32_t
|
||||
calculate_crc32c(uint32_t crc32c,
|
||||
const unsigned char *buffer,
|
||||
unsigned int length)
|
||||
{
|
||||
return (table_crc32c(crc32c, buffer, length));
|
||||
}
|
||||
#endif /* _KERNEL && __aarch64__ */
|
||||
|
||||
#else
|
||||
uint32_t
|
||||
calculate_crc32c(uint32_t crc32c, const unsigned char *buffer, unsigned int length)
|
||||
|
|
Loading…
Reference in a new issue