pid_fmt is unset in per-thread mode because we don't need PIDs, so we can't use it as a hint to determine which EL the host is running at. That results in falling though to the next part where EL1 is treated as guest, which is wrong for nVHE.
Fix it by only returning a guest machine when run from perf kvm where a guest image would be provided, which matches existing behavior in other parts of Perf. The exception is when pid_fmt shows that the host is running at EL2 (VHE). Then EL1 is always a guest, so keep using the guest machine rather than decoding guest trace with the host kernel maps.
Reviewed-by: Leo Yan leo.yan@arm.com Signed-off-by: James Clark james.clark@linaro.org --- tools/perf/util/cs-etm.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c index c8a6a6e4c7d3..509ec014b276 100644 --- a/tools/perf/util/cs-etm.c +++ b/tools/perf/util/cs-etm.c @@ -1102,6 +1102,20 @@ static struct machine *cs_etm__get_machine(struct cs_etm_queue *etmq, if (pid_fmt == CS_ETM_PIDFMT_CTXTID) return &etmq->etm->session->machines.host;
+ /* + * If guest processing hasn't been enabled, also assume everything is + * the host, unless the host is known to be running at EL2 (VHE). + * + * This matches Perf's guest handling in machines__find_for_cpumode() + * etc where guest machines are only created and used when perf_guest is + * set. This also guards against accidentally using guest machines when + * pid_fmt can't be used as a hint (per-thread mode). With VHE, EL1 is + * always a guest so keep using the guest machine to avoid decoding guest + * trace with the host kernel maps. + */ + if (!perf_guest && pid_fmt != CS_ETM_PIDFMT_CTXTID2) + return &etmq->etm->session->machines.host; + /* * Not perfect, but otherwise assume anything in EL1 is the default * guest, and everything else is the host. Distinguishing between guest