| .. SPDX-License-Identifier: (GPL-2.0+ OR CC-BY-4.0) |
| .. [see the bottom of this file for redistribution information] |
| |
| ========================================= |
| How to verify bugs and bisect regressions |
| ========================================= |
| |
| This document describes how to check if some Linux kernel problem occurs in code |
| currently supported by developers -- to then explain how to locate the change |
| causing the issue, if it is a regression (e.g. did not happen with earlier |
| versions). |
| |
| The text aims at people running kernels from mainstream Linux distributions on |
| commodity hardware who want to report a kernel bug to the upstream Linux |
| developers. Despite this intent, the instructions work just as well for users |
| who are already familiar with building their own kernels: they help avoid |
| mistakes occasionally made even by experienced developers. |
| |
| .. |
| Note: if you see this note, you are reading the text's source file. You |
| might want to switch to a rendered version: it makes it a lot easier to |
| read and navigate this document -- especially when you want to look something |
| up in the reference section, then jump back to where you left off. |
| .. |
| Find the latest rendered version of this text here: |
| https://docs.kernel.org/admin-guide/verify-bugs-and-bisect-regressions.html |
| |
| The essence of the process (aka 'TL;DR') |
| ======================================== |
| |
| *[If you are new to building or bisecting Linux, ignore this section and head |
| over to the* ':ref:`step-by-step guide <introguide_bissbs>`' *below. It utilizes |
| the same commands as this section while describing them in brief fashion. The |
| steps are nevertheless easy to follow and together with accompanying entries |
| in a reference section mention many alternatives, pitfalls, and additional |
| aspects, all of which might be essential in your present case.]* |
| |
| **In case you want to check if a bug is present in code currently supported by |
| developers**, execute just the *preparations* and *segment 1*; while doing so, |
| consider the newest Linux kernel you regularly use to be the 'working' kernel. |
| In the following example that's assumed to be 6.0, which is why its sources |
| will be used to prepare the .config file. |
| |
| **In case you face a regression**, follow the steps at least till the end of |
| *segment 2*. Then you can submit a preliminary report -- or continue with |
| *segment 3*, which describes how to perform a bisection needed for a |
| full-fledged regression report. In the following example 6.0.13 is assumed to be |
| the 'working' kernel and 6.1.5 to be the first 'broken', which is why 6.0 |
| will be considered the 'good' release and used to prepare the .config file. |
| |
| * **Preparations**: set up everything to build your own kernels:: |
| |
| # * Remove any software that depends on externally maintained kernel modules |
| # or builds any automatically during bootup. |
| # * Ensure Secure Boot permits booting self-compiled Linux kernels. |
| # * If you are not already running the 'working' kernel, reboot into it. |
| # * Install compilers and everything else needed for building Linux. |
| # * Ensure to have 15 Gigabyte free space in your home directory. |
| git clone -o mainline --no-checkout \ |
| https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git ~/linux/ |
| cd ~/linux/ |
| git remote add -t master stable \ |
| https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git |
| git switch --detach v6.0 |
| # * Hint: if you used an existing clone, ensure no stale .config is around. |
| make olddefconfig |
| # * Ensure the former command picked the .config of the 'working' kernel. |
| # * Connect external hardware (USB keys, tokens, ...), start a VM, bring up |
| # VPNs, mount network shares, and briefly try the feature that is broken. |
| yes '' | make localmodconfig |
| ./scripts/config --set-str CONFIG_LOCALVERSION '-local' |
| ./scripts/config -e CONFIG_LOCALVERSION_AUTO |
| # * Note, when short on storage space, check the guide for an alternative: |
| ./scripts/config -d DEBUG_INFO_NONE -e KALLSYMS_ALL -e DEBUG_KERNEL \ |
| -e DEBUG_INFO -e DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT -e KALLSYMS |
| # * Hint: at this point you might want to adjust the build configuration; |
| # you'll have to, if you are running Debian. |
| make olddefconfig |
| cp .config ~/kernel-config-working |
| |
| * **Segment 1**: build a kernel from the latest mainline codebase. |
| |
| This among others checks if the problem was fixed already and which developers |
| later need to be told about the problem; in case of a regression, this rules |
| out a .config change as root of the problem. |
| |
| a) Checking out latest mainline code:: |
| |
| cd ~/linux/ |
| git switch --discard-changes --detach mainline/master |
| |
| b) Build, install, and boot a kernel:: |
| |
| cp ~/kernel-config-working .config |
| make olddefconfig |
| make -j $(nproc --all) |
| # * Make sure there is enough disk space to hold another kernel: |
| df -h /boot/ /lib/modules/ |
| # * Note: on Arch Linux, its derivatives and a few other distributions |
| # the following commands will do nothing at all or only part of the |
| # job. See the step-by-step guide for further details. |
| sudo make modules_install |
| command -v installkernel && sudo make install |
| # * Check how much space your self-built kernel actually needs, which |
| # enables you to make better estimates later: |
| du -ch /boot/*$(make -s kernelrelease)* | tail -n 1 |
| du -sh /lib/modules/$(make -s kernelrelease)/ |
| # * Hint: the output of the following command will help you pick the |
| # right kernel from the boot menu: |
| make -s kernelrelease | tee -a ~/kernels-built |
| reboot |
| # * Once booted, ensure you are running the kernel you just built by |
| # checking if the output of the next two commands matches: |
| tail -n 1 ~/kernels-built |
| uname -r |
| cat /proc/sys/kernel/tainted |
| |
| c) Check if the problem occurs with this kernel as well. |
| |
| * **Segment 2**: ensure the 'good' kernel is also a 'working' kernel. |
| |
| This among others verifies the trimmed .config file actually works well, as |
| bisecting with it otherwise would be a waste of time: |
| |
| a) Start by checking out the sources of the 'good' version:: |
| |
| cd ~/linux/ |
| git switch --discard-changes --detach v6.0 |
| |
| b) Build, install, and boot a kernel as described earlier in *segment 1, |
| section b* -- just feel free to skip the 'du' commands, as you have a rough |
| estimate already. |
| |
| c) Ensure the feature that regressed with the 'broken' kernel actually works |
| with this one. |
| |
| * **Segment 3**: perform and validate the bisection. |
| |
| a) Retrieve the sources for your 'bad' version:: |
| |
| git remote set-branches --add stable linux-6.1.y |
| git fetch stable |
| |
| b) Initialize the bisection:: |
| |
| cd ~/linux/ |
| git bisect start |
| git bisect good v6.0 |
| git bisect bad v6.1.5 |
| |
| c) Build, install, and boot a kernel as described earlier in *segment 1, |
| section b*. |
| |
| In case building or booting the kernel fails for unrelated reasons, run |
| ``git bisect skip``. In all other outcomes, check if the regressed feature |
| works with the newly built kernel. If it does, tell Git by executing |
| ``git bisect good``; if it does not, run ``git bisect bad`` instead. |
| |
| All three commands will make Git check out another commit; then re-execute |
| this step (e.g. build, install, boot, and test a kernel to then tell Git |
| the outcome). Do so again and again until Git shows which commit broke |
| things. If you run short of disk space during this process, check the |
| section 'Complementary tasks: cleanup during and after the process' |
| below. |
| |
| d) Once your finished the bisection, put a few things away:: |
| |
| cd ~/linux/ |
| git bisect log > ~/bisect-log |
| cp .config ~/bisection-config-culprit |
| git bisect reset |
| |
| e) Try to verify the bisection result:: |
| |
| git switch --discard-changes --detach mainline/master |
| git revert --no-edit cafec0cacaca0 |
| cp ~/kernel-config-working .config |
| ./scripts/config --set-str CONFIG_LOCALVERSION '-local-cafec0cacaca0-reverted' |
| |
| This is optional, as some commits are impossible to revert. But if the |
| second command worked flawlessly, build, install, and boot one more kernel |
| kernel; just this time skip the first command copying the base .config file |
| over, as that already has been taken care off. |
| |
| * **Complementary tasks**: cleanup during and after the process. |
| |
| a) To avoid running out of disk space during a bisection, you might need to |
| remove some kernels you built earlier. You most likely want to keep those |
| you built during segment 1 and 2 around for a while, but you will most |
| likely no longer need kernels tested during the actual bisection |
| (Segment 3 c). You can list them in build order using:: |
| |
| ls -ltr /lib/modules/*-local* |
| |
| To then for example erase a kernel that identifies itself as |
| '6.0-rc1-local-gcafec0cacaca0', use this:: |
| |
| sudo rm -rf /lib/modules/6.0-rc1-local-gcafec0cacaca0 |
| sudo kernel-install -v remove 6.0-rc1-local-gcafec0cacaca0 |
| # * Note, on some distributions kernel-install is missing |
| # or does only part of the job. |
| |
| b) If you performed a bisection and successfully validated the result, feel |
| free to remove all kernels built during the actual bisection (Segment 3 c); |
| the kernels you built earlier and later you might want to keep around for |
| a week or two. |
| |
| * **Optional task**: test a debug patch or a proposed fix later:: |
| |
| git fetch mainline |
| git switch --discard-changes --detach mainline/master |
| git apply /tmp/foobars-proposed-fix-v1.patch |
| cp ~/kernel-config-working .config |
| ./scripts/config --set-str CONFIG_LOCALVERSION '-local-foobars-fix-v1' |
| |
| Build, install, and boot a kernel as described in *segment 1, section b* -- |
| but this time omit the first command copying the build configuration over, |
| as that has been taken care of already. |
| |
| .. _introguide_bissbs: |
| |
| Step-by-step guide on how to verify bugs and bisect regressions |
| =============================================================== |
| |
| This guide describes how to set up your own Linux kernels for investigating bugs |
| or regressions you intend to report. How far you want to follow the instructions |
| depends on your issue: |
| |
| Execute all steps till the end of *segment 1* to **verify if your kernel problem |
| is present in code supported by Linux kernel developers**. If it is, you are all |
| set to report the bug -- unless it did not happen with earlier kernel versions, |
| as then your want to at least continue with *segment 2* to **check if the issue |
| qualifies as regression** which receive priority treatment. Depending on the |
| outcome you then are ready to report a bug or submit a preliminary regression |
| report; instead of the latter your could also head straight on and follow |
| *segment 3* to **perform a bisection** for a full-fledged regression report |
| developers are obliged to act upon. |
| |
| :ref:`Preparations: set up everything to build your own kernels <introprep_bissbs>`. |
| |
| :ref:`Segment 1: try to reproduce the problem with the latest codebase <introlatestcheck_bissbs>`. |
| |
| :ref:`Segment 2: check if the kernels you build work fine <introworkingcheck_bissbs>`. |
| |
| :ref:`Segment 3: perform a bisection and validate the result <introbisect_bissbs>`. |
| |
| :ref:`Complementary tasks: cleanup during and after following this guide <introclosure_bissbs>`. |
| |
| :ref:`Optional tasks: test reverts, patches, or later versions <introoptional_bissbs>`. |
| |
| The steps in each segment illustrate the important aspects of the process, while |
| a comprehensive reference section holds additional details for almost all of the |
| steps. The reference section sometimes also outlines alternative approaches, |
| pitfalls, as well as problems that might occur at the particular step -- and how |
| to get things rolling again. |
| |
| For further details on how to report Linux kernel issues or regressions check |
| out Documentation/admin-guide/reporting-issues.rst, which works in conjunction |
| with this document. It among others explains why you need to verify bugs with |
| the latest 'mainline' kernel (e.g. versions like 6.0, 6.1-rc1, or 6.1-rc6), |
| even if you face a problem with a kernel from a 'stable/longterm' series |
| (say 6.0.13). |
| |
| For users facing a regression that document also explains why sending a |
| preliminary report after segment 2 might be wise, as the regression and its |
| culprit might be known already. For further details on what actually qualifies |
| as a regression check out Documentation/admin-guide/reporting-regressions.rst. |
| |
| If you run into any problems while following this guide or have ideas how to |
| improve it, :ref:`please let the kernel developers know <submit_improvements>`. |
| |
| .. _introprep_bissbs: |
| |
| Preparations: set up everything to build your own kernels |
| --------------------------------------------------------- |
| |
| The following steps lay the groundwork for all further tasks. |
| |
| Note: the instructions assume you are building and testing on the same |
| machine; if you want to compile the kernel on another system, check |
| :ref:`Build kernels on a different machine <buildhost_bis>` below. |
| |
| .. _backup_bissbs: |
| |
| * Create a fresh backup and put system repair and restore tools at hand, just |
| to be prepared for the unlikely case of something going sideways. |
| |
| [:ref:`details <backup_bisref>`] |
| |
| .. _vanilla_bissbs: |
| |
| * Remove all software that depends on externally developed kernel drivers or |
| builds them automatically. That includes but is not limited to DKMS, openZFS, |
| VirtualBox, and Nvidia's graphics drivers (including the GPLed kernel module). |
| |
| [:ref:`details <vanilla_bisref>`] |
| |
| .. _secureboot_bissbs: |
| |
| * On platforms with 'Secure Boot' or similar solutions, prepare everything to |
| ensure the system will permit your self-compiled kernel to boot. The |
| quickest and easiest way to achieve this on commodity x86 systems is to |
| disable such techniques in the BIOS setup utility; alternatively, remove |
| their restrictions through a process initiated by |
| ``mokutil --disable-validation``. |
| |
| [:ref:`details <secureboot_bisref>`] |
| |
| .. _rangecheck_bissbs: |
| |
| * Determine the kernel versions considered 'good' and 'bad' throughout this |
| guide: |
| |
| * Do you follow this guide to verify if a bug is present in the code the |
| primary developers care for? Then consider the version of the newest kernel |
| you regularly use currently as 'good' (e.g. 6.0, 6.0.13, or 6.1-rc2). |
| |
| * Do you face a regression, e.g. something broke or works worse after |
| switching to a newer kernel version? In that case it depends on the version |
| range during which the problem appeared: |
| |
| * Something regressed when updating from a stable/longterm release |
| (say 6.0.13) to a newer mainline series (like 6.1-rc7 or 6.1) or a |
| stable/longterm version based on one (say 6.1.5)? Then consider the |
| mainline release your working kernel is based on to be the 'good' |
| version (e.g. 6.0) and the first version to be broken as the 'bad' one |
| (e.g. 6.1-rc7, 6.1, or 6.1.5). Note, at this point it is merely assumed |
| that 6.0 is fine; this hypothesis will be checked in segment 2. |
| |
| * Something regressed when switching from one mainline version (say 6.0) to |
| a later one (like 6.1-rc1) or a stable/longterm release based on it |
| (say 6.1.5)? Then regard the last working version (e.g. 6.0) as 'good' and |
| the first broken (e.g. 6.1-rc1 or 6.1.5) as 'bad'. |
| |
| * Something regressed when updating within a stable/longterm series (say |
| from 6.0.13 to 6.0.15)? Then consider those versions as 'good' and 'bad' |
| (e.g. 6.0.13 and 6.0.15), as you need to bisect within that series. |
| |
| *Note, do not confuse 'good' version with 'working' kernel; the latter term |
| throughout this guide will refer to the last kernel that has been working |
| fine.* |
| |
| [:ref:`details <rangecheck_bisref>`] |
| |
| .. _bootworking_bissbs: |
| |
| * Boot into the 'working' kernel and briefly use the apparently broken feature. |
| |
| [:ref:`details <bootworking_bisref>`] |
| |
| .. _diskspace_bissbs: |
| |
| * Ensure to have enough free space for building Linux. 15 Gigabyte in your home |
| directory should typically suffice. If you have less available, be sure to pay |
| attention to later steps about retrieving the Linux sources and handling of |
| debug symbols: both explain approaches reducing the amount of space, which |
| should allow you to master these tasks with about 4 Gigabytes free space. |
| |
| [:ref:`details <diskspace_bisref>`] |
| |
| .. _buildrequires_bissbs: |
| |
| * Install all software required to build a Linux kernel. Often you will need: |
| 'bc', 'binutils' ('ld' et al.), 'bison', 'flex', 'gcc', 'git', 'openssl', |
| 'pahole', 'perl', and the development headers for 'libelf' and 'openssl'. The |
| reference section shows how to quickly install those on various popular Linux |
| distributions. |
| |
| [:ref:`details <buildrequires_bisref>`] |
| |
| .. _sources_bissbs: |
| |
| * Retrieve the mainline Linux sources; then change into the directory holding |
| them, as all further commands in this guide are meant to be executed from |
| there. |
| |
| *Note, the following describe how to retrieve the sources using a full |
| mainline clone, which downloads about 2,75 GByte as of early 2024. The* |
| :ref:`reference section describes two alternatives <sources_bisref>` *: |
| one downloads less than 500 MByte, the other works better with unreliable |
| internet connections.* |
| |
| Execute the following command to retrieve a fresh mainline codebase while |
| preparing things to add branches for stable/longterm series later:: |
| |
| git clone -o mainline --no-checkout \ |
| https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git ~/linux/ |
| cd ~/linux/ |
| git remote add -t master stable \ |
| https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git |
| |
| [:ref:`details <sources_bisref>`] |
| |
| .. _stablesources_bissbs: |
| |
| * Is one of the versions you earlier established as 'good' or 'bad' a stable or |
| longterm release (say 6.1.5)? Then download the code for the series it belongs |
| to ('linux-6.1.y' in this example):: |
| |
| git remote set-branches --add stable linux-6.1.y |
| git fetch stable |
| |
| .. _oldconfig_bissbs: |
| |
| * Start preparing a kernel build configuration (the '.config' file). |
| |
| Before doing so, ensure you are still running the 'working' kernel an earlier |
| step told you to boot; if you are unsure, check the current kernelrelease |
| identifier using ``uname -r``. |
| |
| Afterwards check out the source code for the version earlier established as |
| 'good'. In the following example command this is assumed to be 6.0; note that |
| the version number in this and all later Git commands needs to be prefixed |
| with a 'v':: |
| |
| git switch --discard-changes --detach v6.0 |
| |
| Now create a build configuration file:: |
| |
| make olddefconfig |
| |
| The kernel build scripts then will try to locate the build configuration file |
| for the running kernel and then adjust it for the needs of the kernel sources |
| you checked out. While doing so, it will print a few lines you need to check. |
| |
| Look out for a line starting with '# using defaults found in'. It should be |
| followed by a path to a file in '/boot/' that contains the release identifier |
| of your currently working kernel. If the line instead continues with something |
| like 'arch/x86/configs/x86_64_defconfig', then the build infra failed to find |
| the .config file for your running kernel -- in which case you have to put one |
| there manually, as explained in the reference section. |
| |
| In case you can not find such a line, look for one containing '# configuration |
| written to .config'. If that's the case you have a stale build configuration |
| lying around. Unless you intend to use it, delete it; afterwards run |
| 'make olddefconfig' again and check if it now picked up the right config file |
| as base. |
| |
| [:ref:`details <oldconfig_bisref>`] |
| |
| .. _localmodconfig_bissbs: |
| |
| * Disable any kernel modules apparently superfluous for your setup. This is |
| optional, but especially wise for bisections, as it speeds up the build |
| process enormously -- at least unless the .config file picked up in the |
| previous step was already tailored to your and your hardware needs, in which |
| case you should skip this step. |
| |
| To prepare the trimming, connect external hardware you occasionally use (USB |
| keys, tokens, ...), quickly start a VM, and bring up VPNs. And if you rebooted |
| since you started that guide, ensure that you tried using the feature causing |
| trouble since you started the system. Only then trim your .config:: |
| |
| yes '' | make localmodconfig |
| |
| There is a catch to this, as the 'apparently' in initial sentence of this step |
| and the preparation instructions already hinted at: |
| |
| The 'localmodconfig' target easily disables kernel modules for features only |
| used occasionally -- like modules for external peripherals not yet connected |
| since booting, virtualization software not yet utilized, VPN tunnels, and a |
| few other things. That's because some tasks rely on kernel modules Linux only |
| loads when you execute tasks like the aforementioned ones for the first time. |
| |
| This drawback of localmodconfig is nothing you should lose sleep over, but |
| something to keep in mind: if something is misbehaving with the kernels built |
| during this guide, this is most likely the reason. You can reduce or nearly |
| eliminate the risk with tricks outlined in the reference section; but when |
| building a kernel just for quick testing purposes this is usually not worth |
| spending much effort on, as long as it boots and allows to properly test the |
| feature that causes trouble. |
| |
| [:ref:`details <localmodconfig_bisref>`] |
| |
| .. _tagging_bissbs: |
| |
| * Ensure all the kernels you will build are clearly identifiable using a special |
| tag and a unique version number:: |
| |
| ./scripts/config --set-str CONFIG_LOCALVERSION '-local' |
| ./scripts/config -e CONFIG_LOCALVERSION_AUTO |
| |
| [:ref:`details <tagging_bisref>`] |
| |
| .. _debugsymbols_bissbs: |
| |
| * Decide how to handle debug symbols. |
| |
| In the context of this document it is often wise to enable them, as there is a |
| decent chance you will need to decode a stack trace from a 'panic', 'Oops', |
| 'warning', or 'BUG':: |
| |
| ./scripts/config -d DEBUG_INFO_NONE -e KALLSYMS_ALL -e DEBUG_KERNEL \ |
| -e DEBUG_INFO -e DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT -e KALLSYMS |
| |
| But if you are extremely short on storage space, you might want to disable |
| debug symbols instead:: |
| |
| ./scripts/config -d DEBUG_INFO -d DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT \ |
| -d DEBUG_INFO_DWARF4 -d DEBUG_INFO_DWARF5 -e CONFIG_DEBUG_INFO_NONE |
| |
| [:ref:`details <debugsymbols_bisref>`] |
| |
| .. _configmods_bissbs: |
| |
| * Check if you may want or need to adjust some other kernel configuration |
| options: |
| |
| * Are you running Debian? Then you want to avoid known problems by performing |
| additional adjustments explained in the reference section. |
| |
| [:ref:`details <configmods_distros_bisref>`]. |
| |
| * If you want to influence other aspects of the configuration, do so now using |
| your preferred tool. Note, to use make targets like 'menuconfig' or |
| 'nconfig', you will need to install the development files of ncurses; for |
| 'xconfig' you likewise need the Qt5 or Qt6 headers. |
| |
| [:ref:`details <configmods_individual_bisref>`]. |
| |
| .. _saveconfig_bissbs: |
| |
| * Reprocess the .config after the latest adjustments and store it in a safe |
| place:: |
| |
| make olddefconfig |
| cp .config ~/kernel-config-working |
| |
| [:ref:`details <saveconfig_bisref>`] |
| |
| .. _introlatestcheck_bissbs: |
| |
| Segment 1: try to reproduce the problem with the latest codebase |
| ---------------------------------------------------------------- |
| |
| The following steps verify if the problem occurs with the code currently |
| supported by developers. In case you face a regression, it also checks that the |
| problem is not caused by some .config change, as reporting the issue then would |
| be a waste of time. [:ref:`details <introlatestcheck_bisref>`] |
| |
| .. _checkoutmaster_bissbs: |
| |
| * Check out the latest Linux codebase. |
| |
| * Are your 'good' and 'bad' versions from the same stable or longterm series? |
| Then check the `front page of kernel.org <https://kernel.org/>`_: if it |
| lists a release from that series without an '[EOL]' tag, checkout the series |
| latest version ('linux-6.1.y' in the following example):: |
| |
| cd ~/linux/ |
| git switch --discard-changes --detach stable/linux-6.1.y |
| |
| Your series is unsupported, if is not listed or carrying a 'end of life' |
| tag. In that case you might want to check if a successor series (say |
| linux-6.2.y) or mainline (see next point) fix the bug. |
| |
| * In all other cases, run:: |
| |
| cd ~/linux/ |
| git switch --discard-changes --detach mainline/master |
| |
| [:ref:`details <checkoutmaster_bisref>`] |
| |
| .. _build_bissbs: |
| |
| * Build the image and the modules of your first kernel using the config file you |
| prepared:: |
| |
| cp ~/kernel-config-working .config |
| make olddefconfig |
| make -j $(nproc --all) |
| |
| If you want your kernel packaged up as deb, rpm, or tar file, see the |
| reference section for alternatives, which obviously will require other |
| steps to install as well. |
| |
| [:ref:`details <build_bisref>`] |
| |
| .. _install_bissbs: |
| |
| * Install your newly built kernel. |
| |
| Before doing so, consider checking if there is still enough space for it:: |
| |
| df -h /boot/ /lib/modules/ |
| |
| For now assume 150 MByte in /boot/ and 200 in /lib/modules/ will suffice; how |
| much your kernels actually require will be determined later during this guide. |
| |
| Now install the kernel's modules and its image, which will be stored in |
| parallel to the your Linux distribution's kernels:: |
| |
| sudo make modules_install |
| command -v installkernel && sudo make install |
| |
| The second command ideally will take care of three steps required at this |
| point: copying the kernel's image to /boot/, generating an initramfs, and |
| adding an entry for both to the boot loader's configuration. |
| |
| Sadly some distributions (among them Arch Linux, its derivatives, and many |
| immutable Linux distributions) will perform none or only some of those tasks. |
| You therefore want to check if all of them were taken care of and manually |
| perform those that were not. The reference section provides further details on |
| that; your distribution's documentation might help, too. |
| |
| Once you figured out the steps needed at this point, consider writing them |
| down: if you will build more kernels as described in segment 2 and 3, you will |
| have to perform those again after executing ``command -v installkernel [...]``. |
| |
| [:ref:`details <install_bisref>`] |
| |
| .. _storagespace_bissbs: |
| |
| * In case you plan to follow this guide further, check how much storage space |
| the kernel, its modules, and other related files like the initramfs consume:: |
| |
| du -ch /boot/*$(make -s kernelrelease)* | tail -n 1 |
| du -sh /lib/modules/$(make -s kernelrelease)/ |
| |
| Write down or remember those two values for later: they enable you to prevent |
| running out of disk space accidentally during a bisection. |
| |
| [:ref:`details <storagespace_bisref>`] |
| |
| .. _kernelrelease_bissbs: |
| |
| * Show and store the kernelrelease identifier of the kernel you just built:: |
| |
| make -s kernelrelease | tee -a ~/kernels-built |
| |
| Remember the identifier momentarily, as it will help you pick the right kernel |
| from the boot menu upon restarting. |
| |
| * Reboot into your newly built kernel. To ensure your actually started the one |
| you just built, you might want to verify if the output of these commands |
| matches:: |
| |
| tail -n 1 ~/kernels-built |
| uname -r |
| |
| .. _tainted_bissbs: |
| |
| * Check if the kernel marked itself as 'tainted':: |
| |
| cat /proc/sys/kernel/tainted |
| |
| If that command does not return '0', check the reference section, as the cause |
| for this might interfere with your testing. |
| |
| [:ref:`details <tainted_bisref>`] |
| |
| .. _recheckbroken_bissbs: |
| |
| * Verify if your bug occurs with the newly built kernel. If it does not, check |
| out the instructions in the reference section to ensure nothing went sideways |
| during your tests. |
| |
| [:ref:`details <recheckbroken_bisref>`] |
| |
| .. _recheckstablebroken_bissbs: |
| |
| * Did you just built a stable or longterm kernel? And were you able to reproduce |
| the regression with it? Then you should test the latest mainline codebase as |
| well, because the result determines which developers the bug must be submitted |
| to. |
| |
| To prepare that test, check out current mainline:: |
| |
| cd ~/linux/ |
| git switch --discard-changes --detach mainline/master |
| |
| Now use the checked out code to build and install another kernel using the |
| commands the earlier steps already described in more detail:: |
| |
| cp ~/kernel-config-working .config |
| make olddefconfig |
| make -j $(nproc --all) |
| # * Check if the free space suffices holding another kernel: |
| df -h /boot/ /lib/modules/ |
| sudo make modules_install |
| command -v installkernel && sudo make install |
| make -s kernelrelease | tee -a ~/kernels-built |
| reboot |
| |
| Confirm you booted the kernel you intended to start and check its tainted |
| status:: |
| |
| tail -n 1 ~/kernels-built |
| uname -r |
| cat /proc/sys/kernel/tainted |
| |
| Now verify if this kernel is showing the problem. If it does, then you need |
| to report the bug to the primary developers; if it does not, report it to the |
| stable team. See Documentation/admin-guide/reporting-issues.rst for details. |
| |
| [:ref:`details <recheckstablebroken_bisref>`] |
| |
| Do you follow this guide to verify if a problem is present in the code |
| currently supported by Linux kernel developers? Then you are done at this |
| point. If you later want to remove the kernel you just built, check out |
| :ref:`Complementary tasks: cleanup during and after following this guide <introclosure_bissbs>`. |
| |
| In case you face a regression, move on and execute at least the next segment |
| as well. |
| |
| .. _introworkingcheck_bissbs: |
| |
| Segment 2: check if the kernels you build work fine |
| --------------------------------------------------- |
| |
| In case of a regression, you now want to ensure the trimmed configuration file |
| you created earlier works as expected; a bisection with the .config file |
| otherwise would be a waste of time. [:ref:`details <introworkingcheck_bisref>`] |
| |
| .. _recheckworking_bissbs: |
| |
| * Build your own variant of the 'working' kernel and check if the feature that |
| regressed works as expected with it. |
| |
| Start by checking out the sources for the version earlier established as |
| 'good' (once again assumed to be 6.0 here):: |
| |
| cd ~/linux/ |
| git switch --discard-changes --detach v6.0 |
| |
| Now use the checked out code to configure, build, and install another kernel |
| using the commands the previous subsection explained in more detail:: |
| |
| cp ~/kernel-config-working .config |
| make olddefconfig |
| make -j $(nproc --all) |
| # * Check if the free space suffices holding another kernel: |
| df -h /boot/ /lib/modules/ |
| sudo make modules_install |
| command -v installkernel && sudo make install |
| make -s kernelrelease | tee -a ~/kernels-built |
| reboot |
| |
| When the system booted, you may want to verify once again that the |
| kernel you started is the one you just built:: |
| |
| tail -n 1 ~/kernels-built |
| uname -r |
| |
| Now check if this kernel works as expected; if not, consult the reference |
| section for further instructions. |
| |
| [:ref:`details <recheckworking_bisref>`] |
| |
| .. _introbisect_bissbs: |
| |
| Segment 3: perform the bisection and validate the result |
| -------------------------------------------------------- |
| |
| With all the preparations and precaution builds taken care of, you are now ready |
| to begin the bisection. This will make you build quite a few kernels -- usually |
| about 15 in case you encountered a regression when updating to a newer series |
| (say from 6.0.13 to 6.1.5). But do not worry, due to the trimmed build |
| configuration created earlier this works a lot faster than many people assume: |
| overall on average it will often just take about 10 to 15 minutes to compile |
| each kernel on commodity x86 machines. |
| |
| .. _bisectstart_bissbs: |
| |
| * Start the bisection and tell Git about the versions earlier established as |
| 'good' (6.0 in the following example command) and 'bad' (6.1.5):: |
| |
| cd ~/linux/ |
| git bisect start |
| git bisect good v6.0 |
| git bisect bad v6.1.5 |
| |
| [:ref:`details <bisectstart_bisref>`] |
| |
| .. _bisectbuild_bissbs: |
| |
| * Now use the code Git checked out to build, install, and boot a kernel using |
| the commands introduced earlier:: |
| |
| cp ~/kernel-config-working .config |
| make olddefconfig |
| make -j $(nproc --all) |
| # * Check if the free space suffices holding another kernel: |
| df -h /boot/ /lib/modules/ |
| sudo make modules_install |
| command -v installkernel && sudo make install |
| make -s kernelrelease | tee -a ~/kernels-built |
| reboot |
| |
| If compilation fails for some reason, run ``git bisect skip`` and restart |
| executing the stack of commands from the beginning. |
| |
| In case you skipped the 'test latest codebase' step in the guide, check its |
| description as for why the 'df [...]' and 'make -s kernelrelease [...]' |
| commands are here. |
| |
| Important note: the latter command from this point on will print release |
| identifiers that might look odd or wrong to you -- which they are not, as it's |
| totally normal to see release identifiers like '6.0-rc1-local-gcafec0cacaca0' |
| if you bisect between versions 6.1 and 6.2 for example. |
| |
| [:ref:`details <bisectbuild_bisref>`] |
| |
| .. _bisecttest_bissbs: |
| |
| * Now check if the feature that regressed works in the kernel you just built. |
| |
| You again might want to start by making sure the kernel you booted is the one |
| you just built:: |
| |
| cd ~/linux/ |
| tail -n 1 ~/kernels-built |
| uname -r |
| |
| Now verify if the feature that regressed works at this kernel bisection point. |
| If it does, run this:: |
| |
| git bisect good |
| |
| If it does not, run this:: |
| |
| git bisect bad |
| |
| Be sure about what you tell Git, as getting this wrong just once will send the |
| rest of the bisection totally off course. |
| |
| While the bisection is ongoing, Git will use the information you provided to |
| find and check out another bisection point for you to test. While doing so, it |
| will print something like 'Bisecting: 675 revisions left to test after this |
| (roughly 10 steps)' to indicate how many further changes it expects to be |
| tested. Now build and install another kernel using the instructions from the |
| previous step; afterwards follow the instructions in this step again. |
| |
| Repeat this again and again until you finish the bisection -- that's the case |
| when Git after tagging a change as 'good' or 'bad' prints something like |
| 'cafecaca0c0dacafecaca0c0dacafecaca0c0da is the first bad commit'; right |
| afterwards it will show some details about the culprit including the patch |
| description of the change. The latter might fill your terminal screen, so you |
| might need to scroll up to see the message mentioning the culprit; |
| alternatively, run ``git bisect log > ~/bisection-log``. |
| |
| [:ref:`details <bisecttest_bisref>`] |
| |
| .. _bisectlog_bissbs: |
| |
| * Store Git's bisection log and the current .config file in a safe place before |
| telling Git to reset the sources to the state before the bisection:: |
| |
| cd ~/linux/ |
| git bisect log > ~/bisection-log |
| cp .config ~/bisection-config-culprit |
| git bisect reset |
| |
| [:ref:`details <bisectlog_bisref>`] |
| |
| .. _revert_bissbs: |
| |
| * Try reverting the culprit on top of latest mainline to see if this fixes your |
| regression. |
| |
| This is optional, as it might be impossible or hard to realize. The former is |
| the case, if the bisection determined a merge commit as the culprit; the |
| latter happens if other changes depend on the culprit. But if the revert |
| succeeds, it is worth building another kernel, as it validates the result of |
| a bisection, which can easily deroute; it furthermore will let kernel |
| developers know, if they can resolve the regression with a quick revert. |
| |
| Begin by checking out the latest codebase depending on the range you bisected: |
| |
| * Did you face a regression within a stable/longterm series (say between |
| 6.0.13 and 6.0.15) that does not happen in mainline? Then check out the |
| latest codebase for the affected series like this:: |
| |
| git fetch stable |
| git switch --discard-changes --detach linux-6.0.y |
| |
| * In all other cases check out latest mainline:: |
| |
| git fetch mainline |
| git switch --discard-changes --detach mainline/master |
| |
| If you bisected a regression within a stable/longterm series that also |
| happens in mainline, there is one more thing to do: look up the mainline |
| commit-id. To do so, use a command like ``git show abcdcafecabcd`` to |
| view the patch description of the culprit. There will be a line near |
| the top which looks like 'commit cafec0cacaca0 upstream.' or |
| 'Upstream commit cafec0cacaca0'; use that commit-id in the next command |
| and not the one the bisection blamed. |
| |
| Now try reverting the culprit by specifying its commit id:: |
| |
| git revert --no-edit cafec0cacaca0 |
| |
| If that fails, give up trying and move on to the next step; if it works, |
| adjust the tag to facilitate the identification and prevent accidentally |
| overwriting another kernel:: |
| |
| cp ~/kernel-config-working .config |
| ./scripts/config --set-str CONFIG_LOCALVERSION '-local-cafec0cacaca0-reverted' |
| |
| Build a kernel using the familiar command sequence, just without copying the |
| the base .config over:: |
| |
| make olddefconfig && |
| make -j $(nproc --all) |
| # * Check if the free space suffices holding another kernel: |
| df -h /boot/ /lib/modules/ |
| sudo make modules_install |
| command -v installkernel && sudo make install |
| make -s kernelrelease | tee -a ~/kernels-built |
| reboot |
| |
| Now check one last time if the feature that made you perform a bisection works |
| with that kernel: if everything went well, it should not show the regression. |
| |
| [:ref:`details <revert_bisref>`] |
| |
| .. _introclosure_bissbs: |
| |
| Complementary tasks: cleanup during and after the bisection |
| ----------------------------------------------------------- |
| |
| During and after following this guide you might want or need to remove some of |
| the kernels you installed: the boot menu otherwise will become confusing or |
| space might run out. |
| |
| .. _makeroom_bissbs: |
| |
| * To remove one of the kernels you installed, look up its 'kernelrelease' |
| identifier. This guide stores them in '~/kernels-built', but the following |
| command will print them as well:: |
| |
| ls -ltr /lib/modules/*-local* |
| |
| You in most situations want to remove the oldest kernels built during the |
| actual bisection (e.g. segment 3 of this guide). The two ones you created |
| beforehand (e.g. to test the latest codebase and the version considered |
| 'good') might become handy to verify something later -- thus better keep them |
| around, unless you are really short on storage space. |
| |
| To remove the modules of a kernel with the kernelrelease identifier |
| '*6.0-rc1-local-gcafec0cacaca0*', start by removing the directory holding its |
| modules:: |
| |
| sudo rm -rf /lib/modules/6.0-rc1-local-gcafec0cacaca0 |
| |
| Afterwards try the following command:: |
| |
| sudo kernel-install -v remove 6.0-rc1-local-gcafec0cacaca0 |
| |
| On quite a few distributions this will delete all other kernel files installed |
| while also removing the kernel's entry from the boot menu. But on some |
| distributions kernel-install does not exist or leaves boot-loader entries or |
| kernel image and related files behind; in that case remove them as described |
| in the reference section. |
| |
| [:ref:`details <makeroom_bisref>`] |
| |
| .. _finishingtouch_bissbs: |
| |
| * Once you have finished the bisection, do not immediately remove anything you |
| set up, as you might need a few things again. What is safe to remove depends |
| on the outcome of the bisection: |
| |
| * Could you initially reproduce the regression with the latest codebase and |
| after the bisection were able to fix the problem by reverting the culprit on |
| top of the latest codebase? Then you want to keep those two kernels around |
| for a while, but safely remove all others with a '-local' in the release |
| identifier. |
| |
| * Did the bisection end on a merge-commit or seems questionable for other |
| reasons? Then you want to keep as many kernels as possible around for a few |
| days: it's pretty likely that you will be asked to recheck something. |
| |
| * In other cases it likely is a good idea to keep the following kernels around |
| for some time: the one built from the latest codebase, the one created from |
| the version considered 'good', and the last three or four you compiled |
| during the actual bisection process. |
| |
| [:ref:`details <finishingtouch_bisref>`] |
| |
| .. _introoptional_bissbs: |
| |
| Optional: test reverts, patches, or later versions |
| -------------------------------------------------- |
| |
| While or after reporting a bug, you might want or potentially will be asked to |
| test reverts, debug patches, proposed fixes, or other versions. In that case |
| follow these instructions. |
| |
| * Update your Git clone and check out the latest code. |
| |
| * In case you want to test mainline, fetch its latest changes before checking |
| its code out:: |
| |
| git fetch mainline |
| git switch --discard-changes --detach mainline/master |
| |
| * In case you want to test a stable or longterm kernel, first add the branch |
| holding the series you are interested in (6.2 in the example), unless you |
| already did so earlier:: |
| |
| git remote set-branches --add stable linux-6.2.y |
| |
| Then fetch the latest changes and check out the latest version from the |
| series:: |
| |
| git fetch stable |
| git switch --discard-changes --detach stable/linux-6.2.y |
| |
| * Copy your kernel build configuration over:: |
| |
| cp ~/kernel-config-working .config |
| |
| * Your next step depends on what you want to do: |
| |
| * In case you just want to test the latest codebase, head to the next step, |
| you are already all set. |
| |
| * In case you want to test if a revert fixes an issue, revert one or multiple |
| changes by specifying their commit ids:: |
| |
| git revert --no-edit cafec0cacaca0 |
| |
| Now give that kernel a special tag to facilitates its identification and |
| prevent accidentally overwriting another kernel:: |
| |
| ./scripts/config --set-str CONFIG_LOCALVERSION '-local-cafec0cacaca0-reverted' |
| |
| * In case you want to test a patch, store the patch in a file like |
| '/tmp/foobars-proposed-fix-v1.patch' and apply it like this:: |
| |
| git apply /tmp/foobars-proposed-fix-v1.patch |
| |
| In case of multiple patches, repeat this step with the others. |
| |
| Now give that kernel a special tag to facilitates its identification and |
| prevent accidentally overwriting another kernel:: |
| |
| ./scripts/config --set-str CONFIG_LOCALVERSION '-local-foobars-fix-v1' |
| |
| * Build a kernel using the familiar commands, just without copying the kernel |
| build configuration over, as that has been taken care of already:: |
| |
| make olddefconfig && |
| make -j $(nproc --all) |
| # * Check if the free space suffices holding another kernel: |
| df -h /boot/ /lib/modules/ |
| sudo make modules_install |
| command -v installkernel && sudo make install |
| make -s kernelrelease | tee -a ~/kernels-built |
| reboot |
| |
| * Now verify you booted the newly built kernel and check it. |
| |
| [:ref:`details <introoptional_bisref>`] |
| |
| .. _submit_improvements: |
| |
| Conclusion |
| ---------- |
| |
| You have reached the end of the step-by-step guide. |
| |
| Did you run into trouble following any of the above steps not cleared up by the |
| reference section below? Did you spot errors? Or do you have ideas how to |
| improve the guide? |
| |
| If any of that applies, please take a moment and let the maintainer of this |
| document know by email (Thorsten Leemhuis <linux@leemhuis.info>), ideally while |
| CCing the Linux docs mailing list (linux-doc@vger.kernel.org). Such feedback is |
| vital to improve this text further, which is in everybody's interest, as it |
| will enable more people to master the task described here -- and hopefully also |
| improve similar guides inspired by this one. |
| |
| |
| Reference section for the step-by-step guide |
| ============================================ |
| |
| This section holds additional information for almost all the items in the above |
| step-by-step guide. |
| |
| Preparations for building your own kernels |
| ------------------------------------------ |
| |
| *The steps in this section lay the groundwork for all further tests.* |
| [:ref:`... <introprep_bissbs>`] |
| |
| The steps in all later sections of this guide depend on those described here. |
| |
| [:ref:`back to step-by-step guide <introprep_bissbs>`]. |
| |
| .. _backup_bisref: |
| |
| Prepare for emergencies |
| ~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| *Create a fresh backup and put system repair and restore tools at hand.* |
| [:ref:`... <backup_bissbs>`] |
| |
| Remember, you are dealing with computers, which sometimes do unexpected things |
| -- especially if you fiddle with crucial parts like the kernel of an operating |
| system. That's what you are about to do in this process. Hence, better prepare |
| for something going sideways, even if that should not happen. |
| |
| [:ref:`back to step-by-step guide <backup_bissbs>`] |
| |
| .. _vanilla_bisref: |
| |
| Remove anything related to externally maintained kernel modules |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| *Remove all software that depends on externally developed kernel drivers or |
| builds them automatically.* [:ref:`...<vanilla_bissbs>`] |
| |
| Externally developed kernel modules can easily cause trouble during a bisection. |
| |
| But there is a more important reason why this guide contains this step: most |
| kernel developers will not care about reports about regressions occurring with |
| kernels that utilize such modules. That's because such kernels are not |
| considered 'vanilla' anymore, as Documentation/admin-guide/reporting-issues.rst |
| explains in more detail. |
| |
| [:ref:`back to step-by-step guide <vanilla_bissbs>`] |
| |
| .. _secureboot_bisref: |
| |
| Deal with techniques like Secure Boot |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| *On platforms with 'Secure Boot' or similar techniques, prepare everything to |
| ensure the system will permit your self-compiled kernel to boot later.* |
| [:ref:`... <secureboot_bissbs>`] |
| |
| Many modern systems allow only certain operating systems to start; that's why |
| they reject booting self-compiled kernels by default. |
| |
| You ideally deal with this by making your platform trust your self-built kernels |
| with the help of a certificate. How to do that is not described |
| here, as it requires various steps that would take the text too far away from |
| its purpose; 'Documentation/admin-guide/module-signing.rst' and various web |
| sides already explain everything needed in more detail. |
| |
| Temporarily disabling solutions like Secure Boot is another way to make your own |
| Linux boot. On commodity x86 systems it is possible to do this in the BIOS Setup |
| utility; the required steps vary a lot between machines and therefore cannot be |
| described here. |
| |
| On mainstream x86 Linux distributions there is a third and universal option: |
| disable all Secure Boot restrictions for your Linux environment. You can |
| initiate this process by running ``mokutil --disable-validation``; this will |
| tell you to create a one-time password, which is safe to write down. Now |
| restart; right after your BIOS performed all self-tests the bootloader Shim will |
| show a blue box with a message 'Press any key to perform MOK management'. Hit |
| some key before the countdown exposes, which will open a menu. Choose 'Change |
| Secure Boot state'. Shim's 'MokManager' will now ask you to enter three |
| randomly chosen characters from the one-time password specified earlier. Once |
| you provided them, confirm you really want to disable the validation. |
| Afterwards, permit MokManager to reboot the machine. |
| |
| [:ref:`back to step-by-step guide <secureboot_bissbs>`] |
| |
| .. _bootworking_bisref: |
| |
| Boot the last kernel that was working |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| *Boot into the last working kernel and briefly recheck if the feature that |
| regressed really works.* [:ref:`...<bootworking_bissbs>`] |
| |
| This will make later steps that cover creating and trimming the configuration do |
| the right thing. |
| |
| [:ref:`back to step-by-step guide <bootworking_bissbs>`] |
| |
| .. _diskspace_bisref: |
| |
| Space requirements |
| ~~~~~~~~~~~~~~~~~~ |
| |
| *Ensure to have enough free space for building Linux.* |
| [:ref:`... <diskspace_bissbs>`] |
| |
| The numbers mentioned are rough estimates with a big extra charge to be on the |
| safe side, so often you will need less. |
| |
| If you have space constraints, be sure to hay attention to the :ref:`step about |
| debug symbols' <debugsymbols_bissbs>` and its :ref:`accompanying reference |
| section' <debugsymbols_bisref>`, as disabling then will reduce the consumed disk |
| space by quite a few gigabytes. |
| |
| [:ref:`back to step-by-step guide <diskspace_bissbs>`] |
| |
| .. _rangecheck_bisref: |
| |
| Bisection range |
| ~~~~~~~~~~~~~~~ |
| |
| *Determine the kernel versions considered 'good' and 'bad' throughout this |
| guide.* [:ref:`...<rangecheck_bissbs>`] |
| |
| Establishing the range of commits to be checked is mostly straightforward, |
| except when a regression occurred when switching from a release of one stable |
| series to a release of a later series (e.g. from 6.0.13 to 6.1.5). In that case |
| Git will need some hand holding, as there is no straight line of descent. |
| |
| That's because with the release of 6.0 mainline carried on to 6.1 while the |
| stable series 6.0.y branched to the side. It's therefore theoretically possible |
| that the issue you face with 6.1.5 only worked in 6.0.13, as it was fixed by a |
| commit that went into one of the 6.0.y releases, but never hit mainline or the |
| 6.1.y series. Thankfully that normally should not happen due to the way the |
| stable/longterm maintainers maintain the code. It's thus pretty safe to assume |
| 6.0 as a 'good' kernel. That assumption will be tested anyway, as that kernel |
| will be built and tested in the segment '2' of this guide; Git would force you |
| to do this as well, if you tried bisecting between 6.0.13 and 6.1.15. |
| |
| [:ref:`back to step-by-step guide <rangecheck_bissbs>`] |
| |
| .. _buildrequires_bisref: |
| |
| Install build requirements |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| *Install all software required to build a Linux kernel.* |
| [:ref:`...<buildrequires_bissbs>`] |
| |
| The kernel is pretty stand-alone, but besides tools like the compiler you will |
| sometimes need a few libraries to build one. How to install everything needed |
| depends on your Linux distribution and the configuration of the kernel you are |
| about to build. |
| |
| Here are a few examples what you typically need on some mainstream |
| distributions: |
| |
| * Arch Linux and derivatives:: |
| |
| sudo pacman --needed -S bc binutils bison flex gcc git kmod libelf openssl \ |
| pahole perl zlib ncurses qt6-base |
| |
| * Debian, Ubuntu, and derivatives:: |
| |
| sudo apt install bc binutils bison dwarves flex gcc git kmod libelf-dev \ |
| libssl-dev make openssl pahole perl-base pkg-config zlib1g-dev \ |
| libncurses-dev qt6-base-dev g++ |
| |
| * Fedora and derivatives:: |
| |
| sudo dnf install binutils \ |
| /usr/bin/{bc,bison,flex,gcc,git,openssl,make,perl,pahole,rpmbuild} \ |
| /usr/include/{libelf.h,openssl/pkcs7.h,zlib.h,ncurses.h,qt6/QtGui/QAction} |
| |
| * openSUSE and derivatives:: |
| |
| sudo zypper install bc binutils bison dwarves flex gcc git \ |
| kernel-install-tools libelf-devel make modutils openssl openssl-devel \ |
| perl-base zlib-devel rpm-build ncurses-devel qt6-base-devel |
| |
| These commands install a few packages that are often, but not always needed. You |
| for example might want to skip installing the development headers for ncurses, |
| which you will only need in case you later might want to adjust the kernel build |
| configuration using make the targets 'menuconfig' or 'nconfig'; likewise omit |
| the headers of Qt6 if you do not plan to adjust the .config using 'xconfig'. |
| |
| You furthermore might need additional libraries and their development headers |
| for tasks not covered in this guide -- for example when building utilities from |
| the kernel's tools/ directory. |
| |
| [:ref:`back to step-by-step guide <buildrequires_bissbs>`] |
| |
| .. _sources_bisref: |
| |
| Download the sources using Git |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| *Retrieve the Linux mainline sources.* |
| [:ref:`...<sources_bissbs>`] |
| |
| The step-by-step guide outlines how to download the Linux sources using a full |
| Git clone of Linus' mainline repository. There is nothing more to say about |
| that -- but there are two alternatives ways to retrieve the sources that might |
| work better for you: |
| |
| * If you have an unreliable internet connection, consider |
| :ref:`using a 'Git bundle'<sources_bundle_bisref>`. |
| |
| * If downloading the complete repository would take too long or requires too |
| much storage space, consider :ref:`using a 'shallow |
| clone'<sources_shallow_bisref>`. |
| |
| .. _sources_bundle_bisref: |
| |
| Downloading Linux mainline sources using a bundle |
| """"""""""""""""""""""""""""""""""""""""""""""""" |
| |
| Use the following commands to retrieve the Linux mainline sources using a |
| bundle:: |
| |
| wget -c \ |
| https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/clone.bundle |
| git clone --no-checkout clone.bundle ~/linux/ |
| cd ~/linux/ |
| git remote remove origin |
| git remote add mainline \ |
| https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git |
| git fetch mainline |
| git remote add -t master stable \ |
| https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git |
| |
| In case the 'wget' command fails, just re-execute it, it will pick up where |
| it left off. |
| |
| [:ref:`back to step-by-step guide <sources_bissbs>`] |
| [:ref:`back to section intro <sources_bisref>`] |
| |
| .. _sources_shallow_bisref: |
| |
| Downloading Linux mainline sources using a shallow clone |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| First, execute the following command to retrieve the latest mainline codebase:: |
| |
| git clone -o mainline --no-checkout --depth 1 -b master \ |
| https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git ~/linux/ |
| cd ~/linux/ |
| git remote add -t master stable \ |
| https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git |
| |
| Now deepen your clone's history to the second predecessor of the mainline |
| release of your 'good' version. In case the latter are 6.0 or 6.0.13, 5.19 would |
| be the first predecessor and 5.18 the second -- hence deepen the history up to |
| that version:: |
| |
| git fetch --shallow-exclude=v5.18 mainline |
| |
| Afterwards add the stable Git repository as remote and all required stable |
| branches as explained in the step-by-step guide. |
| |
| Note, shallow clones have a few peculiar characteristics: |
| |
| * For bisections the history needs to be deepened a few mainline versions |
| farther than it seems necessary, as explained above already. That's because |
| Git otherwise will be unable to revert or describe most of the commits within |
| a range (say 6.1..6.2), as they are internally based on earlier kernels |
| releases (like 6.0-rc2 or 5.19-rc3). |
| |
| * This document in most places uses ``git fetch`` with ``--shallow-exclude=`` |
| to specify the earliest version you care about (or to be precise: its git |
| tag). You alternatively can use the parameter ``--shallow-since=`` to specify |
| an absolute (say ``'2023-07-15'``) or relative (``'12 months'``) date to |
| define the depth of the history you want to download. When using them while |
| bisecting mainline, ensure to deepen the history to at least 7 months before |
| the release of the mainline release your 'good' kernel is based on. |
| |
| * Be warned, when deepening your clone you might encounter an error like |
| 'fatal: error in object: unshallow cafecaca0c0dacafecaca0c0dacafecaca0c0da'. |
| In that case run ``git repack -d`` and try again. |
| |
| [:ref:`back to step-by-step guide <sources_bissbs>`] |
| [:ref:`back to section intro <sources_bisref>`] |
| |
| .. _oldconfig_bisref: |
| |
| Start defining the build configuration for your kernel |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| *Start preparing a kernel build configuration (the '.config' file).* |
| [:ref:`... <oldconfig_bissbs>`] |
| |
| *Note, this is the first of multiple steps in this guide that create or modify |
| build artifacts. The commands used in this guide store them right in the source |
| tree to keep things simple. In case you prefer storing the build artifacts |
| separately, create a directory like '~/linux-builddir/' and add the parameter |
| ``O=~/linux-builddir/`` to all make calls used throughout this guide. You will |
| have to point other commands there as well -- among them the ``./scripts/config |
| [...]`` commands, which will require ``--file ~/linux-builddir/.config`` to |
| locate the right build configuration.* |
| |
| Two things can easily go wrong when creating a .config file as advised: |
| |
| * The oldconfig target will use a .config file from your build directory, if |
| one is already present there (e.g. '~/linux/.config'). That's totally fine if |
| that's what you intend (see next step), but in all other cases you want to |
| delete it. This for example is important in case you followed this guide |
| further, but due to problems come back here to redo the configuration from |
| scratch. |
| |
| * Sometimes olddefconfig is unable to locate the .config file for your running |
| kernel and will use defaults, as briefly outlined in the guide. In that case |
| check if your distribution ships the configuration somewhere and manually put |
| it in the right place (e.g. '~/linux/.config') if it does. On distributions |
| where /proc/config.gz exists this can be achieved using this command:: |
| |
| zcat /proc/config.gz > .config |
| |
| Once you put it there, run ``make olddefconfig`` again to adjust it to the |
| needs of the kernel about to be built. |
| |
| Note, the olddefconfig target will set any undefined build options to their |
| default value. If you prefer to set such configuration options manually, use |
| ``make oldconfig`` instead. Then for each undefined configuration option you |
| will be asked how to proceed; in case you are unsure what to answer, simply hit |
| 'enter' to apply the default value. Note though that for bisections you normally |
| want to go with the defaults, as you otherwise might enable a new feature that |
| causes a problem looking like regressions (for example due to security |
| restrictions). |
| |
| Occasionally odd things happen when trying to use a config file prepared for one |
| kernel (say 6.1) on an older mainline release -- especially if it is much older |
| (say 5.15). That's one of the reasons why the previous step in the guide told |
| you to boot the kernel where everything works. If you manually add a .config |
| file you thus want to ensure it's from the working kernel and not from a one |
| that shows the regression. |
| |
| In case you want to build kernels for another machine, locate its kernel build |
| configuration; usually ``ls /boot/config-$(uname -r)`` will print its name. Copy |
| that file to the build machine and store it as ~/linux/.config; afterwards run |
| ``make olddefconfig`` to adjust it. |
| |
| [:ref:`back to step-by-step guide <oldconfig_bissbs>`] |
| |
| .. _localmodconfig_bisref: |
| |
| Trim the build configuration for your kernel |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| *Disable any kernel modules apparently superfluous for your setup.* |
| [:ref:`... <localmodconfig_bissbs>`] |
| |
| As explained briefly in the step-by-step guide already: with localmodconfig it |
| can easily happen that your self-built kernels will lack modules for tasks you |
| did not perform at least once before utilizing this make target. That happens |
| when a task requires kernel modules which are only autoloaded when you execute |
| it for the first time. So when you never performed that task since starting your |
| kernel the modules will not have been loaded -- and from localmodonfig's point |
| of view look superfluous, which thus disables them to reduce the amount of code |
| to be compiled. |
| |
| You can try to avoid this by performing typical tasks that often will autoload |
| additional kernel modules: start a VM, establish VPN connections, loop-mount a |
| CD/DVD ISO, mount network shares (CIFS, NFS, ...), and connect all external |
| devices (2FA keys, headsets, webcams, ...) as well as storage devices with file |
| systems you otherwise do not utilize (btrfs, ext4, FAT, NTFS, XFS, ...). But it |
| is hard to think of everything that might be needed -- even kernel developers |
| often forget one thing or another at this point. |
| |
| Do not let that risk bother you, especially when compiling a kernel only for |
| testing purposes: everything typically crucial will be there. And if you forget |
| something important you can turn on a missing feature manually later and quickly |
| run the commands again to compile and install a kernel that has everything you |
| need. |
| |
| But if you plan to build and use self-built kernels regularly, you might want to |
| reduce the risk by recording which modules your system loads over the course of |
| a few weeks. You can automate this with `modprobed-db |
| <https://github.com/graysky2/modprobed-db>`_. Afterwards use ``LSMOD=<path>`` to |
| point localmodconfig to the list of modules modprobed-db noticed being used:: |
| |
| yes '' | make LSMOD='${HOME}'/.config/modprobed.db localmodconfig |
| |
| That parameter also allows you to build trimmed kernels for another machine in |
| case you copied a suitable .config over to use as base (see previous step). Just |
| run ``lsmod > lsmod_foo-machine`` on that system and copy the generated file to |
| your build's host home directory. Then run these commands instead of the one the |
| step-by-step guide mentions:: |
| |
| yes '' | make LSMOD=~/lsmod_foo-machine localmodconfig |
| |
| [:ref:`back to step-by-step guide <localmodconfig_bissbs>`] |
| |
| .. _tagging_bisref: |
| |
| Tag the kernels about to be build |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| *Ensure all the kernels you will build are clearly identifiable using a |
| special tag and a unique version identifier.* [:ref:`... <tagging_bissbs>`] |
| |
| This allows you to differentiate your distribution's kernels from those created |
| during this process, as the file or directories for the latter will contain |
| '-local' in the name; it also helps picking the right entry in the boot menu and |
| not lose track of you kernels, as their version numbers will look slightly |
| confusing during the bisection. |
| |
| [:ref:`back to step-by-step guide <tagging_bissbs>`] |
| |
| .. _debugsymbols_bisref: |
| |
| Decide to enable or disable debug symbols |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| *Decide how to handle debug symbols.* [:ref:`... <debugsymbols_bissbs>`] |
| |
| Having debug symbols available can be important when your kernel throws a |
| 'panic', 'Oops', 'warning', or 'BUG' later when running, as then you will be |
| able to find the exact place where the problem occurred in the code. But |
| collecting and embedding the needed debug information takes time and consumes |
| quite a bit of space: in late 2022 the build artifacts for a typical x86 kernel |
| trimmed with localmodconfig consumed around 5 Gigabyte of space with debug |
| symbols, but less than 1 when they were disabled. The resulting kernel image and |
| modules are bigger as well, which increases storage requirements for /boot/ and |
| load times. |
| |
| In case you want a small kernel and are unlikely to decode a stack trace later, |
| you thus might want to disable debug symbols to avoid those downsides. If it |
| later turns out that you need them, just enable them as shown and rebuild the |
| kernel. |
| |
| You on the other hand definitely want to enable them for this process, if there |
| is a decent chance that you need to decode a stack trace later. The section |
| 'Decode failure messages' in Documentation/admin-guide/reporting-issues.rst |
| explains this process in more detail. |
| |
| [:ref:`back to step-by-step guide <debugsymbols_bissbs>`] |
| |
| .. _configmods_bisref: |
| |
| Adjust build configuration |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| *Check if you may want or need to adjust some other kernel configuration |
| options:* |
| |
| Depending on your needs you at this point might want or have to adjust some |
| kernel configuration options. |
| |
| .. _configmods_distros_bisref: |
| |
| Distro specific adjustments |
| """"""""""""""""""""""""""" |
| |
| *Are you running* [:ref:`... <configmods_bissbs>`] |
| |
| The following sections help you to avoid build problems that are known to occur |
| when following this guide on a few commodity distributions. |
| |
| **Debian:** |
| |
| * Remove a stale reference to a certificate file that would cause your build to |
| fail:: |
| |
| ./scripts/config --set-str SYSTEM_TRUSTED_KEYS '' |
| |
| Alternatively, download the needed certificate and make that configuration |
| option point to it, as `the Debian handbook explains in more detail |
| <https://debian-handbook.info/browse/stable/sect.kernel-compilation.html>`_ |
| -- or generate your own, as explained in |
| Documentation/admin-guide/module-signing.rst. |
| |
| [:ref:`back to step-by-step guide <configmods_bissbs>`] |
| |
| .. _configmods_individual_bisref: |
| |
| Individual adjustments |
| """""""""""""""""""""" |
| |
| *If you want to influence the other aspects of the configuration, do so |
| now.* [:ref:`... <configmods_bissbs>`] |
| |
| At this point you can use a command like ``make menuconfig`` or ``make nconfig`` |
| to enable or disable certain features using a text-based user interface; to use |
| a graphical configuration utility, run ``make xconfig`` instead. Both of them |
| require development libraries from toolkits they are rely on (ncurses |
| respectively Qt5 or Qt6); an error message will tell you if something required |
| is missing. |
| |
| [:ref:`back to step-by-step guide <configmods_bissbs>`] |
| |
| .. _saveconfig_bisref: |
| |
| Put the .config file aside |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| *Reprocess the .config after the latest changes and store it in a safe place.* |
| [:ref:`... <saveconfig_bissbs>`] |
| |
| Put the .config you prepared aside, as you want to copy it back to the build |
| directory every time during this guide before you start building another |
| kernel. That's because going back and forth between different versions can alter |
| .config files in odd ways; those occasionally cause side effects that could |
| confuse testing or in some cases render the result of your bisection |
| meaningless. |
| |
| [:ref:`back to step-by-step guide <saveconfig_bissbs>`] |
| |
| .. _introlatestcheck_bisref: |
| |
| Try to reproduce the problem with the latest codebase |
| ----------------------------------------------------- |
| |
| *Verify the regression is not caused by some .config change and check if it |
| still occurs with the latest codebase.* [:ref:`... <introlatestcheck_bissbs>`] |
| |
| For some readers it might seem unnecessary to check the latest codebase at this |
| point, especially if you did that already with a kernel prepared by your |
| distributor or face a regression within a stable/longterm series. But it's |
| highly recommended for these reasons: |
| |
| * You will run into any problems caused by your setup before you actually begin |
| a bisection. That will make it a lot easier to differentiate between 'this |
| most likely is some problem in my setup' and 'this change needs to be skipped |
| during the bisection, as the kernel sources at that stage contain an unrelated |
| problem that causes building or booting to fail'. |
| |
| * These steps will rule out if your problem is caused by some change in the |
| build configuration between the 'working' and the 'broken' kernel. This for |
| example can happen when your distributor enabled an additional security |
| feature in the newer kernel which was disabled or not yet supported by the |
| older kernel. That security feature might get into the way of something you |
| do -- in which case your problem from the perspective of the Linux kernel |
| upstream developers is not a regression, as |
| Documentation/admin-guide/reporting-regressions.rst explains in more detail. |
| You thus would waste your time if you'd try to bisect this. |
| |
| * If the cause for your regression was already fixed in the latest mainline |
| codebase, you'd perform the bisection for nothing. This holds true for a |
| regression you encountered with a stable/longterm release as well, as they are |
| often caused by problems in mainline changes that were backported -- in which |
| case the problem will have to be fixed in mainline first. Maybe it already was |
| fixed there and the fix is already in the process of being backported. |
| |
| * For regressions within a stable/longterm series it's furthermore crucial to |
| know if the issue is specific to that series or also happens in the mainline |
| kernel, as the report needs to be sent to different people: |
| |
| * Regressions specific to a stable/longterm series are the stable team's |
| responsibility; mainline Linux developers might or might not care. |
| |
| * Regressions also happening in mainline are something the regular Linux |
| developers and maintainers have to handle; the stable team does not care |
| and does not need to be involved in the report, they just should be told |
| to backport the fix once it's ready. |
| |
| Your report might be ignored if you send it to the wrong party -- and even |
| when you get a reply there is a decent chance that developers tell you to |
| evaluate which of the two cases it is before they take a closer look. |
| |
| [:ref:`back to step-by-step guide <introlatestcheck_bissbs>`] |
| |
| .. _checkoutmaster_bisref: |
| |
| Check out the latest Linux codebase |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| *Check out the latest Linux codebase.* |
| [:ref:`... <checkoutmaster_bissbs>`] |
| |
| In case you later want to recheck if an ever newer codebase might fix the |
| problem, remember to run that ``git fetch --shallow-exclude [...]`` command |
| again mentioned earlier to update your local Git repository. |
| |
| [:ref:`back to step-by-step guide <checkoutmaster_bissbs>`] |
| |
| .. _build_bisref: |
| |
| Build your kernel |
| ~~~~~~~~~~~~~~~~~ |
| |
| *Build the image and the modules of your first kernel using the config file |
| you prepared.* [:ref:`... <build_bissbs>`] |
| |
| A lot can go wrong at this stage, but the instructions below will help you help |
| yourself. Another subsection explains how to directly package your kernel up as |
| deb, rpm or tar file. |
| |
| Dealing with build errors |
| """"""""""""""""""""""""" |
| |
| When a build error occurs, it might be caused by some aspect of your machine's |
| setup that often can be fixed quickly; other times though the problem lies in |
| the code and can only be fixed by a developer. A close examination of the |
| failure messages coupled with some research on the internet will often tell you |
| which of the two it is. To perform such investigation, restart the build |
| process like this:: |
| |
| make V=1 |
| |
| The ``V=1`` activates verbose output, which might be needed to see the actual |
| error. To make it easier to spot, this command also omits the ``-j $(nproc |
| --all)`` used earlier to utilize every CPU core in the system for the job -- but |
| this parallelism also results in some clutter when failures occur. |
| |
| After a few seconds the build process should run into the error again. Now try |
| to find the most crucial line describing the problem. Then search the internet |
| for the most important and non-generic section of that line (say 4 to 8 words); |
| avoid or remove anything that looks remotely system-specific, like your username |
| or local path names like ``/home/username/linux/``. First try your regular |
| internet search engine with that string, afterwards search Linux kernel mailing |
| lists via `lore.kernel.org/all/ <https://lore.kernel.org/all/>`_. |
| |
| This most of the time will find something that will explain what is wrong; quite |
| often one of the hits will provide a solution for your problem, too. If you |
| do not find anything that matches your problem, try again from a different angle |
| by modifying your search terms or using another line from the error messages. |
| |
| In the end, most issues you run into have likely been encountered and |
| reported by others already. That includes issues where the cause is not your |
| system, but lies in the code. If you run into one of those, you might thus find |
| a solution (e.g. a patch) or workaround for your issue, too. |
| |
| Package your kernel up |
| """""""""""""""""""""" |
| |
| The step-by-step guide uses the default make targets (e.g. 'bzImage' and |
| 'modules' on x86) to build the image and the modules of your kernel, which later |
| steps of the guide then install. You instead can also directly build everything |
| and directly package it up by using one of the following targets: |
| |
| * ``make -j $(nproc --all) bindeb-pkg`` to generate a deb package |
| |
| * ``make -j $(nproc --all) binrpm-pkg`` to generate a rpm package |
| |
| * ``make -j $(nproc --all) tarbz2-pkg`` to generate a bz2 compressed tarball |
| |
| This is just a selection of available make targets for this purpose, see |
| ``make help`` for others. You can also use these targets after running |
| ``make -j $(nproc --all)``, as they will pick up everything already built. |
| |
| If you employ the targets to generate deb or rpm packages, ignore the |
| step-by-step guide's instructions on installing and removing your kernel; |
| instead install and remove the packages using the package utility for the format |
| (e.g. dpkg and rpm) or a package management utility build on top of them (apt, |
| aptitude, dnf/yum, zypper, ...). Be aware that the packages generated using |
| these two make targets are designed to work on various distributions utilizing |
| those formats, they thus will sometimes behave differently than your |
| distribution's kernel packages. |
| |
| [:ref:`back to step-by-step guide <build_bissbs>`] |
| |
| .. _install_bisref: |
| |
| Put the kernel in place |
| ~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| *Install the kernel you just built.* [:ref:`... <install_bissbs>`] |
| |
| What you need to do after executing the command in the step-by-step guide |
| depends on the existence and the implementation of ``/sbin/installkernel`` |
| executable on your distribution. |
| |
| If installkernel is found, the kernel's build system will delegate the actual |
| installation of your kernel image to this executable, which then performs some |
| or all of these tasks: |
| |
| * On almost all Linux distributions installkernel will store your kernel's |
| image in /boot/, usually as '/boot/vmlinuz-<kernelrelease_id>'; often it will |
| put a 'System.map-<kernelrelease_id>' alongside it. |
| |
| * On most distributions installkernel will then generate an 'initramfs' |
| (sometimes also called 'initrd'), which usually are stored as |
| '/boot/initramfs-<kernelrelease_id>.img' or |
| '/boot/initrd-<kernelrelease_id>'. Commodity distributions rely on this file |
| for booting, hence ensure to execute the make target 'modules_install' first, |
| as your distribution's initramfs generator otherwise will be unable to find |
| the modules that go into the image. |
| |
| * On some distributions installkernel will then add an entry for your kernel |
| to your bootloader's configuration. |
| |
| You have to take care of some or all of the tasks yourself, if your |
| distribution lacks a installkernel script or does only handle part of them. |
| Consult the distribution's documentation for details. If in doubt, install the |
| kernel manually:: |
| |
| sudo install -m 0600 $(make -s image_name) /boot/vmlinuz-$(make -s kernelrelease) |
| sudo install -m 0600 System.map /boot/System.map-$(make -s kernelrelease) |
| |
| Now generate your initramfs using the tools your distribution provides for this |
| process. Afterwards add your kernel to your bootloader configuration and reboot. |
| |
| [:ref:`back to step-by-step guide <install_bissbs>`] |
| |
| .. _storagespace_bisref: |
| |
| Storage requirements per kernel |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| *Check how much storage space the kernel, its modules, and other related files |
| like the initramfs consume.* [:ref:`... <storagespace_bissbs>`] |
| |
| The kernels built during a bisection consume quite a bit of space in /boot/ and |
| /lib/modules/, especially if you enabled debug symbols. That makes it easy to |
| fill up volumes during a bisection -- and due to that even kernels which used to |
| work earlier might fail to boot. To prevent that you will need to know how much |
| space each installed kernel typically requires. |
| |
| Note, most of the time the pattern '/boot/*$(make -s kernelrelease)*' used in |
| the guide will match all files needed to boot your kernel -- but neither the |
| path nor the naming scheme are mandatory. On some distributions you thus will |
| need to look in different places. |
| |
| [:ref:`back to step-by-step guide <storagespace_bissbs>`] |
| |
| .. _tainted_bisref: |
| |
| Check if your newly built kernel considers itself 'tainted' |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| *Check if the kernel marked itself as 'tainted'.* |
| [:ref:`... <tainted_bissbs>`] |
| |
| Linux marks itself as tainted when something happens that potentially leads to |
| follow-up errors that look totally unrelated. That is why developers might |
| ignore or react scantly to reports from tainted kernels -- unless of course the |
| kernel set the flag right when the reported bug occurred. |
| |
| That's why you want check why a kernel is tainted as explained in |
| Documentation/admin-guide/tainted-kernels.rst; doing so is also in your own |
| interest, as your testing might be flawed otherwise. |
| |
| [:ref:`back to step-by-step guide <tainted_bissbs>`] |
| |
| .. _recheckbroken_bisref: |
| |
| Check the kernel built from a recent mainline codebase |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| *Verify if your bug occurs with the newly built kernel.* |
| [:ref:`... <recheckbroken_bissbs>`] |
| |
| There are a couple of reasons why your bug or regression might not show up with |
| the kernel you built from the latest codebase. These are the most frequent: |
| |
| * The bug was fixed meanwhile. |
| |
| * What you suspected to be a regression was caused by a change in the build |
| configuration the provider of your kernel carried out. |
| |
| * Your problem might be a race condition that does not show up with your kernel; |
| the trimmed build configuration, a different setting for debug symbols, the |
| compiler used, and various other things can cause this. |
| |
| * In case you encountered the regression with a stable/longterm kernel it might |
| be a problem that is specific to that series; the next step in this guide will |
| check this. |
| |
| [:ref:`back to step-by-step guide <recheckbroken_bissbs>`] |
| |
| .. _recheckstablebroken_bisref: |
| |
| Check the kernel built from the latest stable/longterm codebase |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| *Are you facing a regression within a stable/longterm release, but failed to |
| reproduce it with the kernel you just built using the latest mainline sources? |
| Then check if the latest codebase for the particular series might already fix |
| the problem.* [:ref:`... <recheckstablebroken_bissbs>`] |
| |
| If this kernel does not show the regression either, there most likely is no need |
| for a bisection. |
| |
| [:ref:`back to step-by-step guide <recheckstablebroken_bissbs>`] |
| |
| .. _introworkingcheck_bisref: |
| |
| Ensure the 'good' version is really working well |
| ------------------------------------------------ |
| |
| *Check if the kernels you build work fine.* |
| [:ref:`... <introworkingcheck_bissbs>`] |
| |
| This section will reestablish a known working base. Skipping it might be |
| appealing, but is usually a bad idea, as it does something important: |
| |
| It will ensure the .config file you prepared earlier actually works as expected. |
| That is in your own interest, as trimming the configuration is not foolproof -- |
| and you might be building and testing ten or more kernels for nothing before |
| starting to suspect something might be wrong with the build configuration. |
| |
| That alone is reason enough to spend the time on this, but not the only reason. |
| |
| Many readers of this guide normally run kernels that are patched, use add-on |
| modules, or both. Those kernels thus are not considered 'vanilla' -- therefore |
| it's possible that the thing that regressed might never have worked in vanilla |
| builds of the 'good' version in the first place. |
| |
| There is a third reason for those that noticed a regression between |
| stable/longterm kernels of different series (e.g. 6.0.13..6.1.5): it will |
| ensure the kernel version you assumed to be 'good' earlier in the process (e.g. |
| 6.0) actually is working. |
| |
| [:ref:`back to step-by-step guide <introworkingcheck_bissbs>`] |
| |
| .. _recheckworking_bisref: |
| |
| Build your own version of the 'good' kernel |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| *Build your own variant of the working kernel and check if the feature that |
| regressed works as expected with it.* [:ref:`... <recheckworking_bissbs>`] |
| |
| In case the feature that broke with newer kernels does not work with your first |
| self-built kernel, find and resolve the cause before moving on. There are a |
| multitude of reasons why this might happen. Some ideas where to look: |
| |
| * Check the taint status and the output of ``dmesg``, maybe something unrelated |
| went wrong. |
| |
| * Maybe localmodconfig did something odd and disabled the module required to |
| test the feature? Then you might want to recreate a .config file based on the |
| one from the last working kernel and skip trimming it down; manually disabling |
| some features in the .config might work as well to reduce the build time. |
| |
| * Maybe it's not a kernel regression and something that is caused by some fluke, |
| a broken initramfs (also known as initrd), new firmware files, or an updated |
| userland software? |
| |
| * Maybe it was a feature added to your distributor's kernel which vanilla Linux |
| at that point never supported? |
| |
| Note, if you found and fixed problems with the .config file, you want to use it |
| to build another kernel from the latest codebase, as your earlier tests with |
| mainline and the latest version from an affected stable/longterm series were |
| most likely flawed. |
| |
| [:ref:`back to step-by-step guide <recheckworking_bissbs>`] |
| |
| Perform a bisection and validate the result |
| ------------------------------------------- |
| |
| *With all the preparations and precaution builds taken care of, you are now |
| ready to begin the bisection.* [:ref:`... <introbisect_bissbs>`] |
| |
| The steps in this segment perform and validate the bisection. |
| |
| [:ref:`back to step-by-step guide <introbisect_bissbs>`]. |
| |
| .. _bisectstart_bisref: |
| |
| Start the bisection |
| ~~~~~~~~~~~~~~~~~~~ |
| |
| *Start the bisection and tell Git about the versions earlier established as |
| 'good' and 'bad'.* [:ref:`... <bisectstart_bissbs>`] |
| |
| This will start the bisection process; the last of the commands will make Git |
| check out a commit round about half-way between the 'good' and the 'bad' changes |
| for you to test. |
| |
| [:ref:`back to step-by-step guide <bisectstart_bissbs>`] |
| |
| .. _bisectbuild_bisref: |
| |
| Build a kernel from the bisection point |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| *Build, install, and boot a kernel from the code Git checked out using the |
| same commands you used earlier.* [:ref:`... <bisectbuild_bissbs>`] |
| |
| There are two things worth of note here: |
| |
| * Occasionally building the kernel will fail or it might not boot due some |
| problem in the code at the bisection point. In that case run this command:: |
| |
| git bisect skip |
| |
| Git will then check out another commit nearby which with a bit of luck should |
| work better. Afterwards restart executing this step. |
| |
| * Those slightly odd looking version identifiers can happen during bisections, |
| because the Linux kernel subsystems prepare their changes for a new mainline |
| release (say 6.2) before its predecessor (e.g. 6.1) is finished. They thus |
| base them on a somewhat earlier point like 6.1-rc1 or even 6.0 -- and then |
| get merged for 6.2 without rebasing nor squashing them once 6.1 is out. This |
| leads to those slightly odd looking version identifiers coming up during |
| bisections. |
| |
| [:ref:`back to step-by-step guide <bisectbuild_bissbs>`] |
| |
| .. _bisecttest_bisref: |
| |
| Bisection checkpoint |
| ~~~~~~~~~~~~~~~~~~~~ |
| |
| *Check if the feature that regressed works in the kernel you just built.* |
| [:ref:`... <bisecttest_bissbs>`] |
| |
| Ensure what you tell Git is accurate: getting it wrong just one time will bring |
| the rest of the bisection totally off course, hence all testing after that point |
| will be for nothing. |
| |
| [:ref:`back to step-by-step guide <bisecttest_bissbs>`] |
| |
| .. _bisectlog_bisref: |
| |
| Put the bisection log away |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| *Store Git's bisection log and the current .config file in a safe place.* |
| [:ref:`... <bisectlog_bissbs>`] |
| |
| As indicated above: declaring just one kernel wrongly as 'good' or 'bad' will |
| render the end result of a bisection useless. In that case you'd normally have |
| to restart the bisection from scratch. The log can prevent that, as it might |
| allow someone to point out where a bisection likely went sideways -- and then |
| instead of testing ten or more kernels you might only have to build a few to |
| resolve things. |
| |
| The .config file is put aside, as there is a decent chance that developers might |
| ask for it after you report the regression. |
| |
| [:ref:`back to step-by-step guide <bisectlog_bissbs>`] |
| |
| .. _revert_bisref: |
| |
| Try reverting the culprit |
| ~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| *Try reverting the culprit on top of the latest codebase to see if this fixes |
| your regression.* [:ref:`... <revert_bissbs>`] |
| |
| This is an optional step, but whenever possible one you should try: there is a |
| decent chance that developers will ask you to perform this step when you bring |
| the bisection result up. So give it a try, you are in the flow already, building |
| one more kernel shouldn't be a big deal at this point. |
| |
| The step-by-step guide covers everything relevant already except one slightly |
| rare thing: did you bisected a regression that also happened with mainline using |
| a stable/longterm series, but Git failed to revert the commit in mainline? Then |
| try to revert the culprit in the affected stable/longterm series -- and if that |
| succeeds, test that kernel version instead. |
| |
| [:ref:`back to step-by-step guide <revert_bissbs>`] |
| |
| Cleanup steps during and after following this guide |
| --------------------------------------------------- |
| |
| *During and after following this guide you might want or need to remove some |
| of the kernels you installed.* [:ref:`... <introclosure_bissbs>`] |
| |
| The steps in this section describe clean-up procedures. |
| |
| [:ref:`back to step-by-step guide <introclosure_bissbs>`]. |
| |
| .. _makeroom_bisref: |
| |
| Cleaning up during the bisection |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| *To remove one of the kernels you installed, look up its 'kernelrelease' |
| identifier.* [:ref:`... <makeroom_bissbs>`] |
| |
| The kernels you install during this process are easy to remove later, as its |
| parts are only stored in two places and clearly identifiable. You thus do not |
| need to worry to mess up your machine when you install a kernel manually (and |
| thus bypass your distribution's packaging system): all parts of your kernels are |
| relatively easy to remove later. |
| |
| One of the two places is a directory in /lib/modules/, which holds the modules |
| for each installed kernel. This directory is named after the kernel's release |
| identifier; hence, to remove all modules for one of the kernels you built, |
| simply remove its modules directory in /lib/modules/. |
| |
| The other place is /boot/, where typically two up to five files will be placed |
| during installation of a kernel. All of them usually contain the release name in |
| their file name, but how many files and their exact names depend somewhat on |
| your distribution's installkernel executable and its initramfs generator. On |
| some distributions the ``kernel-install remove...`` command mentioned in the |
| step-by-step guide will delete all of these files for you while also removing |
| the menu entry for the kernel from your bootloader configuration. On others you |
| have to take care of these two tasks yourself. The following command should |
| interactively remove the three main files of a kernel with the release name |
| '6.0-rc1-local-gcafec0cacaca0':: |
| |
| rm -i /boot/{System.map,vmlinuz,initr}-6.0-rc1-local-gcafec0cacaca0 |
| |
| Afterwards check for other files in /boot/ that have |
| '6.0-rc1-local-gcafec0cacaca0' in their name and consider deleting them as well. |
| Now remove the boot entry for the kernel from your bootloader's configuration; |
| the steps to do that vary quite a bit between Linux distributions. |
| |
| Note, be careful with wildcards like '*' when deleting files or directories |
| for kernels manually: you might accidentally remove files of a 6.0.13 kernel |
| when all you want is to remove 6.0 or 6.0.1. |
| |
| [:ref:`back to step-by-step guide <makeroom_bissbs>`] |
| |
| Cleaning up after the bisection |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| .. _finishingtouch_bisref: |
| |
| *Once you have finished the bisection, do not immediately remove anything |
| you set up, as you might need a few things again.* |
| [:ref:`... <finishingtouch_bissbs>`] |
| |
| When you are really short of storage space removing the kernels as described in |
| the step-by-step guide might not free as much space as you would like. In that |
| case consider running ``rm -rf ~/linux/*`` as well now. This will remove the |
| build artifacts and the Linux sources, but will leave the Git repository |
| (~/linux/.git/) behind -- a simple ``git reset --hard`` thus will bring the |
| sources back. |
| |
| Removing the repository as well would likely be unwise at this point: there |
| is a decent chance developers will ask you to build another kernel to |
| perform additional tests -- like testing a debug patch or a proposed fix. |
| Details on how to perform those can be found in the section :ref:`Optional |
| tasks: test reverts, patches, or later versions <introoptional_bissbs>`. |
| |
| Additional tests are also the reason why you want to keep the |
| ~/kernel-config-working file around for a few weeks. |
| |
| [:ref:`back to step-by-step guide <finishingtouch_bissbs>`] |
| |
| .. _introoptional_bisref: |
| |
| Test reverts, patches, or later versions |
| ---------------------------------------- |
| |
| *While or after reporting a bug, you might want or potentially will be asked |
| to test reverts, patches, proposed fixes, or other versions.* |
| [:ref:`... <introoptional_bissbs>`] |
| |
| All the commands used in this section should be pretty straight forward, so |
| there is not much to add except one thing: when setting a kernel tag as |
| instructed, ensure it is not much longer than the one used in the example, as |
| problems will arise if the kernelrelease identifier exceeds 63 characters. |
| |
| [:ref:`back to step-by-step guide <introoptional_bissbs>`]. |
| |
| |
| Additional information |
| ====================== |
| |
| .. _buildhost_bis: |
| |
| Build kernels on a different machine |
| ------------------------------------ |
| |
| To compile kernels on another system, slightly alter the step-by-step guide's |
| instructions: |
| |
| * Start following the guide on the machine where you want to install and test |
| the kernels later. |
| |
| * After executing ':ref:`Boot into the working kernel and briefly use the |
| apparently broken feature <bootworking_bissbs>`', save the list of loaded |
| modules to a file using ``lsmod > ~/test-machine-lsmod``. Then locate the |
| build configuration for the running kernel (see ':ref:`Start defining the |
| build configuration for your kernel <oldconfig_bisref>`' for hints on where |
| to find it) and store it as '~/test-machine-config-working'. Transfer both |
| files to the home directory of your build host. |
| |
| * Continue the guide on the build host (e.g. with ':ref:`Ensure to have enough |
| free space for building [...] <diskspace_bissbs>`'). |
| |
| * When you reach ':ref:`Start preparing a kernel build configuration[...] |
| <oldconfig_bissbs>`': before running ``make olddefconfig`` for the first time, |
| execute the following command to base your configuration on the one from the |
| test machine's 'working' kernel:: |
| |
| cp ~/test-machine-config-working ~/linux/.config |
| |
| * During the next step to ':ref:`disable any apparently superfluous kernel |
| modules <localmodconfig_bissbs>`' use the following command instead:: |
| |
| yes '' | make localmodconfig LSMOD=~/lsmod_foo-machine localmodconfig |
| |
| * Continue the guide, but ignore the instructions outlining how to compile, |
| install, and reboot into a kernel every time they come up. Instead build |
| like this:: |
| |
| cp ~/kernel-config-working .config |
| make olddefconfig && |
| make -j $(nproc --all) targz-pkg |
| |
| This will generate a gzipped tar file whose name is printed in the last |
| line shown; for example, a kernel with the kernelrelease identifier |
| '6.0.0-rc1-local-g928a87efa423' built for x86 machines usually will |
| be stored as '~/linux/linux-6.0.0-rc1-local-g928a87efa423-x86.tar.gz'. |
| |
| Copy that file to your test machine's home directory. |
| |
| * Switch to the test machine to check if you have enough space to hold another |
| kernel. Then extract the file you transferred:: |
| |
| sudo tar -xvzf ~/linux-6.0.0-rc1-local-g928a87efa423-x86.tar.gz -C / |
| |
| Afterwards :ref:`generate the initramfs and add the kernel to your boot |
| loader's configuration <install_bisref>`; on some distributions the following |
| command will take care of both these tasks:: |
| |
| sudo /sbin/installkernel 6.0.0-rc1-local-g928a87efa423 /boot/vmlinuz-6.0.0-rc1-local-g928a87efa423 |
| |
| Now reboot and ensure you started the intended kernel. |
| |
| This approach even works when building for another architecture: just install |
| cross-compilers and add the appropriate parameters to every invocation of make |
| (e.g. ``make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- [...]``). |
| |
| Additional reading material |
| --------------------------- |
| |
| * The `man page for 'git bisect' <https://git-scm.com/docs/git-bisect>`_ and |
| `fighting regressions with 'git bisect' <https://git-scm.com/docs/git-bisect-lk2009.html>`_ |
| in the Git documentation. |
| * `Working with git bisect <https://nathanchance.dev/posts/working-with-git-bisect/>`_ |
| from kernel developer Nathan Chancellor. |
| * `Using Git bisect to figure out when brokenness was introduced <http://webchick.net/node/99>`_. |
| * `Fully automated bisecting with 'git bisect run' <https://lwn.net/Articles/317154>`_. |
| |
| .. |
| end-of-content |
| .. |
| This document is maintained by Thorsten Leemhuis <linux@leemhuis.info>. If |
| you spot a typo or small mistake, feel free to let him know directly and |
| he'll fix it. You are free to do the same in a mostly informal way if you |
| want to contribute changes to the text -- but for copyright reasons please CC |
| linux-doc@vger.kernel.org and 'sign-off' your contribution as |
| Documentation/process/submitting-patches.rst explains in the section 'Sign |
| your work - the Developer's Certificate of Origin'. |
| .. |
| This text is available under GPL-2.0+ or CC-BY-4.0, as stated at the top |
| of the file. If you want to distribute this text under CC-BY-4.0 only, |
| please use 'The Linux kernel development community' for author attribution |
| and link this as source: |
| https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/plain/Documentation/admin-guide/verify-bugs-and-bisect-regressions.rst |
| |
| .. |
| Note: Only the content of this RST file as found in the Linux kernel sources |
| is available under CC-BY-4.0, as versions of this text that were processed |
| (for example by the kernel's build system) might contain content taken from |
| files which use a more restrictive license. |