How linux device drivers are loaded? - linux

Can anyone explain me in simple terms the following thing.
How Linux drivers are loaded into kernel space?
Which functions are exported, after drivers being loaded?
How driver functions are called?

Normally you will use insmod or modprobe userspace application to load module (and possibly its dependencies in case of the 2nd one). Both of them do the same under the hood to actually load single module - they read the file into memory and use init_module system call, providing address of memory where this module was loaded. This call tells kernel that module should be loaded.
Now kernel modules are actually ELF files and are not much different from shared libraries used in userspace. The kernel has an equivalent of shared library linker, that will parse those files, get a list of symbols that are provided by it, updating the list of functions known to kernel. It will also check if all the symbols that this module needs are already in the kernel and do proper relocations. One of the last thing that it will do is to call initialization function in the module.
Note that you cannot compile the kernel that will directly call any function that is provided by module. Similarly, you can call any function provided by a module in another module before loading the first one. Kernel will refuse to load any module with symbols that are not known. Most of the modules will, however, register its functions as some kind of callbacks that can be called indirectly.

Related

How to know which is the current kernel module?

I'm using User Mode Linux and I'm redefining some I/O memory related functions. The idea it's that any function that is called from a list of our own kernel modules will be handled differently from the rest of the modules.
Is that possible to know whichy module is calling (kernel module name would be enough) a function like writel?
Libunwind defines a portable and efficient C programming interface (API) to determine the call-chain of a program (http://savannah.nongnu.org/projects/libunwind).
/proc/modules file displays a list of all modules loaded into the kernel along with their sizes and memory offsets.

Difference between Linux Loadable and built-in modules

What's the difference between loadable modules and built-in (statically linked) modules?
I got this question while finding out an answer for difference between system calls subsys_initcall() and module_init()
Linux kernel supports inserting of modules (aka device drivers) in two ways:
Built-in kernel modules - When the kernel is booted up, the kernel automatically inserts this driver in to the kernel (it's more like it is already part of the kernel code).
Loadable kernel module (LKM) - A driver that is not automatically loaded by the kernel, the user can insert this module at run-time by insmod driver.ko or modprobe driver.ko
The advantage the loadable modules have over the built-in modules is that you can load unload them on run-time. This is good if you are working on a module and you need to test it. Every time you test it and you need to make changes to it, you can easily unload it (rmmod driver.ko or modprobe -r driver.ko) and then after making changes, you can insert it back. But for the built-in modules if you need to make any changes in the module then you need to compile the whole kernel and then reboot the system with the new image of the kernel.
Configuration:
You can configure a module to be either of the two by editing the .config file in the root folder of your kernel source:
DRIVER_1=y // y indicate a builtin module
DRIVER_1=m //m inicates a loadable module
Note: lsmod displays only the dynamically loaded modules not the built-in ones.
Read on: http://www.tldp.org/HOWTO/Module-HOWTO/x73.html

What is the Linux built-in driver load order?

How can we customize the built-in driver load order (to make some built-in driver module load first, and the dependent module load later)?
Built-in drivers wont be loaded, hence built-in. Their initialization functions are called and the drivers are activated when kernel sets up itself. These init functions are called in init/main.c::do_initcalls(). All init calls are classified in levels, which are defined in initcall_levels and include/linux/init.h
These levels are actuall symbols defined in linker script (arch/*/kernel/vmlinux.lds.*). At kernel compile time, the linker collects all function marked module_init() or other *_initcall(), classify in levels, put all functions in the same level together in the same place, and create like an array of function pointers.
What do_initcall_level() does in the run-time is to call each function pointed by the pointers in the array. There is no calling policy, except levels, in do_initcall_level, but the order in the array is decided in the link time.
So, now you can see that the driver's initiation order is fixed at the link time, but what can you do?
put your init function in the higher level, or
put your device driver at the higher position in Makefile
The first one is clear if you've read the above. ie) use early_initcall() instead if it is appropriate.
The second one needs a bit more explanation. The reason why the order in a Makefile matter is how the current kernel build system works and how the linkers works. To make a long story short, the build system takes all object files in obj-y and link them together. It is highly environment dependent but there is high probability that the linker place first object file in the obj-y in lower address, thus, called earlier.
If you just want your driver to be called earlier than other drivers in the same directory, this is simplest way to do it.
depmod examines the symbols exported and required by each module and does a topological sort on them that modprobe can later use to load modules in the proper order. Requiring the symbols from modules you wish to be dependent on is enough for it to do the right thing.
Correct module order and dependencies are handled by modprobe, even within the initrd.
Recently i got this problem my charger driver is having dependency on ADC driver so before loading ADC driver charger driver has loaded and checking for adc phandle which is defined in DTS file and has to intialize by ADC driver. its got resolved by changing the order of the module in drivers/Makefile

How to use systemcalls in linux modules

I attempted to use systemcalls such as sys_sendto when programming a kernel module. But the compiler warned me that the symbol 'sys_sendto' is undefined. I'm sure I have inculded the header file syscalls.h, so please help me and thank you. P.S: My linux version is 2.6.32
For a module to link to a symbol in the kernel like sys_sendto(), it has to be exported by the kernel. Not all system calls are exported. See here
http://www.ibm.com/developerworks/linux/library/l-system-calls/
Here's a whole explanation on writing them and using them. They're not used by direct method calls because they have to be executed in kernel mode. The processor loads the syscall number into a register and then issues a hardware interrupt which the kernel processes and handles to execute your system call.

how to replace a static kernel function without modifying and precomiling linux kernel

all,
I want to know how to replace a kernel static function in a module without modifying linux kernel.
I have known that Linux hook can replace some functions, but the
problem is that I want to replace a static function without modifying linux kernel.
Would you please help me ?
Thank you.
Generally the way the Linux kernel is compiled, replacing / hooking a static function at runtime isn't possible (short of unloading / reloading the entire module if you're talking module code).
That is because the compile inlines static functions much of the time (unless you take the address of it somewhere), and therefore they won't even show up in the symbol table. There's no way after the compile to find out where in the generated binary the static code ended up - not unlikely, you'll find several inlined versions of it in all the call sites invoking the func.
So the basic question: Why does the function have to be static ? What exactly is it you're attempting to do that mandates the use of static ?
If it's actually compiled as a module (not built-in), then just recompile the code, rmmod the module, and insmod the new .ko file. Easy as... some kind of cliche pastry.
In general, you may use some of this techniques:
kprobes/jprobes, that allows you to hook a function with int3
modifying the function's code (for ex., prologue) to jump to your handler and get back, later
If you don't wish to modify the kernel's code at all, you might set up the debugging registers and watch for an access exceptions (in your exception handler, of course). Besides that, you can try to find and invalidate some of the kernel's internal variables so the access to them from the kernel causes the invalid pointer dereference exception. In that case you can handle such an exception and do a back-trace to achive target function.

Resources