mirror of
https://github.com/cirosantilli/linux-kernel-module-cheat.git
synced 2026-01-23 02:05:57 +01:00
Enable either ext2, initrd or initramfs for x86, arm and aarch64
Mention that initrd and initramfs must fit into memory. Fix missing stdout when ./run -d is used. Ignore ./run -n for non x86.
This commit is contained in:
321
README.adoc
321
README.adoc
@@ -248,88 +248,7 @@ root
|
||||
|
||||
every time.
|
||||
|
||||
Here are some methods to automate that.
|
||||
|
||||
==== Replace init
|
||||
|
||||
This method replaces init and evals a command from the <<kernel-command-line-parameters>>:
|
||||
|
||||
....
|
||||
./run -E 'echo "asdf qwer";insmod /hello.ko;/poweroff.out' -n
|
||||
....
|
||||
|
||||
It is basically a shortcut for:
|
||||
|
||||
....
|
||||
./run -e 'init=/eval.sh - lkmc_eval="insmod /hello.ko;/poweroff.out"' -n
|
||||
....
|
||||
|
||||
although `-E` allows for quoting and newlines by using base64 encoding, so you should almost always use it, unless you are really counting each cycle ;-)
|
||||
|
||||
If the script is large, you can add it to a gitignored file and pass that to `-E` as in:
|
||||
|
||||
....
|
||||
echo '
|
||||
insmod /hello.ko
|
||||
/poweroff.out
|
||||
' > ignore.sh
|
||||
./run -E "$(cat ignore.sh)" -n
|
||||
....
|
||||
|
||||
or add it to a file to the root filesystem guest and rebuild:
|
||||
|
||||
....
|
||||
echo '#!/bin/sh
|
||||
insmod /hello.ko
|
||||
/poweroff.out
|
||||
' > rootfs_overlay/ignore.sh
|
||||
chmod +x rootfs_overlay/ignore.sh
|
||||
./build
|
||||
./run -e 'init=/ignore.sh' -n
|
||||
....
|
||||
|
||||
==== Run command at the end of BusyBox init
|
||||
|
||||
If you rely on something that BusyBox' init set up for you like networking, this is the way to go:
|
||||
|
||||
....
|
||||
./run -e '- lkmc_eval="insmod /hello.ko;wget -S google.com;poweroff.out;"'
|
||||
....
|
||||
|
||||
or add them to a new `init.d` entry to run at the end o the BusyBox init:
|
||||
|
||||
....
|
||||
cp rootfs_overlay/etc/init.d/S98 rootfs_overlay/etc/init.d/S99
|
||||
vim S99
|
||||
./build
|
||||
./run
|
||||
....
|
||||
|
||||
and they will be run automatically before the login prompt.
|
||||
|
||||
`S99` is a git tracked convenience symlink to the gitignored `rootfs_overlay/etc/init.d/S99`
|
||||
|
||||
Scripts under `/etc/init.d` are run by `/etc/init.d/rcS`, which gets called by the line `::sysinit:/etc/init.d/rcS` in `/etc/inittab`.
|
||||
|
||||
==== The kernel panics despite poweroff
|
||||
|
||||
Just using Busybox' `poweroff` at the end of the `init` does not work and the kernel panics:
|
||||
|
||||
....
|
||||
./run -E poweroff
|
||||
....
|
||||
|
||||
because BusyBox' `poweroff` tries to do some fancy stuff like killing init, likely to allow userland to shutdown nicely.
|
||||
|
||||
But this fails when we are `init` itself!
|
||||
|
||||
`poweroff` works more brutally and effectively if you add `-f`:
|
||||
|
||||
....
|
||||
./run -E 'poweroff -f'
|
||||
....
|
||||
|
||||
but why not just use your super simple and effective `/poweroff.out` and be done with it?
|
||||
To automate that, use the methods described at: <<init>>
|
||||
|
||||
=== Kernel command line parameters
|
||||
|
||||
@@ -367,6 +286,12 @@ When dealing with real boards, extra command line options are provided on some m
|
||||
* GRUB configuration files: https://askubuntu.com/questions/19486/how-do-i-add-a-kernel-boot-parameter
|
||||
* Raspberry pi `/boot/cmdline.txt` on a magic partition: https://raspberrypi.stackexchange.com/questions/14839/how-to-change-the-kernel-commandline-for-archlinuxarm-on-raspberry-pi-effectly
|
||||
|
||||
=== Kernel command line parameters escaping
|
||||
|
||||
Double quotes can be used to escape spaces as in `opt="a b"`, but double quotes themselves cannot be escaped, e.g. `opt"a\"b"`
|
||||
|
||||
This even lead us to use base64 encoding with `-E`!
|
||||
|
||||
=== What command was actually run?
|
||||
|
||||
When asking for help on upstream repositories outside of this repository, you will need to provide the commands that you are running in detail without referencing our scripts.
|
||||
@@ -408,6 +333,12 @@ If you want to break immediately at a symbol, e.g. `start_kernel` of the boot se
|
||||
./rungdb start_kernel
|
||||
....
|
||||
|
||||
or at a given line:
|
||||
|
||||
....
|
||||
./rungdb init/main.c:1088
|
||||
....
|
||||
|
||||
Now QEMU will stop there, and you can use the normal GDB commands:
|
||||
|
||||
....
|
||||
@@ -948,37 +879,140 @@ TODOs:
|
||||
|
||||
When the Linux kernel finishes booting, it runs an executable as the first and only userland process.
|
||||
|
||||
The default path is `/init`, but we an set a custom one with the `init=` <<kernel-command-line-parameters,kernel command line parameter>>.
|
||||
|
||||
This process is then responsible for setting up the entire userland (or destroying everything when you want to have fun).
|
||||
This init process is then responsible for setting up the entire userland (or destroying everything when you want to have fun).
|
||||
|
||||
This typically means reading some configuration files (e.g. `/etc/initrc`) and forking a bunch of userland executables based on those files.
|
||||
|
||||
systemd is a "popular" `/init` implementation for desktop distros as of 2017.
|
||||
systemd provides a "popular" init implementation for desktop distros as of 2017.
|
||||
|
||||
BusyBox provides its own minimalistic init implementation which Buildroot uses by default.
|
||||
BusyBox provides its own minimalistic init implementation which Buildroot, and therefore this repo, uses by default.
|
||||
|
||||
=== Custom init
|
||||
=== Replace init
|
||||
|
||||
Is the default BusyBox `/init` too bloated for you, minimalism freak?
|
||||
To have more control over the system, you can replace BusyBox's init with your own.
|
||||
|
||||
No problem, just use the `init` kernel boot parameter:
|
||||
The following method replaces init and evals a command from the <<kernel-command-line-parameters>>:
|
||||
|
||||
....
|
||||
./run -e 'init=/sleep_forever.out'
|
||||
./run -E 'echo "asdf qwer";insmod /hello.ko;/poweroff.out' -n
|
||||
....
|
||||
|
||||
Remember that shell scripts can also be used for `init` https://unix.stackexchange.com/questions/174062/init-as-a-shell-script/395375#395375:
|
||||
It is basically a shortcut for:
|
||||
|
||||
....
|
||||
./run -e 'init=/count.sh'
|
||||
./run -e 'init=/eval.sh - lkmc_eval="insmod /hello.ko;/poweroff.out"' -n
|
||||
....
|
||||
|
||||
Also remember that if your init returns, the kernel will panic, there are just two non-panic possibilities:
|
||||
although `-E` is smarter:
|
||||
|
||||
* allows quoting and newlines by using base64 encoding, see: <<kernel-command-line-parameters-escaping>>
|
||||
* automatically chooses between `init=` and `rcinit=` for you, see: <<path-to-init>>
|
||||
|
||||
so you should almost always use it, unless you are really counting each cycle ;-)
|
||||
|
||||
If the script is large, you can add it to a gitignored file and pass that to `-E` as in:
|
||||
|
||||
....
|
||||
echo '
|
||||
insmod /hello.ko
|
||||
/poweroff.out
|
||||
' > ignore.sh
|
||||
./run -E "$(cat ignore.sh)" -n
|
||||
....
|
||||
|
||||
or add it to a file to the root filesystem guest and rebuild:
|
||||
|
||||
....
|
||||
echo '#!/bin/sh
|
||||
insmod /hello.ko
|
||||
/poweroff.out
|
||||
' > rootfs_overlay/ignore.sh
|
||||
chmod +x rootfs_overlay/ignore.sh
|
||||
./build
|
||||
./run -e 'init=/ignore.sh' -n
|
||||
....
|
||||
|
||||
Remember that if your init returns, the kernel will panic, there are just two non-panic possibilities:
|
||||
|
||||
* run forever in a loop or long sleep
|
||||
* `poweroff` the machine
|
||||
|
||||
==== The kernel panics despite poweroff
|
||||
|
||||
Just using BusyBox' `poweroff` at the end of the `init` does not work and the kernel panics:
|
||||
|
||||
....
|
||||
./run -E poweroff
|
||||
....
|
||||
|
||||
because BusyBox' `poweroff` tries to do some fancy stuff like killing init, likely to allow userland to shutdown nicely.
|
||||
|
||||
But this fails when we are `init` itself!
|
||||
|
||||
`poweroff` works more brutally and effectively if you add `-f`:
|
||||
|
||||
....
|
||||
./run -E 'poweroff -f'
|
||||
....
|
||||
|
||||
but why not just use your super simple and effective `/poweroff.out` and be done with it?
|
||||
|
||||
=== Run command at the end of BusyBox init
|
||||
|
||||
If you rely on something that BusyBox' init set up for you like networking, you caould do:
|
||||
|
||||
....
|
||||
./run -e '- lkmc_eval="insmod /hello.ko;wget -S google.com;poweroff.out;"'
|
||||
....
|
||||
|
||||
The `lkmc_eval` option gets evaled by our default `S98` startup script if present.
|
||||
|
||||
Alternatively, add them to a new `init.d` entry to run at the end o the BusyBox init:
|
||||
|
||||
....
|
||||
cp rootfs_overlay/etc/init.d/S98 rootfs_overlay/etc/init.d/S99
|
||||
vim S99
|
||||
./build
|
||||
./run
|
||||
....
|
||||
|
||||
and they will be run automatically before the login prompt.
|
||||
|
||||
`S99` is a git tracked convenience symlink to the gitignored `rootfs_overlay/etc/init.d/S99`
|
||||
|
||||
Scripts under `/etc/init.d` are run by `/etc/init.d/rcS`, which gets called by the line `::sysinit:/etc/init.d/rcS` in `/etc/inittab`.
|
||||
|
||||
=== Path to init
|
||||
|
||||
The init is selected at:
|
||||
|
||||
- initrd or initramfs system: `/init`, a custom one can be set with the `rdinit=` <<kernel-command-line-parameters,kernel command line parameter>>
|
||||
- otherwise: default is `/sbin/init`, followed by some other paths, a custom one can be set with `init=`
|
||||
|
||||
More details: https://unix.stackexchange.com/questions/30414/what-can-make-passing-init-path-to-program-to-the-kernel-not-start-program-as-i/430614#430614
|
||||
|
||||
=== Init environment
|
||||
|
||||
Documented at link:https://www.kernel.org/doc/html/v4.14/admin-guide/kernel-parameters.html[]:
|
||||
|
||||
____
|
||||
The kernel parses parameters from the kernel command line up to "-"; if it doesn't recognize a parameter and it doesn't contain a '.', the parameter gets passed to init: parameters with '=' go into init's environment, others are passed as command line arguments to init. Everything after "-" is passed as an argument to init.
|
||||
____
|
||||
|
||||
And you can try it out with:
|
||||
|
||||
....
|
||||
./run -e 'init=/init_env_poweroff.sh - asdf=qwer zxcv' -n
|
||||
....
|
||||
|
||||
Also note how the annoying dash `-` also gets passed as a parameter to `init`, which makes it impossible to use this method for most executables.
|
||||
|
||||
Finally, the docs are lying, arguments with dots that come after `-` are still treated specially (of the form `subsystem.somevalue`) and disappear:
|
||||
|
||||
....
|
||||
./run -e 'init=/init_env_poweroff.sh - /poweroff.out' -n
|
||||
....
|
||||
|
||||
=== Disable networking
|
||||
|
||||
The default BusyBox init scripts enable networking, and there is a 15 second timeout in case your network is down or if your kernel / emulator setup does not support it.
|
||||
@@ -995,20 +1029,6 @@ To restore it, run:
|
||||
./build -- initscripts-reconfigure
|
||||
....
|
||||
|
||||
=== The init environment
|
||||
|
||||
The docs make it clear https://www.kernel.org/doc/html/v4.14/admin-guide/kernel-parameters.html
|
||||
|
||||
____
|
||||
The kernel parses parameters from the kernel command line up to “–”; if it doesn’t recognize a parameter and it doesn’t contain a ‘.’, the parameter gets passed to init: parameters with ‘=’ go into init’s environment, others are passed as command line arguments to init. Everything after “–” is passed as an argument to init.
|
||||
____
|
||||
|
||||
And you can try it out with:
|
||||
|
||||
....
|
||||
./run -e 'init=/init_env_poweroff.sh - asdf=qwer zxcv' -n
|
||||
....
|
||||
|
||||
== modprobe
|
||||
|
||||
If you are feeling fancy, you can also insert modules with:
|
||||
@@ -1088,7 +1108,7 @@ Only tested successfully in `x86_64`.
|
||||
Build:
|
||||
|
||||
....
|
||||
./build -i br2_x11
|
||||
./build -b br2_x11
|
||||
./run
|
||||
....
|
||||
|
||||
@@ -1257,13 +1277,18 @@ The bootloader, which for us is QEMU itself, is then configured to put that CPIO
|
||||
|
||||
With this setup, you don't even need to give a root filesystem to the kernel, it just does everything in memory in a ramfs.
|
||||
|
||||
Try it out with:
|
||||
To enable initrd instead of the default ext2 disk image, do:
|
||||
|
||||
....
|
||||
./build -i
|
||||
./run -i
|
||||
....
|
||||
|
||||
Notice how it boots fine, even though `-drive` is not given.
|
||||
Notice how it boots fine, even though this leads to not giving QEMU the `-drive` option, as can be verified with:
|
||||
|
||||
....
|
||||
cat ./run.log
|
||||
....
|
||||
|
||||
Also as expected, there is no filesystem persistency, since we are doing everything in memory:
|
||||
|
||||
@@ -1274,9 +1299,21 @@ cat f
|
||||
# can't open 'f': No such file or directory
|
||||
....
|
||||
|
||||
This can be good for automated tests, as it ensures that you are using a pristine unmodified system image every time.
|
||||
which can be good for automated tests, as it ensures that you are using a pristine unmodified system image every time.
|
||||
|
||||
The main ingredients to get this working are:
|
||||
One downside of this method is that it has to put the entire filesystem into memory, and could lead to a panic:
|
||||
|
||||
....
|
||||
end Kernel panic - not syncing: Out of memory and no killable processes...
|
||||
....
|
||||
|
||||
This can be solved by increasing the memory with:
|
||||
|
||||
....
|
||||
./run -im 256M
|
||||
....
|
||||
|
||||
The main ingredients to get initrd working are:
|
||||
|
||||
* `BR2_TARGET_ROOTFS_CPIO=y`: make Buildroot generate `output/images/rootfs.cpio` in addition to the other images.
|
||||
+
|
||||
@@ -1311,15 +1348,43 @@ So the only argument that QEMU needs is the `-kernel`, no `-drive` not even `-in
|
||||
Try it out with:
|
||||
|
||||
....
|
||||
./run -a aarch64
|
||||
rm -f buildroot/output.x86_64~/build/linux-custom/.config
|
||||
./build -I
|
||||
./run -I
|
||||
....
|
||||
|
||||
since our <<aarch64>> setup uses it by default.
|
||||
The line:
|
||||
|
||||
....
|
||||
rm -f buildroot/output.x86_64~/build/linux-custom/.config
|
||||
....
|
||||
|
||||
is only needed the first time you move from a different root filesystem method (ext2 or cpio) to initramfs. It is needed because Buildroot is not automatically updating `CONFIG_INITRAMFS_SOURCE` in the kernel config for some reason: https://stackoverflow.com/questions/49260466/why-when-i-change-br2-linux-kernel-custom-config-file-and-run-make-linux-reconfi
|
||||
|
||||
Then to go back to another boot method such as ext filesystems to:
|
||||
|
||||
....
|
||||
rm -f buildroot/output.x86_64~/build/linux-custom/.config
|
||||
./build
|
||||
./run
|
||||
....
|
||||
|
||||
It is interesting to see how this increases the size of the kernel image if you do a:
|
||||
|
||||
....
|
||||
ls -lh buildroot/output.x86_64~/images/bzImage
|
||||
....
|
||||
|
||||
before and after using initramfs, since the `.cpio` is now glued to the kernel image.
|
||||
|
||||
In the background, it uses `BR2_TARGET_ROOTFS_INITRAMFS`, and this makes the kernel config option `CONFIG_INITRAMFS_SOURCE` point to the CPIO that will be embedded in the kernel image.
|
||||
|
||||
http://nairobi-embedded.org/initramfs_tutorial.html shows a full manual setup.
|
||||
|
||||
=== gem5 initrd
|
||||
|
||||
TODO we were not able to get it working yet: https://stackoverflow.com/questions/49261801/how-to-boot-the-linux-kernel-with-initrd-or-initramfs-with-gem5
|
||||
|
||||
== Linux kernel
|
||||
|
||||
=== Use your own kernel config
|
||||
@@ -1992,6 +2057,18 @@ TODO These look promising:
|
||||
|
||||
TODO: now to verify this with the Linux kernel? Besides raw performance benchmarks.
|
||||
|
||||
===== gem5 memory size
|
||||
|
||||
....
|
||||
./run -a arm -m 512M
|
||||
....
|
||||
|
||||
and verify inside the guest with:
|
||||
|
||||
....
|
||||
free -m
|
||||
....
|
||||
|
||||
===== gem5 disk and network latency
|
||||
|
||||
TODO These look promising:
|
||||
@@ -2080,7 +2157,7 @@ Buildroot supports it, which makes everything just trivial:
|
||||
....
|
||||
printf 'BR2_PACKAGE_OPENBLAS=y\n' >> br2_local
|
||||
printf 'BR2_TARGET_ROOTFS_EXT2_SIZE="128M"\n' >> br2_local
|
||||
./build -a arm -g -i br2_local -- kernel_module-reconfigure
|
||||
./build -a arm -g -b br2_local -- kernel_module-reconfigure
|
||||
....
|
||||
|
||||
and then inside the guest run our test program:
|
||||
@@ -2113,7 +2190,7 @@ There are two ways to run PARSEC with this repo:
|
||||
====== PARSEC benchmark without parsecmgmt
|
||||
|
||||
....
|
||||
configure -gpq && ./build -a arm -g -i br2_parsec
|
||||
configure -gpq && ./build -a arm -g -b br2_parsec
|
||||
./run -a arm -g
|
||||
....
|
||||
|
||||
@@ -2146,7 +2223,7 @@ Running a benchmark of a different size requires a rebuild wit:
|
||||
-c 'BR2_PACKAGE_PARSEC_BENCHMARK_INPUT_SIZE="simsmall"' \
|
||||
-c BR2_TARGET_ROOTFS_EXT2_SIZE="500M" \
|
||||
-g \
|
||||
-i br2_parsec \
|
||||
-b br2_parsec \
|
||||
-- parsec-benchmark-reconfigure \
|
||||
;
|
||||
....
|
||||
@@ -2198,7 +2275,7 @@ If you still want to run this, try it out with:
|
||||
./build -a arm \
|
||||
-c BR2_TARGET_ROOTFS_EXT2_SIZE="3G" \
|
||||
-g
|
||||
-i br2_parsec
|
||||
-b br2_parsec
|
||||
-- parsec-benchmark-reconfigure \
|
||||
;
|
||||
....
|
||||
@@ -2225,7 +2302,7 @@ BR2_PACKAGE_PARSEC_BENCHMARK_INPUT_SIZE=simsmall
|
||||
and then rebuild with:
|
||||
|
||||
....
|
||||
./build -a arm -g -i br2_parsec -- parsec-benchmark-reconfigure
|
||||
./build -a arm -g -b br2_parsec -- parsec-benchmark-reconfigure
|
||||
....
|
||||
|
||||
This limitation exists because `parsecmgmt` generates the input files just before running via the Bash scripts, but we can't run `parsecmgmt` on gem5 as it is too slow!
|
||||
@@ -2272,7 +2349,7 @@ before going for the cross compile build.
|
||||
Don't forget to explicitly rebuild PARSEC with:
|
||||
+
|
||||
....
|
||||
./build -a arm -g -i br2_parsec parsec-benchmark-reconfigure
|
||||
./build -a arm -g -b br2_parsec parsec-benchmark-reconfigure
|
||||
....
|
||||
+
|
||||
You may also want to test if your patches are still functionally correct inside of QEMU first, which is a faster emulator.
|
||||
@@ -2627,7 +2704,7 @@ dmesg
|
||||
|
||||
We provide the following mechanisms:
|
||||
|
||||
* `./build -i br2_local`: append the file `br2_local` to a single build. Must be passed every time you run `./build`.
|
||||
* `./build -b br2_local`: append the file `br2_local` to a single build. Must be passed every time you run `./build`.
|
||||
+
|
||||
For convenience, we already gitignore `br2_local` for you.
|
||||
+
|
||||
|
||||
7
br2
7
br2
@@ -1,6 +1,11 @@
|
||||
# Custom packages
|
||||
BR2_PACKAGE_KERNEL_MODULE=y
|
||||
|
||||
# Rootfs
|
||||
BR2_TARGET_ROOTFS_CPIO=n
|
||||
BR2_TARGET_ROOTFS_EXT2=y
|
||||
BR2_TARGET_ROOTFS_INITRAMFS=n
|
||||
|
||||
BR2_CCACHE=y
|
||||
# Otherwise our precious debug would break!
|
||||
BR2_CCACHE_USE_BASEDIR=n
|
||||
@@ -19,8 +24,6 @@ BR2_ROOTFS_OVERLAY="../rootfs_overlay"
|
||||
BR2_ROOTFS_POST_BUILD_SCRIPT="../rootfs_post_build_script"
|
||||
BR2_ROOTFS_POST_IMAGE_SCRIPT="../rootfs_post_image_script"
|
||||
BR2_ROOTFS_USERS_TABLES="../user_table"
|
||||
BR2_TARGET_ROOTFS_CPIO=y
|
||||
BR2_TARGET_ROOTFS_EXT2=y
|
||||
BR2_TOOLCHAIN_BUILDROOT_CXX=y
|
||||
BR2_TOOLCHAIN_BUILDROOT_FORTRAN=y
|
||||
BR2_TOOLCHAIN_BUILDROOT_WCHAR=y
|
||||
|
||||
22
build
22
build
@@ -12,11 +12,14 @@ linux_kernel_custom_config_file=''
|
||||
post_script_args=''
|
||||
qemu_sdl='--enable-sdl --with-sdlabi=2.0'
|
||||
v=0
|
||||
while getopts 'a:c:Cgj:i:kK:lp:qS:v' OPT; do
|
||||
while getopts 'a:b:c:Cgj:IiKk:lp:qS:v' OPT; do
|
||||
case "$OPT" in
|
||||
a)
|
||||
arch="$OPTARG"
|
||||
;;
|
||||
b)
|
||||
config_fragments="$config_fragments $OPTARG"
|
||||
;;
|
||||
c)
|
||||
echo "$OPTARG" >> br2_cli
|
||||
;;
|
||||
@@ -26,11 +29,22 @@ while getopts 'a:c:Cgj:i:kK:lp:qS:v' OPT; do
|
||||
g)
|
||||
gem5=true
|
||||
;;
|
||||
j)
|
||||
j="$OPTARG"
|
||||
I)
|
||||
echo "
|
||||
BR2_TARGET_ROOTFS_CPIO=n
|
||||
BR2_TARGET_ROOTFS_EXT2=n
|
||||
BR2_TARGET_ROOTFS_INITRAMFS=y
|
||||
" >> br2_cli
|
||||
;;
|
||||
i)
|
||||
config_fragments="$config_fragments $OPTARG"
|
||||
echo "
|
||||
BR2_TARGET_ROOTFS_CPIO=y
|
||||
BR2_TARGET_ROOTFS_EXT2=n
|
||||
BR2_TARGET_ROOTFS_INITRAMFS=n
|
||||
" >> br2_cli
|
||||
;;
|
||||
j)
|
||||
echo "$OPTARG" >> br2_cli
|
||||
;;
|
||||
k)
|
||||
extra_make_args="$extra_make_args kernel_module-reconfigure"
|
||||
|
||||
82
run
82
run
@@ -19,8 +19,11 @@ gem5=false
|
||||
gem5opts=''
|
||||
lkmc_eval=''
|
||||
initrd=false
|
||||
initramfs=false
|
||||
memory=128M
|
||||
nographic=false
|
||||
root=''
|
||||
while getopts a:c:DdE:e:G:giKknt:x OPT; do
|
||||
while getopts a:c:DdE:e:G:gIiKkm:nt:x OPT; do
|
||||
case "$OPT" in
|
||||
a)
|
||||
arch="$OPTARG"
|
||||
@@ -29,7 +32,7 @@ while getopts a:c:DdE:e:G:giKknt:x OPT; do
|
||||
cpus="$OPTARG"
|
||||
;;
|
||||
d)
|
||||
extra_flags_qemu="$extra_flags -S -s"
|
||||
extra_flags_qemu="$extra_flags_qemu -S -s"
|
||||
;;
|
||||
D)
|
||||
debug_vm='gdb -q -ex start --args'
|
||||
@@ -47,7 +50,7 @@ while getopts a:c:DdE:e:G:giKknt:x OPT; do
|
||||
extra_append="$extra_append kgdbwait"
|
||||
# For those who want to try KDB.
|
||||
#extra_append="$extra_append kgdbwait kgdboc=kbd"
|
||||
extra_flags_qemu="$extra_flags -serial tcp::1234,server,nowait"
|
||||
extra_flags_qemu="$extra_flags_qemu -serial tcp::1234,server,nowait"
|
||||
kgdb=true
|
||||
;;
|
||||
g)
|
||||
@@ -56,12 +59,17 @@ while getopts a:c:DdE:e:G:giKknt:x OPT; do
|
||||
G)
|
||||
gem5opts="$OPTARG"
|
||||
;;
|
||||
I)
|
||||
initramfs=true
|
||||
;;
|
||||
i)
|
||||
initrd=true
|
||||
;;
|
||||
m)
|
||||
memory="$OPTARG"
|
||||
;;
|
||||
n)
|
||||
extra_append="$extra_append console=ttyS0"
|
||||
extra_flags_qemu="$extra_flags -nographic"
|
||||
nographic=true
|
||||
;;
|
||||
esac
|
||||
done
|
||||
@@ -75,12 +83,27 @@ root_dir="$(pwd)"
|
||||
buildroot_dir="${root_dir}/buildroot"
|
||||
out_dir="${root_dir}/buildroot/output.${arch_dir}~"
|
||||
images_dir="${out_dir}/images"
|
||||
if "$initrd" || "$initramfs"; then
|
||||
ramfs=true
|
||||
else
|
||||
ramfs=false
|
||||
fi
|
||||
if [ -n "$lkmc_eval" ]; then
|
||||
extra_append="$extra_append init=/eval_base64.sh - lkmc_eval=\"$(printf "$lkmc_eval" | base64)\""
|
||||
if "$ramfs"; then
|
||||
initarg="rdinit"
|
||||
else
|
||||
initarg="init"
|
||||
fi
|
||||
extra_append="${extra_append} ${initarg}=/eval_base64.sh - lkmc_eval=\"$(printf "$lkmc_eval" | base64)\""
|
||||
fi
|
||||
if "$nographic" && [ "$arch" = x86_64 ]; then
|
||||
extra_append="$extra_append console=ttyS0"
|
||||
extra_flags_qemu="$extra_flags_qemu -nographic"
|
||||
fi
|
||||
|
||||
if "$gem5"; then
|
||||
build_dir="${out_dir}/build/gem5-1.0"
|
||||
memory="${memory}B"
|
||||
gem5_dir="${build_dir}/gem5"
|
||||
if [ "$arch" = x86_64 ]; then
|
||||
gem5_arch=X86
|
||||
@@ -98,6 +121,7 @@ ${gem5opts} \
|
||||
--checkpoint-dir='${gem5_cpt_dir}' \
|
||||
--disk-image='${out_dir}/images/rootfs.ext2' \
|
||||
--kernel='${out_dir}/build/linux-custom/vmlinux' \
|
||||
--mem-size=${memory} \
|
||||
--num-cpus='${cpus}' \
|
||||
"
|
||||
if [ "$arch" = x86_64 ]; then
|
||||
@@ -109,11 +133,13 @@ ${gem5opts} \
|
||||
$extra_flags \
|
||||
"
|
||||
elif [ "$arch" = arm ] || [ "$arch" = aarch64 ]; then
|
||||
# TODO why is it mandatory to pass mem= here? Not true for QEMU.
|
||||
# Anything smaller than physical blows up as expected, but why can't it auto-detect the right value?
|
||||
cmd="${gem5_common} \
|
||||
--command-line='earlyprintk=pl011,0x1c090000 console=ttyAMA0 lpj=19988480 rw loglevel=8 mem=512MB root=/dev/sda $extra_append' \
|
||||
--command-line='earlyprintk=pl011,0x1c090000 console=ttyAMA0 lpj=19988480 rw loglevel=8 mem=${memory} root=/dev/sda $extra_append' \
|
||||
--dtb-file='${gem5_dir}/system/arm/dt/$([ "$arch" = arm ] && echo "armv7_gem5_v1_${cpus}cpu" || echo "armv8_gem5_v1_${cpus}cpu").dtb' \
|
||||
--machine-type=VExpress_GEM5_V1 \
|
||||
$extra_flags \
|
||||
${extra_flags} \
|
||||
"
|
||||
fi
|
||||
else
|
||||
@@ -125,7 +151,7 @@ else
|
||||
qemu_common="\
|
||||
${debug_vm} \
|
||||
'${out_dir}/host/usr/bin/qemu-system-${arch}' \
|
||||
-m 128M \
|
||||
-m ${memory} \
|
||||
-monitor telnet::45454,server,nowait \
|
||||
-netdev user,hostfwd=tcp::45455-:45455,id=net0 \
|
||||
-smp $cpus \
|
||||
@@ -139,15 +165,17 @@ ${debug_vm} \
|
||||
case "$arch" in
|
||||
x86_64)
|
||||
if "$kgdb"; then
|
||||
extra_append="$extra_append kgdboc=ttyS0,115200"
|
||||
extra_append="${extra_append} kgdboc=ttyS0,115200"
|
||||
fi
|
||||
if ! "$initrd"; then
|
||||
if "$ramfs"; then
|
||||
root='root=/dev/anything'
|
||||
else
|
||||
root='root=/dev/vda'
|
||||
extra_flags="$extra_flags -drive file='${images_dir}/rootfs.ext2.qcow2,if=virtio,format=qcow2'"
|
||||
extra_flags="${extra_flags} -drive file='${images_dir}/rootfs.ext2.qcow2,if=virtio,format=qcow2'"
|
||||
fi
|
||||
cmd="$qemu_common \
|
||||
cmd="${qemu_common} \
|
||||
-M pc \
|
||||
-append '$root nopat $extra_append' \
|
||||
-append '${root} nopat ${extra_append}' \
|
||||
-device edu \
|
||||
-device lkmc_pci_min \
|
||||
-device virtio-net-pci,netdev=net0 \
|
||||
@@ -157,15 +185,17 @@ ${extra_flags} \
|
||||
;;
|
||||
arm)
|
||||
if "$kgdb"; then
|
||||
extra_append="$extra_append kgdboc=ttyAMA0,115200"
|
||||
extra_append="${extra_append} kgdboc=ttyAMA0,115200"
|
||||
fi
|
||||
if ! "$initrd"; then
|
||||
if "$ramfs"; then
|
||||
root='root=/dev/anything'
|
||||
else
|
||||
extra_flags="${extra_flags} -drive file='${images_dir}/rootfs.ext2.qcow2,if=scsi,format=qcow2'"
|
||||
root='root=/dev/sda'
|
||||
extra_flags="$extra_flags -drive file='${images_dir}/rootfs.ext2.qcow2,if=scsi,format=qcow2'"
|
||||
fi
|
||||
cmd="$qemu_common \
|
||||
-M versatilepb \
|
||||
-append '$root $extra_append' \
|
||||
-append '${root} ${extra_append}' \
|
||||
-device rtl8139,netdev=net0 \
|
||||
-dtb '${images_dir}/versatile-pb.dtb' \
|
||||
-kernel '${images_dir}/zImage' \
|
||||
@@ -177,9 +207,15 @@ $extra_flags \
|
||||
if "$kgdb"; then
|
||||
extra_append="${extra_append} kgdboc=ttyAMA0,115200"
|
||||
fi
|
||||
if "$ramfs"; then
|
||||
root='root=/dev/anything'
|
||||
else
|
||||
root='root=/dev/vda'
|
||||
extra_flags="${extra_flags} -drive file='${images_dir}/rootfs.ext2.qcow2,if=virtio,format=qcow2'"
|
||||
fi
|
||||
cmd="${qemu_common} \
|
||||
-M virt \
|
||||
-append 'root=/dev/sda ${extra_append}' \
|
||||
-append '${root} ${extra_append}' \
|
||||
-cpu cortex-a57 \
|
||||
-device virtio-net-device,netdev=net0 \
|
||||
-kernel '${images_dir}/Image' \
|
||||
@@ -189,13 +225,15 @@ ${extra_flags} \
|
||||
"
|
||||
;;
|
||||
mips64)
|
||||
if ! "$initrd"; then
|
||||
if "$ramfs"; then
|
||||
root='root=/dev/anything'
|
||||
else
|
||||
root='root=/dev/hda'
|
||||
extra_flags="${extra_flags} -drive file='${images_dir}/rootfs.ext2.qcow2,format=qcow2'"
|
||||
fi
|
||||
cmd="$qemu_common \
|
||||
cmd="${qemu_common} \
|
||||
-M malta \
|
||||
-append 'root=/dev/hda ${extra_append}' \
|
||||
-append '${root} ${extra_append}' \
|
||||
-cpu I6400 \
|
||||
-device pcnet \
|
||||
-kernel '${images_dir}/vmlinux' \
|
||||
|
||||
Reference in New Issue
Block a user