This shows you the differences between two versions of the page.
ass:cursuri:04:theory:00 [2024/08/09 16:07] radu.mantu |
ass:cursuri:04:theory:00 [2024/08/15 19:20] (current) radu.mantu [QEMU setup for kernel development] |
||
---|---|---|---|
Line 48: | Line 48: | ||
$ chroot rootfs /bin/bash | $ chroot rootfs /bin/bash | ||
</code> | </code> | ||
- | |||
=== The Linux kernel === | === The Linux kernel === | ||
Line 54: | Line 53: | ||
This step is very straightforward. Just clone the Linux repo (with depth=1 to squash the commit history, reducing the amount of downloaded data) and compile it for the **arm64** target. Notice in the instructions below that we also specify ''kvm_guest.config''. We don't plan to perform a //perfect// emulation of arm64 devices but instead be transparent to the kernel and let it know that it's running in a virtual environment. This permits us to cut some corners and save some crucial clock cycles, increasing the performance of the VM. This is also the main difference between //emulation// and //simulation//. | This step is very straightforward. Just clone the Linux repo (with depth=1 to squash the commit history, reducing the amount of downloaded data) and compile it for the **arm64** target. Notice in the instructions below that we also specify ''kvm_guest.config''. We don't plan to perform a //perfect// emulation of arm64 devices but instead be transparent to the kernel and let it know that it's running in a virtual environment. This permits us to cut some corners and save some crucial clock cycles, increasing the performance of the VM. This is also the main difference between //emulation// and //simulation//. | ||
- | Optionally, you can enable the generation of debug symbols and **gdb** helper scripts. The config options are ''CONFIG_DEBUG_INFO_DWARF5'' and ''CONFIG_GDB_SCRIPTS'', found under ''Kernel hacking -> Compile-time checks and compiler options''. | + | Optionally, you can enable the generation of debug symbols and **gdb** helper scripts. The config options are ''CONFIG_DEBUG_INFO_DWARF5'' and ''CONFIG_GDB_SCRIPTS'', found under ''Kernel hacking -> Compile-time checks and compiler options''. Also, make sure ''CONFIG_DEBUG_INFO_REDUCED'' is disabled so that the compiler will generate debug info for //structures//. |
<code bash> | <code bash> | ||
Line 85: | Line 84: | ||
Unfortunately, the server does not have any foolproof method of inferring the structure of the project. For example, it has no idea whether you are using the //arm64// or the //x86// definition of a function. Luckily for us, the Linux build system contains a script that's able to generate a file names ''compile_commands.json''. This file contains all compiler invocations used during the boot and can deduce include paths, compiled source, macro definitions, etc. The language server will automatically load it and generate indices for the compiled source code. | Unfortunately, the server does not have any foolproof method of inferring the structure of the project. For example, it has no idea whether you are using the //arm64// or the //x86// definition of a function. Luckily for us, the Linux build system contains a script that's able to generate a file names ''compile_commands.json''. This file contains all compiler invocations used during the boot and can deduce include paths, compiled source, macro definitions, etc. The language server will automatically load it and generate indices for the compiled source code. | ||
- | Note that this script only forks for the Linux kernel. If you want to generate ''compile_commands.json'' for other projects, consider using [[https://github.com/rizsotto/Bear|Bear]]. This is a tool that hooks the ''exec()'' family of library calls via LD_PRELOAD hooking in order to extract the command arguments. | + | <code bash> |
+ | linux$ ./scripts/clang-tools/gen_compile_commands.py | ||
+ | </code> | ||
+ | |||
+ | Note that this script only works for the Linux kernel. If you want to generate ''compile_commands.json'' for other projects, consider using [[https://github.com/rizsotto/Bear|Bear]]. This is a tool that hooks the ''exec()'' family of library calls via LD_PRELOAD hooking in order to extract the command arguments. | ||
+ | |||
+ | Also, for such a large codebase, expect the language server to take up //a lot// of your CPU when you first open your editor, while doing the indexing (usually in a ''.cache/'' directory). | ||
</note> | </note> | ||
Line 100: | Line 105: | ||
# boot up the VM | # boot up the VM | ||
- | qemu-system-aarch64 \ | + | qemu-system-aarch64 \ |
- | -machine virt \ | + | -machine virt \ |
- | -cpu cortex-a53 \ | + | -cpu cortex-a53 \ |
- | -smp 1 \ | + | -smp 1 \ |
- | -m 512M \ | + | -m 512M \ |
- | -nographic \ | + | -nographic \ |
- | -kernel linux/arch/arm64/boot/Image \ | + | -kernel linux/arch/arm64/boot/Image \ |
-virtfs local,path=${WS_DIR}/rootfs,mount_tag=rootfs,security_model=passthrough,id=rootfs,multidevs=remap \ | -virtfs local,path=${WS_DIR}/rootfs,mount_tag=rootfs,security_model=passthrough,id=rootfs,multidevs=remap \ | ||
-append "root=rootfs rootfstype=9p rootflags=trans=virtio,version=9p2000.L rw console=ttyAMA0" | -append "root=rootfs rootfstype=9p rootflags=trans=virtio,version=9p2000.L rw console=ttyAMA0" | ||
Line 119: | Line 124: | ||
* ''kernel'': Pretty self-explanatory. It's the kernel image that will be loaded. | * ''kernel'': Pretty self-explanatory. It's the kernel image that will be loaded. | ||
* ''virtfs'': This options specifies virtual storage device based on [[https://www.kernel.org/doc/html/latest/filesystems/9p.html|9p]] remote filesystem protocol. Using this instead of a disk image (like the one you had to create with **partx** in the second session) can be chalked up to personal preference. With 9p you can manipulate the guest filesystem from the host while the VM is running. If we used a disk image, we'd have to double mount it to obtain the same functionality and this would lead to corruptions with //100% certainty// due to the lack of synchronization mechanisms at the VFS driver level (between host and guest kernels). For more information regarding it's key-value list of arguments, check out the [[https://wiki.qemu.org/Documentation/9psetup|documentation]]. | * ''virtfs'': This options specifies virtual storage device based on [[https://www.kernel.org/doc/html/latest/filesystems/9p.html|9p]] remote filesystem protocol. Using this instead of a disk image (like the one you had to create with **partx** in the second session) can be chalked up to personal preference. With 9p you can manipulate the guest filesystem from the host while the VM is running. If we used a disk image, we'd have to double mount it to obtain the same functionality and this would lead to corruptions with //100% certainty// due to the lack of synchronization mechanisms at the VFS driver level (between host and guest kernels). For more information regarding it's key-value list of arguments, check out the [[https://wiki.qemu.org/Documentation/9psetup|documentation]]. | ||
- | * ''append'': The command line arguments for the kernel. | + | * ''append'': The command line arguments for the kernel. Check [[https://www.kernel.org/doc/html/v4.14/admin-guide/kernel-parameters.html|this]] out for more kernel cli arguments. |
* ''root=rootfs'': The rootfs device, it's value must match that of the ''mount_tag'' attribute from the previous flag. | * ''root=rootfs'': The rootfs device, it's value must match that of the ''mount_tag'' attribute from the previous flag. | ||
* ''rootfstype=9p'': Informs the kernel what the backing storage device for the rootfs will be. | * ''rootfstype=9p'': Informs the kernel what the backing storage device for the rootfs will be. | ||
Line 127: | Line 132: | ||
<note important> | <note important> | ||
- | **Troubleshoot** | + | **Troubleshooting** |
---- | ---- | ||
If the terminal in the VM is acting weird (e.g., commands wrapping over onto the same line and overwriting the characters on display), set ''TERM=xterm'' inside the VM. This variable defines the type of terminal for which the shell prepares its output. You can read up more on this topic [[https://bash.cyberciti.biz/guide/$TERM_variable|here]] but **xterm** is a safe option for **bash**, **zsh** and **sh**. | If the terminal in the VM is acting weird (e.g., commands wrapping over onto the same line and overwriting the characters on display), set ''TERM=xterm'' inside the VM. This variable defines the type of terminal for which the shell prepares its output. You can read up more on this topic [[https://bash.cyberciti.biz/guide/$TERM_variable|here]] but **xterm** is a safe option for **bash**, **zsh** and **sh**. | ||
Line 133: | Line 138: | ||
Some terminal emulators such as [[https://github.com/kovidgoyal/kitty|kitty]] support custom ''TERM'' values such as **xterm-kitty** but most shells won't have any idea how to particularize the output for it. Stick to **xterm** :p | Some terminal emulators such as [[https://github.com/kovidgoyal/kitty|kitty]] support custom ''TERM'' values such as **xterm-kitty** but most shells won't have any idea how to particularize the output for it. Stick to **xterm** :p | ||
---- | ---- | ||
- | If the VM doesn't accept your root login password even after specifically setting it from **chroot** via **passwd**, make sure you're running the script with **sudo**. When debootstrapping the rootfs, the file owner was set to //root//, meaning that your unprivileged user won't have read access to ''/etc/shadow'' that has ''rw----'' permissions. As a result, ''systemd-login'' won't be able to validate your password against its stored cryptographic hash. Though I agree, it could be a bit more verbose about that fact :/ | + | If the VM doesn't accept your root login password even after specifically setting it from **chroot** via **passwd**, make sure you're running the script with **sudo**. When debootstrapping the rootfs, the file owner was set to //root//, meaning that your unprivileged user won't have read access to ''/etc/shadow'' that has ''rw%%----%%'' permissions. As a result, ''systemd-login'' won't be able to validate your password against its stored cryptographic hash. Though I agree, it could be a bit more verbose about that fact :/ |
</note> | </note> |