Closed pvgoran closed 4 years ago
Thanks for sharing the details. Maybe it's possible to remove global cc-options like -mssse3
and use per-file pragmas at appropriate locations instead. But need to be careful if trading toolchain support for CPU support.
Is it possible to just disable sss33 with CPP in the cabal file for CPU's that don't support it?
Is it possible to just disable sss33 with CPP in the cabal file for CPU's that don't support it?
Even if it's possible, it won't help: the problem manifests at run-time, and compile-time checks won't prevent it because the code may be run on a different machine after being compiled.
I came up with this but it may decrease compiler support: ocheron:aesni-per-file.
@ocheron Will this somehow allow the code in x86ni.c
to run on older CPUs?
I hope it will allow the code in blake2/ref
to run on older CPUs.
Normally x86ni.c
is not run, this is consistent with your report being a Blake2 failure, not AES.
EDIT: Actually this is because of the code in blake2/sse
, not blake2/ref
. On amd64 at least SSE2 is available, and the blake2 condition is OR, not AND.
Ok, this seems to work for me. Even if the test suite is compiled on another machine and copied to the old-CPU machine, it now passes successfully.
(Although I still don't understand how changing the compilation options and pragmas for AES code allows the Blake2 code to run.)
Yes it's a bit convoluted. In the AES code the library already has what is necessary to use AES-NI at runtime when the CPU supports it. But in order to compile the AES-NI variant, we need an option like -mssse3
. With a Makefile-based project the option would be enabled only on needed files easily, but with Cabal we can't do that and enable globally. When enabled, the C compiler can emit SSSE3 intructions to optimize things, including code not related to AES-NI and having a single variant at runtime. For some reason it tends to show up preferably in Blake2 but can be actually anywhere.
Thanks for giving it a try, it's useful to know the approach works with no other cause. Now it's just a matter of reading compiler release notes and deciding how/if/when we can do something like this.
Solution applied in #316 with optional package flag to restore previous behavior. Switching to function attributes instead of file pragma gives better compatibility with clang.
I have a machine with an AMD Phenom II (
AMD Phenom(tm) II X3 720 Processor
as per/proc/cpuinfo
).When I build
cryptonite
on it without specifying any configuration options, it fails the Blake2 tests:Also, when I build
git-annex
(https://git-annex.branchable.com/, uses cryptonite) and run its tests, they also fail, with a more specific message:(See https://git-annex.branchable.com/bugs/__34__Illegal_instruction__34___when_running_certain_tests_on_AMD_Phenom_II for where this came from.)
When I disable support_aesni by passing
--constraint="cryptonite -support_aesni"
tocabal
, both of these tests pass.This means that AES-NI is used in Blake2 implementation based on purely compile-time options. Because of this, any binary distribution of
cryptonite
(or a software which employscryptonite
for Blake2 hashes) will be crippled: if built with AES-NI support, it will fail hard on older CPUs; if built without AES-NI support, it will be slowed than it could be on newer CPUs.Ideally, AES-NI should only be used after checking that it is actually available at runtime. Barring this,
support_aesni
should probably be disabled by default.