Dear Linux folks,
I am trying to decrease the boot time of the Linux kernel so the LUKS
passphrase dialog (in the initrd) is shown as quickly as possible. The
devices I test with is a Lenovo X60 and ASRock E350M1 both running with
coreboot and the GRUB payload. The goal is to do this without having to
rebuild a Linux kernel, but only by run-time
I am currently at 1.2 seconds.
```
[ 0.610437] calling ata_init+0x0/0x2be [libata] @ 88
[ 0.610548] libata version 3.00 loaded.
[ 0.610570] initcall ata_init+0x0/0x2be [libata] returned 0 after 107
usecs
[ 0.612100] calling serio_raw_drv_init+0x0/0x1000 [serio_raw] @ 89
[ 0.612132] initcall serio_raw_drv_init+0x0/0x1000 [serio_raw]
returned 0 after 25 usecs
[ 0.612659] calling ahci_pci_driver_init+0x0/0x1000 [ahci] @ 88
[ 0.612715] ahci 0000:00:1f.2: version 3.0
[ 0.613050] ahci 0000:00:1f.2: SSS flag set, parallel bus scan disabled
[ 0.613153] ahci 0000:00:1f.2: AHCI 0001.0100 32 slots 4 ports 1.5
Gbps 0x1 impl SATA mode
[ 0.613239] ahci 0000:00:1f.2: flags: 64bit ncq ilck stag pm led clo
pmp pio slum part
[ 0.613915] calling evdev_init+0x0/0x1000 [evdev] @ 85
[ 0.614178] initcall evdev_init+0x0/0x1000 [evdev] returned 0 after
250 usecs
[ 0.624366] scsi host0: ahci
[ 0.630638] scsi host1: ahci
[ 0.640413] scsi host2: ahci
[ 0.646559] scsi host3: ahci
[ 0.646752] ata1: SATA max UDMA/133 abar m1024@0xe4445000 port
0xe4445100 irq 28
[ 0.646836] ata2: DUMMY
[ 0.646902] ata3: DUMMY
[ 0.646964] ata4: DUMMY
[ 0.647098] initcall ahci_pci_driver_init+0x0/0x1000 [ahci] returned
0 after 33619 usecs
[ 1.124129] ata1: SATA link up 1.5 Gbps (SStatus 113 SControl 300)
[ 1.124605] ata1.00: ATA-9: M4-CT256M4SSD2, 070H, max UDMA/100
[ 1.124674] ata1.00: 500118192 sectors, multi 16: LBA48 NCQ (depth
31/32), AA
[ 1.125179] ata1.00: configured for UDMA/100
[ 1.125522] scsi 0:0:0:0: Direct-Access ATA M4-CT256M4SSD2
070H PQ: 0 ANSI: 5
[ 1.129127] calling init_sd+0x0/0x1000 [sd_mod] @ 84
[ 1.129268] initcall init_sd+0x0/0x1000 [sd_mod] returned 0 after 129
usecs
[ 1.129444] sd 0:0:0:0: [sda] 500118192 512-byte logical blocks: (256
GB/238 GiB)
[ 1.129550] sd 0:0:0:0: [sda] Write Protect is off
[ 1.129619] sd 0:0:0:0: [sda] Mode Sense: 00 3a 00 00
[ 1.129647] sd 0:0:0:0: [sda] Write cache: enabled, read cache:
enabled, doesn't support DPO or FUA
[ 1.130384] sda: sda1 sda2
[ 1.131009] sd 0:0:0:0: [sda] Attached SCSI disk
[ 1.213492] calling dm_init+0x0/0x31 [dm_mod] @ 110
[ 1.213535] device-mapper: uevent: version 1.0.3
[ 1.213727] device-mapper: ioctl: 4.37.0-ioctl (2017-09-20)
initialised: [email protected]
[ 1.213829] initcall dm_init+0x0/0x31 [dm_mod] returned 0 after 312 usecs
[ 1.214434] calling dm_crypt_init+0x0/0x1000 [dm_crypt] @ 110
[ 1.214442] initcall dm_crypt_init+0x0/0x1000 [dm_crypt] returned 0
after 2 usecs
```
So, according to `initcall_debug` the method `ahci_pci_driver_init`
takes 33 ms to execute, which is longer then a few milliseconds.
But more importantly, it takes roughly half a second to set up the
device. I understand, that the probing is part of AHCI(?), and in this
case the Crucial m4 SSD drive/firmware is especially slow. So, I assume
it will be hard to improve anything in the code to decrease the time.
That said, in my case the assumption is, that the device configuration
will not change. That means, the drive will be the same and will be
connected to the same port all the time.
Additionally, GRUB already probed the device to read the Linux kernel
image and initrd image.
So, is there a way to avoid doing the probing twice or at all? That
means, either cache the settings, and load them during boot by reading
it from the firmware flash ROM chip, possible when using coreboot, and
passing it to the Linux kernel for example by GRUB. That would also help
with LinuxBoot [1], where the Linux kernel is used as the payload (boot
kernel), already setting up the drive and kexec’s another Linux kernel,
read from the drive.
Or, GRUB passes the settings it detected to the Linux kernel.
Kind regards,
Paul
[1] https://www.linuxboot.org/
[Attach full output of `dmesg`.]
On 04/04/18 11:53, Paul Menzel wrote:
> Dear Linux folks,
>
>
> I am trying to decrease the boot time of the Linux kernel so the LUKS
> passphrase dialog (in the initrd) is shown as quickly as possible. The
> devices I test with is a Lenovo X60 and ASRock E350M1 both running with
> coreboot and the GRUB payload. The goal is to do this without having to
> rebuild a Linux kernel, but only by run-time
>
> I am currently at 1.2 seconds.
>
> ```
> [ 0.610437] calling ata_init+0x0/0x2be [libata] @ 88
> [ 0.610548] libata version 3.00 loaded.
> [ 0.610570] initcall ata_init+0x0/0x2be [libata] returned 0 after 107
> usecs
> [ 0.612100] calling serio_raw_drv_init+0x0/0x1000 [serio_raw] @ 89
> [ 0.612132] initcall serio_raw_drv_init+0x0/0x1000 [serio_raw]
> returned 0 after 25 usecs
> [ 0.612659] calling ahci_pci_driver_init+0x0/0x1000 [ahci] @ 88
> [ 0.612715] ahci 0000:00:1f.2: version 3.0
> [ 0.613050] ahci 0000:00:1f.2: SSS flag set, parallel bus scan disabled
> [ 0.613153] ahci 0000:00:1f.2: AHCI 0001.0100 32 slots 4 ports 1.5
> Gbps 0x1 impl SATA mode
> [ 0.613239] ahci 0000:00:1f.2: flags: 64bit ncq ilck stag pm led clo
> pmp pio slum part
> [ 0.613915] calling evdev_init+0x0/0x1000 [evdev] @ 85
> [ 0.614178] initcall evdev_init+0x0/0x1000 [evdev] returned 0 after
> 250 usecs
> [ 0.624366] scsi host0: ahci
> [ 0.630638] scsi host1: ahci
> [ 0.640413] scsi host2: ahci
> [ 0.646559] scsi host3: ahci
> [ 0.646752] ata1: SATA max UDMA/133 abar m1024@0xe4445000 port
> 0xe4445100 irq 28
> [ 0.646836] ata2: DUMMY
> [ 0.646902] ata3: DUMMY
> [ 0.646964] ata4: DUMMY
> [ 0.647098] initcall ahci_pci_driver_init+0x0/0x1000 [ahci] returned
> 0 after 33619 usecs
> [ 1.124129] ata1: SATA link up 1.5 Gbps (SStatus 113 SControl 300)
> [ 1.124605] ata1.00: ATA-9: M4-CT256M4SSD2, 070H, max UDMA/100
> [ 1.124674] ata1.00: 500118192 sectors, multi 16: LBA48 NCQ (depth
> 31/32), AA
> [ 1.125179] ata1.00: configured for UDMA/100
> [ 1.125522] scsi 0:0:0:0: Direct-Access ATA M4-CT256M4SSD2
> 070H PQ: 0 ANSI: 5
> [ 1.129127] calling init_sd+0x0/0x1000 [sd_mod] @ 84
> [ 1.129268] initcall init_sd+0x0/0x1000 [sd_mod] returned 0 after 129
> usecs
> [ 1.129444] sd 0:0:0:0: [sda] 500118192 512-byte logical blocks: (256
> GB/238 GiB)
> [ 1.129550] sd 0:0:0:0: [sda] Write Protect is off
> [ 1.129619] sd 0:0:0:0: [sda] Mode Sense: 00 3a 00 00
> [ 1.129647] sd 0:0:0:0: [sda] Write cache: enabled, read cache:
> enabled, doesn't support DPO or FUA
> [ 1.130384] sda: sda1 sda2
> [ 1.131009] sd 0:0:0:0: [sda] Attached SCSI disk
> [ 1.213492] calling dm_init+0x0/0x31 [dm_mod] @ 110
> [ 1.213535] device-mapper: uevent: version 1.0.3
> [ 1.213727] device-mapper: ioctl: 4.37.0-ioctl (2017-09-20)
> initialised: [email protected]
> [ 1.213829] initcall dm_init+0x0/0x31 [dm_mod] returned 0 after 312
> usecs
> [ 1.214434] calling dm_crypt_init+0x0/0x1000 [dm_crypt] @ 110
> [ 1.214442] initcall dm_crypt_init+0x0/0x1000 [dm_crypt] returned 0
> after 2 usecs
> ```
>
> So, according to `initcall_debug` the method `ahci_pci_driver_init`
> takes 33 ms to execute, which is longer then a few milliseconds.
>
> But more importantly, it takes roughly half a second to set up the
> device. I understand, that the probing is part of AHCI(?), and in this
> case the Crucial m4 SSD drive/firmware is especially slow. So, I assume
> it will be hard to improve anything in the code to decrease the time.
>
> That said, in my case the assumption is, that the device configuration
> will not change. That means, the drive will be the same and will be
> connected to the same port all the time.
>
> Additionally, GRUB already probed the device to read the Linux kernel
> image and initrd image.
>
> So, is there a way to avoid doing the probing twice or at all? That
> means, either cache the settings, and load them during boot by reading
> it from the firmware flash ROM chip, possible when using coreboot, and
> passing it to the Linux kernel for example by GRUB. That would also help
> with LinuxBoot [1], where the Linux kernel is used as the payload (boot
> kernel), already setting up the drive and kexec’s another Linux kernel,
> read from the drive.
>
> Or, GRUB passes the settings it detected to the Linux kernel.
>
>
> Kind regards,
>
> Paul
>
>
> [1] https://www.linuxboot.org/
> But more importantly, it takes roughly half a second to set up the
> device. I understand, that the probing is part of AHCI(?), and in this
> case the Crucial m4 SSD drive/firmware is especially slow. So, I assume
> it will be hard to improve anything in the code to decrease the time.
Probably. The OS basically waits for the device to flag read. It's not
that slow (spinning rust can take several seconds, and historically up to
30)
> So, is there a way to avoid doing the probing twice or at all? That
You have to do it once. It's not probing that is slow. Your SSD is
basically a single board computer pretending to be a disk. It's go to
boot and load in and work out what the hell it's doing, what happened
before it died and so on. Spinning rust is similar - in fact with a
modern ATA disk plugged into a really old machine it's not uncommon that
the disk has the most CPU power 8)
Once you have completed the boot for that channel (so for SATA pretty
much for that device) you could in theory pass the OS a flag saying 'is
initialized, is present' and you'd be able to avoid a repeat reset/probe
and just go on to re-issue identify and similar commands in order to
re-obtain the configuration data of the drive. Those commands are fast on
any hardware I've seen.
This is known to work for straigt ATA - it's sort of what we do in the
corner cases where we find an ATA class controller we don't support. AHCI
is a bit more complex but the theory should hold.
Alan