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:
* link:packages/lkmc/kernel_modules/hello.c[]
* link:packages/lkmc/kernel_modules/hello2.c[]
* link:kernel_modules/hello.c[]
* link:kernel_modules/hello2.c[]
Quit QEMU with:
@@ -134,7 +134,7 @@ Ctrl-A X
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:
@@ -245,7 +245,7 @@ So you are now officially a Linux kernel hacker, way to go!
===== 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");
@@ -1124,7 +1124,7 @@ Wait for the boot to end and run:
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.
@@ -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'
....
Source: link:packages/lkmc/userland/sched_getaffinity.c[]
Source: link:userland/sched_getaffinity.c[]
Sample output:
@@ -2199,9 +2199,9 @@ traps: ring0.out[55] general protection ip:40054c sp:7fffffffec20 error:0 in rin
Sources:
* link:packages/lkmc/kernel_modules/ring0.c[]
* link:packages/lkmc/kernel_modules/ring0.h[]
* link:packages/lkmc/userland/ring0.c[]
* link:kernel_modules/ring0.c[]
* link:kernel_modules/ring0.h[]
* link:userland/ring0.c[]
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'
....
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
@@ -2363,7 +2363,7 @@ I dare you to guess what this does:
./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.
@@ -2456,7 +2456,7 @@ TERM=linux
asdf=qwer
....
Source: link:packages/lkmc/userland/init_env_poweroff.c[].
Source: link:userland/init_env_poweroff.c[].
==== init environment args
@@ -2867,7 +2867,7 @@ If you are feeling fancy, you can also insert modules with:
modprobe hello
....
which insmods link:packages/lkmc/kernel_modules/hello.c[].
which insmods link:kernel_modules/hello.c[].
`modprobe` searches for modules under:
@@ -2897,8 +2897,8 @@ which teaches you how it is done from C code.
Source:
* link:packages/lkmc/userland/myinsmod.c[]
* link:packages/lkmc/userland/myrmmod.c[]
* link:userland/myinsmod.c[]
* link:userland/myrmmod.c[]
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
....
Source: link:packages/lkmc/kernel_modules/myprintk.c[]
Source: link:kernel_modules/myprintk.c[]
This outputs the `pr_debug` message:
@@ -4215,7 +4215,7 @@ Outcome: the test passes:
Sources:
* link:packages/lkmc/kernel_modules/params.c[]
* link:kernel_modules/params.c[]
* link:rootfs_overlay/params.sh[]
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:
* link:packages/lkmc/kernel_modules/dep.c[]
* link:packages/lkmc/kernel_modules/dep2.c[]
* link:kernel_modules/dep.c[]
* link:kernel_modules/dep2.c[]
* link:rootfs_overlay/dep.sh[]
The kernel deduces dependencies based on the `EXPORT_SYMBOL` that each module uses.
@@ -4368,7 +4368,7 @@ name = module_info
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:
@@ -4454,7 +4454,7 @@ Possible dmesg output:
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:
@@ -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 '
....
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]:
@@ -4516,7 +4516,7 @@ init_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
@@ -4531,8 +4531,8 @@ insmod /oops.ko
Source:
* link:packages/lkmc/kernel_modules/panic.c[]
* link:packages/lkmc/kernel_modules/oops.c[]
* link:kernel_modules/panic.c[]
* link:kernel_modules/oops.c[]
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
....
Source: link:packages/lkmc/kernel_modules/dump_stack.c[]
Source: link:kernel_modules/dump_stack.c[]
==== WARN_ON
@@ -4882,7 +4882,7 @@ echo 1 > /proc/sys/kernel/panic_on_warn
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.
@@ -4914,7 +4914,7 @@ Outcome: the test passes:
Sources:
* link:packages/lkmc/kernel_modules/debugfs.c[]
* link:kernel_modules/debugfs.c[]
* link:rootfs_overlay/debugfs.sh[]
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:
* link:packages/lkmc/kernel_modules/procfs.c[]
* link:kernel_modules/procfs.c[]
* link:rootfs_overlay/procfs.sh[]
Bibliography: https://stackoverflow.com/questions/8516021/proc-create-example-for-kernel-module/18924359#18924359
@@ -4977,7 +4977,7 @@ Outcome: the test passes:
Sources:
* link:packages/lkmc/kernel_modules/sysfs.c[]
* link:kernel_modules/sysfs.c[]
* link:rootfs_overlay/sysfs.sh[]
Vs procfs:
@@ -5018,7 +5018,7 @@ Sources:
* link:rootfs_overlay/character_device.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:
@@ -5071,7 +5071,7 @@ Outcome: the test passes:
Sources:
* link:packages/lkmc/kernel_modules/character_device_create.c[]
* link:kernel_modules/character_device_create.c[]
* 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
@@ -5097,7 +5097,7 @@ Outcome: the test passes:
Sources:
* link:packages/lkmc/kernel_modules/fops.c[]
* link:kernel_modules/fops.c[]
* link:rootfs_overlay/fops.sh[]
Then give this a try:
@@ -5127,7 +5127,7 @@ Outcome: the test passes:
Sources:
* link:packages/lkmc/kernel_modules/seq_file.c[]
* link:kernel_modules/seq_file.c[]
* link:rootfs_overlay/seq_file.sh[]
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:
* 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[]
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:
* link:packages/lkmc/kernel_modules/poll.c[]
* link:packages/lkmc/kernel_modules/poll.c[]
* link:kernel_modules/poll.c[]
* link:kernel_modules/poll.c[]
* link:rootfs_overlay/poll.sh[]
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:
* link:packages/lkmc/kernel_modules/ioctl.c[]
* link:packages/lkmc/kernel_modules/ioctl.h[]
* link:packages/lkmc/userland/ioctl.c[]
* link:kernel_modules/ioctl.c[]
* link:kernel_modules/ioctl.h[]
* link:userland/ioctl.c[]
* 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.
@@ -5264,8 +5264,8 @@ Outcome: the test passes:
Sources:
* link:packages/lkmc/kernel_modules/mmap.c[]
* link:packages/lkmc/userland/mmap.c[]
* link:kernel_modules/mmap.c[]
* link:userland/mmap.c[]
* 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.
@@ -5300,9 +5300,9 @@ Outcome: the test passes:
Sources:
* link:packages/lkmc/kernel_modules/anonymous_inode.c[]
* link:packages/lkmc/kernel_modules/anonymous_inode.h[]
* link:packages/lkmc/userland/anonymous_inode.c[]
* link:kernel_modules/anonymous_inode.c[]
* link:kernel_modules/anonymous_inode.h[]
* link:userland/anonymous_inode.c[]
* link:rootfs_overlay/anonymous_inode.sh[]
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:
* link:packages/lkmc/kernel_modules/netlink.c[]
* link:packages/lkmc/kernel_modules/netlink.h[]
* link:packages/lkmc/userland/netlink.c[]
* link:kernel_modules/netlink.c[]
* link:kernel_modules/netlink.h[]
* link:userland/netlink.c[]
* link:rootfs_overlay/netlink.sh[]
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
....
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:
@@ -5393,7 +5393,7 @@ Let's launch two threads and see if they actually run in parallel:
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.
@@ -5427,7 +5427,7 @@ Count to dmesg every one second from `0` up to `n - 1`:
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.
@@ -5452,7 +5452,7 @@ Stop counting:
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.
@@ -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.
Source: link:packages/lkmc/kernel_modules/work_from_work.c[]
Source: link:kernel_modules/work_from_work.c[]
==== 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.
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.
@@ -5544,7 +5544,7 @@ Stop the count:
rmmod wait_queue
....
Source: link:packages/lkmc/kernel_modules/wait_queue.c[]
Source: link:kernel_modules/wait_queue.c[]
This example launches three threads:
@@ -5572,7 +5572,7 @@ Stop counting:
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.
@@ -5593,7 +5593,7 @@ Brute force monitor every shared interrupt that will accept us:
./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:
@@ -5737,7 +5737,7 @@ Outcome: the test passes:
Sources:
* link:packages/lkmc/kernel_modules/kstrto.c[]
* link:kernel_modules/kstrto.c[]
* link:rootfs_overlay/kstrto.sh[]
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
....
Source: link:packages/lkmc/kernel_modules/virt_to_phys.c[]
Source: link:kernel_modules/virt_to_phys.c[]
Sample output:
@@ -5808,7 +5808,7 @@ First get a virtual address to play with:
/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:
@@ -5835,7 +5835,7 @@ Sample output physical address:
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:
@@ -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
....
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
@@ -6028,7 +6028,7 @@ I hope to have examples of all methods some day, since I'm obsessed with visibil
==== 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:
@@ -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`?
@@ -6255,7 +6255,7 @@ Outcome: dmesg outputs on every fork:
<_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?
@@ -6420,7 +6420,7 @@ TODO not always reproducible. Find a more reproducible failure. I could not obse
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/
@@ -6462,7 +6462,7 @@ UIO interface in a nutshell:
Sources:
* link:packages/lkmc/userland/uio_read.c[]
* link:userland/uio_read.c[]
* link:rootfs_overlay/uio_read.sh[]
Bibliography:
@@ -6593,7 +6593,7 @@ Minimal example:
./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:
@@ -6910,7 +6910,7 @@ DRM / DRI is the new interface that supersedes `fbdev`:
./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.
@@ -7316,7 +7316,7 @@ insmod /pci_min.ko
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
Outcome:
@@ -7355,7 +7355,7 @@ This tests a lot of features of the edu device, to understand the results, compa
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
* 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:
* link:bst-vs-heap[]
* link:packages/lkmc/userland/bst_vs_heap.cpp[]
* link:userland/bst_vs_heap.cpp[]
===== OpenMP
@@ -8694,7 +8694,7 @@ Implemented by GCC itself, so just a toolchain configuration, no external libs,
/openmp.out
....
Source: link:packages/lkmc/userland/openmp.c[]
Source: link:userland/openmp.c[]
===== BLAS
@@ -8712,7 +8712,7 @@ Outcome: the test passes:
0
....
Source: link:packages/lkmc/userland/openblas.c[]
Source: link:userland/openblas.c[]
The test performs a general matrix multiplication:
@@ -8758,7 +8758,7 @@ Output:
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.
@@ -9443,8 +9443,8 @@ The executable `/m5ops.out` illustrates how to hard code with inline assembly th
Sources:
* link:packages/lkmc/userland/m5ops.h[]
* link:packages/lkmc/userland/m5ops.c[]
* link:userland/m5ops.h[]
* 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.
@@ -9592,7 +9592,7 @@ Let's have some fun and try to correlate the gem5 cycle count `system.cpu.numCyc
./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`:
@@ -9610,7 +9610,7 @@ Bibliography:
===== 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/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
....
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.
@@ -9894,7 +9894,7 @@ with:
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 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:
==== 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
Every directory inside it is a Buildroot package.
@@ -11137,7 +11143,7 @@ We use it for:
* customized configuration files
* 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
@@ -11281,8 +11287,8 @@ hello cpp
Sources:
* link:packages/lkmc/userland/hello.c[]
* link:packages/lkmc/userland/hello_cpp.c[]
* link:userland/hello.c[]
* link:userland/hello_cpp.c[]
==== 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'
....
Source: link:packages/lkmc/userland/rand_check.c[]
Source: link:userland/rand_check.c[]
This can be used to check the determinism of: