asciidotor README.adoc +xdg-open README.html+
diff --git a/index.html b/index.html index 4bbbe79..4bcfd3f 100644 --- a/index.html +++ b/index.html @@ -445,10 +445,13 @@ body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-b
The perfect emulation setup to study and develop the Linux kernel v5.2.1, kernel modules, QEMU, gem5 and x86_64, ARMv7 and ARMv8 userland and baremetal assembly, ANSI C, C++ and POSIX. GDB step debug and KGDB just work. Powered by Buildroot and crosstool-NG. Highly automated. Thoroughly documented. Automated tests. "Tested" in an Ubuntu 18.04 host.
TL;DR: QEMU Buildroot setup getting started
+TL;DR: Section 1.1.1, “QEMU Buildroot setup getting started”
The source code for this page is located at: https://github.com/cirosantilli/linux-kernel-module-cheat. Due to a GitHub limitation, this README is too long and not fully rendered on github.com. Either use: README.adoc, https://cirosantilli.com/linux-kernel-module-cheat or build the docs yourself.
@@ -510,6 +513,7 @@ body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-bIf you don’t know which one to go for, start with QEMU Buildroot setup getting started.
Design goals of this project are documented at: Design goals.
+Design goals of this project are documented at: Section 29.18.1, “Design goals”.
This setup has been mostly tested on Ubuntu. For other host operating systems see: Supported hosts. For greater stability, consider using the latest release instead of master: https://github.com/cirosantilli/linux-kernel-module-cheat/releases
+This setup has been mostly tested on Ubuntu. For other host operating systems see: Section 29.1, “Supported hosts”. For greater stability, consider using the latest release instead of master: https://github.com/cirosantilli/linux-kernel-module-cheat/releases
Reserve 12Gb of disk and run:
@@ -1808,7 +1821,7 @@ cd linux-kernel-module-cheatYou don’t need to clone recursively even though we have .git submodules: download-dependencies fetches just the submodules that you need for this build to save time.
If something goes wrong, see: Common build issues and use our issue tracker: https://github.com/cirosantilli/linux-kernel-module-cheat/issues
+If something goes wrong, see: Section 29.2, “Common build issues” and use our issue tracker: https://github.com/cirosantilli/linux-kernel-module-cheat/issues
The initial build will take a while (30 minutes to 2 hours) to clone and build, see Benchmark builds for more details.
@@ -1876,7 +1889,7 @@ hello2 cleanupSee also: Quit QEMU from text mode.
+See also: Section 13.1.1, “Quit QEMU from text mode”.
All available modules can be found in the kernel_modules directory.
@@ -1891,7 +1904,7 @@ hello2 cleanupTo avoid typing --arch aarch64 many times, you can set the default arch as explained at: Default command line arguments
To avoid typing --arch aarch64 many times, you can set the default arch as explained at: Section 29.4, “Default command line arguments”
I now urge you to read the following sections which contain widely applicable information:
@@ -2040,7 +2053,7 @@ hello /root/.profileWhen you reach difficulties, QEMU makes it possible to easily GDB step debug the Linux kernel source code, see: GDB step debug.
+When you reach difficulties, QEMU makes it possible to easily GDB step debug the Linux kernel source code, see: Section 2, “GDB step debug”.
All of this put together makes the safe procedure acceptably fast for regular development as well.
It is also easy to GDB step debug kernel modules with our setup, see: GDB step debug kernel module.
+It is also easy to GDB step debug kernel modules with our setup, see: Section 2.4, “GDB step debug kernel module”.
If you really want to develop semiconductors, your only choice is to join an university or a semiconductor company that has the EDA licenses.
See also: Should you waste your life with systems programming?.
+See also: Section 29.19.2, “Should you waste your life with systems programming?”.
While hacking QEMU, you will likely want to GDB step its source. That is trivial since QEMU is just another userland program like any other, but our setup has a shortcut to make it even more convenient, see: Debug the emulator.
+While hacking QEMU, you will likely want to GDB step its source. That is trivial since QEMU is just another userland program like any other, but our setup has a shortcut to make it even more convenient, see: Section 17.7, “Debug the emulator”.
and can therefore be used to estimate system performance, see: gem5 run benchmark for an example.
+and can therefore be used to estimate system performance, see: Section 18.2, “gem5 run benchmark” for an example.
The downside of gem5 much slower than QEMU because of the greater simulation detail.
@@ -2585,7 +2598,7 @@ j = 0See also: tmux gem5.
+See also: Section 2.3.1, “tmux gem5”.
At the end of boot, it might not be very clear that you have the shell since some printk messages may appear in front of the prompt like this:
@@ -2608,7 +2621,7 @@ j = 0More gem5 information is present at: gem5
+More gem5 information is present at: Section 18, “gem5”
Good next steps are:
@@ -2634,7 +2647,7 @@ j = 0This repository has been tested inside clean Docker containers.
This is a good option if you are on a Linux host, but the native setup failed due to your weird host distribution, and you have better things to do with your life than to debug it. See also: Supported hosts.
+This is a good option if you are on a Linux host, but the native setup failed due to your weird host distribution, and you have better things to do with your life than to debug it. See also: Section 29.1, “Supported hosts”.
For example, to do a QEMU Buildroot setup inside Docker, run:
@@ -2822,7 +2835,7 @@ j = 0can’t GDB step debug the kernel, since the source and cross toolchain with GDB are not available. Buildroot cannot easily use a host toolchain: Buildroot use prebuilt host toolchain.
+can’t GDB step debug the kernel, since the source and cross toolchain with GDB are not available. Buildroot cannot easily use a host toolchain: Section 28.2.2.1.1, “Buildroot use prebuilt host toolchain”.
Maybe we could work around this by just downloading the kernel source somehow, and using a host prebuilt GDB, but we felt that it would be too messy and unreliable.
natively on the host as shown at: Userland setup getting started natively
+natively on the host as shown at: Section 1.6.2.1, “Userland setup getting started natively”
Can only run examples compatible with your host CPU architecture and OS, but has the fastest setup and runtimes.
the host prebuilt toolchain: Userland setup getting started with prebuilt toolchain and QEMU user mode
+the host prebuilt toolchain: Section 1.6.2.2, “Userland setup getting started with prebuilt toolchain and QEMU user mode”
the Buildroot toolchain you built yourself: QEMU user mode getting started
+the Buildroot toolchain you built yourself: Section 10.1, “QEMU user mode getting started”
from full system simulation as shown at: QEMU Buildroot setup getting started.
+from full system simulation as shown at: Section 1.1.1, “QEMU Buildroot setup getting started”.
This is the most reproducible and controlled environment, and all examples work there. But also the slower one to setup.
So you can use any option supported by build-userland script freely with build-userland-in-tree and build.
The situation is analogous for userland/test, test-executables-in-tree and test-executables, which are further documented at: User mode tests.
+The situation is analogous for userland/test, test-executables-in-tree and test-executables, which are further documented at: Section 10.2, “User mode tests”.
Do a more clean out-of-tree build instead and run the program:
@@ -3307,7 +3320,7 @@ cd userlandas shown at: Debug the emulator, although direct GDB host usage works as well of course.
+as shown at: Section 17.7, “Debug the emulator”, although direct GDB host usage works as well of course.
--gcc-which host: use the host toolchain.
We must pass this to ./run as well because QEMU must know which dynamic libraries to use. See also: User mode static executables.
We must pass this to ./run as well because QEMU must know which dynamic libraries to use. See also: Section 10.5, “User mode static executables”.
This present the usual trade-offs of using prebuilts as mentioned at: Prebuilt setup.
+This present the usual trade-offs of using prebuilts as mentioned at: Section 1.4, “Prebuilt setup”.
Other functionality are analogous, e.g. testing:
@@ -3390,7 +3403,7 @@ cd userlandAfter doing that setup, you can already execute your userland programs from inside QEMU: the only missing step is how to rebuild executables and run them.
And the answer is exactly analogous to what is shown at: Your first kernel module hack
+And the answer is exactly analogous to what is shown at: Section 1.1.2.2, “Your first kernel module hack”
For example, if we modify userland/c/hello.c to print out something different, we can just rebuild it with:
@@ -3596,7 +3609,7 @@ error: simulation error detected by parsing logsTODO: the carriage returns are a bit different than in QEMU, see: gem5 baremetal carriage return.
+TODO: the carriage returns are a bit different than in QEMU, see: Section 26.4, “gem5 baremetal carriage return”.
Note that ./build-baremetal requires the --emulator gem5 option, and generates separate executable images for both, as can be seen from:
But just stick to newer and better VExpress_GEM5_V1 unless you have a good reason to use RealViewPBX.
When doing baremetal programming, it is likely that you will want to learn userland assembly first, see: Userland assembly.
+When doing baremetal programming, it is likely that you will want to learn userland assembly first, see: Section 21, “Userland assembly”.
For more information on baremetal, see the section: Baremetal.
+For more information on baremetal, see the section: Section 26, “Baremetal”.
The following subjects are particularly important:
@@ -3661,6 +3674,57 @@ echo "$(./getvar --arch aarch64 --baremetal userland/c/hello.c --emulator gem5 -You don’t need to depend on GitHub.
+For a quick and dirty build, install Asciidoctor however you like and build:
+asciidotor README.adoc +xdg-open README.html+
For development, you will want to do a more controlled build with extra error checking as follows.
+For the initial build do:
+./build --download-dependencies docs+
which also downloads build dependencies.
+Then the following times just to the faster:
+./build-doc+
Source: build-doc
+The HTML output is located at:
+xdg-open out/README.html+
More information about our documentation internals can be found at: Section 29.5, “Documentation”
+gem5 tracing with --debug-flags=Exec does show the right symbols however! So in the worst case, we can just read their source. Amazing.
v4.19 also added a CONFIG_HAVE_KERNEL_UNCOMPRESSED=y option for having the kernel uncompressed which could make following the startup easier, but it is only available on s390. aarch64 however is already uncompressed by default, so might be the easiest one. See also: vmlinux vs bzImage vs zImage vs Image.
v4.19 also added a CONFIG_HAVE_KERNEL_UNCOMPRESSED=y option for having the kernel uncompressed which could make following the startup easier, but it is only available on s390. aarch64 however is already uncompressed by default, so might be the easiest one. See also: Section 15.21.1, “vmlinux vs bzImage vs zImage vs Image”.
the emulator does not support host to guest networking. This seems to be the case for gem5: gem5 host to guest networking
+the emulator does not support host to guest networking. This seems to be the case for gem5 as explained at: Section 14.3.1.3, “gem5 host to guest networking”
cannot see the start of the init process easily
the kernel might switch context to another process or to the kernel itself e.g. on a system call, and then TODO confirm the PIC would go to weird places and source code would be missing.
Solutions to this are being researched at: lx-ps.
+Solutions to this are being researched at: Section 2.10.1, “lx-ps”.
For a more minimal baremetal multicore setup, see: ARM multicore.
+For a more minimal baremetal multicore setup, see: Section 26.8.3, “ARM multicore”.
We can set and get which cores the Linux kernel allows a program to run on with sched_getaffinity and sched_setaffinity:
The number of cores is modified as explained at: Number of cores
+The number of cores is modified as explained at: Section 18.2.2.1, “Number of cores”
taskset from the util-linux package sets the initial core affinity of a program:
KGDB expects the connection at ttyS1, our second serial port after ttyS0 which contains the terminal.
The last line is the KDB prompt, and is covered at: KDB. Typing now shows nothing because that prompt is expecting input from ttyS1.
The last line is the KDB prompt, and is covered at: Section 3.3, “KDB”. Typing now shows nothing because that prompt is expecting input from ttyS1.
Instead, we connect to the serial port ttyS1 with GDB:
The init program can be either an executable shell text file, or a compiled ELF file. It becomes easy to accept this once you see that the exec system call handles both cases equally: https://unix.stackexchange.com/questions/174062/can-the-init-process-be-a-shell-script-in-linux/395375#395375
The init executable is searched for in a list of paths in the root filesystem, including /init, /sbin/init and a few others. For more details see: Path to init
The init executable is searched for in a list of paths in the root filesystem, including /init, /sbin/init and a few others. For more details see: Section 6.3, “Path to init”
This just counts every second forever and does not give you a shell.
This method is not very flexible however, as it is hard to reliably pass multiple commands and command line arguments to the init with it, as explained at: Init environment.
+This method is not very flexible however, as it is hard to reliably pass multiple commands and command line arguments to the init with it, as explained at: Section 6.4, “Init environment”.
For this reason, we have created a more robust helper method with the --eval option:
Source: rootfs_overlay/lkmc/eval_base64.sh.
This allows quoting and newlines by base64 encoding on host, and decoding on guest, see: Kernel command line parameters escaping.
+This allows quoting and newlines by base64 encoding on host, and decoding on guest, see: Section 15.3.1, “Kernel command line parameters escaping”.
It also automatically chooses between init= and rcinit= for you, see: Path to init
It also automatically chooses between init= and rcinit= for you, see: Section 6.3, “Path to init”
--eval replaces BusyBox' init completely, which makes things more minimal, but also has has the following consequences:
The best way to overcome those limitations is to use: Run command at the end of BusyBox init
+The best way to overcome those limitations is to use: Section 6.2, “Run command at the end of BusyBox init”
If the script is large, you can add it to a gitignored file and pass that to --eval as in:
which can be good for automated tests, as it ensures that you are using a pristine unmodified system image every time.
Not however that we already disable disk persistency by default on ext2 filesystems even without --initrd: Disk persistency.
Not however that we already disable disk persistency by default on ext2 filesystems even without --initrd: Section 17.2, “Disk persistency”.
One downside of this method is that it has to put the entire filesystem into memory, and could lead to a panic:
@@ -6445,7 +6509,7 @@ cat fSee: rootfs
+We think that this might be because gem5 boots directly vmlinux, and not from the final compressed images that contain the attached rootfs such as bzImage, which is what QEMU does, see also: vmlinux vs bzImage vs zImage vs Image.
We think that this might be because gem5 boots directly vmlinux, and not from the final compressed images that contain the attached rootfs such as bzImage, which is what QEMU does, see also: Section 15.21.1, “vmlinux vs bzImage vs zImage vs Image”.
To do this failed test, we automatically pass a dummy disk image as of gem5 7fa4c946386e7207ad5859e8ade0bbfc14000d91 since the scripts don’t handle a missing --disk-image well, much like is currently done for Baremetal.
emulator implementers have to keep up with libc changes, some of which break even a C hello world due setup code executed before main.
See also: User mode simulation with glibc
+./run --userland path resolution is analogous to that of ./run --baremetal.
./build user-mode-qemu first builds Buildroot, and then runs ./build-userland, which is further documented at: Userland setup. It also builds QEMU. If you ahve already done a QEMU Buildroot setup previously, this will be very fast.
./build user-mode-qemu first builds Buildroot, and then runs ./build-userland, which is further documented at: Section 1.6, “Userland setup”. It also builds QEMU. If you ahve already done a QEMU Buildroot setup previously, this will be very fast.
If you modify the userland programs, rebuild simply with:
@@ -6976,7 +7040,7 @@ qw erTo stop at the very first instruction of a freestanding program, just use --no-continue. A good example of this is shown at: Freestanding programs.
To stop at the very first instruction of a freestanding program, just use --no-continue. A good example of this is shown at: Section 21.5.1, “Freestanding programs”.
Tests under userland/libs/ depend on certain libraries being available on the target, e.g. BLAS for userland/libs/openblas. They are not run by default, but can be enabled with --package and --package-all.
The gem5 tests require building statically with build id static, see also: gem5 syscall emulation mode. TODO automate this better.
The gem5 tests require building statically with build id static, see also: Section 10.6, “gem5 syscall emulation mode”. TODO automate this better.
See: Test this repo for more useful testing tips.
+See: Section 29.13, “Test this repo” for more useful testing tips.
Here is an interesting examples of this: Linux Test Project
+Here is an interesting examples of this: Section 15.20.1, “Linux Test Project”
gem5 user mode currently only supports static executables: gem5 syscall emulation mode
+gem5 user mode currently only supports static executables as mentioned at: Section 10.6, “gem5 syscall emulation mode”
QEMU x86_64 guest on x86_64 host was failing with stack smashing detected, but we found a workaround
@@ -7390,7 +7454,7 @@ qemu: uncaught target signal 6 (Aborted) - core dumpedLet’s see if user mode runs considerably faster than full system or not.
First we build Dhrystone manually statically since dynamic linking is broken in gem5: gem5 syscall emulation mode.
+First we build Dhrystone manually statically since dynamic linking is broken in gem5 as explained at: Section 10.6, “gem5 syscall emulation mode”.
gem5 user mode:
@@ -7477,11 +7541,11 @@ time \./run --userland userland/posix/count.c --userland-args 3+
./run --userland userland/posix/count_to.c --userland-args 3
it first waits for 3 seconds, and then dumps all the output at once, instead of counting once every second as expected.
+it first waits for 3 seconds, then the program exits, and then it dumps all the stdout at once, instead of counting once every second as expected.
The same can be reproduced by copying the raw QEMU command and piping it through tee, so I don’t think it is a bug in our setup:
modules built with Buildroot, see: kernel_modules buildroot package
+modules built with Buildroot, see: Section 29.12.2.1, “kernel_modules buildroot package”
modules built from the kernel tree itself, see: dummy-irq
+modules built from the kernel tree itself, see: Section 15.12.2, “dummy-irq”
we would have to think how to not have to include the kernel modules twice in the root filesystem, but still have 9P working for fast development as described at: Your first kernel module hack
+we would have to think how to not have to include the kernel modules twice in the root filesystem, but still have 9P working for fast development as described at: Section 1.1.2.2, “Your first kernel module hack”
no need to regenerate the root filesystem at all and reboot
overcomes the check_bin_arch problem: Buildroot rebuild is slow when the root filesystem is large
overcomes the check_bin_arch problem as shown at: Section 19.8, “Buildroot rebuild is slow when the root filesystem is large”
scrolling up: Scroll up in graphic mode
+scrolling up: Section 13.2.1, “Scroll up in graphic mode”
copy paste to and from the terminal
@@ -7972,7 +8036,7 @@ a crash or deadlock.Outcome: you see a penguin due to CONFIG_LOGO.
For a more exciting GUI experience, see: X11 Buildroot
+For a more exciting GUI experience, see: Section 13.4, “X11 Buildroot”
Text mode is the default due to the following considerable advantages:
@@ -8533,7 +8597,7 @@ xeyesWe disable networking by default because it starts an userland process, and we want to keep the number of userland processes to a minimum to make the system more understandable: Resource tradeoff guidelines
+We disable networking by default because it starts an userland process, and we want to keep the number of userland processes to a minimum to make the system more understandable as explained at: Section 29.18.3, “Resource tradeoff guidelines”
To enable networking on Buildroot, simply run:
@@ -8595,7 +8659,7 @@ cat index.htmlIn this section we discuss how to interact between the guest and the host through networking.
First ensure that you can access the external network since that is easier to get working: Networking.
+First ensure that you can access the external network since that is easier to get working, see: Section 14, “Networking”.
9P is better with emulation, but let’s just get this working for fun.
First make sure that this works: Guest to host networking.
+First make sure that this works: Section 14.3.2, “Guest to host networking”.
Then, build the kernel with NFS support:
@@ -9042,7 +9106,7 @@ cp "$(./getvar linux_build_dir)/defconfig" data/myconfigYou can also use other config generating targets such as defconfig with the same method as shown at: Linux kernel defconfig.
You can also use other config generating targets such as defconfig with the same method as shown at: Section 15.1.3.1.1, “Linux kernel defconfig”.
a base config extracted from Buildroot’s minimal per machine .config, which has the minimal options needed to boot: About Buildroot’s kernel configs.
a base config extracted from Buildroot’s minimal per machine .config, which has the minimal options needed to boot as explained at: Section 15.1.3.1, “About Buildroot’s kernel configs”.
small overlays put top of that
@@ -9152,12 +9216,12 @@ CONFIG_IKCONFIG_PROC=ylinux_config/min: see: Linux kernel min config
+linux_config/min: see: Section 15.1.3.1.2, “Linux kernel min config”
linux_config/default: other optional configs that we enable by default because they increase visibility, or expose some cool feature, and don’t significantly increase build time nor add significant runtime overhead
We have since observed that the kernel size itself is very bloated compared to defconfig: Linux kernel defconfig.
We have since observed that the kernel size itself is very bloated compared to defconfig as shown at: Section 15.1.3.1.1, “Linux kernel defconfig”.
linux_config/min contains minimal tweaks required to boot gem5 or for using our slightly different QEMU command line options than Buildroot on all archs.
It is one of the default config fragments we use, as explained at: About our Linux kernel configs>.
+It is one of the default config fragments we use, as explained at: Section 15.1.3, “About our Linux kernel configs”>.
Having the same config working for both QEMU and gem5 (oh, the hours of bisection) means that you can deal with functional matters in QEMU, which runs much faster, and switch to gem5 only for performance issues.
@@ -9304,7 +9368,7 @@ CONFIG_IKCONFIG_PROC=yarm and aarch64 configs present in the official ARM gem5 Linux kernel fork: gem5 arm Linux kernel patches. Some of the configs present there are added by the patches.
arm and aarch64 configs present in the official ARM gem5 Linux kernel fork as described at: Section 18.9, “gem5 arm Linux kernel patches”. Some of the configs present there are added by the patches.
Jason’s magic x86_64 config: http://web.archive.org/web/20171229121642/http://www.lowepower.com/jason/files/config which is referenced at: http://web.archive.org/web/20171229121525/http://www.lowepower.com/jason/setting-up-gem5-full-system.html. QEMU boots with that by removing # CONFIG_VIRTIO_PCI is not set.
This also makes this repo the perfect setup to develop the Linux kernel.
In case something breaks while updating the Linux kernel, you can try to bisect it to understand the root cause: Bisection.
+In case something breaks while updating the Linux kernel, you can try to bisect it to understand the root cause, see: Section 29.14, “Bisection”.
First, use use the branching procedure described at: Update a forked submodule
+First, use use the branching procedure described at: Section 29.16, “Update a forked submodule”
Because the kernel is so central to this repository, almost all tests must be re-run, so basically just follow the full testing procedure described at: Test this repo. The only tests that can be skipped are essentially the Baremetal tests.
+Because the kernel is so central to this repository, almost all tests must be re-run, so basically just follow the full testing procedure described at: Section 29.13, “Test this repo”. The only tests that can be skipped are essentially the Baremetal tests.
Before comitting, don’t forget to update:
@@ -9376,7 +9440,17 @@ git log | grep -E ' Linux [0-9]+\.' | headthe linux_kernel_version constant in common.py
the tagline of this README
+the tagline of this repository on:
+this README
+the GitHub project description
+The debug highest level is a bit more magic, see: pr_debug for more info.
+The debug highest level is a bit more magic, see: Section 15.4.2, “pr_debug” for more info.
panic=-1 command line option which reboots the kernel immediately on panic, see: Reboot on panic
panic=-1 command line option which reboots the kernel immediately on panic, see: Section 15.7.1.4, “Reboot on panic”
QEMU -no-reboot, which makes QEMU exit when the guest tries to reboot
The sleep is done with usleep_range, see: sleep.
The sleep is done with usleep_range, see: Section 15.10.2, “sleep”.
Bibliography:
@@ -13276,7 +13350,7 @@ sleep 4 & sleep 4 &Results (boot not excluded): Boot instruction counts for various setups
+Results (boot not excluded) are shown at: Table 1, “Boot instruction counts for various setups”