From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B823A366567 for ; Fri, 20 Mar 2026 13:22:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774012953; cv=none; b=gYm5/EXqkjwPV3JWWdEljrUSPBycssVWffnbwDhM/n3TwEARifbxD/aUhpthK14JuaUdPwk+/NIe/lyxbUivixRcZpGu8EBaOEjG4/rhFDN0LEXD363styHP3L7rMukbjLaWiTuvf4gKeAMb+nL0ILnI60bIGRHQ3c7JkbVX9s4= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774012953; c=relaxed/simple; bh=PGEc4KC2iWY9rDhQYE7v/0YdgSyfeejBfw29Au/4+4o=; h=Date:Message-ID:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=cuM2hVmdj+46t9iu2yv50YlKZsaDe0aeVPqSbiqbKCLmnGpYZdWQ8fa8/sX0EN3k7BUmhmvIT2SMkOlYjZykSoS+LT9dWvgqUWrwoYH1xpZY1J3k9NKUIT5mC31Yh+w77SpH0lvN0Vf9/zTK6uSK4Nzip3papHh6yRKZd6mdUK8= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=YeTHY5nH; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="YeTHY5nH" Received: by smtp.kernel.org (Postfix) with ESMTPSA id CE31DC4CEF7; Fri, 20 Mar 2026 13:22:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774012953; bh=PGEc4KC2iWY9rDhQYE7v/0YdgSyfeejBfw29Au/4+4o=; h=Date:From:To:Cc:Subject:References:From; b=YeTHY5nHP16hakIESMydL8ed1LovNmWHfaggRP4k74x2QrhHsky/z/4S0L0vSiNgK HweyygbkQF8imKhgTrVvOaJtrokBMj1/45+WR+15fWVWp5eskggqqCE5aCKgrV/lyk 5QmRReZtGZHGG8V/g3nF6GL3BWoVCyBqawtP4zR9riddjMMf4K3+951kffxGCQr59W 3SBXYvEC22vOMwpa2jGfvCjrZ30R4D08bE9WKVya8CaRNEXfdSpunI/wJxtJvddMW0 9K88LCXpgSCTRdOQb75NsfiTO2bwxNFlfYHzG9OKqqJsGMzuLQkTHoX3oJffFYu8nc rfQsU5tjbghdQ== Date: Fri, 20 Mar 2026 14:22:29 +0100 Message-ID: <20260320132102.910277045@kernel.org> User-Agent: quilt/0.68 From: Thomas Gleixner To: LKML Cc: x86@kernel.org, Dmitry Ilvokhin , Neil Horman , Radu Rendec Subject: [patch v2 13/14] [RFC] genirq/proc: Provide architecture specific binary statistics References: <20260320131108.344376329@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Provide a binary statistics interface similar to the per device and per CPU interfaces to access the architecture specific interrupt statistics. The architecture has to select it in Kconfig and provide an accessor to the per CPU interrupt information and the number of architecture specific entries. The entries are ordered by a numerical index starting from 0, which corresponds to the ordering of those interrupts in /proc/interrupt. The output format is the same as for the per device and per CPU interfaces and only contains entries which have an interrupt count > 0. Reading the architecture specific counters of a 256 CPU x86 system takes 36us kernel time for 6 interrupts with non-zero counts and produces about 10k of data. Signed-off-by: Thomas Gleixner --- kernel/irq/Kconfig | 3 ++ kernel/irq/proc.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) --- a/kernel/irq/Kconfig +++ b/kernel/irq/Kconfig @@ -18,6 +18,9 @@ config GENERIC_IRQ_SHOW config GENERIC_IRQ_SHOW_LEVEL bool +config GENERIC_IRQ_STATS_ARCH + bool + config GENERIC_IRQ_STATS_PERCPU bool --- a/kernel/irq/proc.c +++ b/kernel/irq/proc.c @@ -945,6 +945,61 @@ static __init void irq_pcp_stats_init(vo static inline void irq_pcp_stats_init(void) { } #endif /* !CONFIG_GENERIC_IRQ_STATS_PERCPU */ +#ifdef CONFIG_GENERIC_IRQ_STATS_ARCH +static inline void arch_stat_update_one(struct irq_proc_stat *s) +{ + struct irq_proc_stat_data *d = s->data; + unsigned int cpu, idx = s->irqnr; + + for_each_online_cpu(cpu) { + struct irq_proc_stat_cpu pcpu = { + .cpu = cpu, + .cnt = arch_get_irq_stat(cpu, idx), + }; + + if (pcpu.cnt) + d->pcpu[d->entries++] = pcpu; + } + + if (d->entries) { + d->irqnr = idx; + s->count = sizeof(*d) + d->entries * sizeof(*d->pcpu); + } +} + +static __always_inline bool arch_stat_next_data(struct irq_proc_stat *s) +{ + if (unlikely(s->first)) { + s->irqnr = 0; + s->first = false; + } + + for(; !s->count && s->irqnr < ARCH_IRQ_STATS_NUM_IRQS; s->irqnr++) + arch_stat_update_one(s); + return !!s->count; +} + +static ssize_t irq_arch_stats_read(struct kiocb *iocb, struct iov_iter *iter) +{ + return __irq_stats_read(iocb, iter, arch_stat_next_data); +} + +static const struct proc_ops irq_arch_stat_ops = { + .proc_flags = PROC_ENTRY_PERMANENT, + .proc_open = irq_stats_open, + .proc_release = irq_stats_release, + .proc_read_iter = irq_arch_stats_read, + .proc_lseek = irq_stats_llseek, +}; + +static __init void irq_arch_stats_init(void) +{ + proc_create("arch_stats", 0, root_irq_dir, &irq_arch_stat_ops); +} +#else /* CONFIG_GENERIC_IRQ_STATS_ARCH */ +static inline void irq_arch_stats_init(void) { } +#endif /* !CONFIG_GENERIC_IRQ_STATS_ARCH */ + static int __init irq_proc_init(void) { proc_create_seq("interrupts", 0, NULL, &irq_seq_ops); @@ -953,6 +1008,7 @@ static int __init irq_proc_init(void) proc_create("device_stats", 0, root_irq_dir, &irq_dev_stat_ops); irq_pcp_stats_init(); + irq_arch_stats_init(); return 0; } fs_initcall(irq_proc_init);