docker: crate docker host setup

readme: standardize keyboard input notation to the format: Ctrl-C
This commit is contained in:
Ciro Santilli
2018-04-07 20:47:20 +01:00
parent ecf2f3b29e
commit 294a8c2424
7 changed files with 215 additions and 53 deletions

1
.gitignore vendored
View File

@@ -8,3 +8,4 @@ gitignore*
# Specific files.
/data
/out
/out.*

View File

@@ -15,6 +15,10 @@ toc::[]
== Getting started
=== Getting started Ubuntu
This is the most native setup, and therefore the best one if you are on one of the supported Ubuntu: 16.04 or 17.10. We will try to keep up with both the latest LTS and release.
Reserve 12Gb of disk and run:
....
@@ -51,6 +55,113 @@ image:screenshot.png[image]
All available modules can be found in the link:kernel_module/[`kernel_module` directory].
[[docker]]
=== Getting started Docker
This is a good option if you are on a Linux host, but the <<getting-started-ubuntu,native build>> failed due to your weird host distribution.
Note however that most things in this repository are highly Linux-portable, should just work once you have found the corresponding `apt-get` package manager commands in the link:configure[] for your distro. In theory :-)
Before anything, you must get ride of any host build files on `out/` if you have any. A simple way to do this it to:
....
mv out out.host
....
A cleaner option is to make a separate clone of this repository just for Docker, although this will require another submodule update.
Then install Docker, e.g. on Ubuntu:
....
sudo apt-get install docker
....
The very first time you launch Docker, create the container with:
....
./rundocker setup
....
You are now left inside a shell in the Docker guest.
From there, run the exact same commands that you would on a native install: <<getting-started>>
The host git top level directory is mounted inside the guest, which means for example that you can use your host's GUI text editor directly on the files.
Just don't forget that if you nuke that directory on the guest, then it gets nuked on the host as well!
Trying to run the output from Docker from host won't however, I think the main reason is that the absolute paths inside Docker are will be different than the host ones, but even if we fix that there will likely be other problems.
TODO make files created inside Docker be owned by the current user in host instead of `root`: https://stackoverflow.com/questions/23544282/what-is-the-best-way-to-manage-permissions-for-docker-shared-volumes
Quit and stop the container:
....
Ctrl-D
....
Restart the container:
....
./rundocker
....
Open a second shell in a running container:
....
./rundocker sh
....
You will need this for example to use <<gdb>>.
Start a second shell, and run a command in it at the same time:
....
./rundocker sh ./rungdb start_kernel
....
Docker stops if and only if you quit the initial shell, you can quit this one without consequences.
If you mistakenly run `./rundocker` twice, it opens two mirrored terminals. To quit one of them do link:https://stackoverflow.com/questions/19688314/how-do-you-attach-and-detach-from-dockers-process[]:
....
Ctrl-P Ctrl-Q
....
To use <<graphic-mode>> from Docker:
....
./run -Vx
....
and then on host:
....
sudo apt-get install vinagre
./vnc
....
Destroy the docker container:
....
./rundocker DELETE
....
Since we mount the guest's working directory on the host git top-level, you will likely not lose data from doing this, just the `apt-get` installs.
To get back to a host build, don't forget to clean up `out/` again:
....
mv out out.docker
mv out.host out
....
After this, to start using Docker again will you need another:
....
./rundocker setup
....
=== Module documentation
....
@@ -181,7 +292,7 @@ sync
also saves the disk.
This is particularly useful to re-run shell commands from the history of a previous session with `Ctrl + R`.
This is particularly useful to re-run shell commands from the history of a previous session with `Ctrl-R`.
However, when you do:
@@ -205,10 +316,10 @@ dmesg -n 1
See also: https://superuser.com/questions/351387/how-to-stop-kernel-messages-from-flooding-my-console
When in <<text-mode,graphical mode>>, you can scroll up a bit on the default TTY with:
When in <<graphic-mode>>, you can scroll up a bit on the default TTY with:
....
Shift + PgUp
Shift-PgUp
....
but I never managed to increase that buffer:
@@ -218,7 +329,7 @@ but I never managed to increase that buffer:
The superior alternative is to use text mode or a telnet connection.
=== Text mode
=== Graphic mode
By default, we show the serial console directly on the current terminal, without opening a QEMU window.
@@ -243,7 +354,7 @@ Text mode has the following limitations over graphics mode:
Both good and bad:
* Ctrl + C kills the host emulator instead of sending SIGINT to the guest process.
* `Ctrl-C` kills the host emulator instead of sending SIGINT to the guest process.
+
On one hand, this provides an easy way to quit QEMU.
+
@@ -273,7 +384,7 @@ I think the problem was reversed in older QEMU versions: https://superuser.com/q
+
`sendkey sendkey ctrl-c` does not work on the text terminal either.
+
This is however fortunate when running QEMU with GDB, as the Ctrl + C reaches GDB and breaks.
This is however fortunate when running QEMU with GDB, as the `Ctrl-C` reaches GDB and breaks.
* Not everything generates interrupts, only the final enter.
+
This makes things a bit more reproducible, since the microsecond in which you pressed a key does not matter.
@@ -482,7 +593,7 @@ which counts to infinity to stdout. Then in another shell, run:
and then hit:
....
Ctrl + C
Ctrl-C
break sys_write
continue
continue
@@ -491,7 +602,7 @@ continue
And you now control the counting on the first shell from GDB!
When you hit `Ctrl + C`, if we happen to be inside kernel code at that point, which is very likely if there are no heavy background tasks waiting, and we are just waiting on a `sleep` type system call of the command prompt, we can already see the source for the random place inside the kernel where we stopped.
When you hit `Ctrl-C`, if we happen to be inside kernel code at that point, which is very likely if there are no heavy background tasks waiting, and we are just waiting on a `sleep` type system call of the command prompt, we can already see the source for the random place inside the kernel where we stopped.
=== tmux multi terminal
@@ -529,7 +640,7 @@ Shell 2:
./rungdb
....
In GDB, hit `Ctrl + C`, and note how it says:
In GDB, hit `Ctrl-C`, and note how it says:
....
scanning for modules in /home/ciro/bak/git/linux-kernel-module-cheat/out/x86_64/buildroot/build/linux-custom
@@ -577,7 +688,7 @@ fops 2327 0 - Live 0xfffffffa00000000
And then tell GDB where the module was loaded with:
....
Ctrl + C
Ctrl-C
add-symbol-file ../kernel_module-1.0/fops.ko 0xfffffffa00000000
....
@@ -716,7 +827,7 @@ The problem is that the `b main` that we do inside `./rungdb-user` says:
Cannot access memory at address 0x107b8
....
However, if we do a Ctrl + C, and then a direct:
However, if we do a `Ctrl-C`, and then a direct:
....
b *0x107b8
@@ -991,7 +1102,7 @@ https://stackoverflow.com/questions/31990487/how-to-cleanly-exit-qemu-after-exec
reboot: System halted
....
A blunt resolution for QEMU is to do a `Ctrl + c` on host, or run on a nother shell:
A blunt resolution for QEMU is to do a `Ctrl-C` on host, or run on a nother shell:
....
pkill qemu
@@ -1554,9 +1665,9 @@ You should then look up if there is a branch that supports that kernel. Staying
=== Console fun
You can also try those on the Ctrl + Alt + F3 of your Ubuntu host, but it is much more fun inside a VM!
You can also try those on the `Ctrl-Alt-F3` of your Ubuntu host, but it is much more fun inside a VM!
Must be run in <<text-mode,graphical mode>>.
Must be run in <<graphic-mode>>.
Stop the cursor from blinking:
@@ -1778,7 +1889,7 @@ grep -n 4003a0 trace.txt
....
+
I have observed a single match for that instruction, so it must be the init, and there were only 20k instructions after it, so the impact is negligible.
* on arm, you need to hit `Ctrl + C` once after seeing the message `reboot: System halted` due to <<arm-shutdown>>
* on arm, you need to hit `Ctrl-C` once after seeing the message `reboot: System halted` due to <<arm-shutdown>>
* to disable networking. Is replacing `init` enough?
+
--
@@ -1801,7 +1912,7 @@ Maybe some brave should will send a pull request one day.
Let's have some fun.
Those only work in <<text-mode,graphical mode>>.
Those only work in <<graphic-mode>>.
I think most are implemented under:
@@ -1814,8 +1925,8 @@ TODO find all.
Scroll up / down the terminal:
....
Shift + PgDown
Shift + PgUp
Shift-PgDown
Shift-PgUp
....
Or inside `./qemumonitor`:
@@ -1866,7 +1977,7 @@ console::respawn:/sbin/getty -n -L -l /loginroot.sh ttyS1 0 vt100
but nothing changed.
Note that on Ubuntu 17.10, to get to the text terminal from the GUI we first need `Ctrl + Alt + Fx`, and once in the text terminals, `Alt + Fn` works without `Ctrl`.
Note that on Ubuntu 17.10, to get to the text terminal from the GUI we first need `Ctrl-Alt-Fx`, and once in the text terminals, `Alt-Fn` works without `Ctrl`.
== QEMU
@@ -2189,7 +2300,7 @@ And in QEMU:
/pci.sh
....
Just make sure that you never click inside the QEMU window when doing that, otherwise you mouse gets captured forever, and the only solution I can find is to go to a TTY with Ctrl + Alt + F1 and `kill` QEMU.
Just make sure that you never click inside the QEMU window when doing that, otherwise you mouse gets captured forever, and the only solution I can find is to go to a TTY with `Ctrl-Alt-F1` and `kill` QEMU.
You can still send key presses to QEMU however even without the mouse capture, just either click on the title bar, or alt tab to give it focus.
@@ -2320,8 +2431,8 @@ Sometimes in Ubuntu 14.04, after the QEMU SDL GUI starts, it does not get update
We have not managed to track this problem down yet, but the following workaround always works:
....
Ctrl + Shift + U
Ctrl + C
Ctrl-Shift-U
Ctrl-C
root
....
@@ -2929,7 +3040,7 @@ On a third shell:
./gem5-shell
....
When you want to break, just do a Ctrl + C on GDB shell, and then `continue`.
When you want to break, just do a `Ctrl-C` on GDB shell, and then `continue`.
And we now see the boot messages, and then get a shell. Now try the `/continue.sh` procedure described for QEMU.
@@ -3751,7 +3862,7 @@ time 376.03
insts 634548425
....
For ARM `arm` QEMU, we just try to manually hit Ctrl + C as soon as system shutdown message appears: <<arm-shutdown>>.
For ARM `arm` QEMU, we just try to manually hit `Ctrl-C` as soon as system shutdown message appears: <<arm-shutdown>>.
The results on the <<p51>> were:

76
configure vendored
View File

@@ -18,42 +18,23 @@ while getopts gpqt OPT; do
;;
t)
interactive_pkgs=
y='-y'
y=-y
;;
esac
done
shift $(($OPTIND - 1))
## Submodules
if "$qemu"; then
submodules="$submodules qemu"
fi
if "$gem5"; then
submodules="$submodules gem5/gem5"
fi
(
set -e
# Shallow cloning saves a considerable amount of time, specially because of the linux kernel.
# However, git submodules are buggy as usual, and this is the best way I've found to get it done:
# https://stackoverflow.com/questions/2144406/git-shallow-submodules/47374702#47374702
# In particular:
# - `shallow = true` on the submodule has no effect for the non default educational branches of our submodules
# - QEMU's submodules point to commits that are neither under branches nor tags, and so `--shallow-submodules` fails
git submodule update --depth 1 --jobs 4 --init -- $submodules
if "$qemu"; then
cd qemu
git submodule update --init
fi
) &
wait $! || git submodule update --init -- $submodules
## apt-get
pkgs="\
automake \
bc \
build-essential \
coreutils \
cpio \
git \
unzip \
wget \
"
if "$gem5"; then
pkgs="$pkgs \
@@ -61,6 +42,8 @@ gcc-aarch64-linux-gnu \
gcc-arm-linux-gnueabi \
libgoogle-perftools-dev \
protobuf-compiler \
python-dev \
scons \
"
fi
command -v apt-get >/dev/null 2>&1 || {
@@ -78,16 +61,53 @@ EOF
# Makefile:932: *** "Cannot generate ORC metadata for CONFIG_UNWINDER_ORC=y, please install libelf-dev, libelf-devel or elfutils-libelf-devel". Stop.
pkgs="$pkgs libelf-dev"
sudo apt-get update $y
# https://stackoverflow.com/questions/20010199/determining-if-a-process-runs-inside-lxc-docker
if [ -f /.dockerenv ]; then
# --jobs is not available in git 2.7.4 from Ubuntu 16.04.
gitjobs=
mysudo=
# https://askubuntu.com/questions/496549/error-you-must-put-some-source-uris-in-your-sources-list
sed -Ei 's/^# deb-src/deb-src/' /etc/apt/sources.list
y=-y
else
gitjobs="--jobs $(nproc)"
mysudo=sudo
fi
$mysudo apt-get update $y
# Building SDL for QEMU in Buildroot was rejected upstream because it adds many dependencies:
# https://patchwork.ozlabs.org/patch/770684/
# We are just using the host SDL for now, if it causes too much problems we might remove it.
# libsdl2-dev needs to be installed separatedly from sudo apt-get build-dep qemu
# because Ubuntu 16.04's QEMU uses SDL 1.
sudo apt-get install $y \
$mysudo apt-get install $y \
$pkgs \
$interactive_pkgs \
;
if "$qemu"; then
sudo apt-get build-dep $y qemu
$mysudo apt-get build-dep $y qemu
fi
## Submodules
if "$qemu"; then
submodules="$submodules qemu"
fi
if "$gem5"; then
submodules="$submodules gem5/gem5"
fi
(
set -e
# Shallow cloning saves a considerable amount of time, specially because of the linux kernel.
# However, git submodules are buggy as usual, and this is the best way I've found to get it done:
# https://stackoverflow.com/questions/2144406/git-shallow-submodules/47374702#47374702
# In particular:
# - `shallow = true` on the submodule has no effect for the non default educational branches of our submodules
# - QEMU's submodules point to commits that are neither under branches nor tags, and so `--shallow-submodules` fails
#
git submodule update --depth 1 $gitjobs --init -- $submodules
if "$qemu"; then
cd qemu
git submodule update --init
fi
) &
wait $! || git submodule update --init -- $submodules

7
run
View File

@@ -28,7 +28,8 @@ root=
# A dummy value that is already turned on by default and does not produce large output,
# just to prevent QEMU from emitting a warning that '' is not valid.
trace_enable=pr_manager_run
while getopts a:c:DdE:e:f:G:ghIiKkm:T:x OPT; do
vnc=
while getopts a:c:DdE:e:f:G:ghIiKkm:T:Vx OPT; do
case "$OPT" in
a)
arch="$OPTARG"
@@ -87,6 +88,9 @@ while getopts a:c:DdE:e:f:G:ghIiKkm:T:x OPT; do
x)
nographic=false
;;
V)
vnc='-vnc :0'
;;
?)
exit 2
;;
@@ -180,6 +184,7 @@ ${debug_vm} \
-trace 'enable=${trace_enable},file=${qemu_out_dir}/trace.bin' \
-virtfs 'local,path=${p9_dir},mount_tag=host_scratch,security_model=mapped,id=host_scratch' \
-virtfs 'local,path=${buildroot_out_dir}/build,mount_tag=host_out,security_model=mapped,id=host_out' \
$vnc \
"
if "$initrd"; then
extra_flags="${extra_flags} -initrd '${images_dir}/rootfs.cpio'"

View File

@@ -43,5 +43,7 @@
some by default, e.g. `pr_manager_run`, and I don't know how to
get rid of them. But those events are rare and should not impact
performance, so we just ignore them for now.
|`-V` | |Run QEMU with VNC instead of the default SDL.
Connect to it with: `vinagre localhost:5900`.
|`-x` | |Run in graphic mode. Mnemonic: X11.
|===

21
rundocker Executable file
View File

@@ -0,0 +1,21 @@
#!/usr/bin/env bash
set -eu
cmd="${1:-start}"
shift
container_name=lkmc
target_dir=/root/linux-kernel-module-cheat
if [ "$cmd" = start ]; then
sudo docker start -ai "$container_name"
elif [ "$cmd" = sh ]; then
# https://stackoverflow.com/questions/39794509/how-to-open-multiple-terminals-in-docker
sudo docker exec -it "$container_name" bash "$@"
elif [ "$cmd" = setup ]; then
# --privileged for KVM:
# https://stackoverflow.com/questions/48422001/launching-qemu-kvm-from-inside-docker-container
sudo docker run --name "$container_name" --net host -i --privileged -t -w "${target_dir}" -v "$(pwd):${target_dir}" ubuntu:16.04 bash
elif [ "$cmd" = DELETE ]; then
sudo docker rm "$container_name"
else
echo "error: unknown action: ${cmd}" 1>&2
exit 2
fi

2
vnc Executable file
View File

@@ -0,0 +1,2 @@
#!/usr/bin/env bash
vinagre localhost:5900