This commit adds the debug-console (or debugcon) device to CHV. It is a very simple device on I/O port 0xe9 supported by QEMU and BOCHS. It is meant for printing information as easy as possible, without any necessary configuration from the guest at all. It is primarily interesting to OS/kernel and firmware developers as they can produce output as soon as the guest starts without any configuration of a serial device or similar. Furthermore, a kernel hacker might use this device for information of type B whereas information of type A are printed to the serial device. This device is not used by default by Linux, Windows, or any other "real" OS, but only by toy kernels and during firmware development. In the CLI, it can be configured similar to --console or --serial with the --debug-console parameter. Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
3.7 KiB
cloud-hypervisor
debug IO ports
When running x86 guests, cloud-hypervisor
provides different kinds of debug ports:
0x80
debug port- Debug console (by default at
0xe9
). - Firmware debug port at
0x402
.
All of them can be used to trace user-defined guest events and all of them can be used simultaneously.
Debug Ports Overview
0x80
I/O port
Whenever the guest write one byte between 0x0
and 0xF
on this particular
I/O port, cloud-hypervisor
will log and timestamp that event at the debug
log level.
It is up to the guest stack to decide when and what to write to the 0x80 port
in order to signal the host about specific events and have cloud-hypervisor
log it.
cloud-hypervisor
defines several debug port code ranges that should be used
for debugging specific components of the guest software stack. When logging a
write of one of those codes to the debug port, cloud-hypervisor
adds a
pre-defined string to the logs.
Code Range | Component | Log string |
---|---|---|
0x00 to 0x1f |
Firmware | Firmware |
0x20 to 0x3f |
Bootloader | Bootloader |
0x40 to 0x5f |
Kernel | Kernel |
0x60 to 0x7f |
Userspace | Userspace |
0x80 to 0xff |
Custom | Custom |
One typical use case is guest boot time measurement and tracing. By writing
different values to the debug I/O port at different boot process steps, the
guest will have cloud-hypervisor
generate timestamped logs of all those steps.
That provides a basic but convenient way of measuring not only the overall guest
boot time but all intermediate steps as well.
Logging
Assuming parts of the guest software stack have been instrumented to use the
cloud-hypervisor
debug I/O port, we may want to gather the related logs.
To do so we need to start cloud-hypervisor
with the right debug level
(-vvv
). It is also recommended to have it log into a dedicated file in order
to easily grep for the tracing logs (e.g.
--log-file /tmp/cloud-hypervisor.log
):
./target/debug/cloud-hypervisor \
--kernel ~/rust-hypervisor-firmware/target/target/release/hypervisor-fw \
--disk path=~/hypervisor/images/focal-server-cloudimg-amd64.raw \
--cpus 4 \
--memory size=1024M \
--rng \
--log-file /tmp/ch-fw.log \
-vvv
After booting the guest, we then have to grep for the debug I/O port traces in the log file:
$ grep "Debug I/O port" /tmp/ch-fw.log
cloud-hypervisor: 19.762449ms: DEBUG:vmm/src/vm.rs:510 -- [Debug I/O port: Firmware code 0x0] 0.019004 seconds
cloud-hypervisor: 403.499628ms: DEBUG:vmm/src/vm.rs:510 -- [Debug I/O port: Firmware code 0x1] 0.402744 seconds
Debug console port
The debug console is inspired by QEMU and Bochs, which have a similar feature.
By default, the I/O port 0xe9
is used. This port can be configured like a
console. Thus, it can print to a tty, a file, or a pty, for example.
Firmware debug port
The firmware debug port is also a simple port that prints all bytes written to it. The firmware debug port only prints to stdout.
When do I need these ports?
The ports are on the one hand interesting for firmware or kernel developers, as they provide an easy way to print debug information from within a guest. Furthermore, you can patch "normal" software to measure certain events, such as the boot time of a guest.
Which port should I choose?
The 0x80
debug port and the port of the firmware debug device are always
available. The debug console must be activated via the command line, but
provides more configuration options.
You can use different ports for different aspect of your logging messages.