0

I'm trying to build a simple kernel module for arm64 machine from my x86_64 machine. The target and host are both using ubuntu 20.04 as OS. First I tried building a simple kernel module for the host (x86_64) using this Makefile. By the way, uname -r gives 5.4.0-77-generic in my case.

obj-m += chr_drv_ex1.o

all:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

The program builds and runs ok.

Now I want to try it for arm64 ubuntu 20.04 machine target (I have a virtual machine). One idea is to copy the /lib/modules/5.4.0-77-generic/build directory from the arm64 machine and use the folder as the -C option for my cross-compile. But I soon found that this 'build' directory a symbolic link to /usr/src/linux-headers-5.4.0-77-generic and many files or directories there are also symbolic links to those under /usr/src/linux-headers-5.4.0-77. So I need to copy the /lib/modules/5.4.0-77-generic, /usr/src/linux-headers-5.4.0-77 and /usr/src/linx-headers-5.4.0-77-generic. And this doesn't seem nice.

So my question is: how should I provide the -C option (where build scripts are located) in this case? Can I just install linux-headers-5.4.0-77 and linux-headers-5.4.0-77-generic in my host system and use them? (I tried it but I have this compile error:

make ARCH=arm64 CROSS_COMPILE=aarch64-none-linux-gnu- -C /lib/modules/5.4.0-77-generic/build M=/home/ckim/pprj/qemu_test/test_ldd modules
make[1]: Entering directory '/usr/src/linux-headers-5.4.0-77-generic'
  CC [M]  /home/ckim/pprj/qemu_test/test_ldd/chr_drv_ex1.o
In file included from ./include/linux/types.h:6,
                 from ./include/linux/limits.h:6,
                 from ./include/linux/kernel.h:7,
                 from /home/ckim/pprj/qemu_test/test_ldd/chr_drv_ex1.c:1:
./include/uapi/linux/types.h:5:10: fatal error: asm/types.h: No such file or directory
    5 | #include <asm/types.h>
      |          ^~~~~~~~~~~~~
compilation terminated.
make[2]: *** [scripts/Makefile.build:271: /home/ckim/pprj/qemu_test/test_ldd/chr_drv_ex1.o] Error 1
make[1]: *** [Makefile:1762: /home/ckim/pprj/qemu_test/test_ldd] Error 2
make[1]: Leaving directory '/usr/src/linux-headers-5.4.0-77-generic'
make: *** [Makefile:4: all] Error 2
0andriy
  • 4,183
  • 1
  • 24
  • 37
Chan Kim
  • 5,177
  • 12
  • 57
  • 112
  • 2
    When building a module, `-C` option should point to the **build tree** of the Linux kernel. That kernel should already be **compiled for target platform** (ARM in your case). You cannot build ARM-targeted module with kernel build tree compiled for x86. – Tsyvarev Jul 14 '21 at 06:39
  • I see. I installed linux-source-5.4.0 using apt install, and I see under /usr/src directory, there are debian, debian.master directories and linux-source-5.4.0.tar.bz2. Am I supposed to uncompress the tar.gz2 file and build linux kernel using arm64 defconfig there? – Chan Kim Jul 14 '21 at 07:31
  • @Tsyvarev thanks! I used the build directory and now the problem is gone. (I wrote the answer myself for others' reference.) – Chan Kim Jul 14 '21 at 08:59

1 Answers1

0

@Tsyvarev told me in his comment that I should actually build the kernel and the -C option should point to the kernel build directory. So here is what I did with a little more search. (Thanks @Tsyvarev!)

Suppose you are in the directory where you have your kernel module *.c source program (chr_drv_ex1.c here) and the Makefile, and I have copied /boot/config-5.4.0-77-generic from a virtual machine that I'm making the kernel module for to ./u20_config. To get the .config file for the currently running kernel, see here.

sudo apt install linux-source-5.4.0 (/usr/src/linux-source-5.4.0 is installed)
tar -xf /usr/src/linux-source-5.4.0/linux-source-5.4.0.tar.bz2
cd linux-source-5.4.0
cp ../u20_config .config (u20_config is from ubuntu-20.04 VM)
make ARCH=arm64 CROSS_COMPILE=aarch64-none-linux-gnu- -j`nproc`

cd ..
make (this builds kernel module and app, see Makefile)

And this is the Makefile I used (test_chr_drv is the application using the driver).

export CROSS_COMPILE:=aarch64-none-linux-gnu-
export ARCH:=arm64
obj-m += chr_drv_ex1.o
export KDIR:=linux-source-5.4.0

all: test_chr_drv
    make ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) -C $(KDIR) M=$(PWD) modules

clean:
    make ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) -C $(KDIR) M=$(PWD) clean
    rm -f test_chr_drv

test_chr_drv: test_chr_drv.c
    $(CROSS_COMPILE)gcc $^ -o $@
0andriy
  • 4,183
  • 1
  • 24
  • 37
Chan Kim
  • 5,177
  • 12
  • 57
  • 112