LowEndTalk member @forest shared an interesting technique to enable AES-NI even when the provider doesn’t pass it through.
OpenSSL can read an environment setting which will use the host CPU’s AES-NI code, even if the provider presents a generic, non-AES CPU. Why? As @forest puts it:
…all QEMU does is change the effect of the CPUID instruction to stop advertising AES-NI support. But the AES-NI instructions can’t be trapped, so they’ll always work if the guest attempts to issue them and the hardware supports them.
If you have a bleeding-edge kernel, you can add a line to the kernel’s command line. I don’t have anything quite that bleeding edge, but I spun up a Debian 13 VPS in my home Proxmox environment to test it.
The host CPU is an Intel i5-8250. Flags:
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb pti ssbd ibrs ibpb stibp tpr_shadow flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp vnmi md_clear flush_l1d ibpb_exit_to_user
I created a VM and turned off AES:

After booting, /proc/cpuinfo shows:
processor : 0 vendor_id : GenuineIntel cpu family : 15 model : 107 model name : QEMU Virtual CPU version 2.5+ stepping : 1 microcode : 0x1 cpu MHz : 1799.997 cache size : 16384 KB physical id : 0 siblings : 2 core id : 0 cpu cores : 2 apicid : 0 initial apicid : 0 fpu : yes fpu_exception : yes cpuid level : 13 wp : yes flags : fpu de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx lm constant_tsc nopl xtopology cpuid tsc_known_freq pni ssse3 cx16 sse4_1 sse4_2 x2apic popcnt hypervisor lahf_lm cpuid_fault pti bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs itlb_multihit mmio_unknown bhi its bogomips : 3599.99 clflush size : 64 cache_alignment : 128 address sizes : 40 bits physical, 48 bits virtual power management:
Or more simply:
root@cheyenne:~# grep aes /proc/cpuinfo root@cheyenne:~#
Now, I set the environment variable (see LowEndTalk) in /etc/environment. This doesn’t put the aes flag into /proc/cpuinfo (you’d need Linux >= 6.15 for that to work, and this Deb 13 only has 6.12) but openssl noticed the difference.
I conducted a test, running
openssl speed -evp aes-128-gcmwhere OpenSSL know about the AES-NI change, and
OPENSSL_ia32cap="~0x200000200000000" openssl speed -evp aes-128-gcmto disable it. Here’s the results when OpenSSL doesn’t know AES-NI is available, expressed as 1000s of bytes per second processed.
type 16 bytes 64 bytes 256 bytes 1024 bytes 8192 bytes 16384 bytes AES-128-GCM 23742.96k 54507.56k 161768.36k 223708.50k 248173.91k 253700.78k AES-128-GCM 22595.02k 56259.63k 163820.29k 217182.55k 249061.38k 252952.58k AES-128-GCM 25263.70k 57340.35k 157953.79k 219676.67k 251308.09k 251346.94k AES-128-GCM 25034.56k 54598.95k 154434.90k 229229.23k 251330.56k 253542.40k AES-128-GCM 24268.28k 54054.95k 149522.18k 221888.51k 249987.07k 250609.44k AES-128-GCM 22205.23k 54394.26k 154687.40k 221060.44k 246680.23k 250631.51k AES-128-GCM 23914.66k 56894.49k 163471.87k 225880.41k 253856.43k 252706.82k AES-128-GCM 22851.15k 58245.33k 155108.35k 226806.44k 251527.17k 251964.07k AES-128-GCM 22334.89k 58429.91k 153731.50k 226722.13k 247305.56k 244110.68k AES-128-GCM 22744.85k 58385.28k 161000.62k 222503.59k 247987.46k 246721.19k
And when OpenSSL does know about AES-NI:
type 16 bytes 64 bytes 256 bytes 1024 bytes 8192 bytes 16384 bytes AES-128-GCM 39364.50k 137706.85k 274209.88k 395095.38k 429694.98k 426306.22k AES-128-GCM 41216.78k 140006.89k 287575.13k 404291.24k 443310.08k 445923.33k AES-128-GCM 47618.55k 138826.41k 297024.94k 393789.78k 435423.91k 441821.87k AES-128-GCM 47737.88k 145784.13k 276959.91k 398552.75k 431426.22k 441969.32k AES-128-GCM 44153.77k 135803.56k 264861.44k 376348.67k 424419.33k 412259.67k AES-128-GCM 49602.42k 136317.44k 283622.83k 403563.18k 435680.60k 443973.63k AES-128-GCM 45073.05k 142177.83k 299664.55k 401787.90k 445480.96k 447321.43k AES-128-GCM 43739.06k 127955.88k 287771.31k 382980.44k 426344.45k 430096.38k AES-128-GCM 44878.53k 139109.03k 279658.41k 395250.35k 439675.56k 445360.81k AES-128-GCM 47816.07k 141160.49k 286757.55k 395026.43k 443569.49k 445169.66k
So nearly a 2x improvement!





















Leave a Reply