Skip to content

Commit 58f184a

Browse files
committed
MDEV-24745 Generic CRC-32C computation wrongly uses SSE4.2 instructions
In commit d25f806 (MDEV-22749) the CRC-32C implementation of MariaDB was broken on some IA-32 and AMD64 builds, depending on the compiler version and build options. This was verified for IA-32 on GCC 10.2.1. Even though we try to identify the SSE4.2 extensions and the availaibility of the PCLMULQDQ instruction by executing CPUID, the fall-back code could be generated with extended instructions, because the entire file mysys/crc32/crc32c.c was being compiled with -msse4.2 -mpclmul. This would cause SIGILL on a PINSRD instruction on affected IA-32 targets (such as some Intel Atom processors). This might also affect old AMD64 processors (predating the 2007 Intel Nehalem microarchitecture), if some compiler chose to emit the offending instructions. While it is fine to pass a target-specific option to a target-specific compilation unit (like -mpclmul to a PCLMUL-specific compilation unit), that is not safe for mixed-architecture compilation units. For mixed-architecture compilation units, the correct way is to set target attributes on the target-specific functions. There does not seem to be a way to pass target attributes to function template instantiation. Hence, we must replace the ExtendImpl template with plain functions crc32_sse42() and crc32_slow(). We will also remove some inconsistency between my_crc32_implementation() and mysys_namespace::crc32::Choose_Extend(). The function crc32_pclmul_enabled() will be moved to mysys/crc32/crc32c.cc so that the detection code will be compiled without -msse4.2 -mpclmul. The AMD64 PCLMUL accelerated crc32c_3way() will be moved to a new file crc32c_amd64.cc. In this way, only a few functions that depend on -msse4.2 in mysys/crc32/crc32c.cc can be declared with __attribute__((target("sse4.2"))), and most of the file can be compiled for the generic target. Last, the file mysys/crc32ieee.cc will be omitted on 64-bit POWER, because it was dead code (no symbols were exported). Reviewed by: Vladislav Vaintroub
1 parent 18a8290 commit 58f184a

File tree

5 files changed

+879
-867
lines changed

5 files changed

+879
-867
lines changed

mysys/CMakeLists.txt

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR} ${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/mysys)
1818

19-
SET(MYSYS_SOURCES array.c charset-def.c charset.c crc32ieee.cc my_default.c
19+
SET(MYSYS_SOURCES array.c charset-def.c charset.c my_default.c
2020
get_password.c
2121
errors.c hash.c list.c
2222
mf_cache.c mf_dirname.c mf_fn_ext.c
@@ -60,19 +60,29 @@ ENDIF()
6060

6161
IF(MSVC)
6262
SET(MYSYS_SOURCES ${MYSYS_SOURCES} crc32/crc32_x86.c)
63+
IF(CMAKE_SIZEOF_VOID_P EQUAL 8)
64+
SET (MYSYS_SOURCES ${MYSYS_SOURCES} crc32/crc32c_amd64.cc)
65+
ENDIF()
6366
ADD_DEFINITIONS(-DHAVE_SSE42 -DHAVE_PCLMUL)
6467
IF(CLANG_CL)
65-
SET_SOURCE_FILES_PROPERTIES(crc32/crc32_x86.cc crc32/crc32c.c PROPERTIES COMPILE_FLAGS "-msse4.2 -mpclmul")
68+
SET_SOURCE_FILES_PROPERTIES(crc32/crc32_x86.c PROPERTIES COMPILE_FLAGS "-msse4.2 -mpclmul")
6669
ENDIF()
6770
ELSEIF(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|amd64|i386|i686")
68-
MY_CHECK_C_COMPILER_FLAG(-msse4.2)
69-
MY_CHECK_C_COMPILER_FLAG(-mpclmul)
71+
MY_CHECK_CXX_COMPILER_FLAG(-msse4.2)
72+
MY_CHECK_CXX_COMPILER_FLAG(-mpclmul)
7073
CHECK_INCLUDE_FILE(cpuid.h HAVE_CPUID_H)
7174
CHECK_INCLUDE_FILE(x86intrin.h HAVE_X86INTRIN_H)
72-
IF(have_C__msse4.2 AND have_C__mpclmul AND HAVE_CPUID_H AND HAVE_X86INTRIN_H)
73-
SET(MYSYS_SOURCES ${MYSYS_SOURCES} crc32/crc32_x86.c)
74-
SET_SOURCE_FILES_PROPERTIES(crc32/crc32_x86.c crc32/crc32c.cc PROPERTIES COMPILE_FLAGS "-msse4.2 -mpclmul")
75-
ADD_DEFINITIONS(-DHAVE_SSE42 -DHAVE_PCLMUL)
75+
IF(have_CXX__msse4.2 AND HAVE_CPUID_H)
76+
ADD_DEFINITIONS(-DHAVE_SSE42)
77+
IF (have_CXX__mpclmul AND HAVE_X86INTRIN_H)
78+
ADD_DEFINITIONS(-DHAVE_PCLMUL)
79+
SET(MYSYS_SOURCES ${MYSYS_SOURCES} crc32/crc32_x86.c)
80+
SET_SOURCE_FILES_PROPERTIES(crc32/crc32_x86.c PROPERTIES COMPILE_FLAGS "-msse4.2 -mpclmul")
81+
IF(CMAKE_SIZEOF_VOID_P EQUAL 8)
82+
SET(MYSYS_SOURCES ${MYSYS_SOURCES} crc32/crc32c_amd64.cc)
83+
SET_SOURCE_FILES_PROPERTIES(crc32/crc32c_amd64.cc PROPERTIES COMPILE_FLAGS "-msse4.2 -mpclmul")
84+
ENDIF()
85+
ENDIF()
7686
ENDIF()
7787
ELSEIF(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|AARCH64")
7888
IF(CMAKE_COMPILER_IS_GNUCC)
@@ -129,11 +139,15 @@ ELSEIF(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|AARCH64")
129139
COMPILE_FLAGS "-march=armv8-a+crc+crypto")
130140
ENDIF()
131141
ENDIF()
132-
ELSEIF(CMAKE_SYSTEM_PROCESSOR MATCHES "ppc64|powerpc64" OR CMAKE_SYSTEM_NAME MATCHES AIX)
142+
ENDIF()
143+
144+
IF(CMAKE_SYSTEM_PROCESSOR MATCHES "ppc64|powerpc64" OR CMAKE_SYSTEM_NAME MATCHES AIX)
133145
SET(MYSYS_SOURCES ${MYSYS_SOURCES} crc32/crc32_ppc64.c crc32/crc32c_ppc.c)
134146
SET_SOURCE_FILES_PROPERTIES(crc32/crc32_ppc64.c crc32/crc32c_ppc.c PROPERTIES
135147
COMPILE_FLAGS "${COMPILE_FLAGS} -maltivec -mvsx -mpower8-vector -mcrypto -mpower8-vector")
136148
ADD_DEFINITIONS(-DHAVE_POWER8 -DHAS_ALTIVEC)
149+
ELSE()
150+
SET (MYSYS_SOURCES ${MYSYS_SOURCES} crc32ieee.cc)
137151
ENDIF()
138152

139153
IF(UNIX)

mysys/crc32/crc32_x86.c

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (c) 2020 MariaDB
1+
/* Copyright (c) 2020, 2021, MariaDB
22
33
This program is free software; you can redistribute it and/or modify
44
it under the terms of the GNU General Public License as published by
@@ -55,38 +55,14 @@
5555
#include <stdint.h>
5656
#include <stddef.h>
5757

58-
#if defined(__GNUC__)
58+
#ifdef __GNUC__
5959
#include <x86intrin.h>
60-
#include <cpuid.h>
6160
#elif defined(_MSC_VER)
6261
#include <intrin.h>
6362
#else
6463
#error "unknown compiler"
6564
#endif
6665

67-
static int has_sse42_and_pclmul(uint32_t recx)
68-
{
69-
/* 1 << 20 is SSE42, 1 << 1 is PCLMULQDQ */
70-
#define bits_SSE42_AND_PCLMUL (1 << 20 | 1 << 1)
71-
return (recx & bits_SSE42_AND_PCLMUL) == bits_SSE42_AND_PCLMUL;
72-
}
73-
74-
#ifdef __GNUC__
75-
int crc32_pclmul_enabled(void)
76-
{
77-
uint32_t reax= 0, rebx= 0, recx= 0, redx= 0;
78-
__cpuid(1, reax, rebx, recx, redx);
79-
return has_sse42_and_pclmul(recx);
80-
}
81-
#elif defined(_MSC_VER)
82-
int crc32_pclmul_enabled(void)
83-
{
84-
int regs[4];
85-
__cpuid(regs, 1);
86-
return has_sse42_and_pclmul(regs[2]);
87-
}
88-
#endif
89-
9066
/**
9167
* @brief Shifts left 128 bit register by specified number of bytes
9268
*

0 commit comments

Comments
 (0)