ikvmnet / ikvm

A Java Virtual Machine and Bytecode-to-IL Converter for .NET
Other
1.27k stars 119 forks source link

Port AES-NI from Hotspot to IKVM #390

Open AliveDevil opened 1 year ago

AliveDevil commented 1 year ago

There are some intrinsics in JDK, that allow runtime swapping of class implementations. AES-NI would allow getting ikvmnet from 16 MByte/s (128 MBit/s) up to JDK-level (Gigabit, beyond) in AES-scenarios. This heavily limits the usage in high-bandwidth encrypted data transfers (HTTP, FTP, etc.). An IKVM-fork got more bandwidth, than ikvmnet, reasons are unclear, for now: iterate-ch/cyberduck#14909

IKVM is currently targeting x86, x64, aarch64 and arm.

Ref implementation, against jdk8u92. x86: https://github.com/openjdk/jdk8u/blob/jdk8u92-b34/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp#L2189 x64: https://github.com/openjdk/jdk8u/blob/jdk8u92-b34/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp#L3031

With JDK8u312 aarch64 has been added: arm64: https://github.com/openjdk/jdk8u/blob/jdk8u312-ga/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp#L2606

JDK8 doesn't have an implementation for AES-NI in arm, this would require sourcing the native implementation from e.g. jdk9: https://github.com/openjdk/jdk/blob/jdk-9%2B150/hotspot/src/cpu/arm/vm/stubRoutinesCrypto_arm.cpp#L120

This could probably be replaced with regular PInvoke on IKVM-side, and simple implementations without the stub-magic in C.

Stubbing is performed in vmSymbols-file: https://github.com/openjdk/jdk8u/blob/jdk8u92-b34/hotspot/src/share/vm/classfile/vmSymbols.hpp#L819-L833

PInvoke signature could look like:

void com_sun_crypto_provider_aescrypt_encryptBlock(byte*, int, byte*, int);
void com_sun_crypto_provider_aescrypt_decryptBlock(byte*, int, byte*, int);

This would need detecting CPU-features in runtime and selecting appropriate implementation (AES-NI or Java) based on that.

As we now have native library-support, we could look at adding this to libjava/libjvm.

AliveDevil commented 1 year ago

Research brought up: Slowest path in IKVM is com.sun.crypto.provider.GHASH.update(uint8[], int, int). This lead to finding this: https://github.com/openjdk/jdk8u/blob/jdk8u312-ga/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp#L3664 Which got added as recently as 8u242. Need to port GHash intrinsics as well then.

AliveDevil commented 1 year ago

Discussion around this resolved to this:

AliveDevil commented 1 year ago

Intrinsics: com/sun/crypto/provider/AESCrypt, methods

com/sun/crypto/provider/CipherBlockChaining, methods: