From patchwork Mon Jan 13 19:31:27 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jing Zhang X-Patchwork-Id: 13937940 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id C2ECBC02180 for ; Mon, 13 Jan 2025 19:34:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Type:Cc:To:From: Subject:Message-ID:References:Mime-Version:In-Reply-To:Date:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=2PWimBk5DhwL9cF43Xhuc6g6cWmEmAEK8mMsdBs1h1s=; b=ARX+ItRshx7kZ2mJRT1F8m758i iwnjg63/ei+gp5tgD2xAULyoh0MOb2FOhpDnBm6uwE/ri++bZ6tCb7feInIqOfXoSdDH20C3c7uEI f/Ra3DeA/Tct7WNcMtZTKKppEkgILPhsTocy/kn1cenl89SKTszg6+7/Kom6g9cbSpj6vIjkuIalo 7l576I2/2DSlRAPF7ga60RzNx3J9pQrgdODCO78oElAjKIG6oF9TPOAXLYALwFYNANaUGm4azobNM 4m8W+swoFr6p5TiwdxRWkHb6IUGEtUD69ETlDFwRSCayiYywrlNH14zxZ5N2jlsT+z74IEv4MYmi+ y/PeuVYQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tXQCN-00000006OwC-3v0x; Mon, 13 Jan 2025 19:34:07 +0000 Received: from mail-pl1-x64a.google.com ([2607:f8b0:4864:20::64a]) by bombadil.infradead.org with esmtps (Exim 4.98 #2 (Red Hat Linux)) id 1tXQ9v-00000006OII-35N3 for linux-arm-kernel@lists.infradead.org; Mon, 13 Jan 2025 19:31:36 +0000 Received: by mail-pl1-x64a.google.com with SMTP id d9443c01a7336-2166f9f52fbso142522525ad.2 for ; Mon, 13 Jan 2025 11:31:34 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1736796694; x=1737401494; darn=lists.infradead.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=2PWimBk5DhwL9cF43Xhuc6g6cWmEmAEK8mMsdBs1h1s=; b=VHW/NC5g3ukoh0CdhzvBG1LiUzLgtKsMDbXAxyxBy6jl7kfhc6ZjQoAPHMmfIuDELo EX8RdL+3gp4sCp4msdAzQh6FFGFx3Oi1UUoXVeRe+o0RzScE3x/E8675ncYQ6y+43E5v vBLCec2gtYE+nCGIzrj/157eiuCK59wHA1Qe9gI7Y40S7LuUEu/ScKMryMPM17JRfO4O mSJFfdd2+KdzqG0EZPldtbWEgrN/NwgwEGJtmpwpBABGhPscciy6VaKk1eUUEOx5wXji Xz4Hp7BmNQGVCb1B5dFDjgTY9Z4RfKc6x0eBXZMKN/hS9yiBY9y7qR2C5Afft4gftrPx uJ2w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1736796694; x=1737401494; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=2PWimBk5DhwL9cF43Xhuc6g6cWmEmAEK8mMsdBs1h1s=; b=vr6T5XkRhXL5tm8dsg3wa3FTuDR8BeQXpZlmHLfDre0wt9h+unIbShlv3jqmls8C/U bm9cLJblqVErn+uqgtAheIV9ZNqYCuZveJeFj7/Ml0/iBcpKyJktN4Wxqmng8cGYZ0PR JUKkwOaOFm9FKihFTnhvjROQPaXSsT3q+10UsmZ8SaXwUh9cxrosfKNnjW8UXyA/t/ss qzL7f0iX9R7nGrOAd16cYuh+anNtW2ADuGtj4qehKgnorAfPbBi1f60EpCI8fssgqUvT TKiO7Bks+JBzHH41FtEeVadi8No1mR0PGpihjImpY76CnKcrdTvmAqEm/WqkK5aQ6/sD sOkQ== X-Forwarded-Encrypted: i=1; AJvYcCUDd24odpUoG4/PZwgAAp4jkOHFAZNoAsQjNi8dJDsQmdol9QqXwYk70idpuLiF6kDchg8jERIIK9EhwSCyvMIc@lists.infradead.org X-Gm-Message-State: AOJu0Yz8k/5dGK9QAKk2p+GH/WZ7q1WpEX2Afz/3irxzuMPJvkBSdFwW tjTBduAi8p6A/wfxDVZBCqsdvHfUotd4LILOTv+IqhEMFum7kKitBWTvlAksGBQKMFL93EplnDF K0S+pPapobW51Y0OSKF2mKg== X-Google-Smtp-Source: AGHT+IE53D6sRek6iO0DXKKc/drL2kO78dR/t9m8UV/64TjSz8QuQZBuhOrcyZOy57H9+hzVq/ih8zpJhVPFYciB2Q== X-Received: from plbkl14.prod.google.com ([2002:a17:903:74e:b0:215:57bd:17e7]) (user=jingzhangos job=prod-delivery.src-stubby-dispatcher) by 2002:a17:902:e74f:b0:216:7cde:523 with SMTP id d9443c01a7336-21a83f6710dmr367766355ad.32.1736796693775; Mon, 13 Jan 2025 11:31:33 -0800 (PST) Date: Mon, 13 Jan 2025 11:31:27 -0800 In-Reply-To: <20250113193128.1533449-1-jingzhangos@google.com> Mime-Version: 1.0 References: <20250113193128.1533449-1-jingzhangos@google.com> X-Mailer: git-send-email 2.47.1.688.g23fc6f90ad-goog Message-ID: <20250113193128.1533449-2-jingzhangos@google.com> Subject: [RFC PATCH 1/2] KVM: arm64: vgic-its: Add debugfs interface to expose ITS tables From: Jing Zhang To: KVMARM , ARMLinux Cc: Marc Zyngier , Oliver Upton , Joey Gouly , Zenghui Yu , Suzuki K Poulose , Jing Zhang X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20250113_113135_783289_6CC57456 X-CRM114-Status: GOOD ( 32.53 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org This commit introduces a debugfs interface to display the contents of the VGIC Interrupt Translation Service (ITS) tables. The ITS tables map Device/Event IDs to Interrupt IDs and target processors. Exposing this information through debugfs allows for easier inspection and debugging of the interrupt routing configuration. The debugfs interface presents the ITS table data in a tabular format: Device ID: 0, Event ID Range: [0 - 65535] EVENT_ID INTID HWINTID TARGET COL_ID HW ----------------------------------------------- 0 32 0 0 0 0 1 33 0 0 0 0 2 34 0 0 0 0 ... ... ... ... ... .. The output is generated using the seq_file interface, allowing for efficient handling of potentially large ITS tables. This interface is read-only and does not allow modification of the ITS tables. It is intended for debugging and informational purposes only. Signed-off-by: Jing Zhang --- arch/arm64/kvm/Makefile | 2 +- arch/arm64/kvm/vgic/vgic-its-debug.c | 234 +++++++++++++++++++++++++++ arch/arm64/kvm/vgic/vgic-its.c | 39 +---- arch/arm64/kvm/vgic/vgic.h | 33 ++++ 4 files changed, 276 insertions(+), 32 deletions(-) create mode 100644 arch/arm64/kvm/vgic/vgic-its-debug.c diff --git a/arch/arm64/kvm/Makefile b/arch/arm64/kvm/Makefile index 3cf7adb2b503..b1e7b9c29589 100644 --- a/arch/arm64/kvm/Makefile +++ b/arch/arm64/kvm/Makefile @@ -23,7 +23,7 @@ kvm-y += arm.o mmu.o mmio.o psci.o hypercalls.o pvtime.o \ vgic/vgic-v3.o vgic/vgic-v4.o \ vgic/vgic-mmio.o vgic/vgic-mmio-v2.o \ vgic/vgic-mmio-v3.o vgic/vgic-kvm-device.o \ - vgic/vgic-its.o vgic/vgic-debug.o + vgic/vgic-its.o vgic/vgic-debug.o vgic/vgic-its-debug.o kvm-$(CONFIG_HW_PERF_EVENTS) += pmu-emul.o pmu.o kvm-$(CONFIG_ARM64_PTR_AUTH) += pauth.o diff --git a/arch/arm64/kvm/vgic/vgic-its-debug.c b/arch/arm64/kvm/vgic/vgic-its-debug.c new file mode 100644 index 000000000000..1ff0dd013793 --- /dev/null +++ b/arch/arm64/kvm/vgic/vgic-its-debug.c @@ -0,0 +1,234 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * vgic-its-debug.c - Debugfs interface for exposing VGIC ITS tables. + * + * Copyright (C) 2025 Google + * + * This file provides a debugfs interface to display the contents of the + * VGIC Interrupt Translation Service (ITS) tables. This allows for + * inspection of the mapping between Event IDs, Interrupt IDs, and target + * processors. The information is presented in a tabular format through a + * seq_file interface. + */ + +#include +#include +#include +#include +#include "vgic.h" + +/** + * struct vgic_its_iter - Iterator for traversing VGIC ITS tables. + * @dev: Pointer to the current its_device being processed. + * @ite: Pointer to the current its_ite within the device being processed. + * + * This structure is used to maintain the current position during iteration + * over the ITS tables. It holds pointers to both the current device and the + * current ITE within that device. + */ +struct vgic_its_iter { + struct its_device *dev; + struct its_ite *ite; +}; + +/** + * end_of_iter - Checks if the iterator has reached the end of the ITS tables. + * @iter: The iterator to check. + * + * Return: True if the iterator is at the end, false otherwise. + */ +static inline bool end_of_iter(struct vgic_its_iter *iter) +{ + return !iter->dev && !iter->ite; +} + +/** + * iter_next - Advances the iterator to the next entry in the ITS tables. + * @its: The VGIC ITS structure. + * @iter: The iterator to advance. + * + * This function moves the iterator to the next ITE within the current device, + * or to the first ITE of the next device if the current ITE is the last in + * the device. If the current device is the last device, the iterator is set + * to indicate the end of iteration. + */ +static void iter_next(struct vgic_its *its, struct vgic_its_iter *iter) +{ + struct its_device *dev = iter->dev; + struct its_ite *ite = iter->ite; + + if (!ite || list_is_last(&ite->ite_list, &dev->itt_head)) { + if (list_is_last(&dev->dev_list, &its->device_list)) { + dev = NULL; + ite = NULL; + } else { + dev = list_next_entry(dev, dev_list); + ite = list_first_entry_or_null(&dev->itt_head, + struct its_ite, + ite_list); + } + } else { + ite = list_next_entry(ite, ite_list); + } + + iter->dev = dev; + iter->ite = ite; +} + +/** + * vgic_its_debug_start - Start function for the seq_file interface. + * @s: The seq_file structure. + * @pos: The starting position (offset). + * + * This function initializes the iterator to the beginning of the ITS tables + * and advances it to the specified position. It acquires the its_lock mutex + * to protect shared data. + * + * Return: An iterator pointer on success, NULL if no devices are found or + * the end of the list is reached, or ERR_PTR(-ENOMEM) on memory + * allocation failure. + */ +static void *vgic_its_debug_start(struct seq_file *s, loff_t *pos) +{ + struct vgic_its *its = s->private; + struct vgic_its_iter *iter; + struct its_device *dev; + loff_t offset = *pos; + + mutex_lock(&its->its_lock); + + dev = list_first_entry_or_null(&its->device_list, + struct its_device, dev_list); + if (!dev) + return NULL; + + iter = kmalloc(sizeof(*iter), GFP_KERNEL); + if (!iter) + return ERR_PTR(-ENOMEM); + + iter->dev = dev; + iter->ite = list_first_entry_or_null(&dev->itt_head, + struct its_ite, ite_list); + + while (!end_of_iter(iter) && offset--) + iter_next(its, iter); + + if (end_of_iter(iter)) { + kfree(iter); + return NULL; + } + + return iter; +} + +/** + * vgic_its_debug_next - Next function for the seq_file interface. + * @s: The seq_file structure. + * @v: The current iterator. + * @pos: The current position (offset). + * + * This function advances the iterator to the next entry and increments the + * position. + * + * Return: An iterator pointer on success, or NULL if the end of the list is + * reached. + */ +static void *vgic_its_debug_next(struct seq_file *s, void *v, loff_t *pos) +{ + struct vgic_its *its = s->private; + struct vgic_its_iter *iter = v; + + ++*pos; + iter_next(its, iter); + + if (end_of_iter(iter)) { + kfree(iter); + return NULL; + } + return iter; +} + +/** + * vgic_its_debug_stop - Stop function for the seq_file interface. + * @s: The seq_file structure. + * @v: The current iterator. + * + * This function frees the iterator and releases the its_lock mutex. + */ +static void vgic_its_debug_stop(struct seq_file *s, void *v) +{ + struct vgic_its *its = s->private; + struct vgic_its_iter *iter = v; + + if (!IS_ERR_OR_NULL(iter)) + kfree(iter); + mutex_unlock(&its->its_lock); +} + +/** + * vgic_its_debug_show - Show function for the seq_file interface. + * @s: The seq_file structure. + * @v: The current iterator. + * + * This function formats and prints the ITS table entry information to the + * seq_file output. + * + * Return: 0 on success. + */ +static int vgic_its_debug_show(struct seq_file *s, void *v) +{ + struct vgic_its_iter *iter = v; + struct its_device *dev = iter->dev; + struct its_ite *ite = iter->ite; + + if (list_is_first(&ite->ite_list, &dev->itt_head)) { + seq_printf(s, "\n"); + seq_printf(s, "Device ID: %u, Event ID Range: [0 - %llu]\n", + dev->device_id, BIT_ULL(dev->num_eventid_bits) - 1); + seq_printf(s, "EVENT_ID INTID HWINTID TARGET COL_ID HW\n"); + seq_printf(s, "-----------------------------------------------\n"); + } + + if (ite && ite->irq && ite->collection) { + seq_printf(s, "%8u %8u %8u %8u %8u %2d\n", + ite->event_id, ite->irq->intid, ite->irq->hwintid, + ite->collection->target_addr, + ite->collection->collection_id, ite->irq->hw); + } + + return 0; +} + +static const struct seq_operations vgic_its_debug_sops = { + .start = vgic_its_debug_start, + .next = vgic_its_debug_next, + .stop = vgic_its_debug_stop, + .show = vgic_its_debug_show +}; + +DEFINE_SEQ_ATTRIBUTE(vgic_its_debug); + +/** + * vgic_its_debug_init - Initializes the debugfs interface for VGIC ITS. + * @dev: The KVM device structure. + * + * This function creates a debugfs file named "vgic-its-state@%its_base" + * to expose the ITS table information. + * + * Return: 0 on success. + */ +int vgic_its_debug_init(struct kvm_device *dev) +{ + struct vgic_its *its = dev->private; + char name[32]; + + snprintf(name, sizeof(name), "vgic-its-state@%llx", (u64)its->vgic_its_base); + debugfs_create_file(name, 0444, dev->kvm->debugfs_dentry, its, &vgic_its_debug_fops); + + return 0; +} + +void vgic_its_debug_destroy(struct kvm_device *dev) +{ +} + diff --git a/arch/arm64/kvm/vgic/vgic-its.c b/arch/arm64/kvm/vgic/vgic-its.c index fb96802799c6..569f9da9049f 100644 --- a/arch/arm64/kvm/vgic/vgic-its.c +++ b/arch/arm64/kvm/vgic/vgic-its.c @@ -154,36 +154,6 @@ static struct vgic_irq *vgic_add_lpi(struct kvm *kvm, u32 intid, return irq; } -struct its_device { - struct list_head dev_list; - - /* the head for the list of ITTEs */ - struct list_head itt_head; - u32 num_eventid_bits; - gpa_t itt_addr; - u32 device_id; -}; - -#define COLLECTION_NOT_MAPPED ((u32)~0) - -struct its_collection { - struct list_head coll_list; - - u32 collection_id; - u32 target_addr; -}; - -#define its_is_collection_mapped(coll) ((coll) && \ - ((coll)->target_addr != COLLECTION_NOT_MAPPED)) - -struct its_ite { - struct list_head ite_list; - - struct vgic_irq *irq; - struct its_collection *collection; - u32 event_id; -}; - /** * struct vgic_its_abi - ITS abi ops and settings * @cte_esz: collection table entry size @@ -1938,6 +1908,8 @@ static void vgic_its_destroy(struct kvm_device *kvm_dev) mutex_lock(&its->its_lock); + vgic_its_debug_destroy(kvm_dev); + vgic_its_free_device_list(kvm, its); vgic_its_free_collection_list(kvm, its); vgic_its_invalidate_cache(its); @@ -2771,7 +2743,12 @@ static int vgic_its_set_attr(struct kvm_device *dev, if (ret) return ret; - return vgic_register_its_iodev(dev->kvm, its, addr); + ret = vgic_register_its_iodev(dev->kvm, its, addr); + if (ret) + return ret; + + return vgic_its_debug_init(dev); + } case KVM_DEV_ARM_VGIC_GRP_CTRL: return vgic_its_ctrl(dev->kvm, its, attr->attr); diff --git a/arch/arm64/kvm/vgic/vgic.h b/arch/arm64/kvm/vgic/vgic.h index 122d95b4e284..c2891d7b5e62 100644 --- a/arch/arm64/kvm/vgic/vgic.h +++ b/arch/arm64/kvm/vgic/vgic.h @@ -172,6 +172,36 @@ struct vgic_reg_attr { gpa_t addr; }; +struct its_device { + struct list_head dev_list; + + /* the head for the list of ITTEs */ + struct list_head itt_head; + u32 num_eventid_bits; + gpa_t itt_addr; + u32 device_id; +}; + +#define COLLECTION_NOT_MAPPED ((u32)~0) + +struct its_collection { + struct list_head coll_list; + + u32 collection_id; + u32 target_addr; +}; + +#define its_is_collection_mapped(coll) ((coll) && \ + ((coll)->target_addr != COLLECTION_NOT_MAPPED)) + +struct its_ite { + struct list_head ite_list; + + struct vgic_irq *irq; + struct its_collection *collection; + u32 event_id; +}; + int vgic_v3_parse_attr(struct kvm_device *dev, struct kvm_device_attr *attr, struct vgic_reg_attr *reg_attr); int vgic_v2_parse_attr(struct kvm_device *dev, struct kvm_device_attr *attr, @@ -353,4 +383,7 @@ static inline bool kvm_has_gicv3(struct kvm *kvm) return kvm_has_feat(kvm, ID_AA64PFR0_EL1, GIC, IMP); } +int vgic_its_debug_init(struct kvm_device *dev); +void vgic_its_debug_destroy(struct kvm_device *dev); + #endif From patchwork Mon Jan 13 19:31:28 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jing Zhang X-Patchwork-Id: 13937962 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 7F450C02183 for ; Mon, 13 Jan 2025 19:35:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Type:Cc:To:From: Subject:Message-ID:References:Mime-Version:In-Reply-To:Date:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=AjSHhLfzPpweAeruuV41TxV8cjx61KJKZIlFZE69SAQ=; b=VhYMLwT0/YMzJ0YhMym1QS6szI iIqop/U7fOsKixe9O+19D3uFPXKE8129sAsjSRx/A8cQsxkdaUKLC5ZTQ7lIIBIeiTFXZ/iTRUMJ2 35Hubfsnb0BDx65SNKRm/41mKBf3FFyIDNUl465WobJXiARtTpJylo2LL9f9oGVkvSAtqfGIXtnbD +mFB6TmBebohofxP7c4NxFJ/8uAHGh5zkPJqNcTeJ68ymIAs5MVIHFqKfew8rX5olWTHw7YjG8PZt hg/vLpUXRwqm62GuBOVFu/YbHK2f1/e83wzsDs59W/S7jVTG6kwkNWorVc19RafNa5uVuf5w2UdSA ZY27PsQA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tXQDb-00000006PGu-2RV4; Mon, 13 Jan 2025 19:35:23 +0000 Received: from mail-pj1-x104a.google.com ([2607:f8b0:4864:20::104a]) by bombadil.infradead.org with esmtps (Exim 4.98 #2 (Red Hat Linux)) id 1tXQ9w-00000006OIa-2CTk for linux-arm-kernel@lists.infradead.org; Mon, 13 Jan 2025 19:31:37 +0000 Received: by mail-pj1-x104a.google.com with SMTP id 98e67ed59e1d1-2ee5668e09bso8326836a91.3 for ; Mon, 13 Jan 2025 11:31:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1736796695; x=1737401495; darn=lists.infradead.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=AjSHhLfzPpweAeruuV41TxV8cjx61KJKZIlFZE69SAQ=; b=A5Xb9BGt4bds53XoOwzdTPOkW/PzgdzwpeVdpFSohoPmlH7OJRA8/6k3t5+dzeXoDX 1OSioYgwJ0zzbm5O+kk/e+kP3ObcR8M3GBLoU9LuXM+gjkFsOAIcbbbrz9wltAsKgKR1 qZ3dUh/OoulqsCR9HeZMuc9x9ixZIHh9No8vwrTpW5SuIn+6IfUu2MX4/CWrQdqfb+lD GrYEUbVrsp8GDv+/qNcCC+WR6MM/HlMg9sBiay5vOY7fn3IWhMMrHhpOjvZgkHOIcQRW H/bt1WGJVZXEiXGmmiV94D3PB2ff64UC7XjNIEva25IAWVVtsjNl8TsCAChHz09bHvfl ZENA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1736796695; x=1737401495; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=AjSHhLfzPpweAeruuV41TxV8cjx61KJKZIlFZE69SAQ=; b=A+IkAr+v2xY3DA19wT/iXkAm9+RnxAIOiySgzhlYJA3m87/wUYtAD0N2O019aMN50Y SYN4VobNcEaew4OawpAcqvG7G1j3Ilt9T6MBiktXTLNWUeDZOAOWkvUY1LwQGWVW36GD RDlk/IOj2U3ty2dsyEwpligcN6Zv5D2f+tAZkn7yH0M/Q9qKZXPI+AYzzv9dIJ4eee0l 938zeXh996yUmlCrRdKynXLNRIX7b6T5Fmx0d8nw5xolvtTxV0lKEXf84fBAbpXeaOIj GJ/uaSilPXvTlZlvmOZc7IfGOTrHdlASCZ8zEW9nNbMKX8wOeY0wkdI23SVuHwcw9Pd7 cvbQ== X-Forwarded-Encrypted: i=1; AJvYcCVTkaZZMkd4RzQn00ATFt4aRIasXEbfX+0AWJ3ZwcPj4c6I9rh93XOn1ArIt+qbMZsPsLVJ3/RuguqJBCPj+XME@lists.infradead.org X-Gm-Message-State: AOJu0Yym5HKgexDqh5RoiHoOElp5Xk4fez/LNL0TfGxw8m6bLPlV5NL0 nG5C2wcMXB99EUWur6caTa8Cu3BzUllLnw4WqF4qZiEvP94miDDQ5yYmMgLlhUjMOZ5qanm68i9 JC8oyA6o1FGX/iFSntaNFZA== X-Google-Smtp-Source: AGHT+IHgy/xhjs0ZlLXfoJvzHD/baMNuiYAMQ8oeX9ah+6G+BrGfVdNx/nIjUYcPrD4FhCjo+aJMyh+mafTgb4aApA== X-Received: from pjbsw3.prod.google.com ([2002:a17:90b:2c83:b0:2f4:3ea1:9033]) (user=jingzhangos job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90b:2f4e:b0:2eb:140d:f6df with SMTP id 98e67ed59e1d1-2f548e98382mr28470262a91.1.1736796695319; Mon, 13 Jan 2025 11:31:35 -0800 (PST) Date: Mon, 13 Jan 2025 11:31:28 -0800 In-Reply-To: <20250113193128.1533449-1-jingzhangos@google.com> Mime-Version: 1.0 References: <20250113193128.1533449-1-jingzhangos@google.com> X-Mailer: git-send-email 2.47.1.688.g23fc6f90ad-goog Message-ID: <20250113193128.1533449-3-jingzhangos@google.com> Subject: [RFC PATCH 2/2] KVM: arm64: vgic-its: Add tracepoints for VGIC ITS commands From: Jing Zhang To: KVMARM , ARMLinux Cc: Marc Zyngier , Oliver Upton , Joey Gouly , Zenghui Yu , Suzuki K Poulose , Jing Zhang X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20250113_113136_566655_CBD57764 X-CRM114-Status: GOOD ( 13.44 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org 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 --- arch/arm64/kvm/vgic/trace.h | 135 +++++++++++++++++++++++++++++++++ arch/arm64/kvm/vgic/vgic-its.c | 19 +++++ 2 files changed, 154 insertions(+) diff --git a/arch/arm64/kvm/vgic/trace.h b/arch/arm64/kvm/vgic/trace.h index 83c64401a7fc..22953c0ef159 100644 --- a/arch/arm64/kvm/vgic/trace.h +++ b/arch/arm64/kvm/vgic/trace.h @@ -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 diff --git a/arch/arm64/kvm/vgic/vgic-its.c b/arch/arm64/kvm/vgic/vgic-its.c index 569f9da9049f..d7524e3abad6 100644 --- a/arch/arm64/kvm/vgic/vgic-its.c +++ b/arch/arm64/kvm/vgic/vgic-its.c @@ -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); }