get rid of lkmc package, move userland and kernel-modules to top

Rationale: we already had a non buildroot build system,
maintaining both will be hard, and having short paths is more awesome.
This commit is contained in:
Ciro Santilli 六四事件 法轮功
2018-10-25 00:00:01 +00:00
parent 98d2c83317
commit ca231b82f6
99 changed files with 184 additions and 181 deletions

View File

@@ -123,8 +123,8 @@ which are `printk` messages from `init` and `cleanup` methods of those modules.
Sources: Sources:
* link:packages/lkmc/kernel_modules/hello.c[] * link:kernel_modules/hello.c[]
* link:packages/lkmc/kernel_modules/hello2.c[] * link:kernel_modules/hello2.c[]
Quit QEMU with: Quit QEMU with:
@@ -134,7 +134,7 @@ Ctrl-A X
See also: <<quit-qemu-from-text-mode>>. See also: <<quit-qemu-from-text-mode>>.
All available modules can be found in the link:packages/lkmc/kernel_modules[] directory. All available modules can be found in the link:kernel_modules[] directory.
It is super easy to build for different CPU architectures, just use the `--arch` option: It is super easy to build for different CPU architectures, just use the `--arch` option:
@@ -245,7 +245,7 @@ So you are now officially a Linux kernel hacker, way to go!
===== Your first kernel module hack ===== Your first kernel module hack
Edit link:packages/lkmc/kernel_modules/hello.c[] to contain: Edit link:kernel_modules/hello.c[] to contain:
.... ....
pr_info("hello init hacked\n"); pr_info("hello init hacked\n");
@@ -1124,7 +1124,7 @@ Wait for the boot to end and run:
insmod /timer.ko insmod /timer.ko
.... ....
Source: link:packages/lkmc/kernel_modules/timer.c[]. Source: link:kernel_modules/timer.c[].
This prints a message to dmesg every second. This prints a message to dmesg every second.
@@ -1695,7 +1695,7 @@ We can set and get which cores the Linux kernel allows a program to run on with
./run --cpus 2 --eval-busybox '/sched_getaffinity.out' ./run --cpus 2 --eval-busybox '/sched_getaffinity.out'
.... ....
Source: link:packages/lkmc/userland/sched_getaffinity.c[] Source: link:userland/sched_getaffinity.c[]
Sample output: Sample output:
@@ -2199,9 +2199,9 @@ traps: ring0.out[55] general protection ip:40054c sp:7fffffffec20 error:0 in rin
Sources: Sources:
* link:packages/lkmc/kernel_modules/ring0.c[] * link:kernel_modules/ring0.c[]
* link:packages/lkmc/kernel_modules/ring0.h[] * link:kernel_modules/ring0.h[]
* link:packages/lkmc/userland/ring0.c[] * link:userland/ring0.c[]
In both cases, we attempt to run the exact same code which is shared on the `ring0.h` header file. In both cases, we attempt to run the exact same code which is shared on the `ring0.h` header file.
@@ -2351,7 +2351,7 @@ but why not just use our minimal `/poweroff.out` and be done with it?
./run --eval '/poweroff.out' ./run --eval '/poweroff.out'
.... ....
Source: link:packages/lkmc/userland/poweroff.c[] Source: link:userland/poweroff.c[]
This also illustrates how to shutdown the computer from C: https://stackoverflow.com/questions/28812514/how-to-shutdown-linux-using-c-or-qt-without-call-to-system This also illustrates how to shutdown the computer from C: https://stackoverflow.com/questions/28812514/how-to-shutdown-linux-using-c-or-qt-without-call-to-system
@@ -2363,7 +2363,7 @@ I dare you to guess what this does:
./run --eval '/sleep_forever.out' ./run --eval '/sleep_forever.out'
.... ....
Source: link:packages/lkmc/userland/sleep_forever.c[] Source: link:userland/sleep_forever.c[]
This executable is a convenient simple init that does not panic and sleeps instead. This executable is a convenient simple init that does not panic and sleeps instead.
@@ -2456,7 +2456,7 @@ TERM=linux
asdf=qwer asdf=qwer
.... ....
Source: link:packages/lkmc/userland/init_env_poweroff.c[]. Source: link:userland/init_env_poweroff.c[].
==== init environment args ==== init environment args
@@ -2867,7 +2867,7 @@ If you are feeling fancy, you can also insert modules with:
modprobe hello modprobe hello
.... ....
which insmods link:packages/lkmc/kernel_modules/hello.c[]. which insmods link:kernel_modules/hello.c[].
`modprobe` searches for modules under: `modprobe` searches for modules under:
@@ -2897,8 +2897,8 @@ which teaches you how it is done from C code.
Source: Source:
* link:packages/lkmc/userland/myinsmod.c[] * link:userland/myinsmod.c[]
* link:packages/lkmc/userland/myrmmod.c[] * link:userland/myrmmod.c[]
The Linux kernel offers two system calls for module insertion: The Linux kernel offers two system calls for module insertion:
@@ -4124,7 +4124,7 @@ echo 'module myprintk +p' > /sys/kernel/debug/dynamic_debug/control
insmod /myprintk.ko insmod /myprintk.ko
.... ....
Source: link:packages/lkmc/kernel_modules/myprintk.c[] Source: link:kernel_modules/myprintk.c[]
This outputs the `pr_debug` message: This outputs the `pr_debug` message:
@@ -4215,7 +4215,7 @@ Outcome: the test passes:
Sources: Sources:
* link:packages/lkmc/kernel_modules/params.c[] * link:kernel_modules/params.c[]
* link:rootfs_overlay/params.sh[] * link:rootfs_overlay/params.sh[]
As shown in the example, module parameters can also be read and modified at runtime from <<sysfs>>. As shown in the example, module parameters can also be read and modified at runtime from <<sysfs>>.
@@ -4269,8 +4269,8 @@ Outcome: the test passes:
Sources: Sources:
* link:packages/lkmc/kernel_modules/dep.c[] * link:kernel_modules/dep.c[]
* link:packages/lkmc/kernel_modules/dep2.c[] * link:kernel_modules/dep2.c[]
* link:rootfs_overlay/dep.sh[] * link:rootfs_overlay/dep.sh[]
The kernel deduces dependencies based on the `EXPORT_SYMBOL` that each module uses. The kernel deduces dependencies based on the `EXPORT_SYMBOL` that each module uses.
@@ -4368,7 +4368,7 @@ name = module_info
version = 1.0 version = 1.0
.... ....
Source: link:packages/lkmc/kernel_modules/module_info.c[] Source: link:kernel_modules/module_info.c[]
Some of those are also present on sysfs: Some of those are also present on sysfs:
@@ -4454,7 +4454,7 @@ Possible dmesg output:
VERMAGIC_STRING = 4.17.0 SMP mod_unload modversions VERMAGIC_STRING = 4.17.0 SMP mod_unload modversions
.... ....
Source: link:packages/lkmc/kernel_modules/vermagic.c[] Source: link:kernel_modules/vermagic.c[]
If we artificially create a mismatch with `MODULE_INFO(vermagic`, the insmod fails with: If we artificially create a mismatch with `MODULE_INFO(vermagic`, the insmod fails with:
@@ -4468,7 +4468,7 @@ and `dmesg` says the expected and found vermagic found:
vermagic_fail: version magic 'asdfqwer' should be '4.17.0 SMP mod_unload modversions ' vermagic_fail: version magic 'asdfqwer' should be '4.17.0 SMP mod_unload modversions '
.... ....
Source: link:packages/lkmc/kernel_modules/vermagic_fail.c[] Source: link:kernel_modules/vermagic_fail.c[]
The kernel's vermagic is defined based on compile time configurations at link:https://github.com/torvalds/linux/blob/v4.17/include/linux/vermagic.h#L35[include/linux/vermagic.h]: The kernel's vermagic is defined based on compile time configurations at link:https://github.com/torvalds/linux/blob/v4.17/include/linux/vermagic.h#L35[include/linux/vermagic.h]:
@@ -4516,7 +4516,7 @@ init_module
cleanup_module cleanup_module
.... ....
Source: link:packages/lkmc/kernel_modules/module_init.c[] Source: link:kernel_modules/module_init.c[]
TODO why were `module_init` and `module_exit` created? https://stackoverflow.com/questions/3218320/what-is-the-difference-between-module-init-and-init-module-in-a-linux-kernel-mod TODO why were `module_init` and `module_exit` created? https://stackoverflow.com/questions/3218320/what-is-the-difference-between-module-init-and-init-module-in-a-linux-kernel-mod
@@ -4531,8 +4531,8 @@ insmod /oops.ko
Source: Source:
* link:packages/lkmc/kernel_modules/panic.c[] * link:kernel_modules/panic.c[]
* link:packages/lkmc/kernel_modules/oops.c[] * link:kernel_modules/oops.c[]
A panic can also be generated with: A panic can also be generated with:
@@ -4869,7 +4869,7 @@ The `dump_stack` function produces a stack trace much like panic and oops, but c
insmod /dump_stack.ko insmod /dump_stack.ko
.... ....
Source: link:packages/lkmc/kernel_modules/dump_stack.c[] Source: link:kernel_modules/dump_stack.c[]
==== WARN_ON ==== WARN_ON
@@ -4882,7 +4882,7 @@ echo 1 > /proc/sys/kernel/panic_on_warn
insmod /warn_on.ko insmod /warn_on.ko
.... ....
Source: link:packages/lkmc/kernel_modules/warn_on.c[] Source: link:kernel_modules/warn_on.c[]
Can also be activated with the `panic_on_warn` boot parameter. Can also be activated with the `panic_on_warn` boot parameter.
@@ -4914,7 +4914,7 @@ Outcome: the test passes:
Sources: Sources:
* link:packages/lkmc/kernel_modules/debugfs.c[] * link:kernel_modules/debugfs.c[]
* link:rootfs_overlay/debugfs.sh[] * link:rootfs_overlay/debugfs.sh[]
Debugfs is made specifically to help test kernel stuff. Just mount, set <<file-operations>>, and we are done. Debugfs is made specifically to help test kernel stuff. Just mount, set <<file-operations>>, and we are done.
@@ -4955,7 +4955,7 @@ Procfs can run all system calls, including ones that debugfs can't, e.g. <<mmap>
Sources: Sources:
* link:packages/lkmc/kernel_modules/procfs.c[] * link:kernel_modules/procfs.c[]
* link:rootfs_overlay/procfs.sh[] * link:rootfs_overlay/procfs.sh[]
Bibliography: https://stackoverflow.com/questions/8516021/proc-create-example-for-kernel-module/18924359#18924359 Bibliography: https://stackoverflow.com/questions/8516021/proc-create-example-for-kernel-module/18924359#18924359
@@ -4977,7 +4977,7 @@ Outcome: the test passes:
Sources: Sources:
* link:packages/lkmc/kernel_modules/sysfs.c[] * link:kernel_modules/sysfs.c[]
* link:rootfs_overlay/sysfs.sh[] * link:rootfs_overlay/sysfs.sh[]
Vs procfs: Vs procfs:
@@ -5018,7 +5018,7 @@ Sources:
* link:rootfs_overlay/character_device.sh[] * link:rootfs_overlay/character_device.sh[]
* link:rootfs_overlay/mknoddev.sh[] * link:rootfs_overlay/mknoddev.sh[]
* link:packages/lkmc/kernel_modules/character_device.c[] * link:kernel_modules/character_device.c[]
Unlike <<procfs>> entires, character device files are created with userland `mknod` or `mknodat` syscalls: Unlike <<procfs>> entires, character device files are created with userland `mknod` or `mknodat` syscalls:
@@ -5071,7 +5071,7 @@ Outcome: the test passes:
Sources: Sources:
* link:packages/lkmc/kernel_modules/character_device_create.c[] * link:kernel_modules/character_device_create.c[]
* link:rootfs_overlay/character_device_create.sh[] * link:rootfs_overlay/character_device_create.sh[]
Bibliography: https://stackoverflow.com/questions/5970595/how-to-create-a-device-node-from-the-init-module-code-of-a-linux-kernel-module/45531867#45531867 Bibliography: https://stackoverflow.com/questions/5970595/how-to-create-a-device-node-from-the-init-module-code-of-a-linux-kernel-module/45531867#45531867
@@ -5097,7 +5097,7 @@ Outcome: the test passes:
Sources: Sources:
* link:packages/lkmc/kernel_modules/fops.c[] * link:kernel_modules/fops.c[]
* link:rootfs_overlay/fops.sh[] * link:rootfs_overlay/fops.sh[]
Then give this a try: Then give this a try:
@@ -5127,7 +5127,7 @@ Outcome: the test passes:
Sources: Sources:
* link:packages/lkmc/kernel_modules/seq_file.c[] * link:kernel_modules/seq_file.c[]
* link:rootfs_overlay/seq_file.sh[] * link:rootfs_overlay/seq_file.sh[]
In this example we create a debugfs file that behaves just like a file that contains: In this example we create a debugfs file that behaves just like a file that contains:
@@ -5164,7 +5164,7 @@ Outcome: the test passes:
Sources: Sources:
* link:packages/lkmc/kernel_modules/seq_file_single_open.c[] * link:kernel_modules/seq_file_single_open.c[]
* link:rootfs_overlay/seq_file_single_open.sh[] * link:rootfs_overlay/seq_file_single_open.sh[]
This example produces a debugfs file that behaves like a file that contains: This example produces a debugfs file that behaves like a file that contains:
@@ -5186,8 +5186,8 @@ Outcome: `jiffies` gets printed to stdout every second from userland.
Sources: Sources:
* link:packages/lkmc/kernel_modules/poll.c[] * link:kernel_modules/poll.c[]
* link:packages/lkmc/kernel_modules/poll.c[] * link:kernel_modules/poll.c[]
* link:rootfs_overlay/poll.sh[] * link:rootfs_overlay/poll.sh[]
Typically, we are waiting for some hardware to make some piece of data available available to the kernel. Typically, we are waiting for some hardware to make some piece of data available available to the kernel.
@@ -5215,9 +5215,9 @@ Outcome: the test passes:
Sources: Sources:
* link:packages/lkmc/kernel_modules/ioctl.c[] * link:kernel_modules/ioctl.c[]
* link:packages/lkmc/kernel_modules/ioctl.h[] * link:kernel_modules/ioctl.h[]
* link:packages/lkmc/userland/ioctl.c[] * link:userland/ioctl.c[]
* link:rootfs_overlay/ioctl.sh[] * link:rootfs_overlay/ioctl.sh[]
`ioctl` is one of the most important methods of communication with real device drivers, which often take several fields as input. `ioctl` is one of the most important methods of communication with real device drivers, which often take several fields as input.
@@ -5264,8 +5264,8 @@ Outcome: the test passes:
Sources: Sources:
* link:packages/lkmc/kernel_modules/mmap.c[] * link:kernel_modules/mmap.c[]
* link:packages/lkmc/userland/mmap.c[] * link:userland/mmap.c[]
* link:rootfs_overlay/mmap.sh[] * link:rootfs_overlay/mmap.sh[]
In this example, we make a tiny 4 byte kernel buffer available to user-space, and we then modify it on userspace, and check that the kernel can see the modification. In this example, we make a tiny 4 byte kernel buffer available to user-space, and we then modify it on userspace, and check that the kernel can see the modification.
@@ -5300,9 +5300,9 @@ Outcome: the test passes:
Sources: Sources:
* link:packages/lkmc/kernel_modules/anonymous_inode.c[] * link:kernel_modules/anonymous_inode.c[]
* link:packages/lkmc/kernel_modules/anonymous_inode.h[] * link:kernel_modules/anonymous_inode.h[]
* link:packages/lkmc/userland/anonymous_inode.c[] * link:userland/anonymous_inode.c[]
* link:rootfs_overlay/anonymous_inode.sh[] * link:rootfs_overlay/anonymous_inode.sh[]
This example gets an anonymous inode via <<ioctl>> from a debugfs entry by using `anon_inode_getfd`. This example gets an anonymous inode via <<ioctl>> from a debugfs entry by using `anon_inode_getfd`.
@@ -5328,9 +5328,9 @@ Outcome: the test passes:
Sources: Sources:
* link:packages/lkmc/kernel_modules/netlink.c[] * link:kernel_modules/netlink.c[]
* link:packages/lkmc/kernel_modules/netlink.h[] * link:kernel_modules/netlink.h[]
* link:packages/lkmc/userland/netlink.c[] * link:userland/netlink.c[]
* link:rootfs_overlay/netlink.sh[] * link:rootfs_overlay/netlink.sh[]
Launch multiple user requests in parallel to stress our socket: Launch multiple user requests in parallel to stress our socket:
@@ -5355,7 +5355,7 @@ Kernel threads are managed exactly like userland threads; they also have a backi
insmod /kthread.ko insmod /kthread.ko
.... ....
Source: link:packages/lkmc/kernel_modules/kthread.c[] Source: link:kernel_modules/kthread.c[]
Outcome: dmesg counts from `0` to `9` once every second infinitely many times: Outcome: dmesg counts from `0` to `9` once every second infinitely many times:
@@ -5393,7 +5393,7 @@ Let's launch two threads and see if they actually run in parallel:
insmod /kthreads.ko insmod /kthreads.ko
.... ....
Source: link:packages/lkmc/kernel_modules/kthreads.c[] Source: link:kernel_modules/kthreads.c[]
Outcome: two threads count to dmesg from `0` to `9` in parallel. Outcome: two threads count to dmesg from `0` to `9` in parallel.
@@ -5427,7 +5427,7 @@ Count to dmesg every one second from `0` up to `n - 1`:
insmod /sleep.ko n=5 insmod /sleep.ko n=5
.... ....
Source: link:packages/lkmc/kernel_modules/sleep.c[] Source: link:kernel_modules/sleep.c[]
The sleep is done with a call to link:https://github.com/torvalds/linux/blob/v4.17/kernel/time/timer.c#L1984[`usleep_range`] directly inside `module_init` for simplicity. The sleep is done with a call to link:https://github.com/torvalds/linux/blob/v4.17/kernel/time/timer.c#L1984[`usleep_range`] directly inside `module_init` for simplicity.
@@ -5452,7 +5452,7 @@ Stop counting:
rmmod workqueue_cheat rmmod workqueue_cheat
.... ....
Source: link:packages/lkmc/kernel_modules/workqueue_cheat.c[] Source: link:kernel_modules/workqueue_cheat.c[]
The workqueue thread is killed after the worker function returns. The workqueue thread is killed after the worker function returns.
@@ -5476,7 +5476,7 @@ rmmod work_from_work
The sleep is done indirectly through: link:https://github.com/torvalds/linux/blob/v4.17/include/linux/workqueue.h#L522[`queue_delayed_work`], which waits the specified time before scheduling the work. The sleep is done indirectly through: link:https://github.com/torvalds/linux/blob/v4.17/include/linux/workqueue.h#L522[`queue_delayed_work`], which waits the specified time before scheduling the work.
Source: link:packages/lkmc/kernel_modules/work_from_work.c[] Source: link:kernel_modules/work_from_work.c[]
==== schedule ==== schedule
@@ -5488,7 +5488,7 @@ Let's block the entire kernel! Yay:
Outcome: the system hangs, the only way out is to kill the VM. Outcome: the system hangs, the only way out is to kill the VM.
Source: link:packages/lkmc/kernel_modules/schedule.c[] Source: link:kernel_modules/schedule.c[]
kthreads only allow interrupting if you call `schedule()`, and the `schedule=0` <<kernel-module-parameters,kernel module parameter>> turns it off. kthreads only allow interrupting if you call `schedule()`, and the `schedule=0` <<kernel-module-parameters,kernel module parameter>> turns it off.
@@ -5544,7 +5544,7 @@ Stop the count:
rmmod wait_queue rmmod wait_queue
.... ....
Source: link:packages/lkmc/kernel_modules/wait_queue.c[] Source: link:kernel_modules/wait_queue.c[]
This example launches three threads: This example launches three threads:
@@ -5572,7 +5572,7 @@ Stop counting:
rmmod timer rmmod timer
.... ....
Source: link:packages/lkmc/kernel_modules/timer.c[] Source: link:kernel_modules/timer.c[]
Timers are callbacks that run when an interrupt happens, from the interrupt context itself. Timers are callbacks that run when an interrupt happens, from the interrupt context itself.
@@ -5593,7 +5593,7 @@ Brute force monitor every shared interrupt that will accept us:
./run --eval-busybox 'insmod /irq.ko' --graphic ./run --eval-busybox 'insmod /irq.ko' --graphic
.... ....
Source: link:packages/lkmc/kernel_modules/irq.c[]. Source: link:kernel_modules/irq.c[].
Now try the following: Now try the following:
@@ -5737,7 +5737,7 @@ Outcome: the test passes:
Sources: Sources:
* link:packages/lkmc/kernel_modules/kstrto.c[] * link:kernel_modules/kstrto.c[]
* link:rootfs_overlay/kstrto.sh[] * link:rootfs_overlay/kstrto.sh[]
Bibliography: https://stackoverflow.com/questions/6139493/how-convert-char-to-int-in-linux-kernel/49811658#49811658 Bibliography: https://stackoverflow.com/questions/6139493/how-convert-char-to-int-in-linux-kernel/49811658#49811658
@@ -5751,7 +5751,7 @@ insmod /virt_to_phys.ko
cat /sys/kernel/debug/lkmc_virt_to_phys cat /sys/kernel/debug/lkmc_virt_to_phys
.... ....
Source: link:packages/lkmc/kernel_modules/virt_to_phys.c[] Source: link:kernel_modules/virt_to_phys.c[]
Sample output: Sample output:
@@ -5808,7 +5808,7 @@ First get a virtual address to play with:
/virt_to_phys_test.out & /virt_to_phys_test.out &
.... ....
Source: link:packages/lkmc/userland/virt_to_phys_test.c[] Source: link:userland/virt_to_phys_test.c[]
Sample output: Sample output:
@@ -5835,7 +5835,7 @@ Sample output physical address:
0x7c7b800 0x7c7b800
.... ....
Source: link:packages/lkmc/userland/virt_to_phys_user.c[] Source: link:userland/virt_to_phys_user.c[]
Now we can verify that `virt_to_phys_user.out` gave the correct physical address in the following ways: Now we can verify that `virt_to_phys_user.out` gave the correct physical address in the following ways:
@@ -5952,7 +5952,7 @@ vaddr pfn soft-dirty file/shared swapped present library
7ffff78ec000 1fd4 0 1 0 1 /lib/libuClibc-1.0.30.so 7ffff78ec000 1fd4 0 1 0 1 /lib/libuClibc-1.0.30.so
.... ....
Source: link:packages/lkmc/userland/pagemap_dump.c[] Source: link:userland/pagemap_dump.c[]
Adapted from: https://github.com/dwks/pagemap/blob/8a25747bc79d6080c8b94eac80807a4dceeda57a/pagemap2.c Adapted from: https://github.com/dwks/pagemap/blob/8a25747bc79d6080c8b94eac80807a4dceeda57a/pagemap2.c
@@ -6028,7 +6028,7 @@ I hope to have examples of all methods some day, since I'm obsessed with visibil
==== CONFIG_PROC_EVENTS ==== CONFIG_PROC_EVENTS
Logs proc events such as process creation to a link:packages/lkmc/kernel_modules/netlink.c[netlink socket]. Logs proc events such as process creation to a link:kernel_modules/netlink.c[netlink socket].
We then have a userland program that listens to the events and prints them out: We then have a userland program that listens to the events and prints them out:
@@ -6047,7 +6047,7 @@ a
# #
.... ....
Source: link:packages/lkmc/userland/proc_events.c[] Source: link:userland/proc_events.c[]
TODO: why `exit: tid=79` shows after `exit: tid=80`? TODO: why `exit: tid=79` shows after `exit: tid=80`?
@@ -6255,7 +6255,7 @@ Outcome: dmesg outputs on every fork:
<_do_fork> post_handler: p->addr = 0x00000000e1360063, flags = 0x246 <_do_fork> post_handler: p->addr = 0x00000000e1360063, flags = 0x246
.... ....
Source: link:packages/lkmc/kernel_modules/kprobe_example.c[] Source: link:kernel_modules/kprobe_example.c[]
TODO: it does not work if I try to immediately launch `sleep`, why? TODO: it does not work if I try to immediately launch `sleep`, why?
@@ -6420,7 +6420,7 @@ TODO not always reproducible. Find a more reproducible failure. I could not obse
insmod /memcpy_overflow.ko insmod /memcpy_overflow.ko
.... ....
Source: link:packages/lkmc/kernel_modules/strlen_overflow.c[] Source: link:kernel_modules/strlen_overflow.c[]
Bibliography: https://www.reddit.com/r/hacking/comments/8h4qxk/what_a_buffer_overflow_in_the_linux_kernel_looks/ Bibliography: https://www.reddit.com/r/hacking/comments/8h4qxk/what_a_buffer_overflow_in_the_linux_kernel_looks/
@@ -6462,7 +6462,7 @@ UIO interface in a nutshell:
Sources: Sources:
* link:packages/lkmc/userland/uio_read.c[] * link:userland/uio_read.c[]
* link:rootfs_overlay/uio_read.sh[] * link:rootfs_overlay/uio_read.sh[]
Bibliography: Bibliography:
@@ -6593,7 +6593,7 @@ Minimal example:
./run --kernel-cli 'init=/ctrl_alt_del.out' --graphic ./run --kernel-cli 'init=/ctrl_alt_del.out' --graphic
.... ....
Source: link:packages/lkmc/userland/ctrl_alt_del.c[] Source: link:userland/ctrl_alt_del.c[]
When you hit `Ctrl-Alt-Del` in the guest, our tiny init handles a `SIGINT` sent by the kernel and outputs to stdout: When you hit `Ctrl-Alt-Del` in the guest, our tiny init handles a `SIGINT` sent by the kernel and outputs to stdout:
@@ -6910,7 +6910,7 @@ DRM / DRI is the new interface that supersedes `fbdev`:
./run --eval-busybox '/libdrm_modeset.out' --graphic ./run --eval-busybox '/libdrm_modeset.out' --graphic
.... ....
Source: link:packages/lkmc/userland/libdrm_modeset.c[] Source: link:userland/libdrm_modeset.c[]
Outcome: for a few seconds, the screen that contains the terminal gets taken over by changing colors of the rainbow. Outcome: for a few seconds, the screen that contains the terminal gets taken over by changing colors of the rainbow.
@@ -7316,7 +7316,7 @@ insmod /pci_min.ko
Sources: Sources:
* Kernel module: link:packages/lkmc/kernel_modules/pci_min.c[]. * Kernel module: link:kernel_modules/pci_min.c[].
* QEMU device: https://github.com/cirosantilli/qemu/blob/lkmc/hw/misc/lkmc_pci_min.c * QEMU device: https://github.com/cirosantilli/qemu/blob/lkmc/hw/misc/lkmc_pci_min.c
Outcome: Outcome:
@@ -7355,7 +7355,7 @@ This tests a lot of features of the edu device, to understand the results, compa
Sources: Sources:
* kernel module: link:packages/lkmc/kernel_modules/qemu_edu.c[] * kernel module: link:kernel_modules/qemu_edu.c[]
* QEMU device: https://github.com/qemu/qemu/blob/v2.12.0/hw/misc/edu.c * QEMU device: https://github.com/qemu/qemu/blob/v2.12.0/hw/misc/edu.c
* test script: link:rootfs_overlay/qemu_edu.sh[] * test script: link:rootfs_overlay/qemu_edu.sh[]
@@ -8684,7 +8684,7 @@ and then feed `bst_vs_heap.dat` into: https://github.com/cirosantilli/cpp-cheat/
Sources: Sources:
* link:bst-vs-heap[] * link:bst-vs-heap[]
* link:packages/lkmc/userland/bst_vs_heap.cpp[] * link:userland/bst_vs_heap.cpp[]
===== OpenMP ===== OpenMP
@@ -8694,7 +8694,7 @@ Implemented by GCC itself, so just a toolchain configuration, no external libs,
/openmp.out /openmp.out
.... ....
Source: link:packages/lkmc/userland/openmp.c[] Source: link:userland/openmp.c[]
===== BLAS ===== BLAS
@@ -8712,7 +8712,7 @@ Outcome: the test passes:
0 0
.... ....
Source: link:packages/lkmc/userland/openblas.c[] Source: link:userland/openblas.c[]
The test performs a general matrix multiplication: The test performs a general matrix multiplication:
@@ -8758,7 +8758,7 @@ Output:
2.5 1.5 2.5 1.5
.... ....
Source: link:packages/lkmc/userland/eigen_hello.cpp[] Source: link:userland/eigen_hello.cpp[]
This example just creates a matrix and prints it out. This example just creates a matrix and prints it out.
@@ -9443,8 +9443,8 @@ The executable `/m5ops.out` illustrates how to hard code with inline assembly th
Sources: Sources:
* link:packages/lkmc/userland/m5ops.h[] * link:userland/m5ops.h[]
* link:packages/lkmc/userland/m5ops.c[] * link:userland/m5ops.c[]
That executable is of course a subset of <<m5>> and useless by itself: its goal is only illustrate how to hardcode some <<m5ops>> yourself as one-liners. That executable is of course a subset of <<m5>> and useless by itself: its goal is only illustrate how to hardcode some <<m5ops>> yourself as one-liners.
@@ -9592,7 +9592,7 @@ Let's have some fun and try to correlate the gem5 cycle count `system.cpu.numCyc
./gem5-stat ./gem5-stat
.... ....
Source: link:packages/lkmc/userland/rdtsc.c[] Source: link:userland/rdtsc.c[]
`rdtsc` outputs a cycle count which we compare with gem5's `gem5-stat`: `rdtsc` outputs a cycle count which we compare with gem5's `gem5-stat`:
@@ -9610,7 +9610,7 @@ Bibliography:
===== pmccntr ===== pmccntr
TODO We didn't manage to find a working ARM analogue to <<rdtsc>>: link:packages/lkmc/kernel_modules/pmccntr.c[] is oopsing, and even it if weren't, it likely won't give the cycle count since boot since it needs to be activate before it starts counting anything: TODO We didn't manage to find a working ARM analogue to <<rdtsc>>: link:kernel_modules/pmccntr.c[] is oopsing, and even it if weren't, it likely won't give the cycle count since boot since it needs to be activate before it starts counting anything:
* https://stackoverflow.com/questions/40454157/is-there-an-equivalent-instruction-to-rdtsc-in-arm * https://stackoverflow.com/questions/40454157/is-there-an-equivalent-instruction-to-rdtsc-in-arm
* https://stackoverflow.com/questions/31620375/arm-cortex-a7-returning-pmccntr-0-in-kernel-mode-and-illegal-instruction-in-u/31649809#31649809 * https://stackoverflow.com/questions/31620375/arm-cortex-a7-returning-pmccntr-0-in-kernel-mode-and-illegal-instruction-in-u/31649809#31649809
@@ -9798,7 +9798,7 @@ You will likely want to change that to:
BR2_OPTIMIZE_3=y BR2_OPTIMIZE_3=y
.... ....
Our link:packages/lkmc/kernel_modules/user[] package correctly forwards the Buildroot options to the build with `$(TARGET_CONFIGURE_OPTS)`, so you don't have to do any extra work. Our link:kernel_modules/user[] package correctly forwards the Buildroot options to the build with `$(TARGET_CONFIGURE_OPTS)`, so you don't have to do any extra work.
Don't forget to do that if you are <<add-new-buildroot-packages,adding a new package>> with your own build system. Don't forget to do that if you are <<add-new-buildroot-packages,adding a new package>> with your own build system.
@@ -9894,7 +9894,7 @@ with:
First, see if you can't get away without actually adding a new package, for example: First, see if you can't get away without actually adding a new package, for example:
* if you have a standalone C file with no dependencies besides the C standard library to be compiled with GCC, just add a new file under link:packages/lkmc/kernel_modules/user[] and you are done * if you have a standalone C file with no dependencies besides the C standard library to be compiled with GCC, just add a new file under link:kernel_modules/user[] and you are done
* if you have a dependency on a library, first check if Buildroot doesn't have a package for it already with `ls buildroot/package`. If yes, just enable that package as explained at: <<custom-buildroot-configs>> * if you have a dependency on a library, first check if Buildroot doesn't have a package for it already with `ls buildroot/package`. If yes, just enable that package as explained at: <<custom-buildroot-configs>>
If none of those methods are flexible enough for you, you can just fork or hack up link:packages/sample_package[] the sample package to do what you want. If none of those methods are flexible enough for you, you can just fork or hack up link:packages/sample_package[] the sample package to do what you want.
@@ -11084,6 +11084,12 @@ There is also the `m5` tool that we must build through Buildroot ans install on
This directory has the following structure: This directory has the following structure:
==== include directory
link:include/[] contains headers that are shared acros both kernel modules and userland structures.
They contain data structs and magic constant for kernel to userland communication.
==== packages directory ==== packages directory
Every directory inside it is a Buildroot package. Every directory inside it is a Buildroot package.
@@ -11137,7 +11143,7 @@ We use it for:
* customized configuration files * customized configuration files
* userland module test scripts that don't need to be compiled. * userland module test scripts that don't need to be compiled.
+ +
C files for example need compilation, and must go through the regular package system, e.g. through link:packages/lkmc/kernel_modules/user[]. C files for example need compilation, and must go through the regular package system, e.g. through link:kernel_modules/user[].
=== Test this repo === Test this repo
@@ -11281,8 +11287,8 @@ hello cpp
Sources: Sources:
* link:packages/lkmc/userland/hello.c[] * link:userland/hello.c[]
* link:packages/lkmc/userland/hello_cpp.c[] * link:userland/hello_cpp.c[]
==== rand_check.out ==== rand_check.out
@@ -11292,7 +11298,7 @@ Print out several parameters that normally change randomly from boot to boot:
./run --eval-busybox '/rand_check.out;/poweroff.out' ./run --eval-busybox '/rand_check.out;/poweroff.out'
.... ....
Source: link:packages/lkmc/userland/rand_check.c[] Source: link:userland/rand_check.c[]
This can be used to check the determinism of: This can be used to check the determinism of:

View File

@@ -41,8 +41,13 @@ class ModulesComponent(common.Component):
# This copies only modified files as per: # This copies only modified files as per:
# https://stackoverflow.com/questions/5718899/building-an-out-of-tree-linux-kernel-module-in-a-separate-object-directory # https://stackoverflow.com/questions/5718899/building-an-out-of-tree-linux-kernel-module-in-a-separate-object-directory
distutils.dir_util.copy_tree( distutils.dir_util.copy_tree(
common.lkmc_package_src_dir, common.kernel_modules_src_dir,
os.path.join(build_dir), os.path.join(build_dir, common.kernel_modules_subdir),
update=1,
)
distutils.dir_util.copy_tree(
common.include_src_dir,
os.path.join(build_dir, common.include_subdir),
update=1, update=1,
) )
all_kernel_modules = [] all_kernel_modules = []

73
build-overlay Normal file
View File

@@ -0,0 +1,73 @@
#!/usr/bin/env python3
import os
import platform
import shutil
import subprocess
import common
class UserlandComponent(common.Component):
def add_parser_arguments(self, parser):
parser.add_argument(
'--has-package',
action='append',
default=[],
help='''\
Indicate that a given package is present in the root filesystem, which
allows us to build examples that rely on it.
''',
)
parser.add_argument(
'targets',
default=[],
help='''\
Build only the given userland programs.
Default: build all examples that have their package dependencies met.
For example, an OpenBLAS example can only be built if the target root filesystem
has the OpenBLAS libraries and headers installed.
''',
metavar='programs',
nargs='*',
)
def do_build(self, args):
build_dir = self.get_build_dir(args)
os.makedirs(build_dir, exist_ok=True)
allowed_toolchains = ['buildroot']
cc = common.get_toolchain_tool('gcc', allowed_toolchains=allowed_toolchains)
cxx = common.get_toolchain_tool('g++', allowed_toolchains=allowed_toolchains)
common.run_cmd(
(
[
'make',
'-j', str(args.nproc),
'CC={}'.format(cc),
'CXX={}'.format(cxx),
'PKG_CONFIG={}'.format(common.buildroot_pkg_config),
'STAGING_DIR={}'.format(common.buildroot_staging_dir),
'OUT_DIR={}'.format(build_dir),
] +
['HAS_{}=y'.format(package.upper()) for package in args.has_package] +
[os.path.join(build_dir, os.path.splitext(os.path.split(target)[1])[0]) + common.executable_ext for target in args.targets]
),
cwd=common.userland_src_dir,
extra_paths=[common.ccache_dir],
)
common.copy_dir_if_update_non_recursive(
srcdir=build_dir,
destdir=common.out_rootfs_overlay_dir,
filter_ext=common.executable_ext,
)
def get_argparse_args(self):
return {
'description': 'Build our compiled userland examples',
}
def get_build_dir(self, args):
return common.userland_build_dir
if __name__ == '__main__':
UserlandComponent().build()

View File

@@ -32,9 +32,11 @@ bench_boot = os.path.join(out_dir, 'bench-boot.txt')
packages_dir = os.path.join(root_dir, 'packages') packages_dir = os.path.join(root_dir, 'packages')
lkmc_package_src_dir = os.path.join(this_module.packages_dir, 'lkmc') lkmc_package_src_dir = os.path.join(this_module.packages_dir, 'lkmc')
kernel_modules_subdir = 'kernel_modules' kernel_modules_subdir = 'kernel_modules'
kernel_modules_src_dir = os.path.join(this_module.lkmc_package_src_dir, this_module.kernel_modules_subdir) kernel_modules_src_dir = os.path.join(this_module.root_dir, this_module.kernel_modules_subdir)
userland_subdir = 'userland' userland_subdir = 'userland'
userland_src_dir = os.path.join(this_module.lkmc_package_src_dir, this_module.userland_subdir) userland_src_dir = os.path.join(this_module.root_dir, this_module.userland_subdir)
include_subdir = 'include'
include_src_dir = os.path.join(this_module.root_dir, this_module.include_subdir)
submodules_dir = os.path.join(root_dir, 'submodules') submodules_dir = os.path.join(root_dir, 'submodules')
buildroot_src_dir = os.path.join(submodules_dir, 'buildroot') buildroot_src_dir = os.path.join(submodules_dir, 'buildroot')
crosstool_ng_src_dir = os.path.join(submodules_dir, 'crosstool-ng') crosstool_ng_src_dir = os.path.join(submodules_dir, 'crosstool-ng')

1
include/README.adoc Normal file
View File

@@ -0,0 +1 @@
https://github.com/cirosantilli/linux-kernel-module-cheat#include-directory

View File

@@ -9,7 +9,7 @@
#include <linux/printk.h> /* printk */ #include <linux/printk.h> /* printk */
#include <linux/uaccess.h> /* copy_from_user */ #include <linux/uaccess.h> /* copy_from_user */
#include "../anonymous_inode.h" #include "../include/anonymous_inode.h"
static struct dentry *debugfs_file; static struct dentry *debugfs_file;
static u32 myval = 1; static u32 myval = 1;

View File

@@ -5,7 +5,7 @@
#include <linux/printk.h> /* printk */ #include <linux/printk.h> /* printk */
#include <linux/uaccess.h> /* copy_from_user, copy_to_user */ #include <linux/uaccess.h> /* copy_from_user, copy_to_user */
#include "../ioctl.h" #include "../include/ioctl.h"
static struct dentry *debugfs_file; static struct dentry *debugfs_file;

View File

@@ -6,7 +6,7 @@
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <net/sock.h> #include <net/sock.h>
#include "../netlink.h" #include "../include/netlink.h"
struct sock *nl_sk = NULL; struct sock *nl_sk = NULL;

View File

@@ -3,7 +3,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include "../ring0.h" #include "../include/ring0.h"
static int myinit(void) static int myinit(void)
{ {

View File

@@ -1 +0,0 @@
/system

View File

@@ -1,7 +0,0 @@
config BR2_PACKAGE_GEM5
bool "gem5"
help
Only for the m5 guest instrumentation tool of the gem5 system simulator,
does not build the simulator itself.
http://gem5.org

View File

@@ -1 +0,0 @@
https://github.com/cirosantilli/linux-kernel-module-cheat#gem5-directory

View File

@@ -1 +0,0 @@
name: GEM5

View File

@@ -1,27 +0,0 @@
################################################################################
#
# GEM5
#
################################################################################
GEM5_VERSION = 1.0
GEM5_SITE = $(LKMC_GEM5_SRCDIR)
GEM5_SITE_METHOD = local
ifeq ($(ARCH),x86_64)
ARCH_MAKE = x86
else
ARCH_MAKE = $(ARCH)
endif
define GEM5_BUILD_CMDS
# TODO cannot use TARGET_CONFIGURE_OPTS here because it overrides the CFLAGS on m5,
# which have an include. We should patch gem5 to add a += instead of = there.
cd '$(@D)/util/m5' && $(MAKE) -f 'Makefile.$(ARCH_MAKE)' CC='$(TARGET_CC)' LD='$(TARGET_LD)'
endef
define GEM5_INSTALL_TARGET_CMDS
$(INSTALL) -D -m 0755 '$(@D)/util/m5/m5' '$(TARGET_DIR)/usr/bin'
endef
$(eval $(generic-package))

View File

@@ -1,5 +0,0 @@
config BR2_PACKAGE_LKMC
bool "lkmc"
depends on BR2_LINUX_KERNEL
help
Linux Kernel Module Cheat kernel modules and compiled userland examples.

View File

@@ -1 +0,0 @@
https://github.com/cirosantilli/linux-kernel-module-cheat#directory-structure

View File

@@ -1 +0,0 @@
name: LKMC

View File

@@ -1,40 +0,0 @@
################################################################################
#
# kernel_modules
#
################################################################################
LKMC_VERSION = 1.0
LKMC_SITE = $(BR2_EXTERNAL_LKMC_PATH)
LKMC_SITE_METHOD = local
LKMC_MODULE_SUBDIRS = kernel_modules
ifeq ($(BR2_PACKAGE_EIGEN),y)
LKMC_DEPENDENCIES += eigen
endif
ifeq ($(BR2_PACKAGE_LIBDRM),y)
LKMC_DEPENDENCIES += libdrm
endif
ifeq ($(BR2_PACKAGE_OPENBLAS),y)
LKMC_DEPENDENCIES += openblas
endif
define LKMC_BUILD_CMDS
$(MAKE) -C '$(@D)/userland' $(TARGET_CONFIGURE_OPTS) \
HAS_EIGEN="$(BR2_PACKAGE_EIGEN)" \
HAS_LIBDRM="$(BR2_PACKAGE_LIBDRM)" \
HAS_OPENBLAS="$(BR2_PACKAGE_OPENBLAS)" \
;
endef
define LKMC_INSTALL_TARGET_CMDS
# The modules are already installed by the kernel-module package type
# under /lib/modules/**, but let's also copy the modules to the root
# for insmod convenience.
#
# Modules can be still be easily inserted with "modprobe module" however.
$(INSTALL) -D -m 0755 $(@D)/userland/*.out '$(TARGET_DIR)'
endef
$(eval $(kernel-module))
$(eval $(generic-package))

View File

@@ -10,7 +10,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> /* sleep */ #include <unistd.h> /* sleep */
#include "../anonymous_inode.h" #include "../include/anonymous_inode.h"
int main(int argc, char **argv) int main(int argc, char **argv)
{ {

View File

@@ -10,7 +10,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#include "../ioctl.h" #include "../include/ioctl.h"
int main(int argc, char **argv) int main(int argc, char **argv)
{ {

View File

@@ -7,7 +7,7 @@
#include <sys/socket.h> #include <sys/socket.h>
#include <unistd.h> #include <unistd.h>
#include "../netlink.h" #include "../include/netlink.h"
#define MAX_PAYLOAD 1024 #define MAX_PAYLOAD 1024

View File

@@ -3,7 +3,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include "../ring0.h" #include "../include/ring0.h"
int main(void) { int main(void) {
#if defined(__x86_64__) || defined(__i386__) #if defined(__x86_64__) || defined(__i386__)