# [solved partly] Howto microcode early

## ulenrich

How to verify intel microcode was (early) loaded  ?Last edited by ulenrich on Thu Oct 30, 2014 8:25 am; edited 2 times in total

----------

## Jaglover

dmesg | grep microcode

If you have kernel timecode enabled you'll see exactly how early it was loaded.

----------

## ulenrich

My  system doesn't update revisions using the new /lib/firmware/intel-ucode files:

```
# dmesg |grep microcode

[    0.631290] microcode: CPU0 sig=0x1067a, pf=0x80, revision=0xa07

[    0.631353] microcode: CPU1 sig=0x1067a, pf=0x80, revision=0xa07

[    0.631448] microcode: Microcode Update Driver: v2.00 <tigran@aivazian.fsnet.co.uk>, Peter Oruba
```

I found /usr/src/linux-3.13.1/Documentation/x86/early-microcode.txt

saying: You have to include into your initrd

kernel/x86/microcode/GenuineIntel.bin

This My .config options 

```
# grep MICROCODE config-3.13.1-1138.localyes 

CONFIG_MICROCODE=y

CONFIG_MICROCODE_INTEL=y

# CONFIG_MICROCODE_AMD is not set

CONFIG_MICROCODE_OLD_INTERFACE=y

CONFIG_MICROCODE_INTEL_LIB=y

CONFIG_MICROCODE_INTEL_EARLY=y

# CONFIG_MICROCODE_AMD_EARLY is not set

CONFIG_MICROCODE_EARLY=y
```

[Edit] Using the old method with /lib/firmware/microcode.dat works:

```
microcode_ctl -u

/lib/firmware/microcode_ctl: writing microcode (length: 576512)

/lib/firmware/microcode_ctl: microcode successfuly written to /dev/cpu/microcode

 maci firmware # dmesg|grep microcode

[    0.631290] microcode: CPU0 sig=0x1067a, pf=0x80, revision=0xa07

[    0.631353] microcode: CPU1 sig=0x1067a, pf=0x80, revision=0xa07

[    0.631448] microcode: Microcode Update Driver: v2.00 <tigran@aivazian.fsnet.co.uk>, Peter Oruba

[ 2767.027590] microcode: CPU0 sig=0x1067a, pf=0x80, revision=0xa07

[ 2767.029728] microcode: CPU0 updated to revision 0xa0b, date = 2010-09-28

[ 2767.034279] microcode: CPU1 sig=0x1067a, pf=0x80, revision=0xa07

[ 2767.037609] microcode: CPU1 updated to revision 0xa0b, date = 2010-09-28
```

----------

## ulenrich

Ping!

Has someone managed to use and verify the early microcode kernel feature ? ! ?

----------

## ulenrich

Actually I worked out howto early microcode

using Debians iucode tool

```
iucode_tool -l  -t d ./microcode.dat --scan-system \

    --write-earlyfw=icoreduo.img
```

and use it as an initrd. That img file holds:

```
# lsinitrd icoreduo.img 

Image: icoreduo.img: 28K

========================================================================

Version: 

Arguments: 

dracut modules:

========================================================================

drwxr-xr-x   2 root     root            0 Oct 29 19:00 kernel

drwxr-xr-x   2 root     root            0 Oct 29 19:00 kernel/x86

drwxr-xr-x   2 root     root            0 Oct 29 19:00 kernel/x86/microcode

-rw-r--r--   1 root     root        24576 Oct 29 19:00 kernel/x86/microcode/GenuineIntel.bin

========================================================================
```

which added at cmdline from grub,gummiboot,refind as a prepended initrd icoreduo.img

```
# cat /proc/cmdline

initrd=\icoreduo.img initrd=\initrd init=/sbin/systemd root=/dev/sda3 systemd.unit=default.target net.ifnames=0 rootfstype=ext4 systemd.show_status=1 systemd.log_level=1 nomodeset
```

brings early in the first second: 

```
# dmesg|grep micro

[    0.000000] CPU0 microcode updated early to revision 0xa0b, date = 2010-09-28

[    0.009999] CPU1 microcode updated early to revision 0xa0b, date = 2010-09-28
```

----------

## s4e8

Yes, early microcode is different than normal initrd. It must resident first cpio segment, and must NOT compressed. You'd betterr make a microcode a seperate uncompressed cpio, than cat with other initrd.

----------

## ulenrich

Using gummiboot for an efi system you have to use initrd two times:

initrd icoreduo.img

initrd initrd-the-rest.img

But grub takes one initrd line with two files.

Why don't we have such an iucode_tool with Gentoo?

(I changed title accordingly)

----------

## Ant P.

A few years back I had a need to do this; I had a broken Intel Atom system (PSE erratum, updated microcode could fix it but it's loaded too late to have any useful effect). My solution there was an early-boot init script to grep dmesg for the error message and do a kexec reboot. It did slow cold boot down a few seconds, but works without needing any initrd/initramfs at all.

I'm guessing this "early microcode" thing is relatively new, otherwise I would've been using it back then.

----------

## s4e8

Agree, but I goto another method, embed the blob into kernel source.

 *Ant P. wrote:*   

> A few years back I had a need to do this; I had a broken Intel Atom system (PSE erratum, updated microcode could fix it but it's loaded too late to have any useful effect). My solution there was an early-boot init script to grep dmesg for the error message and do a kexec reboot. It did slow cold boot down a few seconds, but works without needing any initrd/initramfs at all.
> 
> I'm guessing this "early microcode" thing is relatively new, otherwise I would've been using it back then.

 

----------

## ulenrich

 *s4e8 wrote:*   

> Agree, but I goto another method, embed the blob into kernel source.

 

Do you in /usr/src/linux/.config for example:

CONFIG_INITRAMFS_SOURCE="/usr/local/icoreduo.img"

Give it the path to that created initrd image?

----------

## Fitzcarraldo

ulenrich, I hope you don't mind me jumping in here, as I'm also interested in finding out how to load the Intel CPU microcode early, albeit in an installation using OpenRC, and it seemed daft to create a separate thread running in parallel.

Currently I am using the 'microcode' kernel module to load the microcode into the Intel CPU at boot:

```
# rc-update -v show | grep microcode

        microcode_ctl | boot
```

```
$ grep -i microcode /usr/src/linux/.config

CONFIG_MICROCODE=m

CONFIG_MICROCODE_INTEL=y

# CONFIG_MICROCODE_AMD is not set

CONFIG_MICROCODE_OLD_INTERFACE=y

# CONFIG_MICROCODE_INTEL_EARLY is not set

# CONFIG_MICROCODE_AMD_EARLY is not set
```

In my installation the CPU microcode files are in the directory /lib/firmware/intel-ucode/ and there is also a file /lib/firmware/microcode.dat which I believe contains the raw data from which the microcode files in /lib/firmware/intel-ucode/ were created. Presumably /lib/firmware/microcode.dat is therefore not required any more?

Currently, the OpenRC initscript 'microcode_ctl' loads the microcode into the CPU during boot after the message 'Waiting for uevents to be processed ...' is displayed on VT1.

I would like to rebuild the kernel with CONFIG_MICROCODE_INTEL_EARLY=y and use the initramfs to load the CPU microcode earlier than the current method does it. I have read about it being done in Debian using the initramfs: ANNOUNCEMENT: Intel processor microcode security update. If I understand that Debian announcement correctly, the microcode 'binary blob' and an application to update the microcode can be included in the initramfs. Is that what you did? (Note to self: Presumably one would have to rebuild the initramfs each time Intel issues an update to the microcode.)

If I understand you correctly, ulenrich, you use the same approach that Arch Linux uses: Arch Wiki - Enabling Intel Microcode Updates? However, if I read s4e8 correctly, he's using a different method.

Anyway, has anyone loaded CPU firmware from the initramfs successfully in a Gentoo installation using OpenRC, and, if so, what are the precise steps required? I can't find a 'How To' use the initramfs for this purpose in Gentoo.

----------

## freke

 *ulenrich wrote:*   

>  *s4e8 wrote:*   Agree, but I goto another method, embed the blob into kernel source. 
> 
> Do you in /usr/src/linux/.config for example:
> 
> CONFIG_INITRAMFS_SOURCE="/usr/local/icoreduo.img"
> ...

 

I tried that with a img created with

```
iucode_tool -l  -t d ./microcode.dat --scan-system --write-earlyfw=icoreduo.img
```

but couldn't get it to work, didn't want to dig further into it at the moment because it's my mail/dhcp/dns-server and I'm migrating to another machine soon™

Edit:

Also tried with

```
iucode_tool -l  -t d ./microcode.dat --scan-system --write-to=icoreduo.img
```

 but that didn't help either.Last edited by freke on Mon Nov 03, 2014 6:23 pm; edited 1 time in total

----------

## s4e8

 *ulenrich wrote:*   

>  *s4e8 wrote:*   Agree, but I goto another method, embed the blob into kernel source. 
> 
> Do you in /usr/src/linux/.config for example:
> 
> CONFIG_INITRAMFS_SOURCE="/usr/local/icoreduo.img"
> ...

 

I means pre-early-microcode-update age, ATOM suffer a PSE36 bug, cause 4M hugepage to be disabed. Update microcode after initramfs built is too late, so I embed the microcode blob to kernel source, update it at early CPU detection.

----------

## freke

 *s4e8 wrote:*   

> I means pre-early-microcode-update age, ATOM suffer a PSE36 bug, cause 4M hugepage to be disabed. Update microcode after initramfs built is too late, so I embed the microcode blob to kernel source, update it at early CPU detection.

 

I guess the question was more like.... how?  :Wink: 

----------

## Fitzcarraldo

After a lot of reading over the last couple of days I believe I understand how to update the microcode early in Gentoo, and I didn't need to use any tools from other distributions to do it.

These are the kernel timings beforehand, when I was using the microcode_ctl initscript and the kernel module 'microcode' to update the microcode from revision 0x3 to 0x7 in the Intel Core i7-720QM CPU in my main laptop:

```
# dmesg | grep microcode

[   15.749533] microcode: CPU0 sig=0x106e5, pf=0x10, revision=0x3

[   15.834790] microcode: CPU0 sig=0x106e5, pf=0x10, revision=0x3

[   15.835530] microcode: CPU0 updated to revision 0x7, date = 2013-08-20

[   15.835544] microcode: CPU1 sig=0x106e5, pf=0x10, revision=0x3

[   15.835587] microcode: CPU1 sig=0x106e5, pf=0x10, revision=0x3

[   15.836241] microcode: CPU1 updated to revision 0x7, date = 2013-08-20

[   15.836257] microcode: CPU2 sig=0x106e5, pf=0x10, revision=0x3

[   15.836299] microcode: CPU2 sig=0x106e5, pf=0x10, revision=0x3

[   15.836953] microcode: CPU2 updated to revision 0x7, date = 2013-08-20

[   15.837063] microcode: CPU3 sig=0x106e5, pf=0x10, revision=0x3

[   15.837128] microcode: CPU3 sig=0x106e5, pf=0x10, revision=0x3

[   15.837767] microcode: CPU3 updated to revision 0x7, date = 2013-08-20

[   15.837857] microcode: CPU4 sig=0x106e5, pf=0x10, revision=0x3

[   15.837968] microcode: CPU4 sig=0x106e5, pf=0x10, revision=0x3

[   15.838605] microcode: CPU4 updated to revision 0x7, date = 2013-08-20

[   15.838634] microcode: CPU5 sig=0x106e5, pf=0x10, revision=0x3

[   15.838681] microcode: CPU5 sig=0x106e5, pf=0x10, revision=0x3

[   15.839357] microcode: CPU5 updated to revision 0x7, date = 2013-08-20

[   15.839390] microcode: CPU6 sig=0x106e5, pf=0x10, revision=0x3

[   15.839453] microcode: CPU6 sig=0x106e5, pf=0x10, revision=0x3

[   15.840121] microcode: CPU6 updated to revision 0x7, date = 2013-08-20

[   15.840180] microcode: CPU7 sig=0x106e5, pf=0x10, revision=0x3

[   15.840274] microcode: CPU7 sig=0x106e5, pf=0x10, revision=0x3

[   15.840911] microcode: CPU7 updated to revision 0x7, date = 2013-08-20

[   15.840997] microcode: Microcode Update Driver: v2.00 <tigran@aivazian.fsnet.co.uk>, Peter Oruba

[   26.940662] microcode: Microcode Update Driver: v2.00 removed.
```

The updates to the eight cores occurred in the period between 15.749533 and 15.840911 seconds after the kernel started, which is a long time, even if booting had not finished.

Below are the timings I am getting now after setting CONFIG_MICROCODE_EARLY and CONFIG_MICROCODE_INTEL_EARLY in the kernel and prependiing the microcode cpio file to the initramfs file (as per /usr/src/linux/Documentation/x86/early-microcode.txt, although that document only uses the term 'initrd' instead of 'initramfs' when, in fact, it is permissible to do it with an initramfs file):

```
# dmesg | grep microcode

[    0.252234] CPU1 microcode updated early to revision 0x7, date = 2013-08-20

[    0.265389] CPU2 microcode updated early to revision 0x7, date = 2013-08-20

[    0.278696] CPU3 microcode updated early to revision 0x7, date = 2013-08-20

[    1.888471] microcode: CPU0 sig=0x106e5, pf=0x10, revision=0x7

[    1.888481] microcode: CPU1 sig=0x106e5, pf=0x10, revision=0x7

[    1.888491] microcode: CPU2 sig=0x106e5, pf=0x10, revision=0x7

[    1.888498] microcode: CPU3 sig=0x106e5, pf=0x10, revision=0x7

[    1.888506] microcode: CPU4 sig=0x106e5, pf=0x10, revision=0x7

[    1.888515] microcode: CPU5 sig=0x106e5, pf=0x10, revision=0x7

[    1.888523] microcode: CPU6 sig=0x106e5, pf=0x10, revision=0x7

[    1.888534] microcode: CPU7 sig=0x106e5, pf=0x10, revision=0x7

[    1.888597] microcode: Microcode Update Driver: v2.00 <tigran@aivazian.fsnet.co.uk>, Peter Oruba
```

But why were only Cores 1, 2 and 3 updated in the period between 0.252234 and 0.278696 seconds and then all eight cores updated in the period between 1.888471 and 1.888597 seconds? Something looks wrong. Or were the messages for Cores 0 and 4 to 7 in that early period just lost because the kernel ring buffer could not update fast enough? Are the messages between 1.888491 and 1.888597 seconds just the kernel early microcode update driver confirming later on that the updates happened? Anyone have and ideas what could be happening? It seems the early microcode update driver is still buggy*, so I wonder if that is what I'm seeing?

* See https://lkml.org/lkml/2014/9/8/513 https://lkml.org/lkml/2014/9/8/517 https://lkml.org/lkml/2014/10/31/533 and a bunch of other very recent posts in the kernel mailing list regarding the early microcode update driver.

EDIT: The precise steps I used are documented in my blog post Updating Intel CPU microcode from Gentoo Linux.

----------

## N8Fear

My guess would be that core 0 got updated but this misses from this log and half of the cores are likely logical cores (due to hyperthreading) and share the microcode with the other logical cores (2 logical cores are one physical).

But as stated above this is just a guess.

----------

## Fitzcarraldo

I suppose the kernel ring buffer size might not be large enough and the early message for Core 0 was overwritten. I'll increase the size of the ring buffer in the kernel config and see.

Yes, it's a Core i7 quad core CPU, so there are 8 logical cores, but I don't understand why there are two groups of messages in the kernel ring buffer: one group between 0.252234 and 0.278696 seconds, and the other group between 1.888471 and 1.888597 seconds. But it seems that two sets of messages is the normal way, as I found the following dmesg output  (unfortunately without times) posted by a CrunchBang Linux user on another forum:

```
$ dmesg | grep microcode

CPU0 microcode updated early to revision 0x19, date = 2013-06-13

CPU1 microcode updated early to revision 0x19, date = 2013-06-13

CPU2 microcode updated early to revision 0x19, date = 2013-06-13

CPU3 microcode updated early to revision 0x19, date = 2013-06-13

microcode: CPU0 sig=0x306a9, pf=0x10, revision=0x19

microcode: CPU1 sig=0x306a9, pf=0x10, revision=0x19

microcode: CPU2 sig=0x306a9, pf=0x10, revision=0x19

microcode: CPU3 sig=0x306a9, pf=0x10, revision=0x19

microcode: CPU4 sig=0x306a9, pf=0x10, revision=0x19

microcode: CPU5 sig=0x306a9, pf=0x10, revision=0x19

microcode: CPU6 sig=0x306a9, pf=0x10, revision=0x19

microcode: CPU7 sig=0x306a9, pf=0x10, revision=0x19

microcode: Microcode Update Driver: v2.00 <tigran@aivazian.fsnet.co.uk>, Peter Oruba 
```

----------

