QRandom: add support for RDSEED
The Intel whitepaer[1] recommends using the RDSEED over RDRAND whenever present. libstdc++ from GCC 10 will also use it in std::random_device. [ChangeLog][QtCore][QRandomGenerator] The system() random generator will now use the RDSEED instruction on x86 processors whenever available as the first source of random data. It will fall back to RDRAND and then to the system functions, in that order. [1] https://software.intel.com/en-us/articles/intel-digital-random-number-generator-drng-software-implementation-guide Change-Id: I907a43cd9a714da288a2fffd15bab176e54e1975 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
This commit is contained in:
parent
74858dc4af
commit
780137d585
@ -132,6 +132,23 @@ attribute_target("rdrnd") int test_rdrnd()
|
||||
}
|
||||
#endif
|
||||
|
||||
#if T(RDSEED)
|
||||
attribute_target("rdseed") int test_rdseed()
|
||||
{
|
||||
unsigned short us;
|
||||
unsigned int ui;
|
||||
if (_rdseed16_step(&us))
|
||||
return 1;
|
||||
if (_rdseed32_step(&ui))
|
||||
return 1;
|
||||
# if defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(_M_X64)
|
||||
unsigned long long ull;
|
||||
if (_rdseed64_step(&ull))
|
||||
return 1;
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if T(SHANI)
|
||||
attribute_target("sha") void test_shani()
|
||||
{
|
||||
|
@ -527,6 +527,10 @@
|
||||
"label": "RDRAND instruction",
|
||||
"type": "x86Simd"
|
||||
},
|
||||
"rdseed": {
|
||||
"label": "RDSEED instruction",
|
||||
"type": "x86Simd"
|
||||
},
|
||||
"shani": {
|
||||
"label": "SHA new instructions",
|
||||
"type": "x86Simd"
|
||||
@ -1181,6 +1185,14 @@
|
||||
{ "type": "define", "name": "QT_COMPILER_SUPPORTS_RDRND", "value": 1 }
|
||||
]
|
||||
},
|
||||
"rdseed": {
|
||||
"label": "RDSEED",
|
||||
"condition": "tests.rdseed",
|
||||
"output": [
|
||||
"privateConfig",
|
||||
{ "type": "define", "name": "QT_COMPILER_SUPPORTS_RDSEED", "value": 1 }
|
||||
]
|
||||
},
|
||||
"shani": {
|
||||
"label": "SHA",
|
||||
"condition": "features.sse2 && tests.shani",
|
||||
|
@ -93,6 +93,7 @@ QMAKE_CFLAGS_SSE4_1 += -msse4.1
|
||||
QMAKE_CFLAGS_SSE4_2 += -msse4.2
|
||||
QMAKE_CFLAGS_F16C += -mf16c
|
||||
QMAKE_CFLAGS_RDRND += -mrdrnd
|
||||
QMAKE_CFLAGS_RDSEED += -mrdseed
|
||||
QMAKE_CFLAGS_AVX += -mavx
|
||||
QMAKE_CFLAGS_AVX2 += -mavx2
|
||||
QMAKE_CFLAGS_AVX512F += -mavx512f
|
||||
|
@ -51,6 +51,7 @@ QMAKE_CFLAGS_AVX512VL += -march=skylake-avx512
|
||||
QMAKE_CFLAGS_AESNI += -maes
|
||||
QMAKE_CFLAGS_F16C += $$QMAKE_CFLAGS_AVX2
|
||||
QMAKE_CFLAGS_RDRND += -mrdrnd
|
||||
QMAKE_CFLAGS_RDSEED += -mrdseed
|
||||
QMAKE_CFLAGS_SHANI += -msha
|
||||
|
||||
QMAKE_CXX = icpc
|
||||
|
@ -50,6 +50,7 @@ greaterThan(QMAKE_MSC_VER, 1799) {
|
||||
|
||||
QMAKE_CFLAGS_F16C = -arch:AVX
|
||||
QMAKE_CFLAGS_RDRND =
|
||||
QMAKE_CFLAGS_RDSEED =
|
||||
|
||||
equals(QMAKE_MSC_VER, 1800) {
|
||||
QMAKE_CFLAGS_RELEASE += -Zc:strictStrings
|
||||
|
@ -137,6 +137,7 @@ addSimdCompiler(avx512ifma)
|
||||
addSimdCompiler(avx512vbmi)
|
||||
addSimdCompiler(f16c)
|
||||
addSimdCompiler(rdrnd)
|
||||
addSimdCompiler(rdseed)
|
||||
addSimdCompiler(neon)
|
||||
addSimdCompiler(mips_dsp)
|
||||
addSimdCompiler(mips_dspr2)
|
||||
|
@ -15,6 +15,7 @@ QMAKE_CFLAGS_AVX = -mavx
|
||||
QMAKE_CFLAGS_AVX2 = -mavx2
|
||||
QMAKE_CFLAGS_F16C = -mf16c
|
||||
QMAKE_CFLAGS_RDRND = -mrdrnd
|
||||
QMAKE_CFLAGS_RDSEED = -mrdseed
|
||||
QMAKE_CFLAGS_AVX512F = -mavx512f
|
||||
QMAKE_CFLAGS_AVX512ER = -mavx512er
|
||||
QMAKE_CFLAGS_AVX512CD = -mavx512cd
|
||||
|
@ -626,8 +626,40 @@ void qDumpCPUFeatures()
|
||||
|
||||
# ifdef Q_PROCESSOR_X86_64
|
||||
# define _rdrandXX_step _rdrand64_step
|
||||
# define _rdseedXX_step _rdseed64_step
|
||||
# else
|
||||
# define _rdrandXX_step _rdrand32_step
|
||||
# define _rdseedXX_step _rdseed32_step
|
||||
# endif
|
||||
|
||||
# if QT_COMPILER_SUPPORTS_HERE(RDSEED)
|
||||
static QT_FUNCTION_TARGET(RDSEED) unsigned *qt_random_rdseed(unsigned *ptr, unsigned *end) noexcept
|
||||
{
|
||||
// Unlike for the RDRAND code below, the Intel whitepaper describing the
|
||||
// use of the RDSEED instruction indicates we should not retry in a loop.
|
||||
// If the independent bit generator used by RDSEED is out of entropy, it
|
||||
// may take time to replenish.
|
||||
// https://software.intel.com/en-us/articles/intel-digital-random-number-generator-drng-software-implementation-guide
|
||||
while (ptr + sizeof(qregisteruint)/sizeof(*ptr) <= end) {
|
||||
if (_rdseedXX_step(reinterpret_cast<qregisteruint *>(ptr)) == 0)
|
||||
goto out;
|
||||
ptr += sizeof(qregisteruint)/sizeof(*ptr);
|
||||
}
|
||||
|
||||
if (sizeof(*ptr) != sizeof(qregisteruint) && ptr != end) {
|
||||
if (_rdseed32_step(ptr) == 0)
|
||||
goto out;
|
||||
++ptr;
|
||||
}
|
||||
|
||||
out:
|
||||
return ptr;
|
||||
}
|
||||
# else
|
||||
static unsigned *qt_random_rdseed(unsigned *ptr, unsigned *)
|
||||
{
|
||||
return ptr;
|
||||
}
|
||||
# endif
|
||||
|
||||
QT_FUNCTION_TARGET(RDRND) qsizetype qRandomCpu(void *buffer, qsizetype count) noexcept
|
||||
@ -636,6 +668,9 @@ QT_FUNCTION_TARGET(RDRND) qsizetype qRandomCpu(void *buffer, qsizetype count) no
|
||||
unsigned *end = ptr + count;
|
||||
int retries = 10;
|
||||
|
||||
if (qCpuHasFeature(RDSEED))
|
||||
ptr = qt_random_rdseed(ptr, end);
|
||||
|
||||
while (ptr + sizeof(qregisteruint)/sizeof(*ptr) <= end) {
|
||||
if (_rdrandXX_step(reinterpret_cast<qregisteruint *>(ptr)))
|
||||
ptr += sizeof(qregisteruint)/sizeof(*ptr);
|
||||
@ -657,5 +692,4 @@ out:
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
Loading…
x
Reference in New Issue
Block a user