git: 4bc8d0dcdb37 - stable/13 - Switch to an ifunc in the kernel for crc32c

Andrew Turner andrew at FreeBSD.org
Mon Aug 30 12:43:12 UTC 2021


The branch stable/13 has been updated by andrew:

URL: https://cgit.FreeBSD.org/src/commit/?id=4bc8d0dcdb3739eaf771727797d70220f4bd2f6e

commit 4bc8d0dcdb3739eaf771727797d70220f4bd2f6e
Author:     Andrew Turner <andrew at FreeBSD.org>
AuthorDate: 2021-07-22 10:24:33 +0000
Commit:     Andrew Turner <andrew at FreeBSD.org>
CommitDate: 2021-08-30 11:22:21 +0000

    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
    
    (cherry picked from commit a93941b439fce7047dffad6bc380cc9454b967cd)
---
 sys/libkern/gsb_crc32.c | 56 +++++++++++++++++++++++++++++++++----------------
 1 file changed, 38 insertions(+), 18 deletions(-)

diff --git a/sys/libkern/gsb_crc32.c b/sys/libkern/gsb_crc32.c
index 170ceb3aa710..27b9a926888b 100644
--- a/sys/libkern/gsb_crc32.c
+++ b/sys/libkern/gsb_crc32.c
@@ -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, &reg)) {
+		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)


More information about the dev-commits-src-all mailing list