Skip to content

Failure with zero call-used registers #192

@bwendling

Description

@bwendling

During the Clang implementation of -fzero-call-used-regs, @nathanchance came across an issue where a Clang-built kernel failed to boot. It was seen as a issue, but is probably more pernicious than we first thought.

Related to #84.

Steps to replicate (by @nathanchance).

We uses Fedora for ease of installation via the serial console. @nathanchance wrote a Python script to drive QEMU specifically for testing. The latest version can be found here:

https://github.com/nathanchance/env/raw/235104e8740fcc8833caa284ebc549416dd6eb7b/python/cbl_vmm.py

With that, the setup command can be run to initially configure the machine.

cbl_vmm.py setup -i "https://download.fedoraproject.org/pub/fedora/linux/releases/36/Server/x86_64/iso/Fedora-Server-netinst-x86_64-36-1.5.iso" -n fedora

This downloads the .iso file in to a vm folder in the same folder as cbl_vmm.py. Once it's finished downloading, QEMU should fire up, printing the full command it uses.

Next, you should see grub. Hit 'e' to add console=ttyS0 to the linuxefi line after quiet then hit Ctrl-X to boot.

After a bunch of text flies across the screen, you should be prompted to either use VNC or text mode for configuration. I usually use text mode because it is a little simpler. The console might look a bit garbled, hitting r then Enter a few times should clear things up enough to see. In text mode, I customized the time zone and user creation sections but leave the installation source, software selection, and network configuration. Don't touch the root account. Instead create a user account that's the same as yours on the host and give it a password of some sort (i.e. don't just leave it blank).

The installation destination has to be run through but leave everything on the default. After the installation process finishes, the machine should reboot.

The script adds a forwarding rule for the virtual machine's SSH port (22) to the host (8022) so you should be able to log into the machine like:

ssh -p 8022 localhost

Once you are in, you'll need to do three things to make booting self compiled kernels through QEMU possible (as opposed to generating a kernel package and installing it within the machine).

  1. Copy the contents of /proc/cmdline somewhere you can use later, aside from the BOOT_IMAGE variable.

  2. Generate an initramfs and copy it out of the machine.

    Within the VM:

    sudo bash -c "rm -f /tmp/initramfs.img && dracut --no-kernel /tmp/initramfs.img && chown $USER:$USER /tmp/initramfs.img"

    Outside of the VM:

    scp -P 8022 localhost:/tmp/initramfs.img /tmp
    
  3. Get a list of the currently running kernel modules (it is easier to generate outside of the VM):

ssh -p 8022 localhost lsmod >/tmp/lsmod.txt

Once those are done, exit QEMU and go into your kernel source.

First, we'll use Fedora's kernel configuration as a base:

curl -LSso .config https://src.fedoraproject.org/rpms/kernel/raw/rawhide/f/kernel-x86_64-fedora.config

Next, we're going to build all the modules that we need to boot the VM into the kernel image with the 'localyesconfig' target (I have not found a clean way to generate a Fedora initramfs with modules) then run 'menuconfig' to turn on CONFIG_ZERO_CALL_USED_REGS then finally build the bzImage. The 'localyesconfig' step might prompt you for some values, I usually just hit <Enter> to choose the defaults.

make -skj"$(nproc)" LLVM=1 LSMOD=/tmp/lsmod.txt olddefconfig localyesconfig menuconfig bzImage

Once the image is done, you should be able to fire up the VM with the pieces we generated earlier (I usually do this in a different terminal/tmux tab):

cbl_vmm.py run -C "<cmdline_string_from_earlier>" -i /tmp/initramfs.img -k <path_to_kernel_src> -n fedora

That hangs for me with CONFIG_ZERO_CALL_USED_REGS=y. If it is disabled, the machine fully boots.

The script supports -g, which will pass -s -S to QEMU for easier debugging with GDB, you'll just need to make sure to enable CONFIG_GDB_SCRIPTS during the menuconfig stage and add the scripts_gdb target to your make command (or just use all in lieu of bzImage).

Metadata

Metadata

Assignees

Labels

[Linux] v5.15Released in Linux kernel v5.15[PATCH] AcceptedA submitted patch has been accepted upstream[PATCH] ExistsA patch exists to address the issuebugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions