diff --git a/api/util/crc32.hpp b/api/util/crc32.hpp index 3f0a3173bb..3a587cd44e 100644 --- a/api/util/crc32.hpp +++ b/api/util/crc32.hpp @@ -81,15 +81,41 @@ static uint32_t crc_32_tab[] = for (; len; --len, ++buf) partial = UPDC32(*buf, partial); - + return partial; #undef UPDC32 } +#ifdef __SSE4_2__ +#include + +inline uint32_t crc32_hw(const uint8_t* buffer, size_t len) +{ + uint32_t hash = 0xFFFFFFFF; + for (size_t i = 0; i < len; i++) { + hash = _mm_crc32_u8(hash, buffer[i]); + } + return hash ^ 0xFFFFFFFF; +} +#endif + +/** Ethernet/ZIP **/ inline uint32_t crc32(const void* buf, size_t len) { return ~crc32(0xFFFFFFFF, (const char*) buf, len); } +/** Intel (iSCSI) or vanilla-polynomial, DONT mix with other code **/ +/** This variant uses the fastest CRC method possible, but we don't + know which polynomial it will use, so use with care! **/ +inline uint32_t crc32_fast(const void* buf, size_t len) +{ +#ifdef __SSE4_2__ + return crc32_hw((const uint8_t*) buf, len); +#else + return ~crc32(0xFFFFFFFF, (const char*) buf, len); +#endif +} + #endif diff --git a/src/kernel/sanity_checks.cpp b/src/kernel/sanity_checks.cpp index f488e49a91..c5c073594f 100644 --- a/src/kernel/sanity_checks.cpp +++ b/src/kernel/sanity_checks.cpp @@ -40,9 +40,7 @@ static void self_test_gconstr() { static uint32_t generate_ro_crc() noexcept { - uint32_t crc = CRC32_BEGIN(); - crc = crc32(crc, &_TEXT_START_, &_RODATA_END_ - &_TEXT_START_); - return CRC32_VALUE(crc); + return crc32_fast(&_TEXT_START_, &_RODATA_END_ - &_TEXT_START_); } extern "C" diff --git a/src/kernel/softreset.cpp b/src/kernel/softreset.cpp index e5e04e6e0a..213f68420a 100644 --- a/src/kernel/softreset.cpp +++ b/src/kernel/softreset.cpp @@ -35,7 +35,7 @@ void OS::resume_softreset(intptr_t addr) /// validate soft-reset data const uint32_t csum_copy = data->checksum; data->checksum = 0; - uint32_t crc = crc32(data, sizeof(softreset_t)); + uint32_t crc = crc32_fast(data, sizeof(softreset_t)); if (crc != csum_copy) { kprintf("[!] Failed to verify CRC of softreset data: %08x vs %08x\n", crc, csum_copy); @@ -66,7 +66,7 @@ void* __os_store_soft_reset(void* extra, size_t extra_len) data->extra = extra; data->extra_len = extra_len; - uint32_t csum = crc32(data, sizeof(softreset_t)); + uint32_t csum = crc32_fast(data, sizeof(softreset_t)); data->checksum = csum; return data; }