Date: Thu, 12 Jul 2018 14:31:16 -0400 From: Mark Johnston <markj@freebsd.org> To: freebsd-arch@freebsd.org Subject: early x86 microcode loading Message-ID: <20180712183116.GB15892@raichu>
next in thread | raw e-mail | index | archive | help
I've been working on support for early loading of microcode updates and wanted to solicit feedback on the approach before starting to get any code changes reviewed. Currently we support microcode updates via cpuctl(4), where cpucontrol(8) passes microcode blobs to the kernel via an ioctl interface. Updates are distributed by the sysutils/devcpu-data port. The scheme has a few shortcomings: - Microcode updates may introduce new CPU features, but since we load microcode from userland, updates are performed well after the kernel has done CPU feature detection. - Updates need to be reapplied after an ACPI suspend/resume, and there's currently no mechanism to automatically reapply the update after a resume. - Updates aren't applied until userspace starts running, so there exists a window in which the kernel is running without vulnerability mitigations provided by microcode updates. The aim of this work is to instead use the boot loader to load microcode updates into kernel memory, and modify the kernel to apply the updates as the first step in BSP and AP initialization, as well as after an ACPI resume. To configure an update, one would then just need to add the following lines to loader.conf: cpu_ucode_load="YES" cpu_ucode_name="/boot/firmware/microcode.bin" cpu_ucode_type="cpu_ucode" The kernel would then automatically load the update during processor initialization in the subsequent boot-up. A given Intel microcode update applies only to CPUs of a specific <family, model, stepping> tuple, while AMD releases a single update per processor family. My plan is to extend cpucontrol(8) to determine the correct microcode update for the running system, and have the devcpu-data port install the corresponding file to /boot/firmware. The port could then add the following to loader.conf.local: devcpu_data_load="YES" devcpu_data_name="/boot/firmware/<update file>" devcpu_data_type="cpu_ucode" Currently, the port doesn't automatically enable microcode updates; one needs to enable the microcode_update rc script after installing the port. I'm not yet sure how this should be integrated with early loading. For example, if "service microcode_update onestart" enables early loading, how should early loading be disabled? Would it be reasonable for the port to automatically enable updates when it is installed? For at least Intel, my intention is to support loading of multiple update files concatenated together, and have the kernel determine the correct update to apply. This is to make it easier to support a cluster of mixed systems which boot from some shared environment; rather than needing to select and configure the correct update for each machine, one can supply all updates as a single file and have each machine select the right one automatically. This would come at the expense of some wasted memory: the combined set of Intel microcode files is currently about 1.8MB in size. A small patch to the loader is needed to guarantee the 16 byte-alignment of the loaded microcode update required by Intel. This will require a bootcode update on GPT-based systems in order for early loading to work reliably. I'm interested in any feedback on the above, and especially any suggestions on how this feature should be integrated with the devcpu-data port. Thanks in advance.
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20180712183116.GB15892>