|
| 1 | +# Introduction |
| 2 | + |
| 3 | +There are things which are hard to do from regular user programs such as directly talking to hardware. |
| 4 | + |
| 5 | +Some operations can be done via system calls, but if you want flexibility and speed, using the kernel ring is fundamental |
| 6 | + |
| 7 | +However: |
| 8 | + |
| 9 | +- it would be very complicated to recompile the kernel and reboot every time you make some modification |
| 10 | +- the kernel would be huge if it were to support all possible hardware |
| 11 | + |
| 12 | +Modules overcome those two problems exactly because they can be loaded into the kernel *while it is running* and use symbols that the kernel chooses to export TODO which |
| 13 | + |
| 14 | +It then runs in the same address space as the kernel and with the same permissions as the kernel (basically do anything) |
| 15 | + |
| 16 | +Compiled modules are special object files that have a `.ko` extension instead of `.o` they also contain module specific metadata |
| 17 | + |
| 18 | +Device drivers (programs that enables the computer to talk to hardware) are one specific type of kernel modules |
| 19 | + |
| 20 | +Two devices can map to the same hardware! |
| 21 | + |
| 22 | +## Stable kernel interface |
| 23 | + |
| 24 | +Kernel modules can use any internal interface of the kernel, although some are more visible than others. |
| 25 | + |
| 26 | +But there is no stable kernel API for modules: if you don't add your driver to the kernel tree, it can break any time: <https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/stable_api_nonsense.txt?id=v4.0> |
| 27 | + |
| 28 | +## Configuration files |
| 29 | + |
| 30 | +If file it gets read, if dir, all files in dir get read: |
| 31 | + |
| 32 | + sudo ls /etc/modprobe.d |
| 33 | + sudo ls /etc/modprobe.conf |
| 34 | + |
| 35 | +Modules loaded at boot: |
| 36 | + |
| 37 | + sudo cat /etc/modules |
| 38 | + |
| 39 | +## Hardware communication |
| 40 | + |
| 41 | +Talking to hardware always comes down to writing bytes in specific registers at a given memory addresses. |
| 42 | + |
| 43 | +Some processors implement a single address space for memory and other hardware devices, and others do not. |
| 44 | + |
| 45 | +However, since x86 is the most popular and it separates address spaces, every architecture must at least mimic this separation. |
| 46 | + |
| 47 | +On x86, the following specialized instructions exist for port IO: |
| 48 | + |
| 49 | +- `IN`: Read from a port |
| 50 | +- `OUT`: Write to a port |
| 51 | +- `INS/INSB`: Input string from port/Input byte string from port |
| 52 | +- `INS/INSW`: Input string from port/Input word string from port |
| 53 | +- `INS/INSD`: Input string from port/Input `doubleword` string from port |
| 54 | +- `OUTS/OUTSB`: Output string to port/Output byte string to port |
| 55 | +- `OUTS/OUTSW`: Output string to port/Output word string to port |
| 56 | +- `OUTS/OUTSD`: Output string to port/Output `doubleword` string to port |
| 57 | + |
| 58 | +However, you should avoid using those instructions directly in your device driver code since Linux functions abstract over multiple architectures (when possible) making your code more portable. |
| 59 | + |
| 60 | +Those instructions cannot be used from an user space program since the kernel prevents those from accessing hardware directly. |
| 61 | + |
| 62 | +The memory space for non-memory locations is called I/O ports or I/O space. |
| 63 | + |
| 64 | +To use a port, you must first reserve it. To see who reserved what: |
| 65 | + |
| 66 | + sudo cat /proc/ioports |
0 commit comments