* [PATCH 7.2 v10 2/2] x86/tlb: skip redundant sync IPIs for native TLB flush
From: Lance Yang @ 2026-04-24 6:25 UTC (permalink / raw)
To: akpm
Cc: peterz, david, dave.hansen, dave.hansen, ypodemsk, hughd, will,
aneesh.kumar, npiggin, tglx, mingo, bp, x86, hpa, arnd, ljs, ziy,
baolin.wang, Liam.Howlett, npache, ryan.roberts, dev.jain, baohua,
shy828301, riel, jannh, jgross, seanjc, pbonzini, boris.ostrovsky,
virtualization, kvm, linux-arch, linux-mm, linux-kernel,
ioworker0, Lance Yang
In-Reply-To: <20260424062528.71951-1-lance.yang@linux.dev>
From: Lance Yang <lance.yang@linux.dev>
Some page table operations need to synchronize with software/lockless
walkers after a TLB flush by calling tlb_remove_table_sync_{one,rcu}().
On x86, that extra synchronization is redundant when the preceding TLB
flush already broadcast IPIs to all relevant CPUs.
native_pv_tlb_init() checks whether native_flush_tlb_multi() is in use.
On CONFIG_PARAVIRT systems, it checks pv_ops; on non-PARAVIRT, native
flush is always in use.
It decides once at boot whether to enable the optimization: if using
native TLB flush and INVLPGB is not supported, we know IPIs were sent
and can skip the redundant sync. The decision is fixed via a static
key as Peter suggested[1].
PV backends (KVM, Xen, Hyper-V) typically have their own implementations
and don't call native_flush_tlb_multi() directly, so they cannot be trusted
to provide the IPI guarantees we need.
Also rename the x86 flush_tlb_info bit from freed_tables to wake_lazy_cpus,
as Dave suggested[2], to match the behavior it controls: whether the remote
flush may skip CPUs in lazy TLB mode. Both freed_tables and unshared_tables
set it, because lazy-TLB CPUs must receive IPIs before page tables can be
freed or reused. With that guarantee in place,
tlb_table_flush_implies_ipi_broadcast() can safely skip the later sync IPI.
Two-step plan as David suggested[3]:
Step 1 (this patch): Skip redundant sync when we're 100% certain the TLB
flush sent IPIs. INVLPGB is excluded because when supported, we cannot
guarantee IPIs were sent, keeping it clean and simple.
Step 2 (future work): Send targeted IPIs only to CPUs actually doing
software/lockless page table walks, benefiting all architectures.
Regarding Step 2, it obviously only applies to setups where Step 1 does
not apply: like x86 with INVLPGB or arm64.
[1] https://lore.kernel.org/linux-mm/20260302145652.GH1395266@noisy.programming.kicks-ass.net/
[2] https://lore.kernel.org/linux-mm/f856051b-10c7-4d65-9dbe-6b1677af74bd@intel.com/
[3] https://lore.kernel.org/linux-mm/bbfdf226-4660-4949-b17b-0d209ee4ef8c@kernel.org/
Suggested-by: Dave Hansen <dave.hansen@intel.com>
Suggested-by: Peter Zijlstra <peterz@infradead.org>
Suggested-by: David Hildenbrand (Arm) <david@kernel.org>
Signed-off-by: Lance Yang <lance.yang@linux.dev>
---
arch/x86/hyperv/mmu.c | 4 ++--
arch/x86/include/asm/tlb.h | 19 +++++++++++++++-
arch/x86/include/asm/tlbflush.h | 6 +++--
arch/x86/kernel/smpboot.c | 1 +
arch/x86/mm/tlb.c | 39 +++++++++++++++++++++++----------
5 files changed, 52 insertions(+), 17 deletions(-)
diff --git a/arch/x86/hyperv/mmu.c b/arch/x86/hyperv/mmu.c
index cfcb60468b01..2cf1eeaffd6f 100644
--- a/arch/x86/hyperv/mmu.c
+++ b/arch/x86/hyperv/mmu.c
@@ -63,7 +63,7 @@ static void hyperv_flush_tlb_multi(const struct cpumask *cpus,
struct hv_tlb_flush *flush;
u64 status;
unsigned long flags;
- bool do_lazy = !info->freed_tables;
+ bool do_lazy = !info->wake_lazy_cpus;
trace_hyperv_mmu_flush_tlb_multi(cpus, info);
@@ -198,7 +198,7 @@ static u64 hyperv_flush_tlb_others_ex(const struct cpumask *cpus,
flush->hv_vp_set.format = HV_GENERIC_SET_SPARSE_4K;
nr_bank = cpumask_to_vpset_skip(&flush->hv_vp_set, cpus,
- info->freed_tables ? NULL : cpu_is_lazy);
+ info->wake_lazy_cpus ? NULL : cpu_is_lazy);
if (nr_bank < 0)
return HV_STATUS_INVALID_PARAMETER;
diff --git a/arch/x86/include/asm/tlb.h b/arch/x86/include/asm/tlb.h
index 866ea78ba156..fb256fd95f95 100644
--- a/arch/x86/include/asm/tlb.h
+++ b/arch/x86/include/asm/tlb.h
@@ -5,22 +5,39 @@
#define tlb_flush tlb_flush
static inline void tlb_flush(struct mmu_gather *tlb);
+#define tlb_table_flush_implies_ipi_broadcast tlb_table_flush_implies_ipi_broadcast
+static inline bool tlb_table_flush_implies_ipi_broadcast(void);
+
#include <asm-generic/tlb.h>
#include <linux/kernel.h>
#include <vdso/bits.h>
#include <vdso/page.h>
+DECLARE_STATIC_KEY_FALSE(tlb_ipi_broadcast_key);
+
+static inline bool tlb_table_flush_implies_ipi_broadcast(void)
+{
+ return static_branch_likely(&tlb_ipi_broadcast_key);
+}
+
static inline void tlb_flush(struct mmu_gather *tlb)
{
unsigned long start = 0UL, end = TLB_FLUSH_ALL;
unsigned int stride_shift = tlb_get_unmap_shift(tlb);
+ /*
+ * Both freed_tables and unshared_tables must wake lazy-TLB CPUs, so
+ * they receive IPIs before reusing or freeing page tables, allowing
+ * us to safely implement tlb_table_flush_implies_ipi_broadcast().
+ */
+ bool wake_lazy_cpus = tlb->freed_tables || tlb->unshared_tables;
+
if (!tlb->fullmm && !tlb->need_flush_all) {
start = tlb->start;
end = tlb->end;
}
- flush_tlb_mm_range(tlb->mm, start, end, stride_shift, tlb->freed_tables);
+ flush_tlb_mm_range(tlb->mm, start, end, stride_shift, wake_lazy_cpus);
}
static inline void invlpg(unsigned long addr)
diff --git a/arch/x86/include/asm/tlbflush.h b/arch/x86/include/asm/tlbflush.h
index 5a3cdc439e38..39b9454781c3 100644
--- a/arch/x86/include/asm/tlbflush.h
+++ b/arch/x86/include/asm/tlbflush.h
@@ -18,6 +18,8 @@
DECLARE_PER_CPU(u64, tlbstate_untag_mask);
+void __init native_pv_tlb_init(void);
+
void __flush_tlb_all(void);
#define TLB_FLUSH_ALL -1UL
@@ -225,7 +227,7 @@ struct flush_tlb_info {
u64 new_tlb_gen;
unsigned int initiating_cpu;
u8 stride_shift;
- u8 freed_tables;
+ u8 wake_lazy_cpus;
u8 trim_cpumask;
};
@@ -315,7 +317,7 @@ static inline bool mm_in_asid_transition(struct mm_struct *mm) { return false; }
extern void flush_tlb_all(void);
extern void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,
unsigned long end, unsigned int stride_shift,
- bool freed_tables);
+ bool wake_lazy_cpus);
extern void flush_tlb_kernel_range(unsigned long start, unsigned long end);
static inline void flush_tlb_page(struct vm_area_struct *vma, unsigned long a)
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index 294a8ea60298..df776b645a9c 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -1256,6 +1256,7 @@ void __init native_smp_prepare_boot_cpu(void)
switch_gdt_and_percpu_base(me);
native_pv_lock_init();
+ native_pv_tlb_init();
}
void __init native_smp_cpus_done(unsigned int max_cpus)
diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c
index 621e09d049cb..3ce254a3982c 100644
--- a/arch/x86/mm/tlb.c
+++ b/arch/x86/mm/tlb.c
@@ -26,6 +26,8 @@
#include "mm_internal.h"
+DEFINE_STATIC_KEY_FALSE(tlb_ipi_broadcast_key);
+
#ifdef CONFIG_PARAVIRT
# define STATIC_NOPV
#else
@@ -1360,16 +1362,16 @@ STATIC_NOPV void native_flush_tlb_multi(const struct cpumask *cpumask,
(info->end - info->start) >> PAGE_SHIFT);
/*
- * If no page tables were freed, we can skip sending IPIs to
- * CPUs in lazy TLB mode. They will flush the CPU themselves
- * at the next context switch.
+ * If lazy-TLB CPUs do not need to be woken, we can skip sending
+ * IPIs to them. They will flush themselves at the next context
+ * switch.
*
- * However, if page tables are getting freed, we need to send the
- * IPI everywhere, to prevent CPUs in lazy TLB mode from tripping
- * up on the new contents of what used to be page tables, while
- * doing a speculative memory access.
+ * However, if page tables are getting freed or unshared, we need
+ * to send the IPI everywhere, to prevent CPUs in lazy TLB mode
+ * from tripping up on the new contents of what used to be page
+ * tables, while doing a speculative memory access.
*/
- if (info->freed_tables || mm_in_asid_transition(info->mm))
+ if (info->wake_lazy_cpus || mm_in_asid_transition(info->mm))
on_each_cpu_mask(cpumask, flush_tlb_func, (void *)info, true);
else
on_each_cpu_cond_mask(should_flush_tlb, flush_tlb_func,
@@ -1402,7 +1404,7 @@ static DEFINE_PER_CPU(unsigned int, flush_tlb_info_idx);
static struct flush_tlb_info *get_flush_tlb_info(struct mm_struct *mm,
unsigned long start, unsigned long end,
- unsigned int stride_shift, bool freed_tables,
+ unsigned int stride_shift, bool wake_lazy_cpus,
u64 new_tlb_gen)
{
struct flush_tlb_info *info = this_cpu_ptr(&flush_tlb_info);
@@ -1429,7 +1431,7 @@ static struct flush_tlb_info *get_flush_tlb_info(struct mm_struct *mm,
info->end = end;
info->mm = mm;
info->stride_shift = stride_shift;
- info->freed_tables = freed_tables;
+ info->wake_lazy_cpus = wake_lazy_cpus;
info->new_tlb_gen = new_tlb_gen;
info->initiating_cpu = smp_processor_id();
info->trim_cpumask = 0;
@@ -1448,7 +1450,7 @@ static void put_flush_tlb_info(void)
void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,
unsigned long end, unsigned int stride_shift,
- bool freed_tables)
+ bool wake_lazy_cpus)
{
struct flush_tlb_info *info;
int cpu = get_cpu();
@@ -1457,7 +1459,7 @@ void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,
/* This is also a barrier that synchronizes with switch_mm(). */
new_tlb_gen = inc_mm_tlb_gen(mm);
- info = get_flush_tlb_info(mm, start, end, stride_shift, freed_tables,
+ info = get_flush_tlb_info(mm, start, end, stride_shift, wake_lazy_cpus,
new_tlb_gen);
/*
@@ -1834,3 +1836,16 @@ static int __init create_tlb_single_page_flush_ceiling(void)
return 0;
}
late_initcall(create_tlb_single_page_flush_ceiling);
+
+void __init native_pv_tlb_init(void)
+{
+#ifdef CONFIG_PARAVIRT
+ if (pv_ops.mmu.flush_tlb_multi != native_flush_tlb_multi)
+ return;
+#endif
+
+ if (cpu_feature_enabled(X86_FEATURE_INVLPGB))
+ return;
+
+ static_branch_enable(&tlb_ipi_broadcast_key);
+}
--
2.49.0
^ permalink raw reply related
* [PATCH 7.2 v10 1/2] mm/mmu_gather: prepare to skip redundant sync IPIs
From: Lance Yang @ 2026-04-24 6:25 UTC (permalink / raw)
To: akpm
Cc: peterz, david, dave.hansen, dave.hansen, ypodemsk, hughd, will,
aneesh.kumar, npiggin, tglx, mingo, bp, x86, hpa, arnd, ljs, ziy,
baolin.wang, Liam.Howlett, npache, ryan.roberts, dev.jain, baohua,
shy828301, riel, jannh, jgross, seanjc, pbonzini, boris.ostrovsky,
virtualization, kvm, linux-arch, linux-mm, linux-kernel,
ioworker0, Lance Yang
In-Reply-To: <20260424062528.71951-1-lance.yang@linux.dev>
From: Lance Yang <lance.yang@linux.dev>
When page table operations require synchronization with software/lockless
walkers, they call tlb_remove_table_sync_{one,rcu}() after flushing the
TLB (tlb->freed_tables or tlb->unshared_tables).
On architectures where the TLB flush already sends IPIs to all target CPUs,
the subsequent sync IPI broadcast is redundant. This is not only costly on
large systems where it disrupts all CPUs even for single-process page table
operations, but has also been reported to hurt RT workloads[1].
Introduce tlb_table_flush_implies_ipi_broadcast() to check if the prior TLB
flush already provided the necessary synchronization. When true, the sync
calls can early-return.
A few cases rely on this synchronization:
1) hugetlb PMD unshare[2]: The problem is not the freeing but the reuse
of the PMD table for other purposes in the last remaining user after
unsharing.
2) khugepaged collapse[3]: Ensure no concurrent GUP-fast before collapsing
and (possibly) freeing the page table / re-depositing it.
Currently always returns false (no behavior change). The follow-up patch
will enable the optimization for x86.
[1] https://lore.kernel.org/linux-mm/1b27a3fa-359a-43d0-bdeb-c31341749367@kernel.org/
[2] https://lore.kernel.org/linux-mm/6a364356-5fea-4a6c-b959-ba3b22ce9c88@kernel.org/
[3] https://lore.kernel.org/linux-mm/2cb4503d-3a3f-4f6c-8038-7b3d1c74b3c2@kernel.org/
Suggested-by: David Hildenbrand (Arm) <david@kernel.org>
Acked-by: David Hildenbrand (Arm) <david@kernel.org>
Signed-off-by: Lance Yang <lance.yang@linux.dev>
---
include/asm-generic/tlb.h | 17 +++++++++++++++++
mm/mmu_gather.c | 15 +++++++++++++++
2 files changed, 32 insertions(+)
diff --git a/include/asm-generic/tlb.h b/include/asm-generic/tlb.h
index bdcc2778ac64..cb41cc6a0024 100644
--- a/include/asm-generic/tlb.h
+++ b/include/asm-generic/tlb.h
@@ -240,6 +240,23 @@ static inline void tlb_remove_table(struct mmu_gather *tlb, void *table)
}
#endif /* CONFIG_MMU_GATHER_TABLE_FREE */
+/**
+ * tlb_table_flush_implies_ipi_broadcast - does TLB flush imply IPI sync
+ *
+ * When page table operations require synchronization with software/lockless
+ * walkers, they flush the TLB (tlb->freed_tables or tlb->unshared_tables)
+ * then call tlb_remove_table_sync_{one,rcu}(). If the flush already sent
+ * IPIs to all CPUs, the sync call is redundant.
+ *
+ * Returns false by default. Architectures can override by defining this.
+ */
+#ifndef tlb_table_flush_implies_ipi_broadcast
+static inline bool tlb_table_flush_implies_ipi_broadcast(void)
+{
+ return false;
+}
+#endif
+
#ifdef CONFIG_MMU_GATHER_RCU_TABLE_FREE
/*
* This allows an architecture that does not use the linux page-tables for
diff --git a/mm/mmu_gather.c b/mm/mmu_gather.c
index 3985d856de7f..37a6a711c37e 100644
--- a/mm/mmu_gather.c
+++ b/mm/mmu_gather.c
@@ -283,6 +283,14 @@ void tlb_remove_table_sync_one(void)
* It is however sufficient for software page-table walkers that rely on
* IRQ disabling.
*/
+
+ /*
+ * Skip IPI if the preceding TLB flush already synchronized with
+ * all CPUs that could be doing software/lockless page table walks.
+ */
+ if (tlb_table_flush_implies_ipi_broadcast())
+ return;
+
smp_call_function(tlb_remove_table_smp_sync, NULL, 1);
}
@@ -312,6 +320,13 @@ static void tlb_remove_table_free(struct mmu_table_batch *batch)
*/
void tlb_remove_table_sync_rcu(void)
{
+ /*
+ * Skip RCU wait if the preceding TLB flush already synchronized
+ * with all CPUs that could be doing software/lockless page table walks.
+ */
+ if (tlb_table_flush_implies_ipi_broadcast())
+ return;
+
synchronize_rcu();
}
--
2.49.0
^ permalink raw reply related
* [PATCH 7.2 v10 0/2] skip redundant sync IPIs when TLB flush sent them
From: Lance Yang @ 2026-04-24 6:25 UTC (permalink / raw)
To: akpm
Cc: peterz, david, dave.hansen, dave.hansen, ypodemsk, hughd, will,
aneesh.kumar, npiggin, tglx, mingo, bp, x86, hpa, arnd, ljs, ziy,
baolin.wang, Liam.Howlett, npache, ryan.roberts, dev.jain, baohua,
shy828301, riel, jannh, jgross, seanjc, pbonzini, boris.ostrovsky,
virtualization, kvm, linux-arch, linux-mm, linux-kernel,
ioworker0
Hi all,
When page table operations require synchronization with software/lockless
walkers, they call tlb_remove_table_sync_{one,rcu}() after flushing the
TLB (tlb->freed_tables or tlb->unshared_tables).
On architectures where the TLB flush already sends IPIs to all target CPUs,
the subsequent sync IPI broadcast is redundant. This is not only costly on
large systems where it disrupts all CPUs even for single-process page table
operations, but has also been reported to hurt RT workloads[1].
This series introduces tlb_table_flush_implies_ipi_broadcast() to check if
the prior TLB flush already provided the necessary synchronization. When
true, the sync calls can early-return.
A few cases rely on this synchronization:
1) hugetlb PMD unshare[2]: The problem is not the freeing but the reuse
of the PMD table for other purposes in the last remaining user after
unsharing.
2) khugepaged collapse[3]: Ensure no concurrent GUP-fast before collapsing
and (possibly) freeing the page table / re-depositing it.
Two-step plan as David suggested[4]:
Step 1 (this series): Skip redundant sync when we're 100% certain the TLB
flush sent IPIs. INVLPGB is excluded because when supported, we cannot
guarantee IPIs were sent, keeping it clean and simple.
Step 2 (future work): Send targeted IPIs only to CPUs actually doing
software/lockless page table walks, benefiting all architectures.
Regarding Step 2, it obviously only applies to setups where Step 1 does not
apply: like x86 with INVLPGB or arm64. Step 2 work is ongoing; early
attempts showed ~3% GUP-fast overhead. Reducing the overhead requires more
work and tuning; it will be submitted separately once ready.
On a 64-core Intel x86 server, the CAL interrupt count in
/proc/interrupts dropped from 646,316 to 785 when collapsing a 20 GiB
range with this series applied.
David Hildenbrand did the initial implementation. I built on his work and
relied on off-list discussions to push it further - thanks a lot David!
[1] https://lore.kernel.org/linux-mm/1b27a3fa-359a-43d0-bdeb-c31341749367@kernel.org/
[2] https://lore.kernel.org/linux-mm/6a364356-5fea-4a6c-b959-ba3b22ce9c88@kernel.org/
[3] https://lore.kernel.org/linux-mm/2cb4503d-3a3f-4f6c-8038-7b3d1c74b3c2@kernel.org/
[4] https://lore.kernel.org/linux-mm/bbfdf226-4660-4949-b17b-0d209ee4ef8c@kernel.org/
v9 -> v10:
- Rename the x86 flush_tlb_info bit from freed_tables to wake_lazy_cpus,
to make the lazy-TLB behavior explicit (per Dave, thanks!)
- https://lore.kernel.org/linux-mm/20260420030851.6735-1-lance.yang@linux.dev/
v8 -> v9:
- Rebase on mm-new; re-tested, no code changes.
- https://lore.kernel.org/linux-mm/20260324085238.44477-1-lance.yang@linux.dev/
v7 -> v8:
- Pick up Acked-by tags from David, thanks!
- Add CAL interrupt numbers to the cover letter (per Andrew, thanks!)
- Rewrite the [2/2] changelog and reword the comment (per David, thanks!)
- https://lore.kernel.org/linux-mm/20260309020711.20831-1-lance.yang@linux.dev/
v6 -> v7:
- Simplify init logic and eliminate duplicated X86_FEATURE_INVLPGB checks
(per Dave, thanks!)
- Remove flush_tlb_multi_implies_ipi_broadcast property because no PV
backend sets it today.
- https://lore.kernel.org/linux-mm/20260304021046.18550-1-lance.yang@linux.dev/
v5 -> v6:
- Use static_branch to eliminate the branch overhead (per Peter, thanks!)
- https://lore.kernel.org/linux-mm/20260302063048.9479-1-lance.yang@linux.dev/
v4 -> v5:
- Drop per-CPU tracking (active_lockless_pt_walk_mm) from this series;
defer to Step 2 as it adds ~3% GUP-fast overhead
- Keep pv_ops property false for PV backends like KVM: preempted vCPUs
cannot be assumed safe (per Sean, thanks!)
https://lore.kernel.org/linux-mm/aaCP95l-m8ISXF78@google.com/
- https://lore.kernel.org/linux-mm/20260202074557.16544-1-lance.yang@linux.dev/
v3 -> v4:
- Rework based on David's two-step direction and per-CPU idea:
1) Targeted IPIs: per-CPU variable when entering/leaving lockless page
table walk; tlb_remove_table_sync_mm() IPIs only those CPUs.
2) On x86, pv_mmu_ops property set at init to skip the extra sync when
flush_tlb_multi() already sends IPIs.
https://lore.kernel.org/linux-mm/bbfdf226-4660-4949-b17b-0d209ee4ef8c@kernel.org/
- https://lore.kernel.org/linux-mm/20260106120303.38124-1-lance.yang@linux.dev/
v2 -> v3:
- Complete rewrite: use dynamic IPI tracking instead of static checks
(per Dave Hansen, thanks!)
- Track IPIs via mmu_gather: native_flush_tlb_multi() sets flag when
actually sending IPIs
- Motivation for skipping redundant IPIs explained by David:
https://lore.kernel.org/linux-mm/1b27a3fa-359a-43d0-bdeb-c31341749367@kernel.org/
- https://lore.kernel.org/linux-mm/20251229145245.85452-1-lance.yang@linux.dev/
v1 -> v2:
- Fix cover letter encoding to resolve send-email issues. Apologies for
any email flood caused by the failed send attempts :(
RFC -> v1:
- Use a callback function in pv_mmu_ops instead of comparing function
pointers (per David)
- Embed the check directly in tlb_remove_table_sync_one() instead of
requiring every caller to check explicitly (per David)
- Move tlb_table_flush_implies_ipi_broadcast() outside of
CONFIG_MMU_GATHER_RCU_TABLE_FREE to fix build error on architectures
that don't enable this config.
https://lore.kernel.org/oe-kbuild-all/202512142156.cShiu6PU-lkp@intel.com/
- https://lore.kernel.org/linux-mm/20251213080038.10917-1-lance.yang@linux.dev/
Lance Yang (2):
mm/mmu_gather: prepare to skip redundant sync IPIs
x86/tlb: skip redundant sync IPIs for native TLB flush
arch/x86/hyperv/mmu.c | 4 ++--
arch/x86/include/asm/tlb.h | 19 +++++++++++++++-
arch/x86/include/asm/tlbflush.h | 6 +++--
arch/x86/kernel/smpboot.c | 1 +
arch/x86/mm/tlb.c | 39 +++++++++++++++++++++++----------
include/asm-generic/tlb.h | 17 ++++++++++++++
mm/mmu_gather.c | 15 +++++++++++++
7 files changed, 84 insertions(+), 17 deletions(-)
--
2.49.0
^ permalink raw reply
* Re: [PATCH 0/4] scsi: Support devices that don't have a cmd_per_lun limit
From: Hannes Reinecke @ 2026-04-24 5:45 UTC (permalink / raw)
To: Bart Van Assche, Mike Christie, Stefan Hajnoczi
Cc: martin.petersen, linux-scsi, james.bottomley, virtualization, mst,
pbonzini, eperezma
In-Reply-To: <39585b28-64d8-42a4-afab-a88ca1eb83b6@acm.org>
On 4/23/26 18:40, Bart Van Assche wrote:
> On 4/23/26 2:45 AM, Hannes Reinecke wrote:
>> Ideally I would kill cmd_per_lun.
>> This really is a poor man's fairness algorithm (sole purpose is to
>> avoid starvation with many luns), and we really should look at if
>> we cannot replace it with tagsets.
>
> Hmm ... isn't cmd_per_lun essential since the introduction of scsi-mq?
> Without a host-wide tagset, and with n hardware queues,
> blk_mq_alloc_tag_set() allocates (number of hardware queues) *
> (shost->can_queue + shost->nr_reserved_cmds) requests. Each request
> maps to one SCSI command. Setting cmd_per_lun to shost->can_queue may
> be essential to avoid BUSY responses from a SCSI device. Here is an
> example from the ib_srp driver (there are many more SCSI LLDs that
> follow this pattern):
> * During connection establishment, the SCSI target reports the
> maximum queue depth it supports. This response is used to initialize
> can_queue and cmd_per_lun.
> * Multiple hardware queues are allocated, all supporting can_queue
> commands.
> * cmd_per_lun is set to can_queue to avoid BUSY responses from the SCSI
> target. My experience is that for high performance SCSI targets even
> 1% BUSY responses cause a significant performance drop.
>
My point being that cmd_per_lun is a single setting, and is extremely
imprecise. At the same time we already have fine-grained request QoS
available by virtue of tagsets.
Seems like we need to have a 'device_tagset' setting, too.
Hmm.
Cheers,
Hannes
--
Dr. Hannes Reinecke Kernel Storage Architect
hare@suse.de +49 911 74053 688
SUSE Software Solutions GmbH, Frankenstr. 146, 90461 Nürnberg
HRB 36809 (AG Nürnberg), GF: I. Totev, A. McDonald, W. Knoblich
^ permalink raw reply
* Re: [PATCH 7.2 v9 2/2] x86/tlb: skip redundant sync IPIs for native TLB flush
From: Lance Yang @ 2026-04-24 5:03 UTC (permalink / raw)
To: dave.hansen
Cc: lance.yang, akpm, peterz, david, dave.hansen, ypodemsk, hughd,
will, aneesh.kumar, npiggin, tglx, mingo, bp, x86, hpa, arnd, ljs,
ziy, baolin.wang, Liam.Howlett, npache, ryan.roberts, dev.jain,
baohua, shy828301, riel, jannh, jgross, seanjc, pbonzini,
boris.ostrovsky, virtualization, kvm, linux-arch, linux-mm,
linux-kernel, ioworker0
In-Reply-To: <f856051b-10c7-4d65-9dbe-6b1677af74bd@intel.com>
Hi Dave,
On Thu, Apr 23, 2026 at 10:56:03AM -0700, Dave Hansen wrote:
[...]
>On 4/19/26 20:08, Lance Yang wrote:
>> - flush_tlb_mm_range(tlb->mm, start, end, stride_shift, tlb->freed_tables);
>> + /*
>> + * Treat unshared_tables just like freed_tables, such that lazy-TLB
>> + * CPUs also receive IPIs during unsharing of page tables, allowing
>> + * us to safely implement tlb_table_flush_implies_ipi_broadcast().
>> + */
>> + flush_tlb_mm_range(tlb->mm, start, end, stride_shift,
>> + tlb->freed_tables || tlb->unshared_tables);
>> }
>
>I've been staring at this trying to make sense of it for too long.
>
>Right now, flush_tlb_mm_range() literally has an argument named
>"freed_tables" and "tlb->freed_tables" is passed there. That seems
>totally sane. It's 100% straightforward to follow.
>
>But it makes zero logical sense to me to now mix "tlb->unshared_tables"
>in there. Sure, what you _want_ is the freed_tables==1 behavior from
>tlb->unshared_tables==1, and this obviously hacks that in there, but
>it's not explained well enough and not maintainable like this. IOW, it's
>still just hack.
>
>I think what's happened here is that info->freed_tables is being
>modified from being strictly related to page table freeing, and moved
>over to a bit which tells TLB flushing implementations whether they can
>respect CPUs in lazy TLB mode.
>
>It's mentioned in the comment, but then ever reflected into the code.
>
>Shouldn't we be doing something like the attached patch? Look at how
>that maps over to the flushing side, like in the hyperv code:
Cool, thanks!
I was trying to keep the change small by passing unshared_tables through
the exsiting freed_tables argument, but that made the code a bit harder
to follow ...
>
>> - bool do_lazy = !info->freed_tables;
>> + bool do_lazy = !info->wake_lazy_cpus;
>>
>> trace_hyperv_mmu_flush_tlb_multi(cpus, info);
>>
>> @@ -198,7 +198,7 @@ static u64 hyperv_flush_tlb_others_ex(co
>>
>> flush->hv_vp_set.format = HV_GENERIC_SET_SPARSE_4K;
>> nr_bank = cpumask_to_vpset_skip(&flush->hv_vp_set, cpus,
>> - info->freed_tables ? NULL : cpu_is_lazy);
>> + info->wake_lazy_cpus ? NULL : cpu_is_lazy);
>
>That even makes the hyperv code easier to read over what was there
>before, IMNHO.
>
>Thoughts?
[...]
Yeah, renaming the flush_tlb_info bit to wake_lazy_cpus reads much
better. Will fold this into v10, Thanks for spelling it out!
Lance
^ permalink raw reply
* [PATCH v2] virtio: rtc: tear down old virtqueues before restore
From: JiaJia @ 2026-04-24 3:14 UTC (permalink / raw)
To: Peter Hilber
Cc: mst, jasowang, xuanzhuo, eperezma, virtualization, linux-kernel,
physicalmtea
In-Reply-To: <iwb4axxcxti6bpgpde5cv3n7y46xaopvkbdd2kug3qhn2ehfim@ny45mixj7ncn>
virtio_device_restore() resets the device and restores the negotiated
features before calling ->restore(). viortc_freeze() intentionally
leaves the existing virtqueues in place so the alarm queue can still
wake the system, but viortc_restore() immediately calls
viortc_init_vqs() without first deleting those old queues.
If virtqueue reinitialization fails on virtio-pci, the transport error
path can run vp_del_vqs() against a newly allocated vp_dev->vqs array
while vdev->vqs still contains the old virtqueues. vp_del_vqs() then
looks up queue state through the new array and can dereference a NULL
info pointer in vp_del_vq(), crashing the guest kernel during restore.
Delete the stale virtqueues before rebuilding them. If restore fails
before virtio_device_ready(), reuse the remove path to stop the device.
Once the device is ready, return errors directly instead of deleting the
virtqueues again.
Signed-off-by: JiaJia <physicalmtea@gmail.com>
---
Hi Peter,
thanks for taking a look and for pointing this out. I took another look
at the restore path and agree that deleting the virtqueues from that
error path can race with `viortc_cb_alarmq()` once the device has been
readied.
This v2 follows the direction you suggested. It factors out
`__viortc_remove()`, reuses that path for restore failures before
`virtio_device_ready()`, routes `viortc_init_vqs()` failures in probe
through `err_reset_vdev` for consistent teardown, drops the
`viortc_del_vqs()` helper and the `viortc_msg_xfer()` NULL-vq guard,
and avoids deleting the virtqueues again after `virtio_device_ready()`.
Thanks,
JiaJia
v2:
- reuse the remove path for restore failures before virtio_device_ready()
- route viortc_init_vqs() failures in probe through err_reset_vdev
- drop the viortc_del_vqs() helper and the viortc_msg_xfer() NULL-vq guard
- avoid deleting virtqueues again after virtio_device_ready()
drivers/virtio/virtio_rtc_driver.c | 28 ++++++++++++++++++++--------
1 file changed, 20 insertions(+), 8 deletions(-)
diff --git a/drivers/virtio/virtio_rtc_driver.c b/drivers/virtio/virtio_rtc_driver.c
index a57d5e06e..4419735b0 100644
--- a/drivers/virtio/virtio_rtc_driver.c
+++ b/drivers/virtio/virtio_rtc_driver.c
@@ -1257,6 +1257,15 @@ static int viortc_init_vqs(struct viortc_dev *viortc)
return 0;
}
+static void __viortc_remove(struct viortc_dev *viortc)
+{
+ struct virtio_device *vdev = viortc->vdev;
+
+ viortc_clocks_deinit(viortc);
+ virtio_reset_device(vdev);
+ vdev->config->del_vqs(vdev);
+}
+
/**
* viortc_probe() - probe a virtio_rtc virtio device
* @vdev: virtio device
@@ -1282,7 +1291,7 @@ static int viortc_probe(struct virtio_device *vdev)
ret = viortc_init_vqs(viortc);
if (ret)
- return ret;
+ goto err_reset_vdev;
virtio_device_ready(vdev);
@@ -1329,10 +1338,7 @@ static void viortc_remove(struct virtio_device *vdev)
{
struct viortc_dev *viortc = vdev->priv;
- viortc_clocks_deinit(viortc);
-
- virtio_reset_device(vdev);
- vdev->config->del_vqs(vdev);
+ __viortc_remove(viortc);
}
static int viortc_freeze(struct virtio_device *dev)
@@ -1353,9 +1359,11 @@ static int viortc_restore(struct virtio_device *dev)
bool notify = false;
int ret;
+ dev->config->del_vqs(dev);
+
ret = viortc_init_vqs(viortc);
if (ret)
- return ret;
+ goto err_remove;
alarm_viortc_vq = &viortc->vqs[VIORTC_ALARMQ];
alarm_vq = alarm_viortc_vq->vq;
@@ -1364,7 +1372,7 @@ static int viortc_restore(struct virtio_device *dev)
ret = viortc_populate_vq(viortc, alarm_viortc_vq,
VIORTC_ALARMQ_BUF_CAP, false);
if (ret)
- return ret;
+ goto err_remove;
notify = virtqueue_kick_prepare(alarm_vq);
}
@@ -1372,8 +1380,12 @@ static int viortc_restore(struct virtio_device *dev)
virtio_device_ready(dev);
if (notify && !virtqueue_notify(alarm_vq))
- ret = -EIO;
+ return -EIO;
+
+ return 0;
+err_remove:
+ __viortc_remove(viortc);
return ret;
}
--
2.34.1
^ permalink raw reply related
* [syzbot] [virt?] [net?] memory leak in __vsock_create (2)
From: syzbot @ 2026-04-24 2:02 UTC (permalink / raw)
To: davem, edumazet, horms, kuba, linux-kernel, netdev, pabeni,
sgarzare, syzkaller-bugs, virtualization
Hello,
syzbot found the following issue on:
HEAD commit: 1f318b96cc84 Linux 7.0-rc3
git tree: upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=14db28ba580000
kernel config: https://syzkaller.appspot.com/x/.config?x=2c6ad6fefffa76b1
dashboard link: https://syzkaller.appspot.com/bug?extid=1b2c9c4a0f8708082678
compiler: gcc (Debian 14.2.0-19) 14.2.0, GNU ld (GNU Binutils for Debian) 2.44
syz repro: https://syzkaller.appspot.com/x/repro.syz?x=12db28ba580000
C reproducer: https://syzkaller.appspot.com/x/repro.c?x=1215175a580000
Downloadable assets:
disk image: https://storage.googleapis.com/syzbot-assets/d4ebd240d832/disk-1f318b96.raw.xz
vmlinux: https://storage.googleapis.com/syzbot-assets/9548f49a7dec/vmlinux-1f318b96.xz
kernel image: https://storage.googleapis.com/syzbot-assets/4e16f2bcfc7d/bzImage-1f318b96.xz
IMPORTANT: if you fix the issue, please add the following tag to the commit:
Reported-by: syzbot+1b2c9c4a0f8708082678@syzkaller.appspotmail.com
2026/03/09 23:37:29 executed programs: 5
BUG: memory leak
unreferenced object 0xffff888128bb6d00 (size 1272):
comm "kworker/0:1", pid 10, jiffies 4294944453
hex dump (first 32 bytes):
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
28 00 0b 40 00 00 00 00 00 00 00 00 00 00 00 00 (..@............
backtrace (crc 31367ed9):
kmemleak_alloc_recursive include/linux/kmemleak.h:44 [inline]
slab_post_alloc_hook mm/slub.c:4547 [inline]
slab_alloc_node mm/slub.c:4869 [inline]
kmem_cache_alloc_noprof+0x372/0x480 mm/slub.c:4876
sk_prot_alloc+0x3e/0x1b0 net/core/sock.c:2239
sk_alloc+0x36/0x460 net/core/sock.c:2301
__vsock_create.constprop.0+0x38/0x2f0 net/vmw_vsock/af_vsock.c:893
virtio_transport_recv_listen net/vmw_vsock/virtio_transport_common.c:1557 [inline]
virtio_transport_recv_pkt+0x855/0xfc0 net/vmw_vsock/virtio_transport_common.c:1685
vsock_loopback_work+0x104/0x140 net/vmw_vsock/vsock_loopback.c:142
process_one_work+0x26c/0x5d0 kernel/workqueue.c:3275
process_scheduled_works kernel/workqueue.c:3358 [inline]
worker_thread+0x243/0x490 kernel/workqueue.c:3439
kthread+0x14e/0x1a0 kernel/kthread.c:436
ret_from_fork+0x23c/0x4b0 arch/x86/kernel/process.c:158
ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
BUG: memory leak
unreferenced object 0xffff8881141e93a0 (size 32):
comm "kworker/0:1", pid 10, jiffies 4294944453
hex dump (first 32 bytes):
f8 6e 0a 00 81 88 ff ff 00 00 00 00 00 00 00 00 .n..............
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
backtrace (crc e7f5c8b3):
kmemleak_alloc_recursive include/linux/kmemleak.h:44 [inline]
slab_post_alloc_hook mm/slub.c:4547 [inline]
slab_alloc_node mm/slub.c:4869 [inline]
__do_kmalloc_node mm/slub.c:5262 [inline]
__kmalloc_noprof+0x3bd/0x560 mm/slub.c:5275
kmalloc_noprof include/linux/slab.h:954 [inline]
kzalloc_noprof include/linux/slab.h:1188 [inline]
lsm_blob_alloc+0x4d/0x80 security/security.c:192
lsm_sock_alloc security/security.c:4375 [inline]
security_sk_alloc+0x2d/0x290 security/security.c:4391
sk_prot_alloc+0x8f/0x1b0 net/core/sock.c:2248
sk_alloc+0x36/0x460 net/core/sock.c:2301
__vsock_create.constprop.0+0x38/0x2f0 net/vmw_vsock/af_vsock.c:893
virtio_transport_recv_listen net/vmw_vsock/virtio_transport_common.c:1557 [inline]
virtio_transport_recv_pkt+0x855/0xfc0 net/vmw_vsock/virtio_transport_common.c:1685
vsock_loopback_work+0x104/0x140 net/vmw_vsock/vsock_loopback.c:142
process_one_work+0x26c/0x5d0 kernel/workqueue.c:3275
process_scheduled_works kernel/workqueue.c:3358 [inline]
worker_thread+0x243/0x490 kernel/workqueue.c:3439
kthread+0x14e/0x1a0 kernel/kthread.c:436
ret_from_fork+0x23c/0x4b0 arch/x86/kernel/process.c:158
ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
BUG: memory leak
unreferenced object 0xffff888128bfa8a0 (size 96):
comm "kworker/0:1", pid 10, jiffies 4294944453
hex dump (first 32 bytes):
00 6d bb 28 81 88 ff ff 00 00 00 00 00 00 00 00 .m.(............
00 00 00 00 00 00 00 00 00 00 04 00 00 00 00 00 ................
backtrace (crc 1fd60988):
kmemleak_alloc_recursive include/linux/kmemleak.h:44 [inline]
slab_post_alloc_hook mm/slub.c:4547 [inline]
slab_alloc_node mm/slub.c:4869 [inline]
__kmalloc_cache_noprof+0x377/0x480 mm/slub.c:5378
kmalloc_noprof include/linux/slab.h:950 [inline]
kzalloc_noprof include/linux/slab.h:1188 [inline]
virtio_transport_do_socket_init+0x2b/0xf0 net/vmw_vsock/virtio_transport_common.c:923
vsock_assign_transport+0x309/0x3a0 net/vmw_vsock/af_vsock.c:642
virtio_transport_recv_listen net/vmw_vsock/virtio_transport_common.c:1575 [inline]
virtio_transport_recv_pkt+0x8bc/0xfc0 net/vmw_vsock/virtio_transport_common.c:1685
vsock_loopback_work+0x104/0x140 net/vmw_vsock/vsock_loopback.c:142
process_one_work+0x26c/0x5d0 kernel/workqueue.c:3275
process_scheduled_works kernel/workqueue.c:3358 [inline]
worker_thread+0x243/0x490 kernel/workqueue.c:3439
kthread+0x14e/0x1a0 kernel/kthread.c:436
ret_from_fork+0x23c/0x4b0 arch/x86/kernel/process.c:158
ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
BUG: memory leak
unreferenced object 0xffff888129e1e800 (size 1272):
comm "kworker/1:3", pid 5832, jiffies 4294944454
hex dump (first 32 bytes):
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
28 00 0b 40 00 00 00 00 00 00 00 00 00 00 00 00 (..@............
backtrace (crc 4bfb7c57):
kmemleak_alloc_recursive include/linux/kmemleak.h:44 [inline]
slab_post_alloc_hook mm/slub.c:4547 [inline]
slab_alloc_node mm/slub.c:4869 [inline]
kmem_cache_alloc_noprof+0x372/0x480 mm/slub.c:4876
sk_prot_alloc+0x3e/0x1b0 net/core/sock.c:2239
sk_alloc+0x36/0x460 net/core/sock.c:2301
__vsock_create.constprop.0+0x38/0x2f0 net/vmw_vsock/af_vsock.c:893
virtio_transport_recv_listen net/vmw_vsock/virtio_transport_common.c:1557 [inline]
virtio_transport_recv_pkt+0x855/0xfc0 net/vmw_vsock/virtio_transport_common.c:1685
vsock_loopback_work+0x104/0x140 net/vmw_vsock/vsock_loopback.c:142
process_one_work+0x26c/0x5d0 kernel/workqueue.c:3275
process_scheduled_works kernel/workqueue.c:3358 [inline]
worker_thread+0x243/0x490 kernel/workqueue.c:3439
kthread+0x14e/0x1a0 kernel/kthread.c:436
ret_from_fork+0x23c/0x4b0 arch/x86/kernel/process.c:158
ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
BUG: memory leak
unreferenced object 0xffff888114372e80 (size 32):
comm "kworker/1:3", pid 5832, jiffies 4294944454
hex dump (first 32 bytes):
f8 6e 0a 00 81 88 ff ff 00 00 00 00 00 00 00 00 .n..............
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
backtrace (crc e7f5c8b3):
kmemleak_alloc_recursive include/linux/kmemleak.h:44 [inline]
slab_post_alloc_hook mm/slub.c:4547 [inline]
slab_alloc_node mm/slub.c:4869 [inline]
__do_kmalloc_node mm/slub.c:5262 [inline]
__kmalloc_noprof+0x3bd/0x560 mm/slub.c:5275
kmalloc_noprof include/linux/slab.h:954 [inline]
kzalloc_noprof include/linux/slab.h:1188 [inline]
lsm_blob_alloc+0x4d/0x80 security/security.c:192
lsm_sock_alloc security/security.c:4375 [inline]
security_sk_alloc+0x2d/0x290 security/security.c:4391
sk_prot_alloc+0x8f/0x1b0 net/core/sock.c:2248
sk_alloc+0x36/0x460 net/core/sock.c:2301
__vsock_create.constprop.0+0x38/0x2f0 net/vmw_vsock/af_vsock.c:893
virtio_transport_recv_listen net/vmw_vsock/virtio_transport_common.c:1557 [inline]
virtio_transport_recv_pkt+0x855/0xfc0 net/vmw_vsock/virtio_transport_common.c:1685
vsock_loopback_work+0x104/0x140 net/vmw_vsock/vsock_loopback.c:142
process_one_work+0x26c/0x5d0 kernel/workqueue.c:3275
process_scheduled_works kernel/workqueue.c:3358 [inline]
worker_thread+0x243/0x490 kernel/workqueue.c:3439
kthread+0x14e/0x1a0 kernel/kthread.c:436
ret_from_fork+0x23c/0x4b0 arch/x86/kernel/process.c:158
ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
BUG: memory leak
unreferenced object 0xffff8881054d0ea0 (size 96):
comm "kworker/1:3", pid 5832, jiffies 4294944454
hex dump (first 32 bytes):
00 e8 e1 29 81 88 ff ff 00 00 00 00 00 00 00 00 ...)............
00 00 00 00 00 00 00 00 00 00 04 00 00 00 00 00 ................
backtrace (crc 72501265):
kmemleak_alloc_recursive include/linux/kmemleak.h:44 [inline]
slab_post_alloc_hook mm/slub.c:4547 [inline]
slab_alloc_node mm/slub.c:4869 [inline]
__kmalloc_cache_noprof+0x377/0x480 mm/slub.c:5378
kmalloc_noprof include/linux/slab.h:950 [inline]
kzalloc_noprof include/linux/slab.h:1188 [inline]
virtio_transport_do_socket_init+0x2b/0xf0 net/vmw_vsock/virtio_transport_common.c:923
vsock_assign_transport+0x309/0x3a0 net/vmw_vsock/af_vsock.c:642
virtio_transport_recv_listen net/vmw_vsock/virtio_transport_common.c:1575 [inline]
virtio_transport_recv_pkt+0x8bc/0xfc0 net/vmw_vsock/virtio_transport_common.c:1685
vsock_loopback_work+0x104/0x140 net/vmw_vsock/vsock_loopback.c:142
process_one_work+0x26c/0x5d0 kernel/workqueue.c:3275
process_scheduled_works kernel/workqueue.c:3358 [inline]
worker_thread+0x243/0x490 kernel/workqueue.c:3439
kthread+0x14e/0x1a0 kernel/kthread.c:436
ret_from_fork+0x23c/0x4b0 arch/x86/kernel/process.c:158
ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
connection error: failed to recv *flatrpc.ExecutorMessageRawT: EOF
---
This report is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzkaller@googlegroups.com.
syzbot will keep track of this issue. See:
https://goo.gl/tpsmEJ#status for how to communicate with syzbot.
If the report is already addressed, let syzbot know by replying with:
#syz fix: exact-commit-title
If you want syzbot to run the reproducer, reply with:
#syz test: git://repo/address.git branch-or-commit-hash
If you attach or paste a git patch, syzbot will apply it before testing.
If you want to overwrite report's subsystems, reply with:
#syz set subsystems: new-subsystem
(See the list of subsystem names on the web dashboard)
If the report is a duplicate of another one, reply with:
#syz dup: exact-subject-of-another-report
If you want to undo deduplication, reply with:
#syz undup
^ permalink raw reply
* Re: [PATCH v2 1/3] vfio/pci: Set up bar resources and maps in vfio_pci_core_enable()
From: Alex Williamson @ 2026-04-23 21:30 UTC (permalink / raw)
To: Matt Evans
Cc: Kevin Tian, Jason Gunthorpe, Ankit Agrawal, Alistair Popple,
Leon Romanovsky, Kees Cook, Shameer Kolothum, Yishai Hadas,
Alexey Kardashevskiy, Eric Auger, Peter Xu, Vivek Kasireddy,
Zhi Wang, kvm, linux-kernel, virtualization, alex
In-Reply-To: <20260423182517.2286030-2-mattev@meta.com>
On Thu, 23 Apr 2026 11:25:07 -0700
Matt Evans <mattev@meta.com> wrote:
> Previously BAR resource requests and the corresponding pci_iomap()
> were performed on-demand and without synchronisation, which was racy.
> Rather than add synchronisation, it's simplest to address this by
> doing both activities from vfio_pci_core_enable().
>
> The resource allocation and/or pci_iomap() can still fail; their
> status is tracked and existing calls to vfio_pci_core_setup_barmap()
> will fail in the same way as before. This keeps the point of failure
> as observed by userspace the same, i.e. failures to request/map unused
> BARs are benign.
>
> Fixes: 7f5764e179c6 ("vfio: use vfio_pci_core_setup_barmap to map bar in mmap")
> Fixes: 0d77ed3589ac0 ("vfio/pci: Pull BAR mapping setup from read-write path")
> Signed-off-by: Matt Evans <mattev@meta.com>
> ---
> drivers/vfio/pci/vfio_pci_core.c | 61 +++++++++++++++++++++++++++-----
> drivers/vfio/pci/vfio_pci_rdwr.c | 29 ++++++---------
> include/linux/vfio_pci_core.h | 1 +
> 3 files changed, 64 insertions(+), 27 deletions(-)
>
> diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c
> index 3f8d093aacf8..c59c61861d81 100644
> --- a/drivers/vfio/pci/vfio_pci_core.c
> +++ b/drivers/vfio/pci/vfio_pci_core.c
> @@ -482,6 +482,55 @@ static int vfio_pci_core_runtime_resume(struct device *dev)
> }
> #endif /* CONFIG_PM */
>
> +static void __vfio_pci_core_unmap_bars(struct vfio_pci_core_device *vdev)
> +{
> + struct pci_dev *pdev = vdev->pdev;
> + int i;
> +
> + for (i = 0; i < PCI_STD_NUM_BARS; i++) {
> + int bar = i + PCI_STD_RESOURCES;
> +
> + if (vdev->barmap[bar])
> + pci_iounmap(pdev, vdev->barmap[bar]);
> + if (vdev->have_bar_resource[bar])
> + pci_release_selected_regions(pdev, 1 << bar);
> + vdev->barmap[bar] = NULL;
> + vdev->have_bar_resource[bar] = false;
> + }
> +}
> +
> +static void __vfio_pci_core_map_bars(struct vfio_pci_core_device *vdev)
> +{
> + struct pci_dev *pdev = vdev->pdev;
> + int i;
> +
> + /*
> + * Eager-request BAR resources, and iomap; soft failures are
> + * allowed, and consumers must check before use.
> + */
I'd use this to describe that soft failures maintain compatible error
signatures to previously used on-demand mapping.
> + for (i = 0; i < PCI_STD_NUM_BARS; i++) {
> + int ret;
> + int bar = i + PCI_STD_RESOURCES;
> + void __iomem *io;
Reverse Christmas tree ordering.
> +
> + if (pci_resource_len(pdev, i) == 0)
> + continue;
> +
> + ret = pci_request_selected_regions(pdev, 1 << bar, "vfio");
> + if (ret) {
> + pci_warn(vdev->pdev, "Failed to reserve region %d\n", bar);
> + continue;
> + }
> + vdev->have_bar_resource[bar] = true;
> +
> + io = pci_iomap(pdev, bar, 0);
> + if (io)
> + vdev->barmap[bar] = io;
> + else
> + pci_warn(vdev->pdev, "Failed to iomap region %d\n", bar);
> + }
> +}
I see you making the point in the cover letter about the resource
request vs the iomap resource, but we currently handle these together.
If either fails, setup barmap fails and the path returns error. I
don't see any justification for now allowing the request resource to
succeed but the iomap fails.
These functions also don't need the double-underscore prefix.
> +
> /*
> * The pci-driver core runtime PM routines always save the device state
> * before going into suspended state. If the device is going into low power
> @@ -568,6 +617,7 @@ int vfio_pci_core_enable(struct vfio_pci_core_device *vdev)
> if (!vfio_vga_disabled() && vfio_pci_is_vga(pdev))
> vdev->has_vga = true;
>
> + __vfio_pci_core_map_bars(vdev);
>
> return 0;
>
> @@ -591,7 +641,7 @@ void vfio_pci_core_disable(struct vfio_pci_core_device *vdev)
> struct pci_dev *pdev = vdev->pdev;
> struct vfio_pci_dummy_resource *dummy_res, *tmp;
> struct vfio_pci_ioeventfd *ioeventfd, *ioeventfd_tmp;
> - int i, bar;
> + int i;
>
> /* For needs_reset */
> lockdep_assert_held(&vdev->vdev.dev_set->lock);
> @@ -646,14 +696,7 @@ void vfio_pci_core_disable(struct vfio_pci_core_device *vdev)
>
> vfio_config_free(vdev);
>
> - for (i = 0; i < PCI_STD_NUM_BARS; i++) {
> - bar = i + PCI_STD_RESOURCES;
> - if (!vdev->barmap[bar])
> - continue;
> - pci_iounmap(pdev, vdev->barmap[bar]);
> - pci_release_selected_regions(pdev, 1 << bar);
> - vdev->barmap[bar] = NULL;
> - }
> + __vfio_pci_core_unmap_bars(vdev);
I expect this doesn't need to change if we drop the separation between
resources and iomap.
> list_for_each_entry_safe(dummy_res, tmp,
> &vdev->dummy_resources_list, res_next) {
> diff --git a/drivers/vfio/pci/vfio_pci_rdwr.c b/drivers/vfio/pci/vfio_pci_rdwr.c
> index 4251ee03e146..bf7152316db4 100644
> --- a/drivers/vfio/pci/vfio_pci_rdwr.c
> +++ b/drivers/vfio/pci/vfio_pci_rdwr.c
> @@ -200,25 +200,18 @@ EXPORT_SYMBOL_GPL(vfio_pci_core_do_io_rw);
>
> int vfio_pci_core_setup_barmap(struct vfio_pci_core_device *vdev, int bar)
> {
> - struct pci_dev *pdev = vdev->pdev;
> - int ret;
> - void __iomem *io;
> -
> - if (vdev->barmap[bar])
> - return 0;
> -
> - ret = pci_request_selected_regions(pdev, 1 << bar, "vfio");
> - if (ret)
> - return ret;
> -
> - io = pci_iomap(pdev, bar, 0);
> - if (!io) {
> - pci_release_selected_regions(pdev, 1 << bar);
> + /*
> + * The barmap is now always set up in vfio_pci_core_enable().
"now" is going to read strangely very quickly.
> + * Some legacy callers use this function to ensure the BAR
> + * resources are requested, and others to ensure the
> + * pci_iomap() was done, so check here:
> + */
> + if (bar < 0 || bar >= PCI_STD_NUM_BARS)
> + return -EINVAL;
> + if (vdev->barmap[bar] == 0)
> return -ENOMEM;
> - }
> -
> - vdev->barmap[bar] = io;
> -
> + if (!vdev->bar_has_rsrc[bar])
Typo, this won't incrementally compile. Thanks,
Alex
> + return -EBUSY;
> return 0;
> }
> EXPORT_SYMBOL_GPL(vfio_pci_core_setup_barmap);
> diff --git a/include/linux/vfio_pci_core.h b/include/linux/vfio_pci_core.h
> index 2ebba746c18f..1f508b067d82 100644
> --- a/include/linux/vfio_pci_core.h
> +++ b/include/linux/vfio_pci_core.h
> @@ -101,6 +101,7 @@ struct vfio_pci_core_device {
> const struct vfio_pci_device_ops *pci_ops;
> void __iomem *barmap[PCI_STD_NUM_BARS];
> bool bar_mmap_supported[PCI_STD_NUM_BARS];
> + bool have_bar_resource[PCI_STD_NUM_BARS];
> u8 *pci_config_map;
> u8 *vconfig;
> struct perm_bits *msi_perm;
^ permalink raw reply
* Re: [PATCH v2 2/3] vfio/pci: Replace vfio_pci_core_setup_barmap() with checks for resource/map
From: Alex Williamson @ 2026-04-23 21:30 UTC (permalink / raw)
To: Matt Evans
Cc: Kevin Tian, Jason Gunthorpe, Ankit Agrawal, Alistair Popple,
Leon Romanovsky, Kees Cook, Shameer Kolothum, Yishai Hadas,
Alexey Kardashevskiy, Eric Auger, Peter Xu, Vivek Kasireddy,
Zhi Wang, kvm, linux-kernel, virtualization, alex
In-Reply-To: <20260423182517.2286030-3-mattev@meta.com>
On Thu, 23 Apr 2026 11:25:08 -0700
Matt Evans <mattev@meta.com> wrote:
> Since "vfio/pci: Set up barmap in vfio_pci_core_enable()", the
> resource request and iomap for the BARs was performed early, and
> vfio_pci_core_setup_barmap() now just checks those actions succeeded.
>
> There were two types of callers:
> - Those that need the iomap, because they'll access the BAR
> - Those that need the resource, because they'll map/export it
>
> This replaces vfio_pci_core_setup_barmap() with two helpers,
> vfio_pci_core_check_barmap_valid() and vfio_pci_core_check_bar_rsrc(),
> to make it clear which behaviour is required in each caller.
TBH, I don't see why we need the distinction. Thanks,
Alex
^ permalink raw reply
* [PATCH v14 19/92] dyndbg,module: make proper substructs in _ddebug_info
From: Jim Cromie @ 2026-04-23 20:54 UTC (permalink / raw)
To: Arnd Bergmann, Jason Baron, Luis Chamberlain, Petr Pavlu,
Daniel Gomez, Sami Tolvanen, Aaron Tomlin, Andrew Morton,
Jonathan Corbet, Shuah Khan, Shuah Khan, Greg Kroah-Hartman,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
Tvrtko Ursulin, Alex Deucher, Christian König, David Airlie,
Gerd Hoffmann, Dmitry Osipenko, Gurchetan Singh, Chia-I Wu,
Matthew Brost, Thomas Hellström, Lyude Paul,
Danilo Krummrich, Patrik Jakobsson, Zack Rusin,
Broadcom internal kernel review list, Louis Chauvet,
Haneen Mohammed, Melissa Wen, Sean Paul, Jocelyn Falempe,
Ruben Wauters, Dave Stevenson, Maíra Canal,
Raspberry Pi Kernel Maintenance, Rob Clark, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, Xinliang Liu,
Tian Tao, Xinwei Kong, Sumit Semwal, Yongqin Liu, John Stultz,
Philipp Zabel, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, Chun-Kuang Hu, Matthias Brugger,
AngeloGioacchino Del Regno, Sandy Huang, Heiko Stübner,
Andy Yan, Alain Volmat, Raphael Gallais-Pou, Yannick Fertre,
Raphael Gallais-Pou, Philippe Cornu, Maxime Coquelin,
Alexandre Torgue, Oded Gabbay, Maciej Falkowski, Karol Wachowski,
Rob Herring (Arm), Tomeu Vizoso, Liviu Dudau, Andrzej Hajda,
Neil Armstrong, Robert Foss, Laurent Pinchart, Jonas Karlman,
Jernej Skrabec, Liu Ying, Laurentiu Palcu, Lucas Stach,
Paul Kocialkowski, Jianmin Lv, Qianhai Wu, Huacai Chen,
Mingcong Bai, Xi Ruoyao, Icenowy Zheng, Laurent Pinchart,
Tomi Valkeinen, Kieran Bingham, Geert Uytterhoeven, Magnus Damm,
Javier Martinez Canillas, Huang Rui, Matthew Auld, Jani Nikula,
Luca Coelho, Russell King, Christian Gmeiner
Cc: linux-arch, linux-kernel, linux-modules, linux-doc,
linux-kselftest, dri-devel, intel-gfx, amd-gfx, virtualization,
intel-xe, nouveau, spice-devel, linux-arm-msm, freedreno, imx,
linux-arm-kernel, linux-mediatek, linux-rockchip, linux-stm32,
linux-renesas-soc, etnaviv, Jim Cromie
In-Reply-To: <20260423-submit-dyndbg-classmap-foundation-v14-0-2b809a8019d0@gmail.com>
recompose struct _ddebug_info, inserting proper sub-structs.
The struct _ddebug_info has 2 pairs of _vec, num_##_vec fields, for
descs and classes respectively. for_subvec() makes walking these
vectors less cumbersome, now lets move those field pairs into their
own "vec" structs: _ddebug_descs & _ddebug_class_maps, and re-compose
struct _ddebug_info to contain them cleanly. This also lets us get
rid of for_subvec()'s num_##_vec paste-up.
Also recompose struct ddebug_table to contain a _ddebug_info. This
reinforces its use as a cursor into relevant data for a builtin
module, and access to the full _ddebug state for modules.
NOTES:
Fixup names:
Normalize all struct names to "struct _ddebug_*" eliminating the
minor/stupid variations created in classmaps-v1.
Modify __section names: __dyndbg to __dyndbg_descriptors, and
__dyndbg_classes to __dyndbg_class_maps. This better matches the new
struct names, and makes room for forthcoming _ddebug_class_user(s)
structs and section.
Invariant: These vectors ref a contiguous subrange of __section memory
in builtin/DATA or in loadable modules via mod->dyndbg_info; with
guaranteed life-time for us.
struct module contains a _ddebug_info field and module/main.c sets it
up, so that gets adjusted rather obviously.
Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
include/asm-generic/dyndbg.lds.h | 18 +++---
include/linux/dynamic_debug.h | 40 ++++++++-----
kernel/module/main.c | 12 ++--
lib/dynamic_debug.c | 120 +++++++++++++++++++--------------------
lib/test_dynamic_debug.c | 2 +-
5 files changed, 103 insertions(+), 89 deletions(-)
diff --git a/include/asm-generic/dyndbg.lds.h b/include/asm-generic/dyndbg.lds.h
index f95683aa16b6..8345ac6c52b7 100644
--- a/include/asm-generic/dyndbg.lds.h
+++ b/include/asm-generic/dyndbg.lds.h
@@ -3,17 +3,19 @@
#define __ASM_GENERIC_DYNDBG_LDS_H
#include <asm-generic/bounded_sections.lds.h>
-#define DYNDBG_SECTIONS() \
- . = ALIGN(8); \
- BOUNDED_SECTION_BY(__dyndbg, ___dyndbg) \
- BOUNDED_SECTION_BY(__dyndbg_classes, ___dyndbg_classes)
+#define DYNDBG_SECTIONS() \
+ . = ALIGN(8); \
+ BOUNDED_SECTION_BY(__dyndbg_descriptors, ___dyndbg_descs) \
+ BOUNDED_SECTION_BY(__dyndbg_class_maps, ___dyndbg_class_maps)
#define MOD_DYNDBG_SECTIONS() \
- __dyndbg : { \
- BOUNDED_SECTION_BY(__dyndbg, ___dyndbg) \
+ __dyndbg_descriptors : { \
+ BOUNDED_SECTION_BY(__dyndbg_descriptors, \
+ ___dyndbg_descs) \
} \
- __dyndbg_classes : { \
- BOUNDED_SECTION_BY(__dyndbg_classes, ___dyndbg_classes) \
+ __dyndbg_class_maps : { \
+ BOUNDED_SECTION_BY(__dyndbg_class_maps, \
+ ___dyndbg_class_maps) \
}
#endif /* __ASM_GENERIC_DYNDBG_LDS_H */
diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index 9fd36339db52..5429315ada8e 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -83,8 +83,8 @@ enum class_map_type {
*/
};
-struct ddebug_class_map {
- struct module *mod;
+struct _ddebug_class_map {
+ struct module *mod; /* NULL for builtins */
const char *mod_name; /* needed for builtins */
const char **class_names;
const int length;
@@ -92,21 +92,33 @@ struct ddebug_class_map {
enum class_map_type map_type;
};
-/* encapsulate linker provided built-in (or module) dyndbg data */
+/*
+ * @_ddebug_info: gathers module/builtin dyndbg_* __sections together.
+ * For builtins, it is used as a cursor, with the inner structs
+ * marking sub-vectors of the builtin __sections in DATA.
+ */
+struct _ddebug_descs {
+ struct _ddebug *start;
+ int len;
+};
+
+struct _ddebug_class_maps {
+ struct _ddebug_class_map *start;
+ int len;
+};
+
struct _ddebug_info {
- struct _ddebug *descs;
- struct ddebug_class_map *classes;
- unsigned int num_descs;
- unsigned int num_classes;
+ struct _ddebug_descs descs;
+ struct _ddebug_class_maps maps;
};
-struct ddebug_class_param {
+struct _ddebug_class_param {
union {
unsigned long *bits;
unsigned long *lvl;
};
char flags[8];
- const struct ddebug_class_map *map;
+ const struct _ddebug_class_map *map;
};
/*
@@ -125,8 +137,8 @@ struct ddebug_class_param {
*/
#define DECLARE_DYNDBG_CLASSMAP(_var, _maptype, _base, ...) \
static const char *_var##_classnames[] = { __VA_ARGS__ }; \
- static struct ddebug_class_map __aligned(8) __used \
- __section("__dyndbg_classes") _var = { \
+ static struct _ddebug_class_map __aligned(8) __used \
+ __section("__dyndbg_class_maps") _var = { \
.mod = THIS_MODULE, \
.mod_name = KBUILD_MODNAME, \
.base = _base, \
@@ -166,7 +178,7 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
#define DEFINE_DYNAMIC_DEBUG_METADATA_CLS(name, cls, fmt) \
static struct _ddebug __aligned(8) \
- __section("__dyndbg") name = { \
+ __section("__dyndbg_descriptors") name = { \
.modname = KBUILD_MODNAME, \
.function = __func__, \
.filename = __FILE__, \
@@ -253,7 +265,7 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
* macro.
*/
#define _dynamic_func_call_cls(cls, fmt, func, ...) \
- __dynamic_func_call_cls(__UNIQUE_ID(ddebug), cls, fmt, func, ##__VA_ARGS__)
+ __dynamic_func_call_cls(__UNIQUE_ID(_ddebug), cls, fmt, func, ##__VA_ARGS__)
#define _dynamic_func_call(fmt, func, ...) \
_dynamic_func_call_cls(_DPRINTK_CLASS_DFLT, fmt, func, ##__VA_ARGS__)
@@ -263,7 +275,7 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
* with precisely the macro's varargs.
*/
#define _dynamic_func_call_cls_no_desc(cls, fmt, func, ...) \
- __dynamic_func_call_cls_no_desc(__UNIQUE_ID(ddebug), cls, fmt, \
+ __dynamic_func_call_cls_no_desc(__UNIQUE_ID(_ddebug), cls, fmt, \
func, ##__VA_ARGS__)
#define _dynamic_func_call_no_desc(fmt, func, ...) \
_dynamic_func_call_cls_no_desc(_DPRINTK_CLASS_DFLT, fmt, \
diff --git a/kernel/module/main.c b/kernel/module/main.c
index 46dd8d25a605..c2b6e70f2e77 100644
--- a/kernel/module/main.c
+++ b/kernel/module/main.c
@@ -2774,12 +2774,12 @@ static int find_module_sections(struct module *mod, struct load_info *info)
pr_warn("%s: Ignoring obsolete parameters\n", mod->name);
#ifdef CONFIG_DYNAMIC_DEBUG_CORE
- mod->dyndbg_info.descs = section_objs(info, "__dyndbg",
- sizeof(*mod->dyndbg_info.descs),
- &mod->dyndbg_info.num_descs);
- mod->dyndbg_info.classes = section_objs(info, "__dyndbg_classes",
- sizeof(*mod->dyndbg_info.classes),
- &mod->dyndbg_info.num_classes);
+ mod->dyndbg_info.descs.start = section_objs(info, "__dyndbg_descriptors",
+ sizeof(*mod->dyndbg_info.descs.start),
+ &mod->dyndbg_info.descs.len);
+ mod->dyndbg_info.maps.start = section_objs(info, "__dyndbg_class_maps",
+ sizeof(*mod->dyndbg_info.maps.start),
+ &mod->dyndbg_info.maps.len);
#endif
return 0;
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index 8f614eba8ace..f47fdb769d7a 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -39,17 +39,15 @@
#include <rdma/ib_verbs.h>
-extern struct _ddebug __start___dyndbg[];
-extern struct _ddebug __stop___dyndbg[];
-extern struct ddebug_class_map __start___dyndbg_classes[];
-extern struct ddebug_class_map __stop___dyndbg_classes[];
+extern struct _ddebug __start___dyndbg_descs[];
+extern struct _ddebug __stop___dyndbg_descs[];
+extern struct _ddebug_class_map __start___dyndbg_class_maps[];
+extern struct _ddebug_class_map __stop___dyndbg_class_maps[];
struct ddebug_table {
struct list_head link;
const char *mod_name;
- struct _ddebug *ddebugs;
- struct ddebug_class_map *classes;
- unsigned int num_ddebugs, num_classes;
+ struct _ddebug_info info;
};
struct ddebug_query {
@@ -136,19 +134,19 @@ do { \
* @_i: caller provided counter.
* @_sp: cursor into _vec, to examine each item.
* @_box: ptr to a struct containing @_vec member
- * @_vec: name of a member in @_box
+ * @_vec: name of a vector member in @_box
*/
#define __ASSERT_IS_LVALUE(x) ((void)sizeof((void)0, &(x)))
#define __ASSERT_HAS_VEC_MEMBER(_box, _vec) \
- (void)sizeof((_box)->_vec + (_box)->num_##_vec)
+ ((void)sizeof((_box)->_vec.start + (_box)->_vec.len))
#define for_subvec(_i, _sp, _box, _vec) \
for (__ASSERT_IS_LVALUE(_i), \
__ASSERT_IS_LVALUE(_sp), \
__ASSERT_HAS_VEC_MEMBER(_box, _vec), \
(_i) = 0, \
- (_sp) = (_box)->_vec; \
- (_i) < (_box)->num_##_vec; \
+ (_sp) = (_box)->_vec.start; \
+ (_i) < (_box)->_vec.len; \
(_i)++, (_sp)++) /* { block } */
static void vpr_info_dq(const struct ddebug_query *query, const char *msg)
@@ -171,14 +169,14 @@ static void vpr_info_dq(const struct ddebug_query *query, const char *msg)
query->first_lineno, query->last_lineno, query->class_string);
}
-static struct ddebug_class_map *ddebug_find_valid_class(struct ddebug_table const *dt,
+static struct _ddebug_class_map *ddebug_find_valid_class(struct ddebug_table const *dt,
const char *class_string,
int *class_id)
{
- struct ddebug_class_map *map;
+ struct _ddebug_class_map *map;
int i, idx;
- for_subvec(i, map, dt, classes) {
+ for_subvec(i, map, &dt->info, maps) {
idx = match_string(map->class_names, map->length, class_string);
if (idx >= 0) {
*class_id = idx + map->base;
@@ -249,7 +247,7 @@ static int ddebug_change(const struct ddebug_query *query,
unsigned int newflags;
unsigned int nfound = 0;
struct flagsbuf fbuf, nbuf;
- struct ddebug_class_map *map = NULL;
+ struct _ddebug_class_map *map = NULL;
int valid_class;
/* search for matching ddebugs */
@@ -270,8 +268,8 @@ static int ddebug_change(const struct ddebug_query *query,
valid_class = _DPRINTK_CLASS_DFLT;
}
- for (i = 0; i < dt->num_ddebugs; i++) {
- struct _ddebug *dp = &dt->ddebugs[i];
+ for (i = 0; i < dt->info.descs.len; i++) {
+ struct _ddebug *dp = &dt->info.descs.start[i];
if (!ddebug_match_desc(query, dp, valid_class))
continue;
@@ -629,14 +627,14 @@ static int ddebug_exec_queries(char *query, const char *modname)
}
/* apply a new class-param setting */
-static int ddebug_apply_class_bitmap(const struct ddebug_class_param *dcp,
+static int ddebug_apply_class_bitmap(const struct _ddebug_class_param *dcp,
const unsigned long *new_bits,
const unsigned long old_bits,
const char *query_modname)
{
#define QUERY_SIZE 128
char query[QUERY_SIZE];
- const struct ddebug_class_map *map = dcp->map;
+ const struct _ddebug_class_map *map = dcp->map;
int matches = 0;
int bi, ct;
@@ -672,8 +670,8 @@ static int ddebug_apply_class_bitmap(const struct ddebug_class_param *dcp,
/* accept comma-separated-list of [+-] classnames */
static int param_set_dyndbg_classnames(const char *instr, const struct kernel_param *kp)
{
- const struct ddebug_class_param *dcp = kp->arg;
- const struct ddebug_class_map *map = dcp->map;
+ const struct _ddebug_class_param *dcp = kp->arg;
+ const struct _ddebug_class_map *map = dcp->map;
unsigned long curr_bits, old_bits;
char *cl_str, *p, *tmp;
int cls_id, totct = 0;
@@ -743,8 +741,8 @@ static int param_set_dyndbg_module_classes(const char *instr,
const struct kernel_param *kp,
const char *mod_name)
{
- const struct ddebug_class_param *dcp = kp->arg;
- const struct ddebug_class_map *map = dcp->map;
+ const struct _ddebug_class_param *dcp = kp->arg;
+ const struct _ddebug_class_map *map = dcp->map;
unsigned long inrep, new_bits, old_bits;
int rc, totct = 0;
@@ -831,8 +829,8 @@ EXPORT_SYMBOL(param_set_dyndbg_classes);
*/
int param_get_dyndbg_classes(char *buffer, const struct kernel_param *kp)
{
- const struct ddebug_class_param *dcp = kp->arg;
- const struct ddebug_class_map *map = dcp->map;
+ const struct _ddebug_class_param *dcp = kp->arg;
+ const struct _ddebug_class_map *map = dcp->map;
switch (map->map_type) {
@@ -1083,8 +1081,8 @@ static struct _ddebug *ddebug_iter_first(struct ddebug_iter *iter)
}
iter->table = list_entry(ddebug_tables.next,
struct ddebug_table, link);
- iter->idx = iter->table->num_ddebugs;
- return &iter->table->ddebugs[--iter->idx];
+ iter->idx = iter->table->info.descs.len;
+ return &iter->table->info.descs.start[--iter->idx];
}
/*
@@ -1105,10 +1103,10 @@ static struct _ddebug *ddebug_iter_next(struct ddebug_iter *iter)
}
iter->table = list_entry(iter->table->link.next,
struct ddebug_table, link);
- iter->idx = iter->table->num_ddebugs;
+ iter->idx = iter->table->info.descs.len;
--iter->idx;
}
- return &iter->table->ddebugs[iter->idx];
+ return &iter->table->info.descs.start[iter->idx];
}
/*
@@ -1152,16 +1150,19 @@ static void *ddebug_proc_next(struct seq_file *m, void *p, loff_t *pos)
return dp;
}
-#define class_in_range(class_id, map) \
- (class_id >= map->base && class_id < map->base + map->length)
+static bool ddebug_class_in_range(const int class_id, const struct _ddebug_class_map *map)
+{
+ return (class_id >= map->base &&
+ class_id < map->base + map->length);
+}
-static const char *ddebug_class_name(struct ddebug_iter *iter, struct _ddebug *dp)
+static const char *ddebug_class_name(struct ddebug_table *dt, struct _ddebug *dp)
{
- struct ddebug_class_map *map = iter->table->classes;
- int i, nc = iter->table->num_classes;
+ struct _ddebug_class_map *map;
+ int i;
- for (i = 0; i < nc; i++, map++)
- if (class_in_range(dp->class_id, map))
+ for_subvec(i, map, &dt->info, maps)
+ if (ddebug_class_in_range(dp->class_id, map))
return map->class_names[dp->class_id - map->base];
return NULL;
@@ -1194,7 +1195,7 @@ static int ddebug_proc_show(struct seq_file *m, void *p)
seq_putc(m, '"');
if (dp->class_id != _DPRINTK_CLASS_DFLT) {
- class = ddebug_class_name(iter, dp);
+ class = ddebug_class_name(iter->table, dp);
if (class)
seq_printf(m, " class:%s", class);
else
@@ -1246,7 +1247,7 @@ static const struct proc_ops proc_fops = {
static void ddebug_attach_module_classes(struct ddebug_table *dt, struct _ddebug_info *di)
{
- struct ddebug_class_map *cm;
+ struct _ddebug_class_map *cm;
int i, nc = 0;
/*
@@ -1254,18 +1255,18 @@ static void ddebug_attach_module_classes(struct ddebug_table *dt, struct _ddebug
* the builtin/modular classmap vector/section. Save the start
* and length of the subrange at its edges.
*/
- for_subvec(i, cm, di, classes) {
+ for_subvec(i, cm, di, maps) {
if (!strcmp(cm->mod_name, dt->mod_name)) {
if (!nc) {
v2pr_info("start subrange, class[%d]: module:%s base:%d len:%d ty:%d\n",
i, cm->mod_name, cm->base, cm->length, cm->map_type);
- dt->classes = cm;
+ dt->info.maps.start = cm;
}
nc++;
}
}
if (nc) {
- dt->num_classes = nc;
+ dt->info.maps.len = nc;
vpr_info("module:%s attached %d classes\n", dt->mod_name, nc);
}
}
@@ -1278,10 +1279,10 @@ static int ddebug_add_module(struct _ddebug_info *di, const char *modname)
{
struct ddebug_table *dt;
- if (!di->num_descs)
+ if (!di->descs.len)
return 0;
- v3pr_info("add-module: %s %d sites\n", modname, di->num_descs);
+ v3pr_info("add-module: %s %d sites\n", modname, di->descs.len);
dt = kzalloc_obj(*dt);
if (dt == NULL) {
@@ -1295,19 +1296,18 @@ static int ddebug_add_module(struct _ddebug_info *di, const char *modname)
* this struct ddebug_table.
*/
dt->mod_name = modname;
- dt->ddebugs = di->descs;
- dt->num_ddebugs = di->num_descs;
+ dt->info = *di;
INIT_LIST_HEAD(&dt->link);
- if (di->classes && di->num_classes)
+ if (di->maps.len)
ddebug_attach_module_classes(dt, di);
mutex_lock(&ddebug_lock);
list_add_tail(&dt->link, &ddebug_tables);
mutex_unlock(&ddebug_lock);
- vpr_info("%3u debug prints in module %s\n", di->num_descs, modname);
+ vpr_info("%3u debug prints in module %s\n", di->descs.len, modname);
return 0;
}
@@ -1454,10 +1454,10 @@ static int __init dynamic_debug_init(void)
char *cmdline;
struct _ddebug_info di = {
- .descs = __start___dyndbg,
- .classes = __start___dyndbg_classes,
- .num_descs = __stop___dyndbg - __start___dyndbg,
- .num_classes = __stop___dyndbg_classes - __start___dyndbg_classes,
+ .descs.start = __start___dyndbg_descs,
+ .maps.start = __start___dyndbg_class_maps,
+ .descs.len = __stop___dyndbg_descs - __start___dyndbg_descs,
+ .maps.len = __stop___dyndbg_class_maps - __start___dyndbg_class_maps,
};
#ifdef CONFIG_MODULES
@@ -1468,7 +1468,7 @@ static int __init dynamic_debug_init(void)
}
#endif /* CONFIG_MODULES */
- if (&__start___dyndbg == &__stop___dyndbg) {
+ if (&__start___dyndbg_descs == &__stop___dyndbg_descs) {
if (IS_ENABLED(CONFIG_DYNAMIC_DEBUG)) {
pr_warn("_ddebug table is empty in a CONFIG_DYNAMIC_DEBUG build\n");
return 1;
@@ -1478,16 +1478,16 @@ static int __init dynamic_debug_init(void)
return 0;
}
- iter = iter_mod_start = __start___dyndbg;
+ iter = iter_mod_start = __start___dyndbg_descs;
modname = iter->modname;
i = mod_sites = mod_ct = 0;
- for (; iter < __stop___dyndbg; iter++, i++, mod_sites++) {
+ for (; iter < __stop___dyndbg_descs; iter++, i++, mod_sites++) {
if (strcmp(modname, iter->modname)) {
mod_ct++;
- di.num_descs = mod_sites;
- di.descs = iter_mod_start;
+ di.descs.len = mod_sites;
+ di.descs.start = iter_mod_start;
ret = ddebug_add_module(&di, modname);
if (ret)
goto out_err;
@@ -1497,8 +1497,8 @@ static int __init dynamic_debug_init(void)
iter_mod_start = iter;
}
}
- di.num_descs = mod_sites;
- di.descs = iter_mod_start;
+ di.descs.len = mod_sites;
+ di.descs.start = iter_mod_start;
ret = ddebug_add_module(&di, modname);
if (ret)
goto out_err;
@@ -1508,8 +1508,8 @@ static int __init dynamic_debug_init(void)
i, mod_ct, (int)((mod_ct * sizeof(struct ddebug_table)) >> 10),
(int)((i * sizeof(struct _ddebug)) >> 10));
- if (di.num_classes)
- v2pr_info(" %d builtin ddebug class-maps\n", di.num_classes);
+ if (di.maps.len)
+ v2pr_info(" %d builtin ddebug class-maps\n", di.maps.len);
/* now that ddebug tables are loaded, process all boot args
* again to find and activate queries given in dyndbg params.
diff --git a/lib/test_dynamic_debug.c b/lib/test_dynamic_debug.c
index 396144cf351b..8434f70b51bb 100644
--- a/lib/test_dynamic_debug.c
+++ b/lib/test_dynamic_debug.c
@@ -41,7 +41,7 @@ module_param_cb(do_prints, ¶m_ops_do_prints, NULL, 0600);
*/
#define DD_SYS_WRAP(_model, _flags) \
static unsigned long bits_##_model; \
- static struct ddebug_class_param _flags##_model = { \
+ static struct _ddebug_class_param _flags##_model = { \
.bits = &bits_##_model, \
.flags = #_flags, \
.map = &map_##_model, \
--
2.53.0
^ permalink raw reply related
* [PATCH v14 18/92] dyndbg: macrofy a 2-index for-loop pattern
From: Jim Cromie @ 2026-04-23 20:53 UTC (permalink / raw)
To: Arnd Bergmann, Jason Baron, Luis Chamberlain, Petr Pavlu,
Daniel Gomez, Sami Tolvanen, Aaron Tomlin, Andrew Morton,
Jonathan Corbet, Shuah Khan, Shuah Khan, Greg Kroah-Hartman,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
Tvrtko Ursulin, Alex Deucher, Christian König, David Airlie,
Gerd Hoffmann, Dmitry Osipenko, Gurchetan Singh, Chia-I Wu,
Matthew Brost, Thomas Hellström, Lyude Paul,
Danilo Krummrich, Patrik Jakobsson, Zack Rusin,
Broadcom internal kernel review list, Louis Chauvet,
Haneen Mohammed, Melissa Wen, Sean Paul, Jocelyn Falempe,
Ruben Wauters, Dave Stevenson, Maíra Canal,
Raspberry Pi Kernel Maintenance, Rob Clark, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, Xinliang Liu,
Tian Tao, Xinwei Kong, Sumit Semwal, Yongqin Liu, John Stultz,
Philipp Zabel, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, Chun-Kuang Hu, Matthias Brugger,
AngeloGioacchino Del Regno, Sandy Huang, Heiko Stübner,
Andy Yan, Alain Volmat, Raphael Gallais-Pou, Yannick Fertre,
Raphael Gallais-Pou, Philippe Cornu, Maxime Coquelin,
Alexandre Torgue, Oded Gabbay, Maciej Falkowski, Karol Wachowski,
Rob Herring (Arm), Tomeu Vizoso, Liviu Dudau, Andrzej Hajda,
Neil Armstrong, Robert Foss, Laurent Pinchart, Jonas Karlman,
Jernej Skrabec, Liu Ying, Laurentiu Palcu, Lucas Stach,
Paul Kocialkowski, Jianmin Lv, Qianhai Wu, Huacai Chen,
Mingcong Bai, Xi Ruoyao, Icenowy Zheng, Laurent Pinchart,
Tomi Valkeinen, Kieran Bingham, Geert Uytterhoeven, Magnus Damm,
Javier Martinez Canillas, Huang Rui, Matthew Auld, Jani Nikula,
Luca Coelho, Russell King, Christian Gmeiner
Cc: linux-arch, linux-kernel, linux-modules, linux-doc,
linux-kselftest, dri-devel, intel-gfx, amd-gfx, virtualization,
intel-xe, nouveau, spice-devel, linux-arm-msm, freedreno, imx,
linux-arm-kernel, linux-mediatek, linux-rockchip, linux-stm32,
linux-renesas-soc, etnaviv, Jim Cromie
In-Reply-To: <20260423-submit-dyndbg-classmap-foundation-v14-0-2b809a8019d0@gmail.com>
dynamic-debug currently has 2 __sections (__dyndbg, __dyndb_classes),
struct _ddebug_info keeps track of them both, with 2 members each:
_vec and _vec#_len.
We need to loop over these sections, with index and record pointer,
making ref to both _vec and _vec_len. This is already fiddly and
error-prone, and will get worse as we add a 3rd section.
Lets instead embed/abstract the fiddly-ness in the `for_subvec()`
macro, and avoid repeating it going forward.
This is a for-loop macro expander, so it syntactically expects to
precede either a single statement or a { block } of them, and the
usual typeof or do-while-0 tricks are unavailable to fix the
multiple-expansion warning.
The macro needs a lot from its caller: it needs 2 local vars, 1 of
which is a ref to a contained struct with named members. To support
these requirements, add:
1. __ASSERT_IS_LVALUE(_X):
ie: ((void)sizeof((void)0, &(x)))
2. __ASSERT_HAS_VEC_MEMBERS(_X, _Y):
compile-time check that the _Y "vector" exists
ie: _X->_Y and _X->num_##_Y are lvalues.
The for_subvec() macro then invokes these in the initialization of the
for-loop; they disappear at runtime.
Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
lib/dynamic_debug.c | 27 ++++++++++++++++++++++++---
1 file changed, 24 insertions(+), 3 deletions(-)
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index 94a66c8537ab..8f614eba8ace 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -129,6 +129,28 @@ do { \
#define v3pr_info(fmt, ...) vnpr_info(3, fmt, ##__VA_ARGS__)
#define v4pr_info(fmt, ...) vnpr_info(4, fmt, ##__VA_ARGS__)
+/*
+ * simplify a repeated for-loop pattern walking N steps in a T _vec
+ * member inside a struct _box. It expects int i and T *_sp to be
+ * declared in the caller.
+ * @_i: caller provided counter.
+ * @_sp: cursor into _vec, to examine each item.
+ * @_box: ptr to a struct containing @_vec member
+ * @_vec: name of a member in @_box
+ */
+#define __ASSERT_IS_LVALUE(x) ((void)sizeof((void)0, &(x)))
+#define __ASSERT_HAS_VEC_MEMBER(_box, _vec) \
+ (void)sizeof((_box)->_vec + (_box)->num_##_vec)
+
+#define for_subvec(_i, _sp, _box, _vec) \
+ for (__ASSERT_IS_LVALUE(_i), \
+ __ASSERT_IS_LVALUE(_sp), \
+ __ASSERT_HAS_VEC_MEMBER(_box, _vec), \
+ (_i) = 0, \
+ (_sp) = (_box)->_vec; \
+ (_i) < (_box)->num_##_vec; \
+ (_i)++, (_sp)++) /* { block } */
+
static void vpr_info_dq(const struct ddebug_query *query, const char *msg)
{
/* trim any trailing newlines */
@@ -156,7 +178,7 @@ static struct ddebug_class_map *ddebug_find_valid_class(struct ddebug_table cons
struct ddebug_class_map *map;
int i, idx;
- for (map = dt->classes, i = 0; i < dt->num_classes; i++, map++) {
+ for_subvec(i, map, dt, classes) {
idx = match_string(map->class_names, map->length, class_string);
if (idx >= 0) {
*class_id = idx + map->base;
@@ -1232,8 +1254,7 @@ static void ddebug_attach_module_classes(struct ddebug_table *dt, struct _ddebug
* the builtin/modular classmap vector/section. Save the start
* and length of the subrange at its edges.
*/
- for (cm = di->classes, i = 0; i < di->num_classes; i++, cm++) {
-
+ for_subvec(i, cm, di, classes) {
if (!strcmp(cm->mod_name, dt->mod_name)) {
if (!nc) {
v2pr_info("start subrange, class[%d]: module:%s base:%d len:%d ty:%d\n",
--
2.53.0
^ permalink raw reply related
* [PATCH v14 17/92] dyndbg: replace classmap list with a vector
From: Jim Cromie @ 2026-04-23 20:53 UTC (permalink / raw)
To: Arnd Bergmann, Jason Baron, Luis Chamberlain, Petr Pavlu,
Daniel Gomez, Sami Tolvanen, Aaron Tomlin, Andrew Morton,
Jonathan Corbet, Shuah Khan, Shuah Khan, Greg Kroah-Hartman,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
Tvrtko Ursulin, Alex Deucher, Christian König, David Airlie,
Gerd Hoffmann, Dmitry Osipenko, Gurchetan Singh, Chia-I Wu,
Matthew Brost, Thomas Hellström, Lyude Paul,
Danilo Krummrich, Patrik Jakobsson, Zack Rusin,
Broadcom internal kernel review list, Louis Chauvet,
Haneen Mohammed, Melissa Wen, Sean Paul, Jocelyn Falempe,
Ruben Wauters, Dave Stevenson, Maíra Canal,
Raspberry Pi Kernel Maintenance, Rob Clark, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, Xinliang Liu,
Tian Tao, Xinwei Kong, Sumit Semwal, Yongqin Liu, John Stultz,
Philipp Zabel, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, Chun-Kuang Hu, Matthias Brugger,
AngeloGioacchino Del Regno, Sandy Huang, Heiko Stübner,
Andy Yan, Alain Volmat, Raphael Gallais-Pou, Yannick Fertre,
Raphael Gallais-Pou, Philippe Cornu, Maxime Coquelin,
Alexandre Torgue, Oded Gabbay, Maciej Falkowski, Karol Wachowski,
Rob Herring (Arm), Tomeu Vizoso, Liviu Dudau, Andrzej Hajda,
Neil Armstrong, Robert Foss, Laurent Pinchart, Jonas Karlman,
Jernej Skrabec, Liu Ying, Laurentiu Palcu, Lucas Stach,
Paul Kocialkowski, Jianmin Lv, Qianhai Wu, Huacai Chen,
Mingcong Bai, Xi Ruoyao, Icenowy Zheng, Laurent Pinchart,
Tomi Valkeinen, Kieran Bingham, Geert Uytterhoeven, Magnus Damm,
Javier Martinez Canillas, Huang Rui, Matthew Auld, Jani Nikula,
Luca Coelho, Russell King, Christian Gmeiner
Cc: linux-arch, linux-kernel, linux-modules, linux-doc,
linux-kselftest, dri-devel, intel-gfx, amd-gfx, virtualization,
intel-xe, nouveau, spice-devel, linux-arm-msm, freedreno, imx,
linux-arm-kernel, linux-mediatek, linux-rockchip, linux-stm32,
linux-renesas-soc, etnaviv, Jim Cromie
In-Reply-To: <20260423-submit-dyndbg-classmap-foundation-v14-0-2b809a8019d0@gmail.com>
Classmaps are stored in an elf section/array, but currently are
individually list-linked onto dyndbg's per-module ddebug_table for
operation. This is unnecessary.
Just like dyndbg's descriptors, classes are packed in compile order;
so even with many builtin modules employing multiple classmaps, each
modules' maps are packed contiguously, and can be treated as a
array-start-address & array-length.
So this drops the whole list building operation done in
ddebug_attach_module_classes(), and removes the list-head members.
The "select-by-modname" condition is reused to find the start,end of
the subrange.
NOTE: This "filter-by-modname" on classmaps should really be done in
ddebug_add_module(1); ie at least one step closer to ddebug_init(2),
which already splits up pr-debug descriptors into subranges by
modname, then calls (1) on each. (2) knows nothing of classmaps
currently, and doesn't need to. For now, just add comment.
Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
include/linux/dynamic_debug.h | 1 -
lib/dynamic_debug.c | 62 ++++++++++++++++++++++---------------------
2 files changed, 32 insertions(+), 31 deletions(-)
diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index 92627a03b4d1..9fd36339db52 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -84,7 +84,6 @@ enum class_map_type {
};
struct ddebug_class_map {
- struct list_head link;
struct module *mod;
const char *mod_name; /* needed for builtins */
const char **class_names;
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index a18f4bc63473..94a66c8537ab 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -45,10 +45,11 @@ extern struct ddebug_class_map __start___dyndbg_classes[];
extern struct ddebug_class_map __stop___dyndbg_classes[];
struct ddebug_table {
- struct list_head link, maps;
+ struct list_head link;
const char *mod_name;
- unsigned int num_ddebugs;
struct _ddebug *ddebugs;
+ struct ddebug_class_map *classes;
+ unsigned int num_ddebugs, num_classes;
};
struct ddebug_query {
@@ -149,12 +150,13 @@ static void vpr_info_dq(const struct ddebug_query *query, const char *msg)
}
static struct ddebug_class_map *ddebug_find_valid_class(struct ddebug_table const *dt,
- const char *class_string, int *class_id)
+ const char *class_string,
+ int *class_id)
{
struct ddebug_class_map *map;
- int idx;
+ int i, idx;
- list_for_each_entry(map, &dt->maps, link) {
+ for (map = dt->classes, i = 0; i < dt->num_classes; i++, map++) {
idx = match_string(map->class_names, map->length, class_string);
if (idx >= 0) {
*class_id = idx + map->base;
@@ -165,7 +167,6 @@ static struct ddebug_class_map *ddebug_find_valid_class(struct ddebug_table cons
return NULL;
}
-#define __outvar /* filled by callee */
/*
* Search the tables for _ddebug's which match the given `query' and
* apply the `flags' and `mask' to them. Returns number of matching
@@ -227,7 +228,7 @@ static int ddebug_change(const struct ddebug_query *query,
unsigned int nfound = 0;
struct flagsbuf fbuf, nbuf;
struct ddebug_class_map *map = NULL;
- int __outvar valid_class;
+ int valid_class;
/* search for matching ddebugs */
mutex_lock(&ddebug_lock);
@@ -1134,9 +1135,10 @@ static void *ddebug_proc_next(struct seq_file *m, void *p, loff_t *pos)
static const char *ddebug_class_name(struct ddebug_iter *iter, struct _ddebug *dp)
{
- struct ddebug_class_map *map;
+ struct ddebug_class_map *map = iter->table->classes;
+ int i, nc = iter->table->num_classes;
- list_for_each_entry(map, &iter->table->maps, link)
+ for (i = 0; i < nc; i++, map++)
if (class_in_range(dp->class_id, map))
return map->class_names[dp->class_id - map->base];
@@ -1220,30 +1222,31 @@ static const struct proc_ops proc_fops = {
.proc_write = ddebug_proc_write
};
-static void ddebug_attach_module_classes(struct ddebug_table *dt,
- struct ddebug_class_map *classes,
- int num_classes)
+static void ddebug_attach_module_classes(struct ddebug_table *dt, struct _ddebug_info *di)
{
struct ddebug_class_map *cm;
- int i, j, ct = 0;
+ int i, nc = 0;
- for (cm = classes, i = 0; i < num_classes; i++, cm++) {
+ /*
+ * Find this module's classmaps in a subrange/wholerange of
+ * the builtin/modular classmap vector/section. Save the start
+ * and length of the subrange at its edges.
+ */
+ for (cm = di->classes, i = 0; i < di->num_classes; i++, cm++) {
if (!strcmp(cm->mod_name, dt->mod_name)) {
-
- v2pr_info("class[%d]: module:%s base:%d len:%d ty:%d\n", i,
- cm->mod_name, cm->base, cm->length, cm->map_type);
-
- for (j = 0; j < cm->length; j++)
- v3pr_info(" %d: %d %s\n", j + cm->base, j,
- cm->class_names[j]);
-
- list_add(&cm->link, &dt->maps);
- ct++;
+ if (!nc) {
+ v2pr_info("start subrange, class[%d]: module:%s base:%d len:%d ty:%d\n",
+ i, cm->mod_name, cm->base, cm->length, cm->map_type);
+ dt->classes = cm;
+ }
+ nc++;
}
}
- if (ct)
- vpr_info("module:%s attached %d classes\n", dt->mod_name, ct);
+ if (nc) {
+ dt->num_classes = nc;
+ vpr_info("module:%s attached %d classes\n", dt->mod_name, nc);
+ }
}
/*
@@ -1275,10 +1278,9 @@ static int ddebug_add_module(struct _ddebug_info *di, const char *modname)
dt->num_ddebugs = di->num_descs;
INIT_LIST_HEAD(&dt->link);
- INIT_LIST_HEAD(&dt->maps);
if (di->classes && di->num_classes)
- ddebug_attach_module_classes(dt, di->classes, di->num_classes);
+ ddebug_attach_module_classes(dt, di);
mutex_lock(&ddebug_lock);
list_add_tail(&dt->link, &ddebug_tables);
@@ -1391,8 +1393,8 @@ static void ddebug_remove_all_tables(void)
mutex_lock(&ddebug_lock);
while (!list_empty(&ddebug_tables)) {
struct ddebug_table *dt = list_entry(ddebug_tables.next,
- struct ddebug_table,
- link);
+ struct ddebug_table,
+ link);
ddebug_table_free(dt);
}
mutex_unlock(&ddebug_lock);
--
2.53.0
^ permalink raw reply related
* [PATCH v14 16/92] dyndbg: tighten fn-sig of ddebug_apply_class_bitmap
From: Jim Cromie @ 2026-04-23 20:53 UTC (permalink / raw)
To: Arnd Bergmann, Jason Baron, Luis Chamberlain, Petr Pavlu,
Daniel Gomez, Sami Tolvanen, Aaron Tomlin, Andrew Morton,
Jonathan Corbet, Shuah Khan, Shuah Khan, Greg Kroah-Hartman,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
Tvrtko Ursulin, Alex Deucher, Christian König, David Airlie,
Gerd Hoffmann, Dmitry Osipenko, Gurchetan Singh, Chia-I Wu,
Matthew Brost, Thomas Hellström, Lyude Paul,
Danilo Krummrich, Patrik Jakobsson, Zack Rusin,
Broadcom internal kernel review list, Louis Chauvet,
Haneen Mohammed, Melissa Wen, Sean Paul, Jocelyn Falempe,
Ruben Wauters, Dave Stevenson, Maíra Canal,
Raspberry Pi Kernel Maintenance, Rob Clark, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, Xinliang Liu,
Tian Tao, Xinwei Kong, Sumit Semwal, Yongqin Liu, John Stultz,
Philipp Zabel, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, Chun-Kuang Hu, Matthias Brugger,
AngeloGioacchino Del Regno, Sandy Huang, Heiko Stübner,
Andy Yan, Alain Volmat, Raphael Gallais-Pou, Yannick Fertre,
Raphael Gallais-Pou, Philippe Cornu, Maxime Coquelin,
Alexandre Torgue, Oded Gabbay, Maciej Falkowski, Karol Wachowski,
Rob Herring (Arm), Tomeu Vizoso, Liviu Dudau, Andrzej Hajda,
Neil Armstrong, Robert Foss, Laurent Pinchart, Jonas Karlman,
Jernej Skrabec, Liu Ying, Laurentiu Palcu, Lucas Stach,
Paul Kocialkowski, Jianmin Lv, Qianhai Wu, Huacai Chen,
Mingcong Bai, Xi Ruoyao, Icenowy Zheng, Laurent Pinchart,
Tomi Valkeinen, Kieran Bingham, Geert Uytterhoeven, Magnus Damm,
Javier Martinez Canillas, Huang Rui, Matthew Auld, Jani Nikula,
Luca Coelho, Russell King, Christian Gmeiner
Cc: linux-arch, linux-kernel, linux-modules, linux-doc,
linux-kselftest, dri-devel, intel-gfx, amd-gfx, virtualization,
intel-xe, nouveau, spice-devel, linux-arm-msm, freedreno, imx,
linux-arm-kernel, linux-mediatek, linux-rockchip, linux-stm32,
linux-renesas-soc, etnaviv, Jim Cromie
In-Reply-To: <20260423-submit-dyndbg-classmap-foundation-v14-0-2b809a8019d0@gmail.com>
old_bits arg is currently a pointer to the input bits, but this could
allow inadvertent changes to the input by the fn. Disallow this.
And constify new_bits while here.
Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
lib/dynamic_debug.c | 21 +++++++++++----------
1 file changed, 11 insertions(+), 10 deletions(-)
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index 4313c8803007..a18f4bc63473 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -607,7 +607,8 @@ static int ddebug_exec_queries(char *query, const char *modname)
/* apply a new class-param setting */
static int ddebug_apply_class_bitmap(const struct ddebug_class_param *dcp,
- unsigned long *new_bits, unsigned long *old_bits,
+ const unsigned long *new_bits,
+ const unsigned long old_bits,
const char *query_modname)
{
#define QUERY_SIZE 128
@@ -616,12 +617,12 @@ static int ddebug_apply_class_bitmap(const struct ddebug_class_param *dcp,
int matches = 0;
int bi, ct;
- if (*new_bits != *old_bits)
+ if (*new_bits != old_bits)
v2pr_info("apply bitmap: 0x%lx to: 0x%lx for %s\n", *new_bits,
- *old_bits, query_modname ?: "'*'");
+ old_bits, query_modname ?: "'*'");
for (bi = 0; bi < map->length; bi++) {
- if (test_bit(bi, new_bits) == test_bit(bi, old_bits))
+ if (test_bit(bi, new_bits) == test_bit(bi, &old_bits))
continue;
snprintf(query, QUERY_SIZE, "class %s %c%s", map->class_names[bi],
@@ -633,9 +634,9 @@ static int ddebug_apply_class_bitmap(const struct ddebug_class_param *dcp,
v2pr_info("bit_%d: %d matches on class: %s -> 0x%lx\n", bi,
ct, map->class_names[bi], *new_bits);
}
- if (*new_bits != *old_bits)
+ if (*new_bits != old_bits)
v2pr_info("applied bitmap: 0x%lx to: 0x%lx for %s\n", *new_bits,
- *old_bits, query_modname ?: "'*'");
+ old_bits, query_modname ?: "'*'");
return matches;
}
@@ -691,7 +692,7 @@ static int param_set_dyndbg_classnames(const char *instr, const struct kernel_pa
continue;
}
curr_bits ^= BIT(cls_id);
- totct += ddebug_apply_class_bitmap(dcp, &curr_bits, dcp->bits, NULL);
+ totct += ddebug_apply_class_bitmap(dcp, &curr_bits, *dcp->bits, NULL);
*dcp->bits = curr_bits;
v2pr_info("%s: changed bit %d:%s\n", KP_NAME(kp), cls_id,
map->class_names[cls_id]);
@@ -701,7 +702,7 @@ static int param_set_dyndbg_classnames(const char *instr, const struct kernel_pa
old_bits = CLASSMAP_BITMASK(*dcp->lvl);
curr_bits = CLASSMAP_BITMASK(cls_id + (wanted ? 1 : 0 ));
- totct += ddebug_apply_class_bitmap(dcp, &curr_bits, &old_bits, NULL);
+ totct += ddebug_apply_class_bitmap(dcp, &curr_bits, old_bits, NULL);
*dcp->lvl = (cls_id + (wanted ? 1 : 0));
v2pr_info("%s: changed bit-%d: \"%s\" %lx->%lx\n", KP_NAME(kp), cls_id,
map->class_names[cls_id], old_bits, curr_bits);
@@ -755,7 +756,7 @@ static int param_set_dyndbg_module_classes(const char *instr,
inrep &= CLASSMAP_BITMASK(map->length);
}
v2pr_info("bits:0x%lx > %s.%s\n", inrep, mod_name ?: "*", KP_NAME(kp));
- totct += ddebug_apply_class_bitmap(dcp, &inrep, dcp->bits, mod_name);
+ totct += ddebug_apply_class_bitmap(dcp, &inrep, *dcp->bits, mod_name);
*dcp->bits = inrep;
break;
case DD_CLASS_TYPE_LEVEL_NUM:
@@ -768,7 +769,7 @@ static int param_set_dyndbg_module_classes(const char *instr,
old_bits = CLASSMAP_BITMASK(*dcp->lvl);
new_bits = CLASSMAP_BITMASK(inrep);
v2pr_info("lvl:%ld bits:0x%lx > %s\n", inrep, new_bits, KP_NAME(kp));
- totct += ddebug_apply_class_bitmap(dcp, &new_bits, &old_bits, mod_name);
+ totct += ddebug_apply_class_bitmap(dcp, &new_bits, old_bits, mod_name);
*dcp->lvl = inrep;
break;
default:
--
2.53.0
^ permalink raw reply related
* [PATCH v14 15/92] dyndbg: refactor param_set_dyndbg_classes and below
From: Jim Cromie @ 2026-04-23 20:53 UTC (permalink / raw)
To: Arnd Bergmann, Jason Baron, Luis Chamberlain, Petr Pavlu,
Daniel Gomez, Sami Tolvanen, Aaron Tomlin, Andrew Morton,
Jonathan Corbet, Shuah Khan, Shuah Khan, Greg Kroah-Hartman,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
Tvrtko Ursulin, Alex Deucher, Christian König, David Airlie,
Gerd Hoffmann, Dmitry Osipenko, Gurchetan Singh, Chia-I Wu,
Matthew Brost, Thomas Hellström, Lyude Paul,
Danilo Krummrich, Patrik Jakobsson, Zack Rusin,
Broadcom internal kernel review list, Louis Chauvet,
Haneen Mohammed, Melissa Wen, Sean Paul, Jocelyn Falempe,
Ruben Wauters, Dave Stevenson, Maíra Canal,
Raspberry Pi Kernel Maintenance, Rob Clark, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, Xinliang Liu,
Tian Tao, Xinwei Kong, Sumit Semwal, Yongqin Liu, John Stultz,
Philipp Zabel, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, Chun-Kuang Hu, Matthias Brugger,
AngeloGioacchino Del Regno, Sandy Huang, Heiko Stübner,
Andy Yan, Alain Volmat, Raphael Gallais-Pou, Yannick Fertre,
Raphael Gallais-Pou, Philippe Cornu, Maxime Coquelin,
Alexandre Torgue, Oded Gabbay, Maciej Falkowski, Karol Wachowski,
Rob Herring (Arm), Tomeu Vizoso, Liviu Dudau, Andrzej Hajda,
Neil Armstrong, Robert Foss, Laurent Pinchart, Jonas Karlman,
Jernej Skrabec, Liu Ying, Laurentiu Palcu, Lucas Stach,
Paul Kocialkowski, Jianmin Lv, Qianhai Wu, Huacai Chen,
Mingcong Bai, Xi Ruoyao, Icenowy Zheng, Laurent Pinchart,
Tomi Valkeinen, Kieran Bingham, Geert Uytterhoeven, Magnus Damm,
Javier Martinez Canillas, Huang Rui, Matthew Auld, Jani Nikula,
Luca Coelho, Russell King, Christian Gmeiner
Cc: linux-arch, linux-kernel, linux-modules, linux-doc,
linux-kselftest, dri-devel, intel-gfx, amd-gfx, virtualization,
intel-xe, nouveau, spice-devel, linux-arm-msm, freedreno, imx,
linux-arm-kernel, linux-mediatek, linux-rockchip, linux-stm32,
linux-renesas-soc, etnaviv, Jim Cromie
In-Reply-To: <20260423-submit-dyndbg-classmap-foundation-v14-0-2b809a8019d0@gmail.com>
Refactor callchain below param_set_dyndbg_classes(1) to allow mod-name
specific settings. Split (1) into upper/lower fns, adding modname
param to lower, and passing NULL in from upper. Below that, add the
same param to ddebug_apply_class_bitmap(), and pass it thru to
_ddebug_queries(), replacing NULL with the param.
This allows the callchain to update the classmap in just one module,
vs just all as currently done. While the sysfs param is unlikely to
ever update just one module, the callchain will be used for modprobe
handling, which should update only that just-probed module.
In ddebug_apply_class_bitmap(), also check for actual changes to the
bits before announcing them, to declutter logs.
No functional change.
Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
lib/dynamic_debug.c | 65 ++++++++++++++++++++++++++++++++---------------------
1 file changed, 40 insertions(+), 25 deletions(-)
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index 3ae9ecabdad1..4313c8803007 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -605,9 +605,10 @@ static int ddebug_exec_queries(char *query, const char *modname)
return nfound;
}
-/* apply a new bitmap to the sys-knob's current bit-state */
+/* apply a new class-param setting */
static int ddebug_apply_class_bitmap(const struct ddebug_class_param *dcp,
- unsigned long *new_bits, unsigned long *old_bits)
+ unsigned long *new_bits, unsigned long *old_bits,
+ const char *query_modname)
{
#define QUERY_SIZE 128
char query[QUERY_SIZE];
@@ -615,7 +616,9 @@ static int ddebug_apply_class_bitmap(const struct ddebug_class_param *dcp,
int matches = 0;
int bi, ct;
- v2pr_info("apply: 0x%lx to: 0x%lx\n", *new_bits, *old_bits);
+ if (*new_bits != *old_bits)
+ v2pr_info("apply bitmap: 0x%lx to: 0x%lx for %s\n", *new_bits,
+ *old_bits, query_modname ?: "'*'");
for (bi = 0; bi < map->length; bi++) {
if (test_bit(bi, new_bits) == test_bit(bi, old_bits))
@@ -624,12 +627,16 @@ static int ddebug_apply_class_bitmap(const struct ddebug_class_param *dcp,
snprintf(query, QUERY_SIZE, "class %s %c%s", map->class_names[bi],
test_bit(bi, new_bits) ? '+' : '-', dcp->flags);
- ct = ddebug_exec_queries(query, NULL);
+ ct = ddebug_exec_queries(query, query_modname);
matches += ct;
v2pr_info("bit_%d: %d matches on class: %s -> 0x%lx\n", bi,
ct, map->class_names[bi], *new_bits);
}
+ if (*new_bits != *old_bits)
+ v2pr_info("applied bitmap: 0x%lx to: 0x%lx for %s\n", *new_bits,
+ *old_bits, query_modname ?: "'*'");
+
return matches;
}
@@ -684,7 +691,7 @@ static int param_set_dyndbg_classnames(const char *instr, const struct kernel_pa
continue;
}
curr_bits ^= BIT(cls_id);
- totct += ddebug_apply_class_bitmap(dcp, &curr_bits, dcp->bits);
+ totct += ddebug_apply_class_bitmap(dcp, &curr_bits, dcp->bits, NULL);
*dcp->bits = curr_bits;
v2pr_info("%s: changed bit %d:%s\n", KP_NAME(kp), cls_id,
map->class_names[cls_id]);
@@ -694,7 +701,7 @@ static int param_set_dyndbg_classnames(const char *instr, const struct kernel_pa
old_bits = CLASSMAP_BITMASK(*dcp->lvl);
curr_bits = CLASSMAP_BITMASK(cls_id + (wanted ? 1 : 0 ));
- totct += ddebug_apply_class_bitmap(dcp, &curr_bits, &old_bits);
+ totct += ddebug_apply_class_bitmap(dcp, &curr_bits, &old_bits, NULL);
*dcp->lvl = (cls_id + (wanted ? 1 : 0));
v2pr_info("%s: changed bit-%d: \"%s\" %lx->%lx\n", KP_NAME(kp), cls_id,
map->class_names[cls_id], old_bits, curr_bits);
@@ -708,18 +715,9 @@ static int param_set_dyndbg_classnames(const char *instr, const struct kernel_pa
return 0;
}
-/**
- * param_set_dyndbg_classes - class FOO >control
- * @instr: string echo>d to sysfs, input depends on map_type
- * @kp: kp->arg has state: bits/lvl, map, map_type
- *
- * Enable/disable prdbgs by their class, as given in the arguments to
- * DECLARE_DYNDBG_CLASSMAP. For LEVEL map-types, enforce relative
- * levels by bitpos.
- *
- * Returns: 0 or <0 if error.
- */
-int param_set_dyndbg_classes(const char *instr, const struct kernel_param *kp)
+static int param_set_dyndbg_module_classes(const char *instr,
+ const struct kernel_param *kp,
+ const char *mod_name)
{
const struct ddebug_class_param *dcp = kp->arg;
const struct ddebug_class_map *map = dcp->map;
@@ -756,8 +754,8 @@ int param_set_dyndbg_classes(const char *instr, const struct kernel_param *kp)
KP_NAME(kp), inrep, CLASSMAP_BITMASK(map->length));
inrep &= CLASSMAP_BITMASK(map->length);
}
- v2pr_info("bits:%lx > %s\n", inrep, KP_NAME(kp));
- totct += ddebug_apply_class_bitmap(dcp, &inrep, dcp->bits);
+ v2pr_info("bits:0x%lx > %s.%s\n", inrep, mod_name ?: "*", KP_NAME(kp));
+ totct += ddebug_apply_class_bitmap(dcp, &inrep, dcp->bits, mod_name);
*dcp->bits = inrep;
break;
case DD_CLASS_TYPE_LEVEL_NUM:
@@ -770,7 +768,7 @@ int param_set_dyndbg_classes(const char *instr, const struct kernel_param *kp)
old_bits = CLASSMAP_BITMASK(*dcp->lvl);
new_bits = CLASSMAP_BITMASK(inrep);
v2pr_info("lvl:%ld bits:0x%lx > %s\n", inrep, new_bits, KP_NAME(kp));
- totct += ddebug_apply_class_bitmap(dcp, &new_bits, &old_bits);
+ totct += ddebug_apply_class_bitmap(dcp, &new_bits, &old_bits, mod_name);
*dcp->lvl = inrep;
break;
default:
@@ -779,16 +777,33 @@ int param_set_dyndbg_classes(const char *instr, const struct kernel_param *kp)
vpr_info("%s: total matches: %d\n", KP_NAME(kp), totct);
return 0;
}
+
+/**
+ * param_set_dyndbg_classes - classmap kparam setter
+ * @instr: string echo>d to sysfs, input depends on map_type
+ * @kp: kp->arg has state: bits/lvl, map, map_type
+ *
+ * enable/disable all class'd pr_debugs in the classmap. For LEVEL
+ * map-types, enforce * relative levels by bitpos.
+ *
+ * Returns: 0 or <0 if error.
+ */
+int param_set_dyndbg_classes(const char *instr, const struct kernel_param *kp)
+{
+ return param_set_dyndbg_module_classes(instr, kp, NULL);
+}
EXPORT_SYMBOL(param_set_dyndbg_classes);
/**
- * param_get_dyndbg_classes - classes reader
+ * param_get_dyndbg_classes - classmap kparam getter
* @buffer: string description of controlled bits -> classes
* @kp: kp->arg has state: bits, map
*
- * Reads last written state, underlying prdbg state may have been
- * altered by direct >control. Displays 0x for DISJOINT, 0-N for
- * LEVEL Returns: #chars written or <0 on error
+ * Reads last written state, underlying pr_debug states may have been
+ * altered by direct >control. Displays 0x for DISJOINT classmap
+ * types, 0-N for LEVEL types.
+ *
+ * Returns: ct of chars written or <0 on error
*/
int param_get_dyndbg_classes(char *buffer, const struct kernel_param *kp)
{
--
2.53.0
^ permalink raw reply related
* [PATCH v14 14/92] dyndbg: reduce verbose/debug clutter
From: Jim Cromie @ 2026-04-23 20:53 UTC (permalink / raw)
To: Arnd Bergmann, Jason Baron, Luis Chamberlain, Petr Pavlu,
Daniel Gomez, Sami Tolvanen, Aaron Tomlin, Andrew Morton,
Jonathan Corbet, Shuah Khan, Shuah Khan, Greg Kroah-Hartman,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
Tvrtko Ursulin, Alex Deucher, Christian König, David Airlie,
Gerd Hoffmann, Dmitry Osipenko, Gurchetan Singh, Chia-I Wu,
Matthew Brost, Thomas Hellström, Lyude Paul,
Danilo Krummrich, Patrik Jakobsson, Zack Rusin,
Broadcom internal kernel review list, Louis Chauvet,
Haneen Mohammed, Melissa Wen, Sean Paul, Jocelyn Falempe,
Ruben Wauters, Dave Stevenson, Maíra Canal,
Raspberry Pi Kernel Maintenance, Rob Clark, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, Xinliang Liu,
Tian Tao, Xinwei Kong, Sumit Semwal, Yongqin Liu, John Stultz,
Philipp Zabel, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, Chun-Kuang Hu, Matthias Brugger,
AngeloGioacchino Del Regno, Sandy Huang, Heiko Stübner,
Andy Yan, Alain Volmat, Raphael Gallais-Pou, Yannick Fertre,
Raphael Gallais-Pou, Philippe Cornu, Maxime Coquelin,
Alexandre Torgue, Oded Gabbay, Maciej Falkowski, Karol Wachowski,
Rob Herring (Arm), Tomeu Vizoso, Liviu Dudau, Andrzej Hajda,
Neil Armstrong, Robert Foss, Laurent Pinchart, Jonas Karlman,
Jernej Skrabec, Liu Ying, Laurentiu Palcu, Lucas Stach,
Paul Kocialkowski, Jianmin Lv, Qianhai Wu, Huacai Chen,
Mingcong Bai, Xi Ruoyao, Icenowy Zheng, Laurent Pinchart,
Tomi Valkeinen, Kieran Bingham, Geert Uytterhoeven, Magnus Damm,
Javier Martinez Canillas, Huang Rui, Matthew Auld, Jani Nikula,
Luca Coelho, Russell King, Christian Gmeiner
Cc: linux-arch, linux-kernel, linux-modules, linux-doc,
linux-kselftest, dri-devel, intel-gfx, amd-gfx, virtualization,
intel-xe, nouveau, spice-devel, linux-arm-msm, freedreno, imx,
linux-arm-kernel, linux-mediatek, linux-rockchip, linux-stm32,
linux-renesas-soc, etnaviv, Jim Cromie
In-Reply-To: <20260423-submit-dyndbg-classmap-foundation-v14-0-2b809a8019d0@gmail.com>
currently, for verbose=3, these are logged (blank lines for clarity):
dyndbg: query 0: "class DRM_UT_CORE +p" mod:*
dyndbg: split into words: "class" "DRM_UT_CORE" "+p"
dyndbg: op='+'
dyndbg: flags=0x1
dyndbg: *flagsp=0x1 *maskp=0xffffffff
dyndbg: parsed: func="" file="" module="" format="" lineno=0-0 class=...
dyndbg: no matches for query
dyndbg: no-match: func="" file="" module="" format="" lineno=0-0 class=...
dyndbg: processed 1 queries, with 0 matches, 0 errs
That is excessive, so this patch:
- shrinks 3 lines of 2nd stanza to single line
- drops 1st 2 lines of 3rd stanza
3rd line is like 1st, with result, not procedure.
2nd line is just status, retold in 4th, with more info.
New output:
dyndbg: query 0: "class DRM_UT_CORE +p" mod:*
dyndbg: split into words: "class" "DRM_UT_CORE" "+p"
dyndbg: op='+' flags=0x1 *flagsp=0x1 *maskp=0xffffffff
dyndbg: no-match: func="" file="" module="" format="" lineno=0-0 class=...
dyndbg: processed 1 queries, with 0 matches, 0 errs
Also reduce verbose=3 messages in ddebug_add_module
When modprobing a module, dyndbg currently logs/says "add-module", and
then "skipping" if the module has no prdbgs. Instead just check 1st
and return quietly.
no functional change
Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
lib/dynamic_debug.c | 21 ++++++---------------
1 file changed, 6 insertions(+), 15 deletions(-)
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index 9575b92a8deb..3ae9ecabdad1 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -276,9 +276,6 @@ static int ddebug_change(const struct ddebug_query *query,
}
mutex_unlock(&ddebug_lock);
- if (!nfound && verbose)
- pr_info("no matches for query\n");
-
return nfound;
}
@@ -511,7 +508,6 @@ static int ddebug_parse_flags(const char *str, struct flag_settings *modifiers)
pr_err("bad flag-op %c, at start of %s\n", *str, str);
return -EINVAL;
}
- v3pr_info("op='%c'\n", op);
for (; *str ; ++str) {
for (i = ARRAY_SIZE(opt_array) - 1; i >= 0; i--) {
@@ -525,7 +521,6 @@ static int ddebug_parse_flags(const char *str, struct flag_settings *modifiers)
return -EINVAL;
}
}
- v3pr_info("flags=0x%x\n", modifiers->flags);
/* calculate final flags, mask based upon op */
switch (op) {
@@ -541,7 +536,7 @@ static int ddebug_parse_flags(const char *str, struct flag_settings *modifiers)
modifiers->flags = 0;
break;
}
- v3pr_info("*flagsp=0x%x *maskp=0x%x\n", modifiers->flags, modifiers->mask);
+ v3pr_info("op='%c' flags=0x%x maskp=0x%x\n", op, modifiers->flags, modifiers->mask);
return 0;
}
@@ -551,7 +546,7 @@ static int ddebug_exec_query(char *query_string, const char *modname)
struct flag_settings modifiers = {};
struct ddebug_query query = {};
#define MAXWORDS 9
- int nwords, nfound;
+ int nwords;
char *words[MAXWORDS];
nwords = ddebug_tokenize(query_string, words, MAXWORDS);
@@ -569,10 +564,7 @@ static int ddebug_exec_query(char *query_string, const char *modname)
return -EINVAL;
}
/* actually go and implement the change */
- nfound = ddebug_change(&query, &modifiers);
- vpr_info_dq(&query, nfound ? "applied" : "no-match");
-
- return nfound;
+ return ddebug_change(&query, &modifiers);
}
/* handle multiple queries in query string, continue on error, return
@@ -1246,11 +1238,10 @@ static int ddebug_add_module(struct _ddebug_info *di, const char *modname)
{
struct ddebug_table *dt;
- v3pr_info("add-module: %s.%d sites\n", modname, di->num_descs);
- if (!di->num_descs) {
- v3pr_info(" skip %s\n", modname);
+ if (!di->num_descs)
return 0;
- }
+
+ v3pr_info("add-module: %s %d sites\n", modname, di->num_descs);
dt = kzalloc_obj(*dt);
if (dt == NULL) {
--
2.53.0
^ permalink raw reply related
* [PATCH v14 13/92] dyndbg: tweak pr_fmt to avoid expansion conflicts
From: Jim Cromie @ 2026-04-23 20:53 UTC (permalink / raw)
To: Arnd Bergmann, Jason Baron, Luis Chamberlain, Petr Pavlu,
Daniel Gomez, Sami Tolvanen, Aaron Tomlin, Andrew Morton,
Jonathan Corbet, Shuah Khan, Shuah Khan, Greg Kroah-Hartman,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
Tvrtko Ursulin, Alex Deucher, Christian König, David Airlie,
Gerd Hoffmann, Dmitry Osipenko, Gurchetan Singh, Chia-I Wu,
Matthew Brost, Thomas Hellström, Lyude Paul,
Danilo Krummrich, Patrik Jakobsson, Zack Rusin,
Broadcom internal kernel review list, Louis Chauvet,
Haneen Mohammed, Melissa Wen, Sean Paul, Jocelyn Falempe,
Ruben Wauters, Dave Stevenson, Maíra Canal,
Raspberry Pi Kernel Maintenance, Rob Clark, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, Xinliang Liu,
Tian Tao, Xinwei Kong, Sumit Semwal, Yongqin Liu, John Stultz,
Philipp Zabel, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, Chun-Kuang Hu, Matthias Brugger,
AngeloGioacchino Del Regno, Sandy Huang, Heiko Stübner,
Andy Yan, Alain Volmat, Raphael Gallais-Pou, Yannick Fertre,
Raphael Gallais-Pou, Philippe Cornu, Maxime Coquelin,
Alexandre Torgue, Oded Gabbay, Maciej Falkowski, Karol Wachowski,
Rob Herring (Arm), Tomeu Vizoso, Liviu Dudau, Andrzej Hajda,
Neil Armstrong, Robert Foss, Laurent Pinchart, Jonas Karlman,
Jernej Skrabec, Liu Ying, Laurentiu Palcu, Lucas Stach,
Paul Kocialkowski, Jianmin Lv, Qianhai Wu, Huacai Chen,
Mingcong Bai, Xi Ruoyao, Icenowy Zheng, Laurent Pinchart,
Tomi Valkeinen, Kieran Bingham, Geert Uytterhoeven, Magnus Damm,
Javier Martinez Canillas, Huang Rui, Matthew Auld, Jani Nikula,
Luca Coelho, Russell King, Christian Gmeiner
Cc: linux-arch, linux-kernel, linux-modules, linux-doc,
linux-kselftest, dri-devel, intel-gfx, amd-gfx, virtualization,
intel-xe, nouveau, spice-devel, linux-arm-msm, freedreno, imx,
linux-arm-kernel, linux-mediatek, linux-rockchip, linux-stm32,
linux-renesas-soc, etnaviv, Jim Cromie
In-Reply-To: <20260423-submit-dyndbg-classmap-foundation-v14-0-2b809a8019d0@gmail.com>
Disambiguate pr_fmt(fmt) arg, by changing it to _FMT_, to avoid naming
confusion with many later macros also using that argname.
no functional change
Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
lib/dynamic_debug.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index ffa1cf7c2c72..9575b92a8deb 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -11,7 +11,7 @@
* Copyright (C) 2013 Du, Changbin <changbin.du@gmail.com>
*/
-#define pr_fmt(fmt) "dyndbg: " fmt
+#define pr_fmt(_FMT_) "dyndbg: " _FMT_
#include <linux/kernel.h>
#include <linux/module.h>
--
2.53.0
^ permalink raw reply related
* [PATCH v14 12/92] dyndbg: drop NUM_TYPE_ARRAY
From: Jim Cromie @ 2026-04-23 20:53 UTC (permalink / raw)
To: Arnd Bergmann, Jason Baron, Luis Chamberlain, Petr Pavlu,
Daniel Gomez, Sami Tolvanen, Aaron Tomlin, Andrew Morton,
Jonathan Corbet, Shuah Khan, Shuah Khan, Greg Kroah-Hartman,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
Tvrtko Ursulin, Alex Deucher, Christian König, David Airlie,
Gerd Hoffmann, Dmitry Osipenko, Gurchetan Singh, Chia-I Wu,
Matthew Brost, Thomas Hellström, Lyude Paul,
Danilo Krummrich, Patrik Jakobsson, Zack Rusin,
Broadcom internal kernel review list, Louis Chauvet,
Haneen Mohammed, Melissa Wen, Sean Paul, Jocelyn Falempe,
Ruben Wauters, Dave Stevenson, Maíra Canal,
Raspberry Pi Kernel Maintenance, Rob Clark, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, Xinliang Liu,
Tian Tao, Xinwei Kong, Sumit Semwal, Yongqin Liu, John Stultz,
Philipp Zabel, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, Chun-Kuang Hu, Matthias Brugger,
AngeloGioacchino Del Regno, Sandy Huang, Heiko Stübner,
Andy Yan, Alain Volmat, Raphael Gallais-Pou, Yannick Fertre,
Raphael Gallais-Pou, Philippe Cornu, Maxime Coquelin,
Alexandre Torgue, Oded Gabbay, Maciej Falkowski, Karol Wachowski,
Rob Herring (Arm), Tomeu Vizoso, Liviu Dudau, Andrzej Hajda,
Neil Armstrong, Robert Foss, Laurent Pinchart, Jonas Karlman,
Jernej Skrabec, Liu Ying, Laurentiu Palcu, Lucas Stach,
Paul Kocialkowski, Jianmin Lv, Qianhai Wu, Huacai Chen,
Mingcong Bai, Xi Ruoyao, Icenowy Zheng, Laurent Pinchart,
Tomi Valkeinen, Kieran Bingham, Geert Uytterhoeven, Magnus Damm,
Javier Martinez Canillas, Huang Rui, Matthew Auld, Jani Nikula,
Luca Coelho, Russell King, Christian Gmeiner
Cc: linux-arch, linux-kernel, linux-modules, linux-doc,
linux-kselftest, dri-devel, intel-gfx, amd-gfx, virtualization,
intel-xe, nouveau, spice-devel, linux-arm-msm, freedreno, imx,
linux-arm-kernel, linux-mediatek, linux-rockchip, linux-stm32,
linux-renesas-soc, etnaviv, Jim Cromie
In-Reply-To: <20260423-submit-dyndbg-classmap-foundation-v14-0-2b809a8019d0@gmail.com>
ARRAY_SIZE works here, since array decl is complete.
no functional change
Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
include/linux/dynamic_debug.h | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index 441305277914..92627a03b4d1 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -132,11 +132,9 @@ struct ddebug_class_param {
.mod_name = KBUILD_MODNAME, \
.base = _base, \
.map_type = _maptype, \
- .length = NUM_TYPE_ARGS(char*, __VA_ARGS__), \
+ .length = ARRAY_SIZE(_var##_classnames), \
.class_names = _var##_classnames, \
}
-#define NUM_TYPE_ARGS(eltype, ...) \
- (sizeof((eltype[]) {__VA_ARGS__}) / sizeof(eltype))
extern __printf(2, 3)
void __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...);
--
2.53.0
^ permalink raw reply related
* [PATCH v14 11/92] dyndbg: make ddebug_class_param union members same size
From: Jim Cromie @ 2026-04-23 20:53 UTC (permalink / raw)
To: Arnd Bergmann, Jason Baron, Luis Chamberlain, Petr Pavlu,
Daniel Gomez, Sami Tolvanen, Aaron Tomlin, Andrew Morton,
Jonathan Corbet, Shuah Khan, Shuah Khan, Greg Kroah-Hartman,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
Tvrtko Ursulin, Alex Deucher, Christian König, David Airlie,
Gerd Hoffmann, Dmitry Osipenko, Gurchetan Singh, Chia-I Wu,
Matthew Brost, Thomas Hellström, Lyude Paul,
Danilo Krummrich, Patrik Jakobsson, Zack Rusin,
Broadcom internal kernel review list, Louis Chauvet,
Haneen Mohammed, Melissa Wen, Sean Paul, Jocelyn Falempe,
Ruben Wauters, Dave Stevenson, Maíra Canal,
Raspberry Pi Kernel Maintenance, Rob Clark, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, Xinliang Liu,
Tian Tao, Xinwei Kong, Sumit Semwal, Yongqin Liu, John Stultz,
Philipp Zabel, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, Chun-Kuang Hu, Matthias Brugger,
AngeloGioacchino Del Regno, Sandy Huang, Heiko Stübner,
Andy Yan, Alain Volmat, Raphael Gallais-Pou, Yannick Fertre,
Raphael Gallais-Pou, Philippe Cornu, Maxime Coquelin,
Alexandre Torgue, Oded Gabbay, Maciej Falkowski, Karol Wachowski,
Rob Herring (Arm), Tomeu Vizoso, Liviu Dudau, Andrzej Hajda,
Neil Armstrong, Robert Foss, Laurent Pinchart, Jonas Karlman,
Jernej Skrabec, Liu Ying, Laurentiu Palcu, Lucas Stach,
Paul Kocialkowski, Jianmin Lv, Qianhai Wu, Huacai Chen,
Mingcong Bai, Xi Ruoyao, Icenowy Zheng, Laurent Pinchart,
Tomi Valkeinen, Kieran Bingham, Geert Uytterhoeven, Magnus Damm,
Javier Martinez Canillas, Huang Rui, Matthew Auld, Jani Nikula,
Luca Coelho, Russell King, Christian Gmeiner
Cc: linux-arch, linux-kernel, linux-modules, linux-doc,
linux-kselftest, dri-devel, intel-gfx, amd-gfx, virtualization,
intel-xe, nouveau, spice-devel, linux-arm-msm, freedreno, imx,
linux-arm-kernel, linux-mediatek, linux-rockchip, linux-stm32,
linux-renesas-soc, etnaviv, Jim Cromie
In-Reply-To: <20260423-submit-dyndbg-classmap-foundation-v14-0-2b809a8019d0@gmail.com>
struct ddebug_class_param keeps a ref to the state-storage of the
param; make both class-types use the same unsigned long storage type.
ISTM this is simpler and safer; it avoids an irrelevant difference,
and if 2 users somehow get class-type mixed up (or refer to the wrong
union member), at least they will both see the same value.
Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
include/linux/dynamic_debug.h | 2 +-
lib/dynamic_debug.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index a10adac8e8f0..441305277914 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -104,7 +104,7 @@ struct _ddebug_info {
struct ddebug_class_param {
union {
unsigned long *bits;
- unsigned int *lvl;
+ unsigned long *lvl;
};
char flags[8];
const struct ddebug_class_map *map;
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index a9caf84ddb22..ffa1cf7c2c72 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -811,7 +811,7 @@ int param_get_dyndbg_classes(char *buffer, const struct kernel_param *kp)
case DD_CLASS_TYPE_LEVEL_NAMES:
case DD_CLASS_TYPE_LEVEL_NUM:
- return scnprintf(buffer, PAGE_SIZE, "%d\n", *dcp->lvl);
+ return scnprintf(buffer, PAGE_SIZE, "%ld\n", *dcp->lvl);
default:
return -1;
}
--
2.53.0
^ permalink raw reply related
* [PATCH v14 10/92] dyndbg: reword "class unknown," to "class:_UNKNOWN_"
From: Jim Cromie @ 2026-04-23 20:53 UTC (permalink / raw)
To: Arnd Bergmann, Jason Baron, Luis Chamberlain, Petr Pavlu,
Daniel Gomez, Sami Tolvanen, Aaron Tomlin, Andrew Morton,
Jonathan Corbet, Shuah Khan, Shuah Khan, Greg Kroah-Hartman,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
Tvrtko Ursulin, Alex Deucher, Christian König, David Airlie,
Gerd Hoffmann, Dmitry Osipenko, Gurchetan Singh, Chia-I Wu,
Matthew Brost, Thomas Hellström, Lyude Paul,
Danilo Krummrich, Patrik Jakobsson, Zack Rusin,
Broadcom internal kernel review list, Louis Chauvet,
Haneen Mohammed, Melissa Wen, Sean Paul, Jocelyn Falempe,
Ruben Wauters, Dave Stevenson, Maíra Canal,
Raspberry Pi Kernel Maintenance, Rob Clark, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, Xinliang Liu,
Tian Tao, Xinwei Kong, Sumit Semwal, Yongqin Liu, John Stultz,
Philipp Zabel, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, Chun-Kuang Hu, Matthias Brugger,
AngeloGioacchino Del Regno, Sandy Huang, Heiko Stübner,
Andy Yan, Alain Volmat, Raphael Gallais-Pou, Yannick Fertre,
Raphael Gallais-Pou, Philippe Cornu, Maxime Coquelin,
Alexandre Torgue, Oded Gabbay, Maciej Falkowski, Karol Wachowski,
Rob Herring (Arm), Tomeu Vizoso, Liviu Dudau, Andrzej Hajda,
Neil Armstrong, Robert Foss, Laurent Pinchart, Jonas Karlman,
Jernej Skrabec, Liu Ying, Laurentiu Palcu, Lucas Stach,
Paul Kocialkowski, Jianmin Lv, Qianhai Wu, Huacai Chen,
Mingcong Bai, Xi Ruoyao, Icenowy Zheng, Laurent Pinchart,
Tomi Valkeinen, Kieran Bingham, Geert Uytterhoeven, Magnus Damm,
Javier Martinez Canillas, Huang Rui, Matthew Auld, Jani Nikula,
Luca Coelho, Russell King, Christian Gmeiner
Cc: linux-arch, linux-kernel, linux-modules, linux-doc,
linux-kselftest, dri-devel, intel-gfx, amd-gfx, virtualization,
intel-xe, nouveau, spice-devel, linux-arm-msm, freedreno, imx,
linux-arm-kernel, linux-mediatek, linux-rockchip, linux-stm32,
linux-renesas-soc, etnaviv, Jim Cromie
In-Reply-To: <20260423-submit-dyndbg-classmap-foundation-v14-0-2b809a8019d0@gmail.com>
When a dyndbg classname is unknown to a kernel module (as before
previous patch), the callsite is un-addressable via >control queries.
The control-file displays this condition as "class unknown,"
currently. That spelling is sub-optimal/too-generic, so change it to
"class:_UNKNOWN_" to loudly announce the erroneous situation, and to
make it uniquely greppable.
Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
lib/dynamic_debug.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index 6b1e983cfedc..a9caf84ddb22 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -1166,7 +1166,7 @@ static int ddebug_proc_show(struct seq_file *m, void *p)
if (class)
seq_printf(m, " class:%s", class);
else
- seq_printf(m, " class unknown, _id:%d", dp->class_id);
+ seq_printf(m, " class:_UNKNOWN_ _id:%d", dp->class_id);
}
seq_putc(m, '\n');
--
2.53.0
^ permalink raw reply related
* [PATCH v14 09/92] test-dyndbg: fixup CLASSMAP usage error
From: Jim Cromie @ 2026-04-23 20:53 UTC (permalink / raw)
To: Arnd Bergmann, Jason Baron, Luis Chamberlain, Petr Pavlu,
Daniel Gomez, Sami Tolvanen, Aaron Tomlin, Andrew Morton,
Jonathan Corbet, Shuah Khan, Shuah Khan, Greg Kroah-Hartman,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
Tvrtko Ursulin, Alex Deucher, Christian König, David Airlie,
Gerd Hoffmann, Dmitry Osipenko, Gurchetan Singh, Chia-I Wu,
Matthew Brost, Thomas Hellström, Lyude Paul,
Danilo Krummrich, Patrik Jakobsson, Zack Rusin,
Broadcom internal kernel review list, Louis Chauvet,
Haneen Mohammed, Melissa Wen, Sean Paul, Jocelyn Falempe,
Ruben Wauters, Dave Stevenson, Maíra Canal,
Raspberry Pi Kernel Maintenance, Rob Clark, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, Xinliang Liu,
Tian Tao, Xinwei Kong, Sumit Semwal, Yongqin Liu, John Stultz,
Philipp Zabel, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, Chun-Kuang Hu, Matthias Brugger,
AngeloGioacchino Del Regno, Sandy Huang, Heiko Stübner,
Andy Yan, Alain Volmat, Raphael Gallais-Pou, Yannick Fertre,
Raphael Gallais-Pou, Philippe Cornu, Maxime Coquelin,
Alexandre Torgue, Oded Gabbay, Maciej Falkowski, Karol Wachowski,
Rob Herring (Arm), Tomeu Vizoso, Liviu Dudau, Andrzej Hajda,
Neil Armstrong, Robert Foss, Laurent Pinchart, Jonas Karlman,
Jernej Skrabec, Liu Ying, Laurentiu Palcu, Lucas Stach,
Paul Kocialkowski, Jianmin Lv, Qianhai Wu, Huacai Chen,
Mingcong Bai, Xi Ruoyao, Icenowy Zheng, Laurent Pinchart,
Tomi Valkeinen, Kieran Bingham, Geert Uytterhoeven, Magnus Damm,
Javier Martinez Canillas, Huang Rui, Matthew Auld, Jani Nikula,
Luca Coelho, Russell King, Christian Gmeiner
Cc: linux-arch, linux-kernel, linux-modules, linux-doc,
linux-kselftest, dri-devel, intel-gfx, amd-gfx, virtualization,
intel-xe, nouveau, spice-devel, linux-arm-msm, freedreno, imx,
linux-arm-kernel, linux-mediatek, linux-rockchip, linux-stm32,
linux-renesas-soc, etnaviv, Jim Cromie
In-Reply-To: <20260423-submit-dyndbg-classmap-foundation-v14-0-2b809a8019d0@gmail.com>
commit 6ea3bf466ac6 ("dyndbg: test DECLARE_DYNDBG_CLASSMAP, sysfs nodes")
A closer look at test_dynamic_debug.ko logging output reveals a macro
usage error:
lib/test_dynamic_debug.c:105 [test_dynamic_debug]do_cats =p "LOW msg\n" class:MID
lib/test_dynamic_debug.c:106 [test_dynamic_debug]do_cats =p "MID msg\n" class:HI
lib/test_dynamic_debug.c:107 [test_dynamic_debug]do_cats =_ "HI msg\n" class unknown, _id:13
107 says: HI is unknown, and 105,106 have a LOW/MID and MID/HI skew.
DECLARE_DYNDBG_CLASSMAP() _base arg must equal the enum's 1st value,
in this case it was _base + 1. This leaves HI class un-selectable.
NB: the macro could better validate its arguments.
Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Tested-by: Louis Chauvet <louis.chauvet@bootlin.com>
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
lib/test_dynamic_debug.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/test_dynamic_debug.c b/lib/test_dynamic_debug.c
index 77c2a669b6af..396144cf351b 100644
--- a/lib/test_dynamic_debug.c
+++ b/lib/test_dynamic_debug.c
@@ -75,7 +75,7 @@ DD_SYS_WRAP(disjoint_bits, p);
DD_SYS_WRAP(disjoint_bits, T);
/* symbolic input, independent bits */
-enum cat_disjoint_names { LOW = 11, MID, HI };
+enum cat_disjoint_names { LOW = 10, MID, HI };
DECLARE_DYNDBG_CLASSMAP(map_disjoint_names, DD_CLASS_TYPE_DISJOINT_NAMES, 10,
"LOW", "MID", "HI");
DD_SYS_WRAP(disjoint_names, p);
--
2.53.0
^ permalink raw reply related
* [PATCH v14 08/92] docs/dyndbg: explain flags parse 1st
From: Jim Cromie @ 2026-04-23 20:53 UTC (permalink / raw)
To: Arnd Bergmann, Jason Baron, Luis Chamberlain, Petr Pavlu,
Daniel Gomez, Sami Tolvanen, Aaron Tomlin, Andrew Morton,
Jonathan Corbet, Shuah Khan, Shuah Khan, Greg Kroah-Hartman,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
Tvrtko Ursulin, Alex Deucher, Christian König, David Airlie,
Gerd Hoffmann, Dmitry Osipenko, Gurchetan Singh, Chia-I Wu,
Matthew Brost, Thomas Hellström, Lyude Paul,
Danilo Krummrich, Patrik Jakobsson, Zack Rusin,
Broadcom internal kernel review list, Louis Chauvet,
Haneen Mohammed, Melissa Wen, Sean Paul, Jocelyn Falempe,
Ruben Wauters, Dave Stevenson, Maíra Canal,
Raspberry Pi Kernel Maintenance, Rob Clark, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, Xinliang Liu,
Tian Tao, Xinwei Kong, Sumit Semwal, Yongqin Liu, John Stultz,
Philipp Zabel, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, Chun-Kuang Hu, Matthias Brugger,
AngeloGioacchino Del Regno, Sandy Huang, Heiko Stübner,
Andy Yan, Alain Volmat, Raphael Gallais-Pou, Yannick Fertre,
Raphael Gallais-Pou, Philippe Cornu, Maxime Coquelin,
Alexandre Torgue, Oded Gabbay, Maciej Falkowski, Karol Wachowski,
Rob Herring (Arm), Tomeu Vizoso, Liviu Dudau, Andrzej Hajda,
Neil Armstrong, Robert Foss, Laurent Pinchart, Jonas Karlman,
Jernej Skrabec, Liu Ying, Laurentiu Palcu, Lucas Stach,
Paul Kocialkowski, Jianmin Lv, Qianhai Wu, Huacai Chen,
Mingcong Bai, Xi Ruoyao, Icenowy Zheng, Laurent Pinchart,
Tomi Valkeinen, Kieran Bingham, Geert Uytterhoeven, Magnus Damm,
Javier Martinez Canillas, Huang Rui, Matthew Auld, Jani Nikula,
Luca Coelho, Russell King, Christian Gmeiner
Cc: linux-arch, linux-kernel, linux-modules, linux-doc,
linux-kselftest, dri-devel, intel-gfx, amd-gfx, virtualization,
intel-xe, nouveau, spice-devel, linux-arm-msm, freedreno, imx,
linux-arm-kernel, linux-mediatek, linux-rockchip, linux-stm32,
linux-renesas-soc, etnaviv, Jim Cromie
In-Reply-To: <20260423-submit-dyndbg-classmap-foundation-v14-0-2b809a8019d0@gmail.com>
When writing queries to >control, flags are parsed 1st, since they are
the only required field, and they require specific compositions. So
if the flags draw an error (on those specifics), then keyword errors
aren't reported. This can be mildly confusing/annoying, so explain it
instead.
cc: linux-doc@vger.kernel.org
Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
Documentation/admin-guide/dynamic-debug-howto.rst | 17 +++++++++++++----
1 file changed, 13 insertions(+), 4 deletions(-)
diff --git a/Documentation/admin-guide/dynamic-debug-howto.rst b/Documentation/admin-guide/dynamic-debug-howto.rst
index 4b14d9fd0300..9c2f096ed1d8 100644
--- a/Documentation/admin-guide/dynamic-debug-howto.rst
+++ b/Documentation/admin-guide/dynamic-debug-howto.rst
@@ -109,10 +109,19 @@ The match-spec's select *prdbgs* from the catalog, upon which to apply
the flags-spec, all constraints are ANDed together. An absent keyword
is the same as keyword "*".
-
-A match specification is a keyword, which selects the attribute of
-the callsite to be compared, and a value to compare against. Possible
-keywords are:::
+Note that since the match-spec can be empty, the flags are checked 1st,
+then the pairs of keyword and value. Flag errs will hide keyword errs::
+
+ bash-5.2# ddcmd mod bar +foo
+ dyndbg: read 13 bytes from userspace
+ dyndbg: query 0: "mod bar +foo" mod:*
+ dyndbg: unknown flag 'o'
+ dyndbg: flags parse failed
+ dyndbg: processed 1 queries, with 0 matches, 1 errs
+
+So a match-spec is a keyword, which selects the attribute of the
+callsite to be compared, and a value to compare against. Possible
+keywords are::
match-spec ::= 'func' string |
'file' string |
--
2.53.0
^ permalink raw reply related
* [PATCH v14 07/92] docs/dyndbg: update examples \012 to \n
From: Jim Cromie @ 2026-04-23 20:53 UTC (permalink / raw)
To: Arnd Bergmann, Jason Baron, Luis Chamberlain, Petr Pavlu,
Daniel Gomez, Sami Tolvanen, Aaron Tomlin, Andrew Morton,
Jonathan Corbet, Shuah Khan, Shuah Khan, Greg Kroah-Hartman,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
Tvrtko Ursulin, Alex Deucher, Christian König, David Airlie,
Gerd Hoffmann, Dmitry Osipenko, Gurchetan Singh, Chia-I Wu,
Matthew Brost, Thomas Hellström, Lyude Paul,
Danilo Krummrich, Patrik Jakobsson, Zack Rusin,
Broadcom internal kernel review list, Louis Chauvet,
Haneen Mohammed, Melissa Wen, Sean Paul, Jocelyn Falempe,
Ruben Wauters, Dave Stevenson, Maíra Canal,
Raspberry Pi Kernel Maintenance, Rob Clark, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, Xinliang Liu,
Tian Tao, Xinwei Kong, Sumit Semwal, Yongqin Liu, John Stultz,
Philipp Zabel, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, Chun-Kuang Hu, Matthias Brugger,
AngeloGioacchino Del Regno, Sandy Huang, Heiko Stübner,
Andy Yan, Alain Volmat, Raphael Gallais-Pou, Yannick Fertre,
Raphael Gallais-Pou, Philippe Cornu, Maxime Coquelin,
Alexandre Torgue, Oded Gabbay, Maciej Falkowski, Karol Wachowski,
Rob Herring (Arm), Tomeu Vizoso, Liviu Dudau, Andrzej Hajda,
Neil Armstrong, Robert Foss, Laurent Pinchart, Jonas Karlman,
Jernej Skrabec, Liu Ying, Laurentiu Palcu, Lucas Stach,
Paul Kocialkowski, Jianmin Lv, Qianhai Wu, Huacai Chen,
Mingcong Bai, Xi Ruoyao, Icenowy Zheng, Laurent Pinchart,
Tomi Valkeinen, Kieran Bingham, Geert Uytterhoeven, Magnus Damm,
Javier Martinez Canillas, Huang Rui, Matthew Auld, Jani Nikula,
Luca Coelho, Russell King, Christian Gmeiner
Cc: linux-arch, linux-kernel, linux-modules, linux-doc,
linux-kselftest, dri-devel, intel-gfx, amd-gfx, virtualization,
intel-xe, nouveau, spice-devel, linux-arm-msm, freedreno, imx,
linux-arm-kernel, linux-mediatek, linux-rockchip, linux-stm32,
linux-renesas-soc, etnaviv, Jim Cromie
In-Reply-To: <20260423-submit-dyndbg-classmap-foundation-v14-0-2b809a8019d0@gmail.com>
commit 47ea6f99d06e ("dyndbg: use ESCAPE_SPACE for cat control")
changed the control-file to display format strings with "\n" rather
than "\012". Update the docs to match the new reality.
Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Tested-by: Louis Chauvet <louis.chauvet@bootlin.com>
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
Documentation/admin-guide/dynamic-debug-howto.rst | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/Documentation/admin-guide/dynamic-debug-howto.rst b/Documentation/admin-guide/dynamic-debug-howto.rst
index 095a63892257..4b14d9fd0300 100644
--- a/Documentation/admin-guide/dynamic-debug-howto.rst
+++ b/Documentation/admin-guide/dynamic-debug-howto.rst
@@ -38,12 +38,12 @@ You can view the currently configured behaviour in the *prdbg* catalog::
:#> head -n7 /proc/dynamic_debug/control
# filename:lineno [module]function flags format
- init/main.c:1179 [main]initcall_blacklist =_ "blacklisting initcall %s\012
- init/main.c:1218 [main]initcall_blacklisted =_ "initcall %s blacklisted\012"
- init/main.c:1424 [main]run_init_process =_ " with arguments:\012"
- init/main.c:1426 [main]run_init_process =_ " %s\012"
- init/main.c:1427 [main]run_init_process =_ " with environment:\012"
- init/main.c:1429 [main]run_init_process =_ " %s\012"
+ init/main.c:1179 [main]initcall_blacklist =_ "blacklisting initcall %s\n"
+ init/main.c:1218 [main]initcall_blacklisted =_ "initcall %s blacklisted\n"
+ init/main.c:1424 [main]run_init_process =_ " with arguments:\n"
+ init/main.c:1426 [main]run_init_process =_ " %s\n"
+ init/main.c:1427 [main]run_init_process =_ " with environment:\n"
+ init/main.c:1429 [main]run_init_process =_ " %s\n"
The 3rd space-delimited column shows the current flags, preceded by
a ``=`` for easy use with grep/cut. ``=p`` shows enabled callsites.
@@ -59,10 +59,10 @@ query/commands to the control file. Example::
:#> ddcmd '-p; module main func run* +p'
:#> grep =p /proc/dynamic_debug/control
- init/main.c:1424 [main]run_init_process =p " with arguments:\012"
- init/main.c:1426 [main]run_init_process =p " %s\012"
- init/main.c:1427 [main]run_init_process =p " with environment:\012"
- init/main.c:1429 [main]run_init_process =p " %s\012"
+ init/main.c:1424 [main]run_init_process =p " with arguments:\n"
+ init/main.c:1426 [main]run_init_process =p " %s\n"
+ init/main.c:1427 [main]run_init_process =p " with environment:\n"
+ init/main.c:1429 [main]run_init_process =p " %s\n"
Error messages go to console/syslog::
--
2.53.0
^ permalink raw reply related
* [PATCH v14 06/92] dyndbg: add stub macro for DECLARE_DYNDBG_CLASSMAP
From: Jim Cromie @ 2026-04-23 20:53 UTC (permalink / raw)
To: Arnd Bergmann, Jason Baron, Luis Chamberlain, Petr Pavlu,
Daniel Gomez, Sami Tolvanen, Aaron Tomlin, Andrew Morton,
Jonathan Corbet, Shuah Khan, Shuah Khan, Greg Kroah-Hartman,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
Tvrtko Ursulin, Alex Deucher, Christian König, David Airlie,
Gerd Hoffmann, Dmitry Osipenko, Gurchetan Singh, Chia-I Wu,
Matthew Brost, Thomas Hellström, Lyude Paul,
Danilo Krummrich, Patrik Jakobsson, Zack Rusin,
Broadcom internal kernel review list, Louis Chauvet,
Haneen Mohammed, Melissa Wen, Sean Paul, Jocelyn Falempe,
Ruben Wauters, Dave Stevenson, Maíra Canal,
Raspberry Pi Kernel Maintenance, Rob Clark, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, Xinliang Liu,
Tian Tao, Xinwei Kong, Sumit Semwal, Yongqin Liu, John Stultz,
Philipp Zabel, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, Chun-Kuang Hu, Matthias Brugger,
AngeloGioacchino Del Regno, Sandy Huang, Heiko Stübner,
Andy Yan, Alain Volmat, Raphael Gallais-Pou, Yannick Fertre,
Raphael Gallais-Pou, Philippe Cornu, Maxime Coquelin,
Alexandre Torgue, Oded Gabbay, Maciej Falkowski, Karol Wachowski,
Rob Herring (Arm), Tomeu Vizoso, Liviu Dudau, Andrzej Hajda,
Neil Armstrong, Robert Foss, Laurent Pinchart, Jonas Karlman,
Jernej Skrabec, Liu Ying, Laurentiu Palcu, Lucas Stach,
Paul Kocialkowski, Jianmin Lv, Qianhai Wu, Huacai Chen,
Mingcong Bai, Xi Ruoyao, Icenowy Zheng, Laurent Pinchart,
Tomi Valkeinen, Kieran Bingham, Geert Uytterhoeven, Magnus Damm,
Javier Martinez Canillas, Huang Rui, Matthew Auld, Jani Nikula,
Luca Coelho, Russell King, Christian Gmeiner
Cc: linux-arch, linux-kernel, linux-modules, linux-doc,
linux-kselftest, dri-devel, intel-gfx, amd-gfx, virtualization,
intel-xe, nouveau, spice-devel, linux-arm-msm, freedreno, imx,
linux-arm-kernel, linux-mediatek, linux-rockchip, linux-stm32,
linux-renesas-soc, etnaviv, Jim Cromie
In-Reply-To: <20260423-submit-dyndbg-classmap-foundation-v14-0-2b809a8019d0@gmail.com>
Add the stub macro for !DYNAMIC_DEBUG builds, after moving the
original macro-defn down under the big ifdef. Do it now so future
changes have a cleaner starting point.
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
include/linux/dynamic_debug.h | 43 ++++++++++++++++++++++---------------------
1 file changed, 22 insertions(+), 21 deletions(-)
diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index 05743900a116..a10adac8e8f0 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -93,27 +93,6 @@ struct ddebug_class_map {
enum class_map_type map_type;
};
-/**
- * DECLARE_DYNDBG_CLASSMAP - declare classnames known by a module
- * @_var: a struct ddebug_class_map, passed to module_param_cb
- * @_type: enum class_map_type, chooses bits/verbose, numeric/symbolic
- * @_base: offset of 1st class-name. splits .class_id space
- * @classes: class-names used to control class'd prdbgs
- */
-#define DECLARE_DYNDBG_CLASSMAP(_var, _maptype, _base, ...) \
- static const char *_var##_classnames[] = { __VA_ARGS__ }; \
- static struct ddebug_class_map __aligned(8) __used \
- __section("__dyndbg_classes") _var = { \
- .mod = THIS_MODULE, \
- .mod_name = KBUILD_MODNAME, \
- .base = _base, \
- .map_type = _maptype, \
- .length = NUM_TYPE_ARGS(char*, __VA_ARGS__), \
- .class_names = _var##_classnames, \
- }
-#define NUM_TYPE_ARGS(eltype, ...) \
- (sizeof((eltype[]){__VA_ARGS__}) / sizeof(eltype))
-
/* encapsulate linker provided built-in (or module) dyndbg data */
struct _ddebug_info {
struct _ddebug *descs;
@@ -138,6 +117,27 @@ struct ddebug_class_param {
#if defined(CONFIG_DYNAMIC_DEBUG) || \
(defined(CONFIG_DYNAMIC_DEBUG_CORE) && defined(DYNAMIC_DEBUG_MODULE))
+/**
+ * DECLARE_DYNDBG_CLASSMAP - declare classnames known by a module
+ * @_var: a struct ddebug_class_map, passed to module_param_cb
+ * @_type: enum class_map_type, chooses bits/verbose, numeric/symbolic
+ * @_base: offset of 1st class-name. splits .class_id space
+ * @classes: class-names used to control class'd prdbgs
+ */
+#define DECLARE_DYNDBG_CLASSMAP(_var, _maptype, _base, ...) \
+ static const char *_var##_classnames[] = { __VA_ARGS__ }; \
+ static struct ddebug_class_map __aligned(8) __used \
+ __section("__dyndbg_classes") _var = { \
+ .mod = THIS_MODULE, \
+ .mod_name = KBUILD_MODNAME, \
+ .base = _base, \
+ .map_type = _maptype, \
+ .length = NUM_TYPE_ARGS(char*, __VA_ARGS__), \
+ .class_names = _var##_classnames, \
+ }
+#define NUM_TYPE_ARGS(eltype, ...) \
+ (sizeof((eltype[]) {__VA_ARGS__}) / sizeof(eltype))
+
extern __printf(2, 3)
void __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...);
@@ -314,6 +314,7 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
#define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt)
#define DYNAMIC_DEBUG_BRANCH(descriptor) false
+#define DECLARE_DYNDBG_CLASSMAP(...)
#define dynamic_pr_debug(fmt, ...) \
no_printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
--
2.53.0
^ permalink raw reply related
* [PATCH v14 05/92] dyndbg: factor ddebug_match_desc out from ddebug_change
From: Jim Cromie @ 2026-04-23 20:53 UTC (permalink / raw)
To: Arnd Bergmann, Jason Baron, Luis Chamberlain, Petr Pavlu,
Daniel Gomez, Sami Tolvanen, Aaron Tomlin, Andrew Morton,
Jonathan Corbet, Shuah Khan, Shuah Khan, Greg Kroah-Hartman,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
Tvrtko Ursulin, Alex Deucher, Christian König, David Airlie,
Gerd Hoffmann, Dmitry Osipenko, Gurchetan Singh, Chia-I Wu,
Matthew Brost, Thomas Hellström, Lyude Paul,
Danilo Krummrich, Patrik Jakobsson, Zack Rusin,
Broadcom internal kernel review list, Louis Chauvet,
Haneen Mohammed, Melissa Wen, Sean Paul, Jocelyn Falempe,
Ruben Wauters, Dave Stevenson, Maíra Canal,
Raspberry Pi Kernel Maintenance, Rob Clark, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, Xinliang Liu,
Tian Tao, Xinwei Kong, Sumit Semwal, Yongqin Liu, John Stultz,
Philipp Zabel, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, Chun-Kuang Hu, Matthias Brugger,
AngeloGioacchino Del Regno, Sandy Huang, Heiko Stübner,
Andy Yan, Alain Volmat, Raphael Gallais-Pou, Yannick Fertre,
Raphael Gallais-Pou, Philippe Cornu, Maxime Coquelin,
Alexandre Torgue, Oded Gabbay, Maciej Falkowski, Karol Wachowski,
Rob Herring (Arm), Tomeu Vizoso, Liviu Dudau, Andrzej Hajda,
Neil Armstrong, Robert Foss, Laurent Pinchart, Jonas Karlman,
Jernej Skrabec, Liu Ying, Laurentiu Palcu, Lucas Stach,
Paul Kocialkowski, Jianmin Lv, Qianhai Wu, Huacai Chen,
Mingcong Bai, Xi Ruoyao, Icenowy Zheng, Laurent Pinchart,
Tomi Valkeinen, Kieran Bingham, Geert Uytterhoeven, Magnus Damm,
Javier Martinez Canillas, Huang Rui, Matthew Auld, Jani Nikula,
Luca Coelho, Russell King, Christian Gmeiner
Cc: linux-arch, linux-kernel, linux-modules, linux-doc,
linux-kselftest, dri-devel, intel-gfx, amd-gfx, virtualization,
intel-xe, nouveau, spice-devel, linux-arm-msm, freedreno, imx,
linux-arm-kernel, linux-mediatek, linux-rockchip, linux-stm32,
linux-renesas-soc, etnaviv, Jim Cromie
In-Reply-To: <20260423-submit-dyndbg-classmap-foundation-v14-0-2b809a8019d0@gmail.com>
ddebug_change() is a big (~100 lines) function with a nested for loop.
The outer loop walks the per-module ddebug_tables list, and does
module stuff: it filters on a query's "module FOO*" and "class BAR",
failures here skip the entire inner loop.
The inner loop (60 lines) scans a module's descriptors. It starts
with a long block of filters on function, line, format, and the
validated "BAR" class (or the legacy/_DPRINTK_CLASS_DFLT).
These filters "continue" past pr_debugs that don't match the query
criteria, before it falls through the code below that counts matches,
then adjusts the flags and static-keys. This is unnecessarily hard to
think about.
So move the per-descriptor filter-block into a boolean function:
ddebug_match_desc(desc), and change each "continue" to "return false".
This puts a clear interface in place, so any future changes are either
inside, outside, or across this interface.
also fix checkpatch complaints about spaces and braces.
Reviewed-by: Louis Chauvet <louis.chauvet@bootlin.com>
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
lib/dynamic_debug.c | 83 ++++++++++++++++++++++++++++++-----------------------
1 file changed, 47 insertions(+), 36 deletions(-)
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index 18a71a9108d3..6b1e983cfedc 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -172,6 +172,52 @@ static struct ddebug_class_map *ddebug_find_valid_class(struct ddebug_table cons
* callsites, normally the same as number of changes. If verbose,
* logs the changes. Takes ddebug_lock.
*/
+static bool ddebug_match_desc(const struct ddebug_query *query,
+ struct _ddebug *dp,
+ int valid_class)
+{
+ /* match site against query-class */
+ if (dp->class_id != valid_class)
+ return false;
+
+ /* match against the source filename */
+ if (query->filename &&
+ !match_wildcard(query->filename, dp->filename) &&
+ !match_wildcard(query->filename,
+ kbasename(dp->filename)) &&
+ !match_wildcard(query->filename,
+ trim_prefix(dp->filename)))
+ return false;
+
+ /* match against the function */
+ if (query->function &&
+ !match_wildcard(query->function, dp->function))
+ return false;
+
+ /* match against the format */
+ if (query->format) {
+ if (*query->format == '^') {
+ char *p;
+ /* anchored search. match must be at beginning */
+ p = strstr(dp->format, query->format + 1);
+ if (p != dp->format)
+ return false;
+ } else if (!strstr(dp->format, query->format)) {
+ return false;
+ }
+ }
+
+ /* match against the line number range */
+ if (query->first_lineno &&
+ dp->lineno < query->first_lineno)
+ return false;
+ if (query->last_lineno &&
+ dp->lineno > query->last_lineno)
+ return false;
+
+ return true;
+}
+
static int ddebug_change(const struct ddebug_query *query,
struct flag_settings *modifiers)
{
@@ -204,42 +250,7 @@ static int ddebug_change(const struct ddebug_query *query,
for (i = 0; i < dt->num_ddebugs; i++) {
struct _ddebug *dp = &dt->ddebugs[i];
- /* match site against query-class */
- if (dp->class_id != valid_class)
- continue;
-
- /* match against the source filename */
- if (query->filename &&
- !match_wildcard(query->filename, dp->filename) &&
- !match_wildcard(query->filename,
- kbasename(dp->filename)) &&
- !match_wildcard(query->filename,
- trim_prefix(dp->filename)))
- continue;
-
- /* match against the function */
- if (query->function &&
- !match_wildcard(query->function, dp->function))
- continue;
-
- /* match against the format */
- if (query->format) {
- if (*query->format == '^') {
- char *p;
- /* anchored search. match must be at beginning */
- p = strstr(dp->format, query->format+1);
- if (p != dp->format)
- continue;
- } else if (!strstr(dp->format, query->format))
- continue;
- }
-
- /* match against the line number range */
- if (query->first_lineno &&
- dp->lineno < query->first_lineno)
- continue;
- if (query->last_lineno &&
- dp->lineno > query->last_lineno)
+ if (!ddebug_match_desc(query, dp, valid_class))
continue;
nfound++;
--
2.53.0
^ permalink raw reply related
* [PATCH v14 04/92] vmlinux.lds.h: drop unused HEADERED_SECTION* macros
From: Jim Cromie @ 2026-04-23 20:53 UTC (permalink / raw)
To: Arnd Bergmann, Jason Baron, Luis Chamberlain, Petr Pavlu,
Daniel Gomez, Sami Tolvanen, Aaron Tomlin, Andrew Morton,
Jonathan Corbet, Shuah Khan, Shuah Khan, Greg Kroah-Hartman,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
Tvrtko Ursulin, Alex Deucher, Christian König, David Airlie,
Gerd Hoffmann, Dmitry Osipenko, Gurchetan Singh, Chia-I Wu,
Matthew Brost, Thomas Hellström, Lyude Paul,
Danilo Krummrich, Patrik Jakobsson, Zack Rusin,
Broadcom internal kernel review list, Louis Chauvet,
Haneen Mohammed, Melissa Wen, Sean Paul, Jocelyn Falempe,
Ruben Wauters, Dave Stevenson, Maíra Canal,
Raspberry Pi Kernel Maintenance, Rob Clark, Dmitry Baryshkov,
Abhinav Kumar, Jessica Zhang, Marijn Suijten, Xinliang Liu,
Tian Tao, Xinwei Kong, Sumit Semwal, Yongqin Liu, John Stultz,
Philipp Zabel, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, Chun-Kuang Hu, Matthias Brugger,
AngeloGioacchino Del Regno, Sandy Huang, Heiko Stübner,
Andy Yan, Alain Volmat, Raphael Gallais-Pou, Yannick Fertre,
Raphael Gallais-Pou, Philippe Cornu, Maxime Coquelin,
Alexandre Torgue, Oded Gabbay, Maciej Falkowski, Karol Wachowski,
Rob Herring (Arm), Tomeu Vizoso, Liviu Dudau, Andrzej Hajda,
Neil Armstrong, Robert Foss, Laurent Pinchart, Jonas Karlman,
Jernej Skrabec, Liu Ying, Laurentiu Palcu, Lucas Stach,
Paul Kocialkowski, Jianmin Lv, Qianhai Wu, Huacai Chen,
Mingcong Bai, Xi Ruoyao, Icenowy Zheng, Laurent Pinchart,
Tomi Valkeinen, Kieran Bingham, Geert Uytterhoeven, Magnus Damm,
Javier Martinez Canillas, Huang Rui, Matthew Auld, Jani Nikula,
Luca Coelho, Russell King, Christian Gmeiner
Cc: linux-arch, linux-kernel, linux-modules, linux-doc,
linux-kselftest, dri-devel, intel-gfx, amd-gfx, virtualization,
intel-xe, nouveau, spice-devel, linux-arm-msm, freedreno, imx,
linux-arm-kernel, linux-mediatek, linux-rockchip, linux-stm32,
linux-renesas-soc, etnaviv, Jim Cromie
In-Reply-To: <20260423-submit-dyndbg-classmap-foundation-v14-0-2b809a8019d0@gmail.com>
These macros are unused, no point in carrying them any more.
NB: these macros were just moved to bounded_sections.lds.h, from
vmlinux.lds.h, which is the known entity, and therefore more
meaningful in the 1-line summary, so thats what I used as the topic.
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
include/asm-generic/bounded_sections.lds.h | 15 ---------------
1 file changed, 15 deletions(-)
diff --git a/include/asm-generic/bounded_sections.lds.h b/include/asm-generic/bounded_sections.lds.h
index 43e79603d4af..f5876e68cbe7 100644
--- a/include/asm-generic/bounded_sections.lds.h
+++ b/include/asm-generic/bounded_sections.lds.h
@@ -20,19 +20,4 @@
#define BOUNDED_SECTION(_sec) BOUNDED_SECTION_BY(_sec, _sec)
-#define HEADERED_SECTION_PRE_LABEL(_sec_, _label_, _BEGIN_, _END_, _HDR_) \
- _HDR_##_label_ = .; \
- KEEP(*(.gnu.linkonce.##_sec_)) \
- BOUNDED_SECTION_PRE_LABEL(_sec_, _label_, _BEGIN_, _END_)
-
-#define HEADERED_SECTION_POST_LABEL(_sec_, _label_, _BEGIN_, _END_, _HDR_) \
- _label_##_HDR_ = .; \
- KEEP(*(.gnu.linkonce.##_sec_)) \
- BOUNDED_SECTION_POST_LABEL(_sec_, _label_, _BEGIN_, _END_)
-
-#define HEADERED_SECTION_BY(_sec_, _label_) \
- HEADERED_SECTION_PRE_LABEL(_sec_, _label_, __start, __stop)
-
-#define HEADERED_SECTION(_sec) HEADERED_SECTION_BY(_sec, _sec)
-
#endif /* _ASM_GENERIC_BOUNDED_SECTIONS_H */
--
2.53.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox