[RFC] Microcode Update Driver for AMD K8 CPUs

From: Danny van Dyk
Date: Sun Aug 15 2004 - 10:47:23 EST


Hi @ all!

[First of all, please CC me on all responses as I am not subscribed to lkml. Thanx in advance.]

I recently found some piece of code [1] to perform a microcode update on AMD's K8 CPUs. It included some update blocks hardcoded into the module.

gregkh pointed out that this is no good style and that the module should rather use /dev/microcode to provide the kernel with the latest ucode block.


Therefore I rewrote the module to do it similar to the i386 Intel microcode update code. The update block gets written to /dev/microcode. The k8_ucode_write() function does nothing but copying the data from userspace to kernelspace, using means to avoid multiple concurrent writes. After that, the userspace application performs the K8_IOCTL_UCODE_UPDATE ioctl(). This starts the update process for each cpu, checking that the update block is valid and checks for all cpus if their cpuid matches the header's cpuid.

You will find the latest version of the module here [2]. Further it _should_ now be SMP safe; should meaning that I had no chance/no hardware to test it on.


However, I still experience one bug concerning the first update to be performed after loading the module:

The module holds a pointer to a 960 bytes large buffer, holding the actual update block. This buffer gets memset'ed with the pattern 0xA0A0A0A0. When the module's write operation gets used the first time, copy_from_user _definitely_ returns 0, telling me that all the 960 bytes have been written to the buffer. On the other side, when performing the ioctl to start the update, the module tells me that the signature is not 0x00aaaaaa as expected for a valid update, but rather the same pattern which was written into the empty buffer at the beginning. Even stranger is, that the same thing then works for all the following calls to the update application. Have I misunderstood the copy_from_user() function and its return value ? Or is that a bug ?


The process of updating the microcode is rather simple - at least compared to the things the i386 driver does. To start it, you need
a block of 960 bytes containing the update block (I extracted 2 blocks from the bios update for my ASUS K8V MoBo). This block consists of a 64 byte long header and a 896 byte long data block. The header contains - among other things - the signature 0x00AAAAAA and a 32bit checksum. That checksum gets computed by just makeing a sum of all words in the data block.
Performing a msr call with the adress of this updata block in edx:eax and the magic 0xC0010020 in ecx starts the actual update.


Please tell me what you think about this. Ah, and Greg mentioned some problems with my coding style. Would someone please tell me what I did wrong ? ;-)

Danny

[1] http://www.realworldtech.com/forums/index.cfm?action=detail&PostNum=2527&Thread=1&entryID=35446&roomID=11
[2] http://dev.gentoo.org/~kugelfang/k8-ucode/

--
Danny van Dyk
Gentoo/AMD64 Developer
kugelfang@xxxxxxxxxx
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/