@@ -27,6 +27,141 @@ TRACE_EVENT(vgic_update_irq_pending,
__entry->vcpu_id, __entry->irq, __entry->level)
);
+DECLARE_EVENT_CLASS(vgic_its_cmd_class,
+ TP_PROTO(__u32 device_id, __u32 event_id),
+ TP_ARGS(device_id, event_id),
+
+ TP_STRUCT__entry(
+ __field( __u32, device_id )
+ __field( __u32, event_id )
+ ),
+
+ TP_fast_assign(
+ __entry->device_id = device_id;
+ __entry->event_id = event_id;
+ ),
+
+ TP_printk("Device ID: %u, Event ID: %u",
+ __entry->device_id, __entry->event_id)
+);
+
+DEFINE_EVENT(vgic_its_cmd_class, vgic_its_cmd_mapi,
+ TP_PROTO(__u32 device_id, __u32 event_id),
+ TP_ARGS(device_id, event_id));
+
+DEFINE_EVENT(vgic_its_cmd_class, vgic_its_cmd_discard,
+ TP_PROTO(__u32 device_id, __u32 event_id),
+ TP_ARGS(device_id, event_id));
+
+DEFINE_EVENT(vgic_its_cmd_class, vgic_its_cmd_clear,
+ TP_PROTO(__u32 device_id, __u32 event_id),
+ TP_ARGS(device_id, event_id));
+
+DEFINE_EVENT(vgic_its_cmd_class, vgic_its_cmd_int,
+ TP_PROTO(__u32 device_id, __u32 event_id),
+ TP_ARGS(device_id, event_id));
+
+DEFINE_EVENT(vgic_its_cmd_class, vgic_its_cmd_inv,
+ TP_PROTO(__u32 device_id, __u32 event_id),
+ TP_ARGS(device_id, event_id));
+
+TRACE_EVENT(vgic_its_cmd_mapd,
+ TP_PROTO(__u32 device_id, bool valid, __u8 num_eventid_bits, __u64 itt_addr),
+ TP_ARGS(device_id, valid, num_eventid_bits, itt_addr),
+
+ TP_STRUCT__entry(
+ __field( __u32, device_id )
+ __field( bool, valid )
+ __field( __u8, num_eventid_bits )
+ __field( __u64, itt_addr )
+ ),
+
+ TP_fast_assign(
+ __entry->device_id = device_id;
+ __entry->valid = valid;
+ __entry->num_eventid_bits = num_eventid_bits;
+ __entry->itt_addr = itt_addr;
+ ),
+
+ TP_printk("Device ID: %u, valid: %d, num_eventid_bits: %u, itt_addr: %llx",
+ __entry->device_id, __entry->valid,
+ __entry->num_eventid_bits, __entry->itt_addr)
+);
+
+TRACE_EVENT(vgic_its_cmd_mapc,
+ TP_PROTO(__u32 collection_id, bool valid),
+ TP_ARGS(collection_id, valid),
+
+ TP_STRUCT__entry(
+ __field( __u32, collection_id )
+ __field( bool, valid )
+ ),
+
+ TP_fast_assign(
+ __entry->collection_id = collection_id;
+ __entry->valid = valid;
+ ),
+
+ TP_printk("Collection ID: %u, valid: %d",
+ __entry->collection_id, __entry->valid)
+);
+
+TRACE_EVENT(vgic_its_cmd_movi,
+ TP_PROTO(__u32 device_id, __u32 event_id, __u32 collection_id),
+ TP_ARGS(device_id, event_id, collection_id),
+
+ TP_STRUCT__entry(
+ __field( __u32, device_id )
+ __field( __u32, event_id )
+ __field( __u32, collection_id )
+ ),
+
+ TP_fast_assign(
+ __entry->device_id = device_id;
+ __entry->event_id = event_id;
+ __entry->collection_id = collection_id;
+ ),
+
+ TP_printk("Device ID: %u, Event ID: %u, Collection ID: %u",
+ __entry->device_id, __entry->event_id, __entry->collection_id)
+);
+
+TRACE_EVENT(vgic_its_cmd_movall,
+ TP_PROTO(int vcpu_source, int vcpu_target),
+ TP_ARGS(vcpu_source, vcpu_target),
+
+ TP_STRUCT__entry(
+ __field( int, vcpu_source )
+ __field( int, vcpu_target )
+ ),
+
+ TP_fast_assign(
+ __entry->vcpu_source = vcpu_source;
+ __entry->vcpu_target = vcpu_target;
+ ),
+
+ TP_printk("Source VCPU: %d, Target VCPU: %d",
+ __entry->vcpu_source, __entry->vcpu_target)
+);
+
+TRACE_EVENT(vgic_its_cmd_invall,
+ TP_PROTO(__u32 collection_id, int vcpu_id),
+ TP_ARGS(collection_id, vcpu_id),
+
+ TP_STRUCT__entry(
+ __field( __u32, collection_id )
+ __field( int, vcpu_id )
+ ),
+
+ TP_fast_assign(
+ __entry->collection_id = collection_id;
+ __entry->vcpu_id = vcpu_id;
+ ),
+
+ TP_printk("Collection ID: %u, VCPU ID: %d",
+ __entry->collection_id, __entry->vcpu_id)
+);
+
#endif /* _TRACE_VGIC_H */
#undef TRACE_INCLUDE_PATH
@@ -22,6 +22,7 @@
#include "vgic.h"
#include "vgic-mmio.h"
+#include "trace.h"
static struct kvm_device_ops kvm_arm_vgic_its_ops;
@@ -795,6 +796,8 @@ static int vgic_its_cmd_handle_discard(struct kvm *kvm, struct vgic_its *its,
u32 event_id = its_cmd_get_id(its_cmd);
struct its_ite *ite;
+ trace_vgic_its_cmd_discard(device_id, event_id);
+
ite = find_ite(its, device_id, event_id);
if (ite && its_is_collection_mapped(ite->collection)) {
struct its_device *device = find_its_device(its, device_id);
@@ -829,6 +832,8 @@ static int vgic_its_cmd_handle_movi(struct kvm *kvm, struct vgic_its *its,
struct its_ite *ite;
struct its_collection *collection;
+ trace_vgic_its_cmd_movi(device_id, event_id, coll_id);
+
ite = find_ite(its, device_id, event_id);
if (!ite)
return E_ITS_MOVI_UNMAPPED_INTERRUPT;
@@ -1035,6 +1040,8 @@ static int vgic_its_cmd_handle_mapi(struct kvm *kvm, struct vgic_its *its,
struct vgic_irq *irq;
int lpi_nr;
+ trace_vgic_its_cmd_mapi(device_id, event_id);
+
device = find_its_device(its, device_id);
if (!device)
return E_ITS_MAPTI_UNMAPPED_DEVICE;
@@ -1161,6 +1168,8 @@ static int vgic_its_cmd_handle_mapd(struct kvm *kvm, struct vgic_its *its,
struct its_device *device;
gpa_t gpa;
+ trace_vgic_its_cmd_mapd(device_id, valid, num_eventid_bits, itt_addr);
+
if (!vgic_its_check_id(its, its->baser_device_table, device_id, &gpa))
return E_ITS_MAPD_DEVICE_OOR;
@@ -1204,6 +1213,8 @@ static int vgic_its_cmd_handle_mapc(struct kvm *kvm, struct vgic_its *its,
valid = its_cmd_get_validbit(its_cmd);
coll_id = its_cmd_get_collection(its_cmd);
+ trace_vgic_its_cmd_mapc(coll_id, valid);
+
if (!valid) {
vgic_its_free_collection(its, coll_id);
vgic_its_invalidate_cache(its);
@@ -1248,6 +1259,7 @@ static int vgic_its_cmd_handle_clear(struct kvm *kvm, struct vgic_its *its,
u32 event_id = its_cmd_get_id(its_cmd);
struct its_ite *ite;
+ trace_vgic_its_cmd_clear(device_id, event_id);
ite = find_ite(its, device_id, event_id);
if (!ite)
@@ -1278,6 +1290,7 @@ static int vgic_its_cmd_handle_inv(struct kvm *kvm, struct vgic_its *its,
u32 event_id = its_cmd_get_id(its_cmd);
struct its_ite *ite;
+ trace_vgic_its_cmd_inv(device_id, event_id);
ite = find_ite(its, device_id, event_id);
if (!ite)
@@ -1338,6 +1351,8 @@ static int vgic_its_cmd_handle_invall(struct kvm *kvm, struct vgic_its *its,
vcpu = collection_to_vcpu(kvm, collection);
vgic_its_invall(vcpu);
+ trace_vgic_its_cmd_invall(coll_id, vcpu->vcpu_id);
+
return 0;
}
@@ -1364,6 +1379,8 @@ static int vgic_its_cmd_handle_movall(struct kvm *kvm, struct vgic_its *its,
if (!vcpu1 || !vcpu2)
return E_ITS_MOVALL_PROCNUM_OOR;
+ trace_vgic_its_cmd_movall(vcpu1->vcpu_id, vcpu2->vcpu_id);
+
if (vcpu1 == vcpu2)
return 0;
@@ -1392,6 +1409,8 @@ static int vgic_its_cmd_handle_int(struct kvm *kvm, struct vgic_its *its,
u32 msi_data = its_cmd_get_id(its_cmd);
u64 msi_devid = its_cmd_get_deviceid(its_cmd);
+ trace_vgic_its_cmd_int(msi_devid, msi_data);
+
return vgic_its_trigger_msi(kvm, its, msi_devid, msi_data);
}
This commit adds tracepoints to the KVM VGIC ITS on ARM64 to improve observability and debuggability. The following ITS commands now have associated tracepoints: MAPI, DISCARD, CLEAR, INT, INV, MAPD, MAPC, MOVI, MOVALL, and INVALL. Each tracepoint captures essential information such as device ID, event ID, and other relevant parameters, allowing for detailed monitoring of ITS operations. These tracepoints are useful for: * Debugging interrupt routing issues. * Performance analysis and optimization. * Understanding ITS behavior. * Root-causing interrupt handling errors. This enhancement provides crucial insights into interrupt handling in ARM64 virtualized environments, aiding in development, debugging, and maintenance. Signed-off-by: Jing Zhang <jingzhangos@google.com> --- arch/arm64/kvm/vgic/trace.h | 135 +++++++++++++++++++++++++++++++++ arch/arm64/kvm/vgic/vgic-its.c | 19 +++++ 2 files changed, 154 insertions(+)