Linux Trace Kernel
 help / color / mirror / Atom feed
* [PATCH bpf-next 0/2] uprobes: Switch uretprobes_srcu to SRCU-fast-updown
From: Puranjay Mohan @ 2026-07-06 17:27 UTC (permalink / raw)
  To: Lai Jiangshan, Paul E. McKenney, Josh Triplett, Masami Hiramatsu,
	Oleg Nesterov, Peter Zijlstra, Ingo Molnar,
	Arnaldo Carvalho de Melo, Namhyung Kim, Alexei Starovoitov,
	Andrii Nakryiko
  Cc: Puranjay Mohan, Steven Rostedt, Mathieu Desnoyers, Mark Rutland,
	Alexander Shishkin, Jiri Olsa, Ian Rogers, Adrian Hunter,
	James Clark, rcu, linux-kernel, linux-trace-kernel,
	linux-perf-users, bpf

uretprobes_srcu currently uses normal SRCU. Normal SRCU issues an
smp_mb() on both srcu_read_lock() and srcu_read_unlock(), i.e. two full
memory barriers per read-side critical section. For uretprobes this cost
is paid on every uretprobe invocation: prepare_uretprobe() takes the
read lock that is later dropped on the normal return path
(hprobe_finalize()) or from ri_timer()/dup_utask() (hprobe_expire()).

Switch uretprobes_srcu to the SRCU-fast-updown flavor. SRCU-fast moves
the read-side ordering off the reader and onto the (rare) grace-period
side: synchronize_srcu() rides on synchronize_rcu() instead of relying
on reader-side smp_mb(). This is a good trade for uretprobes, where
reader-side hits vastly outnumber grace periods (uprobe unregistration).

The updown variant (rather than plain SRCU-fast) is required because the
read lock is acquired in prepare_uretprobe() on the way out to user
space and is released only once the return instance is finalized -- from
a different context than it was taken: the normal return path
(uprobe_handle_trampoline() -> hprobe_finalize()), the timer callback,
or the fork path (ri_timer()/dup_utask() -> hprobe_expire()).
srcu_down_read_fast()/srcu_up_read_fast() are designed for this
semaphore-like, cross-context pattern and, unlike the same-context
srcu_read_lock_fast() variant, do not carry lockdep read-side tracking
that would warn on it -- which is why the old code had to use the raw
__srcu_read_lock() here. For the short, same-context sections in
ri_timer() and dup_utask(), guard(srcu_fast_updown) is used instead,
giving proper lockdep coverage.

Patch 1 adds the guard(srcu_fast_updown) definition, following the
existing guard(srcu)/guard(srcu_fast) pattern.
Patch 2 does the uretprobes_srcu conversion.

Note
----
Only uretprobes_srcu is converted; the main uprobe readers (RB-tree
lookup and consumer-list iteration) are deliberately left on RCU Tasks
Trace. RCU Tasks Trace is already implemented on top of
srcu_read_lock_fast(), so the reader-side cost is identical, and it has
a nesting fast path that the uprobe -> sleepable-BPF-program call chain
relies on (the BPF trampoline takes rcu_read_lock_trace() while uprobes
already holds it; the nested acquire is just a counter bump). Converting
those readers to a separate srcu_struct would turn one real + one nested
lock into two real locks and lose that optimization for no reader-side
gain. uretprobes_srcu is different: it uses normal SRCU (not Tasks
Trace), its readers are long-lived and cross-context, and it genuinely
benefits from dropping the per-reader barriers.

Puranjay Mohan (2):
  srcu: Add lock guard for srcu_fast_updown flavor
  uprobes: Switch uretprobes_srcu to SRCU-fast-updown

 include/linux/srcu.h    |  7 +++++++
 include/linux/uprobes.h |  5 +++--
 kernel/events/uprobes.c | 29 +++++++++++++++++------------
 3 files changed, 27 insertions(+), 14 deletions(-)


base-commit: 87bfe634b1193db90e5170e1ddbad04a63ef4501
-- 
2.53.0-Meta


^ permalink raw reply

* [PATCH bpf-next 1/2] srcu: Add lock guard for srcu_fast_updown flavor
From: Puranjay Mohan @ 2026-07-06 17:27 UTC (permalink / raw)
  To: Lai Jiangshan, Paul E. McKenney, Josh Triplett, Masami Hiramatsu,
	Oleg Nesterov, Peter Zijlstra, Ingo Molnar,
	Arnaldo Carvalho de Melo, Namhyung Kim, Alexei Starovoitov,
	Andrii Nakryiko
  Cc: Puranjay Mohan, Steven Rostedt, Mathieu Desnoyers, Mark Rutland,
	Alexander Shishkin, Jiri Olsa, Ian Rogers, Adrian Hunter,
	James Clark, rcu, linux-kernel, linux-trace-kernel,
	linux-perf-users, bpf
In-Reply-To: <20260706172744.3920417-1-puranjay@kernel.org>

Add a guard(srcu_fast_updown) definition for scoped
SRCU-fast-updown read-side critical sections, following the
existing pattern of guard(srcu) and guard(srcu_fast).

Signed-off-by: Puranjay Mohan <puranjay@kernel.org>
---
 include/linux/srcu.h | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/include/linux/srcu.h b/include/linux/srcu.h
index a54ce9e808b92..72c86d3b23f2e 100644
--- a/include/linux/srcu.h
+++ b/include/linux/srcu.h
@@ -638,4 +638,11 @@ DEFINE_LOCK_GUARD_1(srcu_fast_notrace, struct srcu_struct,
 DECLARE_LOCK_GUARD_1_ATTRS(srcu_fast_notrace, __acquires_shared(_T), __releases_shared(*(struct srcu_struct **)_T))
 #define class_srcu_fast_notrace_constructor(_T) WITH_LOCK_GUARD_1_ATTRS(srcu_fast_notrace, _T)
 
+DEFINE_LOCK_GUARD_1(srcu_fast_updown, struct srcu_struct,
+		    _T->scp = srcu_read_lock_fast_updown(_T->lock),
+		    srcu_read_unlock_fast_updown(_T->lock, _T->scp),
+		    struct srcu_ctr __percpu *scp)
+DECLARE_LOCK_GUARD_1_ATTRS(srcu_fast_updown, __acquires_shared(_T), __releases_shared(*(struct srcu_struct **)_T))
+#define class_srcu_fast_updown_constructor(_T) WITH_LOCK_GUARD_1_ATTRS(srcu_fast_updown, _T)
+
 #endif
-- 
2.53.0-Meta


^ permalink raw reply related

* [PATCH bpf-next 2/2] uprobes: Switch uretprobes_srcu to SRCU-fast-updown
From: Puranjay Mohan @ 2026-07-06 17:27 UTC (permalink / raw)
  To: Lai Jiangshan, Paul E. McKenney, Josh Triplett, Masami Hiramatsu,
	Oleg Nesterov, Peter Zijlstra, Ingo Molnar,
	Arnaldo Carvalho de Melo, Namhyung Kim, Alexei Starovoitov,
	Andrii Nakryiko
  Cc: Puranjay Mohan, Steven Rostedt, Mathieu Desnoyers, Mark Rutland,
	Alexander Shishkin, Jiri Olsa, Ian Rogers, Adrian Hunter,
	James Clark, rcu, linux-kernel, linux-trace-kernel,
	linux-perf-users, bpf
In-Reply-To: <20260706172744.3920417-1-puranjay@kernel.org>

uretprobes_srcu currently uses normal SRCU, which issues
two smp_mb() per read lock/unlock pair. This overhead is
paid on every uretprobe hit.

Switch to SRCU-fast-updown, which eliminates the per-reader
memory barriers by moving the ordering cost to the
grace-period side (synchronize_rcu() instead of smp_mb()).
This is acceptable because grace periods (uprobe
unregistration) are infrequent compared to reader-side
uretprobe hits.

The updown flavor is required because the SRCU read lock is
taken in prepare_uretprobe() when a return instance is
created and is held until that return instance is finalized.
The traced thread returns to user space in between, so the
lock is inherently released in a different context from
where it was acquired: on the normal return path via
uprobe_handle_trampoline() -> hprobe_finalize(), or from
ri_timer() (expiry) or dup_utask() (fork) via
hprobe_expire(). srcu_down_read_fast() / srcu_up_read_fast()
are designed for this acquire-here / release-elsewhere
pattern and, unlike the same-context srcu_read_lock_fast()
variant, do not carry the lockdep read-side tracking that
would warn on it.

The short, same-context SRCU sections in ri_timer() and
dup_utask() (which guard the uprobe against reuse across the
hprobe_expire() cmpxchg) instead use guard(srcu_fast_updown)
for proper lockdep coverage.

Signed-off-by: Puranjay Mohan <puranjay@kernel.org>
---
 include/linux/uprobes.h |  5 +++--
 kernel/events/uprobes.c | 29 +++++++++++++++++------------
 2 files changed, 20 insertions(+), 14 deletions(-)

diff --git a/include/linux/uprobes.h b/include/linux/uprobes.h
index f548fea2adec8..f3b07753c2f3d 100644
--- a/include/linux/uprobes.h
+++ b/include/linux/uprobes.h
@@ -25,6 +25,7 @@ struct mm_struct;
 struct inode;
 struct notifier_block;
 struct page;
+struct srcu_ctr;
 
 /*
  * Allowed return values from uprobe consumer's handler callback
@@ -106,7 +107,7 @@ enum hprobe_state {
  *     underlying uprobe is not guaranteed anymore. __UPROBE_DEAD is just an
  *     internal marker and is handled transparently by hprobe_fetch() helper.
  *
- * When uprobe is SRCU-protected, we also record srcu_idx value, necessary for
+ * When uprobe is SRCU-protected, we also record srcu_scp value, necessary for
  * SRCU unlocking.
  *
  * See hprobe_expire() and hprobe_fetch() for details of race-free uprobe
@@ -115,7 +116,7 @@ enum hprobe_state {
  */
 struct hprobe {
 	enum hprobe_state state;
-	int srcu_idx;
+	struct srcu_ctr __percpu *srcu_scp;
 	struct uprobe *uprobe;
 };
 
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index 4084e926e2844..afa491b0bd3f9 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -54,7 +54,7 @@ static struct mutex uprobes_mmap_mutex[UPROBES_HASH_SZ];
 DEFINE_STATIC_PERCPU_RWSEM(dup_mmap_sem);
 
 /* Covers return_instance's uprobe lifetime. */
-DEFINE_STATIC_SRCU(uretprobes_srcu);
+DEFINE_STATIC_SRCU_FAST_UPDOWN(uretprobes_srcu);
 
 /* Have a copy of original instruction */
 #define UPROBE_COPY_INSN	0
@@ -707,12 +707,13 @@ static void put_uprobe(struct uprobe *uprobe)
 }
 
 /* Initialize hprobe as SRCU-protected "leased" uprobe */
-static void hprobe_init_leased(struct hprobe *hprobe, struct uprobe *uprobe, int srcu_idx)
+static void hprobe_init_leased(struct hprobe *hprobe, struct uprobe *uprobe,
+			       struct srcu_ctr __percpu *srcu_scp)
 {
 	WARN_ON(!uprobe);
 	hprobe->state = HPROBE_LEASED;
 	hprobe->uprobe = uprobe;
-	hprobe->srcu_idx = srcu_idx;
+	hprobe->srcu_scp = srcu_scp;
 }
 
 /* Initialize hprobe as refcounted ("stable") uprobe (uprobe can be NULL). */
@@ -720,7 +721,7 @@ static void hprobe_init_stable(struct hprobe *hprobe, struct uprobe *uprobe)
 {
 	hprobe->state = uprobe ? HPROBE_STABLE : HPROBE_GONE;
 	hprobe->uprobe = uprobe;
-	hprobe->srcu_idx = -1;
+	hprobe->srcu_scp = NULL;
 }
 
 /*
@@ -757,7 +758,7 @@ static void hprobe_finalize(struct hprobe *hprobe, enum hprobe_state hstate)
 {
 	switch (hstate) {
 	case HPROBE_LEASED:
-		__srcu_read_unlock(&uretprobes_srcu, hprobe->srcu_idx);
+		srcu_up_read_fast(&uretprobes_srcu, hprobe->srcu_scp);
 		break;
 	case HPROBE_STABLE:
 		put_uprobe(hprobe->uprobe);
@@ -829,7 +830,7 @@ static struct uprobe *hprobe_expire(struct hprobe *hprobe, bool get)
 		 */
 		if (try_cmpxchg(&hprobe->state, &hstate, uprobe ? HPROBE_STABLE : HPROBE_GONE)) {
 			/* We won the race, we are the ones to unlock SRCU */
-			__srcu_read_unlock(&uretprobes_srcu, hprobe->srcu_idx);
+			srcu_up_read_fast(&uretprobes_srcu, hprobe->srcu_scp);
 			return get ? get_uprobe(uprobe) : uprobe;
 		}
 
@@ -2045,7 +2046,7 @@ static void ri_timer(struct timer_list *timer)
 	struct return_instance *ri;
 
 	/* SRCU protects uprobe from reuse for the cmpxchg() inside hprobe_expire(). */
-	guard(srcu)(&uretprobes_srcu);
+	guard(srcu_fast_updown)(&uretprobes_srcu);
 	/* RCU protects return_instance from freeing. */
 	guard(rcu)();
 
@@ -2142,7 +2143,7 @@ static int dup_utask(struct task_struct *t, struct uprobe_task *o_utask)
 	t->utask = n_utask;
 
 	/* protect uprobes from freeing, we'll need try_get_uprobe() them */
-	guard(srcu)(&uretprobes_srcu);
+	guard(srcu_fast_updown)(&uretprobes_srcu);
 
 	p = &n_utask->return_instances;
 	for (o = o_utask->return_instances; o; o = o->next) {
@@ -2254,8 +2255,8 @@ static void prepare_uretprobe(struct uprobe *uprobe, struct pt_regs *regs,
 {
 	struct uprobe_task *utask = current->utask;
 	unsigned long orig_ret_vaddr, trampoline_vaddr;
+	struct srcu_ctr __percpu *srcu_scp;
 	bool chained;
-	int srcu_idx;
 
 	if (!get_xol_area())
 		goto free;
@@ -2293,8 +2294,12 @@ static void prepare_uretprobe(struct uprobe *uprobe, struct pt_regs *regs,
 		orig_ret_vaddr = utask->return_instances->orig_ret_vaddr;
 	}
 
-	/* __srcu_read_lock() because SRCU lock survives switch to user space */
-	srcu_idx = __srcu_read_lock(&uretprobes_srcu);
+	/*
+	 * Use srcu_down_read_fast() because the SRCU lock survives a switch to
+	 * user space and can be unlocked from a different context by ri_timer()
+	 * or dup_utask().
+	 */
+	srcu_scp = srcu_down_read_fast(&uretprobes_srcu);
 
 	ri->func = instruction_pointer(regs);
 	ri->stack = user_stack_pointer(regs);
@@ -2303,7 +2308,7 @@ static void prepare_uretprobe(struct uprobe *uprobe, struct pt_regs *regs,
 
 	utask->depth++;
 
-	hprobe_init_leased(&ri->hprobe, uprobe, srcu_idx);
+	hprobe_init_leased(&ri->hprobe, uprobe, srcu_scp);
 	ri->next = utask->return_instances;
 	rcu_assign_pointer(utask->return_instances, ri);
 
-- 
2.53.0-Meta


^ permalink raw reply related

* Re: [PATCH bpf-next 1/2] srcu: Add lock guard for srcu_fast_updown flavor
From: Paul E. McKenney @ 2026-07-06 17:36 UTC (permalink / raw)
  To: Puranjay Mohan
  Cc: Lai Jiangshan, Josh Triplett, Masami Hiramatsu, Oleg Nesterov,
	Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Namhyung Kim, Alexei Starovoitov, Andrii Nakryiko, Steven Rostedt,
	Mathieu Desnoyers, Mark Rutland, Alexander Shishkin, Jiri Olsa,
	Ian Rogers, Adrian Hunter, James Clark, rcu, linux-kernel,
	linux-trace-kernel, linux-perf-users, bpf
In-Reply-To: <20260706172744.3920417-2-puranjay@kernel.org>

On Mon, Jul 06, 2026 at 10:27:41AM -0700, Puranjay Mohan wrote:
> Add a guard(srcu_fast_updown) definition for scoped
> SRCU-fast-updown read-side critical sections, following the
> existing pattern of guard(srcu) and guard(srcu_fast).
> 
> Signed-off-by: Puranjay Mohan <puranjay@kernel.org>

Reviewed-by: Paul E. McKenney <paulmck@kernel.org>

(Or I can take it if you would prefer, but it might be easier and faster
for you to send it along with the next patch.)

> ---
>  include/linux/srcu.h | 7 +++++++
>  1 file changed, 7 insertions(+)
> 
> diff --git a/include/linux/srcu.h b/include/linux/srcu.h
> index a54ce9e808b92..72c86d3b23f2e 100644
> --- a/include/linux/srcu.h
> +++ b/include/linux/srcu.h
> @@ -638,4 +638,11 @@ DEFINE_LOCK_GUARD_1(srcu_fast_notrace, struct srcu_struct,
>  DECLARE_LOCK_GUARD_1_ATTRS(srcu_fast_notrace, __acquires_shared(_T), __releases_shared(*(struct srcu_struct **)_T))
>  #define class_srcu_fast_notrace_constructor(_T) WITH_LOCK_GUARD_1_ATTRS(srcu_fast_notrace, _T)
>  
> +DEFINE_LOCK_GUARD_1(srcu_fast_updown, struct srcu_struct,
> +		    _T->scp = srcu_read_lock_fast_updown(_T->lock),
> +		    srcu_read_unlock_fast_updown(_T->lock, _T->scp),
> +		    struct srcu_ctr __percpu *scp)
> +DECLARE_LOCK_GUARD_1_ATTRS(srcu_fast_updown, __acquires_shared(_T), __releases_shared(*(struct srcu_struct **)_T))
> +#define class_srcu_fast_updown_constructor(_T) WITH_LOCK_GUARD_1_ATTRS(srcu_fast_updown, _T)
> +
>  #endif
> -- 
> 2.53.0-Meta
> 

^ permalink raw reply

* Re: [PATCH v8 13/46] KVM: guest_memfd: Add base support for KVM_SET_MEMORY_ATTRIBUTES2
From: Ackerley Tng @ 2026-07-06 18:17 UTC (permalink / raw)
  To: Suzuki K Poulose, aik, andrew.jones, binbin.wu, brauner,
	chao.p.peng, david, jmattson, jthoughton, michael.roth, oupton,
	pankaj.gupta, qperret, rick.p.edgecombe, rientjes, shivankg,
	steven.price, tabba, willy, wyihan, yan.y.zhao, forkloop,
	pratyush, aneesh.kumar, liam, Paolo Bonzini, Sean Christopherson,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
	H. Peter Anvin, Steven Rostedt, Masami Hiramatsu,
	Mathieu Desnoyers, Jonathan Corbet, Shuah Khan, Shuah Khan,
	Vishal Annapurve, Andrew Morton, Chris Li, Kairui Song,
	Kemeng Shi, Nhat Pham, Barry Song, Axel Rasmussen, Yuanchu Xie,
	Wei Xu, Youngjun Park, Qi Zheng, Shakeel Butt, Kiryl Shutsemau,
	Baoquan He, Jason Gunthorpe, Vlastimil Babka
  Cc: kvm, linux-kernel, linux-trace-kernel, linux-doc, linux-kselftest,
	linux-mm, linux-coco
In-Reply-To: <114e2488-97ed-4740-a8e8-1edd991f26c5@arm.com>

Suzuki K Poulose <suzuki.poulose@arm.com> writes:

>
> [...snip...]
>
>> +static int __kvm_gmem_set_attributes(struct inode *inode, pgoff_t start,
>> +				     size_t nr_pages, uint64_t attrs)
>> +{
>> +	struct address_space *mapping = inode->i_mapping;
>> +	struct gmem_inode *gi = GMEM_I(inode);
>> +	pgoff_t end = start + nr_pages;
>> +	struct maple_tree *mt;
>> +	struct ma_state mas;
>> +	int r;
>> +
>> +	mt = &gi->attributes;
>> +
>> +	filemap_invalidate_lock(mapping);
>> +
>> +	mas_init(&mas, mt, start);
>> +	r = kvm_gmem_mas_preallocate(&mas, attrs, start, nr_pages);
>> +	if (r)
>> +		goto out;
>> +
>> +	/*
>> +	 * From this point on guest_memfd has performed necessary
>> +	 * checks and can proceed to do guest-breaking changes.
>> +	 */
>> +
>> +	kvm_gmem_invalidate_start(inode, start, end);
>
> I added support for Arm CCA KVM patches with the inplace conversion and
> I am hitting the following issue.
>
> 1. I am supporting INIT_SHARED + MMAP flags.
> 2. VMM creates the Gmem_fd with both the flags above.
> 3. Uses the shared gmem-mmap to load the initial payloads (kernel, dtb).
> 4. At the VM finalization time, Populate the loaded regions one by one
>     by
>      a) copying the images to a temparory buffer - Since CCA can't really
>         load the contents in-place.

Sounds good :). I see that you blocked this in the kernel by returning
-EOPNOTSUPP if (!src_page) [0].

>      b) Set the "region" to Private in the gmem_fd (via
> SET_MEMORY_ATTRIBUTES2)
>      c) Invoke CCA backend to populate the private memory via
>         ioctl(KVM_ARM_RMI_POPULATE,..) [0]
>

This flow sounds right.

> [0]
> https://lore.kernel.org/all/20260513131757.116630-27-steven.price@arm.com/
>
>
> 5. Additionally, VMM can mark the entire RAM to be private before the VM
>     starts running, again via SET_MEMORY_ATTRIBUTES2. On CCA, this
> action is measured and doesn't require the Host to "commit" memory to
> the VM.
> Instead the host can lazily donate memory on a fault.
>

For both TDX and SNP, the host can also lazily donate memory,
guest_memfd supports this.

> But step (5) triggers the invalidation of both private and shared
> mappings of the gmem area, from the kvm_gmem_invalidate_start()
> above.
>
> This is because, the entire DRAM now has, some portions PRIVATE (the
> loaded regions) and the rest are SHARED (from the Gmem_fd creation).
>   Thus, kvm_gmem_get_invalidate_filter(Dram_start, Dram_end) causes the
> invalidation of both "PRIVATE" and "SHARED" regions, which results
> in the destruction of the already loaded data and things go south.
>

This destruction will happen for TDX as well. I think we managed to get
around this because we didn't apply conversion on the already-private
ranges.

IIUC on SNP, zapping pages in the stage 2 page tables doesn't destroy
the data, so that's probably why it has been fine for SNP.

> When we know that the kvm_gmem_invalidate_xx is triggered by a
> conversion, we don't need to invalidate the existing pages that
> are in the requested state. i.e., the following patch on top of
> this series does the trick for me :
>
>
> diff --git a/virt/kvm/guest_memfd.c b/virt/kvm/guest_memfd.c
> index a97fcac34a0e..62e0427a49f4 100644
> --- a/virt/kvm/guest_memfd.c
> +++ b/virt/kvm/guest_memfd.c
> @@ -250,16 +250,23 @@ static void __kvm_gmem_invalidate_start(struct
> gmem_file *f, pgoff_t start,
>                  KVM_MMU_UNLOCK(kvm);
>   }
>
> +static void kvm_gmem_invalidate_start_filter(struct inode *inode,
> pgoff_t start,
> +                                            pgoff_t end,
> +                                            enum kvm_gfn_range_filter
> attr_filter)
> +{
> +       struct gmem_file *f;
> +
> +       kvm_gmem_for_each_file(f, inode)
> +               __kvm_gmem_invalidate_start(f, start, end, attr_filter);
> +}
> +
>   static void kvm_gmem_invalidate_start(struct inode *inode, pgoff_t start,
>                                        pgoff_t end)
>   {
>          enum kvm_gfn_range_filter attr_filter;
> -       struct gmem_file *f;
> -
>          attr_filter = kvm_gmem_get_invalidate_filter(inode, start, end);
>
> -       kvm_gmem_for_each_file(f, inode)
> -               __kvm_gmem_invalidate_start(f, start, end, attr_filter);
> +       kvm_gmem_invalidate_start_filter(inode, start, end, attr_filter);
>   }
>
>   static void __kvm_gmem_invalidate_end(struct gmem_file *f, pgoff_t start,
> @@ -724,9 +731,14 @@ static int __kvm_gmem_set_attributes(struct inode
> *inode, pgoff_t start,
>          /*
>           * From this point on guest_memfd has performed necessary
>           * checks and can proceed to do guest-breaking changes.
> +        * Also, we don't have to invalidate the regions that
> +        * may already be in the requested state. Hence, we could
> +        * explicitly filter the invalidations to the opposite
> +        * state.
>           */
>
> -       kvm_gmem_invalidate_start(inode, start, end);
> +       kvm_gmem_invalidate_start_filter(inode, start, end,
> +                                       to_private ? KVM_FILTER_SHARED :
> KVM_FILTER_PRIVATE);
>

I think this makes sense. Thanks for catching this.

>          if (!to_private)
>                  kvm_gmem_invalidate(inode, start, end);
>
>
> Thoughts ?
>
> Suzuki
>
>
>>
>> [...snip...]
>>

^ permalink raw reply

* Re: [PATCH v5 3/9] mm: use enum migrate_reason instead of int for migration reason parameters
From: David Hildenbrand (Arm) @ 2026-07-06 18:34 UTC (permalink / raw)
  To: Ye Liu, Muchun Song, Oscar Salvador, Andrew Morton,
	Steven Rostedt, Masami Hiramatsu, Vlastimil Babka
  Cc: Zi Yan, Matthew Brost, Joshua Hahn, Rakie Kim, Byungchul Park,
	Gregory Price, Ying Huang, Alistair Popple, Lorenzo Stoakes,
	Liam R. Howlett, Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
	Mathieu Desnoyers, Brendan Jackman, Johannes Weiner, linux-mm,
	linux-kernel, linux-trace-kernel
In-Reply-To: <20260701061101.344679-4-ye.liu@linux.dev>

On 7/1/26 08:10, Ye Liu wrote:
> Replace all 'int reason' function parameters that carry migrate_reason
> values with the proper 'enum migrate_reason' type.  This makes the
> intent explicit and leverages compiler type checking.  The affected
> subsystems are:
> 
>   - page_owner: __folio_set_owner_migrate_reason(),
>                 folio_set_owner_migrate_reason()
>   - migrate: migrate_pages(), migrate_pages_sync(),
>              migrate_pages_batch(), migrate_folios_move(),
>              migrate_hugetlbs(), unmap_and_move_huge_page()
>   - hugetlb: move_hugetlb_state(), htlb_allow_alloc_fallback()
>   - trace: mm_migrate_pages and mm_migrate_pages_start events
> 
> The 'short last_migrate_reason' struct field and internal helper
> parameter in page_owner are intentionally left as 'short' since they
> store per-page metadata where size matters.
> 
> No functional change.
> 
> Signed-off-by: Ye Liu <ye.liu@linux.dev>
> Reviewed-by: Zi Yan <ziy@nvidia.com>
> Reviewed-by: Vlastimil Babka (SUSE) <vbabka@kernel.org>
> ---
>  include/linux/hugetlb.h        |  9 +++++----
>  include/linux/migrate.h        |  6 ++++--
>  include/linux/page_owner.h     |  7 ++++---
>  include/trace/events/migrate.h |  8 ++++----
>  mm/hugetlb.c                   |  3 ++-
>  mm/migrate.c                   | 12 ++++++------
>  mm/page_owner.c                |  2 +-
>  7 files changed, 26 insertions(+), 21 deletions(-)
> 
> diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h
> index 2abaf99321e9..fa828232dfcc 100644
> --- a/include/linux/hugetlb.h
> +++ b/include/linux/hugetlb.h
> @@ -154,7 +154,8 @@ long hugetlb_unreserve_pages(struct inode *inode, long start, long end,
>  bool folio_isolate_hugetlb(struct folio *folio, struct list_head *list);
>  int get_hwpoison_hugetlb_folio(struct folio *folio, bool *hugetlb, bool unpoison);
>  void folio_putback_hugetlb(struct folio *folio);
> -void move_hugetlb_state(struct folio *old_folio, struct folio *new_folio, int reason);
> +void move_hugetlb_state(struct folio *old_folio, struct folio *new_folio,
> +			enum migrate_reason reason);

Two tabs indent, applies to all other cases in here as well.

Besides the "extern" Lorenzo mentioned, LGTM.

-- 
Cheers,

David

^ permalink raw reply

* Re: [PATCH] tracing/user_events: fix use-after-free of enabler in user_event_mm_dup()
From: Steven Rostedt @ 2026-07-06 20:06 UTC (permalink / raw)
  To: Beau Belgrave
  Cc: XIAO WU, Michael Bommarito, Masami Hiramatsu, Mathieu Desnoyers,
	linux-trace-kernel, linux-kernel, stable
In-Reply-To: <20260624200535.GA132-beaub@linux.microsoft.com>

On Wed, 24 Jun 2026 20:05:35 +0000
Beau Belgrave <beaub@linux.microsoft.com> wrote:

> While I cannot repro this locally on my 16 core machine, I do agree this
> case needs to be handled correctly. The enabler should keep the ref to
> the user_event until after an RCU grace period. I have this fix that
> addresses it more completely than the original proposal.
> 
> I'm hoping you can try out this fix with your machine that does repro
> the timing window. The below change needs self test fixes, since now the
> free happens after an RCU grace period + work queue schedule. This is
> because the self tests (abi_test and perf_test) assume after unreg the
> last ref is immediate (which was never guaranteed).

I'm taking in the OP patch, but this looks like a separate issue.

Any update on this?

-- Steve

^ permalink raw reply

* Re: [PATCH] tracing/user_events: fix use-after-free of enabler in user_event_mm_dup()
From: Michael Bommarito @ 2026-07-06 20:11 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: Beau Belgrave, XIAO WU, Masami Hiramatsu, Mathieu Desnoyers,
	linux-trace-kernel, linux-kernel, stable
In-Reply-To: <20260706160650.2791767d@gandalf.local.home>

On Mon, Jul 6, 2026 at 4:06 PM Steven Rostedt <rostedt@goodmis.org> wrote:
> I'm taking in the OP patch, but this looks like a separate issue.
>
> Any update on this?

Sorry, had gone fishing.  I'll have v2 in the next day or so

Thanks,
Mike

^ permalink raw reply

* Re: [PATCH v8 13/46] KVM: guest_memfd: Add base support for KVM_SET_MEMORY_ATTRIBUTES2
From: Suzuki K Poulose @ 2026-07-06 22:35 UTC (permalink / raw)
  To: Ackerley Tng, aik, andrew.jones, binbin.wu, brauner, chao.p.peng,
	david, jmattson, jthoughton, michael.roth, oupton, pankaj.gupta,
	qperret, rick.p.edgecombe, rientjes, shivankg, steven.price,
	tabba, willy, wyihan, yan.y.zhao, forkloop, pratyush,
	aneesh.kumar, liam, Paolo Bonzini, Sean Christopherson,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
	H. Peter Anvin, Steven Rostedt, Masami Hiramatsu,
	Mathieu Desnoyers, Jonathan Corbet, Shuah Khan, Shuah Khan,
	Vishal Annapurve, Andrew Morton, Chris Li, Kairui Song,
	Kemeng Shi, Nhat Pham, Barry Song, Axel Rasmussen, Yuanchu Xie,
	Wei Xu, Youngjun Park, Qi Zheng, Shakeel Butt, Kiryl Shutsemau,
	Baoquan He, Jason Gunthorpe, Vlastimil Babka
  Cc: kvm, linux-kernel, linux-trace-kernel, linux-doc, linux-kselftest,
	linux-mm, linux-coco
In-Reply-To: <CAEvNRgFKbKfTMkqh_XF-igm07qYWfRwYJ5SH7wHcLZnqesCzTw@mail.gmail.com>

On 06/07/2026 19:17, Ackerley Tng wrote:
> Suzuki K Poulose <suzuki.poulose@arm.com> writes:
> 
>>
>> [...snip...]
>>
>>> +static int __kvm_gmem_set_attributes(struct inode *inode, pgoff_t start,
>>> +				     size_t nr_pages, uint64_t attrs)
>>> +{
>>> +	struct address_space *mapping = inode->i_mapping;
>>> +	struct gmem_inode *gi = GMEM_I(inode);
>>> +	pgoff_t end = start + nr_pages;
>>> +	struct maple_tree *mt;
>>> +	struct ma_state mas;
>>> +	int r;
>>> +
>>> +	mt = &gi->attributes;
>>> +
>>> +	filemap_invalidate_lock(mapping);
>>> +
>>> +	mas_init(&mas, mt, start);
>>> +	r = kvm_gmem_mas_preallocate(&mas, attrs, start, nr_pages);
>>> +	if (r)
>>> +		goto out;
>>> +
>>> +	/*
>>> +	 * From this point on guest_memfd has performed necessary
>>> +	 * checks and can proceed to do guest-breaking changes.
>>> +	 */
>>> +
>>> +	kvm_gmem_invalidate_start(inode, start, end);
>>
>> I added support for Arm CCA KVM patches with the inplace conversion and
>> I am hitting the following issue.
>>
>> 1. I am supporting INIT_SHARED + MMAP flags.
>> 2. VMM creates the Gmem_fd with both the flags above.
>> 3. Uses the shared gmem-mmap to load the initial payloads (kernel, dtb).
>> 4. At the VM finalization time, Populate the loaded regions one by one
>>      by
>>       a) copying the images to a temparory buffer - Since CCA can't really
>>          load the contents in-place.
> 
> Sounds good :). I see that you blocked this in the kernel by returning
> -EOPNOTSUPP if (!src_page) [0].

We could do the copy in kernel with src_page == dst_page, but that would
affect the batching of Granule delegation (and at which point we might
need a temparory buffer in the kernel as big as the vma_pagesize)

> 
>>       b) Set the "region" to Private in the gmem_fd (via
>> SET_MEMORY_ATTRIBUTES2)
>>       c) Invoke CCA backend to populate the private memory via
>>          ioctl(KVM_ARM_RMI_POPULATE,..) [0]
>>
> 
> This flow sounds right.
> 
>> [0]
>> https://lore.kernel.org/all/20260513131757.116630-27-steven.price@arm.com/
>>
>>
>> 5. Additionally, VMM can mark the entire RAM to be private before the VM
>>      starts running, again via SET_MEMORY_ATTRIBUTES2. On CCA, this
>> action is measured and doesn't require the Host to "commit" memory to
>> the VM.
>> Instead the host can lazily donate memory on a fault.
>>
> 
> For both TDX and SNP, the host can also lazily donate memory,
> guest_memfd supports this.
> 
>> But step (5) triggers the invalidation of both private and shared
>> mappings of the gmem area, from the kvm_gmem_invalidate_start()
>> above.
>>
>> This is because, the entire DRAM now has, some portions PRIVATE (the
>> loaded regions) and the rest are SHARED (from the Gmem_fd creation).
>>    Thus, kvm_gmem_get_invalidate_filter(Dram_start, Dram_end) causes the
>> invalidation of both "PRIVATE" and "SHARED" regions, which results
>> in the destruction of the already loaded data and things go south.
>>
> 
> This destruction will happen for TDX as well. I think we managed to get
> around this because we didn't apply conversion on the already-private
> ranges.
> 
> IIUC on SNP, zapping pages in the stage 2 page tables doesn't destroy
> the data, so that's probably why it has been fine for SNP.

Additionally, the Guest at boot, will try to mark the entire DRAM
as Private (RIPAS_RAM in CCA), which would trigger this anyways.

Suzuki


> 
>> When we know that the kvm_gmem_invalidate_xx is triggered by a
>> conversion, we don't need to invalidate the existing pages that
>> are in the requested state. i.e., the following patch on top of
>> this series does the trick for me :
>>
>>
>> diff --git a/virt/kvm/guest_memfd.c b/virt/kvm/guest_memfd.c
>> index a97fcac34a0e..62e0427a49f4 100644
>> --- a/virt/kvm/guest_memfd.c
>> +++ b/virt/kvm/guest_memfd.c
>> @@ -250,16 +250,23 @@ static void __kvm_gmem_invalidate_start(struct
>> gmem_file *f, pgoff_t start,
>>                   KVM_MMU_UNLOCK(kvm);
>>    }
>>
>> +static void kvm_gmem_invalidate_start_filter(struct inode *inode,
>> pgoff_t start,
>> +                                            pgoff_t end,
>> +                                            enum kvm_gfn_range_filter
>> attr_filter)
>> +{
>> +       struct gmem_file *f;
>> +
>> +       kvm_gmem_for_each_file(f, inode)
>> +               __kvm_gmem_invalidate_start(f, start, end, attr_filter);
>> +}
>> +
>>    static void kvm_gmem_invalidate_start(struct inode *inode, pgoff_t start,
>>                                         pgoff_t end)
>>    {
>>           enum kvm_gfn_range_filter attr_filter;
>> -       struct gmem_file *f;
>> -
>>           attr_filter = kvm_gmem_get_invalidate_filter(inode, start, end);
>>
>> -       kvm_gmem_for_each_file(f, inode)
>> -               __kvm_gmem_invalidate_start(f, start, end, attr_filter);
>> +       kvm_gmem_invalidate_start_filter(inode, start, end, attr_filter);
>>    }
>>
>>    static void __kvm_gmem_invalidate_end(struct gmem_file *f, pgoff_t start,
>> @@ -724,9 +731,14 @@ static int __kvm_gmem_set_attributes(struct inode
>> *inode, pgoff_t start,
>>           /*
>>            * From this point on guest_memfd has performed necessary
>>            * checks and can proceed to do guest-breaking changes.
>> +        * Also, we don't have to invalidate the regions that
>> +        * may already be in the requested state. Hence, we could
>> +        * explicitly filter the invalidations to the opposite
>> +        * state.
>>            */
>>
>> -       kvm_gmem_invalidate_start(inode, start, end);
>> +       kvm_gmem_invalidate_start_filter(inode, start, end,
>> +                                       to_private ? KVM_FILTER_SHARED :
>> KVM_FILTER_PRIVATE);
>>
> 
> I think this makes sense. Thanks for catching this.
> 
>>           if (!to_private)
>>                   kvm_gmem_invalidate(inode, start, end);
>>
>>
>> Thoughts ?
>>
>> Suzuki
>>
>>
>>>
>>> [...snip...]
>>>


^ permalink raw reply

* [PATCH net-next] net/tcp: Add explicit tracepoint for tcp_syn_ack_timeout()
From: Emil Tsalapatis @ 2026-07-07  1:01 UTC (permalink / raw)
  To: netdev, linux-trace-kernel
  Cc: edumazet, ncardwell, kuniyu, rostedt, mhiramat, davem, kuba,
	pabeni, Emil Tsalapatis

Clang can inline the tcp_syn_ack_timeout() function during compilation,
making it impossible to use kprobes for tracing without preventing
inlining. Add an explicit tracepoint to it instead.

Signed-off-by: Emil Tsalapatis <emil@etsalapatis.com>
---
 include/trace/events/tcp.h | 72 ++++++++++++++++++++++++++++++++++++++
 net/ipv4/tcp_timer.c       |  3 ++
 2 files changed, 75 insertions(+)

diff --git a/include/trace/events/tcp.h b/include/trace/events/tcp.h
index f155f95cdb6e..37ffaa50faad 100644
--- a/include/trace/events/tcp.h
+++ b/include/trace/events/tcp.h
@@ -332,6 +332,78 @@ TRACE_EVENT(tcp_retransmit_synack,
 		  __entry->saddr_v6, __entry->daddr_v6)
 );
 
+TRACE_EVENT(tcp_syn_ack_timeout,
+
+	TP_PROTO(const struct request_sock *req),
+
+	TP_ARGS(req),
+
+	TP_STRUCT__entry(
+		__field(const void *, req)
+		__field(__u16, sport)
+		__field(__u16, dport)
+		__field(__u16, family)
+		__array(__u8, saddr, 4)
+		__array(__u8, daddr, 4)
+		__array(__u8, saddr_v6, 16)
+		__array(__u8, daddr_v6, 16)
+		__field(u8, state)
+		__field(u8, num_timeout)
+		__field(bool, acked)
+	),
+
+
+	TP_fast_assign(
+		const struct inet_request_sock *ireq = inet_rsk(req);
+		__be32 *p32;
+
+		__entry->req = req;
+
+		__entry->sport = ireq->ir_num;
+		__entry->dport = ntohs(ireq->ir_rmt_port);
+		__entry->family = req->__req_common.skc_family;
+
+		p32 = (__be32 *) __entry->saddr;
+		*p32 = ireq->ir_loc_addr;
+
+		p32 = (__be32 *) __entry->daddr;
+		*p32 = ireq->ir_rmt_addr;
+
+#if IS_ENABLED(CONFIG_IPV6)
+		/*
+		 * Cannot use TP_STORE_ADDRS directly because it assumes
+		 * there is an sk available.
+		 */
+		if (__entry->family == AF_INET6) {
+			struct in6_addr *pin6;
+
+			pin6 = (struct in6_addr *)__entry->saddr_v6;
+			*pin6 = ireq->ir_v6_loc_addr;
+			pin6 = (struct in6_addr *)__entry->daddr_v6;
+			*pin6 = ireq->ir_v6_rmt_addr;
+		} else {
+			TP_STORE_V4MAPPED(__entry, ireq->ir_loc_addr, ireq->ir_rmt_addr);
+		}
+#else
+		TP_STORE_V4MAPPED(__entry, ireq->ir_loc_addr, ireq->ir_rmt_addr);
+#endif
+
+		__entry->state		= ireq->ireq_state;
+		__entry->num_timeout	= req->num_timeout;
+		__entry->acked		= ireq->acked;
+	),
+
+	TP_printk("family=%s sport=%hu dport=%hu saddr=%pI4 "
+		"daddr=%pI4 saddrv6=%pI6c daddrv6=%pI6c "
+		"ireq_state=%s num_timeout=%u acked=%d",
+		  show_family_name(__entry->family),
+		  __entry->sport, __entry->dport,
+		  __entry->saddr, __entry->daddr,
+		  __entry->saddr_v6, __entry->daddr_v6,
+		  show_tcp_state_name(__entry->state),
+		  __entry->num_timeout, __entry->acked)
+);
+
 TRACE_EVENT(tcp_sendmsg_locked,
 	TP_PROTO(const struct sock *sk, const struct msghdr *msg,
 		 const struct sk_buff *skb, int size_goal),
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
index bf171b5e1eb3..8f482a6b43e3 100644
--- a/net/ipv4/tcp_timer.c
+++ b/net/ipv4/tcp_timer.c
@@ -24,6 +24,7 @@
 #include <net/tcp.h>
 #include <net/tcp_ecn.h>
 #include <net/rstreason.h>
+#include <trace/events/tcp.h>
 
 static u32 tcp_clamp_rto_to_user_timeout(const struct sock *sk)
 {
@@ -753,6 +754,8 @@ void tcp_syn_ack_timeout(const struct request_sock *req)
 	struct net *net = read_pnet(&inet_rsk(req)->ireq_net);
 
 	__NET_INC_STATS(net, LINUX_MIB_TCPTIMEOUTS);
+
+	trace_tcp_syn_ack_timeout(req);
 }
 
 void tcp_reset_keepalive_timer(struct sock *sk, unsigned long len)
-- 
2.54.0


^ permalink raw reply related

* Re: [PATCH 0/4] tracing: add ref_trace_final_put tracing
From: Eugene Mavick @ 2026-07-07  6:18 UTC (permalink / raw)
  To: Eugene Mavick, Will Deacon, Peter Zijlstra, Boqun Feng,
	Mark Rutland, Gary Guo, Steven Rostedt, Masami Hiramatsu,
	Mathieu Desnoyers, Andrew Morton, Dennis Zhou, Tejun Heo,
	Christoph Lameter
  Cc: linux-kernel, linux-trace-kernel, linux-mm
In-Reply-To: <20260705-refcount-final-put-trace-v1-0-cdd0014626a9@mavick.dev>

I apologise for the duplicate patch series submission, I had resent the
v1 via b4 relay as it did not show up on lore.kernel.org for a
day, and I assumed the emails were lost. 

^ permalink raw reply

* Re: [PATCH v3 09/17] rv: Add KUnit tests for some DA/HA monitors
From: Nam Cao @ 2026-07-07  6:52 UTC (permalink / raw)
  To: Gabriele Monaco, linux-trace-kernel, linux-kernel, Steven Rostedt,
	Gabriele Monaco, Masami Hiramatsu
  Cc: Thomas Weissschuh, Tomas Glozar, John Kacur, Wen Yang
In-Reply-To: <20260625121440.116317-10-gmonaco@redhat.com>

Gabriele Monaco <gmonaco@redhat.com> writes:
> + * Automatically generated by rvgen kunit.

I was slightly confused by this, as I wasn't aware that rvgen can
generate this.

The patch adding generation support into rvgen should be before
this patch. But oh well, no big deal.

Reviewed-by: Nam Cao <namcao@linutronix.de>

^ permalink raw reply

* Re: [PATCH v3 11/17] rv: Prevent unintentional tracepoints during KUnit tests
From: Nam Cao @ 2026-07-07  7:00 UTC (permalink / raw)
  To: Gabriele Monaco, linux-trace-kernel, linux-kernel, Steven Rostedt,
	Gabriele Monaco, Masami Hiramatsu
  Cc: Thomas Weissschuh, Tomas Glozar, John Kacur, Wen Yang
In-Reply-To: <20260625121440.116317-12-gmonaco@redhat.com>

Gabriele Monaco <gmonaco@redhat.com> writes:
> Monitor initialisation also called during KUnit tests may register some
> tracepoints, this can lead to issues since we don't expect real monitor
> events running during KUnit tests.
>
> Prevent tracepoint registration if an RV KUnit test is running.
>
> Reviewed-by: Nam Cao <namcao@linutronix.de>
> Signed-off-by: Gabriele Monaco <gmonaco@redhat.com>

Somehow I have no recollection of seeing this patch.

But since we already hold rv_interface_lock during the test, is this
really necessary?

Nam

^ permalink raw reply

* Re: [PATCH v3 12/17] rv: Add KUnit tests for some LTL monitors
From: Nam Cao @ 2026-07-07  7:04 UTC (permalink / raw)
  To: Gabriele Monaco, linux-trace-kernel, linux-kernel, Steven Rostedt,
	Gabriele Monaco, Masami Hiramatsu
  Cc: Thomas Weissschuh, Tomas Glozar, John Kacur, Wen Yang
In-Reply-To: <20260625121440.116317-13-gmonaco@redhat.com>

Gabriele Monaco <gmonaco@redhat.com> writes:
> Validate the functionality of LTL monitors by injecting events in a
> controlled environment (KUnit) and expecting reactions, just like it is
> done in DA monitors.
>
> Signed-off-by: Gabriele Monaco <gmonaco@redhat.com>

Reviewed-by: Nam Cao <namcao@linutronix.de>

^ permalink raw reply

* Re: [PATCH v3 11/17] rv: Prevent unintentional tracepoints during KUnit tests
From: Gabriele Monaco @ 2026-07-07  7:23 UTC (permalink / raw)
  To: Nam Cao, linux-trace-kernel, linux-kernel
  Cc: Thomas Weissschuh, Tomas Glozar, John Kacur, Wen Yang,
	Steven Rostedt, Masami Hiramatsu
In-Reply-To: <878q7n2six.fsf@yellow.woof>

On Tue, 2026-07-07 at 09:00 +0200, Nam Cao wrote:
> Gabriele Monaco <gmonaco@redhat.com> writes:
> > Monitor initialisation also called during KUnit tests may register some
> > tracepoints, this can lead to issues since we don't expect real monitor
> > events running during KUnit tests.
> > 
> > Prevent tracepoint registration if an RV KUnit test is running.
> > 
> > Reviewed-by: Nam Cao <namcao@linutronix.de>
> > Signed-off-by: Gabriele Monaco <gmonaco@redhat.com>
> 
> Somehow I have no recollection of seeing this patch.

Well, I'm fairly sure you reviewed it ;)

> But since we already hold rv_interface_lock during the test, is this
> really necessary?

This is for things like ltl_monitor_init() that attaches the newtask probe.
The function is also doing a few other things we may not want to do, to be fair,
but calling the monitor_init() function as-is was the easiest solution I could
think of. Also ha_monitor_init() may attach a probe.

I suppose I could also do some more targeted initialisation/destruction, in fact
right now, the LTL initialisation does a bunch of stuff tests don't need and
doesn't do what they do need (initialise the dummy tasks, which aren't part of
the task list).

I should probably rethink this a little.

Thanks,
Gabriele


^ permalink raw reply

* Re: [PATCH net-next] net/tcp: Add explicit tracepoint for tcp_syn_ack_timeout()
From: Eric Dumazet @ 2026-07-07  7:52 UTC (permalink / raw)
  To: Emil Tsalapatis
  Cc: netdev, linux-trace-kernel, ncardwell, kuniyu, rostedt, mhiramat,
	davem, kuba, pabeni
In-Reply-To: <20260707010151.43976-1-emil@etsalapatis.com>

On Mon, Jul 6, 2026 at 6:01 PM Emil Tsalapatis <emil@etsalapatis.com> wrote:
>
> Clang can inline the tcp_syn_ack_timeout() function during compilation,
> making it impossible to use kprobes for tracing without preventing
> inlining. Add an explicit tracepoint to it instead.

So much copy/pasting for a very small issue :/

>
> Signed-off-by: Emil Tsalapatis <emil@etsalapatis.com>
> ---
>  include/trace/events/tcp.h | 72 ++++++++++++++++++++++++++++++++++++++
>  net/ipv4/tcp_timer.c       |  3 ++
>  2 files changed, 75 insertions(+)
>

tcp_syn_ack_timeout() is hardly a fast path, so you can instead:

diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
index 322db13333c7..ab2c3de19e46 100644
--- a/net/ipv4/tcp_timer.c
+++ b/net/ipv4/tcp_timer.c
@@ -748,7 +748,7 @@ static void tcp_write_timer(struct timer_list *t)
        sock_put(sk);
 }

-void tcp_syn_ack_timeout(const struct request_sock *req)
+noinline_for_tracing void tcp_syn_ack_timeout(const struct request_sock *req)
 {
        struct net *net = read_pnet(&inet_rsk(req)->ireq_net);

^ permalink raw reply related

* Re: [PATCH v3 06/11] mm/cma: Allow dynamically creating CMA areas
From: Marek Szyprowski @ 2026-07-07 10:02 UTC (permalink / raw)
  To: Thierry Reding, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Jonathan Hunter, Mikko Perttunen, Yury Norov, Rasmus Villemoes,
	Russell King, Alexander Gordeev, Gerald Schaefer, Heiko Carstens,
	Vasily Gorbik, Christian Borntraeger, Sven Schnelle,
	Andrew Morton, David Hildenbrand, Lorenzo Stoakes,
	Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
	Suren Baghdasaryan, Michal Hocko, Robin Murphy, Sumit Semwal,
	Benjamin Gaignard, Brian Starkey, John Stultz, T.J. Mercier,
	Christian König, Steven Rostedt, Masami Hiramatsu,
	Mathieu Desnoyers, Catalin Marinas, Will Deacon
  Cc: devicetree, linux-tegra, linux-kernel, dri-devel, linux-media,
	linux-arm-kernel, linux-s390, linux-mm, iommu, linaro-mm-sig,
	linux-trace-kernel
In-Reply-To: <20260701-tegra-vpr-v3-6-d80f7b871bb4@nvidia.com>

On 01.07.2026 18:08, Thierry Reding wrote:
> From: Thierry Reding <treding@nvidia.com>
>
> There is no technical reason why there should be a limited number of CMA
> regions, so extract some code into helpers and use them to create extra
> functions (cma_create() and cma_free()) that allow creating and freeing,
> respectively, CMA regions dynamically at runtime.


Well, the technical reason for not creating cma regions dynamically at
runtime is that on some architectures (like 32bit ARM) the early fixup
for the region is needed to make it functional for DMA.


I would add a comment about that in the cma_create() and ensure that its
future callers explicitly depend on !ARM_32BIT.


> The static array of CMA areas cannot be replaced by dynamically created
> areas because for many of them, allocation must not fail and some cases
> may need to initialize them before the slab allocator is even available.
> To account for this, keep these "early" areas in a separate list and
> track the dynamic areas in a separate list.
>
> Signed-off-by: Thierry Reding <treding@nvidia.com>
> ---
> Changes in v3:
> - rebase on top of recent linux-next, update kernel/dma/contiguous.c
> - use kzalloc_obj() instead of kzalloc() with sizeof()
>
> Changes in v2:
> - rename fixed number of CMA areas to reflect their main use
> - account for pages in dynamically allocated regions
> ---
> arch/arm/mm/dma-mapping.c | 2 +-
> arch/s390/mm/init.c | 2 +-
> include/linux/cma.h | 8 +-
> kernel/dma/contiguous.c | 2 +-
> mm/cma.c | 187 +++++++++++++++++++++++++++++++++++++---------
> mm/cma.h | 5 +-
> 6 files changed, 165 insertions(+), 41 deletions(-)
>
> diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
> index f9bc53b60f99..934952ab2102 100644
> --- a/arch/arm/mm/dma-mapping.c
> +++ b/arch/arm/mm/dma-mapping.c
> @@ -254,7 +254,7 @@ struct dma_contig_early_reserve {
> unsigned long size;
> };
> -static struct dma_contig_early_reserve dma_mmu_remap[MAX_CMA_AREAS] __initdata;
> +static struct dma_contig_early_reserve dma_mmu_remap[MAX_EARLY_CMA_AREAS] __initdata;
> static int dma_mmu_remap_num __initdata;
> diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c
> index f07168a0d3dd..f8f78f1434ea 100644
> --- a/arch/s390/mm/init.c
> +++ b/arch/s390/mm/init.c
> @@ -241,7 +241,7 @@ static int s390_cma_mem_notifier(struct notifier_block *nb,
> mem_data.start = arg->start_pfn << PAGE_SHIFT;
> mem_data.end = mem_data.start + (arg->nr_pages << PAGE_SHIFT);
> if (action == MEM_GOING_OFFLINE)
> - rc = cma_for_each_area(s390_cma_check_range, &mem_data);
> + rc = cma_for_each_early_area(s390_cma_check_range, &mem_data);
> return notifier_from_errno(rc);
> }
> diff --git a/include/linux/cma.h b/include/linux/cma.h
> index 8555d38a97b1..fb7a4923c3ba 100644
> --- a/include/linux/cma.h
> +++ b/include/linux/cma.h
> @@ -7,7 +7,7 @@
> #include <linux/numa.h>
> #ifdef CONFIG_CMA_AREAS
> -#define MAX_CMA_AREAS CONFIG_CMA_AREAS
> +#define MAX_EARLY_CMA_AREAS CONFIG_CMA_AREAS
> #endif
> #define CMA_MAX_NAME 64
> @@ -57,8 +57,14 @@ struct page *cma_alloc_frozen_compound(struct cma *cma, unsigned int order);
> bool cma_release_frozen(struct cma *cma, const struct page *pages,
> unsigned long count);
> +extern int cma_for_each_early_area(int (*it)(struct cma *cma, void *data), void *data);
> extern int cma_for_each_area(int (*it)(struct cma *cma, void *data), void *data);
> extern bool cma_intersects(struct cma *cma, unsigned long start, unsigned long end);
> extern void cma_reserve_pages_on_error(struct cma *cma);
> +
> +extern struct cma *cma_create(phys_addr_t base, phys_addr_t size,
> + unsigned int order_per_bit, const char *name);
> +extern void cma_free(struct cma *cma);
> +
> #endif
> diff --git a/kernel/dma/contiguous.c b/kernel/dma/contiguous.c
> index f754079a287d..7975551f69b3 100644
> --- a/kernel/dma/contiguous.c
> +++ b/kernel/dma/contiguous.c
> @@ -52,7 +52,7 @@
> #define CMA_SIZE_MBYTES 0
> #endif
> -static struct cma *dma_contiguous_areas[MAX_CMA_AREAS];
> +static struct cma *dma_contiguous_areas[MAX_EARLY_CMA_AREAS];
> static unsigned int dma_contiguous_areas_num;
> static int dma_contiguous_insert_area(struct cma *cma)
> diff --git a/mm/cma.c b/mm/cma.c
> index a13ce4999b39..f989e2e98594 100644
> --- a/mm/cma.c
> +++ b/mm/cma.c
> @@ -34,7 +34,12 @@
> #include "internal.h"
> #include "cma.h"
> -struct cma cma_areas[MAX_CMA_AREAS];
> +static DEFINE_MUTEX(cma_lock);
> +
> +struct cma cma_early_areas[MAX_EARLY_CMA_AREAS];
> +unsigned int cma_early_area_count;
> +
> +static LIST_HEAD(cma_areas);
> unsigned int cma_area_count;
> phys_addr_t cma_get_base(const struct cma *cma)
> @@ -198,7 +203,6 @@ static void __init cma_activate_area(struct cma *cma)
> free_reserved_page(pfn_to_page(pfn));
> }
> }
> - totalcma_pages -= cma->count;
> cma->available_count = cma->count = 0;
> pr_err("CMA area %s could not be activated\n", cma->name);
> }
> @@ -207,8 +211,8 @@ static int __init cma_init_reserved_areas(void)
> {
> int i;
> - for (i = 0; i < cma_area_count; i++)
> - cma_activate_area(&cma_areas[i]);
> + for (i = 0; i < cma_early_area_count; i++)
> + cma_activate_area(&cma_early_areas[i]);
> return 0;
> }
> @@ -219,41 +223,77 @@ void __init cma_reserve_pages_on_error(struct cma *cma)
> set_bit(CMA_RESERVE_PAGES_ON_ERROR, &cma->flags);
> }
> +static void __init cma_init_area(struct cma *cma, const char *name,
> + phys_addr_t size, unsigned int order_per_bit)
> +{
> + if (name)
> + strscpy(cma->name, name);
> + else
> + snprintf(cma->name, CMA_MAX_NAME, "cma%d\n", cma_area_count);
> +
> + cma->available_count = cma->count = size >> PAGE_SHIFT;
> + cma->order_per_bit = order_per_bit;
> +
> + INIT_LIST_HEAD(&cma->node);
> +}
> +
> static int __init cma_new_area(const char *name, phys_addr_t size,
> unsigned int order_per_bit,
> struct cma **res_cma)
> {
> struct cma *cma;
> - if (cma_area_count == ARRAY_SIZE(cma_areas)) {
> + if (cma_early_area_count == ARRAY_SIZE(cma_early_areas)) {
> pr_err("Not enough slots for CMA reserved regions!\n");
> return -ENOSPC;
> }
> + mutex_lock(&cma_lock);
> +
> /*
> * Each reserved area must be initialised later, when more kernel
> * subsystems (like slab allocator) are available.
> */
> - cma = &cma_areas[cma_area_count];
> - cma_area_count++;
> + cma = &cma_early_areas[cma_early_area_count];
> + cma_early_area_count++;
> - if (name)
> - strscpy(cma->name, name);
> - else
> - snprintf(cma->name, CMA_MAX_NAME, "cma%d\n", cma_area_count);
> + cma_init_area(cma, name, size, order_per_bit);
> - cma->available_count = cma->count = size >> PAGE_SHIFT;
> - cma->order_per_bit = order_per_bit;
> - *res_cma = cma;
> totalcma_pages += cma->count;
> + *res_cma = cma;
> +
> + mutex_unlock(&cma_lock);
> return 0;
> }
> static void __init cma_drop_area(struct cma *cma)
> {
> + mutex_lock(&cma_lock);
> totalcma_pages -= cma->count;
> - cma_area_count--;
> + cma_early_area_count--;
> + mutex_unlock(&cma_lock);
> +}
> +
> +static int __init cma_check_memory(phys_addr_t base, phys_addr_t size)
> +{
> + if (!size || !memblock_is_region_reserved(base, size))
> + return -EINVAL;
> +
> + /*
> + * CMA uses CMA_MIN_ALIGNMENT_BYTES as alignment requirement which
> + * needs pageblock_order to be initialized. Let's enforce it.
> + */
> + if (!pageblock_order) {
> + pr_err("pageblock_order not yet initialized. Called during early boot?\n");
> + return -EINVAL;
> + }
> +
> + /* ensure minimal alignment required by mm core */
> + if (!IS_ALIGNED(base | size, CMA_MIN_ALIGNMENT_BYTES))
> + return -EINVAL;
> +
> + return 0;
> }
> /**
> @@ -276,22 +316,9 @@ int __init cma_init_reserved_mem(phys_addr_t base, phys_addr_t size,
> struct cma *cma;
> int ret;
> - /* Sanity checks */
> - if (!size || !memblock_is_region_reserved(base, size))
> - return -EINVAL;
> -
> - /*
> - * CMA uses CMA_MIN_ALIGNMENT_BYTES as alignment requirement which
> - * needs pageblock_order to be initialized. Let's enforce it.
> - */
> - if (!pageblock_order) {
> - pr_err("pageblock_order not yet initialized. Called during early boot?\n");
> - return -EINVAL;
> - }
> -
> - /* ensure minimal alignment required by mm core */
> - if (!IS_ALIGNED(base | size, CMA_MIN_ALIGNMENT_BYTES))
> - return -EINVAL;
> + ret = cma_check_memory(base, size);
> + if (ret < 0)
> + return ret;
> ret = cma_new_area(name, size, order_per_bit, &cma);
> if (ret != 0)
> @@ -444,7 +471,7 @@ static int __init __cma_declare_contiguous_nid(phys_addr_t *basep,
> pr_debug("%s(size %pa, base %pa, limit %pa alignment %pa)\n",
> __func__, &size, &base, &limit, &alignment);
> - if (cma_area_count == ARRAY_SIZE(cma_areas)) {
> + if (cma_early_area_count == ARRAY_SIZE(cma_early_areas)) {
> pr_err("Not enough slots for CMA reserved regions!\n");
> return -ENOSPC;
> }
> @@ -1051,12 +1078,12 @@ bool cma_release_frozen(struct cma *cma, const struct page *pages,
> return true;
> }
> -int cma_for_each_area(int (*it)(struct cma *cma, void *data), void *data)
> +int cma_for_each_early_area(int (*it)(struct cma *cma, void *data), void *data)
> {
> int i;
> - for (i = 0; i < cma_area_count; i++) {
> - int ret = it(&cma_areas[i], data);
> + for (i = 0; i < cma_early_area_count; i++) {
> + int ret = it(&cma_early_areas[i], data);
> if (ret)
> return ret;
> @@ -1065,6 +1092,25 @@ int cma_for_each_area(int (*it)(struct cma *cma, void *data), void *data)
> return 0;
> }
> +int cma_for_each_area(int (*it)(struct cma *cma, void *data), void *data)
> +{
> + struct cma *cma;
> +
> + mutex_lock(&cma_lock);
> +
> + list_for_each_entry(cma, &cma_areas, node) {
> + int ret = it(cma, data);
> +
> + if (ret) {
> + mutex_unlock(&cma_lock);
> + return ret;
> + }
> + }
> +
> + mutex_unlock(&cma_lock);
> + return 0;
> +}
> +
> bool cma_intersects(struct cma *cma, unsigned long start, unsigned long end)
> {
> int r;
> @@ -1147,3 +1193,74 @@ void __init *cma_reserve_early(struct cma *cma, unsigned long size)
> return ret;
> }
> +
> +struct cma *__init cma_create(phys_addr_t base, phys_addr_t size,
> + unsigned int order_per_bit, const char *name)
> +{
> + struct cma *cma;
> + int ret;
> +
> + ret = cma_check_memory(base, size);
> + if (ret < 0)
> + return ERR_PTR(ret);
> +
> + cma = kzalloc_obj(*cma, GFP_KERNEL);
> + if (!cma)
> + return ERR_PTR(-ENOMEM);
> +
> + cma_init_area(cma, name, size, order_per_bit);
> + cma->ranges[0].base_pfn = PFN_DOWN(base);
> + cma->ranges[0].early_pfn = PFN_DOWN(base);
> + cma->ranges[0].count = cma->count;
> + cma->nranges = 1;
> +
> + cma_activate_area(cma);
> +
> + mutex_lock(&cma_lock);
> + list_add_tail(&cma->node, &cma_areas);
> + totalcma_pages += cma->count;
> + cma_area_count++;
> + mutex_unlock(&cma_lock);
> +
> + return cma;
> +}
> +
> +void cma_free(struct cma *cma)
> +{
> + unsigned int i;
> +
> + /*
> + * Safety check to prevent a CMA with active allocations from being
> + * released.
> + */
> + for (i = 0; i < cma->nranges; i++) {
> + unsigned long nbits = cma_bitmap_maxno(cma, &cma->ranges[i]);
> +
> + if (!bitmap_empty(cma->ranges[i].bitmap, nbits)) {
> + WARN(1, "%s: range %u not empty\n", cma->name, i);
> + return;
> + }
> + }
> +
> + /* free reserved pages and the bitmap */
> + for (i = 0; i < cma->nranges; i++) {
> + struct cma_memrange *cmr = &cma->ranges[i];
> + unsigned long end_pfn, pfn;
> +
> + end_pfn = cmr->base_pfn + cmr->count;
> + for (pfn = cmr->base_pfn; pfn < end_pfn; pfn++)
> + free_reserved_page(pfn_to_page(pfn));
> +
> + bitmap_free(cmr->bitmap);
> + }
> +
> + mutex_destroy(&cma->alloc_mutex);
> +
> + mutex_lock(&cma_lock);
> + totalcma_pages -= cma->count;
> + list_del(&cma->node);
> + cma_area_count--;
> + mutex_unlock(&cma_lock);
> +
> + kfree(cma);
> +}
> diff --git a/mm/cma.h b/mm/cma.h
> index c70180c36559..ae4db9819e38 100644
> --- a/mm/cma.h
> +++ b/mm/cma.h
> @@ -41,6 +41,7 @@ struct cma {
> unsigned long available_count;
> unsigned int order_per_bit; /* Order of pages represented by one bit */
> spinlock_t lock;
> + struct list_head node;
> struct mutex alloc_mutex;
> #ifdef CONFIG_CMA_DEBUGFS
> struct hlist_head mem_head;
> @@ -71,8 +72,8 @@ enum cma_flags {
> CMA_ACTIVATED,
> };
> -extern struct cma cma_areas[MAX_CMA_AREAS];
> -extern unsigned int cma_area_count;
> +extern struct cma cma_early_areas[MAX_EARLY_CMA_AREAS];
> +extern unsigned int cma_early_area_count;
> static inline unsigned long cma_bitmap_maxno(struct cma *cma,
> struct cma_memrange *cmr)
>
Best regards

-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland


^ permalink raw reply

* Re: [PATCH 17/30] mm: prefer vma_[start,end]_pgoff() to vma->vm_pgoff in kernel/
From: Marek Szyprowski @ 2026-07-07 10:20 UTC (permalink / raw)
  To: Lorenzo Stoakes, Andrew Morton
  Cc: linux-kernel, linux-arm-kernel, linux-parisc, linux-sgx, etnaviv,
	dri-devel, linux-arm-msm, freedreno, linux-tegra, kvm,
	linux-fsdevel, nvdimm, linux-mm, iommu, linux-perf-users,
	linux-trace-kernel, kasan-dev, damon
In-Reply-To: <ea87349d63205bf4c26ea79854f179a9bf8cfb0b.1782735110.git.ljs@kernel.org>

On 29.06.2026 14:23, Lorenzo Stoakes wrote:
> Be consistent in using vma_start_pgoff() and vma_end_pgoff(), which clearly
> indicates which part of the VMA the page offset refers to and aids
> greppability.
>
> This is part of a broader series laying the ground to provide a virtual
> page offset for MAP_PRIVATE-file backed anon folios.
>
> No functional change intended.
>
> Signed-off-by: Lorenzo Stoakes <ljs@kernel.org>
> ---
>  kernel/dma/coherent.c      |  7 ++++---
>  kernel/dma/direct.c        |  6 ++++--
>  kernel/dma/mapping.c       |  8 +++++---
>  kernel/dma/ops_helpers.c   |  4 ++--


Acked-by: Marek Szyprowski <m.szyprowski@samsung.com> # for kernel/dma


>  kernel/events/core.c       | 20 +++++++++++---------
>  kernel/events/uprobes.c    | 11 +++++++----
>  kernel/kcov.c              |  2 +-
>  kernel/trace/ring_buffer.c |  3 ++-
>  8 files changed, 36 insertions(+), 25 deletions(-)
>
> diff --git a/kernel/dma/coherent.c b/kernel/dma/coherent.c
> index bcdc0f76d2e8..2d3195eb7e83 100644
> --- a/kernel/dma/coherent.c
> +++ b/kernel/dma/coherent.c
> @@ -236,14 +236,15 @@ static int __dma_mmap_from_coherent(struct dma_coherent_mem *mem,
>  {
>  	if (mem && vaddr >= mem->virt_base && vaddr + size <=
>  		   (mem->virt_base + ((dma_addr_t)mem->size << PAGE_SHIFT))) {
> -		unsigned long off = vma->vm_pgoff;
> +		const pgoff_t pgoff_start = vma_start_pgoff(vma);
> +		const pgoff_t pgoff_end = vma_end_pgoff(vma);
>  		int start = (vaddr - mem->virt_base) >> PAGE_SHIFT;
>  		unsigned long user_count = vma_pages(vma);
>  		int count = PAGE_ALIGN(size) >> PAGE_SHIFT;
>  
>  		*ret = -ENXIO;
> -		if (off < count && user_count <= count - off) {
> -			unsigned long pfn = mem->pfn_base + start + off;
> +		if (pgoff_start < count && pgoff_end <= count) {
> +			unsigned long pfn = mem->pfn_base + start + pgoff_start;
>  			*ret = remap_pfn_range(vma, vma->vm_start, pfn,
>  					       user_count << PAGE_SHIFT,
>  					       vma->vm_page_prot);
> diff --git a/kernel/dma/direct.c b/kernel/dma/direct.c
> index 4391b797d4db..436310d6e4a2 100644
> --- a/kernel/dma/direct.c
> +++ b/kernel/dma/direct.c
> @@ -534,6 +534,8 @@ int dma_direct_mmap(struct device *dev, struct vm_area_struct *vma,
>  	unsigned long user_count = vma_pages(vma);
>  	unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT;
>  	unsigned long pfn = PHYS_PFN(dma_to_phys(dev, dma_addr));
> +	const pgoff_t pgoff_start = vma_start_pgoff(vma);
> +	const pgoff_t pgoff_end = vma_end_pgoff(vma);
>  	int ret = -ENXIO;
>  
>  	vma->vm_page_prot = dma_pgprot(dev, vma->vm_page_prot, attrs);
> @@ -545,9 +547,9 @@ int dma_direct_mmap(struct device *dev, struct vm_area_struct *vma,
>  	if (dma_mmap_from_global_coherent(vma, cpu_addr, size, &ret))
>  		return ret;
>  
> -	if (vma->vm_pgoff >= count || user_count > count - vma->vm_pgoff)
> +	if (pgoff_start >= count || pgoff_end > count)
>  		return -ENXIO;
> -	return remap_pfn_range(vma, vma->vm_start, pfn + vma->vm_pgoff,
> +	return remap_pfn_range(vma, vma->vm_start, pfn + pgoff_start,
>  			user_count << PAGE_SHIFT, vma->vm_page_prot);
>  }
>  
> diff --git a/kernel/dma/mapping.c b/kernel/dma/mapping.c
> index 4fe04669e5e6..c986639044e9 100644
> --- a/kernel/dma/mapping.c
> +++ b/kernel/dma/mapping.c
> @@ -761,12 +761,14 @@ EXPORT_SYMBOL_GPL(dma_free_pages);
>  int dma_mmap_pages(struct device *dev, struct vm_area_struct *vma,
>  		size_t size, struct page *page)
>  {
> -	unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT;
> +	const pgoff_t pgoff_start = vma_start_pgoff(vma);
> +	const pgoff_t pgoff_end = vma_end_pgoff(vma);
> +	const unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT;
>  
> -	if (vma->vm_pgoff >= count || vma_pages(vma) > count - vma->vm_pgoff)
> +	if (pgoff_start >= count || pgoff_end > count)
>  		return -ENXIO;
>  	return remap_pfn_range(vma, vma->vm_start,
> -			       page_to_pfn(page) + vma->vm_pgoff,
> +			       page_to_pfn(page) + pgoff_start,
>  			       vma_pages(vma) << PAGE_SHIFT, vma->vm_page_prot);
>  }
>  EXPORT_SYMBOL_GPL(dma_mmap_pages);
> diff --git a/kernel/dma/ops_helpers.c b/kernel/dma/ops_helpers.c
> index 20caf9cabf69..6b5f9208d31c 100644
> --- a/kernel/dma/ops_helpers.c
> +++ b/kernel/dma/ops_helpers.c
> @@ -39,7 +39,7 @@ int dma_common_mmap(struct device *dev, struct vm_area_struct *vma,
>  #ifdef CONFIG_MMU
>  	unsigned long user_count = vma_pages(vma);
>  	unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT;
> -	unsigned long off = vma->vm_pgoff;
> +	unsigned long off = vma_start_pgoff(vma);
>  	struct page *page = dma_common_vaddr_to_page(cpu_addr);
>  	int ret = -ENXIO;
>  
> @@ -52,7 +52,7 @@ int dma_common_mmap(struct device *dev, struct vm_area_struct *vma,
>  		return -ENXIO;
>  
>  	return remap_pfn_range(vma, vma->vm_start,
> -			page_to_pfn(page) + vma->vm_pgoff,
> +			page_to_pfn(page) + vma_start_pgoff(vma),
>  			user_count << PAGE_SHIFT, vma->vm_page_prot);
>  #else
>  	return -ENXIO;
> diff --git a/kernel/events/core.c b/kernel/events/core.c
> index 954c36e28101..d6d2d557ccb8 100644
> --- a/kernel/events/core.c
> +++ b/kernel/events/core.c
> @@ -6998,7 +6998,7 @@ static void perf_mmap_open(struct vm_area_struct *vma)
>  	refcount_inc(&event->mmap_count);
>  	refcount_inc(&event->rb->mmap_count);
>  
> -	if (vma->vm_pgoff)
> +	if (vma_start_pgoff(vma))
>  		refcount_inc(&event->rb->aux_mmap_count);
>  
>  	if (mapped)
> @@ -7032,7 +7032,7 @@ static void perf_mmap_close(struct vm_area_struct *vma)
>  	 * The AUX buffer is strictly a sub-buffer, serialize using aux_mutex
>  	 * to avoid complications.
>  	 */
> -	if (rb_has_aux(rb) && vma->vm_pgoff == rb->aux_pgoff &&
> +	if (rb_has_aux(rb) && vma_start_pgoff(vma) == rb->aux_pgoff &&
>  	    refcount_dec_and_mutex_lock(&rb->aux_mmap_count, &rb->aux_mutex)) {
>  		/*
>  		 * Stop all AUX events that are writing to this buffer,
> @@ -7190,7 +7190,8 @@ static int map_range(struct perf_buffer *rb, struct vm_area_struct *vma)
>  	 */
>  	for (pagenum = 0; pagenum < nr_pages; pagenum++) {
>  		unsigned long va = vma->vm_start + PAGE_SIZE * pagenum;
> -		struct page *page = perf_mmap_to_page(rb, vma->vm_pgoff + pagenum);
> +		struct page *page = perf_mmap_to_page(rb,
> +				vma_start_pgoff(vma) + pagenum);
>  
>  		if (page == NULL) {
>  			err = -EINVAL;
> @@ -7348,6 +7349,7 @@ static int perf_mmap_aux(struct vm_area_struct *vma, struct perf_event *event,
>  	u64 aux_offset, aux_size;
>  	struct perf_buffer *rb;
>  	int ret, rb_flags = 0;
> +	const pgoff_t pgoff_start = vma_start_pgoff(vma);
>  
>  	rb = event->rb;
>  	if (!rb)
> @@ -7366,11 +7368,11 @@ static int perf_mmap_aux(struct vm_area_struct *vma, struct perf_event *event,
>  	if (aux_offset < perf_data_size(rb) + PAGE_SIZE)
>  		return -EINVAL;
>  
> -	if (aux_offset != vma->vm_pgoff << PAGE_SHIFT)
> +	if (aux_offset != pgoff_start << PAGE_SHIFT)
>  		return -EINVAL;
>  
>  	/* already mapped with a different offset */
> -	if (rb_has_aux(rb) && rb->aux_pgoff != vma->vm_pgoff)
> +	if (rb_has_aux(rb) && rb->aux_pgoff != pgoff_start)
>  		return -EINVAL;
>  
>  	if (aux_size != nr_pages * PAGE_SIZE)
> @@ -7400,7 +7402,7 @@ static int perf_mmap_aux(struct vm_area_struct *vma, struct perf_event *event,
>  		if (vma->vm_flags & VM_WRITE)
>  			rb_flags |= RING_BUFFER_WRITABLE;
>  
> -		ret = rb_alloc_aux(rb, event, vma->vm_pgoff, nr_pages,
> +		ret = rb_alloc_aux(rb, event, pgoff_start, nr_pages,
>  				   event->attr.aux_watermark, rb_flags);
>  		if (ret) {
>  			refcount_dec(&rb->mmap_count);
> @@ -7457,7 +7459,7 @@ static int perf_mmap(struct file *file, struct vm_area_struct *vma)
>  		if (event->state <= PERF_EVENT_STATE_REVOKED)
>  			return -ENODEV;
>  
> -		if (vma->vm_pgoff == 0)
> +		if (!vma_start_pgoff(vma))
>  			ret = perf_mmap_rb(vma, event, nr_pages);
>  		else
>  			ret = perf_mmap_aux(vma, event, nr_pages);
> @@ -9884,7 +9886,7 @@ static bool perf_addr_filter_vma_adjust(struct perf_addr_filter *filter,
>  					struct perf_addr_filter_range *fr)
>  {
>  	unsigned long vma_size = vma->vm_end - vma->vm_start;
> -	unsigned long off = vma->vm_pgoff << PAGE_SHIFT;
> +	unsigned long off = vma_start_pgoff(vma) << PAGE_SHIFT;
>  	struct file *file = vma->vm_file;
>  
>  	if (!perf_addr_filter_match(filter, file, off, vma_size))
> @@ -9974,7 +9976,7 @@ void perf_event_mmap(struct vm_area_struct *vma)
>  			/* .tid */
>  			.start  = vma->vm_start,
>  			.len    = vma->vm_end - vma->vm_start,
> -			.pgoff  = (u64)vma->vm_pgoff << PAGE_SHIFT,
> +			.pgoff  = (u64)vma_start_pgoff(vma) << PAGE_SHIFT,
>  		},
>  		/* .maj (attr_mmap2 only) */
>  		/* .min (attr_mmap2 only) */
> diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
> index f23cebacbc6d..244651380ca1 100644
> --- a/kernel/events/uprobes.c
> +++ b/kernel/events/uprobes.c
> @@ -144,12 +144,14 @@ static bool valid_vma(struct vm_area_struct *vma, bool is_register)
>  
>  static unsigned long offset_to_vaddr(struct vm_area_struct *vma, loff_t offset)
>  {
> -	return vma->vm_start + offset - ((loff_t)vma->vm_pgoff << PAGE_SHIFT);
> +	return vma->vm_start + offset -
> +		((loff_t)vma_start_pgoff(vma) << PAGE_SHIFT);
>  }
>  
>  static loff_t vaddr_to_offset(struct vm_area_struct *vma, unsigned long vaddr)
>  {
> -	return ((loff_t)vma->vm_pgoff << PAGE_SHIFT) + (vaddr - vma->vm_start);
> +	return ((loff_t)vma_start_pgoff(vma) << PAGE_SHIFT) +
> +		(vaddr - vma->vm_start);
>  }
>  
>  /**
> @@ -1482,7 +1484,7 @@ static int unapply_uprobe(struct uprobe *uprobe, struct mm_struct *mm)
>  		    file_inode(vma->vm_file) != uprobe->inode)
>  			continue;
>  
> -		offset = (loff_t)vma->vm_pgoff << PAGE_SHIFT;
> +		offset = (loff_t)vma_start_pgoff(vma) << PAGE_SHIFT;
>  		if (uprobe->offset <  offset ||
>  		    uprobe->offset >= offset + vma->vm_end - vma->vm_start)
>  			continue;
> @@ -2453,7 +2455,8 @@ static struct uprobe *find_active_uprobe_speculative(unsigned long bp_vaddr)
>  	if (!vm_file)
>  		return NULL;
>  
> -	offset = (loff_t)(vma->vm_pgoff << PAGE_SHIFT) + (bp_vaddr - vma->vm_start);
> +	offset = (loff_t)(vma_start_pgoff(vma) << PAGE_SHIFT) +
> +		(bp_vaddr - vma->vm_start);
>  	uprobe = find_uprobe_rcu(vm_file->f_inode, offset);
>  	if (!uprobe)
>  		return NULL;
> diff --git a/kernel/kcov.c b/kernel/kcov.c
> index 1df373fb562b..b19b473c366a 100644
> --- a/kernel/kcov.c
> +++ b/kernel/kcov.c
> @@ -512,7 +512,7 @@ static int kcov_mmap(struct file *filep, struct vm_area_struct *vma)
>  
>  	spin_lock_irqsave(&kcov->lock, flags);
>  	size = kcov->size * sizeof(unsigned long);
> -	if (kcov->area == NULL || vma->vm_pgoff != 0 ||
> +	if (kcov->area == NULL || vma_start_pgoff(vma) ||
>  	    vma->vm_end - vma->vm_start != size) {
>  		res = -EINVAL;
>  		goto exit;
> diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
> index 56a328e94395..dfa493d54ef9 100644
> --- a/kernel/trace/ring_buffer.c
> +++ b/kernel/trace/ring_buffer.c
> @@ -7613,7 +7613,8 @@ static int __rb_inc_dec_mapped(struct ring_buffer_per_cpu *cpu_buffer,
>  static int __rb_map_vma(struct ring_buffer_per_cpu *cpu_buffer,
>  			struct vm_area_struct *vma)
>  {
> -	unsigned long nr_subbufs, nr_pages, nr_vma_pages, pgoff = vma->vm_pgoff;
> +	unsigned long nr_subbufs, nr_pages, nr_vma_pages;
> +	pgoff_t pgoff = vma_start_pgoff(vma);
>  	unsigned int subbuf_pages, subbuf_order;
>  	struct page **pages __free(kfree) = NULL;
>  	int p = 0, s = 0;

Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland


^ permalink raw reply

* Re: [PATCH] rtla: Also link in ctype.c
From: Tomas Glozar @ 2026-07-07 10:22 UTC (permalink / raw)
  To: Bastian Blank, Steven Rostedt, Tomas Glozar, linux-trace-kernel,
	linux-kernel
In-Reply-To: <ako2S4mzIqWwYuas@steamhammer.waldi.eu.org>

ne 5. 7. 2026 v 12:55 odesílatel Bastian Blank <waldi@debian.org> napsal:
>
> rtla started to only link parts of the tools library.  It now misses the
> ctype information used by all the related string operations.  Just add
> another single file to make it build again.
>
> Signed-off-by: Bastian Blank <waldi@debian.org>
> ---
>  tools/tracing/rtla/Makefile | 14 ++++++++++----
>  1 file changed, 10 insertions(+), 4 deletions(-)
>

Thank you. It appears that GCC LTO drops the symbol use of "_ctype",
so I didn't see it earlier. With removed -flto=auto from
Makefile.rtla, I can reproduce it:

 LINK    /linux-7.2-rc2/tools/tracing/rtla/rtla
/usr/bin/x86_64-linux-gnu-ld.bfd:
/linux-7.2-rc2/tools/tracing/rtla/lib/string.o: warning: relocation
against `_ctype' in read-only section `.text'
/usr/bin/x86_64-linux-gnu-ld.bfd:
/linux-7.2-rc2/tools/tracing/rtla/lib/string.o: in function
`skip_spaces':
/linux-7.2-rc2/tools/lib/string.c:126:(.text+0x14c): undefined
reference to `_ctype'
/usr/bin/x86_64-linux-gnu-ld.bfd:
/linux-7.2-rc2/tools/tracing/rtla/lib/string.o: in function `strim':
/linux-7.2-rc2/tools/lib/string.c:149:(.text+0x187): undefined
reference to `_ctype'
/usr/bin/x86_64-linux-gnu-ld.bfd: warning: creating DT_TEXTREL in a PIE
collect2: error: ld returned 1 exit status
make: *** [Makefile:121: /linux-7.2-rc2/tools/tracing/rtla/rtla] Error 1

> diff --git a/tools/tracing/rtla/Makefile b/tools/tracing/rtla/Makefile
> index 60a102538988..387bc6cc18f0 100644
> --- a/tools/tracing/rtla/Makefile
> +++ b/tools/tracing/rtla/Makefile
> @@ -45,6 +45,9 @@ else
>    LIB_OUTPUT = $(CURDIR)/lib
>  endif
>
> +LIB_CTYPE = $(LIB_OUTPUT)/ctype.o
> +LIB_CTYPE_SRC = $(srctree)/tools/lib/ctype.c
> +
>  LIB_STRING = $(LIB_OUTPUT)/string.o
>  LIB_STRING_SRC = $(srctree)/tools/lib/string.c
>
> @@ -117,12 +120,12 @@ tests/bpf/bpf_action_map.o: tests/bpf/bpf_action_map.c
>         $(Q)echo "BPF skeleton support is disabled, skipping tests/bpf/bpf_action_map.o"
>  endif
>
> -$(RTLA): $(RTLA_IN) $(LIBSUBCMD) $(LIB_STRING) $(LIB_STR_ERROR_R)
> -       $(QUIET_LINK)$(CC) $(LDFLAGS) -o $(RTLA) $(RTLA_IN) $(LIBSUBCMD) $(LIB_STRING) $(LIB_STR_ERROR_R) $(EXTLIBS)
> +$(RTLA): $(RTLA_IN) $(LIBSUBCMD) $(LIB_CTYPE) $(LIB_STRING) $(LIB_STR_ERROR_R)
> +       $(QUIET_LINK)$(CC) $(LDFLAGS) -o $(RTLA) $(RTLA_IN) $(LIBSUBCMD) $(LIB_CTYPE) $(LIB_STRING) $(LIB_STR_ERROR_R) $(EXTLIBS)
>
> -static: $(RTLA_IN) $(LIBSUBCMD) $(LIB_STRING) $(LIB_STR_ERROR_R)
> +static: $(RTLA_IN) $(LIBSUBCMD) $(LIB_CTYPE) $(LIB_STRING) $(LIB_STR_ERROR_R)
>         $(eval LDFLAGS += -static)
> -       $(QUIET_LINK)$(CC) -static $(LDFLAGS) -o $(RTLA)-static $(RTLA_IN) $(LIBSUBCMD) $(LIB_STRING) $(LIB_STR_ERROR_R) $(EXTLIBS)
> +       $(QUIET_LINK)$(CC) -static $(LDFLAGS) -o $(RTLA)-static $(RTLA_IN) $(LIBSUBCMD) $(LIB_CTYPE) $(LIB_STRING) $(LIB_STR_ERROR_R) $(EXTLIBS)
>
>  rtla.%: fixdep FORCE
>         make -f $(srctree)/tools/build/Makefile.build dir=. $@
> @@ -150,6 +153,9 @@ $(LIB_STR_ERROR_R): $(LIB_STR_ERROR_R_SRC) | $(LIB_OUTPUT)
>  $(LIB_STRING): $(LIB_STRING_SRC) | $(LIB_OUTPUT)
>         $(QUIET_CC)$(CC) $(CFLAGS) -c -o $@ $<
>
> +$(LIB_CTYPE): $(LIB_CTYPE_SRC) | $(LIB_OUTPUT)
> +       $(QUIET_CC)$(CC) $(CFLAGS) -c -o $@ $<
> +
>  libsubcmd-clean:
>         $(call QUIET_CLEAN, libsubcmd)
>         $(Q)$(RM) -r -- $(LIBSUBCMD_OUTPUT)
> --
> 2.53.0
>

The list of libraries is getting a bit long. Maybe it's time to
collapse it into one variable in a future release.

Anyway, I'll take this and attach:

Fixes: 48209d763c22 ("rtla: Add libsubcmd dependency")

Tomas


^ permalink raw reply

* Re: [PATCH 21/30] mm/vma: add and use vma_[add/sub]_pgoff()
From: Lorenzo Stoakes @ 2026-07-07 10:22 UTC (permalink / raw)
  To: Pedro Falcato
  Cc: Andrew Morton, Russell King, Dinh Nguyen, Simon Schuster,
	James E . J . Bottomley, Helge Deller, Jarkko Sakkinen,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
	Ian Abbott, H Hartley Sweeten, Lucas Stach, David Airlie,
	Simona Vetter, Patrik Jakobsson, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, Rob Clark, Dmitry Baryshkov, Tomi Valkeinen,
	Thierry Reding, Mikko Perttunen, Jonathan Hunter,
	Christian Koenig, Huang Rui, Ankit Agrawal, Alex Williamson,
	Alexander Viro, Christian Brauner, Dan Williams, Muchun Song,
	Oscar Salvador, David Hildenbrand, Suren Baghdasaryan,
	Liam R . Howlett, Matthew Wilcox, Marek Szyprowski,
	Peter Zijlstra, Arnaldo Carvalho de Melo, Namhyung Kim,
	Masami Hiramatsu, Oleg Nesterov, Steven Rostedt, SeongJae Park,
	Miaohe Lin, Hugh Dickins, Mike Rapoport, Kees Cook, Paolo Bonzini,
	linux-kernel, linux-arm-kernel, linux-parisc, linux-sgx, etnaviv,
	dri-devel, linux-arm-msm, freedreno, linux-tegra, kvm,
	linux-fsdevel, nvdimm, linux-mm, iommu, linux-perf-users,
	linux-trace-kernel, kasan-dev, damon, Rik van Riel, Harry Yoo,
	Jann Horn
In-Reply-To: <akZI0n1U32Ptd0ye@pedro-suse.lan>

On Thu, Jul 02, 2026 at 12:20:10PM +0100, Pedro Falcato wrote:
> On Mon, Jun 29, 2026 at 01:23:32PM +0100, Lorenzo Stoakes wrote:
> > Add helpers for adding or subtracting to a VMA's page offset, exposed
> > internally for VMA users within mm in mm/vma.h.
> >
> > This is to lay the foundations for tracking anonymous page offset for
> > MAP_PRIVATE file-backed mappings, where adding and subtracting from this
> > value must be reflected in both the file and anonymous offsets.
> >
> > These are used on VMA split and downward stack expansion.
> >
> > No functional change intended.
> >
> > Signed-off-by: Lorenzo Stoakes <ljs@kernel.org>
> > ---
> >  mm/nommu.c                      |  6 ++++--
> >  mm/vma.c                        |  6 +++---
> >  mm/vma.h                        | 12 ++++++++++++
> >  tools/testing/vma/include/dup.h | 13 ++++++++++++-
> >  4 files changed, 31 insertions(+), 6 deletions(-)
> >
> > diff --git a/mm/nommu.c b/mm/nommu.c
> > index 7333d855e974..c7fafcd87c14 100644
> > --- a/mm/nommu.c
> > +++ b/mm/nommu.c
> > @@ -41,6 +41,7 @@
> >  #include <asm/tlbflush.h>
> >  #include <asm/mmu_context.h>
> >  #include "internal.h"
> > +#include "vma.h"
> >
> >  unsigned long highest_memmap_pfn;
> >  int heap_stack_gap = 0;
> > @@ -1338,7 +1339,8 @@ static int split_vma(struct vma_iterator *vmi, struct vm_area_struct *vma,
> >  		region->vm_top = region->vm_end = new->vm_end = addr;
> >  	} else {
> >  		region->vm_start = new->vm_start = addr;
> > -		region->vm_pgoff = new->vm_pgoff += npages;
> > +		vma_add_pgoff(new, npages);
> > +		region->vm_pgoff = vma_start_pgoff(new);
> >  	}
> >
> >  	vma_iter_config(vmi, new->vm_start, new->vm_end);
> > @@ -1355,7 +1357,7 @@ static int split_vma(struct vma_iterator *vmi, struct vm_area_struct *vma,
> >  	delete_nommu_region(vma->vm_region);
> >  	if (new_below) {
> >  		vma->vm_region->vm_start = vma->vm_start = addr;
> > -		vma->vm_pgoff += npages;
> > +		vma_add_pgoff(vma, npages);
> >  		vma->vm_region->vm_pgoff = vma_start_pgoff(vma);
> >  	} else {
> >  		vma->vm_region->vm_end = vma->vm_end = addr;
> > diff --git a/mm/vma.c b/mm/vma.c
> > index 185d07397ca6..cb7222e20c93 100644
> > --- a/mm/vma.c
> > +++ b/mm/vma.c
> > @@ -517,7 +517,7 @@ __split_vma(struct vma_iterator *vmi, struct vm_area_struct *vma,
> >  		new->vm_end = addr;
> >  	} else {
> >  		new->vm_start = addr;
> > -		new->vm_pgoff += linear_page_delta(vma, addr);
> > +		vma_add_pgoff(new, linear_page_delta(vma, addr));
> >  	}
> >
> >  	err = -ENOMEM;
> > @@ -556,7 +556,7 @@ __split_vma(struct vma_iterator *vmi, struct vm_area_struct *vma,
> >
> >  	if (new_below) {
> >  		vma->vm_start = addr;
> > -		vma->vm_pgoff += (addr - new->vm_start) >> PAGE_SHIFT;
> > +		vma_add_pgoff(vma, (addr - new->vm_start) >> PAGE_SHIFT);
> >  	} else {
> >  		vma->vm_end = addr;
> >  	}
> > @@ -3305,7 +3305,7 @@ int expand_downwards(struct vm_area_struct *vma, unsigned long address)
> >  				vm_stat_account(mm, vma->vm_flags, grow);
> >  				anon_vma_interval_tree_pre_update_vma(vma);
> >  				vma->vm_start = address;
> > -				vma->vm_pgoff -= grow;
> > +				vma_sub_pgoff(vma, grow);
> >  				/* Overwrite old entry in mtree. */
> >  				vma_iter_store_overwrite(&vmi, vma);
> >  				anon_vma_interval_tree_post_update_vma(vma);
> > diff --git a/mm/vma.h b/mm/vma.h
> > index 2342516ce00e..47fe35e5307e 100644
> > --- a/mm/vma.h
> > +++ b/mm/vma.h
> > @@ -247,6 +247,18 @@ static inline pgoff_t vmg_end_pgoff(const struct vma_merge_struct *vmg)
> >  	return vmg_start_pgoff(vmg) + vmg_pages(vmg);
> >  }
> >
> > +static inline void vma_add_pgoff(struct vm_area_struct *vma, pgoff_t delta)
> > +{
> > +	vma_assert_can_modify(vma);
> > +	vma->vm_pgoff += delta;
> > +}
> > +
> > +static inline void vma_sub_pgoff(struct vm_area_struct *vma, pgoff_t delta)
> > +{
> > +	vma_assert_can_modify(vma);
> > +	vma->vm_pgoff -= delta;
> > +}
> > +
> >  #define VMG_STATE(name, mm_, vmi_, start_, end_, vma_flags_, pgoff_)	\
> >  	struct vma_merge_struct name = {				\
> >  		.mm = mm_,						\
> > diff --git a/tools/testing/vma/include/dup.h b/tools/testing/vma/include/dup.h
> > index 7ed165c8d9bc..41fea90a344d 100644
> > --- a/tools/testing/vma/include/dup.h
> > +++ b/tools/testing/vma/include/dup.h
> > @@ -1163,6 +1163,11 @@ static inline struct vm_area_struct *vma_next(struct vma_iterator *vmi)
> >  	return mas_find(&vmi->mas, ULONG_MAX);
> >  }
> >
> > +static inline bool vma_is_attached(struct vm_area_struct *vma)
> > +{
> > +	return refcount_read(&vma->vm_refcnt);
> > +}
> > +
> >  /*
> >   * WARNING: to avoid racing with vma_mark_attached()/vma_mark_detached(), these
> >   * assertions should be made either under mmap_write_lock or when the object
> > @@ -1170,7 +1175,13 @@ static inline struct vm_area_struct *vma_next(struct vma_iterator *vmi)
> >   */
> >  static inline void vma_assert_attached(struct vm_area_struct *vma)
> >  {
> > -	WARN_ON_ONCE(!refcount_read(&vma->vm_refcnt));
> > +	WARN_ON_ONCE(!vma_is_attached(vma));
> > +}
> > +
> > +static inline void vma_assert_can_modify(struct vm_area_struct *vma)
> > +{
> > +	if (vma_is_attached(vma))
> > +		vma_assert_write_locked(vma);
> >  }
>
> These hunks in dup.h look lost. Should perhaps be on the previous patch
> (adding the helpers).

Yeah, it's because the VMA code starts actually using them in a way that
otherwise breaks the tests at this point, but you're right, functionally it'd be
nicer to add them at the point they're introduced.

Will fix that up on respin!

>
> Anyway, Obviously Correct(tm).
>
> Reviewed-by: Pedro Falcato <pfalcato@suse.de>

Thanks!

>
> --
> Pedro

Cheers, Lorenzo

^ permalink raw reply

* Re: [PATCH 22/30] mm/vma: move __install_special_mapping() to vma.c
From: Lorenzo Stoakes @ 2026-07-07 10:31 UTC (permalink / raw)
  To: Pedro Falcato
  Cc: Andrew Morton, Russell King, Dinh Nguyen, Simon Schuster,
	James E . J . Bottomley, Helge Deller, Jarkko Sakkinen,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
	Ian Abbott, H Hartley Sweeten, Lucas Stach, David Airlie,
	Simona Vetter, Patrik Jakobsson, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, Rob Clark, Dmitry Baryshkov, Tomi Valkeinen,
	Thierry Reding, Mikko Perttunen, Jonathan Hunter,
	Christian Koenig, Huang Rui, Ankit Agrawal, Alex Williamson,
	Alexander Viro, Christian Brauner, Dan Williams, Muchun Song,
	Oscar Salvador, David Hildenbrand, Suren Baghdasaryan,
	Liam R . Howlett, Matthew Wilcox, Marek Szyprowski,
	Peter Zijlstra, Arnaldo Carvalho de Melo, Namhyung Kim,
	Masami Hiramatsu, Oleg Nesterov, Steven Rostedt, SeongJae Park,
	Miaohe Lin, Hugh Dickins, Mike Rapoport, Kees Cook, Paolo Bonzini,
	linux-kernel, linux-arm-kernel, linux-parisc, linux-sgx, etnaviv,
	dri-devel, linux-arm-msm, freedreno, linux-tegra, kvm,
	linux-fsdevel, nvdimm, linux-mm, iommu, linux-perf-users,
	linux-trace-kernel, kasan-dev, damon, Rik van Riel, Harry Yoo,
	Jann Horn
In-Reply-To: <akZJjNic8u0pDxgD@pedro-suse.lan>

On Thu, Jul 02, 2026 at 12:22:56PM +0100, Pedro Falcato wrote:
> On Mon, Jun 29, 2026 at 01:23:33PM +0100, Lorenzo Stoakes wrote:
> > This function is operating on VMAs and rightly belongs in vma.c, where it
> > can be subject to VMA userland testing and allows us to isolate it from the
> > rest of mm.
> >
> > The _install_special_mapping() function will remain in mmap.c as a wrapper,
> > since this is used by architecture-specific code.
> >
> > Doing so allows us to isolate more functions in vma.c for the same reasons.
> >
> > This forms part of work to allow for tracking MAP_PRIVATE file-backed
> > mappings by their anonymous virtual page offset, as doing so allows us to
> > isolate and keep code that interacts with this together.
> >
> > No functional change intended.
> >
> > Signed-off-by: Lorenzo Stoakes <ljs@kernel.org>
> > ---
> >  mm/mmap.c | 38 --------------------------------------
> >  mm/vma.c  | 38 ++++++++++++++++++++++++++++++++++++++
> >  mm/vma.h  |  5 +++++
> >  3 files changed, 43 insertions(+), 38 deletions(-)
> >
> > diff --git a/mm/mmap.c b/mm/mmap.c
> > index 2d09a57e3620..46174e706bbe 100644
> > --- a/mm/mmap.c
> > +++ b/mm/mmap.c
> > @@ -1447,44 +1447,6 @@ static vm_fault_t special_mapping_fault(struct vm_fault *vmf)
> >  	return VM_FAULT_SIGBUS;
> >  }
> >
> > -static struct vm_area_struct *__install_special_mapping(
> > -	struct mm_struct *mm,
> > -	unsigned long addr, unsigned long len,
> > -	vm_flags_t vm_flags, void *priv,
> > -	const struct vm_operations_struct *ops)
> > -{
> > -	int ret;
> > -	struct vm_area_struct *vma;
> > -
> > -	vma = vm_area_alloc(mm);
> > -	if (unlikely(vma == NULL))
> > -		return ERR_PTR(-ENOMEM);
> > -
> > -	vma_set_range(vma, addr, addr + len, 0);
> > -	vm_flags |= mm->def_flags | VM_DONTEXPAND;
> > -	if (pgtable_supports_soft_dirty())
> > -		vm_flags |= VM_SOFTDIRTY;
> > -	vm_flags_init(vma, vm_flags & ~VM_LOCKED_MASK);
> > -	vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
> > -
> > -	vma->vm_ops = ops;
> > -	vma->vm_private_data = priv;
> > -
> > -	ret = insert_vm_struct(mm, vma);
> > -	if (ret)
> > -		goto out;
> > -
> > -	vm_stat_account(mm, vma->vm_flags, len >> PAGE_SHIFT);
> > -
> > -	perf_event_mmap(vma);
> > -
> > -	return vma;
> > -
> > -out:
> > -	vm_area_free(vma);
> > -	return ERR_PTR(ret);
> > -}
> > -
> >  bool vma_is_special_mapping(const struct vm_area_struct *vma,
> >  	const struct vm_special_mapping *sm)
> >  {
> > diff --git a/mm/vma.c b/mm/vma.c
> > index cb7222e20c93..f4de706a2728 100644
> > --- a/mm/vma.c
> > +++ b/mm/vma.c
> > @@ -3399,3 +3399,41 @@ __weak unsigned long vma_mmu_pagesize(struct vm_area_struct *vma)
> >  {
> >  	return vma_kernel_pagesize(vma);
> >  }
> > +
> > +struct vm_area_struct *__install_special_mapping(
> > +	struct mm_struct *mm,
> > +	unsigned long addr, unsigned long len,
> > +	vm_flags_t vm_flags, void *priv,
> > +	const struct vm_operations_struct *ops)
> > +{
> > +	int ret;
> > +	struct vm_area_struct *vma;
> > +
> > +	vma = vm_area_alloc(mm);
> > +	if (unlikely(vma == NULL))
> > +		return ERR_PTR(-ENOMEM);
> > +
> > +	vma_set_range(vma, addr, addr + len, 0);
> > +	vm_flags |= mm->def_flags | VM_DONTEXPAND;
> > +	if (pgtable_supports_soft_dirty())
> > +		vm_flags |= VM_SOFTDIRTY;
> > +	vm_flags_init(vma, vm_flags & ~VM_LOCKED_MASK);
> > +	vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
> > +
> > +	vma->vm_ops = ops;
> > +	vma->vm_private_data = priv;
> > +
> > +	ret = insert_vm_struct(mm, vma);
> > +	if (ret)
> > +		goto out;
> > +
> > +	vm_stat_account(mm, vma->vm_flags, len >> PAGE_SHIFT);
> > +
> > +	perf_event_mmap(vma);
> > +
> > +	return vma;
> > +
> > +out:
> > +	vm_area_free(vma);
> > +	return ERR_PTR(ret);
> > +}
> > diff --git a/mm/vma.h b/mm/vma.h
> > index 47fe35e5307e..14f026bf3be4 100644
> > --- a/mm/vma.h
> > +++ b/mm/vma.h
> > @@ -775,4 +775,9 @@ static inline bool map_deny_write_exec(const vma_flags_t *old,
> >  }
> >  #endif
> >
> > +struct vm_area_struct *__install_special_mapping(struct mm_struct *mm,
> > +		unsigned long addr, unsigned long len,
> > +		vm_flags_t vm_flags, void *priv,
> > +		const struct vm_operations_struct *ops);
> > +
> >  #endif	/* __MM_VMA_H */
>
> I'm really annoyed that _install_special_mapping has a leading underscore.
> That's it.

Yeah it's horrible :)

>
> Reviewed-by: Pedro Falcato <pfalcato@suse.de>

Thanks!

>
> --
> Pedro

Cheers, Lorenzo

^ permalink raw reply

* Re: [PATCH 25/30] mm/vma: update vmg_adjust_set_range() to offset pgoff instead
From: Lorenzo Stoakes @ 2026-07-07 10:35 UTC (permalink / raw)
  To: Pedro Falcato
  Cc: Andrew Morton, Russell King, Dinh Nguyen, Simon Schuster,
	James E . J . Bottomley, Helge Deller, Jarkko Sakkinen,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
	Ian Abbott, H Hartley Sweeten, Lucas Stach, David Airlie,
	Simona Vetter, Patrik Jakobsson, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, Rob Clark, Dmitry Baryshkov, Tomi Valkeinen,
	Thierry Reding, Mikko Perttunen, Jonathan Hunter,
	Christian Koenig, Huang Rui, Ankit Agrawal, Alex Williamson,
	Alexander Viro, Christian Brauner, Dan Williams, Muchun Song,
	Oscar Salvador, David Hildenbrand, Suren Baghdasaryan,
	Liam R . Howlett, Matthew Wilcox, Marek Szyprowski,
	Peter Zijlstra, Arnaldo Carvalho de Melo, Namhyung Kim,
	Masami Hiramatsu, Oleg Nesterov, Steven Rostedt, SeongJae Park,
	Miaohe Lin, Hugh Dickins, Mike Rapoport, Kees Cook, Paolo Bonzini,
	linux-kernel, linux-arm-kernel, linux-parisc, linux-sgx, etnaviv,
	dri-devel, linux-arm-msm, freedreno, linux-tegra, kvm,
	linux-fsdevel, nvdimm, linux-mm, iommu, linux-perf-users,
	linux-trace-kernel, kasan-dev, damon, Rik van Riel, Harry Yoo,
	Jann Horn
In-Reply-To: <akZLhkjsJ_3sGdox@pedro-suse.lan>

On Thu, Jul 02, 2026 at 12:29:54PM +0100, Pedro Falcato wrote:
> On Mon, Jun 29, 2026 at 01:23:36PM +0100, Lorenzo Stoakes wrote:
> > We are calculating the pgoff as an offset, since we have vma_add_pgoff()
> > and vma_sub_pgoff() available, just offset this value directly and use
> > __vma_set_range() for vma->vm_[start, end] values.
> >
> > We take care to update the range before offsetting the page offset, so the
> > adjusted VMA's vm_start and vm_pgoff are mutually consistent at the point
> > the page offset helpers operate - this matters once vma_set_pgoff() comes
> > to assert invariants which relate the two.
> >
> > Doing so lays the foundation for future work which allows for use of
> > virtual page offsets for MAP_PRIVATE-file backed mappings.
> >
> > No functional change intended.
> >
> > Signed-off-by: Lorenzo Stoakes <ljs@kernel.org>
> > ---
> >  mm/vma.c | 15 ++++-----------
> >  1 file changed, 4 insertions(+), 11 deletions(-)
> >
> > diff --git a/mm/vma.c b/mm/vma.c
> > index e3355eab11f2..0579fc8c9bd5 100644
> > --- a/mm/vma.c
> > +++ b/mm/vma.c
> > @@ -714,9 +714,6 @@ void validate_mm(struct mm_struct *mm)
> >   */
> >  static void vmg_adjust_set_range(struct vma_merge_struct *vmg)
> >  {
> > -	struct vm_area_struct *adjust;
> > -	pgoff_t pgoff;
> > -
> >  	if (vmg->__adjust_middle_start) {
> >  		/*
> >  		 * vmg->start    vmg->end
> > @@ -735,8 +732,8 @@ static void vmg_adjust_set_range(struct vma_merge_struct *vmg)
> >  		struct vm_area_struct *middle = vmg->middle;
> >  		const unsigned long delta = vmg->end - middle->vm_start;
> >
> > -		pgoff = vma_start_pgoff(middle) + (delta >> PAGE_SHIFT);
> > -		adjust = middle;
> > +		__vma_set_range(middle, vmg->end, middle->vm_end);
> > +		vma_add_pgoff(middle, delta >> PAGE_SHIFT);
> >  	} else if (vmg->__adjust_next_start) {
> >  		/*
> >  		 *                Originally:
> > @@ -764,13 +761,9 @@ static void vmg_adjust_set_range(struct vma_merge_struct *vmg)
> >  		struct vm_area_struct *next = vmg->next;
> >  		const unsigned long delta = next->vm_start - vmg->end;
> >
> > -		pgoff = vma_start_pgoff(next) - (delta >> PAGE_SHIFT);
> > -		adjust = next;
> > -	} else {
> > -		return;
> > +		__vma_set_range(next, vmg->end, next->vm_end);
> > +		vma_sub_pgoff(next, delta >> PAGE_SHIFT);
> >  	}
> > -
> > -	vma_set_range(adjust, vmg->end, adjust->vm_end, pgoff);
> >  }
>
> Maybe this should be squashed with That Other Patch that touches this.

Ah this separation makes more sense from the point of view of the virt pgoff
stuff in the RFC (see [0]).

And would rather keep as vaguely bitesized as possible :>)

>
> Anyway,
>
> Reviewed-by: Pedro Falcato <pfalcato@suse.de>

Thanks!

>
> --
> Pedro

Cheers, Lorenzo

[0]:https://lore.kernel.org/linux-mm/cover.1782745153.git.ljs@kernel.org/

^ permalink raw reply

* Re: [PATCH 27/30] mm/vma: correct incorrect vma.h inclusion
From: Lorenzo Stoakes @ 2026-07-07 10:41 UTC (permalink / raw)
  To: Pedro Falcato
  Cc: Andrew Morton, Russell King, Dinh Nguyen, Simon Schuster,
	James E . J . Bottomley, Helge Deller, Jarkko Sakkinen,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
	Ian Abbott, H Hartley Sweeten, Lucas Stach, David Airlie,
	Simona Vetter, Patrik Jakobsson, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, Rob Clark, Dmitry Baryshkov, Tomi Valkeinen,
	Thierry Reding, Mikko Perttunen, Jonathan Hunter,
	Christian Koenig, Huang Rui, Ankit Agrawal, Alex Williamson,
	Alexander Viro, Christian Brauner, Dan Williams, Muchun Song,
	Oscar Salvador, David Hildenbrand, Suren Baghdasaryan,
	Liam R . Howlett, Matthew Wilcox, Marek Szyprowski,
	Peter Zijlstra, Arnaldo Carvalho de Melo, Namhyung Kim,
	Masami Hiramatsu, Oleg Nesterov, Steven Rostedt, SeongJae Park,
	Miaohe Lin, Hugh Dickins, Mike Rapoport, Kees Cook, Paolo Bonzini,
	linux-kernel, linux-arm-kernel, linux-parisc, linux-sgx, etnaviv,
	dri-devel, linux-arm-msm, freedreno, linux-tegra, kvm,
	linux-fsdevel, nvdimm, linux-mm, iommu, linux-perf-users,
	linux-trace-kernel, kasan-dev, damon, Rik van Riel, Harry Yoo,
	Jann Horn
In-Reply-To: <akZNiN5Y9fPk8bZH@pedro-suse.lan>

On Thu, Jul 02, 2026 at 12:40:30PM +0100, Pedro Falcato wrote:
> On Mon, Jun 29, 2026 at 01:23:38PM +0100, Lorenzo Stoakes wrote:
> > The only files which should be including vma.h are the implementation files
> > for the core VMA logic - vma.c, vma_init.c, and vma_exec.c.
> >
> > This is in order to allow for userland testing of core VMA logic. In this
> > cases, vma_internal.h and vma.h are included, providing both the
> > dependencies upon which the core VMA logic requires and its declarations.
> >
> > Userland testable VMA logic is achieved by having separate vma_internal.h
> > implementations for userland and kernel.
> >
> > Callers other than the core VMA implementation should include internal.h
> > instead. This header does not need to include vma_internal.h as it only
> > contains the vma.h declarations, for which the includes already present
> > suffice.
> >
> > Update code to reflect this, update comments to reflect the fact there are
> > 3 VMA implementation files and document things more clearly.
> >
> > While we're here, slightly improve the language of the comment describing
> > vma_exec.c.
>
> Two random thoughts:
> 1) perhaps vma.h -> vma_private.h

Not a bad idea thanks!

> 2) https://lore.kernel.org/all/CAHk-=wghMm2c+AYEcwYY7drSVXB27DYqc-ZXpFiq=XFs-w59wA@mail.gmail.com/
>    mm/vma/whatever.c :) would PROBABLY solve the issue of people snooping vma.h

I think a vma/ subdir would probably confuse things further, I think renaming to
vma_private.h neatly solves it actually, along with a comment maybe in the
header itself?

Then again mm/vma/{vma.c,init.c, exec.c, private.h} isn't too crazy
either. Though vma.h is the actual 'shared' bit, and vma_internal.h is the
private bit that the userland changes. But could switch things around vma.h ->
mm/vma/internal.h that mm/internal.h imports, and mm/vma_internal.h becomes
mm/vma/private.h.

I think that could work but definitely a follow-up!

>
> >
> > No functional change intended.
> >
> > Signed-off-by: Lorenzo Stoakes <ljs@kernel.org>
>
> Reviewed-by: Pedro Falcato <pfalcato@suse.de>

Thanks!

Cheers, Lorenzo

^ permalink raw reply

* Re: [PATCH 29/30] tools/testing/vma: default VMA flag bits to 64-bit
From: Lorenzo Stoakes @ 2026-07-07 10:47 UTC (permalink / raw)
  To: Pedro Falcato
  Cc: Andrew Morton, Russell King, Dinh Nguyen, Simon Schuster,
	James E . J . Bottomley, Helge Deller, Jarkko Sakkinen,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
	Ian Abbott, H Hartley Sweeten, Lucas Stach, David Airlie,
	Simona Vetter, Patrik Jakobsson, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, Rob Clark, Dmitry Baryshkov, Tomi Valkeinen,
	Thierry Reding, Mikko Perttunen, Jonathan Hunter,
	Christian Koenig, Huang Rui, Ankit Agrawal, Alex Williamson,
	Alexander Viro, Christian Brauner, Dan Williams, Muchun Song,
	Oscar Salvador, David Hildenbrand, Suren Baghdasaryan,
	Liam R . Howlett, Matthew Wilcox, Marek Szyprowski,
	Peter Zijlstra, Arnaldo Carvalho de Melo, Namhyung Kim,
	Masami Hiramatsu, Oleg Nesterov, Steven Rostedt, SeongJae Park,
	Miaohe Lin, Hugh Dickins, Mike Rapoport, Kees Cook, Paolo Bonzini,
	linux-kernel, linux-arm-kernel, linux-parisc, linux-sgx, etnaviv,
	dri-devel, linux-arm-msm, freedreno, linux-tegra, kvm,
	linux-fsdevel, nvdimm, linux-mm, iommu, linux-perf-users,
	linux-trace-kernel, kasan-dev, damon, Rik van Riel, Harry Yoo,
	Jann Horn
In-Reply-To: <akZO3xI4Lt1iSbms@pedro-suse.lan>

On Thu, Jul 02, 2026 at 12:44:21PM +0100, Pedro Falcato wrote:
> On Mon, Jun 29, 2026 at 01:23:40PM +0100, Lorenzo Stoakes wrote:
> > With all of the sanitisers turned on, setting the VMA flag bits depth to
> > 128 by default results in overly long build times.
> >
> > Reduce this to 64 - we can always manipulate these later for testing of
> > larger bitmaps as needed.
> >
>
> Hmm, what's the problem with the sanitizers? Shouldn't this just result in
> slightly different codegen?

I'm not sure but it results in vastly longer build times. It was a fun idea but
it partly defeats the point of the VMA userland tests.

Rather than spend too long investigating I'd rather we move to a sane default.

>
> > Signed-off-by: Lorenzo Stoakes <ljs@kernel.org>
> > ---
> >  tools/testing/vma/Makefile | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/tools/testing/vma/Makefile b/tools/testing/vma/Makefile
> > index e72b45dedda5..ef6cc558afe1 100644
> > --- a/tools/testing/vma/Makefile
> > +++ b/tools/testing/vma/Makefile
> > @@ -10,7 +10,7 @@ OFILES = $(SHARED_OFILES) main.o shared.o maple-shim.o
> >  TARGETS = vma
> >
> >  # These can be varied to test different sizes.
> > -CFLAGS += -DNUM_VMA_FLAG_BITS=128 -DNUM_MM_FLAG_BITS=128
> > +CFLAGS += -DNUM_VMA_FLAG_BITS=64 -DNUM_MM_FLAG_BITS=64
> >
> >  main.o: main.c shared.c shared.h vma_internal.h tests/merge.c tests/mmap.c tests/vma.c ../../../mm/vma.c ../../../mm/vma_init.c ../../../mm/vma_exec.c ../../../mm/vma.h include/custom.h include/dup.h include/stubs.h
> >
> > --
> > 2.54.0
> >
>
> --
> Pedro

Thanks, Lorenzo

^ permalink raw reply

* Re: [PATCH v3 04/11] arm64/mm: Add set_memory_device() and set_memory_normal()
From: Will Deacon @ 2026-07-07 11:27 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Jonathan Hunter,
	David Airlie, Simona Vetter, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, Sowjanya Komatineni, Luca Ceresoli,
	Mikko Perttunen, Yury Norov, Rasmus Villemoes, Russell King,
	Alexander Gordeev, Gerald Schaefer, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Sven Schnelle, Andrew Morton,
	David Hildenbrand, Lorenzo Stoakes, Liam R. Howlett,
	Vlastimil Babka, Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
	Marek Szyprowski, Robin Murphy, Sumit Semwal, Benjamin Gaignard,
	Brian Starkey, John Stultz, T.J. Mercier, Christian König,
	Steven Rostedt, Masami Hiramatsu, Mathieu Desnoyers,
	Catalin Marinas, Thierry Reding, devicetree, linux-tegra,
	linux-kernel, dri-devel, linux-media, linux-arm-kernel,
	linux-s390, linux-mm, iommu, linaro-mm-sig, linux-trace-kernel,
	Thierry Reding, Chun Ng
In-Reply-To: <akuvyu1Pq0ZVMZV0@orome>

On Mon, Jul 06, 2026 at 03:49:24PM +0200, Thierry Reding wrote:
> On Fri, Jul 03, 2026 at 06:13:31PM +0100, Will Deacon wrote:
> > On Thu, Jul 02, 2026 at 06:41:23PM +0200, Thierry Reding wrote:
> > > On Thu, Jul 02, 2026 at 03:46:44PM +0200, Thierry Reding wrote:
> > > > On Thu, Jul 02, 2026 at 10:18:47AM +0100, Will Deacon wrote:
> > > > > On Wed, Jul 01, 2026 at 06:08:15PM +0200, Thierry Reding wrote:
> > > > > > From: Chun Ng <chunn@nvidia.com>
> > > > > > 
> > > > > > Add helpers to swap PROT_NORMAL and PROT_DEVICE_nGnRnE protection bits
> > > > > > on a kernel-linear-map range.
> > > > > 
> > > > > That sounds like a really terrible idea. Why is this necessary and how
> > > > > does it interact with things like load_unaligned_zeropad()?
> > > > 
> > > > This is necessary because once the memory controller has walled off the
> > > > new memory region the CPU must not access it under any circumstances or
> > > > it'll cause the CPU to lock up (I think technically it'll hit an SError
> > > > but in practice that just means it'll freeze, as far as I can tell).
> > > > 
> > > > Probably doesn't interact well at all with load_unaligned_zeropad().
> > > > 
> > > > > I think you should unmap the memory from the linear map and memremap()
> > > > > it instead.
> > > > 
> > > > Given that the memory can never be accessed by the CPU after the memory
> > > > controller locks it down, I don't think we'll even need memremap(). The
> > > > only thing we really need is the sg_table we hand out via the DMA BUFs
> > > > so that they can be used by device drivers to program their DMA engines
> > > > internally.
> > > > 
> > > > Looking through some of the architecture code around this, shouldn't we
> > > > simply be using set_memory_encrypted() and set_memory_decrypted() for
> > > > this? While they might've been created for slightly other use-cases,
> > > > they seem to be doing exactly what we want (i.e. remove the page range
> > > > from the linear mapping and flushing it, or restoring the valid bit and
> > > > standard permissions, respectively).
> > > 
> > > Ah... I guess we can't do it because we're not in a realm world and so
> > > the early checks in __set_memory_enc_dec() would return early and turn
> > > it into a no-op.
> > > 
> > > How about if I extract a common helper and provide set_memory_p() and
> > > set_memory_np() in terms of those. Those are available on x86 and
> > > PowerPC as well, so fairly standard. I suppose at that point we're
> > > closer to set_memory_valid().
> > 
> > Why not just call set_direct_map_invalid_noflush() +
> > flush_tlb_kernel_range() for each page? We already have APIs for this.
> 
> Having a "standard" helper with a fixed and documented purposed seemed
> like a preferable approach for this particular case. We also may want to
> make the driver that uses this buildable as a module, in which case we'd
> need to export these rather low-level APIs. And then there's also the
> fact that we typically call this on a rather large region of memory
> (usually something like 512 MiB), so doing it page-by-page is rather
> suboptimal.
> 
> > The big challenge I see with any linear map manipulation, however, is
> > that it will rely on can_set_direct_map() which likely means you need to
> > give up some performance and/or security to make this work. Does memory
> > become inaccesible dynamically at runtime? If not, the best bet would
> > be to describe it as a carveout in the DT and mark it as "no-map" so
> > we avoid mapping it in the first place.
> 
> VPR exists in two modes: static and resizable. For static VPR we do
> exactly that: describe it as carveout in DT with no-map and deal with it
> accordingly in the driver. Resizable VPR is for device that have small
> amounts of RAM. Content-protected video playback will in the worst case
> consume around 1.8 GiB of RAM, so we want to be able to reuse for other
> purposes when VPR is unused on those devices. In that case, the memory
> is also described as a reserved-memory region in DT, but it is marked as
> reusable so that it can be managed by CMA.
> 
> The resize operation is fairly slow to begin with because we need to
> stall the GPU and put it into reset before the operation, then take it
> out of reset and resume it afterwards.
> 
> What kind of performance impact do you expect?

You'll need to measure it, but we've seen reports of double-digit
percentage regressions in performance and power. As I said, the problem
is that you need to split the linear map to 4k page at runtime to unmap
the dynamic carveout, but that isn't something that can be done on most
CPUs. Therefore you end up having to use page-granular mappings for the
entire thing, similarly to how 'rodata_full' drives can_set_direct_map()
and the perf/power hit affects everything.

It's hard to know what to suggest... I wonder if any of the memory
hotplug logic could help here?

Will

^ permalink raw reply


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