Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"__aeabi_ldivmod" undefined when compiling kernel module

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:

  • The Pi is running Pidora 2014 (Fedora 20).
  • The kernel is 3.12.23-1.20140626git25673c3.rpfr20.armv6hl.bcm2708.
  • gcc is 4.8.2.

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?

like image 621
harmic Avatar asked Sep 02 '14 12:09

harmic


1 Answers

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>.

like image 63
CL. Avatar answered Nov 03 '22 04:11

CL.