xref: /cloud-hypervisor/docs/debug-port.md (revision 3f8cd52ffd74627242cb7e8ea1c2bdedadf6741a)
1# `cloud-hypervisor` debug IO ports
2
3When running x86 guests, `cloud-hypervisor` provides different kinds of debug ports:
4- [`0x80` debug port](https://www.intel.com/content/www/us/en/support/articles/000005500/boards-and-kits.html)
5- Debug console (by default at `0xe9`).
6- Firmware debug port at `0x402`.
7
8All of them can be used to trace user-defined guest events and all of them can
9be used simultaneously.
10
11## Debug Ports Overview
12
13### `0x80` I/O port
14
15Whenever the guest write one byte between `0x0` and `0xF` on this particular
16I/O port, `cloud-hypervisor` will log and timestamp that event at the `debug`
17log level.
18
19It is up to the guest stack to decide when and what to write to the 0x80 port
20in order to signal the host about specific events and have `cloud-hypervisor`
21log it.
22
23`cloud-hypervisor` defines several debug port code ranges that should be used
24for debugging specific components of the guest software stack. When logging a
25write of one of those codes to the debug port, `cloud-hypervisor` adds a
26pre-defined string to the logs.
27
28| Code Range       | Component   | Log string   |
29| ---------------- | ----------- | ------------ |
30| `0x00` to `0x1f` | Firmware    | `Firmware`   |
31| `0x20` to `0x3f` | Bootloader  | `Bootloader` |
32| `0x40` to `0x5f` | Kernel      | `Kernel`     |
33| `0x60` to `0x7f` | Userspace   | `Userspace`  |
34| `0x80` to `0xff` | Custom      | `Custom`     |
35
36One typical use case is guest boot time measurement and tracing. By writing
37different values to the debug I/O port at different boot process steps, the
38guest will have `cloud-hypervisor` generate timestamped logs of all those steps.
39That provides a basic but convenient way of measuring not only the overall guest
40boot time but all intermediate steps as well.
41
42#### Logging
43
44Assuming parts of the guest software stack have been instrumented to use the
45`cloud-hypervisor` debug I/O port, we may want to gather the related logs.
46
47To do so we need to start `cloud-hypervisor` with the right debug level
48(`-vvv`). It is also recommended to have it log into a dedicated file in order
49to easily grep for the tracing logs (e.g.
50`--log-file /tmp/cloud-hypervisor.log`):
51
52```
53./target/debug/cloud-hypervisor \
54    --kernel ~/rust-hypervisor-firmware/target/target/release/hypervisor-fw \
55    --disk path=~/hypervisor/images/focal-server-cloudimg-amd64.raw \
56    --cpus 4 \
57    --memory size=1024M \
58    --rng \
59    --log-file /tmp/ch-fw.log \
60    -vvv
61```
62
63After booting the guest, we then have to grep for the debug I/O port traces in
64the log file:
65
66```Shell
67$ grep "Debug I/O port" /tmp/ch-fw.log
68cloud-hypervisor: 19.762449ms: DEBUG:vmm/src/vm.rs:510 -- [Debug I/O port: Firmware code 0x0] 0.019004 seconds
69cloud-hypervisor: 403.499628ms: DEBUG:vmm/src/vm.rs:510 -- [Debug I/O port: Firmware code 0x1] 0.402744 seconds
70```
71
72### Debug console port
73
74The debug console is inspired by QEMU and Bochs, which have a similar feature.
75By default, the I/O port `0xe9` is used. This port can be configured like a
76console. Thus, it can print to a tty, a file, or a pty, for example.
77
78### Firmware debug port
79
80The firmware debug port is also a simple port that prints all bytes written to
81it. The firmware debug port only prints to stdout.
82
83## When do I need these ports?
84
85The ports are on the one hand interesting for firmware or kernel developers, as
86they provide an easy way to print debug information from within a guest.
87Furthermore, you can patch "normal" software to measure certain events, such as
88the boot time of a guest.
89
90## Which port should I choose?
91
92The `0x80` debug port and the port of the firmware debug device are always
93available. The debug console must be activated via the command line, but
94provides more configuration options.
95
96You can use different ports for different aspect of your logging messages.