Linux Trace Kernel
 help / color / mirror / Atom feed
* Re: [PATCH v2] tracing: Show the tracer options in boot-time created instance
From: Masami Hiramatsu @ 2025-11-19  4:39 UTC (permalink / raw)
  To: Masami Hiramatsu (Google)
  Cc: Steven Rostedt, Mark Rutland, Mathieu Desnoyers, Andrew Morton,
	linux-kernel, linux-trace-kernel
In-Reply-To: <176351169375.1795430.7653862896005389480.stgit@mhiramat.tok.corp.google.com>

On Wed, 19 Nov 2025 09:21:34 +0900
"Masami Hiramatsu (Google)" <mhiramat@kernel.org> wrote:

> From: Masami Hiramatsu (Google) <mhiramat@kernel.org>
> 
> Since tracer_init_tracefs_work_func() only updates the tracer options
> for the global_trace, the instances created by the kernel cmdline
> do not have those options.
> 
> Fix to update tracer options for those boot-time created instances
> to show those options.
> 

Wait, this seems not updating the global instance. Let me fix it.
(ftracetest found it.)

Thanks,

> Fixes: 428add559b69 ("tracing: Have tracer option be instance specific")
> Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
> ---
>   Change in v2:
>    - Fix update_tracer_options() to update all instances.
>    - Update tracer_options_updated after update all instances.
> ---
>  kernel/trace/trace.c |   11 ++++++++---
>  1 file changed, 8 insertions(+), 3 deletions(-)
> 
> diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
> index 8ae95800592d..4a6784057855 100644
> --- a/kernel/trace/trace.c
> +++ b/kernel/trace/trace.c
> @@ -10231,11 +10231,16 @@ static __init int __update_tracer_options(struct trace_array *tr)
>  	return ret;
>  }
>  
> -static __init void update_tracer_options(struct trace_array *tr)
> +static __init void update_tracer_options(void)
>  {
> +	struct trace_array *tr;
> +
>  	guard(mutex)(&trace_types_lock);
> +
> +	list_for_each_entry(tr, &ftrace_trace_arrays, list)
> +		__update_tracer_options(tr);
> +
>  	tracer_options_updated = true;
> -	__update_tracer_options(tr);
>  }
>  
>  /* Must have trace_types_lock held */
> @@ -10937,7 +10942,7 @@ static __init void tracer_init_tracefs_work_func(struct work_struct *work)
>  
>  	create_trace_instances(NULL);
>  
> -	update_tracer_options(&global_trace);
> +	update_tracer_options();
>  }
>  
>  static __init int tracer_init_tracefs(void)
> 


-- 
Masami Hiramatsu (Google) <mhiramat@kernel.org>

^ permalink raw reply

* [PATCH] tracing: Fix WARN_ON in tracing_buffers_mmap_close for split VMAs
From: Deepanshu Kartikey @ 2025-11-19  6:40 UTC (permalink / raw)
  To: rostedt, mhiramat, mathieu.desnoyers
  Cc: linux-kernel, linux-trace-kernel, Deepanshu Kartikey,
	syzbot+a72c325b042aae6403c7

When a VMA is split (e.g., by partial munmap or MAP_FIXED), the kernel
calls vm_ops->close on each portion. For trace buffer mappings, this
results in ring_buffer_unmap() being called multiple times while
ring_buffer_map() was only called once.

This causes ring_buffer_unmap() to return -ENODEV on subsequent calls
because user_mapped is already 0, triggering a WARN_ON.

Trace buffer mappings cannot support partial mappings because the ring
buffer structure requires the complete buffer including the meta page.

Fix this by adding a may_split callback that returns -EINVAL to prevent
VMA splits entirely.

Closes: https://syzkaller.appspot.com/bug?extid=a72c325b042aae6403c7
Tested-by: syzbot+a72c325b042aae6403c7@syzkaller.appspotmail.com
Reported-by: syzbot+a72c325b042aae6403c7@syzkaller.appspotmail.com
Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com>
---
 kernel/trace/trace.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index d1e527cf2aae..304e93597126 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -8781,8 +8781,18 @@ static void tracing_buffers_mmap_close(struct vm_area_struct *vma)
 	put_snapshot_map(iter->tr);
 }
 
+static int tracing_buffers_may_split(struct vm_area_struct *vma, unsigned long addr)
+{
+	/*
+	 * Trace buffer mappings require the complete buffer including
+	 * the meta page. Partial mappings are not supported.
+	 */
+	return -EINVAL;
+}
+
 static const struct vm_operations_struct tracing_buffers_vmops = {
 	.close		= tracing_buffers_mmap_close,
+	.may_split      = tracing_buffers_may_split,
 };
 
 static int tracing_buffers_mmap(struct file *filp, struct vm_area_struct *vma)
-- 
2.43.0


^ permalink raw reply related

* Re: [PATCH 2/2] mm/khugepaged: return EAGAIN for transient dirty pages in MADV_COLLAPSE
From: Garg, Shivank @ 2025-11-19  7:00 UTC (permalink / raw)
  To: Dev Jain, Andrew Morton, David Hildenbrand, Lorenzo Stoakes
  Cc: Zi Yan, Baolin Wang, Liam R . Howlett, Nico Pache, Ryan Roberts,
	Barry Song, Lance Yang, Steven Rostedt, Masami Hiramatsu,
	Mathieu Desnoyers, Zach O'Keefe, linux-mm, linux-kernel,
	linux-trace-kernel
In-Reply-To: <4ab54ae0-2607-443d-8698-788d8e951bdd@arm.com>



On 11/10/2025 7:16 PM, Dev Jain wrote:
> 
> On 10/11/25 5:02 pm, Shivank Garg wrote:
>> When MADV_COLLAPSE encounters dirty file-backed pages, it currently
>> returns -EINVAL, this is misleading as EINVAL suggests invalid arguments,
>> whereas dirty pages are a transient condition that may resolve on retry.
>>
>> Introduce SCAN_PAGE_DIRTY and map it to -EAGAIN. For khugepaged, this
>> is harmless as it will revisit the range after async writeback completes.
> 
> Taking a cursory look at enum scan_result, I am sure there are other error
> codes as well which redirect to -EINVAL when they actually should to something
> else...
> 
>>

>> @@ -1967,7 +1968,7 @@ static int collapse_file(struct mm_struct *mm, unsigned long addr,
>>                    */
>>                   xas_unlock_irq(&xas);
>>                   filemap_flush(mapping);
>> -                result = SCAN_FAIL;
>> +                result = SCAN_PAGE_DIRTY;
>>                   goto xa_unlocked;
>>               } else if (folio_test_writeback(folio)) {
>>                   xas_unlock_irq(&xas);
> 
> Now that you are at it, it would make sense to redirect this folio_test_writeback()
> branch also to -EAGAIN, and call the common error code SCAN_PAGE_UNDER_WRITEBACK.
>

Good point about the folio_test_writeback() case.
I think we can use a single error code "SCAN_PAGE_NOT_CLEAN" to cover both dirty and writeback states.

Thanks,
Shivank

^ permalink raw reply

* [bug report] tracing: Have function graph tracer option sleep-time be per instance
From: Dan Carpenter @ 2025-11-19  7:31 UTC (permalink / raw)
  To: Steven Rostedt; +Cc: linux-trace-kernel

Hello Steven Rostedt,

Commit 5abb6ccb58f0 ("tracing: Have function graph tracer option
sleep-time be per instance") from Nov 14, 2025 (linux-next), leads to
the following Smatch static checker warning:

    kernel/trace/trace_functions_graph.c:1649 func_graph_set_flag()
    warn: unsigned 'fgraph_no_sleep_time' is never less than zero.

    kernel/trace/trace_functions_graph.c:1671 func_graph_set_flag()
    warn: unsigned 'fgraph_no_sleep_time' is never less than zero.

kernel/trace/trace_functions_graph.c
    1637 static int
    1638 func_graph_set_flag(struct trace_array *tr, u32 old_flags, u32 bit, int set)
    1639 {
    1640 /*
    1641  * The function profiler gets updated even if function graph
    1642  * isn't the current tracer. Handle it separately.
    1643  */
    1644 #ifdef CONFIG_FUNCTION_PROFILER
    1645         if (bit == TRACE_GRAPH_SLEEP_TIME && (tr->flags & TRACE_ARRAY_FL_GLOBAL) &&
    1646             !!set == fprofile_no_sleep_time) {
    1647                 if (set) {
    1648                         fgraph_no_sleep_time--;
--> 1649                         if (WARN_ON_ONCE(fgraph_no_sleep_time < 0))
                                                  ^^^^^^^^^^^^^^^^^^^^^^^^
Impossible.  Unsigned.

    1650                                 fgraph_no_sleep_time = 0;
    1651                         fprofile_no_sleep_time = false;
    1652                 } else {
    1653                         fgraph_no_sleep_time++;
    1654                         fprofile_no_sleep_time = true;
    1655                 }
    1656         }
    1657 #endif
    1658 
    1659         /* Do nothing if the current tracer is not this tracer */
    1660         if (tr->current_trace != &graph_trace)
    1661                 return 0;
    1662 
    1663         /* Do nothing if already set. */
    1664         if (!!set == !!(tr->current_trace_flags->val & bit))
    1665                 return 0;
    1666 
    1667         switch (bit) {
    1668         case TRACE_GRAPH_SLEEP_TIME:
    1669                 if (set) {
    1670                         fgraph_no_sleep_time--;
    1671                         if (WARN_ON_ONCE(fgraph_no_sleep_time < 0))
                                                  ^^^^^^^^^^^^^^^^^^^^^^^^
Same.

    1672                                 fgraph_no_sleep_time = 0;
    1673                 } else {
    1674                         fgraph_no_sleep_time++;
    1675                 }
    1676                 break;
    1677 
    1678         case TRACE_GRAPH_PRINT_IRQS:
    1679                 if (set)
    1680                         ftrace_graph_skip_irqs--;
    1681                 else
    1682                         ftrace_graph_skip_irqs++;
    1683                 if (WARN_ON_ONCE(ftrace_graph_skip_irqs < 0))
    1684                         ftrace_graph_skip_irqs = 0;
    1685                 break;
    1686 
    1687         case TRACE_GRAPH_ARGS:
    1688                 return ftrace_graph_trace_args(tr, set);
    1689         }
    1690 
    1691         return 0;
    1692 }

regards,
dan carpenter

^ permalink raw reply

* Re: [PATCH v2] tracing: Show the tracer options in boot-time created instance
From: Masami Hiramatsu @ 2025-11-19  8:31 UTC (permalink / raw)
  To: Masami Hiramatsu
  Cc: Steven Rostedt, Mark Rutland, Mathieu Desnoyers, Andrew Morton,
	linux-kernel, linux-trace-kernel
In-Reply-To: <20251119133942.df3ee2c01ccd40055cf139a4@kernel.org>

On Wed, 19 Nov 2025 13:39:42 +0900
Masami Hiramatsu (Google) <mhiramat@kernel.org> wrote:
> > diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
> > index 8ae95800592d..4a6784057855 100644
> > --- a/kernel/trace/trace.c
> > +++ b/kernel/trace/trace.c
> > @@ -10231,11 +10231,16 @@ static __init int __update_tracer_options(struct trace_array *tr)
> >  	return ret;
> >  }
> >  
> > -static __init void update_tracer_options(struct trace_array *tr)
> > +static __init void update_tracer_options(void)
> >  {
> > +	struct trace_array *tr;
> > +
> >  	guard(mutex)(&trace_types_lock);
> > +
> > +	list_for_each_entry(tr, &ftrace_trace_arrays, list)
> > +		__update_tracer_options(tr);
> > +
> >  	tracer_options_updated = true;

Oops, I misunderstood this flag. This should be set *before* calling
__update_tracer_options(). Not updated.

Thanks,

-- 
Masami Hiramatsu (Google) <mhiramat@kernel.org>

^ permalink raw reply

* [PATCH v3] tracing: Show the tracer options in boot-time created instance
From: Masami Hiramatsu (Google) @ 2025-11-19  8:32 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: Masami Hiramatsu, Mark Rutland, Mathieu Desnoyers, Andrew Morton,
	linux-kernel, linux-trace-kernel

From: Masami Hiramatsu (Google) <mhiramat@kernel.org>

Since tracer_init_tracefs_work_func() only updates the tracer options
for the global_trace, the instances created by the kernel cmdline
do not have those options.

Fix to update tracer options for those boot-time created instances
to show those options.

Fixes: 428add559b69 ("tracing: Have tracer option be instance specific")
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
---
  Changes in v3:
   - Fix to update tracer_options_updated before update.
  Changes in v2:
   - Fix update_tracer_options() to update all instances.
   - Update tracer_options_updated after update all instances.
---
 kernel/trace/trace.c |    9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 8ae95800592d..33fcde91924c 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -10231,11 +10231,14 @@ static __init int __update_tracer_options(struct trace_array *tr)
 	return ret;
 }
 
-static __init void update_tracer_options(struct trace_array *tr)
+static __init void update_tracer_options(void)
 {
+	struct trace_array *tr;
+
 	guard(mutex)(&trace_types_lock);
 	tracer_options_updated = true;
-	__update_tracer_options(tr);
+	list_for_each_entry(tr, &ftrace_trace_arrays, list)
+		__update_tracer_options(tr);
 }
 
 /* Must have trace_types_lock held */
@@ -10937,7 +10940,7 @@ static __init void tracer_init_tracefs_work_func(struct work_struct *work)
 
 	create_trace_instances(NULL);
 
-	update_tracer_options(&global_trace);
+	update_tracer_options();
 }
 
 static __init int tracer_init_tracefs(void)


^ permalink raw reply related

* Re: [PATCH v4 2/9] mm: add atomic VMA flags and set VM_MAYBE_GUARD as such
From: David Hildenbrand (Red Hat) @ 2025-11-19  9:06 UTC (permalink / raw)
  To: Lorenzo Stoakes, Andrew Morton
  Cc: Jonathan Corbet, Liam R . Howlett, Vlastimil Babka, Mike Rapoport,
	Suren Baghdasaryan, Michal Hocko, Steven Rostedt,
	Masami Hiramatsu, Mathieu Desnoyers, Jann Horn, Pedro Falcato,
	Zi Yan, Baolin Wang, Nico Pache, Ryan Roberts, Dev Jain,
	Barry Song, Lance Yang, linux-kernel, linux-fsdevel, linux-doc,
	linux-mm, linux-trace-kernel, linux-kselftest, Andrei Vagin
In-Reply-To: <97e57abed09f2663077ed7a36fb8206e243171a9.1763460113.git.lorenzo.stoakes@oracle.com>

On 18.11.25 11:17, Lorenzo Stoakes wrote:
> This patch adds the ability to atomically set VMA flags with only the mmap
> read/VMA read lock held.
> 
> As this could be hugely problematic for VMA flags in general given that
> all other accesses are non-atomic and serialised by the mmap/VMA locks, we
> implement this with a strict allow-list - that is, only designated flags
> are allowed to do this.
> 
> We make VM_MAYBE_GUARD one of these flags.
> 
> Signed-off-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
> Reviewed-by: Pedro Falcato <pfalcato@suse.de>
> Reviewed-by: Vlastimil Babka <vbabka@suse.cz>
> ---

IIUC all other flag modifications need a write lock, so this should just 
work.

Acked-by: David Hildenbrand (Red Hat) <david@kernel.org>

-- 
Cheers

David

^ permalink raw reply

* Re: [PATCH v3 01/21] lib/vsprintf: Add specifier for printing struct timespec64
From: Andy Shevchenko @ 2025-11-19  9:14 UTC (permalink / raw)
  To: Petr Mladek
  Cc: Steven Rostedt, linux-doc, linux-kernel, openipmi-developer,
	linux-media, dri-devel, linaro-mm-sig, amd-gfx, linux-arm-msm,
	freedreno, intel-xe, linux-mmc, netdev, intel-wired-lan,
	linux-pci, linux-s390, linux-scsi, linux-staging, ceph-devel,
	linux-trace-kernel, Rasmus Villemoes, Sergey Senozhatsky,
	Jonathan Corbet
In-Reply-To: <aRd5HHUBu2ookDv_@smile.fi.intel.com>

On Fri, Nov 14, 2025 at 08:46:52PM +0200, Andy Shevchenko wrote:
> On Fri, Nov 14, 2025 at 01:59:38PM +0100, Petr Mladek wrote:
> > On Thu 2025-11-13 15:32:15, Andy Shevchenko wrote:

...

> > I wonder how to move forward. I could take the whole patchset via
> > printk tree. There is no conflict with linux-next at the moment.
> > 
> > It seems that only 3 patches haven't got any ack yet. I am going
> > to wait for more feedback and push it later the following week
> > (Wednesday or so) unless anyone complains.
> 
> Sounds good to me!
> 
> But in the worst case all but untagged can be pushed, the rest can go
> to the next cycle.

Just got a "BUILD SUCCESS" from LKP and since we gained even more tags
I think it's ready to go.

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply

* Re: [PATCH v4 6/9] mm: set the VM_MAYBE_GUARD flag on guard region install
From: David Hildenbrand (Red Hat) @ 2025-11-19  9:16 UTC (permalink / raw)
  To: Lorenzo Stoakes, Andrew Morton
  Cc: Jonathan Corbet, Liam R . Howlett, Vlastimil Babka, Mike Rapoport,
	Suren Baghdasaryan, Michal Hocko, Steven Rostedt,
	Masami Hiramatsu, Mathieu Desnoyers, Jann Horn, Pedro Falcato,
	Zi Yan, Baolin Wang, Nico Pache, Ryan Roberts, Dev Jain,
	Barry Song, Lance Yang, linux-kernel, linux-fsdevel, linux-doc,
	linux-mm, linux-trace-kernel, linux-kselftest, Andrei Vagin
In-Reply-To: <e9e9ce95b6ac17497de7f60fc110c7dd9e489e8d.1763460113.git.lorenzo.stoakes@oracle.com>

>   
> +/* Can we retract page tables for this file-backed VMA? */
> +static bool file_backed_vma_is_retractable(struct vm_area_struct *vma)

It's not really the VMA that is retractable :)

Given that the function we are called this from is called 
"retract_page_tables" (and not file_backed_...) I guess I would just 
have called this

"page_tables_are_retractable"

"page_tables_support_retract"

Or sth. along those lines.

> +{
> +	/*
> +	 * Check vma->anon_vma to exclude MAP_PRIVATE mappings that
> +	 * got written to. These VMAs are likely not worth removing
> +	 * page tables from, as PMD-mapping is likely to be split later.
> +	 */
> +	if (READ_ONCE(vma->anon_vma))
> +		return false;
> +
> +	/*
> +	 * When a vma is registered with uffd-wp, we cannot recycle
> +	 * the page table because there may be pte markers installed.
> +	 * Other vmas can still have the same file mapped hugely, but
> +	 * skip this one: it will always be mapped in small page size
> +	 * for uffd-wp registered ranges.
> +	 */
> +	if (userfaultfd_wp(vma))
> +		return false;
> +
> +	/*
> +	 * If the VMA contains guard regions then we can't collapse it.
> +	 *
> +	 * This is set atomically on guard marker installation under mmap/VMA
> +	 * read lock, and here we may not hold any VMA or mmap lock at all.
> +	 *
> +	 * This is therefore serialised on the PTE page table lock, which is
> +	 * obtained on guard region installation after the flag is set, so this
> +	 * check being performed under this lock excludes races.
> +	 */
> +	if (vma_flag_test_atomic(vma, VM_MAYBE_GUARD_BIT))
> +		return false;
> +
> +	return true;
> +}
> +
>   static void retract_page_tables(struct address_space *mapping, pgoff_t pgoff)
>   {
>   	struct vm_area_struct *vma;
> @@ -1724,14 +1761,6 @@ static void retract_page_tables(struct address_space *mapping, pgoff_t pgoff)
>   		spinlock_t *ptl;
>   		bool success = false;
>   
> -		/*
> -		 * Check vma->anon_vma to exclude MAP_PRIVATE mappings that
> -		 * got written to. These VMAs are likely not worth removing
> -		 * page tables from, as PMD-mapping is likely to be split later.
> -		 */
> -		if (READ_ONCE(vma->anon_vma))
> -			continue;
> -
>   		addr = vma->vm_start + ((pgoff - vma->vm_pgoff) << PAGE_SHIFT);
>   		if (addr & ~HPAGE_PMD_MASK ||
>   		    vma->vm_end < addr + HPAGE_PMD_SIZE)
> @@ -1743,14 +1772,8 @@ static void retract_page_tables(struct address_space *mapping, pgoff_t pgoff)
>   
>   		if (hpage_collapse_test_exit(mm))
>   			continue;
> -		/*
> -		 * When a vma is registered with uffd-wp, we cannot recycle
> -		 * the page table because there may be pte markers installed.
> -		 * Other vmas can still have the same file mapped hugely, but
> -		 * skip this one: it will always be mapped in small page size
> -		 * for uffd-wp registered ranges.
> -		 */
> -		if (userfaultfd_wp(vma))
> +
> +		if (!file_backed_vma_is_retractable(vma))
>   			continue;
>   
>   		/* PTEs were notified when unmapped; but now for the PMD? */
> @@ -1777,15 +1800,15 @@ static void retract_page_tables(struct address_space *mapping, pgoff_t pgoff)
>   			spin_lock_nested(ptl, SINGLE_DEPTH_NESTING);
>   
>   		/*
> -		 * Huge page lock is still held, so normally the page table
> -		 * must remain empty; and we have already skipped anon_vma
> -		 * and userfaultfd_wp() vmas.  But since the mmap_lock is not
> -		 * held, it is still possible for a racing userfaultfd_ioctl()
> -		 * to have inserted ptes or markers.  Now that we hold ptlock,
> -		 * repeating the anon_vma check protects from one category,
> -		 * and repeating the userfaultfd_wp() check from another.
> +		 * Huge page lock is still held, so normally the page table must
> +		 * remain empty; and we have already skipped anon_vma and
> +		 * userfaultfd_wp() vmas.  But since the mmap_lock is not held,
> +		 * it is still possible for a racing userfaultfd_ioctl() or
> +		 * madvise() to have inserted ptes or markers.  Now that we hold
> +		 * ptlock, repeating the retractable checks protects us from
> +		 * races against the prior checks.
>   		 */
> -		if (likely(!vma->anon_vma && !userfaultfd_wp(vma))) {
> +		if (likely(file_backed_vma_is_retractable(vma))) {
>   			pgt_pmd = pmdp_collapse_flush(vma, addr, pmd);
>   			pmdp_get_lockless_sync();
>   			success = true;
> diff --git a/mm/madvise.c b/mm/madvise.c
> index 0b3280752bfb..5dbe40be7c65 100644
> --- a/mm/madvise.c
> +++ b/mm/madvise.c
> @@ -1141,15 +1141,21 @@ static long madvise_guard_install(struct madvise_behavior *madv_behavior)
>   		return -EINVAL;
>   
>   	/*
> -	 * If we install guard markers, then the range is no longer
> -	 * empty from a page table perspective and therefore it's
> -	 * appropriate to have an anon_vma.
> -	 *
> -	 * This ensures that on fork, we copy page tables correctly.
> +	 * Set atomically under read lock. All pertinent readers will need to
> +	 * acquire an mmap/VMA write lock to read it. All remaining readers may
> +	 * or may not see the flag set, but we don't care.
> +	 */
> +	vma_flag_set_atomic(vma, VM_MAYBE_GUARD_BIT);
> +

In general LGTM.

> +	/*
> +	 * If anonymous and we are establishing page tables the VMA ought to
> +	 * have an anon_vma associated with it.

Do you know why? I know that as soon as we have anon folios in there we 
need it, but is it still required for guard regions? Patch #5 should 
handle the for case I guess.

Which other code depends on that?

-- 
Cheers

David

^ permalink raw reply

* Re: [PATCH v4 5/9] mm: introduce copy-on-fork VMAs and make VM_MAYBE_GUARD one
From: David Hildenbrand (Red Hat) @ 2025-11-19  9:17 UTC (permalink / raw)
  To: Lorenzo Stoakes, Andrew Morton
  Cc: Jonathan Corbet, Liam R . Howlett, Vlastimil Babka, Mike Rapoport,
	Suren Baghdasaryan, Michal Hocko, Steven Rostedt,
	Masami Hiramatsu, Mathieu Desnoyers, Jann Horn, Pedro Falcato,
	Zi Yan, Baolin Wang, Nico Pache, Ryan Roberts, Dev Jain,
	Barry Song, Lance Yang, linux-kernel, linux-fsdevel, linux-doc,
	linux-mm, linux-trace-kernel, linux-kselftest, Andrei Vagin
In-Reply-To: <5d41b24e7bc622cda0af92b6d558d7f4c0d1bc8c.1763460113.git.lorenzo.stoakes@oracle.com>

On 18.11.25 11:17, Lorenzo Stoakes wrote:
> Gather all the VMA flags whose presence implies that page tables must be
> copied on fork into a single bitmap - VM_COPY_ON_FORK - and use this
> rather than specifying individual flags in vma_needs_copy().
> 
> We also add VM_MAYBE_GUARD to this list, as it being set on a VMA implies
> that there may be metadata contained in the page tables (that is - guard
> markers) which would will not and cannot be propagated upon fork.
> 
> This was already being done manually previously in vma_needs_copy(), but
> this makes it very explicit, alongside VM_PFNMAP, VM_MIXEDMAP and
> VM_UFFD_WP all of which imply the same.
> 
> Note that VM_STICKY flags ought generally to be marked VM_COPY_ON_FORK too
> - because equally a flag being VM_STICKY indicates that the VMA contains
> metadat that is not propagated by being faulted in - i.e.  that the VMA
> metadata does not fully describe the VMA alone, and thus we must propagate
> whatever metadata there is on a fork.
> 
> However, for maximum flexibility, we do not make this necessarily the case
> here.
> 
> Signed-off-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
> Reviewed-by: Pedro Falcato <pfalcato@suse.de>
> Reviewed-by: Vlastimil Babka <vbabka@suse.cz>
> ---

Acked-by: David Hildenbrand (Red Hat) <david@kernel.org>

-- 
Cheers

David

^ permalink raw reply

* Re: [PATCH v4 6/9] mm: set the VM_MAYBE_GUARD flag on guard region install
From: Lorenzo Stoakes @ 2025-11-19  9:27 UTC (permalink / raw)
  To: David Hildenbrand (Red Hat)
  Cc: Andrew Morton, Jonathan Corbet, Liam R . Howlett, Vlastimil Babka,
	Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Steven Rostedt,
	Masami Hiramatsu, Mathieu Desnoyers, Jann Horn, Pedro Falcato,
	Zi Yan, Baolin Wang, Nico Pache, Ryan Roberts, Dev Jain,
	Barry Song, Lance Yang, linux-kernel, linux-fsdevel, linux-doc,
	linux-mm, linux-trace-kernel, linux-kselftest, Andrei Vagin
In-Reply-To: <61f7c6d2-a15e-4c6a-9704-0e3db65eed3c@kernel.org>

On Wed, Nov 19, 2025 at 10:16:14AM +0100, David Hildenbrand (Red Hat) wrote:
> > +/* Can we retract page tables for this file-backed VMA? */
> > +static bool file_backed_vma_is_retractable(struct vm_area_struct *vma)
>
> It's not really the VMA that is retractable :)
>
> Given that the function we are called this from is called
> "retract_page_tables" (and not file_backed_...) I guess I would just have
> called this
>
> "page_tables_are_retractable"
>
> "page_tables_support_retract"
>
> Or sth. along those lines.

Well it's specific to the VMA and it starts getting messy, this is the problem
with naming, you can_end_up_with_way_too_specific_names :)

Also you'd need to say file-baked for clarity really, and that's getting far too
long...

I think this is fine as-is given it's a static function, a user thinking 'what
does retractable mean?' can see right away in the comment immdiately above the
function name.

>
> > +{
> > +	/*
> > +	 * Check vma->anon_vma to exclude MAP_PRIVATE mappings that
> > +	 * got written to. These VMAs are likely not worth removing
> > +	 * page tables from, as PMD-mapping is likely to be split later.
> > +	 */
> > +	if (READ_ONCE(vma->anon_vma))
> > +		return false;
> > +
> > +	/*
> > +	 * When a vma is registered with uffd-wp, we cannot recycle
> > +	 * the page table because there may be pte markers installed.
> > +	 * Other vmas can still have the same file mapped hugely, but
> > +	 * skip this one: it will always be mapped in small page size
> > +	 * for uffd-wp registered ranges.
> > +	 */
> > +	if (userfaultfd_wp(vma))
> > +		return false;
> > +
> > +	/*
> > +	 * If the VMA contains guard regions then we can't collapse it.
> > +	 *
> > +	 * This is set atomically on guard marker installation under mmap/VMA
> > +	 * read lock, and here we may not hold any VMA or mmap lock at all.
> > +	 *
> > +	 * This is therefore serialised on the PTE page table lock, which is
> > +	 * obtained on guard region installation after the flag is set, so this
> > +	 * check being performed under this lock excludes races.
> > +	 */
> > +	if (vma_flag_test_atomic(vma, VM_MAYBE_GUARD_BIT))
> > +		return false;
> > +
> > +	return true;
> > +}
> > +
> >   static void retract_page_tables(struct address_space *mapping, pgoff_t pgoff)
> >   {
> >   	struct vm_area_struct *vma;
> > @@ -1724,14 +1761,6 @@ static void retract_page_tables(struct address_space *mapping, pgoff_t pgoff)
> >   		spinlock_t *ptl;
> >   		bool success = false;
> > -		/*
> > -		 * Check vma->anon_vma to exclude MAP_PRIVATE mappings that
> > -		 * got written to. These VMAs are likely not worth removing
> > -		 * page tables from, as PMD-mapping is likely to be split later.
> > -		 */
> > -		if (READ_ONCE(vma->anon_vma))
> > -			continue;
> > -
> >   		addr = vma->vm_start + ((pgoff - vma->vm_pgoff) << PAGE_SHIFT);
> >   		if (addr & ~HPAGE_PMD_MASK ||
> >   		    vma->vm_end < addr + HPAGE_PMD_SIZE)
> > @@ -1743,14 +1772,8 @@ static void retract_page_tables(struct address_space *mapping, pgoff_t pgoff)
> >   		if (hpage_collapse_test_exit(mm))
> >   			continue;
> > -		/*
> > -		 * When a vma is registered with uffd-wp, we cannot recycle
> > -		 * the page table because there may be pte markers installed.
> > -		 * Other vmas can still have the same file mapped hugely, but
> > -		 * skip this one: it will always be mapped in small page size
> > -		 * for uffd-wp registered ranges.
> > -		 */
> > -		if (userfaultfd_wp(vma))
> > +
> > +		if (!file_backed_vma_is_retractable(vma))
> >   			continue;
> >   		/* PTEs were notified when unmapped; but now for the PMD? */
> > @@ -1777,15 +1800,15 @@ static void retract_page_tables(struct address_space *mapping, pgoff_t pgoff)
> >   			spin_lock_nested(ptl, SINGLE_DEPTH_NESTING);
> >   		/*
> > -		 * Huge page lock is still held, so normally the page table
> > -		 * must remain empty; and we have already skipped anon_vma
> > -		 * and userfaultfd_wp() vmas.  But since the mmap_lock is not
> > -		 * held, it is still possible for a racing userfaultfd_ioctl()
> > -		 * to have inserted ptes or markers.  Now that we hold ptlock,
> > -		 * repeating the anon_vma check protects from one category,
> > -		 * and repeating the userfaultfd_wp() check from another.
> > +		 * Huge page lock is still held, so normally the page table must
> > +		 * remain empty; and we have already skipped anon_vma and
> > +		 * userfaultfd_wp() vmas.  But since the mmap_lock is not held,
> > +		 * it is still possible for a racing userfaultfd_ioctl() or
> > +		 * madvise() to have inserted ptes or markers.  Now that we hold
> > +		 * ptlock, repeating the retractable checks protects us from
> > +		 * races against the prior checks.
> >   		 */
> > -		if (likely(!vma->anon_vma && !userfaultfd_wp(vma))) {
> > +		if (likely(file_backed_vma_is_retractable(vma))) {
> >   			pgt_pmd = pmdp_collapse_flush(vma, addr, pmd);
> >   			pmdp_get_lockless_sync();
> >   			success = true;
> > diff --git a/mm/madvise.c b/mm/madvise.c
> > index 0b3280752bfb..5dbe40be7c65 100644
> > --- a/mm/madvise.c
> > +++ b/mm/madvise.c
> > @@ -1141,15 +1141,21 @@ static long madvise_guard_install(struct madvise_behavior *madv_behavior)
> >   		return -EINVAL;
> >   	/*
> > -	 * If we install guard markers, then the range is no longer
> > -	 * empty from a page table perspective and therefore it's
> > -	 * appropriate to have an anon_vma.
> > -	 *
> > -	 * This ensures that on fork, we copy page tables correctly.
> > +	 * Set atomically under read lock. All pertinent readers will need to
> > +	 * acquire an mmap/VMA write lock to read it. All remaining readers may
> > +	 * or may not see the flag set, but we don't care.
> > +	 */
> > +	vma_flag_set_atomic(vma, VM_MAYBE_GUARD_BIT);
> > +
>
> In general LGTM.

Thanks

>
> > +	/*
> > +	 * If anonymous and we are establishing page tables the VMA ought to
> > +	 * have an anon_vma associated with it.
>
> Do you know why? I know that as soon as we have anon folios in there we need
> it, but is it still required for guard regions? Patch #5 should handle the
> for case I guess.
>
> Which other code depends on that?

There seems to be a general convention of people seeing 'vma->anon_vma' as
meaning it has page tables, and vice-versa, for anon VMAs.

Obviously we change fork behaviour for this now with the flag, and _perhaps_
it's not necessary, but I'd rather keep this consistent for now (this is what we
were doing before) and come back to it, rather than audit the code base for
assumptions.

I'd probably like to do a patch adding vma_has_page_tables() or something that
EXPLICITLY spells this out for cases that need it.

And it's not really overhead, as there'd not be much point in guard regions if
you didn't fault in the memory (running off the end of empty range doesn't
really make snese).

The key change here is that file-backed guard regions no longer do the horrible
thing of having your file-backed VMA act as if it were MAP_PRIVATE with its own
pointless anon_vma just to get correct fork behaviour... :)

>
> --
> Cheers
>
> David

Thanks, Lorenzo

^ permalink raw reply

* [PATCH v3] mm/memory-failure: remove the selection of RAS
From: Xie Yuanbin @ 2025-11-19  9:59 UTC (permalink / raw)
  To: david, tony.luck, bp, linmiaohe, nao.horiguchi, rostedt, mhiramat,
	mathieu.desnoyers, akpm, david, lorenzo.stoakes, Liam.Howlett,
	vbabka, rppt, surenb, mhocko
  Cc: linux-kernel, linux-edac, linux-mm, linux-trace-kernel, will,
	liaohua4, lilinjie8, Xie Yuanbin

The commit 97f0b13452198290799f ("tracing: add trace event for
memory-failure") introduces the selection of RAS in memory-failure.
This commit is just a tracing feature; in reality, there is no dependency
between memory-failure and RAS. RAS increases the size of the bzImage
image by 8k, which is very valuable for embedded devices.

Move the memory-failure traceing code from ras_event.h to
memory-failure.h and remove the selection of RAS.

v2->v3: https://lore.kernel.org/20251104072306.100738-3-xieyuanbin1@huawei.com
  - Change define TRACE_SYSTEM from ras to memory_failure
  - Add include/trace/events/memory-failure.h to
    "HWPOISON MEMORY FAILURE HANDLING" section in MAINTAINERS
  - Rebase to latest linux-next source

v1->v2: https://lore.kernel.org/20251103033536.52234-2-xieyuanbin1@huawei.com
  - Move the memory-failure traceing code from ras_event.h to
    memory-failure.h

Signed-off-by: Xie Yuanbin <xieyuanbin1@huawei.com>
Cc: David Hildenbrand (Red Hat) <david@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Miaohe Lin <linmiaohe@huawei.com>
---
 MAINTAINERS                           |  1 +
 include/ras/ras_event.h               | 87 ------------------------
 include/trace/events/memory-failure.h | 98 +++++++++++++++++++++++++++
 mm/Kconfig                            |  1 -
 mm/memory-failure.c                   |  5 +-
 5 files changed, 103 insertions(+), 89 deletions(-)
 create mode 100644 include/trace/events/memory-failure.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 7310d9ca0370..43d6eb95fb05 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11631,10 +11631,11 @@ R:	Naoya Horiguchi <nao.horiguchi@gmail.com>
 L:	linux-mm@kvack.org
 S:	Maintained
 F:	include/linux/memory-failure.h
 F:	mm/hwpoison-inject.c
 F:	mm/memory-failure.c
+F:	include/trace/events/memory-failure.h
 
 HYCON HY46XX TOUCHSCREEN SUPPORT
 M:	Giulio Benetti <giulio.benetti@benettiengineering.com>
 L:	linux-input@vger.kernel.org
 S:	Maintained
diff --git a/include/ras/ras_event.h b/include/ras/ras_event.h
index fecfeb7c8be7..1e5e87020eef 100644
--- a/include/ras/ras_event.h
+++ b/include/ras/ras_event.h
@@ -10,11 +10,10 @@
 #include <linux/edac.h>
 #include <linux/ktime.h>
 #include <linux/pci.h>
 #include <linux/aer.h>
 #include <linux/cper.h>
-#include <linux/mm.h>
 
 /*
  * MCE Extended Error Log trace event
  *
  * These events are generated when hardware detects a corrected or
@@ -337,95 +336,9 @@ TRACE_EVENT(aer_event,
 		__entry->tlp_header_valid ?
 			__print_array(__entry->tlp_header, PCIE_STD_MAX_TLP_HEADERLOG, 4) :
 			"Not available")
 );
 #endif /* CONFIG_PCIEAER */
-
-/*
- * memory-failure recovery action result event
- *
- * unsigned long pfn -	Page Frame Number of the corrupted page
- * int type	-	Page types of the corrupted page
- * int result	-	Result of recovery action
- */
-
-#ifdef CONFIG_MEMORY_FAILURE
-#define MF_ACTION_RESULT	\
-	EM ( MF_IGNORED, "Ignored" )	\
-	EM ( MF_FAILED,  "Failed" )	\
-	EM ( MF_DELAYED, "Delayed" )	\
-	EMe ( MF_RECOVERED, "Recovered" )
-
-#define MF_PAGE_TYPE		\
-	EM ( MF_MSG_KERNEL, "reserved kernel page" )			\
-	EM ( MF_MSG_KERNEL_HIGH_ORDER, "high-order kernel page" )	\
-	EM ( MF_MSG_HUGE, "huge page" )					\
-	EM ( MF_MSG_FREE_HUGE, "free huge page" )			\
-	EM ( MF_MSG_GET_HWPOISON, "get hwpoison page" )			\
-	EM ( MF_MSG_UNMAP_FAILED, "unmapping failed page" )		\
-	EM ( MF_MSG_DIRTY_SWAPCACHE, "dirty swapcache page" )		\
-	EM ( MF_MSG_CLEAN_SWAPCACHE, "clean swapcache page" )		\
-	EM ( MF_MSG_DIRTY_MLOCKED_LRU, "dirty mlocked LRU page" )	\
-	EM ( MF_MSG_CLEAN_MLOCKED_LRU, "clean mlocked LRU page" )	\
-	EM ( MF_MSG_DIRTY_UNEVICTABLE_LRU, "dirty unevictable LRU page" )	\
-	EM ( MF_MSG_CLEAN_UNEVICTABLE_LRU, "clean unevictable LRU page" )	\
-	EM ( MF_MSG_DIRTY_LRU, "dirty LRU page" )			\
-	EM ( MF_MSG_CLEAN_LRU, "clean LRU page" )			\
-	EM ( MF_MSG_TRUNCATED_LRU, "already truncated LRU page" )	\
-	EM ( MF_MSG_BUDDY, "free buddy page" )				\
-	EM ( MF_MSG_DAX, "dax page" )					\
-	EM ( MF_MSG_UNSPLIT_THP, "unsplit thp" )			\
-	EM ( MF_MSG_ALREADY_POISONED, "already poisoned" )		\
-	EM ( MF_MSG_PFN_MAP, "non struct page pfn" )                    \
-	EMe ( MF_MSG_UNKNOWN, "unknown page" )
-
-/*
- * First define the enums in MM_ACTION_RESULT to be exported to userspace
- * via TRACE_DEFINE_ENUM().
- */
-#undef EM
-#undef EMe
-#define EM(a, b) TRACE_DEFINE_ENUM(a);
-#define EMe(a, b)	TRACE_DEFINE_ENUM(a);
-
-MF_ACTION_RESULT
-MF_PAGE_TYPE
-
-/*
- * Now redefine the EM() and EMe() macros to map the enums to the strings
- * that will be printed in the output.
- */
-#undef EM
-#undef EMe
-#define EM(a, b)		{ a, b },
-#define EMe(a, b)	{ a, b }
-
-TRACE_EVENT(memory_failure_event,
-	TP_PROTO(unsigned long pfn,
-		 int type,
-		 int result),
-
-	TP_ARGS(pfn, type, result),
-
-	TP_STRUCT__entry(
-		__field(unsigned long, pfn)
-		__field(int, type)
-		__field(int, result)
-	),
-
-	TP_fast_assign(
-		__entry->pfn	= pfn;
-		__entry->type	= type;
-		__entry->result	= result;
-	),
-
-	TP_printk("pfn %#lx: recovery action for %s: %s",
-		__entry->pfn,
-		__print_symbolic(__entry->type, MF_PAGE_TYPE),
-		__print_symbolic(__entry->result, MF_ACTION_RESULT)
-	)
-);
-#endif /* CONFIG_MEMORY_FAILURE */
 #endif /* _TRACE_HW_EVENT_MC_H */
 
 /* This part must be outside protection */
 #include <trace/define_trace.h>
diff --git a/include/trace/events/memory-failure.h b/include/trace/events/memory-failure.h
new file mode 100644
index 000000000000..aa57cc8f896b
--- /dev/null
+++ b/include/trace/events/memory-failure.h
@@ -0,0 +1,98 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM memory_failure
+#define TRACE_INCLUDE_FILE memory-failure
+
+#if !defined(_TRACE_MEMORY_FAILURE_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_MEMORY_FAILURE_H
+
+#include <linux/tracepoint.h>
+#include <linux/mm.h>
+
+/*
+ * memory-failure recovery action result event
+ *
+ * unsigned long pfn -	Page Frame Number of the corrupted page
+ * int type	-	Page types of the corrupted page
+ * int result	-	Result of recovery action
+ */
+
+#define MF_ACTION_RESULT	\
+	EM ( MF_IGNORED, "Ignored" )	\
+	EM ( MF_FAILED,  "Failed" )	\
+	EM ( MF_DELAYED, "Delayed" )	\
+	EMe ( MF_RECOVERED, "Recovered" )
+
+#define MF_PAGE_TYPE		\
+	EM ( MF_MSG_KERNEL, "reserved kernel page" )			\
+	EM ( MF_MSG_KERNEL_HIGH_ORDER, "high-order kernel page" )	\
+	EM ( MF_MSG_HUGE, "huge page" )					\
+	EM ( MF_MSG_FREE_HUGE, "free huge page" )			\
+	EM ( MF_MSG_GET_HWPOISON, "get hwpoison page" )			\
+	EM ( MF_MSG_UNMAP_FAILED, "unmapping failed page" )		\
+	EM ( MF_MSG_DIRTY_SWAPCACHE, "dirty swapcache page" )		\
+	EM ( MF_MSG_CLEAN_SWAPCACHE, "clean swapcache page" )		\
+	EM ( MF_MSG_DIRTY_MLOCKED_LRU, "dirty mlocked LRU page" )	\
+	EM ( MF_MSG_CLEAN_MLOCKED_LRU, "clean mlocked LRU page" )	\
+	EM ( MF_MSG_DIRTY_UNEVICTABLE_LRU, "dirty unevictable LRU page" )	\
+	EM ( MF_MSG_CLEAN_UNEVICTABLE_LRU, "clean unevictable LRU page" )	\
+	EM ( MF_MSG_DIRTY_LRU, "dirty LRU page" )			\
+	EM ( MF_MSG_CLEAN_LRU, "clean LRU page" )			\
+	EM ( MF_MSG_TRUNCATED_LRU, "already truncated LRU page" )	\
+	EM ( MF_MSG_BUDDY, "free buddy page" )				\
+	EM ( MF_MSG_DAX, "dax page" )					\
+	EM ( MF_MSG_UNSPLIT_THP, "unsplit thp" )			\
+	EM ( MF_MSG_ALREADY_POISONED, "already poisoned" )		\
+	EM ( MF_MSG_PFN_MAP, "non struct page pfn" )                    \
+	EMe ( MF_MSG_UNKNOWN, "unknown page" )
+
+/*
+ * First define the enums in MM_ACTION_RESULT to be exported to userspace
+ * via TRACE_DEFINE_ENUM().
+ */
+#undef EM
+#undef EMe
+#define EM(a, b) TRACE_DEFINE_ENUM(a);
+#define EMe(a, b)	TRACE_DEFINE_ENUM(a);
+
+MF_ACTION_RESULT
+MF_PAGE_TYPE
+
+/*
+ * Now redefine the EM() and EMe() macros to map the enums to the strings
+ * that will be printed in the output.
+ */
+#undef EM
+#undef EMe
+#define EM(a, b)		{ a, b },
+#define EMe(a, b)	{ a, b }
+
+TRACE_EVENT(memory_failure_event,
+	TP_PROTO(unsigned long pfn,
+		 int type,
+		 int result),
+
+	TP_ARGS(pfn, type, result),
+
+	TP_STRUCT__entry(
+		__field(unsigned long, pfn)
+		__field(int, type)
+		__field(int, result)
+	),
+
+	TP_fast_assign(
+		__entry->pfn	= pfn;
+		__entry->type	= type;
+		__entry->result	= result;
+	),
+
+	TP_printk("pfn %#lx: recovery action for %s: %s",
+		__entry->pfn,
+		__print_symbolic(__entry->type, MF_PAGE_TYPE),
+		__print_symbolic(__entry->result, MF_ACTION_RESULT)
+	)
+);
+#endif /* _TRACE_MEMORY_FAILURE_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/mm/Kconfig b/mm/Kconfig
index d548976d0e0a..bd0ea5454af8 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -738,11 +738,10 @@ config ARCH_SUPPORTS_MEMORY_FAILURE
 
 config MEMORY_FAILURE
 	depends on MMU
 	depends on ARCH_SUPPORTS_MEMORY_FAILURE
 	bool "Enable recovery from hardware memory errors"
-	select RAS
 	select INTERVAL_TREE
 	help
 	  Enables code to recover from some memory failures on systems
 	  with MCA recovery. This allows a system to continue running
 	  even when some of its memory has uncorrected errors. This requires
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index 7f908ad795ad..fbc5a01260c8 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -59,13 +59,16 @@
 #include <linux/kfifo.h>
 #include <linux/ratelimit.h>
 #include <linux/pagewalk.h>
 #include <linux/shmem_fs.h>
 #include <linux/sysctl.h>
+
+#define CREATE_TRACE_POINTS
+#include <trace/events/memory-failure.h>
+
 #include "swap.h"
 #include "internal.h"
-#include "ras/ras_event.h"
 
 static int sysctl_memory_failure_early_kill __read_mostly;
 
 static int sysctl_memory_failure_recovery __read_mostly = 1;
 
-- 
2.51.0


^ permalink raw reply related

* Re: [PATCH v3 19/21] scsi: fnic: Switch to use %ptSp
From: Petr Mladek @ 2025-11-19 10:08 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Corey Minyard, Christian König, Dr. David Alan Gilbert,
	Alex Deucher, Thomas Zimmermann, Dmitry Baryshkov, Rob Clark,
	Matthew Brost, Ulf Hansson, Aleksandr Loktionov, Vitaly Lifshits,
	Manivannan Sadhasivam, Niklas Cassel, Calvin Owens,
	Vadim Fedorenko, Sagi Maimon, Martin K. Petersen,
	Karan Tilak Kumar, Hans Verkuil, Casey Schaufler, Steven Rostedt,
	Viacheslav Dubeyko, Max Kellermann, linux-doc, linux-kernel,
	openipmi-developer, linux-media, dri-devel, linaro-mm-sig,
	amd-gfx, linux-arm-msm, freedreno, intel-xe, linux-mmc, netdev,
	intel-wired-lan, linux-pci, linux-s390, linux-scsi, linux-staging,
	ceph-devel, linux-trace-kernel, Rasmus Villemoes,
	Sergey Senozhatsky, Jonathan Corbet, Sumit Semwal,
	Gustavo Padovan, David Airlie, Simona Vetter, Maarten Lankhorst,
	Maxime Ripard, Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang,
	Sean Paul, Marijn Suijten, Konrad Dybcio, Lucas De Marchi,
	Thomas Hellström, Rodrigo Vivi, Vladimir Oltean, Andrew Lunn,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Tony Nguyen, Przemek Kitszel, Krzysztof Wilczyński,
	Kishon Vijay Abraham I, Bjorn Helgaas, Rodolfo Giometti,
	Jonathan Lemon, Richard Cochran, Stefan Haberland, Jan Hoeppner,
	Heiko Carstens, Vasily Gorbik, Alexander Gordeev,
	Christian Borntraeger, Sven Schnelle, Satish Kharat,
	Sesidhar Baddela, James E.J. Bottomley, Mauro Carvalho Chehab,
	Greg Kroah-Hartman, Xiubo Li, Ilya Dryomov, Masami Hiramatsu,
	Mathieu Desnoyers, Andrew Morton
In-Reply-To: <20251113150217.3030010-20-andriy.shevchenko@linux.intel.com>

On Thu 2025-11-13 15:32:33, Andy Shevchenko wrote:
> Use %ptSp instead of open coded variants to print content of
> struct timespec64 in human readable format.

I was about to commit the changes into printk/linux.git and
found a mistake during the final double check, see below.

> diff --git a/drivers/scsi/fnic/fnic_trace.c b/drivers/scsi/fnic/fnic_trace.c
> index cdc6b12b1ec2..0a849a195a8e 100644
> --- a/drivers/scsi/fnic/fnic_trace.c
> +++ b/drivers/scsi/fnic/fnic_trace.c
> @@ -215,30 +213,26 @@ int fnic_get_stats_data(struct stats_debug_info *debug,
>  {
>  	int len = 0;
>  	int buf_size = debug->buf_size;
> -	struct timespec64 val1, val2;
> +	struct timespec64 val, val1, val2;
>  	int i = 0;
>  
> -	ktime_get_real_ts64(&val1);
> +	ktime_get_real_ts64(&val);
>  	len = scnprintf(debug->debug_buffer + len, buf_size - len,
>  		"------------------------------------------\n"
>  		 "\t\tTime\n"
>  		"------------------------------------------\n");
>  
> +	val1 = timespec64_sub(val, stats->stats_timestamps.last_reset_time);
> +	val2 = timespec64_sub(val, stats->stats_timestamps.last_read_time);
>  	len += scnprintf(debug->debug_buffer + len, buf_size - len,
> -		"Current time :          [%lld:%ld]\n"
> -		"Last stats reset time:  [%lld:%09ld]\n"
> -		"Last stats read time:   [%lld:%ld]\n"
> -		"delta since last reset: [%lld:%ld]\n"
> -		"delta since last read:  [%lld:%ld]\n",
> -	(s64)val1.tv_sec, val1.tv_nsec,
> -	(s64)stats->stats_timestamps.last_reset_time.tv_sec,
> -	stats->stats_timestamps.last_reset_time.tv_nsec,
> -	(s64)stats->stats_timestamps.last_read_time.tv_sec,
> -	stats->stats_timestamps.last_read_time.tv_nsec,
> -	(s64)timespec64_sub(val1, stats->stats_timestamps.last_reset_time).tv_sec,
> -	timespec64_sub(val1, stats->stats_timestamps.last_reset_time).tv_nsec,
> -	(s64)timespec64_sub(val1, stats->stats_timestamps.last_read_time).tv_sec,
> -	timespec64_sub(val1, stats->stats_timestamps.last_read_time).tv_nsec);
> +			 "Current time :          [%ptSp]\n"
> +			 "Last stats reset time:  [%ptSp]\n"
> +			 "Last stats read time:   [%ptSp]\n"
> +			 "delta since last reset: [%ptSp]\n"
> +			 "delta since last read:  [%ptSp]\n",

Both delta times are printed at the end.

> +			 &val,
> +			 &stats->stats_timestamps.last_reset_time, &val1,
> +			 &stats->stats_timestamps.last_read_time, &val2);

I think that this should be:

			 &stats->stats_timestamps.last_reset_time,
			 &stats->stats_timestamps.last_read_time,
			 &val1, &val2);

>  	stats->stats_timestamps.last_read_time = val1;

The original code stored the current time in "val1". This should be:

	stats->stats_timestamps.last_read_time = val;

> @@ -416,8 +410,8 @@ int fnic_get_stats_data(struct stats_debug_info *debug,
>  	jiffies_to_timespec64(stats->misc_stats.last_ack_time, &val2);

Just for record. Another values are stored into @val1 and @val2 at
this point.

>  	len += scnprintf(debug->debug_buffer + len, buf_size - len,
> -		  "Last ISR time: %llu (%8llu.%09lu)\n"
> -		  "Last ACK time: %llu (%8llu.%09lu)\n"
> +		  "Last ISR time: %llu (%ptSp)\n"
> +		  "Last ACK time: %llu (%ptSp)\n"
>  		  "Max ISR jiffies: %llu\n"
>  		  "Max ISR time (ms) (0 denotes < 1 ms): %llu\n"
>  		  "Corr. work done: %llu\n"
> @@ -437,10 +431,8 @@ int fnic_get_stats_data(struct stats_debug_info *debug,
>  		  "Number of rport not ready: %lld\n"
>  		 "Number of receive frame errors: %lld\n"
>  		 "Port speed (in Mbps): %lld\n",
> -		  (u64)stats->misc_stats.last_isr_time,
> -		  (s64)val1.tv_sec, val1.tv_nsec,
> -		  (u64)stats->misc_stats.last_ack_time,
> -		  (s64)val2.tv_sec, val2.tv_nsec,
> +		  (u64)stats->misc_stats.last_isr_time, &val1,
> +		  (u64)stats->misc_stats.last_ack_time, &val2,

So, this is correct!

>  		  (u64)atomic64_read(&stats->misc_stats.max_isr_jiffies),
>  		  (u64)atomic64_read(&stats->misc_stats.max_isr_time_ms),
>  		  (u64)atomic64_read(&stats->misc_stats.corr_work_done),


Now, I think that there is no need to resend the entire huge patchset.

I could either fix this when comitting or commit the rest and
you could send only this patch for review.

Best Regards,
Petr

PS: All other patches look good. Well, nobody acked 7th patch yet.
    But I think that the change is pretty straightforward and
    we could do it even without an ack.

^ permalink raw reply

* Re: [PATCH 2/2] mm/khugepaged: return EAGAIN for transient dirty pages in MADV_COLLAPSE
From: Garg, Shivank @ 2025-11-19 10:25 UTC (permalink / raw)
  To: Lorenzo Stoakes
  Cc: Andrew Morton, David Hildenbrand, Zi Yan, Baolin Wang,
	Liam R . Howlett, Nico Pache, Ryan Roberts, Dev Jain, Barry Song,
	Lance Yang, Steven Rostedt, Masami Hiramatsu, Mathieu Desnoyers,
	Zach O'Keefe, linux-mm, linux-kernel, linux-trace-kernel
In-Reply-To: <67325651-b7d5-40d0-a9f1-3009b61c8d3a@lucifer.local>



On 11/10/2025 5:26 PM, Lorenzo Stoakes wrote:
> Please, please, please send a cover letter when there's > 1 patch :)
> 
> This 2/2 replying to 1/2 is a pain (not your fault that perhaps you're not aware
> of typical mm series style but FYI :P)
> 
Sure, will do this in V2 (posting today).

> Also there is some tiny conflict on khugepaged.c in mm-new, but it's literally 1
> #include so probably nothing to worry about.
> > On Mon, Nov 10, 2025 at 11:32:55AM +0000, Shivank Garg wrote:
>> When MADV_COLLAPSE encounters dirty file-backed pages, it currently
>> returns -EINVAL, this is misleading as EINVAL suggests invalid arguments,
>> whereas dirty pages are a transient condition that may resolve on retry.
>>
>> Introduce SCAN_PAGE_DIRTY and map it to -EAGAIN. For khugepaged, this
>> is harmless as it will revisit the range after async writeback completes.
>>
>> Signed-off-by: Shivank Garg <shivankg@amd.com>
> 
> With comments below addressed, LGTM so:
> 
> Reviewed-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>

Thank you for the review. 
> 
>> ---
>>  include/trace/events/huge_memory.h | 3 ++-
>>  mm/khugepaged.c                    | 4 +++-
>>  2 files changed, 5 insertions(+), 2 deletions(-)
>>
>> diff --git a/include/trace/events/huge_memory.h b/include/trace/events/huge_memory.h
>> index dd94d14a2427..9014a9bbe64c 100644
>> --- a/include/trace/events/huge_memory.h
>> +++ b/include/trace/events/huge_memory.h
>> @@ -38,7 +38,8 @@
>>  	EM( SCAN_PAGE_HAS_PRIVATE,	"page_has_private")		\
>>  	EM( SCAN_STORE_FAILED,		"store_failed")			\
>>  	EM( SCAN_COPY_MC,		"copy_poisoned_page")		\
>> -	EMe(SCAN_PAGE_FILLED,		"page_filled")
>> +	EM(SCAN_PAGE_FILLED,		"page_filled")			\
>> +	EMe(SCAN_PAGE_DIRTY,		"page_dirty")
>>
>>  #undef EM
>>  #undef EMe
>> diff --git a/mm/khugepaged.c b/mm/khugepaged.c
>> index d08ed6eb9ce1..7df329c9c87d 100644
>> --- a/mm/khugepaged.c
>> +++ b/mm/khugepaged.c
>> @@ -60,6 +60,7 @@ enum scan_result {
>>  	SCAN_STORE_FAILED,
>>  	SCAN_COPY_MC,
>>  	SCAN_PAGE_FILLED,
>> +	SCAN_PAGE_DIRTY,
> 
> it feels like a lot to add a scan result for this, but I mean... probably
> actually valid.
> 
>>  };
>>
>>  #define CREATE_TRACE_POINTS
>> @@ -1967,7 +1968,7 @@ static int collapse_file(struct mm_struct *mm, unsigned long addr,
>>  				 */
>>  				xas_unlock_irq(&xas);
>>  				filemap_flush(mapping);
>> -				result = SCAN_FAIL;
>> +				result = SCAN_PAGE_DIRTY;
>>  				goto xa_unlocked;
> 
> Hmmm shmem dirty is going to be weird but we also have:
> 
> 		if (!is_shmem && (folio_test_dirty(folio) ||
> 				  folio_test_writeback(folio))) {
> 			/*
> 			 * khugepaged only works on read-only fd, so this
> 			 * folio is dirty because it hasn't been flushed
> 			 * since first write.
> 			 */
> 			result = SCAN_FAIL;
> 			goto out_unlock;
> 		}
> 
> It's weird though, why would we have writeback, surely handled by swap, and
> won't it be like anon, i.e. pretty well always dirty? This comment seems
> copy/pasta wrong.
> 
> We do need to at least mention in commit message that shmem is explicitly
> excluded.
> 

Looking at the code, the dirty/writeback checks where I'm making changes 
are all in the !is_shmem branch, so it only affects regular files, not
shmem.

Should I mention in the commit message that these changes are limited
to regular files and don't affect shmem?

I'm not sure I fully understood your concern on shmem. Could you please elaborate?

Thanks,
Shivank


> 
>>  			} else if (folio_test_writeback(folio)) {
>>  				xas_unlock_irq(&xas);
>> @@ -2747,6 +2748,7 @@ static int madvise_collapse_errno(enum scan_result r)
>>  	case SCAN_PAGE_LRU:
>>  	case SCAN_DEL_PAGE_LRU:
>>  	case SCAN_PAGE_FILLED:
>> +	case SCAN_PAGE_DIRTY:
>>  		return -EAGAIN;
>>  	/*
>>  	 * Other: Trying again likely not to succeed / error intrinsic to
>> --
>> 2.43.0
>>


^ permalink raw reply

* Re: [PATCH v3 19/21] scsi: fnic: Switch to use %ptSp
From: Andy Shevchenko @ 2025-11-19 10:26 UTC (permalink / raw)
  To: Petr Mladek
  Cc: Corey Minyard, Christian König, Dr. David Alan Gilbert,
	Alex Deucher, Thomas Zimmermann, Dmitry Baryshkov, Rob Clark,
	Matthew Brost, Ulf Hansson, Aleksandr Loktionov, Vitaly Lifshits,
	Manivannan Sadhasivam, Niklas Cassel, Calvin Owens,
	Vadim Fedorenko, Sagi Maimon, Martin K. Petersen,
	Karan Tilak Kumar, Hans Verkuil, Casey Schaufler, Steven Rostedt,
	Viacheslav Dubeyko, Max Kellermann, linux-doc, linux-kernel,
	openipmi-developer, linux-media, dri-devel, linaro-mm-sig,
	amd-gfx, linux-arm-msm, freedreno, intel-xe, linux-mmc, netdev,
	intel-wired-lan, linux-pci, linux-s390, linux-scsi, linux-staging,
	ceph-devel, linux-trace-kernel, Rasmus Villemoes,
	Sergey Senozhatsky, Jonathan Corbet, Sumit Semwal,
	Gustavo Padovan, David Airlie, Simona Vetter, Maarten Lankhorst,
	Maxime Ripard, Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang,
	Sean Paul, Marijn Suijten, Konrad Dybcio, Lucas De Marchi,
	Thomas Hellström, Rodrigo Vivi, Vladimir Oltean, Andrew Lunn,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Tony Nguyen, Przemek Kitszel, Krzysztof Wilczyński,
	Kishon Vijay Abraham I, Bjorn Helgaas, Rodolfo Giometti,
	Jonathan Lemon, Richard Cochran, Stefan Haberland, Jan Hoeppner,
	Heiko Carstens, Vasily Gorbik, Alexander Gordeev,
	Christian Borntraeger, Sven Schnelle, Satish Kharat,
	Sesidhar Baddela, James E.J. Bottomley, Mauro Carvalho Chehab,
	Greg Kroah-Hartman, Xiubo Li, Ilya Dryomov, Masami Hiramatsu,
	Mathieu Desnoyers, Andrew Morton
In-Reply-To: <aR2XAYWTEgMZu_Mx@pathway.suse.cz>

On Wed, Nov 19, 2025 at 11:08:01AM +0100, Petr Mladek wrote:
> On Thu 2025-11-13 15:32:33, Andy Shevchenko wrote:
> > Use %ptSp instead of open coded variants to print content of
> > struct timespec64 in human readable format.
> 
> I was about to commit the changes into printk/linux.git and
> found a mistake during the final double check, see below.
> 
> > diff --git a/drivers/scsi/fnic/fnic_trace.c b/drivers/scsi/fnic/fnic_trace.c
> > index cdc6b12b1ec2..0a849a195a8e 100644
> > --- a/drivers/scsi/fnic/fnic_trace.c
> > +++ b/drivers/scsi/fnic/fnic_trace.c
> > @@ -215,30 +213,26 @@ int fnic_get_stats_data(struct stats_debug_info *debug,
> >  {
> >  	int len = 0;
> >  	int buf_size = debug->buf_size;
> > -	struct timespec64 val1, val2;
> > +	struct timespec64 val, val1, val2;
> >  	int i = 0;
> >  
> > -	ktime_get_real_ts64(&val1);
> > +	ktime_get_real_ts64(&val);
> >  	len = scnprintf(debug->debug_buffer + len, buf_size - len,
> >  		"------------------------------------------\n"
> >  		 "\t\tTime\n"
> >  		"------------------------------------------\n");
> >  
> > +	val1 = timespec64_sub(val, stats->stats_timestamps.last_reset_time);
> > +	val2 = timespec64_sub(val, stats->stats_timestamps.last_read_time);
> >  	len += scnprintf(debug->debug_buffer + len, buf_size - len,
> > -		"Current time :          [%lld:%ld]\n"
> > -		"Last stats reset time:  [%lld:%09ld]\n"
> > -		"Last stats read time:   [%lld:%ld]\n"
> > -		"delta since last reset: [%lld:%ld]\n"
> > -		"delta since last read:  [%lld:%ld]\n",
> > -	(s64)val1.tv_sec, val1.tv_nsec,
> > -	(s64)stats->stats_timestamps.last_reset_time.tv_sec,
> > -	stats->stats_timestamps.last_reset_time.tv_nsec,
> > -	(s64)stats->stats_timestamps.last_read_time.tv_sec,
> > -	stats->stats_timestamps.last_read_time.tv_nsec,
> > -	(s64)timespec64_sub(val1, stats->stats_timestamps.last_reset_time).tv_sec,
> > -	timespec64_sub(val1, stats->stats_timestamps.last_reset_time).tv_nsec,
> > -	(s64)timespec64_sub(val1, stats->stats_timestamps.last_read_time).tv_sec,
> > -	timespec64_sub(val1, stats->stats_timestamps.last_read_time).tv_nsec);
> > +			 "Current time :          [%ptSp]\n"
> > +			 "Last stats reset time:  [%ptSp]\n"
> > +			 "Last stats read time:   [%ptSp]\n"
> > +			 "delta since last reset: [%ptSp]\n"
> > +			 "delta since last read:  [%ptSp]\n",
> 
> Both delta times are printed at the end.
> 
> > +			 &val,
> > +			 &stats->stats_timestamps.last_reset_time, &val1,
> > +			 &stats->stats_timestamps.last_read_time, &val2);
> 
> I think that this should be:
> 
> 			 &stats->stats_timestamps.last_reset_time,
> 			 &stats->stats_timestamps.last_read_time,
> 			 &val1, &val2);
> 
> >  	stats->stats_timestamps.last_read_time = val1;
> 
> The original code stored the current time in "val1". This should be:
> 
> 	stats->stats_timestamps.last_read_time = val;
> 
> > @@ -416,8 +410,8 @@ int fnic_get_stats_data(struct stats_debug_info *debug,
> >  	jiffies_to_timespec64(stats->misc_stats.last_ack_time, &val2);
> 
> Just for record. Another values are stored into @val1 and @val2 at
> this point.
> 
> >  	len += scnprintf(debug->debug_buffer + len, buf_size - len,
> > -		  "Last ISR time: %llu (%8llu.%09lu)\n"
> > -		  "Last ACK time: %llu (%8llu.%09lu)\n"
> > +		  "Last ISR time: %llu (%ptSp)\n"
> > +		  "Last ACK time: %llu (%ptSp)\n"
> >  		  "Max ISR jiffies: %llu\n"
> >  		  "Max ISR time (ms) (0 denotes < 1 ms): %llu\n"
> >  		  "Corr. work done: %llu\n"
> > @@ -437,10 +431,8 @@ int fnic_get_stats_data(struct stats_debug_info *debug,
> >  		  "Number of rport not ready: %lld\n"
> >  		 "Number of receive frame errors: %lld\n"
> >  		 "Port speed (in Mbps): %lld\n",
> > -		  (u64)stats->misc_stats.last_isr_time,
> > -		  (s64)val1.tv_sec, val1.tv_nsec,
> > -		  (u64)stats->misc_stats.last_ack_time,
> > -		  (s64)val2.tv_sec, val2.tv_nsec,
> > +		  (u64)stats->misc_stats.last_isr_time, &val1,
> > +		  (u64)stats->misc_stats.last_ack_time, &val2,
> 
> So, this is correct!
> 
> >  		  (u64)atomic64_read(&stats->misc_stats.max_isr_jiffies),
> >  		  (u64)atomic64_read(&stats->misc_stats.max_isr_time_ms),
> >  		  (u64)atomic64_read(&stats->misc_stats.corr_work_done),
> 
> 
> Now, I think that there is no need to resend the entire huge patchset.
> 
> I could either fix this when comitting or commit the rest and
> you could send only this patch for review.

Thank you for the thoroughly done review, I changed that patch between the
versions and the problem is that for printf() specifiers (extensions) we do not
have an automatic type checking. We starve for a GCC plugin for that, yeah...

In any case, if you fold your changes in, I will appreciate that!
Otherwise it's also fine with me to send a patch separately later on.

> PS: All other patches look good. Well, nobody acked 7th patch yet.
>     But I think that the change is pretty straightforward and
>     we could do it even without an ack.

This is my understanding as well. It changes the output, but that output is
debug anyway. So I don't expect breakage of anything we have an obligation
to keep working.

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply

* Re: [PATCH v12 mm-new 12/15] khugepaged: Introduce mTHP collapse support
From: Lorenzo Stoakes @ 2025-11-19 11:53 UTC (permalink / raw)
  To: Nico Pache
  Cc: linux-kernel, linux-trace-kernel, linux-mm, linux-doc, david, ziy,
	baolin.wang, Liam.Howlett, ryan.roberts, dev.jain, corbet,
	rostedt, mhiramat, mathieu.desnoyers, akpm, baohua, willy, peterx,
	wangkefeng.wang, usamaarif642, sunnanyong, vishal.moola,
	thomas.hellstrom, yang, kas, aarcange, raquini, anshuman.khandual,
	catalin.marinas, tiwai, will, dave.hansen, jack, cl, jglisse,
	surenb, zokeefe, hannes, rientjes, mhocko, rdunlap, hughd,
	richard.weiyang, lance.yang, vbabka, rppt, jannh, pfalcato
In-Reply-To: <20251022183717.70829-13-npache@redhat.com>

On Wed, Oct 22, 2025 at 12:37:14PM -0600, Nico Pache wrote:
> During PMD range scanning, track occupied pages in a bitmap. If mTHPs are
> enabled we remove the restriction of max_ptes_none during the scan phase
> to avoid missing potential mTHP candidates.

It's a bit odd to open the commit message with a very specific
implementation detail, I think we should instead open with a broad
description of what we intend here, e.g. to permit mTHP collapse, before:

- Discussing the algorithm used (in more detail than below!)
- How and under what circumstances this algorithm is invoked
- (Mention MADV_COLLAPSE not supporting mTHP as of yet)
- THEN super-specific details like this.

>
> Implement collapse_scan_bitmap() to perform binary recursion on the bitmap
> and determine the best eligible order for the collapse. A stack struct is
> used instead of traditional recursion. The algorithm splits the bitmap
> into smaller chunks to find the best fit mTHP.  max_ptes_none is scaled by
> the attempted collapse order to determine how "full" an order must be
> before being considered for collapse.

I feel this is a _very_ brief description of a complicated algorithm. I
think we should go into a lot more detail here. 'Binary recursion' is pretty
hand-wavey, and you go from hand waving that to being super-specific about
max_ptes_none before handwaving about 'fullness' of an order.

All in all I find it super confusing - so I think you need to take a step
back and 'explain it to me like I'm 5' here :)

>
> Once we determine what mTHP sizes fits best in that PMD range a collapse
> is attempted. A minimum collapse order of 2 is used as this is the lowest
> order supported by anon memory.

I don't know what 'lowest order supported by anon memory' means?

I guess really this is the minimum order contptes support for arm64 right?

>
> mTHP collapses reject regions containing swapped out or shared pages.
> This is because adding new entries can lead to new none pages, and these
> may lead to constant promotion into a higher order (m)THP. A similar
> issue can occur with "max_ptes_none > HPAGE_PMD_NR/2" due to a collapse
> introducing at least 2x the number of pages, and on a future scan will
> satisfy the promotion condition once again. This issue is prevented via
> the collapse_allowable_orders() function.

Obviously this has been discussed to death, but you should update this to
reflect the decided upon course (0, 511 + warning, etc.).

>
> Currently madv_collapse is not supported and will only attempt PMD
> collapse.

Good to highlight this.

>
> We can also remove the check for is_khugepaged inside the PMD scan as
> the collapse_max_ptes_none() function handles this logic now.

Again we're kind of leaping from mega handwaving to super-specific details
:) let's make it all a lot more specific + clear, and then put the really
niche details like this at the end of the commit msg (I mean this one is
fine where it is ofc as a result :)

>
> Signed-off-by: Nico Pache <npache@redhat.com>
> ---
>  include/linux/khugepaged.h |   2 +
>  mm/khugepaged.c            | 128 ++++++++++++++++++++++++++++++++++---
>  2 files changed, 122 insertions(+), 8 deletions(-)
>
> diff --git a/include/linux/khugepaged.h b/include/linux/khugepaged.h
> index eb1946a70cff..179ce716e769 100644
> --- a/include/linux/khugepaged.h
> +++ b/include/linux/khugepaged.h
> @@ -1,6 +1,8 @@
>  /* SPDX-License-Identifier: GPL-2.0 */
>  #ifndef _LINUX_KHUGEPAGED_H
>  #define _LINUX_KHUGEPAGED_H
> +#define KHUGEPAGED_MIN_MTHP_ORDER	2
> +#define MAX_MTHP_BITMAP_STACK	(1UL << (ilog2(MAX_PTRS_PER_PTE) - KHUGEPAGED_MIN_MTHP_ORDER))

This is an internal implementation detail, I don't think we need this in a
header do we? I think this define should be in khugepaged.c.

Also this is a really fiddly and confusing value, I don't think it's a good idea
to just put this here without explanation.

It's not even clear what it is. I'd probably rename it to MTHP_STACK_SIZE?

We need a comment that explains how you're deriving this, something like:

/*
 * In order to determine mTHP order, we consider every possible mTHP size
 * starting with MAX_PTRS_PER_PTE PTE entries and stopping at
 * 2^KHUGEPAGED_MIN_THP_ORDER.
 *
 * We store (offset, order) pairs on the stack to do so, each describing a
 * candidate mTHP collapse.
 *
 * For each (offset, order) candidate mTHP range that we consider, we must
 * also consider candiate mTHPs at (offset, order - 1), and (offset + (1 <<
 * order), order - 1).
 *
 *
 * This is because each order can be split into two (an order expresses the
 * power-of-two size), so we examine each half of the next lower order
 * mTHP:
 *
 *                offset   mid_offset
 *                  .          |
 *                  .          v
 *  |---------------.-------------------|
 *  |           PTE page table          |
 *  |---------------.-------------------|
 *                   <--------><-------->
 *                     order-1   order-1
 *
 * Given we must consider the range of KHUGEPAGED_MIN_MTHP_ORDER to
 * MAX_PTRS_PER_PTE number of PTE entries, this is the same as saying we
 * must consider KHUGEPAGED_MIN_MTHP_ORDER to lg2(MAX_PTRS_PER_PTE) mTHP
 * orders.
 *
 * As we must consider 2 possible mTHP ranges for each order, this requires
 * our stack to be 2^n, where n is the number of orders we must consider.
 *
 * And thus MTHP_STACK_SIZE is 2^(lg2(MAX_PTRS_PER_PTE) -
 * KHUGEPAGED_MIN_MTHP_ORDER).
 */

This may seem (very) long-winded, but this is all really non-obvious.

You can additionally rephrase this and utilise it in the commit message,
description of the iterative recursion function and possibly elsewhere to
describe the algorithm more clearly.

In fact, since this should really be declared in khugepaged.c, and since
you can place it just before the mthp collapse function, you could expand
this to describe the algorithm as a whole and simply put the define and the
function immediately next to each other after the comment?

>
>  #include <linux/mm.h>
>
> diff --git a/mm/khugepaged.c b/mm/khugepaged.c
> index 89a105124790..e2319bfd0065 100644
> --- a/mm/khugepaged.c
> +++ b/mm/khugepaged.c
> @@ -93,6 +93,11 @@ static DEFINE_READ_MOSTLY_HASHTABLE(mm_slots_hash, MM_SLOTS_HASH_BITS);
>
>  static struct kmem_cache *mm_slot_cache __ro_after_init;
>
> +struct scan_bit_state {

Scan bit state is a bit of a weird name. Scanning what? What bit? State is
kind of implied?

struct order_offset_pair?

struct mthp_range?

> +	u8 order;
> +	u16 offset;

Real mega nit, but feels more natural to put offset first here. As
(position, size) seems more naturally the way to view this than (size,
position).

> +};
> +

Also needs comments...? Order of what? Offset in what?

>  struct collapse_control {
>  	bool is_khugepaged;
>
> @@ -101,6 +106,13 @@ struct collapse_control {
>
>  	/* nodemask for allocation fallback */
>  	nodemask_t alloc_nmask;
> +
> +	/*
> +	 * bitmap used to collapse mTHP sizes.
> +	 */

Nit but this should be on one line /* Bitmap used to collapse mTHP sizes */.

But we're not storing sizes though are we? And we're declaring two bitmaps?

> +	 DECLARE_BITMAP(mthp_bitmap, HPAGE_PMD_NR);

Really this is more of a PTE table bitmap but probably fine to call it this.

> +	 DECLARE_BITMAP(mthp_bitmap_mask, HPAGE_PMD_NR);

You've added random whitespace after the tab twice here? [tab][space]DECLARE_...

> +	struct scan_bit_state mthp_bitmap_stack[MAX_MTHP_BITMAP_STACK];
>  };
>
>  /**
> @@ -1357,6 +1369,85 @@ static int collapse_huge_page(struct mm_struct *mm, unsigned long pmd_address,
>  	return result;
>  }
>
> +static void push_mthp_bitmap_stack(struct collapse_control *cc, int *top,
> +				   u8 order, u16 offset)

Not sure we need to say mthp_bitmap_stack everywhere. This is a local
static function we can be a little more succinct.

mthp_stack_push()?

> +{
> +	cc->mthp_bitmap_stack[++*top] = (struct scan_bit_state)
> +		{ order, offset };

This feels rather difficult to read, cc->mthp_bitmap_stack[++*top] in
particular is rather too succinct.

This would be better more broken out, e.g.:

static void mthp_stack_push(struct collapse_control *cc, int *sizep,
	    u8 order, u16 offset)
{
	const int size = *sizep;
	struct scan_bit_state *stack = &cc->mthp_bitmap_stack[size];

	VM_WARN_ON_ONCE(idx >= MAX_MTHP_BITMAP_STACK);
	stack->order = order;
	stack->offset = offset;
	*sizep++;
}

(Note this requires the change I suggest below re: not defaulting top to -1
but instead renaming it to stack_size and starting at 0, see below).

Re: below comment having pop as a helper too, that can be:

static struct scan_bit_state mthp_stack_pop(struct collapse_control *cc,
		int *sizep)
{
	const int size = *sizep;

	VM_WARN_ON_ONCE(size <= 0);
	*sizep--;
	return cc->mthp_bitmap_stack[size - 1];
}

> +}
> +
> +/*
> + * collapse_scan_bitmap() consumes the bitmap that is generated during
> + * collapse_scan_pmd() to determine what regions and mTHP orders fit best.
> + *
> + * Each bit in the bitmap represents a single occupied (!none/zero) page.

In which bitmap? There are 2 that are declared. Be specific - cc->mthp_bitmap.

> + * A stack structure cc->mthp_bitmap_stack is used to check different regions

> + * of the bitmap for collapse eligibility. We start at the PMD order and
> + * check if it is eligible for collapse; if not, we add two entries to the

I questioned this since you start at HPAGE_PMD_ORDER -
KHUGEPAGED_MIN_MTHP_ORDER, but then realised you're intentionally
offsetting like that.

See comments below about changing this.

> + * stack at a lower order to represent the left and right halves of the region.
> + *
> + * For each region, we calculate the number of set bits and compare it
> + * against a threshold derived from collapse_max_ptes_none(). A region is
> + * eligible if the number of set bits exceeds this threshold.
> + */

I think we could be clearer here. Something like:

...
 * stack at a lower order to represent the left and right halves of the
 * portion of the PTE page table we are examining.
 *

 * For each of these, we determine how many PTE entries are occupied in the
 * range of PTE entries we propose to collapse, then compare this to the
 * number of PTE entries which would need to be set for a collapse to be
 * permitted at that order (accounting for max_ptes_none).
 *
 * If a collapse is permissible, we attempt to perform one. We do so for
 * every possible mTHP in the PTE page table.
 */

> +static int collapse_scan_bitmap(struct mm_struct *mm, unsigned long address,

Really inconsistent naming going on here, we're collapsing and scanning and
what's the bitmap?

How about mthp_collapse()?

> +		int referenced, int unmapped, struct collapse_control *cc,
> +		bool *mmap_locked, unsigned long enabled_orders)
> +{
> +	u8 order, next_order;
> +	u16 offset, mid_offset;
> +	int num_chunks;
> +	int bits_set, threshold_bits;
> +	int top = -1;

This seems unnecessary and confusing. Just start at 0 and treat this as the
exclusive end of the stack.

You can rename this stack_size to make that clear. Have commented above
about adjustments to push function and introducing pop helper.


> +	int collapsed = 0;
> +	int ret;
> +	struct scan_bit_state state;
> +	unsigned int max_none_ptes;

Everywhere else we say max_ptes_none, let's maintain that convention here
please.

> +
> +	push_mthp_bitmap_stack(cc, &top, HPAGE_PMD_ORDER - KHUGEPAGED_MIN_MTHP_ORDER, 0);

See below re: order here, we should change this.

> +
> +	while (top >= 0) {
> +		state = cc->mthp_bitmap_stack[top--];

I hate that we have a push helper but then do pop manually. See above.

> +		order = state.order + KHUGEPAGED_MIN_MTHP_ORDER;

OK so now the order isn't state.order but is instead state.order +
KHUGEPAGED_MIN_MTHP_ORDER? :/ this is extremely confusing.

We shouldn't call this field order if you're doing a hack where state.order
isn't the order but instead is order - KHUGEPAGED_MIN_MTHP_ORDER.

Just have state.order be the actual order? And change the below condition
as mentioned there.

> +		offset = state.offset;
> +		num_chunks = 1UL << order;

What's a chunk? You do need to clarify these things. This is a new term not
used elsewhere in THP code as far as I can tell?

This is the number of pte entries no?

nr_entries? nr_pte_entries?

> +
> +		/* Skip mTHP orders that are not enabled */

Note we're also considering PMD here :) Probably we can just delete this
comment, the code below makes it clear what you're doing.

> +		if (!test_bit(order, &enabled_orders))
> +			goto next_order;
> +
> +		max_none_ptes = collapse_max_ptes_none(order, !cc->is_khugepaged);

OK so this is going to be scaled to order.

> +
> +		/* Calculate weight of the range */

What's the weight of a range? This isn't a very helpful comment. You're
counting the Hamming weight or much more clearly - the number of set bits.

So it seems you're simply counting the number of bits you have accumulated
so far in cc->mthp_bitmap, adding in the latest offset.

So I'd say add a comment saying something like:

/*
 * Determine how many PTE entries are populated in the range in which we
 * propose to collapse this mTHP.
 */

> +		bitmap_zero(cc->mthp_bitmap_mask, HPAGE_PMD_NR);
> +		bitmap_set(cc->mthp_bitmap_mask, offset, num_chunks);
> +		bits_set = bitmap_weight_and(cc->mthp_bitmap,

I think this variable name is pretty horrible, we don't care that it's the
number of bits set, we care about what it _means_ - that is the number of
PTE occupied entries.

So nr_occupied_pte_entries? Or nr_occupied_ptes?

> +					     cc->mthp_bitmap_mask, HPAGE_PMD_NR);

Frustrating there isn't a bitmap_weight_offset() or something, as you could
do that in one go then...

I think this could be made clearer by separating out the gnarly bitmap
stuff into a helper function:

static int mthp_nr_occupied_pte_entries(struct collapse_control *cc,
		struct scan_bit_state state)
{
	const int nr_pte_entries = 1 << state.order;

	/* Setup cc->mthp_bitmap_mask to contain mask for candidate mTHP. */
	bitmap_zero(cc->mthp_bitmap_mask, HPAGE_PMD_NR);
	bitmap_set(cc->mthp_bitmap_mask, state.offset, nr_pte_entries);
	/* Mask against actually occupied PTE entries in PTE table. */
	return bitmap_weight_and(cc->mthp_bitmap,
				 cc->mthp_bitmap_mask, HPAGE_PMD_NR);
}

> +
> +		threshold_bits = (1UL << order) - max_none_ptes - 1;

We defined num_chunks to 1UL << order then don't use here? :)

I'm not sure we need this to be a separate value, and I don't think we need
the -1 either, which only confuses matter more.

How about just changing the below conditional to (assuming we've renamed
num_chunks to something sensible like nr_pte_entries and bits_set to
nr_occupied_pte_entries):

if (nr_occupied_pte_entries >= nr_pte_entries - max_none_ptes) {
	...
}

> +
> +		/* Check if the region is eligible based on the threshold */

Probalby don't need this comment with the change above.

> +		if (bits_set > threshold_bits) {
> +			ret = collapse_huge_page(mm, address, referenced,
> +						 unmapped, cc, mmap_locked,
> +						 order, offset);

We declare ret at the top of the function scope, then only use it
here. That's confusing and unnecessary, just declare it in block scope
here.

> +			if (ret == SCAN_SUCCEED) {
> +				collapsed += 1UL << order;

Again we have defined num_chunks or rather nr_pte_entries but then
open-code 1UL << order, let's just use the value we declared here.

> +				continue;

This is kinda subtle, we don't bother considering lower orders any longer
*in this range*, but do continue to consider mTHP collapse in other
portions of the PTE page table.

This shouldn't just be a 'continue' :) we need a comment here to explain
that.

E.g.:

	/*
	 * We have collapsed an mTHP in this range at the maximum order we
	 * could, so we do not push lower orders on to the stack.
	 */
	 continue;


> +			}
> +		}
> +
> +next_order:
> +		if (state.order > 0) {

This is a great example of how this is confusing by making state.order not
actually be the order but the order - KHUGEPAGED_MIN_MTHP_ORDER.

Just make the order correct and change this to > KHUGEPAGED_MIN_MTHP_ORDER.

> +			next_order = state.order - 1;

Not sure we should have a label and a variable be the same thing.

Also why are we decl'ing next_order at the top of the function but only using here?

Just declare this here, like:

	if (state.order > KHUGEPAGED_MIN_MTHP_ORDER) {
		const u16 new_order = state.order - 1;

		...
	}

> +			mid_offset = offset + (num_chunks / 2);
> +			push_mthp_bitmap_stack(cc, &top, next_order, mid_offset);
> +			push_mthp_bitmap_stack(cc, &top, next_order, offset);

I guess one subtlety that wouldn't be obvious at first glance is that
num_chunks (oh so badly needs a rename :) is a power-of-2 so we never get
weird 'what if num_chunks is odd' scenarios to worry about.

Probably doesn't really need a comment though. But this _does_ badly needs
an ASCII diagram :):

	/*
	 * The next lowest mTHP order possesses half the number of PTE
	 * entries of the current one. We therefore must consider both
	 * halves of the current mTHP:
	 *
	 *                offset   mid_offset
	 *                  .          |
	 *                  .          v
	 *  |---------------.-------------------|
	 *  |           PTE page table          |
	 *  |---------------.-------------------|
	 *                   <--------><-------->
	 *                     order-1   order-1
	 */

Since writing this I copied this above in another suggestion :P so you
could always say 'see comment above for details' or something.

> +		}
> +	}
> +	return collapsed;
> +}

I've commented this function to death here, but a few more things to note.

(BTW - I'm sorry I personally _hate_ repeated iterations of review when
there's stuff you could have commented in prior iterations BUT I think I
may end up having to once we respin due to the subtleties here.)

- I wonder if we could just use a helper struct to make this all a little
  easier. Perhaps as it's realtively short code not so necesary, but a bit
  horrid to pass around all these paramters all the time. Maybe something
  for later THP rework.

- Could we exit early if it's obvious that we won't be able to collapse due
  to max_ptes_none? I mean for one, we could at least check if the next
  lowest order is empty. If max_ptes_none was 511, then we would have
  already collapsed so can surely throw that out?

  I was thinking we could go 'upwards', starting with the lowest order and
  increasing order (essentially reverse things) then not collapsing until
  we can't collapse at a given order (so collapse at next lowest). That
  might be less efficient though.

- Given that we're going to be only permitting max_ptes_none of 0 and 511
  for mTHP to start with, maybe things can be simplified - either all bits
  have to 1 or we don't care what they are we attempt colalpse anyway?

  But then again, maybe it's worth having the generic algorithm in place
  for future flexibility? Thoughts?

- How much have you tested this? This is pretty subtle stuff... it _seems_
  correct to me logically, but this is crying out for some userland testing
  that exhaustively throws every possible permutation of state at this
  function and asserts it's all correct.

- Are we not missing a bunch of stat counts? Didn't we add a bunch but now
  are actually setting them? E.g. if we reject mTHP candidates due to
  pte_max_none?

> +
>  static int collapse_scan_pmd(struct mm_struct *mm,
>  			     struct vm_area_struct *vma,
>  			     unsigned long start_addr, bool *mmap_locked,
> @@ -1364,11 +1455,15 @@ static int collapse_scan_pmd(struct mm_struct *mm,
>  {
>  	pmd_t *pmd;
>  	pte_t *pte, *_pte;
> +	int i;
>  	int result = SCAN_FAIL, referenced = 0;
> -	int none_or_zero = 0, shared = 0;
> +	int none_or_zero = 0, shared = 0, nr_collapsed = 0;
>  	struct page *page = NULL;
> +	unsigned int max_ptes_none;

Correct spelling of this :)

>  	struct folio *folio = NULL;
>  	unsigned long addr;
> +	unsigned long enabled_orders;
> +	bool full_scan = true;
>  	spinlock_t *ptl;
>  	int node = NUMA_NO_NODE, unmapped = 0;
>
> @@ -1378,16 +1473,29 @@ static int collapse_scan_pmd(struct mm_struct *mm,
>  	if (result != SCAN_SUCCEED)
>  		goto out;
>
> +	bitmap_zero(cc->mthp_bitmap, HPAGE_PMD_NR);
>  	memset(cc->node_load, 0, sizeof(cc->node_load));
>  	nodes_clear(cc->alloc_nmask);
> +
> +	enabled_orders = collapse_allowable_orders(vma, vma->vm_flags, cc->is_khugepaged);
> +
> +	/*
> +	 * If PMD is the only enabled order, enforce max_ptes_none, otherwise
> +	 * scan all pages to populate the bitmap for mTHP collapse.
> +	 */

Ugh this is quite ugly. I don't really love that we've converted this from
doing the actual work to _mostly_ just populating the bitmap for the mthp
logic.

Then again it's only a couple places where this is checked, but it's pretty
horrible that what once was _the logic that determines what is being
considered for THP collapse' is now turned into 'the logic that populates a
bitmap'.

> +	if (cc->is_khugepaged && enabled_orders == _BITUL(HPAGE_PMD_ORDER))

I think this should be BIT(HPAGE_PMD_ORDER), I realise I reviewed the
opposite before (or think I did) but as per David we prefer BIT() :)

> +		full_scan = false;
> +	max_ptes_none = collapse_max_ptes_none(HPAGE_PMD_ORDER, full_scan);

Again really quite nasty, this may as well be:

	if (cc->is_khugepaged && enabled_orders == BIT(HPAGE_PMD_ORDER))
		max_ptes_none = khugepaged_max_ptes_none;
	else
		max_ptes_none = HPAGE_PMD_NR - 1;

It makes this hack a lot more obvious.

But also, what if !cc->is_khugepaged? We're going to scan everything even
if we only have PMD? I thought we only considered PMD size for MADV_COLLAPSE?

> +
>  	pte = pte_offset_map_lock(mm, pmd, start_addr, &ptl);
>  	if (!pte) {
>  		result = SCAN_PMD_NULL;
>  		goto out;
>  	}
>
> -	for (addr = start_addr, _pte = pte; _pte < pte + HPAGE_PMD_NR;
> -	     _pte++, addr += PAGE_SIZE) {
> +	for (i = 0; i < HPAGE_PMD_NR; i++) {
> +		_pte = pte + i;
> +		addr = start_addr + i * PAGE_SIZE;

That's nicer. I still hate _pte...

>  		pte_t pteval = ptep_get(_pte);
>  		if (is_swap_pte(pteval)) {
>  			++unmapped;
> @@ -1412,8 +1520,7 @@ static int collapse_scan_pmd(struct mm_struct *mm,
>  		if (pte_none_or_zero(pteval)) {
>  			++none_or_zero;
>  			if (!userfaultfd_armed(vma) &&
> -			    (!cc->is_khugepaged ||
> -			     none_or_zero <= khugepaged_max_ptes_none)) {
> +			    none_or_zero <= max_ptes_none) {

Why are we dropping !cc->is_khugepaged?

>  				continue;
>  			} else {
>  				result = SCAN_EXCEED_NONE_PTE;
> @@ -1461,6 +1568,8 @@ static int collapse_scan_pmd(struct mm_struct *mm,
>  			}
>  		}
>
> +		/* Set bit for occupied pages */
> +		bitmap_set(cc->mthp_bitmap, i, 1);

Maybe worth highlighting this is now _the entire point_ of the loop.

I wonder if we shouldn't just separate this logic out and name it
apppropriately? As we're into realms of real confusion here.

>  		/*
>  		 * Record which node the original page is from and save this
>  		 * information to cc->node_load[].
> @@ -1517,9 +1626,12 @@ static int collapse_scan_pmd(struct mm_struct *mm,
>  out_unmap:
>  	pte_unmap_unlock(pte, ptl);
>  	if (result == SCAN_SUCCEED) {
> -		result = collapse_huge_page(mm, start_addr, referenced,
> -					    unmapped, cc, mmap_locked,
> -					    HPAGE_PMD_ORDER, 0);

Hmm... what's actually enforcing that MADV_COLLAPSE isn't using this?
You've not done any cc->khugepaged checks afaict?

It seems that you _are_ enabling this for MADV_COLLAPSE unless I've missed
something?

> +		nr_collapsed = collapse_scan_bitmap(mm, start_addr, referenced, unmapped,
> +					      cc, mmap_locked, enabled_orders);
> +		if (nr_collapsed > 0)
> +			result = SCAN_SUCCEED;
> +		else
> +			result = SCAN_FAIL;
>  	}
>  out:
>  	trace_mm_khugepaged_scan_pmd(mm, folio, referenced,
> --
> 2.51.0
>

Thanks, Lorenzo

^ permalink raw reply

* Re: [PATCH v12 mm-new 13/15] khugepaged: avoid unnecessary mTHP collapse attempts
From: Lorenzo Stoakes @ 2025-11-19 12:05 UTC (permalink / raw)
  To: Nico Pache
  Cc: linux-kernel, linux-trace-kernel, linux-mm, linux-doc, david, ziy,
	baolin.wang, Liam.Howlett, ryan.roberts, dev.jain, corbet,
	rostedt, mhiramat, mathieu.desnoyers, akpm, baohua, willy, peterx,
	wangkefeng.wang, usamaarif642, sunnanyong, vishal.moola,
	thomas.hellstrom, yang, kas, aarcange, raquini, anshuman.khandual,
	catalin.marinas, tiwai, will, dave.hansen, jack, cl, jglisse,
	surenb, zokeefe, hannes, rientjes, mhocko, rdunlap, hughd,
	richard.weiyang, lance.yang, vbabka, rppt, jannh, pfalcato
In-Reply-To: <20251022183717.70829-14-npache@redhat.com>

On Wed, Oct 22, 2025 at 12:37:15PM -0600, Nico Pache wrote:
> There are cases where, if an attempted collapse fails, all subsequent
> orders are guaranteed to also fail. Avoid these collapse attempts by
> bailing out early.
>
> Signed-off-by: Nico Pache <npache@redhat.com>
> ---
>  mm/khugepaged.c | 31 ++++++++++++++++++++++++++++++-
>  1 file changed, 30 insertions(+), 1 deletion(-)
>
> diff --git a/mm/khugepaged.c b/mm/khugepaged.c
> index e2319bfd0065..54f5c7888e46 100644
> --- a/mm/khugepaged.c
> +++ b/mm/khugepaged.c
> @@ -1431,10 +1431,39 @@ static int collapse_scan_bitmap(struct mm_struct *mm, unsigned long address,
>  			ret = collapse_huge_page(mm, address, referenced,
>  						 unmapped, cc, mmap_locked,
>  						 order, offset);
> -			if (ret == SCAN_SUCCEED) {
> +
> +			/*
> +			 * Analyze failure reason to determine next action:
> +			 * - goto next_order: try smaller orders in same region
> +			 * - continue: try other regions at same order

The stack is a DFS, so this isn't correct, you may have pushed a bunch of higher
order candidate mTHPs (I don't like plain 'region') which you will also true.

> +			 * - break: stop all attempts (system-wide failure)
> +			 */

This comment isn't hugely helpful, just put the relevant comments next to each
of the goto, continue, break (soon to be return re: review below) statements
please.

> +			switch (ret) {
> +			/* Cases were we should continue to the next region */
> +			case SCAN_SUCCEED:
>  				collapsed += 1UL << order;
> +				fallthrough;
> +			case SCAN_PTE_MAPPED_HUGEPAGE:
>  				continue;

Would we not run into trouble potentially in the previous patch's implementation
of this examing candidate mTHPs that are part of an already existing huge page,
or would a folio check in the collapse just make this wasted work?

> +			/* Cases were lower orders might still succeed */
> +			case SCAN_LACK_REFERENCED_PAGE:
> +			case SCAN_EXCEED_NONE_PTE:

How can we, having checked the max_pte_none, still fail due to this?

> +			case SCAN_EXCEED_SWAP_PTE:
> +			case SCAN_EXCEED_SHARED_PTE:
> +			case SCAN_PAGE_LOCK:
> +			case SCAN_PAGE_COUNT:
> +			case SCAN_PAGE_LRU:
> +			case SCAN_PAGE_NULL:
> +			case SCAN_DEL_PAGE_LRU:
> +			case SCAN_PTE_NON_PRESENT:
> +			case SCAN_PTE_UFFD_WP:
> +			case SCAN_ALLOC_HUGE_PAGE_FAIL:
> +				goto next_order;
> +			/* All other cases should stop collapse attempts */

I don't love us having a catch-all, plase spell out all cases.

> +			default:
> +				break;
>  			}
> +			break;

_Hate_ this double break. Just return collapsed please.

>  		}
>
>  next_order:
> --
> 2.51.0
>

^ permalink raw reply

* Re: [PATCH v12 mm-new 12/15] khugepaged: Introduce mTHP collapse support
From: Lorenzo Stoakes @ 2025-11-19 12:08 UTC (permalink / raw)
  To: Nico Pache
  Cc: linux-kernel, linux-trace-kernel, linux-mm, linux-doc, david, ziy,
	baolin.wang, Liam.Howlett, ryan.roberts, dev.jain, corbet,
	rostedt, mhiramat, mathieu.desnoyers, akpm, baohua, willy, peterx,
	wangkefeng.wang, usamaarif642, sunnanyong, vishal.moola,
	thomas.hellstrom, yang, kas, aarcange, raquini, anshuman.khandual,
	catalin.marinas, tiwai, will, dave.hansen, jack, cl, jglisse,
	surenb, zokeefe, hannes, rientjes, mhocko, rdunlap, hughd,
	richard.weiyang, lance.yang, vbabka, rppt, jannh, pfalcato
In-Reply-To: <d03e079f-35c0-4fc1-8856-44fe33fabb2f@lucifer.local>

Oh I forgot to add -

In collapse_scan_pmd() there are casees where you just bail out altogether.

E.g.: pte_uffd_wp() for _any_ PTE entry in the range.

Or !folio_test_anon() for _any_ PTE entry in the range.

Etc.

Surely these are cases where an mTHP scan on part of the range might still
succeed?

You then in the subseuqent patch seem to check for collapse failures
specifically due to some of these, but surely you will never hit them as you
already discarded the whole PTE page table?

I'm not sure you've updated collapse_scan_pmd() sufficiently to account for the
mTHP logic.

Cheers, Lorenzo


On Wed, Nov 19, 2025 at 11:53:16AM +0000, Lorenzo Stoakes wrote:
> On Wed, Oct 22, 2025 at 12:37:14PM -0600, Nico Pache wrote:
> > During PMD range scanning, track occupied pages in a bitmap. If mTHPs are
> > enabled we remove the restriction of max_ptes_none during the scan phase
> > to avoid missing potential mTHP candidates.
>
> It's a bit odd to open the commit message with a very specific
> implementation detail, I think we should instead open with a broad
> description of what we intend here, e.g. to permit mTHP collapse, before:
>
> - Discussing the algorithm used (in more detail than below!)
> - How and under what circumstances this algorithm is invoked
> - (Mention MADV_COLLAPSE not supporting mTHP as of yet)
> - THEN super-specific details like this.
>
> >
> > Implement collapse_scan_bitmap() to perform binary recursion on the bitmap
> > and determine the best eligible order for the collapse. A stack struct is
> > used instead of traditional recursion. The algorithm splits the bitmap
> > into smaller chunks to find the best fit mTHP.  max_ptes_none is scaled by
> > the attempted collapse order to determine how "full" an order must be
> > before being considered for collapse.
>
> I feel this is a _very_ brief description of a complicated algorithm. I
> think we should go into a lot more detail here. 'Binary recursion' is pretty
> hand-wavey, and you go from hand waving that to being super-specific about
> max_ptes_none before handwaving about 'fullness' of an order.
>
> All in all I find it super confusing - so I think you need to take a step
> back and 'explain it to me like I'm 5' here :)
>
> >
> > Once we determine what mTHP sizes fits best in that PMD range a collapse
> > is attempted. A minimum collapse order of 2 is used as this is the lowest
> > order supported by anon memory.
>
> I don't know what 'lowest order supported by anon memory' means?
>
> I guess really this is the minimum order contptes support for arm64 right?
>
> >
> > mTHP collapses reject regions containing swapped out or shared pages.
> > This is because adding new entries can lead to new none pages, and these
> > may lead to constant promotion into a higher order (m)THP. A similar
> > issue can occur with "max_ptes_none > HPAGE_PMD_NR/2" due to a collapse
> > introducing at least 2x the number of pages, and on a future scan will
> > satisfy the promotion condition once again. This issue is prevented via
> > the collapse_allowable_orders() function.
>
> Obviously this has been discussed to death, but you should update this to
> reflect the decided upon course (0, 511 + warning, etc.).
>
> >
> > Currently madv_collapse is not supported and will only attempt PMD
> > collapse.
>
> Good to highlight this.
>
> >
> > We can also remove the check for is_khugepaged inside the PMD scan as
> > the collapse_max_ptes_none() function handles this logic now.
>
> Again we're kind of leaping from mega handwaving to super-specific details
> :) let's make it all a lot more specific + clear, and then put the really
> niche details like this at the end of the commit msg (I mean this one is
> fine where it is ofc as a result :)
>
> >
> > Signed-off-by: Nico Pache <npache@redhat.com>
> > ---
> >  include/linux/khugepaged.h |   2 +
> >  mm/khugepaged.c            | 128 ++++++++++++++++++++++++++++++++++---
> >  2 files changed, 122 insertions(+), 8 deletions(-)
> >
> > diff --git a/include/linux/khugepaged.h b/include/linux/khugepaged.h
> > index eb1946a70cff..179ce716e769 100644
> > --- a/include/linux/khugepaged.h
> > +++ b/include/linux/khugepaged.h
> > @@ -1,6 +1,8 @@
> >  /* SPDX-License-Identifier: GPL-2.0 */
> >  #ifndef _LINUX_KHUGEPAGED_H
> >  #define _LINUX_KHUGEPAGED_H
> > +#define KHUGEPAGED_MIN_MTHP_ORDER	2
> > +#define MAX_MTHP_BITMAP_STACK	(1UL << (ilog2(MAX_PTRS_PER_PTE) - KHUGEPAGED_MIN_MTHP_ORDER))
>
> This is an internal implementation detail, I don't think we need this in a
> header do we? I think this define should be in khugepaged.c.
>
> Also this is a really fiddly and confusing value, I don't think it's a good idea
> to just put this here without explanation.
>
> It's not even clear what it is. I'd probably rename it to MTHP_STACK_SIZE?
>
> We need a comment that explains how you're deriving this, something like:
>
> /*
>  * In order to determine mTHP order, we consider every possible mTHP size
>  * starting with MAX_PTRS_PER_PTE PTE entries and stopping at
>  * 2^KHUGEPAGED_MIN_THP_ORDER.
>  *
>  * We store (offset, order) pairs on the stack to do so, each describing a
>  * candidate mTHP collapse.
>  *
>  * For each (offset, order) candidate mTHP range that we consider, we must
>  * also consider candiate mTHPs at (offset, order - 1), and (offset + (1 <<
>  * order), order - 1).
>  *
>  *
>  * This is because each order can be split into two (an order expresses the
>  * power-of-two size), so we examine each half of the next lower order
>  * mTHP:
>  *
>  *                offset   mid_offset
>  *                  .          |
>  *                  .          v
>  *  |---------------.-------------------|
>  *  |           PTE page table          |
>  *  |---------------.-------------------|
>  *                   <--------><-------->
>  *                     order-1   order-1
>  *
>  * Given we must consider the range of KHUGEPAGED_MIN_MTHP_ORDER to
>  * MAX_PTRS_PER_PTE number of PTE entries, this is the same as saying we
>  * must consider KHUGEPAGED_MIN_MTHP_ORDER to lg2(MAX_PTRS_PER_PTE) mTHP
>  * orders.
>  *
>  * As we must consider 2 possible mTHP ranges for each order, this requires
>  * our stack to be 2^n, where n is the number of orders we must consider.
>  *
>  * And thus MTHP_STACK_SIZE is 2^(lg2(MAX_PTRS_PER_PTE) -
>  * KHUGEPAGED_MIN_MTHP_ORDER).
>  */
>
> This may seem (very) long-winded, but this is all really non-obvious.
>
> You can additionally rephrase this and utilise it in the commit message,
> description of the iterative recursion function and possibly elsewhere to
> describe the algorithm more clearly.
>
> In fact, since this should really be declared in khugepaged.c, and since
> you can place it just before the mthp collapse function, you could expand
> this to describe the algorithm as a whole and simply put the define and the
> function immediately next to each other after the comment?
>
> >
> >  #include <linux/mm.h>
> >
> > diff --git a/mm/khugepaged.c b/mm/khugepaged.c
> > index 89a105124790..e2319bfd0065 100644
> > --- a/mm/khugepaged.c
> > +++ b/mm/khugepaged.c
> > @@ -93,6 +93,11 @@ static DEFINE_READ_MOSTLY_HASHTABLE(mm_slots_hash, MM_SLOTS_HASH_BITS);
> >
> >  static struct kmem_cache *mm_slot_cache __ro_after_init;
> >
> > +struct scan_bit_state {
>
> Scan bit state is a bit of a weird name. Scanning what? What bit? State is
> kind of implied?
>
> struct order_offset_pair?
>
> struct mthp_range?
>
> > +	u8 order;
> > +	u16 offset;
>
> Real mega nit, but feels more natural to put offset first here. As
> (position, size) seems more naturally the way to view this than (size,
> position).
>
> > +};
> > +
>
> Also needs comments...? Order of what? Offset in what?
>
> >  struct collapse_control {
> >  	bool is_khugepaged;
> >
> > @@ -101,6 +106,13 @@ struct collapse_control {
> >
> >  	/* nodemask for allocation fallback */
> >  	nodemask_t alloc_nmask;
> > +
> > +	/*
> > +	 * bitmap used to collapse mTHP sizes.
> > +	 */
>
> Nit but this should be on one line /* Bitmap used to collapse mTHP sizes */.
>
> But we're not storing sizes though are we? And we're declaring two bitmaps?
>
> > +	 DECLARE_BITMAP(mthp_bitmap, HPAGE_PMD_NR);
>
> Really this is more of a PTE table bitmap but probably fine to call it this.
>
> > +	 DECLARE_BITMAP(mthp_bitmap_mask, HPAGE_PMD_NR);
>
> You've added random whitespace after the tab twice here? [tab][space]DECLARE_...
>
> > +	struct scan_bit_state mthp_bitmap_stack[MAX_MTHP_BITMAP_STACK];
> >  };
> >
> >  /**
> > @@ -1357,6 +1369,85 @@ static int collapse_huge_page(struct mm_struct *mm, unsigned long pmd_address,
> >  	return result;
> >  }
> >
> > +static void push_mthp_bitmap_stack(struct collapse_control *cc, int *top,
> > +				   u8 order, u16 offset)
>
> Not sure we need to say mthp_bitmap_stack everywhere. This is a local
> static function we can be a little more succinct.
>
> mthp_stack_push()?
>
> > +{
> > +	cc->mthp_bitmap_stack[++*top] = (struct scan_bit_state)
> > +		{ order, offset };
>
> This feels rather difficult to read, cc->mthp_bitmap_stack[++*top] in
> particular is rather too succinct.
>
> This would be better more broken out, e.g.:
>
> static void mthp_stack_push(struct collapse_control *cc, int *sizep,
> 	    u8 order, u16 offset)
> {
> 	const int size = *sizep;
> 	struct scan_bit_state *stack = &cc->mthp_bitmap_stack[size];
>
> 	VM_WARN_ON_ONCE(idx >= MAX_MTHP_BITMAP_STACK);
> 	stack->order = order;
> 	stack->offset = offset;
> 	*sizep++;
> }
>
> (Note this requires the change I suggest below re: not defaulting top to -1
> but instead renaming it to stack_size and starting at 0, see below).
>
> Re: below comment having pop as a helper too, that can be:
>
> static struct scan_bit_state mthp_stack_pop(struct collapse_control *cc,
> 		int *sizep)
> {
> 	const int size = *sizep;
>
> 	VM_WARN_ON_ONCE(size <= 0);
> 	*sizep--;
> 	return cc->mthp_bitmap_stack[size - 1];
> }
>
> > +}
> > +
> > +/*
> > + * collapse_scan_bitmap() consumes the bitmap that is generated during
> > + * collapse_scan_pmd() to determine what regions and mTHP orders fit best.
> > + *
> > + * Each bit in the bitmap represents a single occupied (!none/zero) page.
>
> In which bitmap? There are 2 that are declared. Be specific - cc->mthp_bitmap.
>
> > + * A stack structure cc->mthp_bitmap_stack is used to check different regions
>
> > + * of the bitmap for collapse eligibility. We start at the PMD order and
> > + * check if it is eligible for collapse; if not, we add two entries to the
>
> I questioned this since you start at HPAGE_PMD_ORDER -
> KHUGEPAGED_MIN_MTHP_ORDER, but then realised you're intentionally
> offsetting like that.
>
> See comments below about changing this.
>
> > + * stack at a lower order to represent the left and right halves of the region.
> > + *
> > + * For each region, we calculate the number of set bits and compare it
> > + * against a threshold derived from collapse_max_ptes_none(). A region is
> > + * eligible if the number of set bits exceeds this threshold.
> > + */
>
> I think we could be clearer here. Something like:
>
> ...
>  * stack at a lower order to represent the left and right halves of the
>  * portion of the PTE page table we are examining.
>  *
>
>  * For each of these, we determine how many PTE entries are occupied in the
>  * range of PTE entries we propose to collapse, then compare this to the
>  * number of PTE entries which would need to be set for a collapse to be
>  * permitted at that order (accounting for max_ptes_none).
>  *
>  * If a collapse is permissible, we attempt to perform one. We do so for
>  * every possible mTHP in the PTE page table.
>  */
>
> > +static int collapse_scan_bitmap(struct mm_struct *mm, unsigned long address,
>
> Really inconsistent naming going on here, we're collapsing and scanning and
> what's the bitmap?
>
> How about mthp_collapse()?
>
> > +		int referenced, int unmapped, struct collapse_control *cc,
> > +		bool *mmap_locked, unsigned long enabled_orders)
> > +{
> > +	u8 order, next_order;
> > +	u16 offset, mid_offset;
> > +	int num_chunks;
> > +	int bits_set, threshold_bits;
> > +	int top = -1;
>
> This seems unnecessary and confusing. Just start at 0 and treat this as the
> exclusive end of the stack.
>
> You can rename this stack_size to make that clear. Have commented above
> about adjustments to push function and introducing pop helper.
>
>
> > +	int collapsed = 0;
> > +	int ret;
> > +	struct scan_bit_state state;
> > +	unsigned int max_none_ptes;
>
> Everywhere else we say max_ptes_none, let's maintain that convention here
> please.
>
> > +
> > +	push_mthp_bitmap_stack(cc, &top, HPAGE_PMD_ORDER - KHUGEPAGED_MIN_MTHP_ORDER, 0);
>
> See below re: order here, we should change this.
>
> > +
> > +	while (top >= 0) {
> > +		state = cc->mthp_bitmap_stack[top--];
>
> I hate that we have a push helper but then do pop manually. See above.
>
> > +		order = state.order + KHUGEPAGED_MIN_MTHP_ORDER;
>
> OK so now the order isn't state.order but is instead state.order +
> KHUGEPAGED_MIN_MTHP_ORDER? :/ this is extremely confusing.
>
> We shouldn't call this field order if you're doing a hack where state.order
> isn't the order but instead is order - KHUGEPAGED_MIN_MTHP_ORDER.
>
> Just have state.order be the actual order? And change the below condition
> as mentioned there.
>
> > +		offset = state.offset;
> > +		num_chunks = 1UL << order;
>
> What's a chunk? You do need to clarify these things. This is a new term not
> used elsewhere in THP code as far as I can tell?
>
> This is the number of pte entries no?
>
> nr_entries? nr_pte_entries?
>
> > +
> > +		/* Skip mTHP orders that are not enabled */
>
> Note we're also considering PMD here :) Probably we can just delete this
> comment, the code below makes it clear what you're doing.
>
> > +		if (!test_bit(order, &enabled_orders))
> > +			goto next_order;
> > +
> > +		max_none_ptes = collapse_max_ptes_none(order, !cc->is_khugepaged);
>
> OK so this is going to be scaled to order.
>
> > +
> > +		/* Calculate weight of the range */
>
> What's the weight of a range? This isn't a very helpful comment. You're
> counting the Hamming weight or much more clearly - the number of set bits.
>
> So it seems you're simply counting the number of bits you have accumulated
> so far in cc->mthp_bitmap, adding in the latest offset.
>
> So I'd say add a comment saying something like:
>
> /*
>  * Determine how many PTE entries are populated in the range in which we
>  * propose to collapse this mTHP.
>  */
>
> > +		bitmap_zero(cc->mthp_bitmap_mask, HPAGE_PMD_NR);
> > +		bitmap_set(cc->mthp_bitmap_mask, offset, num_chunks);
> > +		bits_set = bitmap_weight_and(cc->mthp_bitmap,
>
> I think this variable name is pretty horrible, we don't care that it's the
> number of bits set, we care about what it _means_ - that is the number of
> PTE occupied entries.
>
> So nr_occupied_pte_entries? Or nr_occupied_ptes?
>
> > +					     cc->mthp_bitmap_mask, HPAGE_PMD_NR);
>
> Frustrating there isn't a bitmap_weight_offset() or something, as you could
> do that in one go then...
>
> I think this could be made clearer by separating out the gnarly bitmap
> stuff into a helper function:
>
> static int mthp_nr_occupied_pte_entries(struct collapse_control *cc,
> 		struct scan_bit_state state)
> {
> 	const int nr_pte_entries = 1 << state.order;
>
> 	/* Setup cc->mthp_bitmap_mask to contain mask for candidate mTHP. */
> 	bitmap_zero(cc->mthp_bitmap_mask, HPAGE_PMD_NR);
> 	bitmap_set(cc->mthp_bitmap_mask, state.offset, nr_pte_entries);
> 	/* Mask against actually occupied PTE entries in PTE table. */
> 	return bitmap_weight_and(cc->mthp_bitmap,
> 				 cc->mthp_bitmap_mask, HPAGE_PMD_NR);
> }
>
> > +
> > +		threshold_bits = (1UL << order) - max_none_ptes - 1;
>
> We defined num_chunks to 1UL << order then don't use here? :)
>
> I'm not sure we need this to be a separate value, and I don't think we need
> the -1 either, which only confuses matter more.
>
> How about just changing the below conditional to (assuming we've renamed
> num_chunks to something sensible like nr_pte_entries and bits_set to
> nr_occupied_pte_entries):
>
> if (nr_occupied_pte_entries >= nr_pte_entries - max_none_ptes) {
> 	...
> }
>
> > +
> > +		/* Check if the region is eligible based on the threshold */
>
> Probalby don't need this comment with the change above.
>
> > +		if (bits_set > threshold_bits) {
> > +			ret = collapse_huge_page(mm, address, referenced,
> > +						 unmapped, cc, mmap_locked,
> > +						 order, offset);
>
> We declare ret at the top of the function scope, then only use it
> here. That's confusing and unnecessary, just declare it in block scope
> here.
>
> > +			if (ret == SCAN_SUCCEED) {
> > +				collapsed += 1UL << order;
>
> Again we have defined num_chunks or rather nr_pte_entries but then
> open-code 1UL << order, let's just use the value we declared here.
>
> > +				continue;
>
> This is kinda subtle, we don't bother considering lower orders any longer
> *in this range*, but do continue to consider mTHP collapse in other
> portions of the PTE page table.
>
> This shouldn't just be a 'continue' :) we need a comment here to explain
> that.
>
> E.g.:
>
> 	/*
> 	 * We have collapsed an mTHP in this range at the maximum order we
> 	 * could, so we do not push lower orders on to the stack.
> 	 */
> 	 continue;
>
>
> > +			}
> > +		}
> > +
> > +next_order:
> > +		if (state.order > 0) {
>
> This is a great example of how this is confusing by making state.order not
> actually be the order but the order - KHUGEPAGED_MIN_MTHP_ORDER.
>
> Just make the order correct and change this to > KHUGEPAGED_MIN_MTHP_ORDER.
>
> > +			next_order = state.order - 1;
>
> Not sure we should have a label and a variable be the same thing.
>
> Also why are we decl'ing next_order at the top of the function but only using here?
>
> Just declare this here, like:
>
> 	if (state.order > KHUGEPAGED_MIN_MTHP_ORDER) {
> 		const u16 new_order = state.order - 1;
>
> 		...
> 	}
>
> > +			mid_offset = offset + (num_chunks / 2);
> > +			push_mthp_bitmap_stack(cc, &top, next_order, mid_offset);
> > +			push_mthp_bitmap_stack(cc, &top, next_order, offset);
>
> I guess one subtlety that wouldn't be obvious at first glance is that
> num_chunks (oh so badly needs a rename :) is a power-of-2 so we never get
> weird 'what if num_chunks is odd' scenarios to worry about.
>
> Probably doesn't really need a comment though. But this _does_ badly needs
> an ASCII diagram :):
>
> 	/*
> 	 * The next lowest mTHP order possesses half the number of PTE
> 	 * entries of the current one. We therefore must consider both
> 	 * halves of the current mTHP:
> 	 *
> 	 *                offset   mid_offset
> 	 *                  .          |
> 	 *                  .          v
> 	 *  |---------------.-------------------|
> 	 *  |           PTE page table          |
> 	 *  |---------------.-------------------|
> 	 *                   <--------><-------->
> 	 *                     order-1   order-1
> 	 */
>
> Since writing this I copied this above in another suggestion :P so you
> could always say 'see comment above for details' or something.
>
> > +		}
> > +	}
> > +	return collapsed;
> > +}
>
> I've commented this function to death here, but a few more things to note.
>
> (BTW - I'm sorry I personally _hate_ repeated iterations of review when
> there's stuff you could have commented in prior iterations BUT I think I
> may end up having to once we respin due to the subtleties here.)
>
> - I wonder if we could just use a helper struct to make this all a little
>   easier. Perhaps as it's realtively short code not so necesary, but a bit
>   horrid to pass around all these paramters all the time. Maybe something
>   for later THP rework.
>
> - Could we exit early if it's obvious that we won't be able to collapse due
>   to max_ptes_none? I mean for one, we could at least check if the next
>   lowest order is empty. If max_ptes_none was 511, then we would have
>   already collapsed so can surely throw that out?
>
>   I was thinking we could go 'upwards', starting with the lowest order and
>   increasing order (essentially reverse things) then not collapsing until
>   we can't collapse at a given order (so collapse at next lowest). That
>   might be less efficient though.
>
> - Given that we're going to be only permitting max_ptes_none of 0 and 511
>   for mTHP to start with, maybe things can be simplified - either all bits
>   have to 1 or we don't care what they are we attempt colalpse anyway?
>
>   But then again, maybe it's worth having the generic algorithm in place
>   for future flexibility? Thoughts?
>
> - How much have you tested this? This is pretty subtle stuff... it _seems_
>   correct to me logically, but this is crying out for some userland testing
>   that exhaustively throws every possible permutation of state at this
>   function and asserts it's all correct.
>
> - Are we not missing a bunch of stat counts? Didn't we add a bunch but now
>   are actually setting them? E.g. if we reject mTHP candidates due to
>   pte_max_none?
>
> > +
> >  static int collapse_scan_pmd(struct mm_struct *mm,
> >  			     struct vm_area_struct *vma,
> >  			     unsigned long start_addr, bool *mmap_locked,
> > @@ -1364,11 +1455,15 @@ static int collapse_scan_pmd(struct mm_struct *mm,
> >  {
> >  	pmd_t *pmd;
> >  	pte_t *pte, *_pte;
> > +	int i;
> >  	int result = SCAN_FAIL, referenced = 0;
> > -	int none_or_zero = 0, shared = 0;
> > +	int none_or_zero = 0, shared = 0, nr_collapsed = 0;
> >  	struct page *page = NULL;
> > +	unsigned int max_ptes_none;
>
> Correct spelling of this :)
>
> >  	struct folio *folio = NULL;
> >  	unsigned long addr;
> > +	unsigned long enabled_orders;
> > +	bool full_scan = true;
> >  	spinlock_t *ptl;
> >  	int node = NUMA_NO_NODE, unmapped = 0;
> >
> > @@ -1378,16 +1473,29 @@ static int collapse_scan_pmd(struct mm_struct *mm,
> >  	if (result != SCAN_SUCCEED)
> >  		goto out;
> >
> > +	bitmap_zero(cc->mthp_bitmap, HPAGE_PMD_NR);
> >  	memset(cc->node_load, 0, sizeof(cc->node_load));
> >  	nodes_clear(cc->alloc_nmask);
> > +
> > +	enabled_orders = collapse_allowable_orders(vma, vma->vm_flags, cc->is_khugepaged);
> > +
> > +	/*
> > +	 * If PMD is the only enabled order, enforce max_ptes_none, otherwise
> > +	 * scan all pages to populate the bitmap for mTHP collapse.
> > +	 */
>
> Ugh this is quite ugly. I don't really love that we've converted this from
> doing the actual work to _mostly_ just populating the bitmap for the mthp
> logic.
>
> Then again it's only a couple places where this is checked, but it's pretty
> horrible that what once was _the logic that determines what is being
> considered for THP collapse' is now turned into 'the logic that populates a
> bitmap'.
>
> > +	if (cc->is_khugepaged && enabled_orders == _BITUL(HPAGE_PMD_ORDER))
>
> I think this should be BIT(HPAGE_PMD_ORDER), I realise I reviewed the
> opposite before (or think I did) but as per David we prefer BIT() :)
>
> > +		full_scan = false;
> > +	max_ptes_none = collapse_max_ptes_none(HPAGE_PMD_ORDER, full_scan);
>
> Again really quite nasty, this may as well be:
>
> 	if (cc->is_khugepaged && enabled_orders == BIT(HPAGE_PMD_ORDER))
> 		max_ptes_none = khugepaged_max_ptes_none;
> 	else
> 		max_ptes_none = HPAGE_PMD_NR - 1;
>
> It makes this hack a lot more obvious.
>
> But also, what if !cc->is_khugepaged? We're going to scan everything even
> if we only have PMD? I thought we only considered PMD size for MADV_COLLAPSE?
>
> > +
> >  	pte = pte_offset_map_lock(mm, pmd, start_addr, &ptl);
> >  	if (!pte) {
> >  		result = SCAN_PMD_NULL;
> >  		goto out;
> >  	}
> >
> > -	for (addr = start_addr, _pte = pte; _pte < pte + HPAGE_PMD_NR;
> > -	     _pte++, addr += PAGE_SIZE) {
> > +	for (i = 0; i < HPAGE_PMD_NR; i++) {
> > +		_pte = pte + i;
> > +		addr = start_addr + i * PAGE_SIZE;
>
> That's nicer. I still hate _pte...
>
> >  		pte_t pteval = ptep_get(_pte);
> >  		if (is_swap_pte(pteval)) {
> >  			++unmapped;
> > @@ -1412,8 +1520,7 @@ static int collapse_scan_pmd(struct mm_struct *mm,
> >  		if (pte_none_or_zero(pteval)) {
> >  			++none_or_zero;
> >  			if (!userfaultfd_armed(vma) &&
> > -			    (!cc->is_khugepaged ||
> > -			     none_or_zero <= khugepaged_max_ptes_none)) {
> > +			    none_or_zero <= max_ptes_none) {
>
> Why are we dropping !cc->is_khugepaged?
>
> >  				continue;
> >  			} else {
> >  				result = SCAN_EXCEED_NONE_PTE;
> > @@ -1461,6 +1568,8 @@ static int collapse_scan_pmd(struct mm_struct *mm,
> >  			}
> >  		}
> >
> > +		/* Set bit for occupied pages */
> > +		bitmap_set(cc->mthp_bitmap, i, 1);
>
> Maybe worth highlighting this is now _the entire point_ of the loop.
>
> I wonder if we shouldn't just separate this logic out and name it
> apppropriately? As we're into realms of real confusion here.
>
> >  		/*
> >  		 * Record which node the original page is from and save this
> >  		 * information to cc->node_load[].
> > @@ -1517,9 +1626,12 @@ static int collapse_scan_pmd(struct mm_struct *mm,
> >  out_unmap:
> >  	pte_unmap_unlock(pte, ptl);
> >  	if (result == SCAN_SUCCEED) {
> > -		result = collapse_huge_page(mm, start_addr, referenced,
> > -					    unmapped, cc, mmap_locked,
> > -					    HPAGE_PMD_ORDER, 0);
>
> Hmm... what's actually enforcing that MADV_COLLAPSE isn't using this?
> You've not done any cc->khugepaged checks afaict?
>
> It seems that you _are_ enabling this for MADV_COLLAPSE unless I've missed
> something?
>
> > +		nr_collapsed = collapse_scan_bitmap(mm, start_addr, referenced, unmapped,
> > +					      cc, mmap_locked, enabled_orders);
> > +		if (nr_collapsed > 0)
> > +			result = SCAN_SUCCEED;
> > +		else
> > +			result = SCAN_FAIL;
> >  	}
> >  out:
> >  	trace_mm_khugepaged_scan_pmd(mm, folio, referenced,
> > --
> > 2.51.0
> >
>
> Thanks, Lorenzo

^ permalink raw reply

* Re: [PATCH v12 mm-new 14/15] khugepaged: run khugepaged for all orders
From: Lorenzo Stoakes @ 2025-11-19 12:13 UTC (permalink / raw)
  To: Nico Pache
  Cc: linux-kernel, linux-trace-kernel, linux-mm, linux-doc, david, ziy,
	baolin.wang, Liam.Howlett, ryan.roberts, dev.jain, corbet,
	rostedt, mhiramat, mathieu.desnoyers, akpm, baohua, willy, peterx,
	wangkefeng.wang, usamaarif642, sunnanyong, vishal.moola,
	thomas.hellstrom, yang, kas, aarcange, raquini, anshuman.khandual,
	catalin.marinas, tiwai, will, dave.hansen, jack, cl, jglisse,
	surenb, zokeefe, hannes, rientjes, mhocko, rdunlap, hughd,
	richard.weiyang, lance.yang, vbabka, rppt, jannh, pfalcato
In-Reply-To: <20251022183717.70829-15-npache@redhat.com>

On Wed, Oct 22, 2025 at 12:37:16PM -0600, Nico Pache wrote:
> From: Baolin Wang <baolin.wang@linux.alibaba.com>
>
> If any order (m)THP is enabled we should allow running khugepaged to
> attempt scanning and collapsing mTHPs. In order for khugepaged to operate
> when only mTHP sizes are specified in sysfs, we must modify the predicate
> function that determines whether it ought to run to do so.
>
> This function is currently called hugepage_pmd_enabled(), this patch
> renames it to hugepage_enabled() and updates the logic to check to
> determine whether any valid orders may exist which would justify
> khugepaged running.
>
> We must also update collapse_allowable_orders() to check all orders if
> the vma is anonymous and the collapse is khugepaged.
>
> After this patch khugepaged mTHP collapse is fully enabled.
>
> Signed-off-by: Baolin Wang <baolin.wang@linux.alibaba.com>
> Signed-off-by: Nico Pache <npache@redhat.com>
> ---
>  mm/khugepaged.c | 25 +++++++++++++------------
>  1 file changed, 13 insertions(+), 12 deletions(-)
>
> diff --git a/mm/khugepaged.c b/mm/khugepaged.c
> index 54f5c7888e46..8ed9f8e2d376 100644
> --- a/mm/khugepaged.c
> +++ b/mm/khugepaged.c
> @@ -418,23 +418,23 @@ static inline int collapse_test_exit_or_disable(struct mm_struct *mm)
>  		mm_flags_test(MMF_DISABLE_THP_COMPLETELY, mm);
>  }
>
> -static bool hugepage_pmd_enabled(void)
> +static bool hugepage_enabled(void)
>  {
>  	/*
>  	 * We cover the anon, shmem and the file-backed case here; file-backed
>  	 * hugepages, when configured in, are determined by the global control.
> -	 * Anon pmd-sized hugepages are determined by the pmd-size control.
> +	 * Anon hugepages are determined by its per-size mTHP control.
>  	 * Shmem pmd-sized hugepages are also determined by its pmd-size control,
>  	 * except when the global shmem_huge is set to SHMEM_HUGE_DENY.
>  	 */
>  	if (IS_ENABLED(CONFIG_READ_ONLY_THP_FOR_FS) &&
>  	    hugepage_global_enabled())
>  		return true;
> -	if (test_bit(PMD_ORDER, &huge_anon_orders_always))
> +	if (READ_ONCE(huge_anon_orders_always))
>  		return true;
> -	if (test_bit(PMD_ORDER, &huge_anon_orders_madvise))
> +	if (READ_ONCE(huge_anon_orders_madvise))
>  		return true;
> -	if (test_bit(PMD_ORDER, &huge_anon_orders_inherit) &&
> +	if (READ_ONCE(huge_anon_orders_inherit) &&
>  	    hugepage_global_enabled())
>  		return true;
>  	if (IS_ENABLED(CONFIG_SHMEM) && shmem_hpage_pmd_enabled())
> @@ -508,7 +508,8 @@ static unsigned long collapse_allowable_orders(struct vm_area_struct *vma,
>  			vm_flags_t vm_flags, bool is_khugepaged)
>  {
>  	enum tva_type tva_flags = is_khugepaged ? TVA_KHUGEPAGED : TVA_FORCED_COLLAPSE;
> -	unsigned long orders = BIT(HPAGE_PMD_ORDER);
> +	unsigned long orders = is_khugepaged && vma_is_anonymous(vma) ?
> +				THP_ORDERS_ALL_ANON : BIT(HPAGE_PMD_ORDER);

Why are we doing this? If this is explicitly enabling mTHP for anon, which it
seems to be, can we please make this a little more explicit :)

I'd prefer this not to be a horribly squashed ternary, rather:

	unsigned long orders;

	/* We explicitly allow mTHP collapse for anonymous khugepaged ONLY. */
	if (is_khugepaged && vma_is_anonymous(vma))
		orders = THP_ORDERS_ALL_ANON;
	else
		orders = BIT(HPAGE_PMD_ORDER);


Also, does THP_ORDERS_ALL_ANON account for KHUGEPAGED_MIN_MTHP_ORDER? It's weird
to say that an order is allowed that isn't permitted by mTHP (e.g. order-0).

>
>  	return thp_vma_allowable_orders(vma, vm_flags, tva_flags, orders);
>  }
> @@ -517,7 +518,7 @@ void khugepaged_enter_vma(struct vm_area_struct *vma,
>  			  vm_flags_t vm_flags)
>  {
>  	if (!mm_flags_test(MMF_VM_HUGEPAGE, vma->vm_mm) &&
> -	    hugepage_pmd_enabled()) {
> +	    hugepage_enabled()) {
>  		if (collapse_allowable_orders(vma, vm_flags, true))
>  			__khugepaged_enter(vma->vm_mm);
>  	}
> @@ -2791,7 +2792,7 @@ static unsigned int collapse_scan_mm_slot(unsigned int pages, int *result,
>
>  static int khugepaged_has_work(void)
>  {
> -	return !list_empty(&khugepaged_scan.mm_head) && hugepage_pmd_enabled();
> +	return !list_empty(&khugepaged_scan.mm_head) && hugepage_enabled();
>  }
>
>  static int khugepaged_wait_event(void)
> @@ -2864,7 +2865,7 @@ static void khugepaged_wait_work(void)
>  		return;
>  	}
>
> -	if (hugepage_pmd_enabled())
> +	if (hugepage_enabled())
>  		wait_event_freezable(khugepaged_wait, khugepaged_wait_event());
>  }
>
> @@ -2895,7 +2896,7 @@ static void set_recommended_min_free_kbytes(void)
>  	int nr_zones = 0;
>  	unsigned long recommended_min;
>
> -	if (!hugepage_pmd_enabled()) {
> +	if (!hugepage_enabled()) {
>  		calculate_min_free_kbytes();
>  		goto update_wmarks;
>  	}
> @@ -2945,7 +2946,7 @@ int start_stop_khugepaged(void)
>  	int err = 0;
>
>  	mutex_lock(&khugepaged_mutex);
> -	if (hugepage_pmd_enabled()) {
> +	if (hugepage_enabled()) {
>  		if (!khugepaged_thread)
>  			khugepaged_thread = kthread_run(khugepaged, NULL,
>  							"khugepaged");
> @@ -2971,7 +2972,7 @@ int start_stop_khugepaged(void)
>  void khugepaged_min_free_kbytes_update(void)
>  {
>  	mutex_lock(&khugepaged_mutex);
> -	if (hugepage_pmd_enabled() && khugepaged_thread)
> +	if (hugepage_enabled() && khugepaged_thread)
>  		set_recommended_min_free_kbytes();
>  	mutex_unlock(&khugepaged_mutex);
>  }
> --
> 2.51.0
>

^ permalink raw reply

* Re: [PATCH bpf-next v3 0/6] bpf trampoline support "jmp" mode
From: Xu Kuohai @ 2025-11-19 12:36 UTC (permalink / raw)
  To: Leon Hwang, Menglong Dong, Menglong Dong, Alexei Starovoitov
  Cc: Alexei Starovoitov, Steven Rostedt, Daniel Borkmann,
	John Fastabend, Andrii Nakryiko, Martin KaFai Lau, Eduard,
	Song Liu, Yonghong Song, KP Singh, Stanislav Fomichev, Hao Luo,
	Jiri Olsa, Masami Hiramatsu, Mark Rutland, Mathieu Desnoyers,
	jiang.biao, bpf, LKML, linux-trace-kernel
In-Reply-To: <97c8e49c-ca27-40ec-8ff6-18b1b9061240@linux.dev>

On 11/19/2025 10:55 AM, Leon Hwang wrote:
> 
> 
> On 19/11/25 10:47, Menglong Dong wrote:
>> On 2025/11/19 08:28, Alexei Starovoitov wrote:
>>> On Tue, Nov 18, 2025 at 4:36 AM Menglong Dong <menglong8.dong@gmail.com> wrote:
>>>>
>>>> As we can see above, the performance of fexit increase from 80.544M/s to
>>>> 136.540M/s, and the "fmodret" increase from 78.301M/s to 159.248M/s.
>>>
>>> Nice! Now we're talking.
>>>
>>> I think arm64 CPUs have a similar RSB-like return address predictor.
>>> Do we need to do something similar there?
>>> The question is not targeted to you, Menglong,
>>> just wondering.
>>
>> I did some research before, and I find that most arch
>> have such RSB-like stuff. I'll have a look at the loongarch
>> later(maybe after the LPC, as I'm forcing on the English practice),
>> and Leon is following the arm64.
> 
> Yep, happy to take this on.
> 
> I'm reviewing the arm64 JIT code now and will experiment with possible
> approaches to handle this as well.
>

Unfortunately, the arm64 trampoline uses a tricky approach to bypass BTI
by using ret instruction to invoke the patched function. This conflicts
with the current approach, and seems there is no straightforward solution.

> Thanks,
> Leon
> 
>>
>> For the other arch, we don't have the machine, and I think
>> it needs some else help.
>>
>> Thanks!
>> Menglong Dong
> 
> 
> 


^ permalink raw reply

* Re: [PATCH v3 3/8] mm: implement sticky VMA flags
From: Mark Brown @ 2025-11-19 12:55 UTC (permalink / raw)
  To: Lorenzo Stoakes
  Cc: Andrew Morton, Jonathan Corbet, David Hildenbrand,
	Liam R . Howlett, Vlastimil Babka, Mike Rapoport,
	Suren Baghdasaryan, Michal Hocko, Steven Rostedt,
	Masami Hiramatsu, Mathieu Desnoyers, Jann Horn, Pedro Falcato,
	Zi Yan, Baolin Wang, Nico Pache, Ryan Roberts, Dev Jain,
	Barry Song, Lance Yang, linux-kernel, linux-fsdevel, linux-doc,
	linux-mm, linux-trace-kernel, linux-kselftest, Andrei Vagin,
	Aishwarya.TCV
In-Reply-To: <1ee529ff912f71b3460d0d21bc5b32ca89d63513.1762531708.git.lorenzo.stoakes@oracle.com>

[-- Attachment #1: Type: text/plain, Size: 30406 bytes --]

On Fri, Nov 07, 2025 at 04:11:48PM +0000, Lorenzo Stoakes wrote:
> It is useful to be able to designate that certain flags are 'sticky', that
> is, if two VMAs are merged one with a flag of this nature and one without,
> the merged VMA sets this flag.

I'm seeing a regression in the futex selftests on arm64:

# TAP version 13
# 1..1
# # Starting 1 tests from 1 test cases.
# #  RUN           global.futex_numa_mpol ...
# # Regular test
# # Mis-aligned futex
# # Memory out of range
# Bail out! futex2_wake(64, 0x86) should fail, but didn't
# # Planned tests != run tests (1 != 0)
# # Totals: pass:0 fail:0 xfail:0 xpass:0 skip:0 error:0
# # futex_numa_mpol: Test failed
# #          FAIL  global.futex_numa_mpol
# not ok 1 global.futex_numa_mpol
# # FAILED: 0 / 1 tests passed.

which bisect to one of the fixup commits on top of this.  I've not done
any real analysis on this but it's a test that's generally very stable
so I'd be surprised if it's not a real failure.

Full log:

   https://lava.sirena.org.uk/scheduler/job/2106243#L11474

There is also a bisection for the mm mkdirty selftest which runs into
the same patch on at least Raspberry Pi 4:

# # -----------------
# # running ./mkdirty
# # -----------------
# # # [INFO] detected THP size: 2048 KiB
# # TAP version 13
# # 1..6
# # # [INFO] PTRACE write access
# # ok 1 SIGSEGV generated, page not modified
# # # [INFO] PTRACE write access to THP
# # ok 2 SIGSEGV generated, page not modified
# # # [INFO] Page migration
# # not ok 3 SIGSEGV generated, page not modified
# # # [INFO] Page migration of THP
# # not ok 4 SIGSEGV generated, page not modified
# # # [INFO] PTE-mapping a THP
# # not ok 5 SIGSEGV generated, page not modified
# # # [INFO] UFFDIO_COPY
# # ok 6 # SKIP __NR_userfaultfd failed
# # Bail out! 3 out of 6 tests failed
# # # 1 skipped test(s) detected. Consider enabling relevant config options to improve coverage.
# # # Totals: pass:2 fail:3 xfail:0 xpass:0 skip:1 error:0
# # [FAIL]
# not ok 61 mkdirty # exit=1

Full log for that:

   https://lava.sirena.org.uk/scheduler/job/2106236#L6939

and I'm also seeing some LTP failures going into these commits that I'll
report separately.

bisect log for the futex test:

# bad: [fe4d0dea039f2befb93f27569593ec209843b0f5] Add linux-next specific files for 20251119
# good: [ef96b7dd050abd62905588c41ffb397e0c9598c7] Merge branch 'for-linux-next-fixes' of https://gitlab.freedesktop.org/drm/misc/kernel.git
# good: [bd79452b39c21599e2cff42e9fbeb182656b6f6a] MAINTAINERS: adjust file entry in RISC-V MICROCHIP SUPPORT
# good: [21e68bcb1b0c688c2d9ca0d457922febac650ac1] regulator: renesas-usb-vbus-regulator: Remove unused headers
# good: [96498e804cb6629e02747336a0a33e4955449732] spi: davinci: remove platform data header
# good: [4422df6782eb7aa9725a3c09d9ba3c38ecc85df4] ASoC: ux500: mop500_ab8500: convert to snd_soc_dapm_xxx()
# good: [9e510e677090bb794b46348b10e1c8038286e00a] spi: aspeed: Add support for the AST2700 SPI controller
# good: [118eb2cb97b8fc0d515bb0449495959247db58f0] spi: bcm63xx: drop wrong casts in probe()
# good: [d5c8b7902a41625ea328b52c78ebe750fbf6fef7] ASoC: Intel: avs: Honor NHLT override when setting up a path
# good: [6402ddf3027d8975f135cf2b2014d6bbeb2d3436] MAINTAINERS: refer to trivial-codec.yaml in relevant sections
# good: [059f545832be85d29ac9ccc416a16f647aa78485] spi: add support for microchip "soft" spi controller
# good: [4e00135b2dd1d7924a58bffa551b6ceb3bd836f2] spi: spi-cadence: supports transmission with bits_per_word of 16 and 32
# good: [e65b871c9b5af9265aefc5b8cd34993586d93aab] ASoC: codecs: pm4125: Remove irq_chip on component unbind
# good: [8d63e85c5b50f1dbfa0ccb214bd91fe5d7e2e860] firmware: cs_dsp: fix kernel-doc warnings in a header file
# good: [8ff3dcb0e8a8bf6c41f23ed4aa62d066d3948a10] ASoC: codecs: lpass-rx-macro: add SM6115 compatible
# good: [123cd174a3782307787268adf45f22de4d290128] ASoC: Intel: atom: Replace strcpy() with strscpy()
# good: [1d562ba0aa7df81335bf96c02be77efe8d5bab87] spi: dt-bindings: nuvoton,npcm-pspi: Convert to DT schema
# good: [4d6e2211aeb932e096f673c88475016b1cc0f8ab] ASoC: Intel: boards: fix HDMI playback lookup when HDMI-In capture used
# good: [32172cf3cb543a04c41a1677c97a38e60cad05b6] ASoC: cs35l56: Allow restoring factory calibration through ALSA control
# good: [b3a5302484033331af37569f7277d00131694b57] ASoC: Intel: sof_rt5682: Add quirk override support
# good: [873bc94689d832878befbcadc10b6ad5bb4e0027] ASoC: Intel: sof_sdw: add codec speaker support for the SKU
# good: [772ada50282b0c80343c8989147db816961f571d] ASoC: cs35l56: Alter error codes for calibration routine
# good: [6985defd1d832f1dd9d1977a6a2cc2cef7632704] regmap: sdw-mbq: Reorder regmap_mbq_context struct for better packing
# good: [fb1ebb10468da414d57153ddebaab29c38ef1a78] regulator: core: disable supply if enabling main regulator fails
# good: [2089f086303b773e181567fd8d5df3038bd85937] regulator: mt6363: Remove unneeded semicolon
# good: [6951be397ca8b8b167c9f99b5a11c541148c38cb] ASoC: codecs: pm4125: remove duplicate code
# good: [4e92abd0a11b91af3742197a9ca962c3c00d0948] spi: imx: add i.MX51 ECSPI target mode support
# good: [abc9a349b87ac0fd3ba8787ca00971b59c2e1257] spi: fsl-qspi: support the SpacemiT K1 SoC
# good: [55d03b5b5bdd04daf9a35ce49db18d8bb488dffb] spi: imx: remove CLK calculation and check for target mode
# good: [6bd1ad97eb790570c167d4de4ca59fbc9c33722a] regulator: pf9453: Fix kernel doc for mux_poll()
# good: [1b0f3f9ee41ee2bdd206667f85ea2aa36dfe6e69] ASoC: SDCA: support Q7.8 volume format
# good: [3c36965df80801344850388592e95033eceea05b] regulator: Add support for MediaTek MT6363 SPMI PMIC Regulators
# good: [2f538ef9f6f7c3d700c68536f21447dfc598f8c8] spi: aspeed: Use devm_iounmap() to unmap devm_ioremap() memory
# good: [aa897ffc396b48cc39eee133b6b43175d0df9eb5] ASoC: dt-bindings: ti,pcm1862: convert to dtschema
# good: [655079ac8a7721ac215a0596e3f33b740e01144a] ASoC: qcom: q6asm: Use guard() for spin locks
# good: [c4e68959af66df525d71db619ffe44af9178bb22] ASoC: dt-bindings: ti,tas2781: Add TAS5822 support
# good: [380fd29d57abe6679d87ec56babe65ddc5873a37] spi: tegra210-quad: Check hardware status on timeout
# good: [af9c8092d84244ca54ffb590435735f788e7a170] regmap: i3c: Use ARRAY_SIZE()
# good: [84194c66aaf78fed150edb217b9f341518b1cba2] ASoC: codecs: aw88261: pass pointer directly instead of passing the address
# good: [252abf2d07d33b1c70a59ba1c9395ba42bbd793e] regulator: Small cleanup in of_get_regulation_constraints()
# good: [2ecc8c089802e033d2e5204d21a9f467e2517df9] regulator: pf9453: remove unused I2C_LT register
# good: [ed5d499b5c9cc11dd3edae1a7a55db7dfa4f1bdc] regcache: maple: Split ->populate() from ->init()
# good: [e73b743bfe8a6ff4e05b5657d3f7586a17ac3ba0] ASoC: soc-core: check ops & auto_selectable_formats in snd_soc_dai_get_fmt() to prevent dereference error
# good: [f1dfbc1b5cf8650ae9a0d543e5f5335fc0f478ce] ASoC: max98090/91: fixing the stream index
# good: [ecd0de438c1f0ee86cf8f6d5047965a2a181444b] spi: tle62x0: Add newline to sysfs attribute output
# good: [6ef8e042cdcaabe3e3c68592ba8bfbaee2fa10a3] ASoC: codec: wm8400: replace printk() calls with dev_*() device aware logging
# good: [20bcda681f8597e86070a4b3b12d1e4f541865d3] ASoC: codecs: va-macro: fix revision checking
# good: [cf6bf51b53252284bafc7377a4d8dbf10f048b4d] ASoC: cs4271: Add support for the external mclk
# good: [28039efa4d8e8bbf98b066133a906bd4e307d496] MAINTAINERS: remove obsolete file entry in DIALOG SEMICONDUCTOR DRIVERS
# good: [e062bdfdd6adbb2dee7751d054c1d8df63ddb8b8] regmap: warn users about uninitialized flat cache
# good: [8fdb030fe283c84fd8d378c97ad0f32d6cdec6ce] ASoC: qcom: sc7280: make use of common helpers
# good: [66fecfa91deb536a12ddf3d878a99590d7900277] ASoC: spacemit: use `depends on` instead of `select`
# good: [f034c16a4663eaf3198dc18b201ba50533fb5b81] ASoC: spacemit: add failure check for spacemit_i2s_init_dai()
# good: [4a5ac6cd05a7e54f1585d7779464d6ed6272c134] ASoC: sun4i-spdif: Support SPDIF output on A523 family
# good: [ef042df96d0e1089764f39ede61bc8f140a4be00] ASoC: SDCA: Add HID button IRQ
# good: [4c33cef58965eb655a0ac8e243aa323581ec025f] regulator: pca9450: link regulator inputs to supply groups
# good: [01313661b248c5ba586acae09bff57077dbec0a5] regulator: Let raspberrypi drivers depend on ARM
# good: [e7434adf0c53a84d548226304cdb41c8818da1cb] ASoC: cs530x: Add SPI bus support for cs530x parts
# good: [77a58ba7c64ccca20616aa03599766ccb0d1a330] spi: spi-mem: Trace exec_op
# good: [4795375d8aa072e9aacb0b278e6203c6ca41816a] ASoC: cs-amp-lib-test: Add test cases for cs_amp_set_efi_calibration_data()
# good: [d29479abaded34b2b1dab2e17efe96a65eba3d61] ASoC: renesas: fsi: Constify struct fsi_stream_handler
# good: [e973dfe9259095fb509ab12658c68d46f0e439d7] ASoC: qcom: sm8250: add qrb2210-sndcard compatible string
# good: [c17fa4cbc546c431ccf13e9354d5d9c1cd247b7c] ASoC: sdw_utils: add name_prefix for rt1321 part id
# good: [2528c15f314ece50218d1273654f630d74109583] ASoC: max98090/91: adding DAPM routing for digital output for max98091
# good: [d054cc3a2ccfb19484f3b54d69b6e416832dc8f4] regulator: rpmh-regulator: Add RPMH regulator support for PMR735D
# good: [310bf433c01f78e0756fd5056a43118a2f77318c] ASoC: max98090/91: fixing a space
# good: [fd5ef3d69f8975bad16c437a337b5cb04c8217a2] spi: spi-qpic-snand: make qcom_spi_ecc_engine_ops_pipelined const
# good: [638bae3fb225a708dc67db613af62f6d14c4eff4] ASoC: max98090/91: added DAPM widget for digital output for max98091
# good: [ecba655bf54a661ffe078856cd8dbc898270e4b5] ASoC: fsl_aud2htx: add IEC958_SUBFRAME_LE format in supported list
# good: [7e1906643a7374529af74b013bba35e4fa4e6ffc] ASoC: codecs: va-macro: Clean up on error path in probe()
# good: [d742ebcfe524dc54023f7c520d2ed2e4b7203c19] ASoC: soc.h: remove snd_soc_kcontrol_component()
# good: [6658472a3e2de08197acfe099ba71ee0e2505ecf] ASoC: amd: amd_sdw: Propagate the PCI subsystem Vendor and Device IDs
# good: [fce217449075d59b29052b8cdac567f0f3e22641] ASoC: spacemit: add i2s support for K1 SoC
# good: [0cc08c8130ac8f74419f99fe707dc193b7f79d86] spi: aspeed: Fix an IS_ERR() vs NULL bug in probe()
# good: [0743acf746a81e0460a56fd5ff847d97fa7eb370] spi: airoha: buffer must be 0xff-ed before writing
# good: [d77daa49085b067137d0adbe3263f75a7ee13a1b] spi: aspeed: fix spelling mistake "triming" -> "trimming"
# good: [15afe57a874eaf104bfbb61ec598fa31627f7b19] ASoC: dt-bindings: qcom: Add Kaanapali LPASS macro codecs
# good: [1e570e77392f43a3cdab2849d1f81535f8a033e2] ASoC: mxs-saif: support usage with simple-audio-card
# good: [fb25114cd760c13cf177d9ac37837fafcc9657b5] regulator: sy7636a: add gpios and input regulator
# good: [6621b0f118d500092f5f3d72ddddb22aeeb3c3a0] ASoC: codecs: rt5670: use SOC_VALUE_ENUM_SINGLE_DECL for DAC2 L/R MX-1B
# good: [65efe5404d151767653c7b7dd39bd2e7ad532c2d] regulator: rpmh-regulator: Add RPMH regulator support for Glymur
# good: [433e294c3c5b5d2020085a0e36c1cb47b694690a] regulator: core: forward undervoltage events downstream by default
# good: [0b0eb7702a9fa410755e86124b4b7cd36e7d1cb4] ASoC: replace use of system_wq with system_dfl_wq
# good: [bf770d6d2097a52d87f4d9c88d0b05bd3998d7de] x86/module: Improve relocation error messages
# good: [c2d420796a427dda71a2400909864e7f8e037fd4] elfnote: Change ELFNOTE() to use __UNIQUE_ID()
# good: [7e7e2c6e2a1cb250f8d03bb99eed01f6d982d5dd] ASoC: sof-function-topology-lib: escalate the log when missing function topoplogy
# good: [64d87ccfae3326a9561fe41dc6073064a083e0df] spi: aspeed: Only map necessary address window region
# good: [4d410ba9aa275e7990a270f63ce436990ace1bea] dt-bindings: sound: Update ADMAIF bindings for tegra264
# good: [5e537031f322d55315cd384398b726a9a0748d47] ASoC: codecs: Fix the error of excessive semicolons
# good: [4412ab501677606436e5c49e41151a1e6eac7ac0] spi: dt-bindings: spi-qpic-snand: Add IPQ5332 compatible
# good: [9797329220a2c6622411eb9ecf6a35b24ce09d04] ASoC: sof-function-topology-lib: escalate the log when missing function topoplogy
# good: [fe8cc44dd173cde5788ab4e3730ac61f3d316d9c] spi: dw: add target mode support
# good: [6277a486a7faaa6c87f4bf1d59a2de233a093248] regulator: dt-bindings: Convert Dialog DA9211 Regulators to DT schema
# good: [b83fb1b14c06bdd765903ac852ba20a14e24f227] spi: offload: Add offset parameter
git bisect start 'fe4d0dea039f2befb93f27569593ec209843b0f5' 'ef96b7dd050abd62905588c41ffb397e0c9598c7' 'bd79452b39c21599e2cff42e9fbeb182656b6f6a' '21e68bcb1b0c688c2d9ca0d457922febac650ac1' '96498e804cb6629e02747336a0a33e4955449732' '4422df6782eb7aa9725a3c09d9ba3c38ecc85df4' '9e510e677090bb794b46348b10e1c8038286e00a' '118eb2cb97b8fc0d515bb0449495959247db58f0' 'd5c8b7902a41625ea328b52c78ebe750fbf6fef7' '6402ddf3027d8975f135cf2b2014d6bbeb2d3436' '059f545832be85d29ac9ccc416a16f647aa78485' '4e00135b2dd1d7924a58bffa551b6ceb3bd836f2' 'e65b871c9b5af9265aefc5b8cd34993586d93aab' '8d63e85c5b50f1dbfa0ccb214bd91fe5d7e2e860' '8ff3dcb0e8a8bf6c41f23ed4aa62d066d3948a10' '123cd174a3782307787268adf45f22de4d290128' '1d562ba0aa7df81335bf96c02be77efe8d5bab87' '4d6e2211aeb932e096f673c88475016b1cc0f8ab' '32172cf3cb543a04c41a1677c97a38e60cad05b6' 'b3a5302484033331af37569f7277d00131694b57' '873bc94689d832878befbcadc10b6ad5bb4e0027' '772ada50282b0c80343c8989147db816961f571d' '6985defd1d832f1dd9d1977a6a2cc2cef7632704' 'fb1ebb10468da414d57153ddebaab29c38ef1a78' '2089f086303b773e181567fd8d5df3038bd85937' '6951be397ca8b8b167c9f99b5a11c541148c38cb' '4e92abd0a11b91af3742197a9ca962c3c00d0948' 'abc9a349b87ac0fd3ba8787ca00971b59c2e1257' '55d03b5b5bdd04daf9a35ce49db18d8bb488dffb' '6bd1ad97eb790570c167d4de4ca59fbc9c33722a' '1b0f3f9ee41ee2bdd206667f85ea2aa36dfe6e69' '3c36965df80801344850388592e95033eceea05b' '2f538ef9f6f7c3d700c68536f21447dfc598f8c8' 'aa897ffc396b48cc39eee133b6b43175d0df9eb5' '655079ac8a7721ac215a0596e3f33b740e01144a' 'c4e68959af66df525d71db619ffe44af9178bb22' '380fd29d57abe6679d87ec56babe65ddc5873a37' 'af9c8092d84244ca54ffb590435735f788e7a170' '84194c66aaf78fed150edb217b9f341518b1cba2' '252abf2d07d33b1c70a59ba1c9395ba42bbd793e' '2ecc8c089802e033d2e5204d21a9f467e2517df9' 'ed5d499b5c9cc11dd3edae1a7a55db7dfa4f1bdc' 'e73b743bfe8a6ff4e05b5657d3f7586a17ac3ba0' 'f1dfbc1b5cf8650ae9a0d543e5f5335fc0f478ce' 'ecd0de438c1f0ee86cf8f6d5047965a2a181444b' '6ef8e042cdcaabe3e3c68592ba8bfbaee2fa10a3' '20bcda681f8597e86070a4b3b12d1e4f541865d3' 'cf6bf51b53252284bafc7377a4d8dbf10f048b4d' '28039efa4d8e8bbf98b066133a906bd4e307d496' 'e062bdfdd6adbb2dee7751d054c1d8df63ddb8b8' '8fdb030fe283c84fd8d378c97ad0f32d6cdec6ce' '66fecfa91deb536a12ddf3d878a99590d7900277' 'f034c16a4663eaf3198dc18b201ba50533fb5b81' '4a5ac6cd05a7e54f1585d7779464d6ed6272c134' 'ef042df96d0e1089764f39ede61bc8f140a4be00' '4c33cef58965eb655a0ac8e243aa323581ec025f' '01313661b248c5ba586acae09bff57077dbec0a5' 'e7434adf0c53a84d548226304cdb41c8818da1cb' '77a58ba7c64ccca20616aa03599766ccb0d1a330' '4795375d8aa072e9aacb0b278e6203c6ca41816a' 'd29479abaded34b2b1dab2e17efe96a65eba3d61' 'e973dfe9259095fb509ab12658c68d46f0e439d7' 'c17fa4cbc546c431ccf13e9354d5d9c1cd247b7c' '2528c15f314ece50218d1273654f630d74109583' 'd054cc3a2ccfb19484f3b54d69b6e416832dc8f4' '310bf433c01f78e0756fd5056a43118a2f77318c' 'fd5ef3d69f8975bad16c437a337b5cb04c8217a2' '638bae3fb225a708dc67db613af62f6d14c4eff4' 'ecba655bf54a661ffe078856cd8dbc898270e4b5' '7e1906643a7374529af74b013bba35e4fa4e6ffc' 'd742ebcfe524dc54023f7c520d2ed2e4b7203c19' '6658472a3e2de08197acfe099ba71ee0e2505ecf' 'fce217449075d59b29052b8cdac567f0f3e22641' '0cc08c8130ac8f74419f99fe707dc193b7f79d86' '0743acf746a81e0460a56fd5ff847d97fa7eb370' 'd77daa49085b067137d0adbe3263f75a7ee13a1b' '15afe57a874eaf104bfbb61ec598fa31627f7b19' '1e570e77392f43a3cdab2849d1f81535f8a033e2' 'fb25114cd760c13cf177d9ac37837fafcc9657b5' '6621b0f118d500092f5f3d72ddddb22aeeb3c3a0' '65efe5404d151767653c7b7dd39bd2e7ad532c2d' '433e294c3c5b5d2020085a0e36c1cb47b694690a' '0b0eb7702a9fa410755e86124b4b7cd36e7d1cb4' 'bf770d6d2097a52d87f4d9c88d0b05bd3998d7de' 'c2d420796a427dda71a2400909864e7f8e037fd4' '7e7e2c6e2a1cb250f8d03bb99eed01f6d982d5dd' '64d87ccfae3326a9561fe41dc6073064a083e0df' '4d410ba9aa275e7990a270f63ce436990ace1bea' '5e537031f322d55315cd384398b726a9a0748d47' '4412ab501677606436e5c49e41151a1e6eac7ac0' '9797329220a2c6622411eb9ecf6a35b24ce09d04' 'fe8cc44dd173cde5788ab4e3730ac61f3d316d9c' '6277a486a7faaa6c87f4bf1d59a2de233a093248' 'b83fb1b14c06bdd765903ac852ba20a14e24f227'
# test job: [bd79452b39c21599e2cff42e9fbeb182656b6f6a] https://lava.sirena.org.uk/scheduler/job/2104091
# test job: [21e68bcb1b0c688c2d9ca0d457922febac650ac1] https://lava.sirena.org.uk/scheduler/job/2104499
# test job: [96498e804cb6629e02747336a0a33e4955449732] https://lava.sirena.org.uk/scheduler/job/2099744
# test job: [4422df6782eb7aa9725a3c09d9ba3c38ecc85df4] https://lava.sirena.org.uk/scheduler/job/2097747
# test job: [9e510e677090bb794b46348b10e1c8038286e00a] https://lava.sirena.org.uk/scheduler/job/2095684
# test job: [118eb2cb97b8fc0d515bb0449495959247db58f0] https://lava.sirena.org.uk/scheduler/job/2092525
# test job: [d5c8b7902a41625ea328b52c78ebe750fbf6fef7] https://lava.sirena.org.uk/scheduler/job/2092722
# test job: [6402ddf3027d8975f135cf2b2014d6bbeb2d3436] https://lava.sirena.org.uk/scheduler/job/2086597
# test job: [059f545832be85d29ac9ccc416a16f647aa78485] https://lava.sirena.org.uk/scheduler/job/2086754
# test job: [4e00135b2dd1d7924a58bffa551b6ceb3bd836f2] https://lava.sirena.org.uk/scheduler/job/2082525
# test job: [e65b871c9b5af9265aefc5b8cd34993586d93aab] https://lava.sirena.org.uk/scheduler/job/2083134
# test job: [8d63e85c5b50f1dbfa0ccb214bd91fe5d7e2e860] https://lava.sirena.org.uk/scheduler/job/2082576
# test job: [8ff3dcb0e8a8bf6c41f23ed4aa62d066d3948a10] https://lava.sirena.org.uk/scheduler/job/2083116
# test job: [123cd174a3782307787268adf45f22de4d290128] https://lava.sirena.org.uk/scheduler/job/2078967
# test job: [1d562ba0aa7df81335bf96c02be77efe8d5bab87] https://lava.sirena.org.uk/scheduler/job/2078346
# test job: [4d6e2211aeb932e096f673c88475016b1cc0f8ab] https://lava.sirena.org.uk/scheduler/job/2078001
# test job: [32172cf3cb543a04c41a1677c97a38e60cad05b6] https://lava.sirena.org.uk/scheduler/job/2075073
# test job: [b3a5302484033331af37569f7277d00131694b57] https://lava.sirena.org.uk/scheduler/job/2074546
# test job: [873bc94689d832878befbcadc10b6ad5bb4e0027] https://lava.sirena.org.uk/scheduler/job/2074833
# test job: [772ada50282b0c80343c8989147db816961f571d] https://lava.sirena.org.uk/scheduler/job/2069152
# test job: [6985defd1d832f1dd9d1977a6a2cc2cef7632704] https://lava.sirena.org.uk/scheduler/job/2059121
# test job: [fb1ebb10468da414d57153ddebaab29c38ef1a78] https://lava.sirena.org.uk/scheduler/job/2059787
# test job: [2089f086303b773e181567fd8d5df3038bd85937] https://lava.sirena.org.uk/scheduler/job/2058104
# test job: [6951be397ca8b8b167c9f99b5a11c541148c38cb] https://lava.sirena.org.uk/scheduler/job/2055777
# test job: [4e92abd0a11b91af3742197a9ca962c3c00d0948] https://lava.sirena.org.uk/scheduler/job/2055848
# test job: [abc9a349b87ac0fd3ba8787ca00971b59c2e1257] https://lava.sirena.org.uk/scheduler/job/2054637
# test job: [55d03b5b5bdd04daf9a35ce49db18d8bb488dffb] https://lava.sirena.org.uk/scheduler/job/2053889
# test job: [6bd1ad97eb790570c167d4de4ca59fbc9c33722a] https://lava.sirena.org.uk/scheduler/job/2053541
# test job: [1b0f3f9ee41ee2bdd206667f85ea2aa36dfe6e69] https://lava.sirena.org.uk/scheduler/job/2053565
# test job: [3c36965df80801344850388592e95033eceea05b] https://lava.sirena.org.uk/scheduler/job/2049494
# test job: [2f538ef9f6f7c3d700c68536f21447dfc598f8c8] https://lava.sirena.org.uk/scheduler/job/2048656
# test job: [aa897ffc396b48cc39eee133b6b43175d0df9eb5] https://lava.sirena.org.uk/scheduler/job/2048772
# test job: [655079ac8a7721ac215a0596e3f33b740e01144a] https://lava.sirena.org.uk/scheduler/job/2049697
# test job: [c4e68959af66df525d71db619ffe44af9178bb22] https://lava.sirena.org.uk/scheduler/job/2044037
# test job: [380fd29d57abe6679d87ec56babe65ddc5873a37] https://lava.sirena.org.uk/scheduler/job/2044746
# test job: [af9c8092d84244ca54ffb590435735f788e7a170] https://lava.sirena.org.uk/scheduler/job/2043671
# test job: [84194c66aaf78fed150edb217b9f341518b1cba2] https://lava.sirena.org.uk/scheduler/job/2038356
# test job: [252abf2d07d33b1c70a59ba1c9395ba42bbd793e] https://lava.sirena.org.uk/scheduler/job/2038551
# test job: [2ecc8c089802e033d2e5204d21a9f467e2517df9] https://lava.sirena.org.uk/scheduler/job/2038657
# test job: [ed5d499b5c9cc11dd3edae1a7a55db7dfa4f1bdc] https://lava.sirena.org.uk/scheduler/job/2029002
# test job: [e73b743bfe8a6ff4e05b5657d3f7586a17ac3ba0] https://lava.sirena.org.uk/scheduler/job/2026439
# test job: [f1dfbc1b5cf8650ae9a0d543e5f5335fc0f478ce] https://lava.sirena.org.uk/scheduler/job/2025521
# test job: [ecd0de438c1f0ee86cf8f6d5047965a2a181444b] https://lava.sirena.org.uk/scheduler/job/2026118
# test job: [6ef8e042cdcaabe3e3c68592ba8bfbaee2fa10a3] https://lava.sirena.org.uk/scheduler/job/2025847
# test job: [20bcda681f8597e86070a4b3b12d1e4f541865d3] https://lava.sirena.org.uk/scheduler/job/2022995
# test job: [cf6bf51b53252284bafc7377a4d8dbf10f048b4d] https://lava.sirena.org.uk/scheduler/job/2023023
# test job: [28039efa4d8e8bbf98b066133a906bd4e307d496] https://lava.sirena.org.uk/scheduler/job/2020299
# test job: [e062bdfdd6adbb2dee7751d054c1d8df63ddb8b8] https://lava.sirena.org.uk/scheduler/job/2020172
# test job: [8fdb030fe283c84fd8d378c97ad0f32d6cdec6ce] https://lava.sirena.org.uk/scheduler/job/2021459
# test job: [66fecfa91deb536a12ddf3d878a99590d7900277] https://lava.sirena.org.uk/scheduler/job/2015314
# test job: [f034c16a4663eaf3198dc18b201ba50533fb5b81] https://lava.sirena.org.uk/scheduler/job/2015467
# test job: [4a5ac6cd05a7e54f1585d7779464d6ed6272c134] https://lava.sirena.org.uk/scheduler/job/2011273
# test job: [ef042df96d0e1089764f39ede61bc8f140a4be00] https://lava.sirena.org.uk/scheduler/job/2010164
# test job: [4c33cef58965eb655a0ac8e243aa323581ec025f] https://lava.sirena.org.uk/scheduler/job/2009454
# test job: [01313661b248c5ba586acae09bff57077dbec0a5] https://lava.sirena.org.uk/scheduler/job/2008766
# test job: [e7434adf0c53a84d548226304cdb41c8818da1cb] https://lava.sirena.org.uk/scheduler/job/2007795
# test job: [77a58ba7c64ccca20616aa03599766ccb0d1a330] https://lava.sirena.org.uk/scheduler/job/2007309
# test job: [4795375d8aa072e9aacb0b278e6203c6ca41816a] https://lava.sirena.org.uk/scheduler/job/2009693
# test job: [d29479abaded34b2b1dab2e17efe96a65eba3d61] https://lava.sirena.org.uk/scheduler/job/2008426
# test job: [e973dfe9259095fb509ab12658c68d46f0e439d7] https://lava.sirena.org.uk/scheduler/job/2008132
# test job: [c17fa4cbc546c431ccf13e9354d5d9c1cd247b7c] https://lava.sirena.org.uk/scheduler/job/2000029
# test job: [2528c15f314ece50218d1273654f630d74109583] https://lava.sirena.org.uk/scheduler/job/1997624
# test job: [d054cc3a2ccfb19484f3b54d69b6e416832dc8f4] https://lava.sirena.org.uk/scheduler/job/1995769
# test job: [310bf433c01f78e0756fd5056a43118a2f77318c] https://lava.sirena.org.uk/scheduler/job/1996063
# test job: [fd5ef3d69f8975bad16c437a337b5cb04c8217a2] https://lava.sirena.org.uk/scheduler/job/1996144
# test job: [638bae3fb225a708dc67db613af62f6d14c4eff4] https://lava.sirena.org.uk/scheduler/job/1991895
# test job: [ecba655bf54a661ffe078856cd8dbc898270e4b5] https://lava.sirena.org.uk/scheduler/job/1985163
# test job: [7e1906643a7374529af74b013bba35e4fa4e6ffc] https://lava.sirena.org.uk/scheduler/job/1978631
# test job: [d742ebcfe524dc54023f7c520d2ed2e4b7203c19] https://lava.sirena.org.uk/scheduler/job/1975980
# test job: [6658472a3e2de08197acfe099ba71ee0e2505ecf] https://lava.sirena.org.uk/scheduler/job/1975543
# test job: [fce217449075d59b29052b8cdac567f0f3e22641] https://lava.sirena.org.uk/scheduler/job/1975685
# test job: [0cc08c8130ac8f74419f99fe707dc193b7f79d86] https://lava.sirena.org.uk/scheduler/job/1965718
# test job: [0743acf746a81e0460a56fd5ff847d97fa7eb370] https://lava.sirena.org.uk/scheduler/job/1964864
# test job: [d77daa49085b067137d0adbe3263f75a7ee13a1b] https://lava.sirena.org.uk/scheduler/job/1962775
# test job: [15afe57a874eaf104bfbb61ec598fa31627f7b19] https://lava.sirena.org.uk/scheduler/job/1962957
# test job: [1e570e77392f43a3cdab2849d1f81535f8a033e2] https://lava.sirena.org.uk/scheduler/job/1962291
# test job: [fb25114cd760c13cf177d9ac37837fafcc9657b5] https://lava.sirena.org.uk/scheduler/job/1960165
# test job: [6621b0f118d500092f5f3d72ddddb22aeeb3c3a0] https://lava.sirena.org.uk/scheduler/job/1959743
# test job: [65efe5404d151767653c7b7dd39bd2e7ad532c2d] https://lava.sirena.org.uk/scheduler/job/1959980
# test job: [433e294c3c5b5d2020085a0e36c1cb47b694690a] https://lava.sirena.org.uk/scheduler/job/1957437
# test job: [0b0eb7702a9fa410755e86124b4b7cd36e7d1cb4] https://lava.sirena.org.uk/scheduler/job/1957381
# test job: [bf770d6d2097a52d87f4d9c88d0b05bd3998d7de] https://lava.sirena.org.uk/scheduler/job/1986562
# test job: [c2d420796a427dda71a2400909864e7f8e037fd4] https://lava.sirena.org.uk/scheduler/job/1986677
# test job: [7e7e2c6e2a1cb250f8d03bb99eed01f6d982d5dd] https://lava.sirena.org.uk/scheduler/job/1954262
# test job: [64d87ccfae3326a9561fe41dc6073064a083e0df] https://lava.sirena.org.uk/scheduler/job/1947255
# test job: [4d410ba9aa275e7990a270f63ce436990ace1bea] https://lava.sirena.org.uk/scheduler/job/1947749
# test job: [5e537031f322d55315cd384398b726a9a0748d47] https://lava.sirena.org.uk/scheduler/job/1946642
# test job: [4412ab501677606436e5c49e41151a1e6eac7ac0] https://lava.sirena.org.uk/scheduler/job/1946288
# test job: [9797329220a2c6622411eb9ecf6a35b24ce09d04] https://lava.sirena.org.uk/scheduler/job/1947398
# test job: [fe8cc44dd173cde5788ab4e3730ac61f3d316d9c] https://lava.sirena.org.uk/scheduler/job/1946085
# test job: [6277a486a7faaa6c87f4bf1d59a2de233a093248] https://lava.sirena.org.uk/scheduler/job/1947023
# test job: [b83fb1b14c06bdd765903ac852ba20a14e24f227] https://lava.sirena.org.uk/scheduler/job/1946841
# test job: [fe4d0dea039f2befb93f27569593ec209843b0f5] https://lava.sirena.org.uk/scheduler/job/2106243
# bad: [fe4d0dea039f2befb93f27569593ec209843b0f5] Add linux-next specific files for 20251119
git bisect bad fe4d0dea039f2befb93f27569593ec209843b0f5
# test job: [c8e2262ce3e7658f7689975d66bbdecaf2cf95f9] https://lava.sirena.org.uk/scheduler/job/2106516
# bad: [c8e2262ce3e7658f7689975d66bbdecaf2cf95f9] Merge branch 'master' of https://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git
git bisect bad c8e2262ce3e7658f7689975d66bbdecaf2cf95f9
# test job: [2d48532d7f2e7d165f29ca9f2cdd589d9a8c2554] https://lava.sirena.org.uk/scheduler/job/2106588
# bad: [2d48532d7f2e7d165f29ca9f2cdd589d9a8c2554] Merge branch 'fs-next' of linux-next
git bisect bad 2d48532d7f2e7d165f29ca9f2cdd589d9a8c2554
# test job: [f80c4f29e62d88f612101dc7addb0cc7a3bc628d] https://lava.sirena.org.uk/scheduler/job/2106622
# bad: [f80c4f29e62d88f612101dc7addb0cc7a3bc628d] Merge branch 'next' of https://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-devel.git
git bisect bad f80c4f29e62d88f612101dc7addb0cc7a3bc628d
# test job: [b7ea3276cbe7ea3cb272c4f7fc0f38db6ea7f1ed] https://lava.sirena.org.uk/scheduler/job/2106673
# bad: [b7ea3276cbe7ea3cb272c4f7fc0f38db6ea7f1ed] Merge branch 'at91-next' of https://git.kernel.org/pub/scm/linux/kernel/git/at91/linux.git
git bisect bad b7ea3276cbe7ea3cb272c4f7fc0f38db6ea7f1ed
# test job: [e92c9e71a82b75ce8297b60db4693af85ef4593b] https://lava.sirena.org.uk/scheduler/job/2106728
# bad: [e92c9e71a82b75ce8297b60db4693af85ef4593b] Merge branch 'mm-unstable' of https://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm
git bisect bad e92c9e71a82b75ce8297b60db4693af85ef4593b
# test job: [7d808bf13943f4c6a6142400bffe14267f6dc997] https://lava.sirena.org.uk/scheduler/job/2106774
# good: [7d808bf13943f4c6a6142400bffe14267f6dc997] mm/damon/tests/sysfs-kunit: handle alloc failures on damon_sysfs_test_add_targets()
git bisect good 7d808bf13943f4c6a6142400bffe14267f6dc997
# test job: [93f3c3ac6e9a0695dec5ca8c5aa0fdc7ada3293e] https://lava.sirena.org.uk/scheduler/job/2106827
# bad: [93f3c3ac6e9a0695dec5ca8c5aa0fdc7ada3293e] mm: vmstat: correct the comment above preempt_disable_nested()
git bisect bad 93f3c3ac6e9a0695dec5ca8c5aa0fdc7ada3293e
# test job: [16cdd4e5a52b421b27b598b9eee3cd18212944a1] https://lava.sirena.org.uk/scheduler/job/2106960
# good: [16cdd4e5a52b421b27b598b9eee3cd18212944a1] migrate: optimise alloc_migration_target()
git bisect good 16cdd4e5a52b421b27b598b9eee3cd18212944a1
# test job: [3da23b1058cde436f5ab711f4597dbe75865ea38] https://lava.sirena.org.uk/scheduler/job/2107042
# bad: [3da23b1058cde436f5ab711f4597dbe75865ea38] tools/testing/selftests/mm: add smaps visibility guard region test
git bisect bad 3da23b1058cde436f5ab711f4597dbe75865ea38
# test job: [6b82275fdba27802ad7ec6910b86d83bea2dda8d] https://lava.sirena.org.uk/scheduler/job/2107095
# good: [6b82275fdba27802ad7ec6910b86d83bea2dda8d] mm: add atomic VMA flags and set VM_MAYBE_GUARD as such
git bisect good 6b82275fdba27802ad7ec6910b86d83bea2dda8d
# test job: [b331f7745489548c5a020301f6f3b4aad20c7b77] https://lava.sirena.org.uk/scheduler/job/2107146
# bad: [b331f7745489548c5a020301f6f3b4aad20c7b77] mm: introduce copy-on-fork VMAs and make VM_MAYBE_GUARD one
git bisect bad b331f7745489548c5a020301f6f3b4aad20c7b77
# test job: [f24f3801039f9a2033e3a2390fccc5adc00a8df7] https://lava.sirena.org.uk/scheduler/job/2107157
# good: [f24f3801039f9a2033e3a2390fccc5adc00a8df7] mm: implement sticky VMA flags
git bisect good f24f3801039f9a2033e3a2390fccc5adc00a8df7
# test job: [2c91ae77d8fbafb153c13e554f50b7bbeef59d76] https://lava.sirena.org.uk/scheduler/job/2107231
# bad: [2c91ae77d8fbafb153c13e554f50b7bbeef59d76] mm-implement-sticky-vma-flags-fix-2
git bisect bad 2c91ae77d8fbafb153c13e554f50b7bbeef59d76
# test job: [79ee48c12ef8fe9a3daf0dbeda74f038a3f557be] https://lava.sirena.org.uk/scheduler/job/2107257
# bad: [79ee48c12ef8fe9a3daf0dbeda74f038a3f557be] mm-implement-sticky-vma-flags-fix
git bisect bad 79ee48c12ef8fe9a3daf0dbeda74f038a3f557be
# first bad commit: [79ee48c12ef8fe9a3daf0dbeda74f038a3f557be] mm-implement-sticky-vma-flags-fix

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply

* Re: [PATCH v3 00/21] treewide: Introduce %ptS for struct timespec64 and convert users
From: Petr Mladek @ 2025-11-19 13:11 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Corey Minyard, Christian König, Dr. David Alan Gilbert,
	Alex Deucher, Thomas Zimmermann, Dmitry Baryshkov, Rob Clark,
	Matthew Brost, Ulf Hansson, Aleksandr Loktionov, Vitaly Lifshits,
	Manivannan Sadhasivam, Niklas Cassel, Calvin Owens,
	Vadim Fedorenko, Sagi Maimon, Martin K. Petersen,
	Karan Tilak Kumar, Hans Verkuil, Casey Schaufler, Steven Rostedt,
	Viacheslav Dubeyko, Max Kellermann, linux-doc, linux-kernel,
	openipmi-developer, linux-media, dri-devel, linaro-mm-sig,
	amd-gfx, linux-arm-msm, freedreno, intel-xe, linux-mmc, netdev,
	intel-wired-lan, linux-pci, linux-s390, linux-scsi, linux-staging,
	ceph-devel, linux-trace-kernel, Rasmus Villemoes,
	Sergey Senozhatsky, Jonathan Corbet, Sumit Semwal,
	Gustavo Padovan, David Airlie, Simona Vetter, Maarten Lankhorst,
	Maxime Ripard, Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang,
	Sean Paul, Marijn Suijten, Konrad Dybcio, Lucas De Marchi,
	Thomas Hellström, Rodrigo Vivi, Vladimir Oltean, Andrew Lunn,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Tony Nguyen, Przemek Kitszel, Krzysztof Wilczyński,
	Kishon Vijay Abraham I, Bjorn Helgaas, Rodolfo Giometti,
	Jonathan Lemon, Richard Cochran, Stefan Haberland, Jan Hoeppner,
	Heiko Carstens, Vasily Gorbik, Alexander Gordeev,
	Christian Borntraeger, Sven Schnelle, Satish Kharat,
	Sesidhar Baddela, James E.J. Bottomley, Mauro Carvalho Chehab,
	Greg Kroah-Hartman, Xiubo Li, Ilya Dryomov, Masami Hiramatsu,
	Mathieu Desnoyers, Andrew Morton
In-Reply-To: <20251113150217.3030010-1-andriy.shevchenko@linux.intel.com>

On Thu 2025-11-13 15:32:14, Andy Shevchenko wrote:
> Here is the third part of the unification time printing in the kernel.
> This time for struct timespec64. The first patch brings a support
> into printf() implementation (test cases and documentation update
> included) followed by the treewide conversion of the current users.
> 
> Petr, we got like more than a half being Acked, I think if you are okay
> with this, the patches that have been tagged can be applied.
> 
> Note, not everything was compile-tested. Kunit test has been passed, though.

JFYI, the patchset has been committed into printk/linux.git,
branch for-6.19-vsprintf-timespec64.

Note, that I have:

   + fixed the 19th patch as proposed, see
     https://lore.kernel.org/all/aR2XAYWTEgMZu_Mx@pathway.suse.cz/

   + reviewed all patches but I triple checked 7th patch which
     did not have any ack yet. And I added my Reviewed-by tag
     there. ;-)

   + I tried build with allyesconfig. It succeeded. I am not 100%
     sure that it built all modified sources but...

Best Regards,
Petr

^ permalink raw reply

* Re: [PATCH v3 3/8] mm: implement sticky VMA flags
From: Mark Brown @ 2025-11-19 13:16 UTC (permalink / raw)
  To: Lorenzo Stoakes
  Cc: Andrew Morton, Jonathan Corbet, David Hildenbrand,
	Liam R . Howlett, Vlastimil Babka, Mike Rapoport,
	Suren Baghdasaryan, Michal Hocko, Steven Rostedt,
	Masami Hiramatsu, Mathieu Desnoyers, Jann Horn, Pedro Falcato,
	Zi Yan, Baolin Wang, Nico Pache, Ryan Roberts, Dev Jain,
	Barry Song, Lance Yang, linux-kernel, linux-fsdevel, linux-doc,
	linux-mm, linux-trace-kernel, linux-kselftest, Andrei Vagin,
	Aishwarya.TCV
In-Reply-To: <1ee529ff912f71b3460d0d21bc5b32ca89d63513.1762531708.git.lorenzo.stoakes@oracle.com>

[-- Attachment #1: Type: text/plain, Size: 32690 bytes --]

On Fri, Nov 07, 2025 at 04:11:48PM +0000, Lorenzo Stoakes wrote:
> It is useful to be able to designate that certain flags are 'sticky', that
> is, if two VMAs are merged one with a flag of this nature and one without,
> the merged VMA sets this flag.

I'm seeing regressions on multiple arm64 platforms in at least the LTP
clone302 and madvise10 selftests, both of which have bisected to one of
the fixups to this patch.  Especially given the other tests that also
bisected to the same place I've not investigated further.  There's a
number of other LTP tests that started failing today including relevant
seeming ones munlockall01, mprotect04, madvise10, mprotect03 and
futex_cmp_requeue01 but I don't have bisects to confirm they're the same
thing.

clone302:

tst_buffers.c:57: TINFO: Test is using guarded buffers
tst_tmpdir.c:316: TINFO: Using /tmp/LTP_clorMwMMw as tmpdir (nfs filesystem)
tst_test.c:1953: TINFO: LTP version: 20250530
tst_test.c:1956: TINFO: Tested kernel: 6.18.0-rc6-next-20251119 #1 SMP PREEMPT @1763523415 aarch64
tst_kconfig.c:88: TINFO: Parsing kernel config '/proc/config.gz'
tst_test.c:1774: TINFO: Overall timeout per run is 0h 05m 24s
clone302.c:61: TPASS: sizeof(struct clone_args_minimal) == 64 (64)
clone302.c:102: TPASS: invalid args: clone3() failed as expected: EFAULT (14)
clone302.c:102: TPASS: zero size: clone3() failed as expected: EINVAL (22)
clone302.c:102: TPASS: short size: clone3() failed as expected: EINVAL (22)
clone302.c:92: TFAIL: extra size: clone3() passed unexpectedly
clone302.c:102: TPASS: sighand-no-VM: clone3() failed as expected: EINVAL (22)
clone302.c:102: TPASS: thread-no-sighand: clone3() failed as expected: EINVAL (22)
clone302.c:102: TPASS: fs-newns: clone3() failed as expected: EINVAL (22)
clone302.c:102: TPASS: invalid pidfd: clone3() failed as expected: EFAULT (14)
clone302.c:102: TPASS: invalid signal: clone3() failed as expected: EINVAL (22)
clone302.c:102: TPASS: zero-stack-size: clone3() failed as expected: EINVAL (22)
clone302.c:102: TPASS: invalid-stack: clone3() failed as expected: EINVAL (22)

madvise10:

tst_test.c:1953: TINFO: LTP version: 20250530
tst_test.c:1956: TINFO: Tested kernel: 6.18.0-rc6-next-20251119 #1 SMP PREEMPT @1763523415 aarch64
tst_kconfig.c:88: TINFO: Parsing kernel config '/proc/config.gz'
tst_test.c:1774: TINFO: Overall timeout per run is 0h 05m 24s
madvise10.c:133: TINFO: MADV_WIPEONFORK zeroes memory in child
madvise10.c:107: TPASS: madvise(0xffffa8fbc000, 16384, 0x0)
madvise10.c:107: TPASS: madvise(0xffffa8fbc000, 16384, 0x12)
madvise10.c:88: TPASS: In PID 660, Matched expected pattern
madvise10.c:133: TINFO: MADV_WIPEONFORK with zero length does nothing
madvise10.c:107: TPASS: madvise(0xffffa8fbc000, 0, 0x0)
madvise10.c:107: TPASS: madvise(0xffffa8fbc000, 0, 0x12)
madvise10.c:88: TPASS: In PID 661, Matched expected pattern
madvise10.c:133: TINFO: MADV_WIPEONFORK zeroes memory in grand-child
madvise10.c:107: TPASS: madvise(0xffffa8fbc000, 16384, 0x0)
madvise10.c:107: TPASS: madvise(0xffffa8fbc000, 16384, 0x12)
madvise10.c:88: TPASS: In PID 663, Matched expected pattern
madvise10.c:133: TINFO: MADV_KEEPONFORK will undo MADV_WIPEONFORK
madvise10.c:107: TPASS: madvise(0xffffa8fbc000, 16384, 0x12)
madvise10.c:107: TPASS: madvise(0xffffa8fbc000, 16384, 0x13)
madvise10.c:81: TFAIL: In PID 664, addr[1] = 0x00, expected[1] = 0x01
madvise10.c:88: TPASS: In PID 664, Matched expected pattern

The bisects for both follow the same pattern:

# bad: [fe4d0dea039f2befb93f27569593ec209843b0f5] Add linux-next specific files for 20251119
# good: [ef96b7dd050abd62905588c41ffb397e0c9598c7] Merge branch 'for-linux-next-fixes' of https://gitlab.freedesktop.org/drm/misc/kernel.git
# good: [bd79452b39c21599e2cff42e9fbeb182656b6f6a] MAINTAINERS: adjust file entry in RISC-V MICROCHIP SUPPORT
# good: [21e68bcb1b0c688c2d9ca0d457922febac650ac1] regulator: renesas-usb-vbus-regulator: Remove unused headers
# good: [96498e804cb6629e02747336a0a33e4955449732] spi: davinci: remove platform data header
# good: [4422df6782eb7aa9725a3c09d9ba3c38ecc85df4] ASoC: ux500: mop500_ab8500: convert to snd_soc_dapm_xxx()
# good: [9e510e677090bb794b46348b10e1c8038286e00a] spi: aspeed: Add support for the AST2700 SPI controller
# good: [d5c8b7902a41625ea328b52c78ebe750fbf6fef7] ASoC: Intel: avs: Honor NHLT override when setting up a path
# good: [118eb2cb97b8fc0d515bb0449495959247db58f0] spi: bcm63xx: drop wrong casts in probe()
# good: [059f545832be85d29ac9ccc416a16f647aa78485] spi: add support for microchip "soft" spi controller
# good: [6402ddf3027d8975f135cf2b2014d6bbeb2d3436] MAINTAINERS: refer to trivial-codec.yaml in relevant sections
# good: [4e00135b2dd1d7924a58bffa551b6ceb3bd836f2] spi: spi-cadence: supports transmission with bits_per_word of 16 and 32
# good: [8ff3dcb0e8a8bf6c41f23ed4aa62d066d3948a10] ASoC: codecs: lpass-rx-macro: add SM6115 compatible
# good: [e65b871c9b5af9265aefc5b8cd34993586d93aab] ASoC: codecs: pm4125: Remove irq_chip on component unbind
# good: [8d63e85c5b50f1dbfa0ccb214bd91fe5d7e2e860] firmware: cs_dsp: fix kernel-doc warnings in a header file
# good: [123cd174a3782307787268adf45f22de4d290128] ASoC: Intel: atom: Replace strcpy() with strscpy()
# good: [4d6e2211aeb932e096f673c88475016b1cc0f8ab] ASoC: Intel: boards: fix HDMI playback lookup when HDMI-In capture used
# good: [1d562ba0aa7df81335bf96c02be77efe8d5bab87] spi: dt-bindings: nuvoton,npcm-pspi: Convert to DT schema
# good: [873bc94689d832878befbcadc10b6ad5bb4e0027] ASoC: Intel: sof_sdw: add codec speaker support for the SKU
# good: [32172cf3cb543a04c41a1677c97a38e60cad05b6] ASoC: cs35l56: Allow restoring factory calibration through ALSA control
# good: [b3a5302484033331af37569f7277d00131694b57] ASoC: Intel: sof_rt5682: Add quirk override support
# good: [772ada50282b0c80343c8989147db816961f571d] ASoC: cs35l56: Alter error codes for calibration routine
# good: [fb1ebb10468da414d57153ddebaab29c38ef1a78] regulator: core: disable supply if enabling main regulator fails
# good: [6985defd1d832f1dd9d1977a6a2cc2cef7632704] regmap: sdw-mbq: Reorder regmap_mbq_context struct for better packing
# good: [2089f086303b773e181567fd8d5df3038bd85937] regulator: mt6363: Remove unneeded semicolon
# good: [6951be397ca8b8b167c9f99b5a11c541148c38cb] ASoC: codecs: pm4125: remove duplicate code
# good: [4e92abd0a11b91af3742197a9ca962c3c00d0948] spi: imx: add i.MX51 ECSPI target mode support
# good: [abc9a349b87ac0fd3ba8787ca00971b59c2e1257] spi: fsl-qspi: support the SpacemiT K1 SoC
# good: [1b0f3f9ee41ee2bdd206667f85ea2aa36dfe6e69] ASoC: SDCA: support Q7.8 volume format
# good: [55d03b5b5bdd04daf9a35ce49db18d8bb488dffb] spi: imx: remove CLK calculation and check for target mode
# good: [6bd1ad97eb790570c167d4de4ca59fbc9c33722a] regulator: pf9453: Fix kernel doc for mux_poll()
# good: [655079ac8a7721ac215a0596e3f33b740e01144a] ASoC: qcom: q6asm: Use guard() for spin locks
# good: [2f538ef9f6f7c3d700c68536f21447dfc598f8c8] spi: aspeed: Use devm_iounmap() to unmap devm_ioremap() memory
# good: [3c36965df80801344850388592e95033eceea05b] regulator: Add support for MediaTek MT6363 SPMI PMIC Regulators
# good: [aa897ffc396b48cc39eee133b6b43175d0df9eb5] ASoC: dt-bindings: ti,pcm1862: convert to dtschema
# good: [c4e68959af66df525d71db619ffe44af9178bb22] ASoC: dt-bindings: ti,tas2781: Add TAS5822 support
# good: [380fd29d57abe6679d87ec56babe65ddc5873a37] spi: tegra210-quad: Check hardware status on timeout
# good: [af9c8092d84244ca54ffb590435735f788e7a170] regmap: i3c: Use ARRAY_SIZE()
# good: [2ecc8c089802e033d2e5204d21a9f467e2517df9] regulator: pf9453: remove unused I2C_LT register
# good: [84194c66aaf78fed150edb217b9f341518b1cba2] ASoC: codecs: aw88261: pass pointer directly instead of passing the address
# good: [252abf2d07d33b1c70a59ba1c9395ba42bbd793e] regulator: Small cleanup in of_get_regulation_constraints()
# good: [ed5d499b5c9cc11dd3edae1a7a55db7dfa4f1bdc] regcache: maple: Split ->populate() from ->init()
# good: [e73b743bfe8a6ff4e05b5657d3f7586a17ac3ba0] ASoC: soc-core: check ops & auto_selectable_formats in snd_soc_dai_get_fmt() to prevent dereference error
# good: [f1dfbc1b5cf8650ae9a0d543e5f5335fc0f478ce] ASoC: max98090/91: fixing the stream index
# good: [6ef8e042cdcaabe3e3c68592ba8bfbaee2fa10a3] ASoC: codec: wm8400: replace printk() calls with dev_*() device aware logging
# good: [ecd0de438c1f0ee86cf8f6d5047965a2a181444b] spi: tle62x0: Add newline to sysfs attribute output
# good: [cf6bf51b53252284bafc7377a4d8dbf10f048b4d] ASoC: cs4271: Add support for the external mclk
# good: [20bcda681f8597e86070a4b3b12d1e4f541865d3] ASoC: codecs: va-macro: fix revision checking
# good: [e062bdfdd6adbb2dee7751d054c1d8df63ddb8b8] regmap: warn users about uninitialized flat cache
# good: [8fdb030fe283c84fd8d378c97ad0f32d6cdec6ce] ASoC: qcom: sc7280: make use of common helpers
# good: [28039efa4d8e8bbf98b066133a906bd4e307d496] MAINTAINERS: remove obsolete file entry in DIALOG SEMICONDUCTOR DRIVERS
# good: [f034c16a4663eaf3198dc18b201ba50533fb5b81] ASoC: spacemit: add failure check for spacemit_i2s_init_dai()
# good: [66fecfa91deb536a12ddf3d878a99590d7900277] ASoC: spacemit: use `depends on` instead of `select`
# good: [4a5ac6cd05a7e54f1585d7779464d6ed6272c134] ASoC: sun4i-spdif: Support SPDIF output on A523 family
# good: [ef042df96d0e1089764f39ede61bc8f140a4be00] ASoC: SDCA: Add HID button IRQ
# good: [4c33cef58965eb655a0ac8e243aa323581ec025f] regulator: pca9450: link regulator inputs to supply groups
# good: [e7434adf0c53a84d548226304cdb41c8818da1cb] ASoC: cs530x: Add SPI bus support for cs530x parts
# good: [77a58ba7c64ccca20616aa03599766ccb0d1a330] spi: spi-mem: Trace exec_op
# good: [01313661b248c5ba586acae09bff57077dbec0a5] regulator: Let raspberrypi drivers depend on ARM
# good: [4795375d8aa072e9aacb0b278e6203c6ca41816a] ASoC: cs-amp-lib-test: Add test cases for cs_amp_set_efi_calibration_data()
# good: [d29479abaded34b2b1dab2e17efe96a65eba3d61] ASoC: renesas: fsi: Constify struct fsi_stream_handler
# good: [e973dfe9259095fb509ab12658c68d46f0e439d7] ASoC: qcom: sm8250: add qrb2210-sndcard compatible string
# good: [c17fa4cbc546c431ccf13e9354d5d9c1cd247b7c] ASoC: sdw_utils: add name_prefix for rt1321 part id
# good: [310bf433c01f78e0756fd5056a43118a2f77318c] ASoC: max98090/91: fixing a space
# good: [fd5ef3d69f8975bad16c437a337b5cb04c8217a2] spi: spi-qpic-snand: make qcom_spi_ecc_engine_ops_pipelined const
# good: [d054cc3a2ccfb19484f3b54d69b6e416832dc8f4] regulator: rpmh-regulator: Add RPMH regulator support for PMR735D
# good: [2528c15f314ece50218d1273654f630d74109583] ASoC: max98090/91: adding DAPM routing for digital output for max98091
# good: [638bae3fb225a708dc67db613af62f6d14c4eff4] ASoC: max98090/91: added DAPM widget for digital output for max98091
# good: [ecba655bf54a661ffe078856cd8dbc898270e4b5] ASoC: fsl_aud2htx: add IEC958_SUBFRAME_LE format in supported list
# good: [7e1906643a7374529af74b013bba35e4fa4e6ffc] ASoC: codecs: va-macro: Clean up on error path in probe()
# good: [d742ebcfe524dc54023f7c520d2ed2e4b7203c19] ASoC: soc.h: remove snd_soc_kcontrol_component()
# good: [6658472a3e2de08197acfe099ba71ee0e2505ecf] ASoC: amd: amd_sdw: Propagate the PCI subsystem Vendor and Device IDs
# good: [fce217449075d59b29052b8cdac567f0f3e22641] ASoC: spacemit: add i2s support for K1 SoC
# good: [5677aa6a08c1df8bc1ec71516fe1ced9b7cb545f] HID: intel-ish-hid: ipc: Separate hibernate callbacks in dev_pm_ops
# good: [0cc08c8130ac8f74419f99fe707dc193b7f79d86] spi: aspeed: Fix an IS_ERR() vs NULL bug in probe()
# good: [0743acf746a81e0460a56fd5ff847d97fa7eb370] spi: airoha: buffer must be 0xff-ed before writing
# good: [b1fc226edf8680882a5bf89038bdc55afa2ac80d] media: stm32: dma2d: Drop unneeded v4l2_m2m_get_vq() NULL check
# good: [15afe57a874eaf104bfbb61ec598fa31627f7b19] ASoC: dt-bindings: qcom: Add Kaanapali LPASS macro codecs
# good: [d77daa49085b067137d0adbe3263f75a7ee13a1b] spi: aspeed: fix spelling mistake "triming" -> "trimming"
# good: [1e570e77392f43a3cdab2849d1f81535f8a033e2] ASoC: mxs-saif: support usage with simple-audio-card
# good: [0d7f4e99217f6f715c7064c67eae8d9d09313b14] drm/i915/display: Introduce dp/psr_compute_config_late()
# good: [fb25114cd760c13cf177d9ac37837fafcc9657b5] regulator: sy7636a: add gpios and input regulator
# good: [65efe5404d151767653c7b7dd39bd2e7ad532c2d] regulator: rpmh-regulator: Add RPMH regulator support for Glymur
# good: [6621b0f118d500092f5f3d72ddddb22aeeb3c3a0] ASoC: codecs: rt5670: use SOC_VALUE_ENUM_SINGLE_DECL for DAC2 L/R MX-1B
# good: [433e294c3c5b5d2020085a0e36c1cb47b694690a] regulator: core: forward undervoltage events downstream by default
# good: [0b0eb7702a9fa410755e86124b4b7cd36e7d1cb4] ASoC: replace use of system_wq with system_dfl_wq
# good: [bf770d6d2097a52d87f4d9c88d0b05bd3998d7de] x86/module: Improve relocation error messages
# good: [c2d420796a427dda71a2400909864e7f8e037fd4] elfnote: Change ELFNOTE() to use __UNIQUE_ID()
# good: [7e7e2c6e2a1cb250f8d03bb99eed01f6d982d5dd] ASoC: sof-function-topology-lib: escalate the log when missing function topoplogy
# good: [4412ab501677606436e5c49e41151a1e6eac7ac0] spi: dt-bindings: spi-qpic-snand: Add IPQ5332 compatible
# good: [5e537031f322d55315cd384398b726a9a0748d47] ASoC: codecs: Fix the error of excessive semicolons
# good: [64d87ccfae3326a9561fe41dc6073064a083e0df] spi: aspeed: Only map necessary address window region
# good: [4d410ba9aa275e7990a270f63ce436990ace1bea] dt-bindings: sound: Update ADMAIF bindings for tegra264
# good: [9797329220a2c6622411eb9ecf6a35b24ce09d04] ASoC: sof-function-topology-lib: escalate the log when missing function topoplogy
# good: [fe8cc44dd173cde5788ab4e3730ac61f3d316d9c] spi: dw: add target mode support
# good: [6277a486a7faaa6c87f4bf1d59a2de233a093248] regulator: dt-bindings: Convert Dialog DA9211 Regulators to DT schema
# good: [b83fb1b14c06bdd765903ac852ba20a14e24f227] spi: offload: Add offset parameter
# good: [807c42dd8028d71222dfce035c2e87aaecbf623f] drm/xe: Don't change LRC ring head on job resubmission
# good: [6c177775dcc5e70a64ddf4ee842c66af498f2c7c] Merge branch 'next/drivers' into for-next
git bisect start 'fe4d0dea039f2befb93f27569593ec209843b0f5' 'ef96b7dd050abd62905588c41ffb397e0c9598c7' 'bd79452b39c21599e2cff42e9fbeb182656b6f6a' '21e68bcb1b0c688c2d9ca0d457922febac650ac1' '96498e804cb6629e02747336a0a33e4955449732' '4422df6782eb7aa9725a3c09d9ba3c38ecc85df4' '9e510e677090bb794b46348b10e1c8038286e00a' 'd5c8b7902a41625ea328b52c78ebe750fbf6fef7' '118eb2cb97b8fc0d515bb0449495959247db58f0' '059f545832be85d29ac9ccc416a16f647aa78485' '6402ddf3027d8975f135cf2b2014d6bbeb2d3436' '4e00135b2dd1d7924a58bffa551b6ceb3bd836f2' '8ff3dcb0e8a8bf6c41f23ed4aa62d066d3948a10' 'e65b871c9b5af9265aefc5b8cd34993586d93aab' '8d63e85c5b50f1dbfa0ccb214bd91fe5d7e2e860' '123cd174a3782307787268adf45f22de4d290128' '4d6e2211aeb932e096f673c88475016b1cc0f8ab' '1d562ba0aa7df81335bf96c02be77efe8d5bab87' '873bc94689d832878befbcadc10b6ad5bb4e0027' '32172cf3cb543a04c41a1677c97a38e60cad05b6' 'b3a5302484033331af37569f7277d00131694b57' '772ada50282b0c80343c8989147db816961f571d' 'fb1ebb10468da414d57153ddebaab29c38ef1a78' '6985defd1d832f1dd9d1977a6a2cc2cef7632704' '2089f086303b773e181567fd8d5df3038bd85937' '6951be397ca8b8b167c9f99b5a11c541148c38cb' '4e92abd0a11b91af3742197a9ca962c3c00d0948' 'abc9a349b87ac0fd3ba8787ca00971b59c2e1257' '1b0f3f9ee41ee2bdd206667f85ea2aa36dfe6e69' '55d03b5b5bdd04daf9a35ce49db18d8bb488dffb' '6bd1ad97eb790570c167d4de4ca59fbc9c33722a' '655079ac8a7721ac215a0596e3f33b740e01144a' '2f538ef9f6f7c3d700c68536f21447dfc598f8c8' '3c36965df80801344850388592e95033eceea05b' 'aa897ffc396b48cc39eee133b6b43175d0df9eb5' 'c4e68959af66df525d71db619ffe44af9178bb22' '380fd29d57abe6679d87ec56babe65ddc5873a37' 'af9c8092d84244ca54ffb590435735f788e7a170' '2ecc8c089802e033d2e5204d21a9f467e2517df9' '84194c66aaf78fed150edb217b9f341518b1cba2' '252abf2d07d33b1c70a59ba1c9395ba42bbd793e' 'ed5d499b5c9cc11dd3edae1a7a55db7dfa4f1bdc' 'e73b743bfe8a6ff4e05b5657d3f7586a17ac3ba0' 'f1dfbc1b5cf8650ae9a0d543e5f5335fc0f478ce' '6ef8e042cdcaabe3e3c68592ba8bfbaee2fa10a3' 'ecd0de438c1f0ee86cf8f6d5047965a2a181444b' 'cf6bf51b53252284bafc7377a4d8dbf10f048b4d' '20bcda681f8597e86070a4b3b12d1e4f541865d3' 'e062bdfdd6adbb2dee7751d054c1d8df63ddb8b8' '8fdb030fe283c84fd8d378c97ad0f32d6cdec6ce' '28039efa4d8e8bbf98b066133a906bd4e307d496' 'f034c16a4663eaf3198dc18b201ba50533fb5b81' '66fecfa91deb536a12ddf3d878a99590d7900277' '4a5ac6cd05a7e54f1585d7779464d6ed6272c134' 'ef042df96d0e1089764f39ede61bc8f140a4be00' '4c33cef58965eb655a0ac8e243aa323581ec025f' 'e7434adf0c53a84d548226304cdb41c8818da1cb' '77a58ba7c64ccca20616aa03599766ccb0d1a330' '01313661b248c5ba586acae09bff57077dbec0a5' '4795375d8aa072e9aacb0b278e6203c6ca41816a' 'd29479abaded34b2b1dab2e17efe96a65eba3d61' 'e973dfe9259095fb509ab12658c68d46f0e439d7' 'c17fa4cbc546c431ccf13e9354d5d9c1cd247b7c' '310bf433c01f78e0756fd5056a43118a2f77318c' 'fd5ef3d69f8975bad16c437a337b5cb04c8217a2' 'd054cc3a2ccfb19484f3b54d69b6e416832dc8f4' '2528c15f314ece50218d1273654f630d74109583' '638bae3fb225a708dc67db613af62f6d14c4eff4' 'ecba655bf54a661ffe078856cd8dbc898270e4b5' '7e1906643a7374529af74b013bba35e4fa4e6ffc' 'd742ebcfe524dc54023f7c520d2ed2e4b7203c19' '6658472a3e2de08197acfe099ba71ee0e2505ecf' 'fce217449075d59b29052b8cdac567f0f3e22641' '5677aa6a08c1df8bc1ec71516fe1ced9b7cb545f' '0cc08c8130ac8f74419f99fe707dc193b7f79d86' '0743acf746a81e0460a56fd5ff847d97fa7eb370' 'b1fc226edf8680882a5bf89038bdc55afa2ac80d' '15afe57a874eaf104bfbb61ec598fa31627f7b19' 'd77daa49085b067137d0adbe3263f75a7ee13a1b' '1e570e77392f43a3cdab2849d1f81535f8a033e2' '0d7f4e99217f6f715c7064c67eae8d9d09313b14' 'fb25114cd760c13cf177d9ac37837fafcc9657b5' '65efe5404d151767653c7b7dd39bd2e7ad532c2d' '6621b0f118d500092f5f3d72ddddb22aeeb3c3a0' '433e294c3c5b5d2020085a0e36c1cb47b694690a' '0b0eb7702a9fa410755e86124b4b7cd36e7d1cb4' 'bf770d6d2097a52d87f4d9c88d0b05bd3998d7de' 'c2d420796a427dda71a2400909864e7f8e037fd4' '7e7e2c6e2a1cb250f8d03bb99eed01f6d982d5dd' '4412ab501677606436e5c49e41151a1e6eac7ac0' '5e537031f322d55315cd384398b726a9a0748d47' '64d87ccfae3326a9561fe41dc6073064a083e0df' '4d410ba9aa275e7990a270f63ce436990ace1bea' '9797329220a2c6622411eb9ecf6a35b24ce09d04' 'fe8cc44dd173cde5788ab4e3730ac61f3d316d9c' '6277a486a7faaa6c87f4bf1d59a2de233a093248' 'b83fb1b14c06bdd765903ac852ba20a14e24f227' '807c42dd8028d71222dfce035c2e87aaecbf623f' '6c177775dcc5e70a64ddf4ee842c66af498f2c7c'
# test job: [bd79452b39c21599e2cff42e9fbeb182656b6f6a] https://lava.sirena.org.uk/scheduler/job/2104086
# test job: [21e68bcb1b0c688c2d9ca0d457922febac650ac1] https://lava.sirena.org.uk/scheduler/job/2104526
# test job: [96498e804cb6629e02747336a0a33e4955449732] https://lava.sirena.org.uk/scheduler/job/2099727
# test job: [4422df6782eb7aa9725a3c09d9ba3c38ecc85df4] https://lava.sirena.org.uk/scheduler/job/2097779
# test job: [9e510e677090bb794b46348b10e1c8038286e00a] https://lava.sirena.org.uk/scheduler/job/2093905
# test job: [d5c8b7902a41625ea328b52c78ebe750fbf6fef7] https://lava.sirena.org.uk/scheduler/job/2092717
# test job: [118eb2cb97b8fc0d515bb0449495959247db58f0] https://lava.sirena.org.uk/scheduler/job/2092417
# test job: [059f545832be85d29ac9ccc416a16f647aa78485] https://lava.sirena.org.uk/scheduler/job/2086746
# test job: [6402ddf3027d8975f135cf2b2014d6bbeb2d3436] https://lava.sirena.org.uk/scheduler/job/2086625
# test job: [4e00135b2dd1d7924a58bffa551b6ceb3bd836f2] https://lava.sirena.org.uk/scheduler/job/2082495
# test job: [8ff3dcb0e8a8bf6c41f23ed4aa62d066d3948a10] https://lava.sirena.org.uk/scheduler/job/2083122
# test job: [e65b871c9b5af9265aefc5b8cd34993586d93aab] https://lava.sirena.org.uk/scheduler/job/2083037
# test job: [8d63e85c5b50f1dbfa0ccb214bd91fe5d7e2e860] https://lava.sirena.org.uk/scheduler/job/2082590
# test job: [123cd174a3782307787268adf45f22de4d290128] https://lava.sirena.org.uk/scheduler/job/2078937
# test job: [4d6e2211aeb932e096f673c88475016b1cc0f8ab] https://lava.sirena.org.uk/scheduler/job/2078014
# test job: [1d562ba0aa7df81335bf96c02be77efe8d5bab87] https://lava.sirena.org.uk/scheduler/job/2078351
# test job: [873bc94689d832878befbcadc10b6ad5bb4e0027] https://lava.sirena.org.uk/scheduler/job/2074819
# test job: [32172cf3cb543a04c41a1677c97a38e60cad05b6] https://lava.sirena.org.uk/scheduler/job/2075088
# test job: [b3a5302484033331af37569f7277d00131694b57] https://lava.sirena.org.uk/scheduler/job/2074568
# test job: [772ada50282b0c80343c8989147db816961f571d] https://lava.sirena.org.uk/scheduler/job/2069245
# test job: [fb1ebb10468da414d57153ddebaab29c38ef1a78] https://lava.sirena.org.uk/scheduler/job/2059767
# test job: [6985defd1d832f1dd9d1977a6a2cc2cef7632704] https://lava.sirena.org.uk/scheduler/job/2059097
# test job: [2089f086303b773e181567fd8d5df3038bd85937] https://lava.sirena.org.uk/scheduler/job/2058075
# test job: [6951be397ca8b8b167c9f99b5a11c541148c38cb] https://lava.sirena.org.uk/scheduler/job/2055750
# test job: [4e92abd0a11b91af3742197a9ca962c3c00d0948] https://lava.sirena.org.uk/scheduler/job/2055873
# test job: [abc9a349b87ac0fd3ba8787ca00971b59c2e1257] https://lava.sirena.org.uk/scheduler/job/2054602
# test job: [1b0f3f9ee41ee2bdd206667f85ea2aa36dfe6e69] https://lava.sirena.org.uk/scheduler/job/2053511
# test job: [55d03b5b5bdd04daf9a35ce49db18d8bb488dffb] https://lava.sirena.org.uk/scheduler/job/2053867
# test job: [6bd1ad97eb790570c167d4de4ca59fbc9c33722a] https://lava.sirena.org.uk/scheduler/job/2053537
# test job: [655079ac8a7721ac215a0596e3f33b740e01144a] https://lava.sirena.org.uk/scheduler/job/2049694
# test job: [2f538ef9f6f7c3d700c68536f21447dfc598f8c8] https://lava.sirena.org.uk/scheduler/job/2048653
# test job: [3c36965df80801344850388592e95033eceea05b] https://lava.sirena.org.uk/scheduler/job/2049502
# test job: [aa897ffc396b48cc39eee133b6b43175d0df9eb5] https://lava.sirena.org.uk/scheduler/job/2048768
# test job: [c4e68959af66df525d71db619ffe44af9178bb22] https://lava.sirena.org.uk/scheduler/job/2044048
# test job: [380fd29d57abe6679d87ec56babe65ddc5873a37] https://lava.sirena.org.uk/scheduler/job/2044588
# test job: [af9c8092d84244ca54ffb590435735f788e7a170] https://lava.sirena.org.uk/scheduler/job/2043656
# test job: [2ecc8c089802e033d2e5204d21a9f467e2517df9] https://lava.sirena.org.uk/scheduler/job/2038631
# test job: [84194c66aaf78fed150edb217b9f341518b1cba2] https://lava.sirena.org.uk/scheduler/job/2038367
# test job: [252abf2d07d33b1c70a59ba1c9395ba42bbd793e] https://lava.sirena.org.uk/scheduler/job/2038561
# test job: [ed5d499b5c9cc11dd3edae1a7a55db7dfa4f1bdc] https://lava.sirena.org.uk/scheduler/job/2029031
# test job: [e73b743bfe8a6ff4e05b5657d3f7586a17ac3ba0] https://lava.sirena.org.uk/scheduler/job/2026425
# test job: [f1dfbc1b5cf8650ae9a0d543e5f5335fc0f478ce] https://lava.sirena.org.uk/scheduler/job/2025503
# test job: [6ef8e042cdcaabe3e3c68592ba8bfbaee2fa10a3] https://lava.sirena.org.uk/scheduler/job/2025871
# test job: [ecd0de438c1f0ee86cf8f6d5047965a2a181444b] https://lava.sirena.org.uk/scheduler/job/2026135
# test job: [cf6bf51b53252284bafc7377a4d8dbf10f048b4d] https://lava.sirena.org.uk/scheduler/job/2023024
# test job: [20bcda681f8597e86070a4b3b12d1e4f541865d3] https://lava.sirena.org.uk/scheduler/job/2022953
# test job: [e062bdfdd6adbb2dee7751d054c1d8df63ddb8b8] https://lava.sirena.org.uk/scheduler/job/2020135
# test job: [8fdb030fe283c84fd8d378c97ad0f32d6cdec6ce] https://lava.sirena.org.uk/scheduler/job/2021440
# test job: [28039efa4d8e8bbf98b066133a906bd4e307d496] https://lava.sirena.org.uk/scheduler/job/2020322
# test job: [f034c16a4663eaf3198dc18b201ba50533fb5b81] https://lava.sirena.org.uk/scheduler/job/2015432
# test job: [66fecfa91deb536a12ddf3d878a99590d7900277] https://lava.sirena.org.uk/scheduler/job/2015351
# test job: [4a5ac6cd05a7e54f1585d7779464d6ed6272c134] https://lava.sirena.org.uk/scheduler/job/2011285
# test job: [ef042df96d0e1089764f39ede61bc8f140a4be00] https://lava.sirena.org.uk/scheduler/job/2010192
# test job: [4c33cef58965eb655a0ac8e243aa323581ec025f] https://lava.sirena.org.uk/scheduler/job/2009429
# test job: [e7434adf0c53a84d548226304cdb41c8818da1cb] https://lava.sirena.org.uk/scheduler/job/2007770
# test job: [77a58ba7c64ccca20616aa03599766ccb0d1a330] https://lava.sirena.org.uk/scheduler/job/2007322
# test job: [01313661b248c5ba586acae09bff57077dbec0a5] https://lava.sirena.org.uk/scheduler/job/2008874
# test job: [4795375d8aa072e9aacb0b278e6203c6ca41816a] https://lava.sirena.org.uk/scheduler/job/2009678
# test job: [d29479abaded34b2b1dab2e17efe96a65eba3d61] https://lava.sirena.org.uk/scheduler/job/2008461
# test job: [e973dfe9259095fb509ab12658c68d46f0e439d7] https://lava.sirena.org.uk/scheduler/job/2008113
# test job: [c17fa4cbc546c431ccf13e9354d5d9c1cd247b7c] https://lava.sirena.org.uk/scheduler/job/2000039
# test job: [310bf433c01f78e0756fd5056a43118a2f77318c] https://lava.sirena.org.uk/scheduler/job/1996043
# test job: [fd5ef3d69f8975bad16c437a337b5cb04c8217a2] https://lava.sirena.org.uk/scheduler/job/1996112
# test job: [d054cc3a2ccfb19484f3b54d69b6e416832dc8f4] https://lava.sirena.org.uk/scheduler/job/1995713
# test job: [2528c15f314ece50218d1273654f630d74109583] https://lava.sirena.org.uk/scheduler/job/1997616
# test job: [638bae3fb225a708dc67db613af62f6d14c4eff4] https://lava.sirena.org.uk/scheduler/job/1991887
# test job: [ecba655bf54a661ffe078856cd8dbc898270e4b5] https://lava.sirena.org.uk/scheduler/job/1985123
# test job: [7e1906643a7374529af74b013bba35e4fa4e6ffc] https://lava.sirena.org.uk/scheduler/job/1978610
# test job: [d742ebcfe524dc54023f7c520d2ed2e4b7203c19] https://lava.sirena.org.uk/scheduler/job/1975999
# test job: [6658472a3e2de08197acfe099ba71ee0e2505ecf] https://lava.sirena.org.uk/scheduler/job/1973530
# test job: [fce217449075d59b29052b8cdac567f0f3e22641] https://lava.sirena.org.uk/scheduler/job/1975656
# test job: [5677aa6a08c1df8bc1ec71516fe1ced9b7cb545f] https://lava.sirena.org.uk/scheduler/job/1978817
# test job: [0cc08c8130ac8f74419f99fe707dc193b7f79d86] https://lava.sirena.org.uk/scheduler/job/1965701
# test job: [0743acf746a81e0460a56fd5ff847d97fa7eb370] https://lava.sirena.org.uk/scheduler/job/1964858
# test job: [b1fc226edf8680882a5bf89038bdc55afa2ac80d] https://lava.sirena.org.uk/scheduler/job/1978391
# test job: [15afe57a874eaf104bfbb61ec598fa31627f7b19] https://lava.sirena.org.uk/scheduler/job/1962906
# test job: [d77daa49085b067137d0adbe3263f75a7ee13a1b] https://lava.sirena.org.uk/scheduler/job/1962818
# test job: [1e570e77392f43a3cdab2849d1f81535f8a033e2] https://lava.sirena.org.uk/scheduler/job/1962269
# test job: [0d7f4e99217f6f715c7064c67eae8d9d09313b14] https://lava.sirena.org.uk/scheduler/job/1980262
# test job: [fb25114cd760c13cf177d9ac37837fafcc9657b5] https://lava.sirena.org.uk/scheduler/job/1960133
# test job: [65efe5404d151767653c7b7dd39bd2e7ad532c2d] https://lava.sirena.org.uk/scheduler/job/1959948
# test job: [6621b0f118d500092f5f3d72ddddb22aeeb3c3a0] https://lava.sirena.org.uk/scheduler/job/1959732
# test job: [433e294c3c5b5d2020085a0e36c1cb47b694690a] https://lava.sirena.org.uk/scheduler/job/1957354
# test job: [0b0eb7702a9fa410755e86124b4b7cd36e7d1cb4] https://lava.sirena.org.uk/scheduler/job/1957417
# test job: [bf770d6d2097a52d87f4d9c88d0b05bd3998d7de] https://lava.sirena.org.uk/scheduler/job/1984426
# test job: [c2d420796a427dda71a2400909864e7f8e037fd4] https://lava.sirena.org.uk/scheduler/job/1984520
# test job: [7e7e2c6e2a1cb250f8d03bb99eed01f6d982d5dd] https://lava.sirena.org.uk/scheduler/job/1954251
# test job: [4412ab501677606436e5c49e41151a1e6eac7ac0] https://lava.sirena.org.uk/scheduler/job/1946234
# test job: [5e537031f322d55315cd384398b726a9a0748d47] https://lava.sirena.org.uk/scheduler/job/1946679
# test job: [64d87ccfae3326a9561fe41dc6073064a083e0df] https://lava.sirena.org.uk/scheduler/job/1947242
# test job: [4d410ba9aa275e7990a270f63ce436990ace1bea] https://lava.sirena.org.uk/scheduler/job/1947841
# test job: [9797329220a2c6622411eb9ecf6a35b24ce09d04] https://lava.sirena.org.uk/scheduler/job/1947406
# test job: [fe8cc44dd173cde5788ab4e3730ac61f3d316d9c] https://lava.sirena.org.uk/scheduler/job/1946044
# test job: [6277a486a7faaa6c87f4bf1d59a2de233a093248] https://lava.sirena.org.uk/scheduler/job/1947003
# test job: [b83fb1b14c06bdd765903ac852ba20a14e24f227] https://lava.sirena.org.uk/scheduler/job/1946832
# test job: [807c42dd8028d71222dfce035c2e87aaecbf623f] https://lava.sirena.org.uk/scheduler/job/1981864
# test job: [6c177775dcc5e70a64ddf4ee842c66af498f2c7c] https://lava.sirena.org.uk/scheduler/job/1780443
# test job: [fe4d0dea039f2befb93f27569593ec209843b0f5] https://lava.sirena.org.uk/scheduler/job/2106238
# bad: [fe4d0dea039f2befb93f27569593ec209843b0f5] Add linux-next specific files for 20251119
git bisect bad fe4d0dea039f2befb93f27569593ec209843b0f5
# test job: [40506e4c543a64ad5846f0a532d5ea16310fd9e3] https://lava.sirena.org.uk/scheduler/job/2106514
# bad: [40506e4c543a64ad5846f0a532d5ea16310fd9e3] Merge branch 'for-next' of https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git
git bisect bad 40506e4c543a64ad5846f0a532d5ea16310fd9e3
# test job: [e510eda33592ffbe54b55476040348b552674cd3] https://lava.sirena.org.uk/scheduler/job/2106557
# bad: [e510eda33592ffbe54b55476040348b552674cd3] Merge branch 'next' of https://git.kernel.org/pub/scm/linux/kernel/git/uml/linux.git
git bisect bad e510eda33592ffbe54b55476040348b552674cd3
# test job: [8903539518403d5e9a7ac09ea2486ed297f337e5] https://lava.sirena.org.uk/scheduler/job/2106617
# bad: [8903539518403d5e9a7ac09ea2486ed297f337e5] Merge branch 'for-next' of https://git.kernel.org/pub/scm/linux/kernel/git/mediatek/linux.git
git bisect bad 8903539518403d5e9a7ac09ea2486ed297f337e5
# test job: [fb6b3841aabe2098b0610eaf9edac0fc562a122f] https://lava.sirena.org.uk/scheduler/job/2106645
# bad: [fb6b3841aabe2098b0610eaf9edac0fc562a122f] Merge branch 'kbuild-next' of https://git.kernel.org/pub/scm/linux/kernel/git/kbuild/linux.git
git bisect bad fb6b3841aabe2098b0610eaf9edac0fc562a122f
# test job: [f24f3801039f9a2033e3a2390fccc5adc00a8df7] https://lava.sirena.org.uk/scheduler/job/2106738
# good: [f24f3801039f9a2033e3a2390fccc5adc00a8df7] mm: implement sticky VMA flags
git bisect good f24f3801039f9a2033e3a2390fccc5adc00a8df7
# test job: [420203301ca3aef72980c78534264c4ec7f672d0] https://lava.sirena.org.uk/scheduler/job/2106793
# good: [420203301ca3aef72980c78534264c4ec7f672d0] Revert "lib/plist.c: enforce memory ordering in plist_check_list"
git bisect good 420203301ca3aef72980c78534264c4ec7f672d0
# test job: [259dbf8c45694409126841a8769c111869fec9c8] https://lava.sirena.org.uk/scheduler/job/2106834
# bad: [259dbf8c45694409126841a8769c111869fec9c8] mm/damon/vaddr: consistently use only pmd_entry for damos_migrate
git bisect bad 259dbf8c45694409126841a8769c111869fec9c8
# test job: [529b176c64b658d258493a03d88126c69aeae25b] https://lava.sirena.org.uk/scheduler/job/2106989
# bad: [529b176c64b658d258493a03d88126c69aeae25b] mm: replace remaining pte_to_swp_entry() with softleaf_from_pte()
git bisect bad 529b176c64b658d258493a03d88126c69aeae25b
# test job: [abedb72c9bfdd177a446ed4c29b50d9dea239471] https://lava.sirena.org.uk/scheduler/job/2107057
# bad: [abedb72c9bfdd177a446ed4c29b50d9dea239471] mm: introduce leaf entry type and use to simplify leaf entry logic
git bisect bad abedb72c9bfdd177a446ed4c29b50d9dea239471
# test job: [b789b80819cdef357c78e613a28f36d1ef7975bf] https://lava.sirena.org.uk/scheduler/job/2107105
# bad: [b789b80819cdef357c78e613a28f36d1ef7975bf] tools/testing/vma: add VMA sticky userland tests
git bisect bad b789b80819cdef357c78e613a28f36d1ef7975bf
# test job: [b331f7745489548c5a020301f6f3b4aad20c7b77] https://lava.sirena.org.uk/scheduler/job/2107143
# bad: [b331f7745489548c5a020301f6f3b4aad20c7b77] mm: introduce copy-on-fork VMAs and make VM_MAYBE_GUARD one
git bisect bad b331f7745489548c5a020301f6f3b4aad20c7b77
# test job: [2c91ae77d8fbafb153c13e554f50b7bbeef59d76] https://lava.sirena.org.uk/scheduler/job/2107226
# bad: [2c91ae77d8fbafb153c13e554f50b7bbeef59d76] mm-implement-sticky-vma-flags-fix-2
git bisect bad 2c91ae77d8fbafb153c13e554f50b7bbeef59d76
# test job: [79ee48c12ef8fe9a3daf0dbeda74f038a3f557be] https://lava.sirena.org.uk/scheduler/job/2107256
# bad: [79ee48c12ef8fe9a3daf0dbeda74f038a3f557be] mm-implement-sticky-vma-flags-fix
git bisect bad 79ee48c12ef8fe9a3daf0dbeda74f038a3f557be
# first bad commit: [79ee48c12ef8fe9a3daf0dbeda74f038a3f557be] mm-implement-sticky-vma-flags-fix

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply

* [PATCH v12 10/13] unwind_user/sframe: Remove .sframe section on detected corruption
From: Jens Remus @ 2025-11-19 13:23 UTC (permalink / raw)
  To: linux-kernel, linux-trace-kernel, bpf, x86, linux-mm,
	Steven Rostedt
  Cc: Jens Remus, Josh Poimboeuf, Masami Hiramatsu, Mathieu Desnoyers,
	Peter Zijlstra, Ingo Molnar, Jiri Olsa, Arnaldo Carvalho de Melo,
	Namhyung Kim, Thomas Gleixner, Andrii Nakryiko, Indu Bhagat,
	Jose E. Marchesi, Beau Belgrave, Linus Torvalds, Andrew Morton,
	Florian Weimer, Kees Cook, Carlos O'Donell, Sam James,
	Dylan Hatch, Borislav Petkov, Dave Hansen, David Hildenbrand,
	H. Peter Anvin, Liam R. Howlett, Lorenzo Stoakes, Michal Hocko,
	Mike Rapoport, Suren Baghdasaryan, Vlastimil Babka,
	Heiko Carstens, Vasily Gorbik, Steven Rostedt (Google)
In-Reply-To: <20251119132323.1281768-1-jremus@linux.ibm.com>

From: Josh Poimboeuf <jpoimboe@kernel.org>

To avoid continued attempted use of a bad .sframe section, remove it
on demand when the first sign of corruption is detected.

Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Andrii Nakryiko <andrii@kernel.org>
Cc: Indu Bhagat <indu.bhagat@oracle.com>
Cc: "Jose E. Marchesi" <jemarch@gnu.org>
Cc: Beau Belgrave <beaub@linux.microsoft.com>
Cc: Jens Remus <jremus@linux.ibm.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Florian Weimer <fweimer@redhat.com>
Cc: Sam James <sam@gentoo.org>
Cc: Kees Cook <kees@kernel.org>
Cc: "Carlos O'Donell" <codonell@redhat.com>
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
Signed-off-by: Jens Remus <jremus@linux.ibm.com>
---
 kernel/unwind/sframe.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/kernel/unwind/sframe.c b/kernel/unwind/sframe.c
index 1e877c3e5417..61340ee524c2 100644
--- a/kernel/unwind/sframe.c
+++ b/kernel/unwind/sframe.c
@@ -342,6 +342,10 @@ int sframe_find(unsigned long ip, struct unwind_user_frame *frame)
 	ret = __find_fre(sec, &fde, ip, frame);
 end:
 	user_read_access_end();
+
+	if (ret == -EFAULT)
+		WARN_ON_ONCE(sframe_remove_section(sec->sframe_start));
+
 	return ret;
 }
 
-- 
2.48.1


^ permalink raw reply related

* [PATCH v12 07/13] unwind_user: Stop when reaching an outermost frame
From: Jens Remus @ 2025-11-19 13:23 UTC (permalink / raw)
  To: linux-kernel, linux-trace-kernel, bpf, x86, linux-mm,
	Steven Rostedt
  Cc: Jens Remus, Josh Poimboeuf, Masami Hiramatsu, Mathieu Desnoyers,
	Peter Zijlstra, Ingo Molnar, Jiri Olsa, Arnaldo Carvalho de Melo,
	Namhyung Kim, Thomas Gleixner, Andrii Nakryiko, Indu Bhagat,
	Jose E. Marchesi, Beau Belgrave, Linus Torvalds, Andrew Morton,
	Florian Weimer, Kees Cook, Carlos O'Donell, Sam James,
	Dylan Hatch, Borislav Petkov, Dave Hansen, David Hildenbrand,
	H. Peter Anvin, Liam R. Howlett, Lorenzo Stoakes, Michal Hocko,
	Mike Rapoport, Suren Baghdasaryan, Vlastimil Babka,
	Heiko Carstens, Vasily Gorbik
In-Reply-To: <20251119132323.1281768-1-jremus@linux.ibm.com>

Add an indication for an outermost frame to the unwind user frame
structure and stop unwinding when reaching an outermost frame.

This will be used by unwind user sframe, as SFrame may represent an
undefined return address as indication for an outermost frame.

Cc: Steven Rostedt <rostedt@kernel.org>
Cc: Josh Poimboeuf <jpoimboe@kernel.org>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Andrii Nakryiko <andrii@kernel.org>
Cc: Indu Bhagat <indu.bhagat@oracle.com>
Cc: "Jose E. Marchesi" <jemarch@gnu.org>
Cc: Beau Belgrave <beaub@linux.microsoft.com>
Cc: Jens Remus <jremus@linux.ibm.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Florian Weimer <fweimer@redhat.com>
Cc: Sam James <sam@gentoo.org>
Cc: Kees Cook <kees@kernel.org>
Cc: "Carlos O'Donell" <codonell@redhat.com>
Signed-off-by: Jens Remus <jremus@linux.ibm.com>
---

Notes (jremus):
    Changes in v12:
    - Adjust to Peter's tip perf/core commit ae25884ad749 ("unwind_user/x86:
      Teach FP unwind about start of function").
    
    Changes in v11:
    - New patch.

 arch/x86/include/asm/unwind_user.h | 6 ++++--
 include/linux/unwind_user_types.h  | 1 +
 kernel/unwind/user.c               | 6 ++++++
 3 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/arch/x86/include/asm/unwind_user.h b/arch/x86/include/asm/unwind_user.h
index 12064284bc4e..f9a1c460150d 100644
--- a/arch/x86/include/asm/unwind_user.h
+++ b/arch/x86/include/asm/unwind_user.h
@@ -11,13 +11,15 @@
 	.cfa_off	=  2*(ws),			\
 	.ra_off		= -1*(ws),			\
 	.fp_off		= -2*(ws),			\
-	.use_fp		= true,
+	.use_fp		= true,				\
+	.outermost	= false,
 
 #define ARCH_INIT_USER_FP_ENTRY_FRAME(ws)		\
 	.cfa_off	=  1*(ws),			\
 	.ra_off		= -1*(ws),			\
 	.fp_off		= 0,				\
-	.use_fp		= false,
+	.use_fp		= false,			\
+	.outermost	= false,
 
 static inline int unwind_user_word_size(struct pt_regs *regs)
 {
diff --git a/include/linux/unwind_user_types.h b/include/linux/unwind_user_types.h
index 43e4b160883f..616cc5ee4586 100644
--- a/include/linux/unwind_user_types.h
+++ b/include/linux/unwind_user_types.h
@@ -32,6 +32,7 @@ struct unwind_user_frame {
 	s32 ra_off;
 	s32 fp_off;
 	bool use_fp;
+	bool outermost;
 };
 
 struct unwind_user_state {
diff --git a/kernel/unwind/user.c b/kernel/unwind/user.c
index 7644ab9f6a61..d053295b1f7e 100644
--- a/kernel/unwind/user.c
+++ b/kernel/unwind/user.c
@@ -32,6 +32,12 @@ static int unwind_user_next_common(struct unwind_user_state *state,
 {
 	unsigned long cfa, fp, ra;
 
+	/* Stop unwinding when reaching an outermost frame. */
+	if (frame->outermost) {
+		state->done = true;
+		return 0;
+	}
+
 	if (frame->use_fp) {
 		if (state->fp < state->sp)
 			return -EINVAL;
-- 
2.48.1


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox