Compile kernel module

From ArchWiki
Jump to navigation Jump to search

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 compiler(base-devel) and linux-headers.

Next you will need to get source code for exact kernel version you are running. You may try use newer kernel sources but most likely compiled module will not load.

Find kernel version with

$ uname -r

Then acquire the required source, see Kernels/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).

Source configuration

When you have source code, enter that directory and clean it with (note it will delete .config.old and rename .config to .config.old)

$ make mrproper

Then you need to copy your current existing kernel configuration to this build dir

$ cp /usr/lib/modules/$(uname -r)/build/.config ./
$ cp /usr/lib/modules/$(uname -r)/build/Module.symvers ./

Next ensure configuration is adjusted for kernel sources (if you are using kernel sources for exact current version then it should not ask anything, but for newer sources than current kernel you might be asked about new options).

Also if module you want to compile have some compilation options such as debug build you can also adjust them with any of make config/menuconfig/xconfig (see README)

$ make oldconfig

Module compilation

In order to 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. The value of the current kernel's EXTRAVERSION (usually -1) can be found in one of two ways:

  1. Look at the top of /usr/lib/modules/$(uname -r)/build/Makefile
  2. Run uname -r and look for the string between the third kernel version number and -ARCH (the Arch-specific setting for LOCALVERSION as set in the kernel .config file). For example, with a kernel version of 4.9.65-1-ARCH, the EXTRAVERSION is -1.

Once the EXTRAVERSION value is known, we prepare the source for module compilation:



$ make EXTRAVERSION=-1 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:

$ make modules_prepare
Note: While the Makefile at /usr/lib/modules/$(uname -r)/build/Makefile could be copied over the Makefile in the kernel source to avoid manually specifying the EXTRAVERSION on the command line, that could cause a different kernel version mismatch to occur. If the kernel source has been obtained through a version control tool such as git, simply copying over the Makefile would cause the working copy to be dirty, which the kernel build process would recognize, causing it to append + to the LOCALVERSION configuration setting. For example: 4.9.65-1-ARCH+.

Finally, compile wanted module by specifying its directory. (You can find module location with modinfo or find)

$ make M=fs/btrfs

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
$ asp update linux
$ asp checkout linux

then point to the checked out source when compiling the module:

$ cd build/mymod
$ make -C ~/build/linux/trunk/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)

$ xz fs/btrfs/btrfs.ko
# cp -f fs/btrfs/btrfs.ko.xz /usr/lib/modules/`uname -r`/kernel/fs/btrfs/

Or alternatively, you can place the updated module in the updates folder (create it if it doesn't already exist).

$ cp fs/btrfs/btrfs.ko.xz /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.xz /usr/lib/modules/`uname -r`/extramodules/

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). Furthermore, if you are using the "updates" folder method, you may need to rebuild the module dependency tree with "depmod" before regenerating Initramfs

# mkinitcpio -p linux

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