- Compile kernel module
- Build environment
- Traditional compilation
- Arch Build System
- Source configuration
- Module compilation
- out-of-tree module compilation
- Module installation
- possible errors
- See also
- How (recipe) to build only one kernel module?
- Setup once
- Each kernel version
- Each edit
- Modprobe error: could not insert
- Notes
Compile kernel module
Sometimes you may wish to compile Linux’s Kernel module without recompiling the whole kernel.
Note: You can only replace existing module if it is compiled as module (M) and not builtin (y) into kernel.
Build environment
Firstly you will need to install build dependencies such as a compiler ( base-devel ) and linux-headers .
Next you will need to get the source code for the kernel version the module is intended to run on. You may try using newer kernel sources but most likely the compiled module will not load.
In case the intended kernel version is the installed kernel, find its version with
There are two main options to acquire the required source. Each option has slightly different usage methods and directory structure.
Traditional compilation
See Kernel/Traditional compilation#Download the kernel source. If you fetch latest source using Git you will need to checkout needed version using tag (eg. v4.1).
Arch Build System
For a general overview on Arch Build System read ABS. See Kernel/Arch Build System for acquiring the kernel source, as well as the directory structure, and other details.
Source configuration
When you have the source code, enter its directory. For the #Arch Build System case, that directory would be src/archlinux-linux/ down from where the PKGBUILD is.
The output from make help is beneficial here. Start by cleaning with
Note: it will delete both .config and .config.old . You might want to save those files some where else before cleaning.
An appropriate .config file is now required. If none is nearby, perhaps from a saved .config , and the intended kernel version is the running kernel, you can use its configuration file:
$ zcat /proc/config.gz > .config
Next ensure the .config file is adjusted for the kernel version. If you are using kernel sources for the exact current version then it should not ask anything. But for another version than the current kernel you might be asked about some options. In any case, for the #Arch Build System option, you might want to examine the PKGBUILD::prepare() function.
If the module you want to compile have some compilation options such as debug build, or it was not compiled before, you can also, possibly must, adjust the kernel configuration. You can do this with one of the many configuration targets mentioned by make help.
Module compilation
In order to compile and load our module cleanly, we must find the value of the EXTRAVERSION component of the current kernel version number so we can match the version number exactly in our kernel source. EXTRAVERSION is a variable set in the kernel top-level Makefile, but the Makefile in a vanilla kernel source will have EXTRAVERSION empty; it is set only as part of the Arch kernel build process. If relevant, the value of the current kernel’s EXTRAVERSION can be found by looking at the output of the uname -r command. In general, the kernel version is the concatenation of three components. Namely, the numeric version, the EXTRAVERSION, and the LOCALVERSION. The numeric version itself is a concatenation of three numbers. If built by a PKGBUILD file, the LOCALVERSION will be taken from the pkgrel variable, prefixed by a hyphen. And the EXTRAVERSION will be the suffix of the pkgver variable, where the period character to the right of the third numeric number of the numeric version is replaced by a hyphen. For example, with the linux package linux 5.5.8.arch1-1 , the LOCALVERSION is -1 . The EXTRAVERSION is -arch1 . The output of uname -r will be 5.5.8-arch1-1 in that example.
Once the EXTRAVERSION value is known, we prepare the source for module compilation:
$ make EXTRAVERSION= modules_prepare
$ make EXTRAVERSION=-arch1 modules_prepare
Alternatively, if you are happy to load modules with modprobe using the —force-vermagic option to ignore mismatches in the kernel version number, you can simply run:
Note: Using the EXTRAVERSION that is recorded in the top level Makefile to avoid manually specifying the EXTRAVERSION on the command line could cause a version mismatch. The kernel build process would recognize that, causing it to append a + character to the LOCALVERSION configuration setting. For example: 5.5.8-arch1-1+ .
Finally, compile wanted module by specifying its directory name. You can find the module location, thus also its directory name, with modinfo or find.
As a last resort, if nothing else has worked, you can
Which will build all the modules from the kernel configuration.
out-of-tree module compilation
get the official source code of the current running linux kernel as described in Kernel/Arch Build System:
$ cd && mkdir build $ pkgctl repo clone linux
then point to the checked out source when compiling the module:
$ cd build/mymod $ make -C ~/build/linux/src/archlinux-linux M=$PWD modules
Module installation
Now after successful compilation you just need to gzip and copy it over for your current kernel.
If you are replacing some existing module you will need to overwrite it (and remember that reinstalling linux will replace it with default module)
$ zstd fs/btrfs/btrfs.ko # cp -f fs/btrfs/btrfs.ko.zst /usr/lib/modules/$(uname -r)/kernel/fs/btrfs/
Or alternatively, you can place the updated module in the updates folder (create it if it does not already exist).
$ cp fs/btrfs/btrfs.ko.zst /usr/lib/modules/$(uname -r)/updates
However if you are adding a new module you can just copy it to extramodules (note, this is just example as btrfs will not get loaded from here)
# cp fs/btrfs/btrfs.ko.zst /usr/lib/modules/$(uname -r)/extramodules/
You need to rebuild the module dependency tree with «depmod» to use installed modules.
If you are compiling a module for early boot (e.g. updated module) which is copied to Initramfs then you must remember to regenerate it with (otherwise your compiled module will not be loaded).
possible errors
If EXTRAVERSION is not set correctly the following errors may occur
# insmod mymod.ko insmod: ERROR: could not insert module mymod.ko: Invalid module format # modprobe mymod modprobe: ERROR: could not insert 'mymod': Exec format error
adding force-vermagic makes it ignore the version mismatch
modprobe mymod --force-vermagic
See also
How (recipe) to build only one kernel module?
The recipe to build a custom module might need to be split in three sections.
Setup once
$ cd ~ $ apt-get source linux-source-3.13.0
I am too lazy to copy the mvsas specific driver source files; just copy them all to your current working directory. If apt-get results in an error message about missing source URIs then see note #4 at the bottom.
$ cd linux-3.13.0 $ make oldconfig $ make prepare $ make scripts
This will prepare some files necessary to build a kernel module.
Each kernel version
$ apt-get install linux-headers-$(uname -r)
This will install headers and the Ubuntu kernel configuration file for that kernel version in /lib/modules.
$ cd ~/linux-3.13.0 $ cp -v /usr/src/linux-headers-$(uname -r)/Module.symvers .
This to prevent the message «no symbol version for module_layout» when loading the module with insmod or modprobe.
$ mv -v /lib/modules/$(uname -r)/kernel/drivers/scsi/mvsas/mvsas.ko /lib/modules/$(uname -r)/kernel/drivers/scsi/mvsas/mvsas.ko.backup
This will rename the original (Ubuntu build) kernel module to make sure that the custom patched one will load.
Each edit
$ cd ~/linux-3.13.0/drivers/scsi/mvsas $ nano mv_sas.h $ nano mv_sas.c
$ make -C /lib/modules/$(uname -r)/build M=$(pwd) modules
This will compile and build the kernel module .ko file using the kernel configuration from your stock Ubuntu distribution as stored in /lib/modules/$(uname -r)/ .
$ make -C /lib/modules/$(uname -r)/build M=$(pwd) modules_install
This will install the kernel module in /lib/modules/$(uname -r)/extra/ , not overwriting the distribution module in case you didn’t rename the distribution kernel module file. In this mvsas case it will also run depmod.
If this results in any output, the mvsas module needs unloading with ( modprobe -r mvsas ) first.
This should load the new kernel module.
Check the output to verify that /lib/modules/. /extra/mvsas.ko is being loaded.
Modprobe error: could not insert
In some cases you might experience a modprobe: ERROR: could not insert ‘xyz’: Unknown symbol in module, or unknown parameter (see dmesg) while in the verbose modprobe output you see that insmod is trying to load the module from the kernel default location. For example:
# insmod /lib/modules/3.17.0-031700rc7-generic/kernel/drivers/scsi/pm8001/pm80xx.ko modprobe: ERROR: could not insert 'pm80xx': Unknown symbol in module, or unknown parameter (see dmesg)
In that case you need to manually run depmod and try to load the module again:
# depmod # sudo modprobe -v mvsas
Notes
- It may be the case that the resulting .ko module files are much (for example 20 times) larger in size than the original module files as distributed by Ubuntu; in that case the make prepare step could have created a Linux developers debugging kernel configuration file and you are building from the source directory. Your -C param might not function as expected.
- I have seen guides with other commands like make modules_prepare and make M=scripts/mod but I don’t think these are necessary for this case.
- You can use the Linux developers debug config by replacing -C /lib/modules/$(uname -r)/build with -C /usr/src/linux-headers-$(uname -r)
- In a default setup, apt-get source linux-sources will return error E: You must put some ‘source’ URIs in your sources.list . To fix this issue you can modify file /etc/apt/sources.list by uncommenting (removing the leading # from) the first deb-src line. Example for Ubuntu 17.10: deb-src http://ie.archive.ubuntu.com/ubuntu/ artful main restricted . run sudo apt-get update , and then the command will deliver sources for you. See also this question where a GUI method for doing this is described too.