blob: facd9d0718fbce929e4444b18681e8b3dfc7d173 [file] [log] [blame] [view]
# Hypervisor & guest tracing
## Hypervisor tracing
Starting with android14-5.15 kernel it is possible to get traces from the hypervisor.
### User space interface
The user space hypervisor tracing interface is located either at /sys/kernel/tracing/hyp or at
/sys/kernel/debug/tracing/hyp. On the Android phones it will usually be /sys/kernel/tracing/hyp,
while on QEMU it will be /sys/kernel/debug/tracing/hyp.
The user space interface is very similar to the ftrace user space interface, however there are some
differences, e.g.:
* Only boot clock is supported, and there is no way for user space to change the tracing_clock.
* Hypervisor tracing periodically polls the data from the hypervisor, this is different from the
regular ftrace instance which pushes the events into the ring buffer.
* Resetting ring buffers (by clearing the trace file) is only supported when there are no active
readers. If the trace file is cleared while there are active readers, then the ring buffers will
be cleared after the last reader disconnects.
* Changing the size of the ring buffer while the tracing session is active is also not supported.
Note: the list above is not exhaustive.
### Perfetto integration
[Perfetto](https://perfetto.dev/docs/) is an open-source stack for performance instrumentation and
trace analysis widely used in Android. Perfetto supports capturing and visualizing hypervisor
traces.
#### Capturing hypervisor traces on Android
Consider first familiarizing yourself with Perfetto documentation for recording traces on Android:
https://perfetto.dev/docs/quickstart/android-tracing.
The [record_android_trace](
https://cs.android.com/android/platform/superproject/+/master:external/perfetto/tools/record_android_trace)
script supports a shortcut to capture all hypervisor events that are known to Perfetto:
```shell
external/perfetto/tools/record_android_trace hyp -t 15s -b 32mb -o /tmp/hyp.pftrace
```
Alternatively you can use full trace config to capture hypervisor. Example usage:
```shell
cat<<EOF>config.pbtx
duration_ms: 10000
buffers: {
size_kb: 8960
fill_policy: DISCARD
}
data_sources: {
config {
name: "linux.ftrace"
ftrace_config {
instance_name: "hyp"
ftrace_events: "hyp/hyp_enter"
ftrace_events: "hyp/hyp_exit"
}
}
}
EOF
./record_android_trace -c config.pbtx -o trace_file.perfetto-trace
```
If you have an Android tree checked out, then record_android_trace helper script can be located at
${REPO_ROOT}/external/perfetto/tools/record_android_traces. Otherwise, you can download the script
by following steps outlined in the [Perfetto docs](
https://perfetto.dev/docs/quickstart/android-tracing#recording-a-trace-through-the-cmdline)
#### Capturing hypervisor traces on QEMU
Perfetto supports capturing traces on Linux: https://perfetto.dev/docs/quickstart/linux-tracing.
However, since pKVM hypervisor is only supported on arm64, you will need to cross-compile Perfetto
binaries for linux-arm64 (unless you have an arm64 workstation).
1. Checkout Perfetto repository: https://perfetto.dev/docs/contributing/getting-started
2. Follow https://perfetto.dev/docs/contributing/build-instructions#cross-compiling-for-linux-arm-64
to compile Perfetto binaries for arm64 architecture.
3. Copy the tracebox binary to QEMU
4. Run `tracebox` binary on QEMU to capture traces, it's interface is very similar to the
`record_android_trace` binary. E.g. to capture all hypervisor events run:
```shell
tracebox -t 15s -b 32mb hyp
```
### Analysing traces using SQL
On top of visualisation, Perfetto also provides a SQL interface to analyse traces. More
documentation is available at https://perfetto.dev/docs/quickstart/trace-analysis and
https://perfetto.dev/docs/analysis/trace-processor.
Hypervisor events can be queried via `pkvm_hypervisor_events` SQL view. You can load that view by
calling `SELECT IMPORT("pkvm.hypervisor");`, e.g.:
```sql
SELECT IMPORT("pkvm.hypervisor");
SELECT * FROM pkvm_hypervisor_events limit 5;
```
Below are some SQL queries that might be useful when analysing hypervisor traces.
**What is the longest time CPU spent in hypervisor, grouped by the reason to enter hypervisor**
```sql
SELECT IMPORT("pkvm.hypervisor");
SELECT
cpu,
reason,
ts,
dur
FROM pkvm_hypervisor_events
JOIN (
SELECT
MAX(dur) as dur2,
cpu as cpu2,
reason as reason2
FROM pkvm_hypervisor_events
GROUP BY 2, 3) AS sc
ON
cpu = sc.cpu2
AND dur = sc.dur2
AND (reason = sc.reason2 OR (reason IS NULL AND sc.reason2 IS NULL))
ORDER BY dur desc;
```
**What are the 10 longest times CPU spent in hypervisor because of host_mem_abort**
```sql
SELECT
hyp.dur as dur,
hyp.ts as ts,
EXTRACT_ARG(slices.arg_set_id, 'esr') as esr,
EXTRACT_ARG(slices.arg_set_id, 'addr') as addr
FROM pkvm_hypervisor_events as hyp
JOIN slices
ON hyp.slice_id = slices.id
WHERE hyp.reason = 'host_mem_abort'
ORDER BY dur desc
LIMIT 10;
```
## Microdroid VM tracing
IMPORTANT: Tracing is only supported for debuggable Microdroid VMs.
### Capturing trace in Microdroid
Starting with Android U, Microdroid contains Perfetto tracing binaries, which makes it possible to
capture traces inside Microdroid VM using Perfetto stack. The commands used to capture traces on
Android should work for Microdroid VM as well, with a difference that Perfetto's tracing binaries
are not enabled in Microdroid by default, so you need to manually start them by setting
`persist.traced.enable` system property to `1`.
Here is a quick example on how trace Microdroid VM:
1. First start your VM. For this example we are going to use
`adb shell /apex/com.android.virt/bin/vm run-microdroid`.
2. Set up an adb connection with the running VM:
```shell
adb shell forward tcp:9876 vsock:${CID}:5555
adb connect localhost:9876
adb -s localhost:9876 root
```
Where `${CID}` corresponds to the running Microdroid VM that you want to establish adb connection
with. List of running VMs can be obtained by running `adb shell /apex/com.android.virt/bin/vm list`.
Alternatively you can use `vm_shell` utility to connect to a running VM, i.e.: `vm_shell connect`.
3. Start Perfetto daemons and capture trace
```shell
adb -s localhost:9876 shell setprop persist.traced.enable 1
${ANDROID_BULD_TOP}/external/perfetto/tools/record_android_trace \
-s localhost:9876 \
-o /tmp/microdroid-trace-file.pftrace \
-t 10s \
-b 32mb \
sched/sched_switch task/task_newtask sched/sched_process_exit
```
If you don't have Android repo checked out, then you can download the record_android_trace script by
following the following [instructions](
https://perfetto.dev/docs/quickstart/android-tracing#recording-a-trace-through-the-cmdline)
More documentation on Perfetto's tracing on Android is available here:
https://perfetto.dev/docs/quickstart/android-tracing
### Capturing Microdroid boot trace
TODO(b/271412868): Stay tuned, more docs are coming soon!