* [PATCH v1 0/3] KVM: arm64: pkvm: Extend hypervisor entering tracing reasons
@ 2026-10-09 8:45 Vincent Donnefort
2026-10-09 8:45 ` [PATCH v1 1/3] KVM: arm64: Add ESR class to the hyp_enter hyp event Vincent Donnefort
` (3 more replies)
0 siblings, 4 replies; 12+ messages in thread
From: Vincent Donnefort @ 2026-10-09 8:45 UTC (permalink / raw)
To: maz, oupton, kvmarm, linux-arm-kernel
Cc: joey.gouly, seiden, suzuki.poulose, yuzenghui, catalin.marinas,
will, kernel-team, fuad.tabba, qperret, Vincent Donnefort
This series make the hyp_enter event more detailed by adding a "from="
field and by using the ESR class when relevant. This is interesting for
example to know when the guest has exited for an HVC.
Speaking of HVCs, protected VMs issue an HVC to share memory with the
host. Without this memory sharing, impossible to get logs. So if for any
reason it fails, debugging is quite cumbersome. Add a specific guest_hvc
event that will give even more details than hyp_enter provides.
Also, add a host_hvc event, so that the host gets similar coverage a
protected VM does.
Vincent Donnefort (3):
KVM: arm64: Add ESR class to the hyp_enter hyp event
KVM: arm64: Add guest_hvc hyp event
KVM: arm64: Add host_hvc hyp event
arch/arm64/include/asm/kvm_hypevents.h | 50 ++++++++++++++++++++-----
arch/arm64/kvm/hyp/nvhe/hyp-main.c | 9 ++---
arch/arm64/kvm/hyp/nvhe/pkvm.c | 7 +++-
arch/arm64/kvm/hyp/nvhe/psci-relay.c | 2 +-
arch/arm64/kvm/hyp/nvhe/switch.c | 6 ++-
arch/arm64/kvm/hyp_trace.c | 52 ++++++++++++++++++++------
6 files changed, 96 insertions(+), 30 deletions(-)
base-commit: a90ee4305c4a5df72c11b31dacfdc76e00fcf78a
--
2.56.0.385.gd3acb90ef8-goog
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v1 1/3] KVM: arm64: Add ESR class to the hyp_enter hyp event
2026-10-09 8:45 [PATCH v1 0/3] KVM: arm64: pkvm: Extend hypervisor entering tracing reasons Vincent Donnefort
@ 2026-10-09 8:45 ` Vincent Donnefort
2026-10-09 11:30 ` Fuad Tabba
2026-10-09 8:45 ` [PATCH v1 2/3] KVM: arm64: Add guest_hvc " Vincent Donnefort
` (2 subsequent siblings)
3 siblings, 1 reply; 12+ messages in thread
From: Vincent Donnefort @ 2026-10-09 8:45 UTC (permalink / raw)
To: maz, oupton, kvmarm, linux-arm-kernel
Cc: joey.gouly, seiden, suzuki.poulose, yuzenghui, catalin.marinas,
will, kernel-team, fuad.tabba, qperret, Vincent Donnefort
Give a more detailed reason the hyp has been entered by reading the ESR
class when relevant (that is on trap). Encode the ESR class directly
into the existing reason field.
To distinguish between a trap from host and from guest, add a "from="
field, which has 3 possibilities: "host", "vcpu" or "firmware". This
value can be deducted based on the existing vcpu field.
Finally, add a "to=" field to the hyp_exit event to mirror "hyp_enter".
Signed-off-by: Vincent Donnefort <vdonnefort@google.com>
---
arch/arm64/include/asm/kvm_hypevents.h | 21 ++++++-----
arch/arm64/kvm/hyp/nvhe/hyp-main.c | 7 +---
arch/arm64/kvm/hyp/nvhe/psci-relay.c | 2 +-
arch/arm64/kvm/hyp/nvhe/switch.c | 6 ++-
arch/arm64/kvm/hyp_trace.c | 52 ++++++++++++++++++++------
5 files changed, 59 insertions(+), 29 deletions(-)
diff --git a/arch/arm64/include/asm/kvm_hypevents.h b/arch/arm64/include/asm/kvm_hypevents.h
index 5f6e6789d121..96985c93a15e 100644
--- a/arch/arm64/include/asm/kvm_hypevents.h
+++ b/arch/arm64/include/asm/kvm_hypevents.h
@@ -10,15 +10,10 @@
#ifndef __HYP_ENTER_EXIT_REASON
#define __HYP_ENTER_EXIT_REASON
enum hyp_enter_exit_reason {
- HYP_REASON_SMC,
- HYP_REASON_HVC,
- HYP_REASON_SYS,
+ HYP_REASON_SMC = ESR_ELx_EC_MAX + 1,
HYP_REASON_PSCI,
- HYP_REASON_HOST_ABORT,
- HYP_REASON_GUEST_EXIT,
- HYP_REASON_ERET_HOST,
- HYP_REASON_ERET_GUEST,
- HYP_REASON_UNKNOWN /* Must be last */
+ HYP_REASON_IRQ,
+ HYP_REASON_ERET,
};
#endif
@@ -32,7 +27,10 @@ HYP_EVENT(hyp_enter,
__entry->reason = reason;
__entry->vcpu = __tracing_get_vcpu_pid(host_ctxt);
),
- HE_PRINTK("reason=%s vcpu=%d", __hyp_enter_exit_reason_str(__entry->reason), __entry->vcpu)
+ HE_PRINTK("from=%s reason=%s vcpu=%d",
+ __hyp_enter_exit_str(__entry->reason, __entry->vcpu),
+ __hyp_enter_exit_reason_str(__entry->reason),
+ __entry->vcpu)
);
HYP_EVENT(hyp_exit,
@@ -45,7 +43,10 @@ HYP_EVENT(hyp_exit,
__entry->reason = reason;
__entry->vcpu = __tracing_get_vcpu_pid(host_ctxt);
),
- HE_PRINTK("reason=%s vcpu=%d", __hyp_enter_exit_reason_str(__entry->reason), __entry->vcpu)
+ HE_PRINTK("to=%s reason=%s vcpu=%d",
+ __hyp_enter_exit_str(__entry->reason, __entry->vcpu),
+ __hyp_enter_exit_reason_str(__entry->reason),
+ __entry->vcpu)
);
HYP_EVENT(selftest,
diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
index ac64a036b0a9..76d08c503dc0 100644
--- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
+++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
@@ -1112,23 +1112,20 @@ void handle_trap(struct kvm_cpu_context *host_ctxt)
{
u64 esr = read_sysreg_el2(SYS_ESR);
+ trace_hyp_enter(host_ctxt, ESR_ELx_EC(esr));
switch (ESR_ELx_EC(esr)) {
case ESR_ELx_EC_HVC64:
- trace_hyp_enter(host_ctxt, HYP_REASON_HVC);
handle_host_hcall(host_ctxt);
break;
case ESR_ELx_EC_SMC64:
- trace_hyp_enter(host_ctxt, HYP_REASON_SMC);
handle_host_smc(host_ctxt);
break;
case ESR_ELx_EC_IABT_LOW:
case ESR_ELx_EC_DABT_LOW:
- trace_hyp_enter(host_ctxt, HYP_REASON_HOST_ABORT);
handle_host_mem_abort(host_ctxt);
break;
case ESR_ELx_EC_SYS64:
- trace_hyp_enter(host_ctxt, HYP_REASON_SYS);
if (handle_host_mte(esr))
break;
fallthrough;
@@ -1136,5 +1133,5 @@ void handle_trap(struct kvm_cpu_context *host_ctxt)
BUG();
}
- trace_hyp_exit(host_ctxt, HYP_REASON_ERET_HOST);
+ trace_hyp_exit(host_ctxt, HYP_REASON_ERET);
}
diff --git a/arch/arm64/kvm/hyp/nvhe/psci-relay.c b/arch/arm64/kvm/hyp/nvhe/psci-relay.c
index e20db999e328..c771c1d150c4 100644
--- a/arch/arm64/kvm/hyp/nvhe/psci-relay.c
+++ b/arch/arm64/kvm/hyp/nvhe/psci-relay.c
@@ -213,7 +213,7 @@ static void __noreturn __kvm_host_psci_cpu_entry(unsigned long pc, unsigned long
write_sysreg_el1(INIT_SCTLR_EL1_MMU_OFF, SYS_SCTLR);
write_sysreg(INIT_PSTATE_EL1, SPSR_EL2);
- trace_hyp_exit(host_ctxt, HYP_REASON_PSCI);
+ trace_hyp_exit(host_ctxt, HYP_REASON_ERET);
__host_enter(host_ctxt);
}
diff --git a/arch/arm64/kvm/hyp/nvhe/switch.c b/arch/arm64/kvm/hyp/nvhe/switch.c
index 7318e3e6a5f3..cf4de8287b97 100644
--- a/arch/arm64/kvm/hyp/nvhe/switch.c
+++ b/arch/arm64/kvm/hyp/nvhe/switch.c
@@ -324,13 +324,15 @@ int __kvm_vcpu_run(struct kvm_vcpu *vcpu)
__debug_switch_to_guest(vcpu);
do {
- trace_hyp_exit(host_ctxt, HYP_REASON_ERET_GUEST);
+ trace_hyp_exit(host_ctxt, HYP_REASON_ERET);
/* Jump in the fire! */
exit_code = __guest_enter(vcpu);
/* And we're baaack! */
- trace_hyp_enter(host_ctxt, HYP_REASON_GUEST_EXIT);
+ trace_hyp_enter(host_ctxt,
+ ARM_EXCEPTION_CODE(exit_code) == ARM_EXCEPTION_IRQ ?
+ HYP_REASON_IRQ : ESR_ELx_EC(read_sysreg_el2(SYS_ESR)));
} while (fixup_guest_exit(vcpu, &exit_code));
__sysreg_save_state_nvhe(guest_ctxt);
diff --git a/arch/arm64/kvm/hyp_trace.c b/arch/arm64/kvm/hyp_trace.c
index 9644c424819b..e47b91bf3ae1 100644
--- a/arch/arm64/kvm/hyp_trace.c
+++ b/arch/arm64/kvm/hyp_trace.c
@@ -400,25 +400,55 @@ static struct trace_remote_callbacks trace_remote_callbacks = {
.enable_event = hyp_trace_enable_event,
};
+static const char *__hyp_enter_exit_str(u8 reason, pid_t vcpu);
static const char *__hyp_enter_exit_reason_str(u8 reason);
#include <asm/kvm_define_hypevents.h>
+static const char *__hyp_enter_exit_str(u8 reason, pid_t vcpu)
+{
+ switch (reason) {
+ case 0 ... ESR_ELx_EC_MAX:
+ case HYP_REASON_IRQ:
+ case HYP_REASON_ERET:
+ return vcpu ? "vcpu" : "host";
+ case HYP_REASON_SMC:
+ case HYP_REASON_PSCI:
+ return "firmware";
+ default:
+ return "unknown";
+ }
+}
+
static const char *__hyp_enter_exit_reason_str(u8 reason)
{
- static const char strs[][12] = {
- "smc",
- "hvc",
- "sys",
- "psci",
- "host_abort",
- "guest_exit",
- "eret_host",
- "eret_guest",
- "unknown",
+ static const struct trace_print_flags class[] = {
+ kvm_arm_exception_class
};
- return strs[min(reason, HYP_REASON_UNKNOWN)];
+ if (reason <= ESR_ELx_EC_MAX) {
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(class); i++) {
+ if (class[i].mask == reason)
+ return class[i].name;
+ }
+
+ return "UNKNOWN_ESR";
+ }
+
+ switch (reason) {
+ case HYP_REASON_SMC:
+ return "SMC";
+ case HYP_REASON_PSCI:
+ return "PSCI";
+ case HYP_REASON_IRQ:
+ return "IRQ";
+ case HYP_REASON_ERET:
+ return "ERET";
+ default:
+ return "UNKNOWN_REASON";
+ }
}
static void __init hyp_trace_init_events(void)
--
2.56.0.385.gd3acb90ef8-goog
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v1 2/3] KVM: arm64: Add guest_hvc hyp event
2026-10-09 8:45 [PATCH v1 0/3] KVM: arm64: pkvm: Extend hypervisor entering tracing reasons Vincent Donnefort
2026-10-09 8:45 ` [PATCH v1 1/3] KVM: arm64: Add ESR class to the hyp_enter hyp event Vincent Donnefort
@ 2026-10-09 8:45 ` Vincent Donnefort
2026-10-09 12:06 ` Fuad Tabba
2026-10-09 8:45 ` [PATCH v1 3/3] KVM: arm64: Add host_hvc " Vincent Donnefort
2026-10-09 13:50 ` [PATCH v1 0/3] KVM: arm64: pkvm: Extend hypervisor entering tracing reasons Marc Zyngier
3 siblings, 1 reply; 12+ messages in thread
From: Vincent Donnefort @ 2026-10-09 8:45 UTC (permalink / raw)
To: maz, oupton, kvmarm, linux-arm-kernel
Cc: joey.gouly, seiden, suzuki.poulose, yuzenghui, catalin.marinas,
will, kernel-team, fuad.tabba, qperret, Vincent Donnefort
Add a guest_hvc hypervisor trace event to log protected VM HVC call IDs,
return values, and whether the call was handled by the hypervisor.
Signed-off-by: Vincent Donnefort <vdonnefort@google.com>
---
arch/arm64/include/asm/kvm_hypevents.h | 16 ++++++++++++++++
arch/arm64/kvm/hyp/nvhe/pkvm.c | 7 ++++++-
2 files changed, 22 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/include/asm/kvm_hypevents.h b/arch/arm64/include/asm/kvm_hypevents.h
index 96985c93a15e..c1239d78c8f9 100644
--- a/arch/arm64/include/asm/kvm_hypevents.h
+++ b/arch/arm64/include/asm/kvm_hypevents.h
@@ -59,4 +59,20 @@ HYP_EVENT(selftest,
),
RE_PRINTK("id=%llu", __entry->id)
);
+
+HYP_EVENT(guest_hvc,
+ HE_PROTO(u32 id, u64 val, u8 handled),
+ HE_STRUCT(
+ he_field(u8, handled)
+ he_field(u32, id)
+ he_field(u64, val)
+ ),
+ HE_ASSIGN(
+ __entry->id = id;
+ __entry->val = val;
+ __entry->handled = handled;
+ ),
+ HE_PRINTK("id=0x%x val=0x%llx handled=%u",
+ __entry->id, __entry->val, __entry->handled)
+);
#endif
diff --git a/arch/arm64/kvm/hyp/nvhe/pkvm.c b/arch/arm64/kvm/hyp/nvhe/pkvm.c
index 6290c4b62659..0deed0622677 100644
--- a/arch/arm64/kvm/hyp/nvhe/pkvm.c
+++ b/arch/arm64/kvm/hyp/nvhe/pkvm.c
@@ -10,6 +10,7 @@
#include <linux/mm.h>
#include <asm/kvm_emulate.h>
+#include <asm/kvm_hypevents.h>
#include <nvhe/mem_protect.h>
#include <nvhe/memory.h>
@@ -1142,9 +1143,10 @@ static void pkvm_memunshare_call(u64 *ret, struct kvm_vcpu *vcpu)
bool kvm_handle_pvm_hvc64(struct kvm_vcpu *vcpu, u64 *exit_code)
{
u64 val[4] = { SMCCC_RET_INVALID_PARAMETER };
+ u32 fn = smccc_get_function(vcpu);
bool handled = true;
- switch (smccc_get_function(vcpu)) {
+ switch (fn) {
case ARM_SMCCC_VENDOR_HYP_KVM_FEATURES_FUNC_ID:
val[0] = BIT(ARM_SMCCC_KVM_FUNC_FEATURES);
val[0] |= BIT(ARM_SMCCC_KVM_FUNC_HYP_MEMINFO);
@@ -1183,5 +1185,8 @@ bool kvm_handle_pvm_hvc64(struct kvm_vcpu *vcpu, u64 *exit_code)
if (handled)
smccc_set_retval(vcpu, val[0], val[1], val[2], val[3]);
+
+ trace_guest_hvc(fn, val[0], handled);
+
return handled;
}
--
2.56.0.385.gd3acb90ef8-goog
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v1 3/3] KVM: arm64: Add host_hvc hyp event
2026-10-09 8:45 [PATCH v1 0/3] KVM: arm64: pkvm: Extend hypervisor entering tracing reasons Vincent Donnefort
2026-10-09 8:45 ` [PATCH v1 1/3] KVM: arm64: Add ESR class to the hyp_enter hyp event Vincent Donnefort
2026-10-09 8:45 ` [PATCH v1 2/3] KVM: arm64: Add guest_hvc " Vincent Donnefort
@ 2026-10-09 8:45 ` Vincent Donnefort
2026-10-09 12:26 ` Fuad Tabba
2026-10-09 13:50 ` [PATCH v1 0/3] KVM: arm64: pkvm: Extend hypervisor entering tracing reasons Marc Zyngier
3 siblings, 1 reply; 12+ messages in thread
From: Vincent Donnefort @ 2026-10-09 8:45 UTC (permalink / raw)
To: maz, oupton, kvmarm, linux-arm-kernel
Cc: joey.gouly, seiden, suzuki.poulose, yuzenghui, catalin.marinas,
will, kernel-team, fuad.tabba, qperret, Vincent Donnefort
Add a host_hvc hypervisor trace event to log host HVC call IDs and
return values.
Signed-off-by: Vincent Donnefort <vdonnefort@google.com>
---
arch/arm64/include/asm/kvm_hypevents.h | 13 +++++++++++++
arch/arm64/kvm/hyp/nvhe/hyp-main.c | 2 ++
2 files changed, 15 insertions(+)
diff --git a/arch/arm64/include/asm/kvm_hypevents.h b/arch/arm64/include/asm/kvm_hypevents.h
index c1239d78c8f9..a37ba9db1cc7 100644
--- a/arch/arm64/include/asm/kvm_hypevents.h
+++ b/arch/arm64/include/asm/kvm_hypevents.h
@@ -60,6 +60,19 @@ HYP_EVENT(selftest,
RE_PRINTK("id=%llu", __entry->id)
);
+HYP_EVENT(host_hvc,
+ HE_PROTO(u8 id, u64 ret),
+ HE_STRUCT(
+ he_field(u8, id)
+ he_field(u64, ret)
+ ),
+ HE_ASSIGN(
+ __entry->id = id;
+ __entry->ret = ret;
+ ),
+ HE_PRINTK("id=%u ret=0x%llx", __entry->id, __entry->ret)
+);
+
HYP_EVENT(guest_hvc,
HE_PROTO(u32 id, u64 val, u8 handled),
HE_STRUCT(
diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
index 76d08c503dc0..579615e3b2dd 100644
--- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
+++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
@@ -996,6 +996,8 @@ static void handle_host_hcall(struct kvm_cpu_context *host_ctxt)
cpu_reg(host_ctxt, 0) = SMCCC_RET_SUCCESS;
hfn(host_ctxt);
+ trace_host_hvc(id, cpu_reg(host_ctxt, 1));
+
return;
inval:
cpu_reg(host_ctxt, 0) = SMCCC_RET_NOT_SUPPORTED;
--
2.56.0.385.gd3acb90ef8-goog
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH v1 1/3] KVM: arm64: Add ESR class to the hyp_enter hyp event
2026-10-09 8:45 ` [PATCH v1 1/3] KVM: arm64: Add ESR class to the hyp_enter hyp event Vincent Donnefort
@ 2026-10-09 11:30 ` Fuad Tabba
2026-10-09 13:02 ` Vincent Donnefort
0 siblings, 1 reply; 12+ messages in thread
From: Fuad Tabba @ 2026-10-09 11:30 UTC (permalink / raw)
To: Vincent Donnefort
Cc: maz, oupton, kvmarm, linux-arm-kernel, joey.gouly, seiden,
suzuki.poulose, yuzenghui, catalin.marinas, will, kernel-team,
qperret
Hi Vincent,
On Fri, 09 Oct 2026 09:45:27 +0100, Vincent Donnefort
<vdonnefort@google.com> wrote:
[...]
> To distinguish between a trap from host and from guest, add a "from="
> field, which has 3 possibilities: "host", "vcpu" or "firmware". This
> value can be deducted based on the existing vcpu field.
nit: "deduced". Also, "firmware" comes from the reason rather than
from the vcpu field.
[...]
> diff --git a/arch/arm64/include/asm/kvm_hypevents.h b/arch/arm64/include/asm/kvm_hypevents.h
[...]
> @@ -10,15 +10,10 @@
> #ifndef __HYP_ENTER_EXIT_REASON
> #define __HYP_ENTER_EXIT_REASON
> enum hyp_enter_exit_reason {
> - HYP_REASON_SMC,
> - HYP_REASON_HVC,
> - HYP_REASON_SYS,
> + HYP_REASON_SMC = ESR_ELx_EC_MAX + 1,
This header now uses ESR_ELx_EC_MAX, so it should include <asm/esr.h>
rather than rely on its includers.
> HYP_REASON_PSCI,
> - HYP_REASON_HOST_ABORT,
> - HYP_REASON_GUEST_EXIT,
> - HYP_REASON_ERET_HOST,
> - HYP_REASON_ERET_GUEST,
> - HYP_REASON_UNKNOWN /* Must be last */
> + HYP_REASON_IRQ,
> + HYP_REASON_ERET,
> };
Aren't fixed trace points ABI? This changes the raw values of the
reason field (1 was hvc and is now WFx) and the strings it prints.
Keeping the old values and recording the EC in a new field would avoid
that.
[...]
> diff --git a/arch/arm64/kvm/hyp/nvhe/psci-relay.c b/arch/arm64/kvm/hyp/nvhe/psci-relay.c
[...]
> @@ -213,7 +213,7 @@ static void __noreturn __kvm_host_psci_cpu_entry(unsigned long pc, unsigned long
> write_sysreg_el1(INIT_SCTLR_EL1_MMU_OFF, SYS_SCTLR);
> write_sysreg(INIT_PSTATE_EL1, SPSR_EL2);
>
> - trace_hyp_exit(host_ctxt, HYP_REASON_PSCI);
> + trace_hyp_exit(host_ctxt, HYP_REASON_ERET);
> __host_enter(host_ctxt);
This also replaces the PSCI, ERET_HOST and ERET_GUEST exit reasons
with a single ERET, which the commit message doesn't mention.
[...]
> diff --git a/arch/arm64/kvm/hyp/nvhe/switch.c b/arch/arm64/kvm/hyp/nvhe/switch.c
[...]
> @@ -324,13 +324,15 @@ int __kvm_vcpu_run(struct kvm_vcpu *vcpu)
> __debug_switch_to_guest(vcpu);
>
> do {
> - trace_hyp_exit(host_ctxt, HYP_REASON_ERET_GUEST);
> + trace_hyp_exit(host_ctxt, HYP_REASON_ERET);
>
> /* Jump in the fire! */
> exit_code = __guest_enter(vcpu);
>
> /* And we're baaack! */
> - trace_hyp_enter(host_ctxt, HYP_REASON_GUEST_EXIT);
> + trace_hyp_enter(host_ctxt,
> + ARM_EXCEPTION_CODE(exit_code) == ARM_EXCEPTION_IRQ ?
> + HYP_REASON_IRQ : ESR_ELx_EC(read_sysreg_el2(SYS_ESR)));
> } while (fixup_guest_exit(vcpu, &exit_code));
Could ESR_EL2 be read only when the event is enabled? The read happens
even when tracing is disabled or compiled out, so every non-IRQ guest
exit now does an extra one: with NVHE_EL2_DEBUG=n, __kvm_vcpu_run()
goes from two reads of ESR_EL2 to three.
[...]
> diff --git a/arch/arm64/kvm/hyp_trace.c b/arch/arm64/kvm/hyp_trace.c
[...]
> static const char *__hyp_enter_exit_reason_str(u8 reason)
> {
[...]
> + if (reason <= ESR_ELx_EC_MAX) {
> + int i;
> +
> + for (i = 0; i < ARRAY_SIZE(class); i++) {
> + if (class[i].mask == reason)
> + return class[i].name;
> + }
> +
> + return "UNKNOWN_ESR";
> + }
Could this print the EC value when it isn't in the table?
kvm_arm_exception_class has no entry for ILL, BTI, SME or GCS among
others, so an ARM_EXCEPTION_IL exit (EC 0x0E) shows up as UNKNOWN_ESR.
Cheers,
/fuad
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v1 2/3] KVM: arm64: Add guest_hvc hyp event
2026-10-09 8:45 ` [PATCH v1 2/3] KVM: arm64: Add guest_hvc " Vincent Donnefort
@ 2026-10-09 12:06 ` Fuad Tabba
2026-10-09 13:17 ` Vincent Donnefort
0 siblings, 1 reply; 12+ messages in thread
From: Fuad Tabba @ 2026-10-09 12:06 UTC (permalink / raw)
To: Vincent Donnefort
Cc: maz, oupton, kvmarm, linux-arm-kernel, joey.gouly, seiden,
suzuki.poulose, yuzenghui, catalin.marinas, will, kernel-team,
qperret
Hi Vincent,
On Fri, 09 Oct 2026 09:45:28 +0100, Vincent Donnefort
<vdonnefort@google.com> wrote:
> Add a guest_hvc hypervisor trace event to log protected VM HVC call IDs,
> return values, and whether the call was handled by the hypervisor.
nit: only the first return value is logged.
[...]
> diff --git a/arch/arm64/include/asm/kvm_hypevents.h b/arch/arm64/include/asm/kvm_hypevents.h
[...]
> +HYP_EVENT(guest_hvc,
> + HE_PROTO(u32 id, u64 val, u8 handled),
> + HE_STRUCT(
> + he_field(u8, handled)
> + he_field(u32, id)
> + he_field(u64, val)
> + ),
remote_event_format_show() doesn't align the field offsets, so the
format file puts id at 3 and val at 7 instead of 4 and 8. hyp_enter's
vcpu is already off the same way, so should this be a separate fix in
trace_remote.c, with ALIGN(offset, field->align)?
[...]
> diff --git a/arch/arm64/kvm/hyp/nvhe/pkvm.c b/arch/arm64/kvm/hyp/nvhe/pkvm.c
[...]
> @@ -1183,5 +1185,8 @@ bool kvm_handle_pvm_hvc64(struct kvm_vcpu *vcpu, u64 *exit_code)
>
> if (handled)
> smccc_set_retval(vcpu, val[0], val[1], val[2], val[3]);
> +
> + trace_guest_hvc(fn, val[0], handled);
> +
> return handled;
When handled is false, val[0] is the SMCCC_RET_INVALID_PARAMETER
initialiser, which the guest never gets. For example, a MEM_SHARE
forwarded to the host logs "id=0xc6000003 val=0xfffffffffffffffd
handled=0". Could this log 0 in that case?
Cheers,
/fuad
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v1 3/3] KVM: arm64: Add host_hvc hyp event
2026-10-09 8:45 ` [PATCH v1 3/3] KVM: arm64: Add host_hvc " Vincent Donnefort
@ 2026-10-09 12:26 ` Fuad Tabba
2026-10-09 13:20 ` Vincent Donnefort
0 siblings, 1 reply; 12+ messages in thread
From: Fuad Tabba @ 2026-10-09 12:26 UTC (permalink / raw)
To: Vincent Donnefort
Cc: maz, oupton, kvmarm, linux-arm-kernel, joey.gouly, seiden,
suzuki.poulose, yuzenghui, catalin.marinas, will, kernel-team,
qperret
Hi Vincent,
On Fri, 09 Oct 2026 09:45:29 +0100, Vincent Donnefort
<vdonnefort@google.com> wrote:
[...]
> diff --git a/arch/arm64/include/asm/kvm_hypevents.h b/arch/arm64/include/asm/kvm_hypevents.h
[...]
> +HYP_EVENT(host_hvc,
> + HE_PROTO(u8 id, u64 ret),
> + HE_STRUCT(
> + he_field(u8, id)
> + he_field(u64, ret)
> + ),
> + HE_ASSIGN(
> + __entry->id = id;
> + __entry->ret = ret;
> + ),
> + HE_PRINTK("id=%u ret=0x%llx", __entry->id, __entry->ret)
> +);
id is the index into host_hcall[], so its value depends on that
table's order. Could this log the SMCCC function ID instead, as
guest_hvc does? The alignment issue from patch 2 applies here too: the
format file puts ret at offset 3 instead of 8.
[...]
> diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
[...]
> @@ -996,6 +996,8 @@ static void handle_host_hcall(struct kvm_cpu_context *host_ctxt)
> cpu_reg(host_ctxt, 0) = SMCCC_RET_SUCCESS;
> hfn(host_ctxt);
>
> + trace_host_hvc(id, cpu_reg(host_ctxt, 1));
> +
> return;
> inval:
> cpu_reg(host_ctxt, 0) = SMCCC_RET_NOT_SUPPORTED;
Only some of the handlers write a return value to x1. For the others,
x1 still holds the first argument, e.g. the mmu pointer for
__kvm_tlb_flush_vmid, so host_hvc's ret field shows that instead.
Could the field be called x1 rather than ret?
Cheers,
/fuad
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v1 1/3] KVM: arm64: Add ESR class to the hyp_enter hyp event
2026-10-09 11:30 ` Fuad Tabba
@ 2026-10-09 13:02 ` Vincent Donnefort
2026-10-09 14:08 ` Fuad Tabba
0 siblings, 1 reply; 12+ messages in thread
From: Vincent Donnefort @ 2026-10-09 13:02 UTC (permalink / raw)
To: Fuad Tabba
Cc: maz, oupton, kvmarm, linux-arm-kernel, joey.gouly, seiden,
suzuki.poulose, yuzenghui, catalin.marinas, will, kernel-team,
qperret
On Fri, Oct 09, 2026 at 12:30:56PM +0100, Fuad Tabba wrote:
> Hi Vincent,
>
> On Fri, 09 Oct 2026 09:45:27 +0100, Vincent Donnefort
> <vdonnefort@google.com> wrote:
>
> [...]
> > To distinguish between a trap from host and from guest, add a "from="
> > field, which has 3 possibilities: "host", "vcpu" or "firmware". This
> > value can be deducted based on the existing vcpu field.
>
> nit: "deduced". Also, "firmware" comes from the reason rather than
> from the vcpu field.
>
> [...]
> > diff --git a/arch/arm64/include/asm/kvm_hypevents.h b/arch/arm64/include/asm/kvm_hypevents.h
>
> [...]
> > @@ -10,15 +10,10 @@
> > #ifndef __HYP_ENTER_EXIT_REASON
> > #define __HYP_ENTER_EXIT_REASON
> > enum hyp_enter_exit_reason {
> > - HYP_REASON_SMC,
> > - HYP_REASON_HVC,
> > - HYP_REASON_SYS,
> > + HYP_REASON_SMC = ESR_ELx_EC_MAX + 1,
>
> This header now uses ESR_ELx_EC_MAX, so it should include <asm/esr.h>
> rather than rely on its includers.
>
> > HYP_REASON_PSCI,
> > - HYP_REASON_HOST_ABORT,
> > - HYP_REASON_GUEST_EXIT,
> > - HYP_REASON_ERET_HOST,
> > - HYP_REASON_ERET_GUEST,
> > - HYP_REASON_UNKNOWN /* Must be last */
> > + HYP_REASON_IRQ,
> > + HYP_REASON_ERET,
> > };
>
> Aren't fixed trace points ABI? This changes the raw values of the
> reason field (1 was hvc and is now WFx) and the strings it prints.
> Keeping the old values and recording the EC in a new field would avoid
> that.
The event format is described precisely in events/hypervisor/hyp_enter/format.
Any tooling should use that, so it doesn't seem like ABI to me. Also, this is
behind NVHE_EL2_DEBUG. The only precedent I know is in kernel/sched/ where there
are only tracepoints to avoid having trace events.
Finally, we do not expose (yet :)) the raw interface. So this part is definitely
not ABI.
I tried to avoid having the EC separately to keep the event as small as
possible.
>
> [...]
> > diff --git a/arch/arm64/kvm/hyp/nvhe/psci-relay.c b/arch/arm64/kvm/hyp/nvhe/psci-relay.c
> [...]
> > @@ -213,7 +213,7 @@ static void __noreturn __kvm_host_psci_cpu_entry(unsigned long pc, unsigned long
> > write_sysreg_el1(INIT_SCTLR_EL1_MMU_OFF, SYS_SCTLR);
> > write_sysreg(INIT_PSTATE_EL1, SPSR_EL2);
> >
> > - trace_hyp_exit(host_ctxt, HYP_REASON_PSCI);
> > + trace_hyp_exit(host_ctxt, HYP_REASON_ERET);
> > __host_enter(host_ctxt);
>
> This also replaces the PSCI, ERET_HOST and ERET_GUEST exit reasons
> with a single ERET, which the commit message doesn't mention.
ERET_HOST is now "to=host reason=eret" and ERET_GUEST "to=guest reason=ERET".
This one here could be considered a bug fix and I could make it a separate
patch?
>
> [...]
> > diff --git a/arch/arm64/kvm/hyp/nvhe/switch.c b/arch/arm64/kvm/hyp/nvhe/switch.c
>
> [...]
> > @@ -324,13 +324,15 @@ int __kvm_vcpu_run(struct kvm_vcpu *vcpu)
> > __debug_switch_to_guest(vcpu);
> >
> > do {
> > - trace_hyp_exit(host_ctxt, HYP_REASON_ERET_GUEST);
> > + trace_hyp_exit(host_ctxt, HYP_REASON_ERET);
> >
> > /* Jump in the fire! */
> > exit_code = __guest_enter(vcpu);
> >
> > /* And we're baaack! */
> > - trace_hyp_enter(host_ctxt, HYP_REASON_GUEST_EXIT);
> > + trace_hyp_enter(host_ctxt,
> > + ARM_EXCEPTION_CODE(exit_code) == ARM_EXCEPTION_IRQ ?
> > + HYP_REASON_IRQ : ESR_ELx_EC(read_sysreg_el2(SYS_ESR)));
> > } while (fixup_guest_exit(vcpu, &exit_code));
>
> Could ESR_EL2 be read only when the event is enabled? The read happens
> even when tracing is disabled or compiled out, so every non-IRQ guest
> exit now does an extra one: with NVHE_EL2_DEBUG=n, __kvm_vcpu_run()
> goes from two reads of ESR_EL2 to three.
Hum, that's a good point. I was thinking about having a HYP_REASON_ESR that when
sent actually read the ESR. But then handle_trap() would read it twice, unless
this one still gives the esr directly.
Alternatively, I thought of moving the esr_el2 = read_sysreg_el2(SYS_ESR) out of
__fixup_guest_exit(). But it didn't look nice.
WDYS?
>
> [...]
> > diff --git a/arch/arm64/kvm/hyp_trace.c b/arch/arm64/kvm/hyp_trace.c
> [...]
> > static const char *__hyp_enter_exit_reason_str(u8 reason)
> > {
> [...]
> > + if (reason <= ESR_ELx_EC_MAX) {
> > + int i;
> > +
> > + for (i = 0; i < ARRAY_SIZE(class); i++) {
> > + if (class[i].mask == reason)
> > + return class[i].name;
> > + }
> > +
> > + return "UNKNOWN_ESR";
> > + }
>
> Could this print the EC value when it isn't in the table?
> kvm_arm_exception_class has no entry for ILL, BTI, SME or GCS among
> others, so an ARM_EXCEPTION_IL exit (EC 0x0E) shows up as UNKNOWN_ESR.
I can extend kvm_arm_exception_class. Having a dynamic format string is not
possible here.
>
> Cheers,
> /fuad
--
Vincent
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v1 2/3] KVM: arm64: Add guest_hvc hyp event
2026-10-09 12:06 ` Fuad Tabba
@ 2026-10-09 13:17 ` Vincent Donnefort
0 siblings, 0 replies; 12+ messages in thread
From: Vincent Donnefort @ 2026-10-09 13:17 UTC (permalink / raw)
To: Fuad Tabba
Cc: maz, oupton, kvmarm, linux-arm-kernel, joey.gouly, seiden,
suzuki.poulose, yuzenghui, catalin.marinas, will, kernel-team,
qperret
On Fri, Oct 09, 2026 at 01:06:05PM +0100, Fuad Tabba wrote:
> Hi Vincent,
>
> On Fri, 09 Oct 2026 09:45:28 +0100, Vincent Donnefort
> <vdonnefort@google.com> wrote:
>
> > Add a guest_hvc hypervisor trace event to log protected VM HVC call IDs,
> > return values, and whether the call was handled by the hypervisor.
>
> nit: only the first return value is logged.
>
> [...]
> > diff --git a/arch/arm64/include/asm/kvm_hypevents.h b/arch/arm64/include/asm/kvm_hypevents.h
>
> [...]
> > +HYP_EVENT(guest_hvc,
> > + HE_PROTO(u32 id, u64 val, u8 handled),
> > + HE_STRUCT(
> > + he_field(u8, handled)
> > + he_field(u32, id)
> > + he_field(u64, val)
> > + ),
>
> remote_event_format_show() doesn't align the field offsets, so the
> format file puts id at 3 and val at 7 instead of 4 and 8. hyp_enter's
> vcpu is already off the same way, so should this be a separate fix in
> trace_remote.c, with ALIGN(offset, field->align)?
Ha, absolutely, I'll send something to linux-trace. We don't have this issue in
Android kernel because the struct are __packed there.
>
> [...]
> > diff --git a/arch/arm64/kvm/hyp/nvhe/pkvm.c b/arch/arm64/kvm/hyp/nvhe/pkvm.c
>
> [...]
> > @@ -1183,5 +1185,8 @@ bool kvm_handle_pvm_hvc64(struct kvm_vcpu *vcpu, u64 *exit_code)
> >
> > if (handled)
> > smccc_set_retval(vcpu, val[0], val[1], val[2], val[3]);
> > +
> > + trace_guest_hvc(fn, val[0], handled);
> > +
> > return handled;
>
> When handled is false, val[0] is the SMCCC_RET_INVALID_PARAMETER
> initialiser, which the guest never gets. For example, a MEM_SHARE
> forwarded to the host logs "id=0xc6000003 val=0xfffffffffffffffd
> handled=0". Could this log 0 in that case?
Ack. That shouldn't be too difficult
>
> Cheers,
> /fuad
--
Vincent
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v1 3/3] KVM: arm64: Add host_hvc hyp event
2026-10-09 12:26 ` Fuad Tabba
@ 2026-10-09 13:20 ` Vincent Donnefort
0 siblings, 0 replies; 12+ messages in thread
From: Vincent Donnefort @ 2026-10-09 13:20 UTC (permalink / raw)
To: Fuad Tabba
Cc: maz, oupton, kvmarm, linux-arm-kernel, joey.gouly, seiden,
suzuki.poulose, yuzenghui, catalin.marinas, will, kernel-team,
qperret
On Fri, Oct 09, 2026 at 01:26:22PM +0100, Fuad Tabba wrote:
> Hi Vincent,
>
> On Fri, 09 Oct 2026 09:45:29 +0100, Vincent Donnefort
> <vdonnefort@google.com> wrote:
>
> [...]
> > diff --git a/arch/arm64/include/asm/kvm_hypevents.h b/arch/arm64/include/asm/kvm_hypevents.h
>
> [...]
> > +HYP_EVENT(host_hvc,
> > + HE_PROTO(u8 id, u64 ret),
> > + HE_STRUCT(
> > + he_field(u8, id)
> > + he_field(u64, ret)
> > + ),
> > + HE_ASSIGN(
> > + __entry->id = id;
> > + __entry->ret = ret;
> > + ),
> > + HE_PRINTK("id=%u ret=0x%llx", __entry->id, __entry->ret)
> > +);
>
> id is the index into host_hcall[], so its value depends on that
> table's order. Could this log the SMCCC function ID instead, as
> guest_hvc does? The alignment issue from patch 2 applies here too: the
> format file puts ret at offset 3 instead of 8.
Ack. I thought this might be easier to get a simpler ID. I even contemplated to
stringify the list before convincing myself this wasn't really the hassle.
>
> [...]
> > diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
>
> [...]
> > @@ -996,6 +996,8 @@ static void handle_host_hcall(struct kvm_cpu_context *host_ctxt)
> > cpu_reg(host_ctxt, 0) = SMCCC_RET_SUCCESS;
> > hfn(host_ctxt);
> >
> > + trace_host_hvc(id, cpu_reg(host_ctxt, 1));
> > +
> > return;
> > inval:
> > cpu_reg(host_ctxt, 0) = SMCCC_RET_NOT_SUPPORTED;
>
> Only some of the handlers write a return value to x1. For the others,
> x1 still holds the first argument, e.g. the mmu pointer for
> __kvm_tlb_flush_vmid, so host_hvc's ret field shows that instead.
> Could the field be called x1 rather than ret?
x1 it is. Perhaps I'll rename too for guest_hvc.
>
> Cheers,
> /fuad
And as always, thanks for reviewing.
--
Vincent
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v1 0/3] KVM: arm64: pkvm: Extend hypervisor entering tracing reasons
2026-10-09 8:45 [PATCH v1 0/3] KVM: arm64: pkvm: Extend hypervisor entering tracing reasons Vincent Donnefort
` (2 preceding siblings ...)
2026-10-09 8:45 ` [PATCH v1 3/3] KVM: arm64: Add host_hvc " Vincent Donnefort
@ 2026-10-09 13:50 ` Marc Zyngier
3 siblings, 0 replies; 12+ messages in thread
From: Marc Zyngier @ 2026-10-09 13:50 UTC (permalink / raw)
To: Vincent Donnefort
Cc: oupton, kvmarm, linux-arm-kernel, joey.gouly, seiden,
suzuki.poulose, yuzenghui, catalin.marinas, will, kernel-team,
fuad.tabba, qperret
On Fri, 09 Oct 2026 09:45:26 +0100,
Vincent Donnefort <vdonnefort@google.com> wrote:
>
> This series make the hyp_enter event more detailed by adding a "from="
> field and by using the ESR class when relevant. This is interesting for
> example to know when the guest has exited for an HVC.
None of that seems to qualify as a fix, and I've now closed the tree
to any new feature.
Please come back after -rc1!
M.
--
Without deviation from the norm, progress is not possible.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v1 1/3] KVM: arm64: Add ESR class to the hyp_enter hyp event
2026-10-09 13:02 ` Vincent Donnefort
@ 2026-10-09 14:08 ` Fuad Tabba
0 siblings, 0 replies; 12+ messages in thread
From: Fuad Tabba @ 2026-10-09 14:08 UTC (permalink / raw)
To: Vincent Donnefort
Cc: maz, oupton, kvmarm, linux-arm-kernel, joey.gouly, seiden,
suzuki.poulose, yuzenghui, catalin.marinas, will, kernel-team,
qperret
Hi Vincent,
On Fri, 09 Oct 2026 14:02:41 +0100, Vincent Donnefort
<vdonnefort@google.com> wrote:
[...]
> > Aren't fixed trace points ABI? This changes the raw values of the
> > reason field (1 was hvc and is now WFx) and the strings it prints.
> > Keeping the old values and recording the EC in a new field would avoid
> > that.
>
> The event format is described precisely in events/hypervisor/hyp_enter/format.
> Any tooling should use that, so it doesn't seem like ABI to me. Also, this is
> behind NVHE_EL2_DEBUG. The only precedent I know is in kernel/sched/ where there
> are only tracepoints to avoid having trace events.
>
> Finally, we do not expose (yet :)) the raw interface. So this part is definitely
> not ABI.
>
> I tried to avoid having the EC separately to keep the event as small as
> possible.
Fair enough, with it behind NVHE_EL2_DEBUG and no raw interface yet.
[...]
> > This also replaces the PSCI, ERET_HOST and ERET_GUEST exit reasons
> > with a single ERET, which the commit message doesn't mention.
>
> ERET_HOST is now "to=host reason=eret" and ERET_GUEST "to=guest reason=ERET".
>
> This one here could be considered a bug fix and I could make it a separate
> patch?
A separate patch sounds good.
[...]
> > Could ESR_EL2 be read only when the event is enabled? The read happens
> > even when tracing is disabled or compiled out, so every non-IRQ guest
> > exit now does an extra one: with NVHE_EL2_DEBUG=n, __kvm_vcpu_run()
> > goes from two reads of ESR_EL2 to three.
>
> Hum, that's a good point. I was thinking about having a HYP_REASON_ESR that when
> sent actually read the ESR. But then handle_trap() would read it twice, unless
> this one still gives the esr directly.
>
> Alternatively, I thought of moving the esr_el2 = read_sysreg_el2(SYS_ESR) out of
> __fixup_guest_exit(). But it didn't look nice.
>
> WDYS?
HYP_REASON_ESR sounds good to me, with handle_trap() still passing the
EC it already has. HE_ASSIGN is only built at EL2 and runs after the
enabled check, so the read can go there.
[...]
> > Could this print the EC value when it isn't in the table?
> > kvm_arm_exception_class has no entry for ILL, BTI, SME or GCS among
> > others, so an ARM_EXCEPTION_IL exit (EC 0x0E) shows up as UNKNOWN_ESR.
>
> I can extend kvm_arm_exception_class. Having a dynamic format string is not
> possible here.
Sounds good, that also helps kvm_exit, which prints from the same table.
Cheers,
/fuad
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2026-10-09 14:09 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-09 8:45 [PATCH v1 0/3] KVM: arm64: pkvm: Extend hypervisor entering tracing reasons Vincent Donnefort
2026-10-09 8:45 ` [PATCH v1 1/3] KVM: arm64: Add ESR class to the hyp_enter hyp event Vincent Donnefort
2026-10-09 11:30 ` Fuad Tabba
2026-10-09 13:02 ` Vincent Donnefort
2026-10-09 14:08 ` Fuad Tabba
2026-10-09 8:45 ` [PATCH v1 2/3] KVM: arm64: Add guest_hvc " Vincent Donnefort
2026-10-09 12:06 ` Fuad Tabba
2026-10-09 13:17 ` Vincent Donnefort
2026-10-09 8:45 ` [PATCH v1 3/3] KVM: arm64: Add host_hvc " Vincent Donnefort
2026-10-09 12:26 ` Fuad Tabba
2026-10-09 13:20 ` Vincent Donnefort
2026-10-09 13:50 ` [PATCH v1 0/3] KVM: arm64: pkvm: Extend hypervisor entering tracing reasons Marc Zyngier
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox