At work I have a HP laptop, EliteBook 8560w, running GNU/Linux. The CPU is a Core i7 2630QM which has support for the AES-NI instructions. But it isn’t enabled. After searching high and low I found a thread where others have solved this by either upgrading their BIOS, and if that doesn’t work, patching their BIOS… I upgraded to the latest BIOS for this computer from HP, Ver. F.29 from Jan. 2013.
Then I installed the cpuid userspace application and ran:
cpuid | grep AES AES instruction = false
The BIOS upgrade didn’t help. So I tried the microcode_ctl userspace application which upgrades the CPU with the latest Intel microcode:
sudo /etc/init.d/microcode_ctl start cpuid | grep AES AES instruction = true
In the thread people talk about reading/writing to MSR register 0x13c, but in my case it was enough to install the latest microcode. Even with the most recent HP BIOS the Intel microcode is only at revision 0x18. AES-NI is available from microcode revision 0x1A and up for this CPU (and other Sandy Bridge CPU:s).
One problem remains. The microcode upgrade is temporary so it has to be installed after each reboot and doing it with microcode_tcl is way too late for the Linux kernel. It doesn’t realize the CPU capabilities flags have changed:
grep aes /proc/cpuinfo
A fix for this would be to load the microcode early, very early. This very thing is discussed by Linux kernel hacker H. Peter Anvin here and it resulted in the microcode-early patchset being available in the mainline Linux kernel from version 3.9.0-rc1 and up.
The patch itself is available here and it almost applies cleanly on my 3.7.10 kernel. Unfortunately the patch relies on another patch, which is harder to backport to 3.7.10. The easiest way is to just go with vanilla 3.9.x. Enable initrd (BLK_DEV_INITRD) and MICROCODE_EARLY from menuconfig and compile the kernel.
To actually load new microcode at boot, create an initrd image containing the microcode. First download the raw microcode from Intel and unpack it:
tar zxvf microcode-20120606-v2.tgz
The archive contains the file microcode.dat. But it has to be converted to binary form. I wrote a small C-program to do this conversion. Then create an uncompressed CPIO image containing the binary microcode:
mkdir -p initrd/kernel/x86/microcode/ cp microcode.bin initrd/kernel/x86/microcode/GenuineIntel.bin cd initrd find . | cpio -o -H newc > /boot/ucode.cpio
And tell grub to use /boot/ucode.cpio. If you already use another initrd/initramfs image, the two files can be concatenated. See Documentation/x86/early-microcode.txt. Note that you must give the flags -o -H newc to CPIO, not the flags mentioned in the documentation.
If all goes well you will have a message like this near the top of dmesg:
CPU0 microcode updated early to revision 0x28, date = 2012-04-24
This happens very early, before the Linux kernel calls the cpuid assembly instruction to determine what capabilities the CPU supports. Now aes will be available in /proc/cpuinfo and the aesni-intel kernel module will happily load. Programs like truecrypt and programs linking against openssl will also take advantage of the AES-NI accelleration.
If you have troubles creating a functioning cpio image, try mine. It has the binary microcode (revision 0x28) in the correct path. I use only that file as initrd. My grub.conf:
kernel /boot/vml-3.9.0-rc1 root=/dev/sda4 initrd /boot/ucode.cpio
If you already use another initramfs image, concatenate both:
cat /boot/ucode.cpio /boot/old-initramfs > /boot/new-initramfs
Update. The latest Intel microcode is currently 2013-02-22.