Linux Trace Kernel
 help / color / mirror / Atom feed
* [PATCH v5 2/3] ring-buffer: Handle RB_MISSED_* flags on commit field correctly
From: Masami Hiramatsu (Google) @ 2026-02-26 13:38 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: Masami Hiramatsu, Mathieu Desnoyers, linux-kernel,
	linux-trace-kernel
In-Reply-To: <177211310553.419230.7846100548994399256.stgit@mhiramat.tok.corp.google.com>

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

Since the MSBs of rb_data_page::commit are used for storing
RB_MISSED_EVENTS and RB_MISSED_STORED, we need to mask out those bits
when it is used for finding the size of data pages.

Fixes: 5f3b6e839f3c ("ring-buffer: Validate boot range memory events")
Fixes: 5b7be9c709e1 ("ring-buffer: Add test to validate the time stamp deltas")
Cc: stable@vger.kernel.org
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
---
 Changes in v5:
   - Do not move rb_commit_index().
   - Fix verify_event() and rb_cpu_meta_valid() too.
 Changes in v4:
   - Fix to move rb_commit_index() after ring_buffer_per_cpu definition.
---
 kernel/trace/ring_buffer.c |   27 +++++++++++++++------------
 1 file changed, 15 insertions(+), 12 deletions(-)

diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
index 0eb6e6595f37..2e9b8ce6b4dc 100644
--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -395,6 +395,12 @@ static __always_inline unsigned int rb_page_commit(struct buffer_page *bpage)
 	return local_read(&bpage->page->commit);
 }
 
+/* Size is determined by what has been committed */
+static __always_inline unsigned int rb_page_size(struct buffer_page *bpage)
+{
+	return rb_page_commit(bpage) & ~RB_MISSED_MASK;
+}
+
 static void free_buffer_page(struct buffer_page *bpage)
 {
 	/* Range pages are not to be freed */
@@ -676,7 +682,7 @@ static void verify_event(struct ring_buffer_per_cpu *cpu_buffer,
 	do {
 		if (page == tail_page || WARN_ON_ONCE(stop++ > 100))
 			done = true;
-		commit = local_read(&page->page->commit);
+		commit = rb_page_size(page);
 		write = local_read(&page->write);
 		if (addr >= (unsigned long)&page->page->data[commit] &&
 		    addr < (unsigned long)&page->page->data[write])
@@ -1820,13 +1826,16 @@ static bool rb_cpu_meta_valid(struct ring_buffer_cpu_meta *meta, int cpu,
 
 	/* Is the meta buffers and the subbufs themselves have correct data? */
 	for (i = 0; i < meta->nr_subbufs; i++) {
+		unsigned long commit;
+
 		if (meta->buffers[i] < 0 ||
 		    meta->buffers[i] >= meta->nr_subbufs) {
 			pr_info("Ring buffer boot meta [%d] array out of range\n", cpu);
 			return false;
 		}
 
-		if ((unsigned)local_read(&subbuf->commit) > subbuf_size) {
+		commit = local_read(&subbuf->commit) & ~RB_MISSED_MASK;
+		if (commit > subbuf_size) {
 			pr_info("Ring buffer boot meta [%d] buffer invalid commit\n", cpu);
 			return false;
 		}
@@ -1907,7 +1916,7 @@ static int rb_validate_buffer(struct buffer_data_page *dpage, int cpu)
 	u64 delta;
 	int tail;
 
-	tail = local_read(&dpage->commit);
+	tail = local_read(&dpage->commit) & ~RB_MISSED_MASK;
 	return rb_read_data_buffer(dpage, tail, cpu, &ts, &delta);
 }
 
@@ -1934,7 +1943,7 @@ static void rb_meta_validate_events(struct ring_buffer_per_cpu *cpu_buffer)
 		goto invalid;
 	}
 	entries += ret;
-	entry_bytes += local_read(&cpu_buffer->reader_page->page->commit);
+	entry_bytes += rb_page_size(cpu_buffer->reader_page);
 	local_set(&cpu_buffer->reader_page->entries, ret);
 
 	ts = head_page->page->time_stamp;
@@ -2054,7 +2063,7 @@ static void rb_meta_validate_events(struct ring_buffer_per_cpu *cpu_buffer)
 			local_inc(&cpu_buffer->pages_touched);
 
 		entries += ret;
-		entry_bytes += local_read(&head_page->page->commit);
+		entry_bytes += rb_page_size(head_page);
 		local_set(&cpu_buffer->head_page->entries, ret);
 
 		if (head_page == cpu_buffer->commit_page)
@@ -3256,12 +3265,6 @@ rb_iter_head_event(struct ring_buffer_iter *iter)
 	return NULL;
 }
 
-/* Size is determined by what has been committed */
-static __always_inline unsigned rb_page_size(struct buffer_page *bpage)
-{
-	return rb_page_commit(bpage) & ~RB_MISSED_MASK;
-}
-
 static __always_inline unsigned
 rb_commit_index(struct ring_buffer_per_cpu *cpu_buffer)
 {
@@ -4432,7 +4435,7 @@ static void check_buffer(struct ring_buffer_per_cpu *cpu_buffer,
 
 	if (tail == CHECK_FULL_PAGE) {
 		full = true;
-		tail = local_read(&bpage->commit);
+		tail = local_read(&bpage->commit) & ~RB_MISSED_MASK;
 	} else if (info->add_timestamp &
 		   (RB_ADD_STAMP_FORCE | RB_ADD_STAMP_ABSOLUTE)) {
 		/* Ignore events with absolute time stamps */


^ permalink raw reply related

* [PATCH v5 1/3] ring-buffer: Flush and stop persistent ring buffer on panic
From: Masami Hiramatsu (Google) @ 2026-02-26 13:38 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: Masami Hiramatsu, Mathieu Desnoyers, linux-kernel,
	linux-trace-kernel
In-Reply-To: <177211310553.419230.7846100548994399256.stgit@mhiramat.tok.corp.google.com>

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

On real hardware, panic and machine reboot may not flush hardware cache
to memory. This means the persistent ring buffer, which relies on a
coherent state of memory, may not have its events written to the buffer
and they may be lost. Moreover, there may be inconsistency with the
counters which are used for validation of the integrity of the
persistent ring buffer which may cause all data to be discarded.

To avoid this issue, stop recording of the ring buffer on panic and
flush the cache of the ring buffer's memory.

Fixes: e645535a954a ("tracing: Add option to use memmapped memory for trace boot instance")
Cc: stable@vger.kernel.org
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
---
 Changes in v5:
   - Use ring_buffer_record_off() instead of ring_buffer_record_disable().
   - Use flush_cache_all() to ensure flush all cache.
 Changes in v3:
   - update patch description.
---
 kernel/trace/ring_buffer.c |   20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
index f16f053ef77d..0eb6e6595f37 100644
--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -6,6 +6,7 @@
  */
 #include <linux/sched/isolation.h>
 #include <linux/trace_recursion.h>
+#include <linux/panic_notifier.h>
 #include <linux/trace_events.h>
 #include <linux/ring_buffer.h>
 #include <linux/trace_clock.h>
@@ -589,6 +590,7 @@ struct trace_buffer {
 
 	unsigned long			range_addr_start;
 	unsigned long			range_addr_end;
+	struct notifier_block		flush_nb;
 
 	struct ring_buffer_meta		*meta;
 
@@ -2471,6 +2473,15 @@ static void rb_free_cpu_buffer(struct ring_buffer_per_cpu *cpu_buffer)
 	kfree(cpu_buffer);
 }
 
+static int rb_flush_buffer_cb(struct notifier_block *nb, unsigned long event, void *data)
+{
+	struct trace_buffer *buffer = container_of(nb, struct trace_buffer, flush_nb);
+
+	ring_buffer_record_off(buffer);
+	flush_cache_all();
+	return NOTIFY_DONE;
+}
+
 static struct trace_buffer *alloc_buffer(unsigned long size, unsigned flags,
 					 int order, unsigned long start,
 					 unsigned long end,
@@ -2590,6 +2601,12 @@ static struct trace_buffer *alloc_buffer(unsigned long size, unsigned flags,
 
 	mutex_init(&buffer->mutex);
 
+	/* Persistent ring buffer needs to flush cache before reboot. */
+	if (start & end) {
+		buffer->flush_nb.notifier_call = rb_flush_buffer_cb;
+		atomic_notifier_chain_register(&panic_notifier_list, &buffer->flush_nb);
+	}
+
 	return_ptr(buffer);
 
  fail_free_buffers:
@@ -2677,6 +2694,9 @@ ring_buffer_free(struct trace_buffer *buffer)
 {
 	int cpu;
 
+	if (buffer->range_addr_start && buffer->range_addr_end)
+		atomic_notifier_chain_unregister(&panic_notifier_list, &buffer->flush_nb);
+
 	cpuhp_state_remove_instance(CPUHP_TRACE_RB_PREPARE, &buffer->node);
 
 	irq_work_sync(&buffer->irq_work.work);


^ permalink raw reply related

* [PATCH v5 0/3] ring-buffer: Making persistent ring buffers robust
From: Masami Hiramatsu (Google) @ 2026-02-26 13:38 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: Masami Hiramatsu, Mathieu Desnoyers, linux-kernel,
	linux-trace-kernel

Hi,

Here is the 5th version of improvement patches for making persistent
ring buffers robust to failures.
The previous version is here:

https://lore.kernel.org/all/177191595057.435720.10116014529518464418.stgit@mhiramat.tok.corp.google.com/

This version fixes multiple issues in the previous version.
 - [1/3] Use appropriate functions for flushing cache and
   stopping event recrod.
 - [2/3] More fixes for masking commit fields and do not move
   unrelated rb_commit_index().
 - [3/3] Show total number of discarded pages instead of
    showing errors on each page.

Thank you,

---

Masami Hiramatsu (Google) (3):
      ring-buffer: Flush and stop persistent ring buffer on panic
      ring-buffer: Handle RB_MISSED_* flags on commit field correctly
      ring-buffer: Skip invalid sub-buffers when validating persistent ring buffer


 kernel/trace/ring_buffer.c |   73 ++++++++++++++++++++++++++++++--------------
 1 file changed, 49 insertions(+), 24 deletions(-)

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

^ permalink raw reply

* Re: [PATCH v1] mm: annotate data race of f_ra.prev_pos
From: Jan Kara @ 2026-02-26 13:21 UTC (permalink / raw)
  To: Jiayuan Chen
  Cc: linux-mm, Jiayuan Chen, syzbot+6880f676b265dbd42d63,
	Theodore Ts'o, Andreas Dilger, Konstantin Komarov,
	Steven Rostedt, Masami Hiramatsu, Mathieu Desnoyers,
	Matthew Wilcox (Oracle), Andrew Morton, Hugh Dickins, Baolin Wang,
	Jan Kara, linux-ext4, linux-kernel, ntfs3, linux-trace-kernel,
	linux-fsdevel
In-Reply-To: <20260226084020.163720-1-jiayuan.chen@linux.dev>

On Thu 26-02-26 16:40:07, Jiayuan Chen wrote:
> From: Jiayuan Chen <jiayuan.chen@shopee.com>
> 
> KCSAN reports a data race when concurrent readers access the same
> struct file:
> 
>   BUG: KCSAN: data-race in filemap_read / filemap_splice_read
> 
>   write to 0xffff88811a6f8228 of 8 bytes by task 10061 on cpu 0:
>    filemap_splice_read+0x523/0x780 mm/filemap.c:3125
>    ...
> 
>   write to 0xffff88811a6f8228 of 8 bytes by task 10066 on cpu 1:
>    filemap_read+0x98d/0xa10 mm/filemap.c:2873
>    ...
> 
> Both filemap_read() and filemap_splice_read() update f_ra.prev_pos
> without synchronization. This is a benign race since prev_pos is only
> used as a hint for readahead heuristics in page_cache_sync_ra(), and a
> stale or torn value merely results in a suboptimal readahead decision,
> not a correctness issue.
> 
> Use WRITE_ONCE/READ_ONCE to annotate all accesses to prev_pos across
> the tree for consistency and silence KCSAN.
> 
> Reported-by: syzbot+6880f676b265dbd42d63@syzkaller.appspotmail.com
> Link: https://syzkaller.appspot.com/bug?extid=6880f676b265dbd42d63
> Signed-off-by: Jiayuan Chen <jiayuan.chen@shopee.com>

Given this, I think it would be much less intrusive and also more
explanatory to just mark prev_pos with __data_racy with appropriate reason
you're mentioning in the changelog.

								Honza

> ---
>  fs/ext4/dir.c                    | 2 +-
>  fs/ntfs3/fsntfs.c                | 2 +-
>  include/trace/events/readahead.h | 2 +-
>  mm/filemap.c                     | 6 +++---
>  mm/readahead.c                   | 4 ++--
>  mm/shmem.c                       | 2 +-
>  6 files changed, 9 insertions(+), 9 deletions(-)
> 
> diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
> index 28b2a3deb954..1ddf7acce5ca 100644
> --- a/fs/ext4/dir.c
> +++ b/fs/ext4/dir.c
> @@ -200,7 +200,7 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
>  					sb->s_bdev->bd_mapping,
>  					&file->f_ra, file, index,
>  					1 << EXT4_SB(sb)->s_min_folio_order);
> -			file->f_ra.prev_pos = (loff_t)index << PAGE_SHIFT;
> +			WRITE_ONCE(file->f_ra.prev_pos, (loff_t)index << PAGE_SHIFT);
>  			bh = ext4_bread(NULL, inode, map.m_lblk, 0);
>  			if (IS_ERR(bh)) {
>  				err = PTR_ERR(bh);
> diff --git a/fs/ntfs3/fsntfs.c b/fs/ntfs3/fsntfs.c
> index 0df2aa81d884..d1232fc03c08 100644
> --- a/fs/ntfs3/fsntfs.c
> +++ b/fs/ntfs3/fsntfs.c
> @@ -1239,7 +1239,7 @@ int ntfs_read_run_nb_ra(struct ntfs_sb_info *sbi, const struct runs_tree *run,
>  			if (!ra_has_index(ra, index)) {
>  				page_cache_sync_readahead(mapping, ra, NULL,
>  							  index, 1);
> -				ra->prev_pos = (loff_t)index << PAGE_SHIFT;
> +				WRITE_ONCE(ra->prev_pos, (loff_t)index << PAGE_SHIFT);
>  			}
>  		}
>  
> diff --git a/include/trace/events/readahead.h b/include/trace/events/readahead.h
> index 0997ac5eceab..63d8df6c2983 100644
> --- a/include/trace/events/readahead.h
> +++ b/include/trace/events/readahead.h
> @@ -101,7 +101,7 @@ DECLARE_EVENT_CLASS(page_cache_ra_op,
>  		__entry->async_size = ra->async_size;
>  		__entry->ra_pages = ra->ra_pages;
>  		__entry->mmap_miss = ra->mmap_miss;
> -		__entry->prev_pos = ra->prev_pos;
> +		__entry->prev_pos = READ_ONCE(ra->prev_pos);
>  		__entry->req_count = req_count;
>  	),
>  
> diff --git a/mm/filemap.c b/mm/filemap.c
> index 63f256307fdd..d3e2d4b826b9 100644
> --- a/mm/filemap.c
> +++ b/mm/filemap.c
> @@ -2771,7 +2771,7 @@ ssize_t filemap_read(struct kiocb *iocb, struct iov_iter *iter,
>  	int i, error = 0;
>  	bool writably_mapped;
>  	loff_t isize, end_offset;
> -	loff_t last_pos = ra->prev_pos;
> +	loff_t last_pos = READ_ONCE(ra->prev_pos);
>  
>  	if (unlikely(iocb->ki_pos < 0))
>  		return -EINVAL;
> @@ -2870,7 +2870,7 @@ ssize_t filemap_read(struct kiocb *iocb, struct iov_iter *iter,
>  	} while (iov_iter_count(iter) && iocb->ki_pos < isize && !error);
>  
>  	file_accessed(filp);
> -	ra->prev_pos = last_pos;
> +	WRITE_ONCE(ra->prev_pos, last_pos);
>  	return already_read ? already_read : error;
>  }
>  EXPORT_SYMBOL_GPL(filemap_read);
> @@ -3122,7 +3122,7 @@ ssize_t filemap_splice_read(struct file *in, loff_t *ppos,
>  			len -= n;
>  			total_spliced += n;
>  			*ppos += n;
> -			in->f_ra.prev_pos = *ppos;
> +			WRITE_ONCE(in->f_ra.prev_pos, *ppos);
>  			if (pipe_is_full(pipe))
>  				goto out;
>  		}
> diff --git a/mm/readahead.c b/mm/readahead.c
> index 7b05082c89ea..de49b35b0329 100644
> --- a/mm/readahead.c
> +++ b/mm/readahead.c
> @@ -142,7 +142,7 @@ void
>  file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping)
>  {
>  	ra->ra_pages = inode_to_bdi(mapping->host)->ra_pages;
> -	ra->prev_pos = -1;
> +	WRITE_ONCE(ra->prev_pos, -1);
>  }
>  EXPORT_SYMBOL_GPL(file_ra_state_init);
>  
> @@ -584,7 +584,7 @@ void page_cache_sync_ra(struct readahead_control *ractl,
>  	}
>  
>  	max_pages = ractl_max_pages(ractl, req_count);
> -	prev_index = (unsigned long long)ra->prev_pos >> PAGE_SHIFT;
> +	prev_index = (unsigned long long)READ_ONCE(ra->prev_pos) >> PAGE_SHIFT;
>  	/*
>  	 * A start of file, oversized read, or sequential cache miss:
>  	 * trivial case: (index - prev_index) == 1
> diff --git a/mm/shmem.c b/mm/shmem.c
> index 5e7dcf5bc5d3..03569199baf4 100644
> --- a/mm/shmem.c
> +++ b/mm/shmem.c
> @@ -3642,7 +3642,7 @@ static ssize_t shmem_file_splice_read(struct file *in, loff_t *ppos,
>  		len -= n;
>  		total_spliced += n;
>  		*ppos += n;
> -		in->f_ra.prev_pos = *ppos;
> +		WRITE_ONCE(in->f_ra.prev_pos, *ppos);
>  		if (pipe_is_full(pipe))
>  			break;
>  
> -- 
> 2.43.0
> 
-- 
Jan Kara <jack@suse.com>
SUSE Labs, CR

^ permalink raw reply

* Re: [PATCH v4 3/3] ring-buffer: Skip invalid sub-buffers when validating persistent ring buffer
From: Masami Hiramatsu @ 2026-02-26 12:58 UTC (permalink / raw)
  To: Masami Hiramatsu (Google)
  Cc: Steven Rostedt, Mathieu Desnoyers, linux-kernel,
	linux-trace-kernel
In-Reply-To: <177191597760.435720.2484229987964512451.stgit@mhiramat.tok.corp.google.com>

On Tue, 24 Feb 2026 15:52:57 +0900
"Masami Hiramatsu (Google)" <mhiramat@kernel.org> wrote:

> From: Masami Hiramatsu (Google) <mhiramat@kernel.org>
> 
> Skip invalid sub-buffers when validating the persistent ring buffer
> instead of discarding the entire ring buffer. Also, mark there are
> missed events on the discarded buffer.
> 
> If the cache data in memory fails to be synchronized during a reboot,
> the persistent ring buffer may become partially corrupted, but other
> sub-buffers may still contain readable event data. Only discard the
> subbuffersa that ar found to be corrupted.
> 
> Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
> ---
>   Changes in v3:
>   - Record missed data event on commit.
> ---
>  kernel/trace/ring_buffer.c |   21 +++++++++++----------
>  1 file changed, 11 insertions(+), 10 deletions(-)
> 
> diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
> index 67bc652ba02a..72f82e2e6740 100644
> --- a/kernel/trace/ring_buffer.c
> +++ b/kernel/trace/ring_buffer.c
> @@ -2058,17 +2058,18 @@ static void rb_meta_validate_events(struct ring_buffer_per_cpu *cpu_buffer)
>  		if (ret < 0) {
>  			pr_info("Ring buffer meta [%d] invalid buffer page\n",
>  				cpu_buffer->cpu);

This pr_info() should be removed too, because multiple pages
can be discarded.

Thanks,

> -			goto invalid;
> -		}
> -
> -		/* If the buffer has content, update pages_touched */
> -		if (ret)
> -			local_inc(&cpu_buffer->pages_touched);
> -
> -		entries += ret;
> -		entry_bytes += rb_page_size(head_page);
> -		local_set(&cpu_buffer->head_page->entries, ret);
> +			/* Instead of discard whole ring buffer, discard only this sub-buffer. */
> +			local_set(&head_page->entries, 0);
> +			local_set(&head_page->page->commit, RB_MISSED_EVENTS);
> +		} else {
> +			/* If the buffer has content, update pages_touched */
> +			if (ret)
> +				local_inc(&cpu_buffer->pages_touched);
>  
> +			entries += ret;
> +			entry_bytes += rb_page_size(head_page);
> +			local_set(&cpu_buffer->head_page->entries, ret);
> +		}
>  		if (head_page == cpu_buffer->commit_page)
>  			break;
>  	}
> 


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

^ permalink raw reply

* Re: [PATCH v4 1/3] ring-buffer: Flush and stop persistent ring buffer on panic
From: Masami Hiramatsu @ 2026-02-26 12:56 UTC (permalink / raw)
  To: Masami Hiramatsu (Google)
  Cc: Steven Rostedt, Mathieu Desnoyers, linux-kernel,
	linux-trace-kernel
In-Reply-To: <177191596224.435720.8250761603256925623.stgit@mhiramat.tok.corp.google.com>

On Tue, 24 Feb 2026 15:52:42 +0900
"Masami Hiramatsu (Google)" <mhiramat@kernel.org> wrote:

> From: Masami Hiramatsu (Google) <mhiramat@kernel.org>
> 
> On real hardware, panic and machine reboot may not flush hardware cache
> to memory. This means the persistent ring buffer, which relies on a
> coherent state of memory, may not have its events written to the buffer
> and they may be lost. Moreover, there may be inconsistency with the
> counters which are used for validation of the integrity of the
> persistent ring buffer which may cause all data to be discarded.
> 
> To avoid this issue, stop recording of the ring buffer on panic and
> flush the cache of the ring buffer's memory.
> 
> Fixes: e645535a954a ("tracing: Add option to use memmapped memory for trace boot instance")
> Cc: stable@vger.kernel.org
> Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
> ---
>  Changes in v3:
>    - update patch description.
> ---
>  kernel/trace/ring_buffer.c |   21 +++++++++++++++++++++
>  1 file changed, 21 insertions(+)
> 
> diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
> index f16f053ef77d..3eb124c93d72 100644
> --- a/kernel/trace/ring_buffer.c
> +++ b/kernel/trace/ring_buffer.c
> @@ -6,6 +6,7 @@
>   */
>  #include <linux/sched/isolation.h>
>  #include <linux/trace_recursion.h>
> +#include <linux/panic_notifier.h>
>  #include <linux/trace_events.h>
>  #include <linux/ring_buffer.h>
>  #include <linux/trace_clock.h>
> @@ -589,6 +590,7 @@ struct trace_buffer {
>  
>  	unsigned long			range_addr_start;
>  	unsigned long			range_addr_end;
> +	struct notifier_block		flush_nb;
>  
>  	struct ring_buffer_meta		*meta;
>  
> @@ -2471,6 +2473,16 @@ static void rb_free_cpu_buffer(struct ring_buffer_per_cpu *cpu_buffer)
>  	kfree(cpu_buffer);
>  }
>  
> +static int rb_flush_buffer_cb(struct notifier_block *nb, unsigned long event, void *data)
> +{
> +	struct trace_buffer *buffer = container_of(nb, struct trace_buffer, flush_nb);
> +
> +	ring_buffer_record_disable(buffer);

I found this was a wrong API. I have to use ring_buffer_record_off().

> +	flush_kernel_vmap_range((void *)buffer->range_addr_start,
> +				buffer->range_addr_end - buffer->range_addr_start);

This does nothing on arm64.



Thanks,

> +	return NOTIFY_DONE;
> +}
> +
>  static struct trace_buffer *alloc_buffer(unsigned long size, unsigned flags,
>  					 int order, unsigned long start,
>  					 unsigned long end,
> @@ -2590,6 +2602,12 @@ static struct trace_buffer *alloc_buffer(unsigned long size, unsigned flags,
>  
>  	mutex_init(&buffer->mutex);
>  
> +	/* Persistent ring buffer needs to flush cache before reboot. */
> +	if (start & end) {
> +		buffer->flush_nb.notifier_call = rb_flush_buffer_cb;
> +		atomic_notifier_chain_register(&panic_notifier_list, &buffer->flush_nb);
> +	}
> +
>  	return_ptr(buffer);
>  
>   fail_free_buffers:
> @@ -2677,6 +2695,9 @@ ring_buffer_free(struct trace_buffer *buffer)
>  {
>  	int cpu;
>  
> +	if (buffer->range_addr_start && buffer->range_addr_end)
> +		atomic_notifier_chain_unregister(&panic_notifier_list, &buffer->flush_nb);
> +
>  	cpuhp_state_remove_instance(CPUHP_TRACE_RB_PREPARE, &buffer->node);
>  
>  	irq_work_sync(&buffer->irq_work.work);
> 


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

^ permalink raw reply

* Re: [PATCH v17 0/3] Improve proc RSS accuracy
From: Heiko Carstens @ 2026-02-26 12:04 UTC (permalink / raw)
  To: Mathieu Desnoyers
  Cc: Andrew Morton, linux-kernel, Paul E. McKenney, Steven Rostedt,
	Masami Hiramatsu, Dennis Zhou, Tejun Heo, Christoph Lameter,
	Martin Liu, David Rientjes, christian.koenig, Shakeel Butt,
	SeongJae Park, Michal Hocko, Johannes Weiner, Sweet Tea Dorminy,
	Lorenzo Stoakes, Liam R . Howlett, Mike Rapoport,
	Suren Baghdasaryan, Vlastimil Babka, Christian Brauner, Wei Yang,
	David Hildenbrand, Miaohe Lin, Al Viro, linux-mm,
	linux-trace-kernel, Yu Zhao, Roman Gushchin, Mateusz Guzik,
	Matthew Wilcox, Baolin Wang, Aboorva Devarajan, Vasily Gorbik,
	linux-s390
In-Reply-To: <20260217161006.1105611-1-mathieu.desnoyers@efficios.com>

On Tue, Feb 17, 2026 at 11:10:03AM -0500, Mathieu Desnoyers wrote:
> This series introduces the hierarchical tree counter (hpcc) to increase
> accuracy of approximated RSS counters exposed through proc interfaces.
> 
> With a test program hopping across CPUs doing frequent mmap/munmap
> operations, the upstream implementation approximation reaches a 1GB
> delta from the precise value after a few minutes, compared to a 80MB
> delta with the hierarchical counter. The hierarchical counter provides a
> guaranteed maximum approximation inaccuracy of 192MB on that hardware
> topology.
> 
> This series is based on
> commit 0f2acd3148e0 Merge tag 'm68knommu-for-v7.0' of git://git.kernel.org/pub/scm/linux/kernel/git/gerg/m68knommu
> 
> The main changes since v16:
> - Dropped OOM killer 2-pass task selection algorithm.
> - Introduce Kunit tests.
> - Only perform atomic increments of intermediate tree nodes when
>   bits which are significant for carry propagation are being changed.

This seems to cause crashes with linux-next on s390, at least I could bisect
it to the last patch of this series. Reverting the last one, makes the crashes
go away:

0acac6604c1cfd7a1762901f0a4abe87cf3a8619 is the first bad commit
commit 0acac6604c1cfd7a1762901f0a4abe87cf3a8619 (HEAD)
Author:     Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
AuthorDate: Tue Feb 17 11:10:06 2026 -0500
Commit:     Andrew Morton <akpm@linux-foundation.org>
CommitDate: Tue Feb 24 11:15:15 2026 -0800

    mm: improve RSS counter approximation accuracy for proc interfaces

Unable to handle kernel pointer dereference in virtual kernel address space
Failing address: 766d615f72615000 TEID: 766d615f72615803 ESOP-2 FSI
Fault in home space mode while using kernel ASCE.
AS:000000025dc04007 R3:0000000000000024
Oops: 0038 ilc:2 [#1]SMP
Modules linked in:
CPU: 0 UID: 0 PID: 1 Comm: swapper/0 Not tainted 7.0.0-20260224.rc1.git266.3ef088b0c577.300.fc43.s390x+next #1 PREEMPTLAZY
Hardware name: IBM 3931 A01 703 (z/VM 7.4.0)
Krnl PSW : 0704c00180000000 00000216ef164cde (kernfs_name_hash+0x1e/0xb0)
           R:0 T:1 IO:1 EX:1 Key:0 M:1 W:0 P:0 AS:3 CC:0 PM:0 RI:0 EA:3
Krnl GPRS: 0000000000000000 0000000000000000 766d615f72615f65 0000000000000000
           766d615f72615f65 0000000000000000 0000000000000000 0000000000000000
           766d615f72615f65 0000000081212440 0000000000000000 0000000000000000
           0000000080a00000 00000216efcb5390 00000216ef16530c 00000196eeb07ae0
Krnl Code: 00000216ef164cd2: a7190000            lghi    %r1,0
           00000216ef164cd6: b9040042            lgr     %r4,%r2
          *00000216ef164cda: a7090000            lghi    %r0,0
          >00000216ef164cde: b25e0014            srst    %r1,%r4
           00000216ef164ce2: a714fffe            brc     1,00000216ef164cde
           00000216ef164ce6: b9e92051            sgrk    %r5,%r1,%r2
           00000216ef164cea: ec1200208076        crj     %r1,%r2,8,00000216ef164d2a
           00000216ef164cf0: b9160005            llgfr   %r0,%r5
Call Trace:
 [<00000216ef164cde>] kernfs_name_hash+0x1e/0xb0
 [<00000216ef167d32>] kernfs_remove_by_name_ns+0x72/0x120
 [<00000216ef16bbfa>] remove_files+0x4a/0x90
 [<00000216ef16bf96>] create_files+0x276/0x2b0
 [<00000216ef16c15a>] internal_create_group+0x18a/0x320
 [<00000216f09b61c6>] swap_init+0x5e/0xa0
 [<00000216eec7fb00>] do_one_initcall+0x40/0x270
 [<00000216f0990a40>] kernel_init_freeable+0x2b0/0x330
 [<00000216efb5160e>] kernel_init+0x2e/0x180
 [<00000216eec81ffc>] __ret_from_fork+0x3c/0x240
 [<00000216efb5e052>] ret_from_fork+0xa/0x30
Last Breaking-Event-Address:
 [<00000216ef165306>] kernfs_find_ns+0x76/0x140
Kernel panic - not syncing: Fatal exception: panic_on_oops

^ permalink raw reply

* Re: [PATCH] kernel/trace/ftrace: introduce ftrace module notifier
From: Miroslav Benes @ 2026-02-26 10:51 UTC (permalink / raw)
  To: Song Chen
  Cc: Steven Rostedt, mcgrof, petr.pavlu, da.gomez, samitolvanen,
	atomlin, mhiramat, mark.rutland, mathieu.desnoyers, linux-modules,
	linux-kernel, linux-trace-kernel, live-patching
In-Reply-To: <e18ed5f4-3917-46e7-bca9-78063e6e4457@189.cn>

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

Hi,

+ Cc: live-patching@vger.kernel.org

On Thu, 26 Feb 2026, Song Chen wrote:

> Hi,
> 
> 在 2026/2/26 08:27, Steven Rostedt 写道:
> > On Wed, 25 Feb 2026 13:46:39 +0800
> > chensong_2000@189.cn wrote:
> > 
> >> From: Song Chen <chensong_2000@189.cn>
> >>
> >> Like kprobe, fprobe and btf, this patch attempts to introduce
> >> a notifier_block for ftrace to decouple its initialization from
> >> load_module.
> >>
> >> Below is the table of ftrace fucntions calls in different
> >> module state:
> >>
> >>  MODULE_STATE_UNFORMED	ftrace_module_init
> >>  MODULE_STATE_COMING	ftrace_module_enable
> >>  MODULE_STATE_LIVE	ftrace_free_mem
> >>  MODULE_STATE_GOING	ftrace_release_mod
> >>
> >> Unlike others, ftrace module notifier must take care of state
> >> MODULE_STATE_UNFORMED to ensure calling ftrace_module_init
> >> before complete_formation which changes module's text property.
> >>
> >> That pretty much remains same logic with its original design,
> >> the only thing that changes is blocking_notifier_call_chain
> >> (MODULE_STATE_GOING) has to be moved from coming_cleanup to
> >> ddebug_cleanup in function load_module to ensure
> >> ftrace_release_mod is invoked in case complete_formation fails.
> >>
> >> Signed-off-by: Song Chen <chensong_2000@189.cn>
> >> ---
> >>   kernel/module/main.c  | 14 ++++----------
> >>   kernel/trace/ftrace.c | 37 +++++++++++++++++++++++++++++++++++++
> >>   2 files changed, 41 insertions(+), 10 deletions(-)
> >>
> >> diff --git a/kernel/module/main.c b/kernel/module/main.c
> >> index 710ee30b3bea..5dc0a980e9bd 100644
> >> --- a/kernel/module/main.c
> >> +++ b/kernel/module/main.c
> >> @@ -45,7 +45,6 @@
> >>   #include <linux/license.h>
> >>   #include <asm/sections.h>
> >>   #include <linux/tracepoint.h>
> >> -#include <linux/ftrace.h>
> >>   #include <linux/livepatch.h>
> >>   #include <linux/async.h>
> >>   #include <linux/percpu.h>
> >> @@ -836,7 +835,6 @@ SYSCALL_DEFINE2(delete_module, const char __user *,
> >> name_user,
> >>    blocking_notifier_call_chain(&module_notify_list,
> >>    			     MODULE_STATE_GOING, mod);
> >>   	klp_module_going(mod);
> >> -	ftrace_release_mod(mod);
> > 
> > Is the above safe? klp uses ftrace. That means klp_module_going() may
> > need to be called before ftrace_release_mod(). That said, I wonder if
> > klp_module_going() could be moved into ftrace_release_mod()?
> > 
> >>   
> 
> I didn't test with klp, so i'm not sure if it's safe. But i consider klp is
> the other part which should be decoupled after ftrace and klp should introduce
> its own notifier.
> 
> If klp_module_going must be running before ftrace_release_mod, i can try to
> use priority in notifier_block to ensure their order.
> 
> Let me see if there is any way to use notifier and remain below calling
> sequence:
> 
> ftrace_module_enable
> klp_module_coming
> blocking_notifier_call_chain_robust(MODULE_STATE_COMING)
> 
> blocking_notifier_call_chain(MODULE_STATE_GOING)
> klp_module_going
> ftrace_release_mod

Both klp and ftrace used module notifiers in the past. We abandoned that 
and opted for direct calls due to issues with ordering at the time. I do 
not have the list of problems at hand but I remember it was very fragile.

See commits 7dcd182bec27 ("ftrace/module: remove ftrace module 
notifier"), 7e545d6eca20 ("livepatch/module: remove livepatch module 
notifier") and their surroundings.

So unless there is a reason for the change (which should be then carefully 
reviewed and properly tested), I would prefer to keep it as is. What is 
the motivation? I am failing to find it in the commit log.

Regards,
Miroslav

^ permalink raw reply

* Re: [PATCH] kernel/trace/ftrace: introduce ftrace module notifier
From: Song Chen @ 2026-02-26 10:12 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: mcgrof, petr.pavlu, da.gomez, samitolvanen, atomlin, mhiramat,
	mark.rutland, mathieu.desnoyers, linux-modules, linux-kernel,
	linux-trace-kernel
In-Reply-To: <20260225192724.48ed165e@fedora>

Hi,

在 2026/2/26 08:27, Steven Rostedt 写道:
> On Wed, 25 Feb 2026 13:46:39 +0800
> chensong_2000@189.cn wrote:
> 
>> From: Song Chen <chensong_2000@189.cn>
>>
>> Like kprobe, fprobe and btf, this patch attempts to introduce
>> a notifier_block for ftrace to decouple its initialization from
>> load_module.
>>
>> Below is the table of ftrace fucntions calls in different
>> module state:
>>
>> 	MODULE_STATE_UNFORMED	ftrace_module_init
>> 	MODULE_STATE_COMING	ftrace_module_enable
>> 	MODULE_STATE_LIVE	ftrace_free_mem
>> 	MODULE_STATE_GOING	ftrace_release_mod
>>
>> Unlike others, ftrace module notifier must take care of state
>> MODULE_STATE_UNFORMED to ensure calling ftrace_module_init
>> before complete_formation which changes module's text property.
>>
>> That pretty much remains same logic with its original design,
>> the only thing that changes is blocking_notifier_call_chain
>> (MODULE_STATE_GOING) has to be moved from coming_cleanup to
>> ddebug_cleanup in function load_module to ensure
>> ftrace_release_mod is invoked in case complete_formation fails.
>>
>> Signed-off-by: Song Chen <chensong_2000@189.cn>
>> ---
>>   kernel/module/main.c  | 14 ++++----------
>>   kernel/trace/ftrace.c | 37 +++++++++++++++++++++++++++++++++++++
>>   2 files changed, 41 insertions(+), 10 deletions(-)
>>
>> diff --git a/kernel/module/main.c b/kernel/module/main.c
>> index 710ee30b3bea..5dc0a980e9bd 100644
>> --- a/kernel/module/main.c
>> +++ b/kernel/module/main.c
>> @@ -45,7 +45,6 @@
>>   #include <linux/license.h>
>>   #include <asm/sections.h>
>>   #include <linux/tracepoint.h>
>> -#include <linux/ftrace.h>
>>   #include <linux/livepatch.h>
>>   #include <linux/async.h>
>>   #include <linux/percpu.h>
>> @@ -836,7 +835,6 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user,
>>   	blocking_notifier_call_chain(&module_notify_list,
>>   				     MODULE_STATE_GOING, mod);
>>   	klp_module_going(mod);
>> -	ftrace_release_mod(mod);
> 
> Is the above safe? klp uses ftrace. That means klp_module_going() may
> need to be called before ftrace_release_mod(). That said, I wonder if
> klp_module_going() could be moved into ftrace_release_mod()?
> 
>>   

I didn't test with klp, so i'm not sure if it's safe. But i consider klp 
is the other part which should be decoupled after ftrace and klp should 
introduce its own notifier.

If klp_module_going must be running before ftrace_release_mod, i can try 
to use priority in notifier_block to ensure their order.

Let me see if there is any way to use notifier and remain below calling 
sequence:

ftrace_module_enable
klp_module_coming
blocking_notifier_call_chain_robust(MODULE_STATE_COMING)

blocking_notifier_call_chain(MODULE_STATE_GOING)
klp_module_going
ftrace_release_mod


>>   	async_synchronize_full();
>>   
>> @@ -3067,8 +3065,6 @@ static noinline int do_init_module(struct module *mod)
>>   	if (!mod->async_probe_requested)
>>   		async_synchronize_full();
>>   
>> -	ftrace_free_mem(mod, mod->mem[MOD_INIT_TEXT].base,
>> -			mod->mem[MOD_INIT_TEXT].base + mod->mem[MOD_INIT_TEXT].size);
> 
> Have you tested the case for why this is called? It has to be called
> before the module frees the kallsyms. It's for tracing the module's
> init functions.
> 
>    cd /sys/kernel/tracing
>    echo :mod:<module> > set_ftrace_filter
>    echo function > current_tracer
>    modprobe <module>
>    cat trace
> 
> You should see the init functions of the module loaded. If
> ftrace_free_mem() is called after the module frees the kallsyms of the
> module init functions, you'll just get garbage for the init function
> names.
> 
> 

Yes, after applying this patch, i tested it with your above commands, 
result is:

cat trace_pipe
            <...>-4027    [004] .....   103.171161: mem_blkdev_init 
<-do_one_initcall
           insmod-4027    [004] .....   103.249854: mem_blkdev_queue_rq 
<-blk_mq_dispatch_rq_list
           insmod-4027    [004] .....   103.249865: mem_blkdev_queue_rq 
<-blk_mq_dispatch_rq_list
....
module init function can be seen when module is being loaded.

As far as my understanding, ftrace_free_mem is called right after 
blocking_notifier_call_chain(MODULE_STATE_LIVE) originally in 
do_init_module, after this patch, it's called by notifier, almost 
nothing changed, so no impact to current calling sequence.

Correct me if I'm wrong.

> 
>>   	mutex_lock(&module_mutex);
>>   	/* Drop initial reference. */
>>   	module_put(mod);
>> @@ -3131,7 +3127,6 @@ static noinline int do_init_module(struct module *mod)
>>   	blocking_notifier_call_chain(&module_notify_list,
>>   				     MODULE_STATE_GOING, mod);
>>   	klp_module_going(mod);
>> -	ftrace_release_mod(mod);
>>   	free_module(mod);
>>   	wake_up_all(&module_wq);
>>   
>> @@ -3278,7 +3273,6 @@ static int prepare_coming_module(struct module *mod)
>>   {
>>   	int err;
>>   
>> -	ftrace_module_enable(mod);
>>   	err = klp_module_coming(mod);
> 
> Same issue with ftrace and klp here.
> 
>>   	if (err)
>>   		return err;
>> @@ -3461,7 +3455,8 @@ static int load_module(struct load_info *info, const char __user *uargs,
>>   	init_build_id(mod, info);
>>   
>>   	/* Ftrace init must be called in the MODULE_STATE_UNFORMED state */
>> -	ftrace_module_init(mod);
>> +	blocking_notifier_call_chain(&module_notify_list,
>> +				MODULE_STATE_UNFORMED, mod);
>>   
>>   	/* Finally it's fully formed, ready to start executing. */
>>   	err = complete_formation(mod, info);
>> @@ -3513,8 +3508,6 @@ static int load_module(struct load_info *info, const char __user *uargs,
>>    coming_cleanup:
>>   	mod->state = MODULE_STATE_GOING;
>>   	destroy_params(mod->kp, mod->num_kp);
>> -	blocking_notifier_call_chain(&module_notify_list,
>> -				     MODULE_STATE_GOING, mod);
>>   	klp_module_going(mod);
> 
> Now klp_module_going() may need to be called *after* the
> MODULE_STATE_GOING callbacks and *before* ftrace_release_mod(). But
> again, if that's moved into ftrace_release_mod() it may be fine.
> 
>>    bug_cleanup:
>>   	mod->state = MODULE_STATE_GOING;
>> @@ -3524,7 +3517,8 @@ static int load_module(struct load_info *info, const char __user *uargs,
>>   	mutex_unlock(&module_mutex);
>>   
>>    ddebug_cleanup:
>> -	ftrace_release_mod(mod);
>> +	blocking_notifier_call_chain(&module_notify_list,
>> +				     MODULE_STATE_GOING, mod);
>>   	synchronize_rcu();
>>   	kfree(mod->args);
>>    free_arch_cleanup:
>> diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
> 
> -- Steve
> 


^ permalink raw reply

* Re: [syzbot] [trace?] WARNING in tracing_buffers_mmap_close (3)
From: syzbot @ 2026-02-26  9:43 UTC (permalink / raw)
  To: linux-kernel, linux-trace-kernel, mathieu.desnoyers, mhiramat,
	rostedt, syzkaller-bugs, wangqing7171
In-Reply-To: <20260226091657.895403-1-wangqing7171@gmail.com>

Hello,

syzbot has tested the proposed patch and the reproducer did not trigger any issue:

Reported-by: syzbot+3b5dd2030fe08afdf65d@syzkaller.appspotmail.com
Tested-by: syzbot+3b5dd2030fe08afdf65d@syzkaller.appspotmail.com

Tested on:

commit:         f4d0ec0a Merge tag 'erofs-for-7.0-rc2-fixes' of git://..
git tree:       upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=1222bde6580000
kernel config:  https://syzkaller.appspot.com/x/.config?x=af6ed0125ed44356
dashboard link: https://syzkaller.appspot.com/bug?extid=3b5dd2030fe08afdf65d
compiler:       gcc (Debian 14.2.0-19) 14.2.0, GNU ld (GNU Binutils for Debian) 2.44
patch:          https://syzkaller.appspot.com/x/patch.diff?x=145d4d5a580000

Note: testing is done by a robot and is best-effort only.

^ permalink raw reply

* Re: [syzbot] [trace?] WARNING in tracing_buffers_mmap_close (3)
From: Qing Wang @ 2026-02-26  9:16 UTC (permalink / raw)
  To: syzbot+3b5dd2030fe08afdf65d
  Cc: linux-kernel, linux-trace-kernel, mathieu.desnoyers, mhiramat,
	rostedt, syzkaller-bugs
In-Reply-To: <699fc6d3.a00a0220.21906d.0073.GAE@google.com>

#syz test

diff --git a/include/linux/ring_buffer.h b/include/linux/ring_buffer.h
index 876358cfe1b1..07f5127c8255 100644
--- a/include/linux/ring_buffer.h
+++ b/include/linux/ring_buffer.h
@@ -248,6 +248,7 @@ int trace_rb_cpu_prepare(unsigned int cpu, struct hlist_node *node);
 
 int ring_buffer_map(struct trace_buffer *buffer, int cpu,
 		    struct vm_area_struct *vma);
+void ring_buffer_map_user_mapped_inc(struct trace_buffer *buffer, int cpu);
 int ring_buffer_unmap(struct trace_buffer *buffer, int cpu);
 int ring_buffer_map_get_reader(struct trace_buffer *buffer, int cpu);
 #endif /* _LINUX_RING_BUFFER_H */
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
index f16f053ef77d..59516b89e612 100644
--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -7310,6 +7310,30 @@ int ring_buffer_map(struct trace_buffer *buffer, int cpu,
 	return err;
 }
 
+/**
+ * ring_buffer_map_user_mapped_inc - Increment user_mapped counter for VMA duplication
+ * @buffer: The ring buffer
+ * @cpu: The CPU of the ring buffer to increment
+ *
+ * This is called when a VMA is duplicated (e.g., on fork()) to increment
+ * the user_mapped counter without remapping pages.
+ */
+void ring_buffer_map_user_mapped_inc(struct trace_buffer *buffer, int cpu)
+{
+	struct ring_buffer_per_cpu *cpu_buffer;
+
+	if (!cpumask_test_cpu(cpu, buffer->cpumask))
+		return;
+
+	cpu_buffer = buffer->buffers[cpu];
+
+	guard(mutex)(&cpu_buffer->mapping_lock);
+
+	if (cpu_buffer->user_mapped)
+		__rb_inc_dec_mapped(cpu_buffer, true);
+}
+EXPORT_SYMBOL_GPL(ring_buffer_map_user_mapped_inc);
+
 int ring_buffer_unmap(struct trace_buffer *buffer, int cpu)
 {
 	struct ring_buffer_per_cpu *cpu_buffer;
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 23de3719f495..b2ab95ed8d41 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -8213,6 +8213,14 @@ static inline int get_snapshot_map(struct trace_array *tr) { return 0; }
 static inline void put_snapshot_map(struct trace_array *tr) { }
 #endif
 
+static void tracing_buffers_mmap_open(struct vm_area_struct *vma)
+{
+	struct ftrace_buffer_info *info = vma->vm_file->private_data;
+	struct trace_iterator *iter = &info->iter;
+
+	ring_buffer_map_user_mapped_inc(iter->array_buffer->buffer, iter->cpu_file);
+}
+
 static void tracing_buffers_mmap_close(struct vm_area_struct *vma)
 {
 	struct ftrace_buffer_info *info = vma->vm_file->private_data;
@@ -8232,6 +8240,7 @@ static int tracing_buffers_may_split(struct vm_area_struct *vma, unsigned long a
 }
 
 static const struct vm_operations_struct tracing_buffers_vmops = {
+	.open		= tracing_buffers_mmap_open,
 	.close		= tracing_buffers_mmap_close,
 	.may_split      = tracing_buffers_may_split,
 };

^ permalink raw reply related

* [PATCH v1] mm: annotate data race of f_ra.prev_pos
From: Jiayuan Chen @ 2026-02-26  8:40 UTC (permalink / raw)
  To: linux-mm
  Cc: jiayuan.chen, Jiayuan Chen, syzbot+6880f676b265dbd42d63,
	Theodore Ts'o, Andreas Dilger, Konstantin Komarov,
	Steven Rostedt, Masami Hiramatsu, Mathieu Desnoyers,
	Matthew Wilcox (Oracle), Andrew Morton, Hugh Dickins, Baolin Wang,
	Jan Kara, linux-ext4, linux-kernel, ntfs3, linux-trace-kernel,
	linux-fsdevel

From: Jiayuan Chen <jiayuan.chen@shopee.com>

KCSAN reports a data race when concurrent readers access the same
struct file:

  BUG: KCSAN: data-race in filemap_read / filemap_splice_read

  write to 0xffff88811a6f8228 of 8 bytes by task 10061 on cpu 0:
   filemap_splice_read+0x523/0x780 mm/filemap.c:3125
   ...

  write to 0xffff88811a6f8228 of 8 bytes by task 10066 on cpu 1:
   filemap_read+0x98d/0xa10 mm/filemap.c:2873
   ...

Both filemap_read() and filemap_splice_read() update f_ra.prev_pos
without synchronization. This is a benign race since prev_pos is only
used as a hint for readahead heuristics in page_cache_sync_ra(), and a
stale or torn value merely results in a suboptimal readahead decision,
not a correctness issue.

Use WRITE_ONCE/READ_ONCE to annotate all accesses to prev_pos across
the tree for consistency and silence KCSAN.

Reported-by: syzbot+6880f676b265dbd42d63@syzkaller.appspotmail.com
Link: https://syzkaller.appspot.com/bug?extid=6880f676b265dbd42d63
Signed-off-by: Jiayuan Chen <jiayuan.chen@shopee.com>
---
 fs/ext4/dir.c                    | 2 +-
 fs/ntfs3/fsntfs.c                | 2 +-
 include/trace/events/readahead.h | 2 +-
 mm/filemap.c                     | 6 +++---
 mm/readahead.c                   | 4 ++--
 mm/shmem.c                       | 2 +-
 6 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
index 28b2a3deb954..1ddf7acce5ca 100644
--- a/fs/ext4/dir.c
+++ b/fs/ext4/dir.c
@@ -200,7 +200,7 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
 					sb->s_bdev->bd_mapping,
 					&file->f_ra, file, index,
 					1 << EXT4_SB(sb)->s_min_folio_order);
-			file->f_ra.prev_pos = (loff_t)index << PAGE_SHIFT;
+			WRITE_ONCE(file->f_ra.prev_pos, (loff_t)index << PAGE_SHIFT);
 			bh = ext4_bread(NULL, inode, map.m_lblk, 0);
 			if (IS_ERR(bh)) {
 				err = PTR_ERR(bh);
diff --git a/fs/ntfs3/fsntfs.c b/fs/ntfs3/fsntfs.c
index 0df2aa81d884..d1232fc03c08 100644
--- a/fs/ntfs3/fsntfs.c
+++ b/fs/ntfs3/fsntfs.c
@@ -1239,7 +1239,7 @@ int ntfs_read_run_nb_ra(struct ntfs_sb_info *sbi, const struct runs_tree *run,
 			if (!ra_has_index(ra, index)) {
 				page_cache_sync_readahead(mapping, ra, NULL,
 							  index, 1);
-				ra->prev_pos = (loff_t)index << PAGE_SHIFT;
+				WRITE_ONCE(ra->prev_pos, (loff_t)index << PAGE_SHIFT);
 			}
 		}
 
diff --git a/include/trace/events/readahead.h b/include/trace/events/readahead.h
index 0997ac5eceab..63d8df6c2983 100644
--- a/include/trace/events/readahead.h
+++ b/include/trace/events/readahead.h
@@ -101,7 +101,7 @@ DECLARE_EVENT_CLASS(page_cache_ra_op,
 		__entry->async_size = ra->async_size;
 		__entry->ra_pages = ra->ra_pages;
 		__entry->mmap_miss = ra->mmap_miss;
-		__entry->prev_pos = ra->prev_pos;
+		__entry->prev_pos = READ_ONCE(ra->prev_pos);
 		__entry->req_count = req_count;
 	),
 
diff --git a/mm/filemap.c b/mm/filemap.c
index 63f256307fdd..d3e2d4b826b9 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -2771,7 +2771,7 @@ ssize_t filemap_read(struct kiocb *iocb, struct iov_iter *iter,
 	int i, error = 0;
 	bool writably_mapped;
 	loff_t isize, end_offset;
-	loff_t last_pos = ra->prev_pos;
+	loff_t last_pos = READ_ONCE(ra->prev_pos);
 
 	if (unlikely(iocb->ki_pos < 0))
 		return -EINVAL;
@@ -2870,7 +2870,7 @@ ssize_t filemap_read(struct kiocb *iocb, struct iov_iter *iter,
 	} while (iov_iter_count(iter) && iocb->ki_pos < isize && !error);
 
 	file_accessed(filp);
-	ra->prev_pos = last_pos;
+	WRITE_ONCE(ra->prev_pos, last_pos);
 	return already_read ? already_read : error;
 }
 EXPORT_SYMBOL_GPL(filemap_read);
@@ -3122,7 +3122,7 @@ ssize_t filemap_splice_read(struct file *in, loff_t *ppos,
 			len -= n;
 			total_spliced += n;
 			*ppos += n;
-			in->f_ra.prev_pos = *ppos;
+			WRITE_ONCE(in->f_ra.prev_pos, *ppos);
 			if (pipe_is_full(pipe))
 				goto out;
 		}
diff --git a/mm/readahead.c b/mm/readahead.c
index 7b05082c89ea..de49b35b0329 100644
--- a/mm/readahead.c
+++ b/mm/readahead.c
@@ -142,7 +142,7 @@ void
 file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping)
 {
 	ra->ra_pages = inode_to_bdi(mapping->host)->ra_pages;
-	ra->prev_pos = -1;
+	WRITE_ONCE(ra->prev_pos, -1);
 }
 EXPORT_SYMBOL_GPL(file_ra_state_init);
 
@@ -584,7 +584,7 @@ void page_cache_sync_ra(struct readahead_control *ractl,
 	}
 
 	max_pages = ractl_max_pages(ractl, req_count);
-	prev_index = (unsigned long long)ra->prev_pos >> PAGE_SHIFT;
+	prev_index = (unsigned long long)READ_ONCE(ra->prev_pos) >> PAGE_SHIFT;
 	/*
 	 * A start of file, oversized read, or sequential cache miss:
 	 * trivial case: (index - prev_index) == 1
diff --git a/mm/shmem.c b/mm/shmem.c
index 5e7dcf5bc5d3..03569199baf4 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -3642,7 +3642,7 @@ static ssize_t shmem_file_splice_read(struct file *in, loff_t *ppos,
 		len -= n;
 		total_spliced += n;
 		*ppos += n;
-		in->f_ra.prev_pos = *ppos;
+		WRITE_ONCE(in->f_ra.prev_pos, *ppos);
 		if (pipe_is_full(pipe))
 			break;
 
-- 
2.43.0


^ permalink raw reply related

* [PATCH 6.12.y] rxrpc: Fix recvmsg() unconditional requeue
From: Robert Garcia @ 2026-02-26  8:23 UTC (permalink / raw)
  To: stable, David Howells
  Cc: Marc Dionne, Robert Garcia, Steven Rostedt, linux-kernel,
	Masami Hiramatsu, David S . Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, linux-afs, linux-trace-kernel, netdev, Faith,
	Pumpkin Chang, Nir Ohfeld, Willy Tarreau, Simon Horman

From: David Howells <dhowells@redhat.com>

[ Upstream commit 2c28769a51deb6022d7fbd499987e237a01dd63a ]

If rxrpc_recvmsg() fails because MSG_DONTWAIT was specified but the call at
the front of the recvmsg queue already has its mutex locked, it requeues
the call - whether or not the call is already queued.  The call may be on
the queue because MSG_PEEK was also passed and so the call was not dequeued
or because the I/O thread requeued it.

The unconditional requeue may then corrupt the recvmsg queue, leading to
things like UAFs or refcount underruns.

Fix this by only requeuing the call if it isn't already on the queue - and
moving it to the front if it is already queued.  If we don't queue it, we
have to put the ref we obtained by dequeuing it.

Also, MSG_PEEK doesn't dequeue the call so shouldn't call
rxrpc_notify_socket() for the call if we didn't use up all the data on the
queue, so fix that also.

Fixes: 540b1c48c37a ("rxrpc: Fix deadlock between call creation and sendmsg/recvmsg")
Reported-by: Faith <faith@zellic.io>
Reported-by: Pumpkin Chang <pumpkin@devco.re>
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Marc Dionne <marc.dionne@auristor.com>
cc: Nir Ohfeld <niro@wiz.io>
cc: Willy Tarreau <w@1wt.eu>
cc: Simon Horman <horms@kernel.org>
cc: linux-afs@lists.infradead.org
cc: stable@kernel.org
Link: https://patch.msgid.link/95163.1768428203@warthog.procyon.org.uk
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
[Use spin_unlock instead of spin_unlock_irq to maintain context consistency.]
Signed-off-by: Robert Garcia <rob_garcia@163.com>
---
 include/trace/events/rxrpc.h |  4 ++++
 net/rxrpc/recvmsg.c          | 19 +++++++++++++++----
 2 files changed, 19 insertions(+), 4 deletions(-)

diff --git a/include/trace/events/rxrpc.h b/include/trace/events/rxrpc.h
index eea3769765ac..c6cae9456698 100644
--- a/include/trace/events/rxrpc.h
+++ b/include/trace/events/rxrpc.h
@@ -274,6 +274,7 @@
 	EM(rxrpc_call_put_kernel,		"PUT kernel  ") \
 	EM(rxrpc_call_put_poke,			"PUT poke    ") \
 	EM(rxrpc_call_put_recvmsg,		"PUT recvmsg ") \
+	EM(rxrpc_call_put_recvmsg_peek_nowait,	"PUT peek-nwt") \
 	EM(rxrpc_call_put_release_sock,		"PUT rls-sock") \
 	EM(rxrpc_call_put_release_sock_tba,	"PUT rls-sk-a") \
 	EM(rxrpc_call_put_sendmsg,		"PUT sendmsg ") \
@@ -291,6 +292,9 @@
 	EM(rxrpc_call_see_distribute_error,	"SEE dist-err") \
 	EM(rxrpc_call_see_input,		"SEE input   ") \
 	EM(rxrpc_call_see_recvmsg,		"SEE recvmsg ") \
+	EM(rxrpc_call_see_recvmsg_requeue,	"SEE recv-rqu") \
+	EM(rxrpc_call_see_recvmsg_requeue_first, "SEE recv-rqF") \
+	EM(rxrpc_call_see_recvmsg_requeue_move,	"SEE recv-rqM") \
 	EM(rxrpc_call_see_release,		"SEE release ") \
 	EM(rxrpc_call_see_userid_exists,	"SEE u-exists") \
 	EM(rxrpc_call_see_waiting_call,		"SEE q-conn  ") \
diff --git a/net/rxrpc/recvmsg.c b/net/rxrpc/recvmsg.c
index e24a44bae9a3..b6e524c065f0 100644
--- a/net/rxrpc/recvmsg.c
+++ b/net/rxrpc/recvmsg.c
@@ -430,7 +430,8 @@ int rxrpc_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
 	if (rxrpc_call_has_failed(call))
 		goto call_failed;
 
-	if (!skb_queue_empty(&call->recvmsg_queue))
+	if (!(flags & MSG_PEEK) &&
+	    !skb_queue_empty(&call->recvmsg_queue))
 		rxrpc_notify_socket(call);
 	goto not_yet_complete;
 
@@ -461,11 +462,21 @@ int rxrpc_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
 error_requeue_call:
 	if (!(flags & MSG_PEEK)) {
 		spin_lock(&rx->recvmsg_lock);
-		list_add(&call->recvmsg_link, &rx->recvmsg_q);
-		spin_unlock(&rx->recvmsg_lock);
+		if (list_empty(&call->recvmsg_link)) {
+			list_add(&call->recvmsg_link, &rx->recvmsg_q);
+			rxrpc_see_call(call, rxrpc_call_see_recvmsg_requeue);
+			spin_unlock(&rx->recvmsg_lock);
+		} else if (list_is_first(&call->recvmsg_link, &rx->recvmsg_q)) {
+			spin_unlock(&rx->recvmsg_lock);
+			rxrpc_put_call(call, rxrpc_call_see_recvmsg_requeue_first);
+		} else {
+			list_move(&call->recvmsg_link, &rx->recvmsg_q);
+			spin_unlock(&rx->recvmsg_lock);
+			rxrpc_put_call(call, rxrpc_call_see_recvmsg_requeue_move);
+		}
 		trace_rxrpc_recvmsg(call_debug_id, rxrpc_recvmsg_requeue, 0);
 	} else {
-		rxrpc_put_call(call, rxrpc_call_put_recvmsg);
+		rxrpc_put_call(call, rxrpc_call_put_recvmsg_peek_nowait);
 	}
 error_no_call:
 	release_sock(&rx->sk);
-- 
2.34.1


^ permalink raw reply related

* Re: [syzbot] [trace?] WARNING in tracing_buffers_mmap_close (3)
From: syzbot @ 2026-02-26  8:18 UTC (permalink / raw)
  To: linux-kernel, linux-trace-kernel, mathieu.desnoyers, mhiramat,
	rostedt, syzkaller-bugs, wangqing7171
In-Reply-To: <20260226080013.270883-1-wangqing7171@gmail.com>

Hello,

syzbot has tested the proposed patch but the reproducer is still triggering an issue:
BUG: Bad rss-counter state

BUG: Bad rss-counter state mm:ffff888022363100 type:MM_FILEPAGES val:4 Comm:syz.0.17 Pid:6501


Tested on:

commit:         f4d0ec0a Merge tag 'erofs-for-7.0-rc2-fixes' of git://..
git tree:       upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=158ac202580000
kernel config:  https://syzkaller.appspot.com/x/.config?x=af6ed0125ed44356
dashboard link: https://syzkaller.appspot.com/bug?extid=3b5dd2030fe08afdf65d
compiler:       gcc (Debian 14.2.0-19) 14.2.0, GNU ld (GNU Binutils for Debian) 2.44
patch:          https://syzkaller.appspot.com/x/patch.diff?x=10fe1b94580000


^ permalink raw reply

* Re: [RFC PATCH v2 09/37] KVM: guest_memfd: Add support for KVM_SET_MEMORY_ATTRIBUTES2
From: Fuad Tabba @ 2026-02-26  8:11 UTC (permalink / raw)
  To: Ackerley Tng
  Cc: kvm, linux-doc, linux-kernel, linux-kselftest, linux-trace-kernel,
	x86, aik, andrew.jones, binbin.wu, bp, brauner, chao.p.peng,
	chao.p.peng, chenhuacai, corbet, dave.hansen, david, hpa,
	ira.weiny, jgg, jmattson, jroedel, jthoughton, maobibo,
	mathieu.desnoyers, maz, mhiramat, michael.roth, mingo, mlevitsk,
	oupton, pankaj.gupta, pbonzini, prsampat, qperret, ricarkol,
	rick.p.edgecombe, rientjes, rostedt, seanjc, shivankg, shuah,
	steven.price, tglx, vannapurve, vbabka, willy, wyihan, yan.y.zhao
In-Reply-To: <CAEvNRgGp598JjouayFhyVKRJnYitNYZ2Ftik0zGyS1HdYaJLKA@mail.gmail.com>

Hi Ackerley,

On Thu, 26 Feb 2026 at 04:16, Ackerley Tng <ackerleytng@google.com> wrote:
>
> Fuad Tabba <tabba@google.com> writes:
>
> > Hi Ackerley,
> >
> > Here are my thoughts, at least when it comes to pKVM.
> >
> >
> > On Tue, 24 Feb 2026 at 10:14, Ackerley Tng <ackerleytng@google.com> wrote:
> >>
> >> Ackerley Tng <ackerleytng@google.com> writes:
> >>
> >> > Ackerley Tng <ackerleytng@google.com> writes:
> >> >
> >> >>
> >> >> [...snip...]
> >> >>
> >> > Before this lands, Sean wants, at the very minimum, an in-principle
> >> > agreement on guest_memfd behavior with respect to whether or not memory
> >> > should be preserved on conversion.
> >> >>
> >> >> [...snip...]
> >> >>
> >>
> >> Here's what I've come up with, following up from last guest_memfd
> >> biweekly.
> >>
> >> Every KVM_SET_MEMORY_ATTRIBUTES2 request will be accompanied by an
> >> enum set_memory_attributes_content_policy:
> >>
> >>     enum set_memory_attributes_content_policy {
> >>         SET_MEMORY_ATTRIBUTES_CONTENT_ZERO,
> >>         SET_MEMORY_ATTRIBUTES_CONTENT_READABLE,
> >>         SET_MEMORY_ATTRIBUTES_CONTENT_ENCRYPTED,
> >>     }
> >>
> >> Within guest_memfd's KVM_SET_MEMORY_ATTRIBUTES2 handler, guest_memfd
> >> will make an arch call
> >>
> >>     kvm_gmem_arch_content_policy_supported(kvm, policy, gfn, nr_pages)
> >>
> >> where every arch will get to return some error if the requested policy
> >> is not supported for the given range.
> >
> > This hook provides the validation mechanism pKVM requires.
> >
> >> ZERO is the simplest of the above, it means that after the conversion
> >> the memory will be zeroed for the next reader.
> >>
> >> + TDX and SNP today will support ZERO since the firmware handles
> >>   zeroing.
> >> + pKVM and SW_PROTECTED_VM will apply software zeroing.
> >> + Purpose: having this policy in the API allows userspace to be sure
> >>   that the memory is zeroed after the conversion - there is no need to
> >>   zero again in userspace (addresses concern that Sean pointed out)
> >>
> >> READABLE means that after the conversion, the memory is readable by
> >> userspace (if converting to shared) or readable by the guest (if
> >> converting to private).
> >>
> >> + TDX and SNP (today) can't support this, so return -EOPNOTSUPP
> >> + SW_PROTECTED_VM will support this and do nothing extra on
> >>   conversion, since there is no encryption anyway and all content
> >>   remains readable.
> >> + pKVM will make use of the arch function above.
> >>
> >> Here's where I need input: (David's questions during the call about
> >> the full flow beginning with the guest prompted this).
> >>
> >> Since pKVM doesn't encrypt the memory contents, there must be some way
> >> that pKVM can say no when userspace requests to convert and retain
> >> READABLE contents? I think pKVM's arch function can be used to check
> >> if the guest previously made a conversion request. Fuad, to check that
> >> the guest made a conversion request, what's other parameters are
> >> needed other than gfn and nr_pages?
> >
> > The gfn and nr_pages parameters are enough I think.
> >
> > To clarify how pKVM would use this hook: all memory sharing and
> > unsharing must be initiated by the guest via a hypercall. When the
> > guest issues this hypercall, the pKVM hypervisor (EL2) exits to the
> > host kernel (EL1). The host kernel records the exit reason (share or
> > unshare) along with the specific memory address in the kvm_run
> > structure before exiting to userspace.
> >
> > We do not track this pending conversion state in the hypervisor. If a
> > compromised host kernel wants to lie and corrupt the state, it can
> > crash the system or the guest (which is an accepted DOS risk), but it
> > cannot compromise guest confidentiality because EL2 still strictly
> > enforces Stage-2 permissions. Our primary goal here is to prevent a
> > malicious or buggy userspace VMM from crashing the system.
> >
>
> Thinking through it again, there's actually no security (in terms of
> CoCo confidentiality) risk here, since the conversion ioctl doesn't
> actually tell the CoCo vendor/platform to encrypt/decrypt or flip
> permissions, it just unmaps the pages as requested.
>
> On TDX, if a rogue private to shared conversion request comes in, the
> private pages would get unmapped from the guest, and on the next guest
> access, the guest would access the page as private, so kvm's fault
> handler would think there's a shared/private mismatch and exit with
> KVM_EXIT_MEMORY_FAULT. Userspace now has a zeroed shared page, and the
> guest needs to re-accept the page to continue using it (if it knows what
> to do with a zeroed page). This would be userspace DOS-ing the guest,
> which userspace can do anyway.
>
> On pKVM, rephrasing what you said, even if there is a rogue private to
> shared conversion, EL2 still thinks of the page as private. After the
> conversion, the page can be faulted in by the host, but any access will
> be stopped by EL2.
>
> David, there's no missing piece in the flow!
>
> > When the VMM subsequently issues the KVM_SET_MEMORY_ATTRIBUTES2 ioctl
> > with the READABLE policy, we will use the
> > kvm_gmem_arch_content_policy_supported() hook in EL1 to validate the
> > ioctl. We will cross-reference the requested gfn and nr_pages against
> > the pending exit reason stored in kvm_run.
> >
> > If the VMM attempts an unsolicited conversion (i.e., there is no
> > matching exit request in kvm_run, or the addresses do not match), our
>
> Ah I see, so struct kvm_run is not considered "in the hypervisor" since
> it is modifiable by host userspace. Would you be using struct
> memory_fault in struct kvm_run?
>
> Which vcpu's kvm_run struct would you look up from
> kvm_gmem_arch_content_policy_supported()?
>
> For this to land, do you still want the gfn and nr_pages parameters?
>
> Can pKVM just always accept the request, whether the guest requested it
> or not? Thinking about it again,
> kvm_gmem_arch_content_policy_supported() probably shouldn't be used to
> guard solicited vs unsolicited requests anyway (unless you think the
> function's name should be changed?)

You spotted a flaw in my proposed validation mechanic. As you said,
KVM_SET_MEMORY_ATTRIBUTES2 is a VM-scoped ioctl, meaning we lack the
vCPU context required to safely inspect a specific kvm_run structure.
Attempting to track this state VM-wide in struct kvm_arch would
require introducing a lock on a hot memory-transition path, which we
want to avoid.

Your assessment of the security implications and the TDX fallback
mechanism is correct and applies to pKVM. Because EL2 maintains the
ultimate source of truth regarding Stage-2 permissions, a rogue
conversion by the VMM cannot breach guest confidentiality.

Given this, it makes sense for pKVM will adopt the TDX approach. We
will drop the requirement to synchronously validate the guest's intent
during the ioctl. We will always accept the request in EL1. If the VMM
is lying and the guest never actually authorized the share, the
resulting attribute mismatch will trigger a KVM_EXIT_MEMORY_FAULT upon
the next guest access, or a SIGBUS/SIGSEGV if the host userspace
attempts to map and read the memory. This will DOS/crash the VMM
without endangering the host kernel.

Therefore, kvm_gmem_arch_content_policy_supported() should not be used
for dynamic state-machine validation. We will use it strictly as a
static capability check (e.g., verifying that the requested policy is
architecturally possible).

I think that we would still require gfn and nr_pages in the hook to
allow for potential range-based capability checks in the future, but
not use them to cross-reference pending conversion requests.

Cheers,
/fuad

> > current plan is to reject the request and return an error. In the
> > future, rather than outright rejecting an unsolicited conversion, we
> > might evolve this to treat it as a host-initiated destructive reclaim,
> > forcing an unshare and zeroing the memory. For the time being,
> > explicit rejection is the simplest and safest path.
> >
>
> >> ENCRYPTED means that after the conversion, the memory contents are
> >> retained as-is, with no decryption.
> >>
> >> + TDX and SNP (today) can't support this, so return -EOPNOTSUPP
> >> + pKVM and SW_PROTECTED_VM can do nothing, but doing nothing retains
> >>   READABLE content, not ENCRYPTED content, hence SW_PROTECTED_VM
> >>   should return -EOPNOTSUPP.
> >> + Michael, you mentioned during the call that SNP is planning to
> >>   introduce a policy that retains the ENCRYPTED version for a special
> >>   GHCB call. ENCRYPTED is meant for that use case. Does it work? I'm
> >>   assuming that SNP should only support this policy given some
> >>   conditions, so would the arch call as described above work?
> >> + If this policy is specified on conversion from shared to private,
> >>   always return -EOPNOTSUPP.
> >> + When this first lands, ENCRYPTED will not be a valid option, but I'm
> >>   listing it here so we have line of sight to having this support.
> >>
> >> READABLE and ENCRYPTED defines the state after conversion clearly
> >> (instead of DONT_CARE or similar).
> >>
> >> DESTROY could be another policy, which means that after the
> >> conversion, the memory is unreadable. This is the option to address
> >> what David brought up during the call, for cases where userspace knows
> >> it is going to free the memory already and doesn't care about the
> >> state as long as nobody gets to read it. This will not implemented
> >> when feature first lands, but is presented here just to show how this
> >> can be extended in future.
> >>
> >> Right now, I'm thinking that one of the above policies MUST be
> >> specified (not specifying a policy will result in -EINVAL).
> >>
> >> How does this sound?
> >
> > I don't think that returning -EINVAL is the right thing to do here. If
> > userspace omits the policy, the API should default to
> > SET_MEMORY_ATTRIBUTES_CONTENT_ZERO and proceed with the conversion. I
> > believe that, in Linux APIs in general, omitting an optional behavior
> > flag results in the safest, most standard default action.
> >
>
> Makes sense, I'll default to zeroing then. Thanks!
>
> > Also, returning -EINVAL when no policy is specified makes the policy
> > parameter strictly mandatory. This makes it difficult for userspace's
> > to seamlessly request clean-slate, destructive conversions. Software
> > zeroing ensures deterministic behavior across pKVM, TDX, and SNP,
> > isolating the KVM uAPI from micro-architectural data destruction
> > nuances.
> >
> > Cheers,
> > /fuad

^ permalink raw reply

* Re: [syzbot] [trace?] WARNING in tracing_buffers_mmap_close (3)
From: Qing Wang @ 2026-02-26  8:00 UTC (permalink / raw)
  To: syzbot+3b5dd2030fe08afdf65d
  Cc: linux-kernel, linux-trace-kernel, mathieu.desnoyers, mhiramat,
	rostedt, syzkaller-bugs
In-Reply-To: <699fc6d3.a00a0220.21906d.0073.GAE@google.com>

#syz test

diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 23de3719f495..72b39295a8b0 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -8213,6 +8213,14 @@ static inline int get_snapshot_map(struct trace_array *tr) { return 0; }
 static inline void put_snapshot_map(struct trace_array *tr) { }
 #endif
 
+static void tracing_buffers_mmap_open(struct vm_area_struct *vma)
+{
+	struct ftrace_buffer_info *info = vma->vm_file->private_data;
+	struct trace_iterator *iter = &info->iter;
+
+	WARN_ON(ring_buffer_map(iter->array_buffer->buffer, iter->cpu_file, vma));
+}
+
 static void tracing_buffers_mmap_close(struct vm_area_struct *vma)
 {
 	struct ftrace_buffer_info *info = vma->vm_file->private_data;
@@ -8232,6 +8240,7 @@ static int tracing_buffers_may_split(struct vm_area_struct *vma, unsigned long a
 }
 
 static const struct vm_operations_struct tracing_buffers_vmops = {
+	.open		= tracing_buffers_mmap_open,
 	.close		= tracing_buffers_mmap_close,
 	.may_split      = tracing_buffers_may_split,
 };


^ permalink raw reply related

* Re: [PATCH v6 14/16] sched_ext: Export task_is_scx_enabled() for verification
From: Gabriele Monaco @ 2026-02-26  7:10 UTC (permalink / raw)
  To: Tejun Heo
  Cc: linux-kernel, Andrea Righi, Joel Fernandes, Steven Rostedt,
	Nam Cao, Juri Lelli, Ingo Molnar, Peter Zijlstra, sched-ext,
	Tomas Glozar, Clark Williams, John Kacur, linux-trace-kernel
In-Reply-To: <aZ8snSHWw-U0lVz2@slm.duckdns.org>

On Wed, 2026-02-25 at 07:08 -1000, Tejun Heo wrote:
> On Wed, Feb 25, 2026 at 10:51:20AM +0100, Gabriele Monaco wrote:
> > When a sched_ext scheduler is loaded, depending on the configuration, it
> > can handle also fair tasks, however it isn't trivial to understand if a
> > certain task is currently handled by fair or ext outside of scheduler
> > code. This can be a problem when writing verification or observability
> > tools like RV monitors.
> > 
> > Export a task_is_scx_enabled() to allow quick classification by using
> > the scx state SCX_TASK_ENABLED.
> 
> This test already exists - task_on_scx(). Please feel free to move that out
> to include/linux/sched/ext.h.

Mmh, right, thanks for the pointer!

I see task_on_scx() is used in what looks like some sched core hot paths (
pick_next_task() -> prio_less()), but I presume not inlining it isn't a big
issue.

Thanks,
Gabriele


^ permalink raw reply

* Re: [syzbot] [trace?] WARNING in tracing_buffers_mmap_close (3)
From: syzbot @ 2026-02-26  6:34 UTC (permalink / raw)
  To: linux-kernel, linux-trace-kernel, mathieu.desnoyers, mhiramat,
	rostedt, syzkaller-bugs, wangqing7171
In-Reply-To: <20260226061625.30751-1-wangqing7171@gmail.com>

Hello,

syzbot has tested the proposed patch but the reproducer is still triggering an issue:
WARNING in tracing_buffers_mmap_close

------------[ cut here ]------------
ring_buffer_unmap(iter->array_buffer->buffer, iter->cpu_file)
WARNING: kernel/trace/trace.c:8221 at tracing_buffers_mmap_close kernel/trace/trace.c:8221 [inline], CPU#0: syz.0.17/6401
WARNING: kernel/trace/trace.c:8221 at tracing_buffers_mmap_close+0xea/0x140 kernel/trace/trace.c:8216, CPU#0: syz.0.17/6401
Modules linked in:
CPU: 0 UID: 0 PID: 6401 Comm: syz.0.17 Not tainted syzkaller #0 PREEMPT(full) 
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 02/12/2026
RIP: 0010:tracing_buffers_mmap_close kernel/trace/trace.c:8221 [inline]
RIP: 0010:tracing_buffers_mmap_close+0xea/0x140 kernel/trace/trace.c:8216
Code: 08 e8 1a 74 ff ff 31 ff 89 c3 89 c6 e8 0f 50 fb ff 85 db 75 0f e8 56 55 fb ff 48 83 c4 08 5b c3 cc cc cc cc e8 47 55 fb ff 90 <0f> 0b 90 e8 3e 55 fb ff 48 83 c4 08 5b e9 54 55 83 09 e8 ff bd 66
RSP: 0018:ffffc90002f27ab8 EFLAGS: 00010293
RAX: 0000000000000000 RBX: 00000000ffffffed RCX: ffffffff820ca621
RDX: ffff88801efcdac0 RSI: ffffffff820ca639 RDI: ffff88801efcdac0
RBP: ffffffff820ca550 R08: 0000000000000005 R09: 0000000000000000
R10: 00000000ffffffed R11: 0000000000000000 R12: ffff888078da3048
R13: 0000000000000001 R14: 0000000000000005 R15: 0000000000000001
FS:  0000000000000000(0000) GS:ffff88812434f000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007f4d99a17dac CR3: 000000000e598000 CR4: 00000000003526f0
Call Trace:
 <TASK>
 vma_close mm/internal.h:190 [inline]
 remove_vma+0x88/0x160 mm/vma.c:466
 tear_down_vmas+0x2a5/0x600 mm/mmap.c:1264
 exit_mmap+0x469/0xa30 mm/mmap.c:1322
 __mmput+0x12a/0x410 kernel/fork.c:1174
 mmput+0x67/0x80 kernel/fork.c:1197
 exit_mm kernel/exit.c:581 [inline]
 do_exit+0x78a/0x2aa0 kernel/exit.c:959
 do_group_exit+0xd5/0x2a0 kernel/exit.c:1112
 __do_sys_exit_group kernel/exit.c:1123 [inline]
 __se_sys_exit_group kernel/exit.c:1121 [inline]
 __x64_sys_exit_group+0x3e/0x50 kernel/exit.c:1121
 x64_sys_call+0x102c/0x1530 arch/x86/include/generated/asm/syscalls_64.h:232
 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
 do_syscall_64+0x106/0xf80 arch/x86/entry/syscall_64.c:94
 entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f4d9979c629
Code: Unable to access opcode bytes at 0x7f4d9979c5ff.
RSP: 002b:00007ffea34a0a28 EFLAGS: 00000246 ORIG_RAX: 00000000000000e7
RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f4d9979c629
RDX: 0000000000000064 RSI: 0000000000000000 RDI: 0000000000000000
RBP: 0000000000000003 R08: 0000000000000000 R09: 00007f4d999e53e0
R10: 0000000000000001 R11: 0000000000000246 R12: 0000000000000000
R13: 00007f4d999e53e0 R14: 0000000000000003 R15: 00007ffea34a0ae0
 </TASK>


Tested on:

commit:         f4d0ec0a Merge tag 'erofs-for-7.0-rc2-fixes' of git://..
git tree:       upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=12efb55a580000
kernel config:  https://syzkaller.appspot.com/x/.config?x=af6ed0125ed44356
dashboard link: https://syzkaller.appspot.com/bug?extid=3b5dd2030fe08afdf65d
compiler:       gcc (Debian 14.2.0-19) 14.2.0, GNU ld (GNU Binutils for Debian) 2.44
patch:          https://syzkaller.appspot.com/x/patch.diff?x=1484c24a580000


^ permalink raw reply

* Re: [syzbot] [trace?] WARNING in tracing_buffers_mmap_close (3)
From: Qing Wang @ 2026-02-26  6:16 UTC (permalink / raw)
  To: syzbot+3b5dd2030fe08afdf65d
  Cc: linux-kernel, linux-trace-kernel, mathieu.desnoyers, mhiramat,
	rostedt, syzkaller-bugs
In-Reply-To: <699fc6d3.a00a0220.21906d.0073.GAE@google.com>

#syz test

diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 23de3719f495..c74ba9c8c98e 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -8251,12 +8251,14 @@ static int tracing_buffers_mmap(struct file *filp, struct vm_area_struct *vma)
 		return ret;
 
 	ret = ring_buffer_map(iter->array_buffer->buffer, iter->cpu_file, vma);
-	if (ret)
+	if (ret) {
 		put_snapshot_map(iter->tr);
+		return ret;
+	}
 
 	vma->vm_ops = &tracing_buffers_vmops;
 
-	return ret;
+	return 0;
 }
 
 static const struct file_operations tracing_buffers_fops = {

^ permalink raw reply related

* Re: [LSF/MM/BPF TOPIC][RFC PATCH v4 00/27] Private Memory Nodes (w/ Compressed RAM)
From: Gregory Price @ 2026-02-26  5:54 UTC (permalink / raw)
  To: Alistair Popple
  Cc: lsf-pc, linux-kernel, linux-cxl, cgroups, linux-mm,
	linux-trace-kernel, damon, kernel-team, gregkh, rafael, dakr,
	dave, jonathan.cameron, dave.jiang, alison.schofield,
	vishal.l.verma, ira.weiny, dan.j.williams, longman, akpm, david,
	lorenzo.stoakes, Liam.Howlett, vbabka, rppt, surenb, mhocko,
	osalvador, ziy, matthew.brost, joshua.hahnjy, rakie.kim,
	byungchul, ying.huang, axelrasmussen, yuanchu, weixugc,
	yury.norov, linux, mhiramat, mathieu.desnoyers, tj, hannes,
	mkoutny, jackmanb, sj, baolin.wang, npache, ryan.roberts,
	dev.jain, baohua, lance.yang, muchun.song, xu.xin16,
	chengming.zhou, jannh, linmiaohe, nao.horiguchi, pfalcato,
	rientjes, shakeel.butt, riel, harry.yoo, cl, roman.gushchin,
	chrisl, kasong, shikemeng, nphamcs, bhe, zhengqi.arch,
	terry.bowman
In-Reply-To: <a6izpi2wlqro72erhbvxhlx2lwdnae7my3ghfs6t33ivtixo4h@bi2u4x6qv7ul>

On Thu, Feb 26, 2026 at 02:27:24PM +1100, Alistair Popple wrote:
> On 2026-02-25 at 02:17 +1100, Gregory Price <gourry@gourry.net> wrote...
> > 
> > DEVICE_COHERENT is the odd-man out among ZONE_DEVICE modes. The others
> > use softleaf entries and don't allow direct mappings.
> 
> I think you have this around the wrong way - DEVICE_PRIVATE is the odd one out as
> it is the one ZONE_DEVICE page type that uses softleaf entries and doesn't
> allow direct mappings. Every other type of ZONE_DEVICE page allows for direct
> mappings.
> 

Sorry, you are correct.  I have trouble keeping the ZONE_DEVICE modes
straight sometimes, and all the hook sites have different reasons for why
all the different ZONE_DEVICE modes and it mucks with my head :[

Device Coherent is the one that doesn't allow pinning, but still comes
with all the baggage of not being on the lru.

Spoke a bit too bluntly here, apologies.

> Don't you still have to add code to hook every operation you care about for your
> private managed nodes?
> 
... snip ... below
> > I don't think that's needed if we just recognize ZONE is the wrong
> > abstraction to be operating on.
> > 
... snip ... below
> > If your service only allocates movable pages - your ZONE_NORMAL is
> > effectively ZONE_MOVABLE.  
> 
> This is interesting - it sounds like the conclusion of this is ZONE_* is just a
> bad abstraction and should be replaced with something else maybe some like this?
> 

Yeah i'm not totally married to this being a node, but it makes far more
sense to me than a zone.

ZONE_DEVICE sorta kinda really *wants* to be its own node, but it seems
that "what constitutes a node" was largely informed by ACPI Proximity
Domains.  Nothing in the rules say that has to remain the case.

To answer your question above - yea you still need to add code to hook
the operations - but this is essentially already true of ZONE_DEVICE
(except you have to contend with other weird ZONE_DEVICE situations).

Some of the hooks here are an experimentation in what's possible, not
what I think is reasonable (mempolicy is a good example - i don't think
userland should really be doing this anyway... but neat, it works :P)

> And FWIW I'm not tied to the ZONE_DEVICE as being a good abstraction, it's just
> what we seem to have today for determing page types. It almost sounds like what
> we want is just a bunch of hooks that can be associated with a range of pages,
> and then you just get rid of ZONE_DEVICE and instead install hooks appropriate
> for each page a driver manages. I have to think more about that though, this
> is just what popped into my head when you start saying ZONE_MOVABLE could also
> disappear :-)

Yup! Basically ZONE_MOVABLE and CMA and ZONE_DEVICE/COHERENT all try to
do similar things for different reasons.

Zones manage to somehow be both too-broad AND too-narrow.

In my head, we should just be able to just plop these things "into the
buddy" and provide hooks that say what's allow "for those pages".

That sounds like Non-Uniform Memory Access *cough* :P

Heck, I was even playing with adding these nodes *back into* the
fallback lists for some situations.

NP_OPS_DIRECT / NP_OPS_FALLBACK
	don't require __GFP_PRIVATE, but give me the hooks I want :V 

> > Where there are new injection sites, it's because ZONE_DEVICE opts
> > out of ever touching that code in some other silently implied way.
> 
> Yeah, I hate that aspect of ZONE_DEVICE. There are far too many places where we
> "prove" you can't have a ZONE_DEVICE page because of ad-hoc "reasons". Usually
> they take the form of it's not on the LRU, or it's not an anonymous page and
> this isn't DAX, etc.
>

It's kinda the opposite of how operating systems do everything else.

Generally we start from a basis of isolation and then poke deliberate
holes, as opposed to try to patch things up after the fact.

> > If NUMA is the interface we want, then NODE_DATA is the right direction
> > regardless of struct page's future or what zone it lives in.
> > 
> > There's no reason to keep per-page pgmap w/ device-to-node mappings.
> 
> In reality I suspect that's already the case today. I'm not sure we need
> per-page pgmap.
>

Probably, and maybe there's a good argument for stealing 80-90% of the
common surface here, shunting ZONE_DEVICE to use this instead of pgmap
before we go all the way to private nodes.

cough cough maybe i'll have looked into this by LSFMM cough cough

> > On (1): ZONE_DEVICE NUMA UAPI is harder than it looks from the surface
> 
> Ok, I will admit I've only been hovering on the surface so need to give this
> some more thought. Everything you've written below makes sense and is definitely
> food for thought. Thanks.
> 

cheers! thanks for reading :)

~Gregory

^ permalink raw reply

* Re: [PATCH v4 1/3] PCI: trace: Add PCI controller LTSSM transition tracepoint
From: Manivannan Sadhasivam @ 2026-02-26  5:52 UTC (permalink / raw)
  To: Ilpo Järvinen
  Cc: Shawn Lin, Bjorn Helgaas, linux-rockchip, linux-pci,
	linux-trace-kernel, linux-doc, Steven Rostedt, Masami Hiramatsu
In-Reply-To: <75b206bb-7fcd-2f59-4181-1839ba5aa8e4@linux.intel.com>

On Tue, Feb 24, 2026 at 05:46:29PM +0200, Ilpo Järvinen wrote:
> On Tue, 24 Feb 2026, Manivannan Sadhasivam wrote:
> 
> > On Tue, Feb 24, 2026 at 05:22:35PM +0200, Ilpo Järvinen wrote:
> > > On Thu, 22 Jan 2026, Shawn Lin wrote:
> > > 
> > > > Some platforms may provide LTSSM trace functionality, recording historical
> > > > LTSSM state transition information. This is very useful for debugging, such
> > > > as when certain devices cannot be recognized or link broken during test.
> > > > Implement the pci controller tracepoint for recording LTSSM and rate.
> > > > 
> > > > Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
> > > > ---
> > > > 
> > > > Changes in v4:
> > > > - use TRACE_EVENT_FN to notify when to start and stop the tracepoint,
> > > >   and export pci_ltssm_tp_enabled() for host drivers to use
> > > > 
> > > > Changes in v3:
> > > > - add TRACE_DEFINE_ENUM for all enums(Steven Rostedt)
> > > > 
> > > > Changes in v2: None
> > > > 
> > > >  drivers/pci/trace.c                   | 20 ++++++++++++
> > > >  include/linux/pci.h                   |  4 +++
> > > >  include/trace/events/pci_controller.h | 57 +++++++++++++++++++++++++++++++++++
> > > >  3 files changed, 81 insertions(+)
> > > >  create mode 100644 include/trace/events/pci_controller.h
> > > > 
> > > > diff --git a/drivers/pci/trace.c b/drivers/pci/trace.c
> > > > index cf11abc..d351a51 100644
> > > > --- a/drivers/pci/trace.c
> > > > +++ b/drivers/pci/trace.c
> > > > @@ -9,3 +9,23 @@
> > > >  
> > > >  #define CREATE_TRACE_POINTS
> > > >  #include <trace/events/pci.h>
> > > > +#include <trace/events/pci_controller.h>
> > > > +
> > > > +static atomic_t pcie_ltssm_tp_enabled = ATOMIC_INIT(0);
> > > > +
> > > > +bool pci_ltssm_tp_enabled(void)
> > > > +{
> > > > +	return atomic_read(&pcie_ltssm_tp_enabled) > 0;
> > > > +}
> > > > +EXPORT_SYMBOL(pci_ltssm_tp_enabled);
> > > > +
> > > > +int pci_ltssm_tp_reg(void)
> > > > +{
> > > > +	atomic_inc(&pcie_ltssm_tp_enabled);
> > > > +	return 0;
> > > > +}
> > > > +
> > > > +void pci_ltssm_tp_unreg(void)
> > > > +{
> > > > +	atomic_dec(&pcie_ltssm_tp_enabled);
> > > > +}
> > > > diff --git a/include/linux/pci.h b/include/linux/pci.h
> > > > index e7cb527..ac25a3e 100644
> > > > --- a/include/linux/pci.h
> > > > +++ b/include/linux/pci.h
> > > > @@ -2770,6 +2770,10 @@ static inline struct eeh_dev *pci_dev_to_eeh_dev(struct pci_dev *pdev)
> > > >  }
> > > >  #endif
> > > >  
> > > > +#ifdef CONFIG_TRACING
> > > > +bool pci_ltssm_tp_enabled(void);
> > > > +#endif
> > > > +
> > > >  void pci_add_dma_alias(struct pci_dev *dev, u8 devfn_from, unsigned nr_devfns);
> > > >  bool pci_devs_are_dma_aliases(struct pci_dev *dev1, struct pci_dev *dev2);
> > > >  int pci_for_each_dma_alias(struct pci_dev *pdev,
> > > > diff --git a/include/trace/events/pci_controller.h b/include/trace/events/pci_controller.h
> > > > new file mode 100644
> > > > index 0000000..db4a960
> > > > --- /dev/null
> > > > +++ b/include/trace/events/pci_controller.h
> > > > @@ -0,0 +1,57 @@
> > > > +/* SPDX-License-Identifier: GPL-2.0 */
> > > > +#undef TRACE_SYSTEM
> > > > +#define TRACE_SYSTEM pci_controller
> > > 
> > > I find putting this into "pci_controller" little odd as LTSSM is related 
> > > to PCIe links/ports. To me looks something that belongs to the existing 
> > > include/trace/events/pci.h.
> > 
> > I suggested 'pci_controller.h' since these tracepoints are only going to be used
> > by the controller drivers. Putting it under 'pci.h' will imply that these can be
> > used by the client drivers also.
> 
> PCIe r7 spec has Flit Performance Measurement Extended Capability that 
> seems to have something for LTSSM tracking and those seem more generic 
> than just for controllers (I've not spent much time on trying to fully 
> understand those capabilities, just recalled seeing them earlier).
> 

Even so, we don't know how that is going to look until someone implements it. So
I'd prefer we put this in pci_controller.h in the meantime to avoid confusion.
We can always come back later when the Flit based LTSSM tracing patch appears in
the list.

- Mani

-- 
மணிவண்ணன் சதாசிவம்

^ permalink raw reply

* Re: [RFC PATCH v2 09/37] KVM: guest_memfd: Add support for KVM_SET_MEMORY_ATTRIBUTES2
From: Ackerley Tng @ 2026-02-26  4:16 UTC (permalink / raw)
  To: Fuad Tabba
  Cc: kvm, linux-doc, linux-kernel, linux-kselftest, linux-trace-kernel,
	x86, aik, andrew.jones, binbin.wu, bp, brauner, chao.p.peng,
	chao.p.peng, chenhuacai, corbet, dave.hansen, david, hpa,
	ira.weiny, jgg, jmattson, jroedel, jthoughton, maobibo,
	mathieu.desnoyers, maz, mhiramat, michael.roth, mingo, mlevitsk,
	oupton, pankaj.gupta, pbonzini, prsampat, qperret, ricarkol,
	rick.p.edgecombe, rientjes, rostedt, seanjc, shivankg, shuah,
	steven.price, tglx, vannapurve, vbabka, willy, wyihan, yan.y.zhao
In-Reply-To: <CA+EHjTxDSW=y=sPRwW70Bz9RVYM3kSCLSbWc_X4v9hz6zj=mcg@mail.gmail.com>

Fuad Tabba <tabba@google.com> writes:

> Hi Ackerley,
>
> Here are my thoughts, at least when it comes to pKVM.
>
>
> On Tue, 24 Feb 2026 at 10:14, Ackerley Tng <ackerleytng@google.com> wrote:
>>
>> Ackerley Tng <ackerleytng@google.com> writes:
>>
>> > Ackerley Tng <ackerleytng@google.com> writes:
>> >
>> >>
>> >> [...snip...]
>> >>
>> > Before this lands, Sean wants, at the very minimum, an in-principle
>> > agreement on guest_memfd behavior with respect to whether or not memory
>> > should be preserved on conversion.
>> >>
>> >> [...snip...]
>> >>
>>
>> Here's what I've come up with, following up from last guest_memfd
>> biweekly.
>>
>> Every KVM_SET_MEMORY_ATTRIBUTES2 request will be accompanied by an
>> enum set_memory_attributes_content_policy:
>>
>>     enum set_memory_attributes_content_policy {
>>         SET_MEMORY_ATTRIBUTES_CONTENT_ZERO,
>>         SET_MEMORY_ATTRIBUTES_CONTENT_READABLE,
>>         SET_MEMORY_ATTRIBUTES_CONTENT_ENCRYPTED,
>>     }
>>
>> Within guest_memfd's KVM_SET_MEMORY_ATTRIBUTES2 handler, guest_memfd
>> will make an arch call
>>
>>     kvm_gmem_arch_content_policy_supported(kvm, policy, gfn, nr_pages)
>>
>> where every arch will get to return some error if the requested policy
>> is not supported for the given range.
>
> This hook provides the validation mechanism pKVM requires.
>
>> ZERO is the simplest of the above, it means that after the conversion
>> the memory will be zeroed for the next reader.
>>
>> + TDX and SNP today will support ZERO since the firmware handles
>>   zeroing.
>> + pKVM and SW_PROTECTED_VM will apply software zeroing.
>> + Purpose: having this policy in the API allows userspace to be sure
>>   that the memory is zeroed after the conversion - there is no need to
>>   zero again in userspace (addresses concern that Sean pointed out)
>>
>> READABLE means that after the conversion, the memory is readable by
>> userspace (if converting to shared) or readable by the guest (if
>> converting to private).
>>
>> + TDX and SNP (today) can't support this, so return -EOPNOTSUPP
>> + SW_PROTECTED_VM will support this and do nothing extra on
>>   conversion, since there is no encryption anyway and all content
>>   remains readable.
>> + pKVM will make use of the arch function above.
>>
>> Here's where I need input: (David's questions during the call about
>> the full flow beginning with the guest prompted this).
>>
>> Since pKVM doesn't encrypt the memory contents, there must be some way
>> that pKVM can say no when userspace requests to convert and retain
>> READABLE contents? I think pKVM's arch function can be used to check
>> if the guest previously made a conversion request. Fuad, to check that
>> the guest made a conversion request, what's other parameters are
>> needed other than gfn and nr_pages?
>
> The gfn and nr_pages parameters are enough I think.
>
> To clarify how pKVM would use this hook: all memory sharing and
> unsharing must be initiated by the guest via a hypercall. When the
> guest issues this hypercall, the pKVM hypervisor (EL2) exits to the
> host kernel (EL1). The host kernel records the exit reason (share or
> unshare) along with the specific memory address in the kvm_run
> structure before exiting to userspace.
>
> We do not track this pending conversion state in the hypervisor. If a
> compromised host kernel wants to lie and corrupt the state, it can
> crash the system or the guest (which is an accepted DOS risk), but it
> cannot compromise guest confidentiality because EL2 still strictly
> enforces Stage-2 permissions. Our primary goal here is to prevent a
> malicious or buggy userspace VMM from crashing the system.
>

Thinking through it again, there's actually no security (in terms of
CoCo confidentiality) risk here, since the conversion ioctl doesn't
actually tell the CoCo vendor/platform to encrypt/decrypt or flip
permissions, it just unmaps the pages as requested.

On TDX, if a rogue private to shared conversion request comes in, the
private pages would get unmapped from the guest, and on the next guest
access, the guest would access the page as private, so kvm's fault
handler would think there's a shared/private mismatch and exit with
KVM_EXIT_MEMORY_FAULT. Userspace now has a zeroed shared page, and the
guest needs to re-accept the page to continue using it (if it knows what
to do with a zeroed page). This would be userspace DOS-ing the guest,
which userspace can do anyway.

On pKVM, rephrasing what you said, even if there is a rogue private to
shared conversion, EL2 still thinks of the page as private. After the
conversion, the page can be faulted in by the host, but any access will
be stopped by EL2.

David, there's no missing piece in the flow!

> When the VMM subsequently issues the KVM_SET_MEMORY_ATTRIBUTES2 ioctl
> with the READABLE policy, we will use the
> kvm_gmem_arch_content_policy_supported() hook in EL1 to validate the
> ioctl. We will cross-reference the requested gfn and nr_pages against
> the pending exit reason stored in kvm_run.
>
> If the VMM attempts an unsolicited conversion (i.e., there is no
> matching exit request in kvm_run, or the addresses do not match), our

Ah I see, so struct kvm_run is not considered "in the hypervisor" since
it is modifiable by host userspace. Would you be using struct
memory_fault in struct kvm_run?

Which vcpu's kvm_run struct would you look up from
kvm_gmem_arch_content_policy_supported()?

For this to land, do you still want the gfn and nr_pages parameters?

Can pKVM just always accept the request, whether the guest requested it
or not? Thinking about it again,
kvm_gmem_arch_content_policy_supported() probably shouldn't be used to
guard solicited vs unsolicited requests anyway (unless you think the
function's name should be changed?)

> current plan is to reject the request and return an error. In the
> future, rather than outright rejecting an unsolicited conversion, we
> might evolve this to treat it as a host-initiated destructive reclaim,
> forcing an unshare and zeroing the memory. For the time being,
> explicit rejection is the simplest and safest path.
>

>> ENCRYPTED means that after the conversion, the memory contents are
>> retained as-is, with no decryption.
>>
>> + TDX and SNP (today) can't support this, so return -EOPNOTSUPP
>> + pKVM and SW_PROTECTED_VM can do nothing, but doing nothing retains
>>   READABLE content, not ENCRYPTED content, hence SW_PROTECTED_VM
>>   should return -EOPNOTSUPP.
>> + Michael, you mentioned during the call that SNP is planning to
>>   introduce a policy that retains the ENCRYPTED version for a special
>>   GHCB call. ENCRYPTED is meant for that use case. Does it work? I'm
>>   assuming that SNP should only support this policy given some
>>   conditions, so would the arch call as described above work?
>> + If this policy is specified on conversion from shared to private,
>>   always return -EOPNOTSUPP.
>> + When this first lands, ENCRYPTED will not be a valid option, but I'm
>>   listing it here so we have line of sight to having this support.
>>
>> READABLE and ENCRYPTED defines the state after conversion clearly
>> (instead of DONT_CARE or similar).
>>
>> DESTROY could be another policy, which means that after the
>> conversion, the memory is unreadable. This is the option to address
>> what David brought up during the call, for cases where userspace knows
>> it is going to free the memory already and doesn't care about the
>> state as long as nobody gets to read it. This will not implemented
>> when feature first lands, but is presented here just to show how this
>> can be extended in future.
>>
>> Right now, I'm thinking that one of the above policies MUST be
>> specified (not specifying a policy will result in -EINVAL).
>>
>> How does this sound?
>
> I don't think that returning -EINVAL is the right thing to do here. If
> userspace omits the policy, the API should default to
> SET_MEMORY_ATTRIBUTES_CONTENT_ZERO and proceed with the conversion. I
> believe that, in Linux APIs in general, omitting an optional behavior
> flag results in the safest, most standard default action.
>

Makes sense, I'll default to zeroing then. Thanks!

> Also, returning -EINVAL when no policy is specified makes the policy
> parameter strictly mandatory. This makes it difficult for userspace's
> to seamlessly request clean-slate, destructive conversions. Software
> zeroing ensures deterministic behavior across pKVM, TDX, and SNP,
> isolating the KVM uAPI from micro-architectural data destruction
> nuances.
>
> Cheers,
> /fuad

^ permalink raw reply

* [syzbot] [trace?] WARNING in tracing_buffers_mmap_close (3)
From: syzbot @ 2026-02-26  4:06 UTC (permalink / raw)
  To: linux-kernel, linux-trace-kernel, mathieu.desnoyers, mhiramat,
	rostedt, syzkaller-bugs

Hello,

syzbot found the following issue on:

HEAD commit:    7dff99b35460 Remove WARN_ALL_UNSEEDED_RANDOM kernel config..
git tree:       upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=14bc2006580000
kernel config:  https://syzkaller.appspot.com/x/.config?x=af6ed0125ed44356
dashboard link: https://syzkaller.appspot.com/bug?extid=3b5dd2030fe08afdf65d
compiler:       gcc (Debian 14.2.0-19) 14.2.0, GNU ld (GNU Binutils for Debian) 2.44
syz repro:      https://syzkaller.appspot.com/x/repro.syz?x=11bc4202580000
C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=107f155a580000

Downloadable assets:
disk image: https://storage.googleapis.com/syzbot-assets/45c7b6686727/disk-7dff99b3.raw.xz
vmlinux: https://storage.googleapis.com/syzbot-assets/36fcc9cd6296/vmlinux-7dff99b3.xz
kernel image: https://storage.googleapis.com/syzbot-assets/fe952fd2745b/bzImage-7dff99b3.xz

IMPORTANT: if you fix the issue, please add the following tag to the commit:
Reported-by: syzbot+3b5dd2030fe08afdf65d@syzkaller.appspotmail.com

------------[ cut here ]------------
ring_buffer_unmap(iter->array_buffer->buffer, iter->cpu_file)
WARNING: kernel/trace/trace.c:8221 at tracing_buffers_mmap_close kernel/trace/trace.c:8221 [inline], CPU#0: syz.0.17/5983
WARNING: kernel/trace/trace.c:8221 at tracing_buffers_mmap_close+0xea/0x140 kernel/trace/trace.c:8216, CPU#0: syz.0.17/5983
Modules linked in:
CPU: 0 UID: 0 PID: 5983 Comm: syz.0.17 Not tainted syzkaller #0 PREEMPT(full) 
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 02/12/2026
RIP: 0010:tracing_buffers_mmap_close kernel/trace/trace.c:8221 [inline]
RIP: 0010:tracing_buffers_mmap_close+0xea/0x140 kernel/trace/trace.c:8216
Code: 08 e8 3a 74 ff ff 31 ff 89 c3 89 c6 e8 2f 50 fb ff 85 db 75 0f e8 76 55 fb ff 48 83 c4 08 5b e9 cc 45 83 09 e8 67 55 fb ff 90 <0f> 0b 90 e8 5e 55 fb ff 48 83 c4 08 5b c3 cc cc cc cc e8 df bd 66
RSP: 0018:ffffc90003ff7ab8 EFLAGS: 00010293
RAX: 0000000000000000 RBX: 00000000ffffffed RCX: ffffffff820ca5c1
RDX: ffff88802a299e40 RSI: ffffffff820ca5d9 RDI: ffff88802a299e40
RBP: ffffffff820ca4f0 R08: 0000000000000005 R09: 0000000000000000
R10: 00000000ffffffed R11: 0000000000000000 R12: ffff88807fc6ecc8
R13: 0000000000000001 R14: 0000000000000005 R15: 0000000000000001
FS:  0000000000000000(0000) GS:ffff888124351000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007fc3f6e17dac CR3: 000000000e598000 CR4: 00000000003526f0
Call Trace:
 <TASK>
 vma_close mm/internal.h:190 [inline]
 remove_vma+0x88/0x160 mm/vma.c:466
 tear_down_vmas+0x2a5/0x600 mm/mmap.c:1264
 exit_mmap+0x469/0xa30 mm/mmap.c:1322
 __mmput+0x12a/0x410 kernel/fork.c:1174
 mmput+0x67/0x80 kernel/fork.c:1197
 exit_mm kernel/exit.c:581 [inline]
 do_exit+0x78a/0x2aa0 kernel/exit.c:959
 do_group_exit+0xd5/0x2a0 kernel/exit.c:1112
 __do_sys_exit_group kernel/exit.c:1123 [inline]
 __se_sys_exit_group kernel/exit.c:1121 [inline]
 __x64_sys_exit_group+0x3e/0x50 kernel/exit.c:1121
 x64_sys_call+0x102c/0x1530 arch/x86/include/generated/asm/syscalls_64.h:232
 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
 do_syscall_64+0x106/0xf80 arch/x86/entry/syscall_64.c:94
 entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7fc3f6b9c629
Code: Unable to access opcode bytes at 0x7fc3f6b9c5ff.
RSP: 002b:00007ffc852ef4c8 EFLAGS: 00000246 ORIG_RAX: 00000000000000e7
RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007fc3f6b9c629
RDX: 0000000000000064 RSI: 0000000000000000 RDI: 0000000000000000
RBP: 0000000000000003 R08: 0000000000000000 R09: 00007fc3f6de53e0
R10: 0000000000000001 R11: 0000000000000246 R12: 0000000000000000
R13: 00007fc3f6de53e0 R14: 0000000000000003 R15: 00007ffc852ef580
 </TASK>


---
This report is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzkaller@googlegroups.com.

syzbot will keep track of this issue. See:
https://goo.gl/tpsmEJ#status for how to communicate with syzbot.

If the report is already addressed, let syzbot know by replying with:
#syz fix: exact-commit-title

If you want syzbot to run the reproducer, reply with:
#syz test: git://repo/address.git branch-or-commit-hash
If you attach or paste a git patch, syzbot will apply it before testing.

If you want to overwrite report's subsystems, reply with:
#syz set subsystems: new-subsystem
(See the list of subsystem names on the web dashboard)

If the report is a duplicate of another one, reply with:
#syz dup: exact-subject-of-another-report

If you want to undo deduplication, reply with:
#syz undup

^ permalink raw reply

* Re: [LSF/MM/BPF TOPIC][RFC PATCH v4 00/27] Private Memory Nodes (w/ Compressed RAM)
From: Alistair Popple @ 2026-02-26  3:27 UTC (permalink / raw)
  To: Gregory Price
  Cc: lsf-pc, linux-kernel, linux-cxl, cgroups, linux-mm,
	linux-trace-kernel, damon, kernel-team, gregkh, rafael, dakr,
	dave, jonathan.cameron, dave.jiang, alison.schofield,
	vishal.l.verma, ira.weiny, dan.j.williams, longman, akpm, david,
	lorenzo.stoakes, Liam.Howlett, vbabka, rppt, surenb, mhocko,
	osalvador, ziy, matthew.brost, joshua.hahnjy, rakie.kim,
	byungchul, ying.huang, axelrasmussen, yuanchu, weixugc,
	yury.norov, linux, mhiramat, mathieu.desnoyers, tj, hannes,
	mkoutny, jackmanb, sj, baolin.wang, npache, ryan.roberts,
	dev.jain, baohua, lance.yang, muchun.song, xu.xin16,
	chengming.zhou, jannh, linmiaohe, nao.horiguchi, pfalcato,
	rientjes, shakeel.butt, riel, harry.yoo, cl, roman.gushchin,
	chrisl, kasong, shikemeng, nphamcs, bhe, zhengqi.arch,
	terry.bowman
In-Reply-To: <aZ3BEn_73Rk8Fn7L@gourry-fedora-PF4VCD3F>

On 2026-02-25 at 02:17 +1100, Gregory Price <gourry@gourry.net> wrote...
> On Tue, Feb 24, 2026 at 05:19:11PM +1100, Alistair Popple wrote:
> > On 2026-02-22 at 19:48 +1100, Gregory Price <gourry@gourry.net> wrote...
> > 
> > Based on our discussion at LPC I believe one of the primary motivators here was
> > to re-use the existing mm buddy allocator rather than writing your own. I remain
> > to be convinced that alone is justification enough for doing all this - DRM for
> > example already has quite a nice standalone buddy allocator (drm_buddy.c) that
> > could presumably be used, or adapted for use, by any device driver.
> >
> > The interesting part of this series (which I have skimmed but not read in
> > detail) is how device memory gets exposed to userspace - this is something that
> > existing ZONE_DEVICE implementations don't address, instead leaving it up to
> > drivers and associated userspace stacks to deal with allocation, migration, etc.
> > 
> 
> I agree that buddy-access alone is insufficient justification, it
> started off that way - but if you want mempolicy/NUMA UAPI access,
> it turns into "Re-use all of MM" - and that means using the buddy.
> 
> I also expected ZONE_DEVICE vs NODE_DATA to be the primary discussion,
> 
> I raise replacing it as a thought experiment, but not the proposal.
> 
> The idea that drm/ is going to switch to private nodes is outside the
> realm of reality, but part of that is because of years of infrastructure
> built on the assumption that re-using mm/ is infeasible.
> 
> But, lets talk about DEVICE_COHERENT
> 
> ---
> 
> DEVICE_COHERENT is the odd-man out among ZONE_DEVICE modes. The others
> use softleaf entries and don't allow direct mappings.

I think you have this around the wrong way - DEVICE_PRIVATE is the odd one out as
it is the one ZONE_DEVICE page type that uses softleaf entries and doesn't
allow direct mappings. Every other type of ZONE_DEVICE page allows for direct
mappings.

> (DEVICE_PRIVATE sort of does if you squint, but you can also view that
>  a bit like PROT_NONE or read-only controls to force migrations).
> 
> If you take DEVICE_COHERENT and:
> 
> - Move pgmap out of the struct page (page_ext, NODE_DATA, etc) to free
>   the LRU list_head
> - Put pages in the buddy (free lists, watermarks, managed_pages) or add
>   pgmap->device_alloc() at every allocation callsite / buddy hook
> - Add LRU support (aging, reclaim, compaction)
> - Add isolated gating (new GFP flag and adjusted zonelist filtering)
> - Add new dev_pagemap_ops callbacks for the various mm/ features
> - Audit evey folio_is_zone_device() to distinguish zone device modes
> 
> ... you've built N_MEMORY_PRIVATE inside ZONE_DEVICE. Except now
> page_zone(page) returns ZONE_DEVICE - so you inherit the wrong
> defaults at every existing ZONE_DEVICE check. 
> 
> Skip-sites become things to opt-out of instead of opting into.
> 
> You just end up with
> 
> if (folio_is_zone_device(folio))
>     if (folio_is_my_special_zone_device())
>     else ....
> 
> and this just generalizes to
> 
> if (folio_is_private_managed(folio))
>     folio_managed_my_hooked_operation()

I don't quite get this - couldn't you just as easily do:

if (folio_is_zone_device(folio))
     folio_device_my_hooked_operation()

Where folio_device_my_hooked_operation() is just:

if (pgmap->ops->my_hoooked_operation)
	pgmap->ops->my_hooked_operation();

> So you get the same code, but have added more complexity to ZONE_DEVICE.

Don't you still have to add code to hook every operation you care about for your
private managed nodes?

> I don't think that's needed if we just recognize ZONE is the wrong
> abstraction to be operating on.
> 
> Honestly, even ZONE_MOVABLE becomes pointless with N_MEMORY_PRIVATE
> if you disallow longterm pinning - because the managing service handles
> allocations (it has to inject GFP_PRIVATE to get access) or selectively
> enables the mm/ services it knows are safe (mempolicy).
> 
> Even if you allow longterm pinning, if your service controls what does
> the pinning it can still be reclaimable - just manually (killing
> processes) instead of letting hotplug do it via migration.
> 
> If your service only allocates movable pages - your ZONE_NORMAL is
> effectively ZONE_MOVABLE.  

This is interesting - it sounds like the conclusion of this is ZONE_* is just a
bad abstraction and should be replaced with something else maybe some like this?

And FWIW I'm not tied to the ZONE_DEVICE as being a good abstraction, it's just
what we seem to have today for determing page types. It almost sounds like what
we want is just a bunch of hooks that can be associated with a range of pages,
and then you just get rid of ZONE_DEVICE and instead install hooks appropriate
for each page a driver manages. I have to think more about that though, this
is just what popped into my head when you start saying ZONE_MOVABLE could also
disappear :-)

> In some cases we use ZONE_MOVABLE to prevent the kernel from allocating
> memory onto devices (like CXL).  This means struct page is forced to
> take up DRAM or use memmap_on_memory - meaning you lose high-value
> capacity or sacrifice contiguity (less huge page support).

One of the other reasons is to prevent long term pinning. But I think that's a
conversation that warrants a whole separate thread.

> This entire problem can evaporate if you can just use ZONE_NORMAL.
> 
> There are a lot of benefits to just re-using the buddy like this.
> 
> Zones are the wrong abstraction and cause more problems.
> 
> > >   free_folio           - mirrors ZONE_DEVICE's
> > >   folio_split          - mirrors ZONE_DEVICE's
> > >   migrate_to           - ... same as ZONE_DEVICE
> > >   handle_fault         - mirrors the ZONE_DEVICE ...
> > >   memory_failure       - parallels memory_failure_dev_pagemap(),
> > 
> > One does not have to squint too hard to see that the above is not so different
> > from what ZONE_DEVICE provides today via dev_pagemap_ops(). So I think I think
> > it would be worth outlining why the existing ZONE_DEVICE mechanism can't be
> > extended to provide these kind of services.
> > 
> > This seems to add a bunch of code just to use NODE_DATA instead of page->pgmap,
> > without really explaining why just extending dev_pagemap_ops wouldn't work. The
> > obvious reason is that if you want to support things like reclaim, compaction,
> > etc. these pages need to be on the LRU, which is a little bit hard when that
> > field is also used by the pgmap pointer for ZONE_DEVICE pages.
> > 
> 
> You don't have to squint because it was deliberate :]

Nice.

> The callback similarity is the feature - they're the same logical
> operations.  The difference is the direction of the defaults.
> 
> Extending ZONE_DEVICE into these areas requires the same set of hooks,
> plus distinguishing "old ZONE_DEVICE" from "new ZONE_DEVICE".
> 
> Where there are new injection sites, it's because ZONE_DEVICE opts
> out of ever touching that code in some other silently implied way.

Yeah, I hate that aspect of ZONE_DEVICE. There are far too many places where we
"prove" you can't have a ZONE_DEVICE page because of ad-hoc "reasons". Usually
they take the form of it's not on the LRU, or it's not an anonymous page and
this isn't DAX, etc.

> For example, reclaim/compaction doesn't run because ZONE_DEVICE doesn't
> add to managed_pages (among other reasons).

And people can't even agree on the reasons. I would argue the primary reason is
reclaim/compaction doesn't run because it can't even find the pages due to them
not being on the LRU. But everyone is equally correct.

> You'd have to go figure out how to hack those things into ZONE_DEVICE 
> *and then* opt every *other* ZONE_DEVICE mode *back out*.
> 
> So you still end up with something like this anyway:
> 
> static inline bool folio_managed_handle_fault(struct folio *folio,
>                                               struct vm_fault *vmf,
>                                               enum pgtable_level level,
>                                               vm_fault_t *ret)
> {
>         /* Zone device pages use swap entries; handled in do_swap_page */
>         if (folio_is_zone_device(folio))
>                 return false;
> 
>         if (folio_is_private_node(folio))
> 		...
>         return false;
> }
> 
> 
> > example page_ext could be used.  Or I hear struct page may go away in place of
> > folios any day now, so maybe that gives us space for both :-)
> > 
> 
> If NUMA is the interface we want, then NODE_DATA is the right direction
> regardless of struct page's future or what zone it lives in.
> 
> There's no reason to keep per-page pgmap w/ device-to-node mappings.

In reality I suspect that's already the case today. I'm not sure we need
per-page pgmap.

> You can have one driver manage multiple devices with the same numa node
> if it uses the same owner context (PFN already differentiates devices).
> 
> The existing code allows for this.
> 
> > The above also looks pretty similar to the existing ZONE_DEVICE methods for
> > doing this which is another reason to argue for just building up the feature set
> > of the existing boondoggle rather than adding another thingymebob.
> >
> > It seems the key thing we are looking for is:
> > 
> > 1) A userspace API to allocate/manage device memory (ie. move_pages(), mbind(),
> > etc.)
> > 
> > 2) Allowing reclaim/LRU list processing of device memory.
> > 
> > From my perspective both of these are interesting and I look forward to the
> > discussion (hopefully I can make it to LSFMM). Mostly I'm interested in the
> > implementation as this does on the surface seem to sprinkle around and duplicate
> > a lot of hooks similar to what ZONE_DEVICE already provides.
> > 
> 
> On (1): ZONE_DEVICE NUMA UAPI is harder than it looks from the surface

Ok, I will admit I've only been hovering on the surface so need to give this
some more thought. Everything you've written below makes sense and is definitely
food for thought. Thanks.

 - Alistair

> Much of the kernel mm/ infrastructure is written on top of the buddy and
> expects N_MEMORY to be the sole arbiter of "Where to Acquire Pages".
> 
> Mempolicy depends on:
>    - Buddy support or a new alloc hook around the buddy
> 
>    - Migration support (mbind() after allocation migrates)
>      - Migration also deeply assumes buddy and LRU support
> 
>    - Changing validations on node states
>      - mempolicy checks N_MEMORY membership, so you have to hack
>        N_MEMORY onto ZONE_DEVICE
>        (or teach it about a new node state... N_MEMORY_PRIVATE)
> 
> 
> Getting mempolicy to work with N_MEMORY_PRIVATE amounts to adding 2
> lines of code in vma_alloc_folio_noprof:
> 
> struct folio *vma_alloc_folio_noprof(gfp_t gfp, int order,
>                                      struct vm_area_struct *vma,
> 				     unsigned long addr)
> {
>         if (pol->flags & MPOL_F_PRIVATE)
>                 gfp |= __GFP_PRIVATE;
> 
>         folio = folio_alloc_mpol_noprof(gfp, order, pol, ilx, numa_node_id());
> 	/* Woo! I faulted a DEVICE PAGE! */
> }
> 
> But this requires the pages to be managed by the buddy.
> 
> The rest of the mempolicy support is around keeping sane nodemasks when
> things like cpuset.mems rebinds occur and validating you don't end up
> with private nodes that don't support mempolicy in your nodemask.
> 
> You have to do all of this anyway, but with the added bonus of fighting
> with the overloaded nature of ZONE_DEVICE at every step.
> 
> ==========
> 
> On (2): Assume you solve LRU. 
> 
> Zone Device has no free lists, managed_pages, or watermarks.
> 
> kswapd can't run, compaction has no targets, vmscan's pressure model
> doesn't function.  These all come for free when the pages are
> buddy-managed on a real zone.  Why re-invent the wheel?
> 
> ==========
> 
> So you really have two options here:
> 
> a) Put pages in the buddy, or
> 
> b) Add pgmap->device_alloc() callbacks at every allocation site that
>    could target a node:
>      - vma_alloc_folio
>      - alloc_migration_target
>      - alloc_demote_folio
>      - alloc_pages_node
>      - alloc_contig_pages
>      - list goes on
> 
> Or more likely - hooking get_page_from_freelist.  Which at that
> point... just use the buddy?  You're already deep in the hot path.
> 
> > 
> > For basic allocation I agree this is the case. But there's no reason some device
> > allocator library couldn't be written. Or in fact as pointed out above reuse the
> > already existing one in drm_buddy.c.  So would be interested to hear arguments
> > for why allocation has to be done by the mm allocator and/or why an allocation
> > library wouldn't work here given DRM already has them.
> > 
> 
> Using the buddy underpins the rest of mm/ services we want to re-use.
> 
> That's basically it.  Otherwise you have to inject hooks into every
> surface that touches the buddy...
> 
> ... or in the buddy (get_page_from_freelist), at which point why not
> just use the buddy?
> 
> ~Gregory

^ permalink raw reply

* [PATCH mm-unstable v15 13/13] Documentation: mm: update the admin guide for mTHP collapse
From: Nico Pache @ 2026-02-26  3:27 UTC (permalink / raw)
  To: linux-doc, linux-kernel, linux-mm, linux-trace-kernel
  Cc: aarcange, akpm, anshuman.khandual, apopple, baohua, baolin.wang,
	byungchul, catalin.marinas, cl, corbet, dave.hansen, david,
	dev.jain, gourry, hannes, hughd, jack, jackmanb, jannh, jglisse,
	joshua.hahnjy, kas, lance.yang, Liam.Howlett, lorenzo.stoakes,
	mathieu.desnoyers, matthew.brost, mhiramat, mhocko, npache,
	peterx, pfalcato, rakie.kim, raquini, rdunlap, richard.weiyang,
	rientjes, rostedt, rppt, ryan.roberts, shivankg, sunnanyong,
	surenb, thomas.hellstrom, tiwai, usamaarif642, vbabka,
	vishal.moola, wangkefeng.wang, will, willy, yang, ying.huang, ziy,
	zokeefe, Bagas Sanjaya
In-Reply-To: <20260226031741.230674-1-npache@redhat.com>

Now that we can collapse to mTHPs lets update the admin guide to
reflect these changes and provide proper guidance on how to utilize it.

Reviewed-by: Bagas Sanjaya <bagasdotme@gmail.com>
Signed-off-by: Nico Pache <npache@redhat.com>
---
 Documentation/admin-guide/mm/transhuge.rst | 48 +++++++++++++---------
 1 file changed, 28 insertions(+), 20 deletions(-)

diff --git a/Documentation/admin-guide/mm/transhuge.rst b/Documentation/admin-guide/mm/transhuge.rst
index eebb1f6bbc6c..67836c683e8d 100644
--- a/Documentation/admin-guide/mm/transhuge.rst
+++ b/Documentation/admin-guide/mm/transhuge.rst
@@ -63,7 +63,8 @@ often.
 THP can be enabled system wide or restricted to certain tasks or even
 memory ranges inside task's address space. Unless THP is completely
 disabled, there is ``khugepaged`` daemon that scans memory and
-collapses sequences of basic pages into PMD-sized huge pages.
+collapses sequences of basic pages into huge pages of either PMD size
+or mTHP sizes, if the system is configured to do so.
 
 The THP behaviour is controlled via :ref:`sysfs <thp_sysfs>`
 interface and using madvise(2) and prctl(2) system calls.
@@ -219,10 +220,10 @@ this behaviour by writing 0 to shrink_underused, and enable it by writing
 	echo 0 > /sys/kernel/mm/transparent_hugepage/shrink_underused
 	echo 1 > /sys/kernel/mm/transparent_hugepage/shrink_underused
 
-khugepaged will be automatically started when PMD-sized THP is enabled
+khugepaged will be automatically started when any THP size is enabled
 (either of the per-size anon control or the top-level control are set
 to "always" or "madvise"), and it'll be automatically shutdown when
-PMD-sized THP is disabled (when both the per-size anon control and the
+all THP sizes are disabled (when both the per-size anon control and the
 top-level control are "never")
 
 process THP controls
@@ -264,11 +265,6 @@ support the following arguments::
 Khugepaged controls
 -------------------
 
-.. note::
-   khugepaged currently only searches for opportunities to collapse to
-   PMD-sized THP and no attempt is made to collapse to other THP
-   sizes.
-
 khugepaged runs usually at low frequency so while one may not want to
 invoke defrag algorithms synchronously during the page faults, it
 should be worth invoking defrag at least in khugepaged. However it's
@@ -296,11 +292,11 @@ allocation failure to throttle the next allocation attempt::
 The khugepaged progress can be seen in the number of pages collapsed (note
 that this counter may not be an exact count of the number of pages
 collapsed, since "collapsed" could mean multiple things: (1) A PTE mapping
-being replaced by a PMD mapping, or (2) All 4K physical pages replaced by
-one 2M hugepage. Each may happen independently, or together, depending on
-the type of memory and the failures that occur. As such, this value should
-be interpreted roughly as a sign of progress, and counters in /proc/vmstat
-consulted for more accurate accounting)::
+being replaced by a PMD mapping, or (2) physical pages replaced by one
+hugepage of various sizes (PMD-sized or mTHP). Each may happen independently,
+or together, depending on the type of memory and the failures that occur.
+As such, this value should be interpreted roughly as a sign of progress,
+and counters in /proc/vmstat consulted for more accurate accounting)::
 
 	/sys/kernel/mm/transparent_hugepage/khugepaged/pages_collapsed
 
@@ -308,16 +304,19 @@ for each pass::
 
 	/sys/kernel/mm/transparent_hugepage/khugepaged/full_scans
 
-``max_ptes_none`` specifies how many extra small pages (that are
-not already mapped) can be allocated when collapsing a group
-of small pages into one large page::
+``max_ptes_none`` specifies how many empty (none/zero) pages are allowed
+when collapsing a group of small pages into one large page::
 
 	/sys/kernel/mm/transparent_hugepage/khugepaged/max_ptes_none
 
-A higher value leads to use additional memory for programs.
-A lower value leads to gain less thp performance. Value of
-max_ptes_none can waste cpu time very little, you can
-ignore it.
+For PMD-sized THP collapse, this directly limits the number of empty pages
+allowed in the 2MB region. For mTHP collapse, only 0 or (HPAGE_PMD_NR - 1)
+are supported. Any other value will emit a warning and no mTHP collapse
+will be attempted.
+
+A higher value allows more empty pages, potentially leading to more memory
+usage but better THP performance. A lower value is more conservative and
+may result in fewer THP collapses.
 
 ``max_ptes_swap`` specifies how many pages can be brought in from
 swap when collapsing a group of pages into a transparent huge page::
@@ -337,6 +336,15 @@ that THP is shared. Exceeding the number would block the collapse::
 
 A higher value may increase memory footprint for some workloads.
 
+.. note::
+   For mTHP collapse, khugepaged does not support collapsing regions that
+   contain shared or swapped out pages, as this could lead to continuous
+   promotion to higher orders. The collapse will fail if any shared or
+   swapped PTEs are encountered during the scan.
+
+   Currently, madvise_collapse only supports collapsing to PMD-sized THPs
+   and does not attempt mTHP collapses.
+
 Boot parameters
 ===============
 
-- 
2.53.0


^ 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