I'm trying to compile a kernel module (which I wrote myself) on a raspberry pi. I am compiling it in the target environment.
I get the following output:
make -C /lib/modules/3.12.23-1.20140626git25673c3.rpfr20.armv6hl.bcm2708/build M=/home/harmic/horus/ppminput modules
make[1]: Entering directory `/usr/src/kernels/3.12.23-1.20140626git25673c3.rpfr20.armv6hl.bcm2708'
CC [M] /home/harmic/horus/ppminput/ppminput.o
Building modules, stage 2.
MODPOST 1 modules
WARNING: "__aeabi_ldivmod" [/home/harmic/horus/ppminput/ppminput.ko] undefined!
CC /home/harmic/horus/ppminput/ppminput.mod.o
LD [M] /home/harmic/horus/ppminput/ppminput.ko
make[1]: Leaving directory `/usr/src/kernels/3.12.23-1.20140626git25673c3.rpfr20.armv6hl.bcm2708'
Sure enough, if I try to insert the module, I get:
insmod: ERROR: could not insert module ./ppminput.ko: Unknown symbol in module
and in syslog:
Sep 2 22:44:26 pidora kernel: [ 7589.354709] ppminput: Unknown symbol __aeabi_ldivmod (err 0)
In my module, I have identified the line causing the problem:
unsigned int chan_abs_val = tdiff / CHAN_SCALE;
(where tdiff is an s64, and CHAN_SCALE is an integer literal).
If I comment the division out, the problem goes away. That is the only line using division in my module.
A bit of googling turned up a few references to this issue, but none I could find in the context of compiling kernel modules.
My makefile looks like this:
obj-m += ppminput.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
Environment Details:
Update
I obviously did not search using the correct terms. Another search has bought up many references, but no solutions as such. Reading them I am getting the opinion that one should not do any 64bit divisions inside the kernel if one wants to compile for ARM?
On most 32-bit CPUs, 64-bit division must be implemented with a slow library function. To prevent the compiler from generating unobviously slow code, Linux does not implement these functions.
If you want to do 64-bit divisions, you have to do them explicitly.
Use do_div()
from <asm/div64.h>
.