|
StuBS
|
All necessary tools required for the exercises (and thus for the development of StuBS) are installed in our BOSS CIP Pool (all computers starting with oscip) for which we have created accounts for you.
Of course you can also work on the assignments at home, we therefore recommend using an up-to-date Linux. Below are some hints on how to configure your Linux system accordingly.
In addition, the script setup-env.sh will help you checking the requirements and setting up a passwordless SSH connection for working at home.
To build StuBS, the C++ source files are compiled using g++ from a current GCC (version > 7) as specified in the Makefile, however The LLVM C++ compiler clang++ can be used as well. Startup code and hardware-related subprograms written in assembly are translated using the Netwide Assembler (nasm). The x86 emulator Qemu is suitable for preliminary testing and, thanks to a built-in debug stub, also for debugging with the GNU Debugger (gdb).
herzog@oscip00:~/stubs> make help
MAKEFILE for the teaching operating system StuBS
--------------------------------------------------
Executing 'make' will compile the operating system from source.
All targets exist in different flavours in addition to <name>:
<name>-noopt, <name>-opt, <name>-dbg, and <name>-verbose.
Targets suffixed with -noopt are compiled without optimizations,
-opt targets produce a highly optimized binary, while
-dbg targets only use optimizations not hindering debugging.
Targets suffixed with -verbose generate binaries including
verbose output (via DBG_VERBOSE), making such targets useful for
debugging.
To get a verbose make output, clear VERBOSE, e.g. make VERBOSE=.
The following targets are available (each target can be suffixed
by -noopt and -verbose):
all Builds StuBS, generating an ELF binary
qemu Starts StuBS in QEMU
Due to the internal design of QEMU, some things
(especially race conditions) might behave
different compared to hardware!
qemu-gdb Starts StuBS in QEMU with internal GDB stub and
attaches it to a GDB session allowing step-by-step
debugging
kvm Starts StuBS in KVM, a hardware-accelerated
virtual machine
kvm-gdb Same as qemu-gdb, but with hardware acceleration
iso Generates a bootable system image
(File: .build/stubs.iso)
qemu-iso Starts the system in QEMU by booting from the
virtual CD drive
kvm-iso Same as qemu-iso, but with hardware acceleration
usb Generates a bootable USB mass-storage device;
the environment variable USBDEV should point
to the USB device
cd Generates a bootable CD; the environment variable
should point to the CD writer
lint Checks the coding style using CPPLINT
tidy Uses Clang Tidy for a static code analysis
netboot Copies StuBS to the network share, allowing
the test systems to boot your system
The fastest and easiest way to test your implementation is to run your system image in Qemu with hardware virtualization:
herzog@oscip00:~/stubs> make kvm
The QEMU target will by default emulate a system with four cores. Only the acceleration provided with the KVM extension will makes your system run really parallel on multiple cores. Hence, this is quite close to the test on real hardware in terms of race conditions and faulty synchronization.
To test your operating system on the reference hardware in our lab, just use the Makefile target netboot:
student@laptop:~/stubs> make netboot
This will compile your StuBS and copy the system image to the TFTP server so that the test hardware can boot your kernel. The test hardware automatically boot from the network when they are switched on. In the boot menu that appears, you only have to select the current semester and then the entry with your group name to boot your kernel. The reference system will always boot the kernel uploaded by the most recent make netboot call of any group member.
If you are not in the CIP right now, you can still access the hardware via the web interface (System A and System B). The web interface can only be accessed with the unversity network (either locally or via RUB VPN).
The systems can also by power-cycled using the web interface
Please shut down the machine if your done with testing. If another kernel is currently running, then another group is currently testing. Either use the other test system or please wait until the other group is done testing.
The web interface allows you to view the contents of the screen and interact with your operating system using keyboard and mouse.
If you have setup a passwordless SSH login (using a key) on the CIP computers, you can even use the Makefile target netboot from your private PC.
herzog@oscip00:~/stubs> make qemu-gdb-dbg
If you get stuck with simple printf debugging, you can use the debug stub integrated in Qemu and connect a debugger (e.g., gdb) to the emulation. This allows you to easily run your operating system code step by step, easing the detection of the reason for crashes or unwanted behavior. For this purpose the Makefile provides the targets qemu-gdb and kvm-gdb (which can be appended with -dbg for a debug build):
herzog@oscip00:~/stubs> make qemu-gdb
In this configuration, the Qemu debug stub waits in the emulator for a socket connection through which a gdb debugger can connect. The debugger will automatically be started so that the gdb prompt appears in the terminal immediately after Qemu is started.
(gdb) help <command>
A full overview of gdb is given in Debugging with GDB.
With the command make qemu-wait qemu can be started in a halted state. qemu won't start the simulation before it receives an continue command from a connected monitor.
This can be used to attach either gdb or another debugger (possibly integrated into the editor or IDE) manually. Otherwise make dbg can be used to attach to the running qemu. In addition to make qemu-wait the KVM variant can be executed using make kvm-wait.
If the DISPLAY environment variable of the current session is not set (as is the case for most SSH sessions), qemu will be executed with a ncurses interface for its VGA output. However this will occupy the whole (pseudo) terminal. Thus it is advisable to use a terminal mutliplexer (such as screen or tmux) to have the option to have access to another shell. The shell may either be used to remote control qemu by attaching a gdb, or to kill a rouge kernel if no monitor is attached (pkill qemu).
Then the commands make qemu-wait and make dbg can be issued from two separate PTS to have both visual output of the kernel, and an active debugger.
There are stubs-specific gdb extensions at tools/gdb/ which are loaded whenever the debugger is invoked via the provided Makefile. The scripts communicate with qemu via the monitor interface, exposed by GDBs python API. Currently the following commands are available:
gdtview: gdtview <base> <limit>
If no arguments are provided, the function displays the current global descriptor table stored at the current core. Optional parameters define the base of the GDT (linear address) and its 16-bit limit.
idtview: idtview [<base> <limit>]
If no arguments are provided, the function displays the current interrupt descriptor table stored at the current core. Otherwise it is possible to select the IDTs base and length manually.
vaview: vaview [<cr3>] <virtual address>
The command expects at least one virtual address, for which the table walk will be performed based on the current cores cr3 register value. It displays the different indices into the page tables, the address of the page tables and their content. The resolved mapping is displayed as well. Optionally it is possible to use any other value as PML4 base by setting the address as first parameter, followed by the virtual address.
$current(): list the currently running struct Thread *
Fetches the currently running thread from the Dispatcher. This only works if the students use the same Dispatcher structure, that is used in this repository.
These $current() function can be combined with other commands. For example vaview $current()->mapping $rsp could be used to check if the stack pointer of the current thread points to valid memory with the correct access permissions (if Thread::mapping would be a cr3 value).