Hi Robert,
> Subject: [PATCH v1] dma-buf/udmabuf: Disable the size limit by default
>
> As udmabuf increasingly enjoys popularity - being used in projects like
> libcamera, Gstreamer, Mesa, KWin and Weston - users more frequently
> encounter cases where the current default size limit of 64MB is too low.
> Examples include allocating video buffers at a 8K resolution - and even 4K
> is affected when using non-subsampled video formats and high bit depths.
>
> In its current form the size limit for individual buffers does not seem to
> provide any additional level of protection - such as limiting the amount of
> memory a process can pin - as the later can just allocate multiple buffers.
> If additional guardrails are desired, they would likely require some kind
> accounting not limited to individual buffers.
>
> Therefor let's disable the size limit by default. Use the special value
> of zero to do so, which prevously could be used to effectively disable the
> interface. Using other means, such as file permissions, appears to be a
> much better fit for that purpose.
>
> Signed-off-by: Robert Mader <robert.mader(a)collabora.com>
>
> ---
>
> Please let me know if changing the meaning of the parameter value of zero
> is considered a breaking change / not acceptable. In that case INT_MAX
> might be a better option.
Yeah, I think using INT_MAX might be better.
Thanks,
Vivek
>
> See
> https://lore.kernel.org/dri-devel/20260711144814.8205-1-
> robert.mader(a)collabora.com/
> for a previous attempt to make the value configurable via kconfig - and
> in particular
> https://lore.kernel.org/dri-devel/6764ca6f-b4d8-4baa-9d27-
> 2ca867ac2d41(a)amd.com/
> for the suggestion and discussion to remove the default limit.
> ---
> drivers/dma-buf/udmabuf.c | 6 +++---
> 1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/dma-buf/udmabuf.c b/drivers/dma-buf/udmabuf.c
> index bced421c0d65..3509b690d8e2 100644
> --- a/drivers/dma-buf/udmabuf.c
> +++ b/drivers/dma-buf/udmabuf.c
> @@ -20,9 +20,9 @@ static int list_limit = 1024;
> module_param(list_limit, int, 0644);
> MODULE_PARM_DESC(list_limit, "udmabuf_create_list->count limit.
> Default is 1024.");
>
> -static int size_limit_mb = 64;
> +static int size_limit_mb = 0;
> module_param(size_limit_mb, int, 0644);
> -MODULE_PARM_DESC(size_limit_mb, "Max size of a dmabuf, in
> megabytes. Default is 64.");
> +MODULE_PARM_DESC(size_limit_mb, "Max size of a dmabuf, in
> megabytes. Setting 0 disables the limit. Default is 0.");
>
> struct udmabuf {
> pgoff_t pagecount;
> @@ -373,7 +373,7 @@ static long udmabuf_create(struct miscdevice
> *device,
>
> subpgcnt = list[i].size >> PAGE_SHIFT;
> pgcnt += subpgcnt;
> - if (pgcnt > pglimit)
> + if (pglimit && pglimit < pgcnt)
> goto err_noinit;
>
> max_nr_folios = max_t(unsigned long, subpgcnt,
> max_nr_folios);
> --
> 2.55.0
Incredible, professional, and fast! Accurate and polite. Understanding and genuinely caring about horrible situations. Thanks, Dune Nectar Web Expert. Dune Nectar Web Expert is a great crypto recovery company to deal with. They have gone above and beyond to help, and they have worked side by side with my local law enforcement. +1, 5,1,6,4,6,7,6,7,8,3
Every devmem dmabuf binding hands the page_pool PAGE_SIZE niovs today.
On NICs that consume one descriptor per netmem, this caps a single RX
descriptor at PAGE_SIZE and burns CPU on buffer churn.
In this series, we add a bind-time netlink attribute,
NETDEV_A_DMABUF_RX_BUF_SIZE, that lets userspace request a larger niov
size (power of two >= PAGE_SIZE). Drivers must opt in via
queue_mgmt_ops.QCFG_RX_PAGE_SIZE.
Measurements:
Setup: kperf devmem RX/TX cuda, 4 flows, 64 MB messages, 60s, dctcp,
num-rx-queues=4, dmabuf-rx/tx-size-mb=2048, 10 runs per niov size,
mlx5.
niov RX dev Gbps RX flow avg Gbps app sys %
----- ---------------- ----------------- ----------------
4K 300.63 +/- 53.21 75.16 +/- 13.30 54.15 +/- 10.23
16K 321.35 +/- 28.20 80.34 +/- 7.05 41.05 +/- 8.87
32K 347.63 +/- 2.20 86.91 +/- 0.55 44.54 +/- 3.51
64K 332.11 +/- 14.26 83.03 +/- 3.56 35.47 +/- 3.11
RX app sys % drops ~19% from 4K to 64K.
kperf support (not yet merged):
https://github.com/facebookexperimental/kperf/commit/8837577f920876bce6986e…
Signed-off-by: Bobby Eshleman <bobbyeshleman(a)meta.com>
---
Changes in v5:
- removed unnecessary change from ssize_t to size_t (Mina)
- removed '--------' lines in the commit message (Paolo)
- removed commit msg about CONFIG_HUGETLB since that change was already
merged
- Link to v4: https://lore.kernel.org/r/20260701-tcpdm-large-niovs-v4-0-ca4654f37570@meta…
Changes in v4:
- ncdevmem: fix the possible overflow in ncdevmem (Sashiko)
- drop the udmabuf patch because the fix is now already in net-next
- silenced two pylint complaints in devmem_lib.py
- Link to v3: https://lore.kernel.org/r/20260612-tcpdm-large-niovs-v3-0-a3b693e76fcb@meta…
Changes in v3:
- fix a bunch of non-reverse christmas tree declarations (Stan)
- remove extra uint32 cast for getpagesize() (Stan)
- remove overzealous strtoul checking (Stan)
- remove value checks that the kernel already performs on rx_buf_size
(Stan)
- Link to v2: https://lore.kernel.org/r/20260611-tcpdm-large-niovs-v2-0-ee2bf15e7523@meta…
Changes in v2:
- Use NL_SET_ERR_MSG_FMT for sg alignment failure details (Stan)
- Keep -E2BIG (not a direct ask, but seemed preferred, Stan)
- Update udmabuf commit message and comments explaining why
"one sg ent per folio" is useful (Christian)
- Set/restore nr_hugepages in py harness (Stan)
- Link to v1: https://lore.kernel.org/r/20260603-tcpdm-large-niovs-v1-0-f37a4ac6726c@meta…
---
Bobby Eshleman (3):
net: devmem: allow rx-buf-size > PAGE_SIZE per dmabuf binding
selftests/net: ncdevmem: add -b option to set rx-buf-size on bind
selftests/net: devmem.py: add check_rx_large_niov
Documentation/netlink/specs/netdev.yaml | 8 +++
include/uapi/linux/netdev.h | 1 +
net/core/devmem.c | 51 +++++++++++--------
net/core/devmem.h | 13 +++--
net/core/netdev-genl-gen.c | 5 +-
net/core/netdev-genl.c | 19 ++++++-
tools/include/uapi/linux/netdev.h | 1 +
tools/testing/selftests/drivers/net/hw/devmem.py | 12 ++++-
.../testing/selftests/drivers/net/hw/devmem_lib.py | 59 +++++++++++++++++++++-
tools/testing/selftests/drivers/net/hw/ncdevmem.c | 36 +++++++++++--
.../testing/selftests/drivers/net/hw/nk_devmem.py | 11 +++-
11 files changed, 178 insertions(+), 38 deletions(-)
---
base-commit: 474cff6868129755cf889edf40d7f491729fc588
change-id: 20260602-tcpdm-large-niovs-56523a3a1077
Best regards,
--
Bobby Eshleman <bobbyeshleman(a)meta.com>
7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tvrtko Ursulin <tvrtko.ursulin(a)igalia.com>
[ Upstream commit e94b9f01543cc6a83538c2c2cc645a424d3015ca ]
Trace_dma_fence_signaled, trace_dma_fence_wait_end and
trace_dma_fence_destroy can all currently dereference a null fence->ops
pointer after it has been reset on fence signalling.
Lets use the safe string getters for most tracepoints to avoid this class
of a problem, while for the signal tracepoint we move it to before ops are
cleared to avoid losing the driver and timeline name information. Apart
from moving it we also need to add a new tracepoint class to bypass the
safe name getters since the signaled bit is already set.
For dma_fence_init we also need to use the new tracepoint class since the
rcu read lock is not held there, and we can do the same for the enable
signaling since there we are certain the fence cannot be signaled while
we are holding the lock and have even validated the fence->ops.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin(a)igalia.com>
Fixes: 541c8f2468b9 ("dma-buf: detach fence ops on signal v3")
Cc: Christian König <christian.koenig(a)amd.com>
Cc: Philipp Stanner <phasta(a)kernel.org>
Cc: Boris Brezillon <boris.brezillon(a)collabora.com>
Cc: linux-media(a)vger.kernel.org
Cc: linaro-mm-sig(a)lists.linaro.org
Reviewed-by: Christian König <christian.koenig(a)amd.com>
Signed-off-by: Tvrtko Ursulin <tursulin(a)ursulin.net>
Link: https://lore.kernel.org/r/20260415083207.40513-2-tvrtko.ursulin@igalia.com
Signed-off-by: Sasha Levin <sashal(a)kernel.org>
---
drivers/dma-buf/dma-fence.c | 3 ++-
include/trace/events/dma_fence.h | 40 +++++++++++++++++++++++++++-----
2 files changed, 36 insertions(+), 7 deletions(-)
diff --git a/drivers/dma-buf/dma-fence.c b/drivers/dma-buf/dma-fence.c
index a2aa82f4eedd49..b3bfa6943a8e13 100644
--- a/drivers/dma-buf/dma-fence.c
+++ b/drivers/dma-buf/dma-fence.c
@@ -363,6 +363,8 @@ void dma_fence_signal_timestamp_locked(struct dma_fence *fence,
&fence->flags)))
return;
+ trace_dma_fence_signaled(fence);
+
/*
* When neither a release nor a wait operation is specified set the ops
* pointer to NULL to allow the fence structure to become independent
@@ -377,7 +379,6 @@ void dma_fence_signal_timestamp_locked(struct dma_fence *fence,
fence->timestamp = timestamp;
set_bit(DMA_FENCE_FLAG_TIMESTAMP_BIT, &fence->flags);
- trace_dma_fence_signaled(fence);
list_for_each_entry_safe(cur, tmp, &cb_list, node) {
INIT_LIST_HEAD(&cur->node);
diff --git a/include/trace/events/dma_fence.h b/include/trace/events/dma_fence.h
index 3abba45c0601a4..5b10a9e06fb4ec 100644
--- a/include/trace/events/dma_fence.h
+++ b/include/trace/events/dma_fence.h
@@ -9,12 +9,40 @@
struct dma_fence;
+DECLARE_EVENT_CLASS(dma_fence,
+
+ TP_PROTO(struct dma_fence *fence),
+
+ TP_ARGS(fence),
+
+ TP_STRUCT__entry(
+ __string(driver, dma_fence_driver_name(fence))
+ __string(timeline, dma_fence_timeline_name(fence))
+ __field(unsigned int, context)
+ __field(unsigned int, seqno)
+ ),
+
+ TP_fast_assign(
+ __assign_str(driver);
+ __assign_str(timeline);
+ __entry->context = fence->context;
+ __entry->seqno = fence->seqno;
+ ),
+
+ TP_printk("driver=%s timeline=%s context=%u seqno=%u",
+ __get_str(driver), __get_str(timeline), __entry->context,
+ __entry->seqno)
+);
+
/*
* Safe only for call sites which are guaranteed to not race with fence
- * signaling,holding the fence->lock and having checked for not signaled, or the
- * signaling path itself.
+ * signaling, holding the fence->lock and having checked for not signaled, or
+ * the signaling path itself.
+ *
+ * TODO: Remove the need for this event class when drivers switch to independent
+ * fences.
*/
-DECLARE_EVENT_CLASS(dma_fence,
+DECLARE_EVENT_CLASS(dma_fence_ops,
TP_PROTO(struct dma_fence *fence),
@@ -46,7 +74,7 @@ DEFINE_EVENT(dma_fence, dma_fence_emit,
TP_ARGS(fence)
);
-DEFINE_EVENT(dma_fence, dma_fence_init,
+DEFINE_EVENT(dma_fence_ops, dma_fence_init,
TP_PROTO(struct dma_fence *fence),
@@ -60,14 +88,14 @@ DEFINE_EVENT(dma_fence, dma_fence_destroy,
TP_ARGS(fence)
);
-DEFINE_EVENT(dma_fence, dma_fence_enable_signal,
+DEFINE_EVENT(dma_fence_ops, dma_fence_enable_signal,
TP_PROTO(struct dma_fence *fence),
TP_ARGS(fence)
);
-DEFINE_EVENT(dma_fence, dma_fence_signaled,
+DEFINE_EVENT(dma_fence_ops, dma_fence_signaled,
TP_PROTO(struct dma_fence *fence),
--
2.53.0
On Fri, 2026-07-17 at 14:14 -0300, Daniel Almeida wrote:
> >
> > > > + try_pin_init!(Self {
> > > > + // SAFETY: `dma_fence_context_alloc()` merely works on a global atomic.
> > > > + // Parameter `1` is the number of contexts we want to allocate.
> > > > + nr: unsafe { bindings::dma_fence_context_alloc(1) },
> > > > + seqno: AtomicU64::new(0),
> > >
> > > Do we really need to force a 0 here? i.e.: can’t we take the initial seqno
> > > as an argument?
> >
> > We could. What would that be useful for?
>
>
> On Mali, the hardware syncobj starts at 0. If you see a 0, is this the default
> state, or should you signal seqno 0?
>
> This problem goes away if we can have seqnos starting at a custom value, like
> 1. It seems like the C machinery also special-cases 0 in a few other places too.
ACK.
>
> >
> > Hm, no, we don't.
> >
> > For the most part that's irrelevant, since all critical components then
> > only get set in new_fence(). Correct typization is enforced through T.
> >
> > The notable exception is the fence_ctx reference itself.
> >
> > What should we do about it?
> >
> > We could keep the fctx field as a MaybeUninit and set it later. Or we
> > check through the fctx identifier number whether it's the correct one
> > in new_fence(), but then new_fence() could fail with some error, and
> > it's probably better to have it be completely fail-free.
>
> Agree about the fail-free part.
>
> The problem I see here is that new_fence() will use "seqno" and "nr" from
> whatever context called new_fence(), but DriverFenceAllocation has some other
> (possibly unrelated) context as its DriverFenceData::fctx.
>
> The lifetimes are apparently broken too, because 'a is the lifetime of the
> context where new_fence_allocation was called, meaning that the context that
> actually called new_fence() can drop, even though it provided the state for
> dma_fence_init().
>
> I guess this can be solved by moving new_fence() to impl DriverFenceAllocation?
> That already has a context, and most importantly, the right context.
Yes that is / was broken. Having the wrong fctx would cause wrong
container_of() calls and therefore explode.
Fixed it locally following your suggestion of creating fences on the
allocation object.
> >
[…]
> > > > +
> > > > +/// The receiving counterpart of a [`DriverFence`], designed to register callbacks
> > > > +/// on, check the signalled state etc. A [`Fence`] cannot be signalled.
> > > > +/// A [`Fence`] is always refcounted.
> > >
> > > I would explain this a tad better.
> >
> > What exactly? The refcounting? The dualism between DriverFence and
> > Fence? :)
>
> For example, you say “a Fence cannot be signaled”. A person seeing this
> code for the first time might ask why. Specially if they start by reading the
> docs for Fence first.
>
> I think explaining a bit more about the DriverFence/Fence/refcounting as you
> said is already enough to settle it.
OK, I flesh that out a bit.
> > >
[…]
> > > > + let ret = unsafe { bindings::dma_fence_is_signaled(fence) };
> > > > +
> > > > + // To guarantee that an API caller can 100% rely on the signalling being
> > > > + // completed (i.e., all fence callbacks ran), we have to take the lock.
> > > > + //
> > > > + // The reason is that the C dma_fence backend currently does not carefully
> > > > + // synchronize the `dma_fence_is_signaled()` function with the proper
> > > > + // spinlock. This can lead to the function returning `true` while fence
> > > > + // callbacks are still being executed. This can be mitigated by guarding
> > > > + // the entire function with the spinlock.
> > > > + //
> > > > + // See commit c8a5d5ea3ba6a.
> > > > +
> > > > + // SAFETY: `fence` is valid because `self` is valid. `flag_ptr` is
> > > > + // merely a pointer to an integer, which lives as long as this function.
> > > > + unsafe { bindings::dma_fence_lock_irqsave(fence, flag_ptr) };
> > >
> > > Shouldn’t this be before the “is_signaled” ffi call? Or is this
> > > only about ensuring all callbacks have run? i.e.: is “ret” valid even
> > > though it was computed before taking the lock?
> >
> > OK, this is where it gets ugly.
> >
> > So during the last weeks I've been struggling to get the C backend into
> > better shape. One issue from my POV is that the C dma_fence spinlock
> > does not protect the fence state; there is insistence that the lock
> > shall only protect the callback list.
> >
> > The function dma_fence_is_signaled() has an unlocked fast path check:
> >
> > https://elixir.bootlin.com/linux/v7.2-rc3/source/include/linux/dma-fence.h#…
> >
> > whereas setting of that bit is done under lock-protection:
> >
> > https://elixir.bootlin.com/linux/v7.2-rc3/source/drivers/dma-buf/dma-fence.…
> >
> >
> > This can lead to funny races like in the commit mentioned in the
> > comment block above (c8a5d5ea3ba6a).
> >
> > And it also leads to weird hacks like this:
> >
> > https://elixir.bootlin.com/linux/v7.2-rc3/source/drivers/gpu/drm/amd/amdgpu…
> >
> >
> > Now, in principle I agree with you that a pattern like this:
> >
> > dma_fence_lock_irqsave(…);
> > let signaled = dma_fence_is_signaled_locked(…);
> > dma_fence_unlock_irqrestore(…);
> >
> > would be better.
> >
> > However, lengthy discussions with Christian seem to settle at the point
> > where Christian sees the very strict requirement of never calling fence
> > callbacks under lock protection, and where he views
> > dma_fence_is_signaled_locked() as a broken function that should be
> > removed.
> >
> > He's currently working on removing all bits where fence callbacks are
> > invoked under lock protection:
> >
> > https://lore.kernel.org/dri-devel/20260624122917.2483-1-christian.koenig@am…
> >
> > There's been a ton of discussions and proposals about that in recent
> > weeks
> >
> > https://lore.kernel.org/dri-devel/20260608142436.265820-2-phasta@kernel.org/
> > https://lore.kernel.org/dri-devel/20260612104251.2264707-2-phasta@kernel.or…
> >
> >
> > So tl;dr: The weird code you're commenting on above ensures that
> >
> > a) the fence->ops->is_signaled() callback is not called under lock
> > protection and
> > b) taking and releasing the lock guarantees that all callbacks are
> > really finished, i.e. they have run.
> >
> >
> > (I continue to believe that setting the bit under lock protection and
> > reading it without lock is fundamentally broken and needs to be fixed,
> > but fixes are being rejected because of claimed performance regressions
> > years ago when this was tried, because checking the bit is some sort of
> > fast path check for.. parties that spin on dma_fence_is_signaled() ??)
>
> I see, there is a lot more context on this then. Can you merely add a comment
> saying it’s ok to call dma_fence_is_signaled() without the locks? Otherwise
> people might try to “fix” this down the line...
I tried to make it clear with the comment above:
// To guarantee that an API caller can 100% rely on the signalling being
// completed (i.e., all fence callbacks ran), we have to take the lock.
//
// The reason is that the C dma_fence backend currently does not carefully
// synchronize the `dma_fence_is_signaled()` function with the proper
// spinlock. This can lead to the function returning `true` while fence
// callbacks are still being executed. This can be mitigated by guarding
// the entire function with the spinlock.
//
// See commit c8a5d5ea3ba6a.
I can try to make it more explicit.
Actually, I suppose with our design in Rust we would not actually need
this lock-unlock, because we ensure that it does not matter whether a
callback already ran.
But since we don't know who will be working on this in 5 years, adding
this or that exotic callback, or maybe registering callbacks on his own
fence, I put this sequence there for robustness.
So if the function returns true, you really know that all callbacks are
gone forever.
>
> >
> > >
> > > >
> >
> > […]
> > >
> > >
> > > > + /// The API user's data. This must either not need drop, or must delay its
> > > > + /// drop by a grace period. It is essential that the data only performs
> > > > + /// operations legal in atomic context in its [`Drop`] implementation.
> > > > + #[pin]
> > > > + data: T::FenceDataType,
> > > > +}
> > > > +
> > > >
> >
> > […]
> >
> > > > +
> > > > + // DriverFenceData is repr(C) and a Fence is its first member.
> > >
> > > > + let fence_data_ptr = fence_ptr as *mut DriverFenceData<'a, T>;
> > >
> > > Without a “CAST:” keyword, I think this will trigger the linter?
> > >
> >
> > Didn't see a complaint from clippy nor compiler.
>
> I recommend the CAST thing anyways. It’s being adopted in other parts of the kernel
> crate.
I can write a CAST comment, no problem.
Thx
P.
On Mon, Jul 20, 2026 at 10:05:33PM +0200, Natalie Vock wrote:
> On 7/19/26 19:58, Taehee Yoo wrote:
> > Add the AMD GCN (gfx9/gfx10) instruction encoder used to build the GPU
> > shaders that knod dispatches, plus a matching disassembler used for
> > debugging the generated code.
>
> Is it really necessary to have a full-on compiler and disassembler in the
> kernel driver? This patch is massive and I'm wondering how much benefit it
> really provides. Is there really no way to move GPU compilation out of the
> kernel, one way or another? Could you get acceptable perf with a static
> shader that interprets BPF programs at runtime? Such a shader can be
> compiled beforehand and just embedded into the kernel - there's prior art
> there with the CWSR trap handler in amdkfd.
>
> In case you really, really need to compile the BPF to native ISA, could you
> still have userspace take care of that in one way or another?
There was a long and painful discussion about P4, and offloading it to
hardware. The proponents of that wanted to do the compilation stage in
user space to produce a binary blob, but it was hard to prove that the
P4 passed to the kernel for software processing, and the binary blob
passed to the hardware actually where the same. It opened up the path
for closed source P4 where the kernel never got to see the actual P4
code. So it was not really offload, but kernel bypass.
So having a compiler in the kernel is probably the correct way to go,
if you want to be friendly to open source.
The other option is to get the GPU to do the compilation itself, so
you pass BPF byte codes to the GPU and it generates its own native
code. I've no idea if that is possible, but clang can target OpenMP,
so maybe it is possible to move this compiler into the GPU?
Andrew
Hi,
These patches fix two issues in the drm/drm_crtc driver. Initially I
was hitting the BUG_ON() in a scenario as explained in the commit
message of what is now the second patch in this series. For the reasons
outlines there, the BUG_ON() should just be removed.
After posting, sashiko.dev noticed another issue, that was previously
masked by the now-removed BUG_ON(). Since we can't have a loud BUG() be
replaced with silent data corruption or worse, I've also added a patch
to address this issue highlighted by sashiko.dev. I believe its
observation and analysis to be correct.
Cheers,
Andre'
Signed-off-by: André Draszik <andre.draszik(a)linaro.org>
---
Changes in v2:
- add new patch 1 to address sashiko observation
- original patch 1 becomes patch 2
- patch 2:
- don't turn fence_to_crtc() into macro (Jani, Philipp)
- update commit message to include reference to deprecated use of BUG
- Link to v1: https://lore.kernel.org/r/20260618-linux-drm_crtc_fix2-v1-1-c03e77b36f34@li…
---
André Draszik (2):
drm/drm_crtc: ensure dma_fence_ops remain valid during device unbind
drm/drm_crtc: fix race with dma_fence_signal() in ::get_driver_name()
drivers/gpu/drm/drm_crtc.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
---
base-commit: b9810cd75b9fb56a3425d391cba3f608502bd474
change-id: 20260618-linux-drm_crtc_fix2-23a7c354a412
Best regards,
--
André Draszik <andre.draszik(a)linaro.org>
The protagonist of the game is a conventional dinosaur known as a Tyrannosaurus rex. This is the species of dinosaur that is typically depicted in films and books that are about dinosaurs. https://dinogameonline.io
Hi David,
On 16/07/2026 22:23, David Matlack wrote:
> On 2026-07-16 03:51 PM, Matt Evans wrote:
>> Hi David,
>>
>> On 15/07/2026 19:12, David Matlack wrote:
>>> On Wed, Jul 15, 2026 at 10:47 AM Matt Evans <matt(a)ozlabs.org> wrote:
>>>
>>>> This is based on v7.2-rc3.
>>>>
>>>> These commits are on GitHub for easier browsing, along with
>>>> "[RFC ONLY] selftests: vfio: Add standalone vfio_dmabuf_mmap_test":
>>>>
>>>> https://github.com/metamev/linux/compare/v7.2-rc3...dev/mev/vfio-dmabuf-mma…
>>>
>>> It'd be great to have this test upstream. I'm happy to review it when
>>> you're ready. Looks like it just needs to be redone to use the VFIO
>>> selftests library and kselftests harness. AI could probably do the
>>> conversion pretty quick :)
>>
>> For sure, I'd intended to catch up with you on best approach here. :)
>>
>> Aside from the organic structure of the test (the open-coded VFIO
>> device/group setup/init needs to go), the main issue is that it relies
>> on a hacked/out of tree QEMU "EDU++" device with a second larger BAR
>> (containing freely read-writable memory). A subset of tests run with
>> the in-tree EDU device, but coverage is too low.
>>
>> The desirable properties are:
>>
>> - Having a BAR that is pure memory (all locations present, writable
>> without disruptive side-effects) so that mapping aliases can be
>> constructed and detected. This is good to test things like non-zero
>> vm_pgoffs and VA space presentation of physically-discontiguous DMABUFs.
>>
>> - BAR >> hugepage size so we can eyeball huge mappings work (or better,
>> mechanically test for them). At least 32MB would tick this box for 4K,
>> 16K page systems.
>>
>> - Something QEMU supports*, so one can run the test in a VM/TCG system.
>>
>> There were some real device models in QEMU that could be used this way,
>> but needed a fair bit of setup; I didn't want to rathole
>> vfio_dmabuf_mmap_test on including a ton of device-specific code for
>> some video card or similar.
>>
>> I'll dig more for a simple target that provides these properties --
>> obviously it would be better to point this test at an off-the-shelf
>> device (including silicon!). And, proposing EDU extensions to the QEMU
>> folks may be useful (there're uses for a better EDU in other contexts too).
>>
>> Since this test uses MMIO for a specific [class of] function, my first
>> thought is it should be another VFIO driver-type test sibling of
>> vfio_pci_driver_test. For example, we could extend the driver-type
>> tests' backend struct vfio_pci_driver_ops for functions capable of
>> providing a Big Memory BAR, like QEMU EDU++. EDU can also memcpy, so
>> could also support vfio_pci_driver_test.
>>
>> The spirit of the device backends hiding setup of a complex device is
>> handy, and it's plausible that several backends could provide this "big
>> memory BAR" service. What do you think, any concerns with extending
>> vfio_pci_driver_ops like that?
>
> I wouldn't recommend leveraging the driver framework unless absolutely
> necessary. It makes the test harder to run.
>
> The biggest issue I see with the proposed properties is being able to
> treat the BAR as memory. That obviously will depend on the device and
> may require device-specific setup. If we decide that treating the BAR as
> memory is truly required then using the driver framework is the way to
> go. But I'm hoping we can avoid that requirement.
>
> Instead, I think you can get pretty far by inspecting /proc/pid/pagemap
> to determine if the mmap() set things up correctly, without actually
> accessing the BAR. You can use /proc/pid/pagemap to look up the PFN and
> PAGEMAP_SCAN to detect huge pages.
Hmm, possible, although that's quite a different test at that point. I
agree never touching the device has advantages, but it's harder to test
certain things if we _never_ do MMIO. The mitigation effort to get
coverage may not be the right tradeoff vs easier running. I can think
of some "easy" VFIO bugs that would be challenging to properly verify in
userspace (e.g. PFNs all having some undesired offset). The current
test method is harder to fool per unit effort in writing it.
Though, I will have a think about this no-touch flavour of test.
What were you picturing regarding populating the VMA PTEs in order to
inspect the result via /proc/pid/pagemap, whilst still upholding the
principle of not touching the device? For example,
madvise(MADV_POPULATE_WRITE) won't work on the VFIO BAR regions because
they're VM_PFNMAP/VM_IO.
> With that requirement gone, then all you really need is a device with a
> large enough BAR. And even that it not a hard requirement. I'm sure
> there are plenty of test cases that could work with smaller BARs. The
> few tests that want to exercise huge mappings can inspect the device BAR
> sizes first, and if they're all too small, SKIP() the test.
>
> If you structure the test this way, then it's easy for the test to be
> used. It can be run against any device for the basic functional
> coverage, and can be run against a device with a larger BAR for full
> coverage of huge mappings.
>
> Does QEMU emulate any devices that have 32MB or larger BARs?
Yep, looks like `-device pci-testdev,membar=64M,membar-backed=on` or
even `-device bochs-display,vgamem=64M` would be suitable.
So I'll also try moving the existing test over to one of these to at
least remove the EDU++ device dependency. (bochs-display has >1 BAR,
and some MMIO regs which are nice for a quick kick-the-tyres access test.)
Cheers,
Matt
On Thu, 16 Jul 2026 21:23:22 +0000
David Matlack <dmatlack(a)google.com> wrote:
> On 2026-07-16 03:51 PM, Matt Evans wrote:
> > Hi David,
> >
> > On 15/07/2026 19:12, David Matlack wrote:
> > > On Wed, Jul 15, 2026 at 10:47 AM Matt Evans <matt(a)ozlabs.org> wrote:
> > >
> > >> This is based on v7.2-rc3.
> > >>
> > >> These commits are on GitHub for easier browsing, along with
> > >> "[RFC ONLY] selftests: vfio: Add standalone vfio_dmabuf_mmap_test":
> > >>
> > >> https://github.com/metamev/linux/compare/v7.2-rc3...dev/mev/vfio-dmabuf-mma…
> > >
> > > It'd be great to have this test upstream. I'm happy to review it when
> > > you're ready. Looks like it just needs to be redone to use the VFIO
> > > selftests library and kselftests harness. AI could probably do the
> > > conversion pretty quick :)
> >
> > For sure, I'd intended to catch up with you on best approach here. :)
> >
> > Aside from the organic structure of the test (the open-coded VFIO
> > device/group setup/init needs to go), the main issue is that it relies
> > on a hacked/out of tree QEMU "EDU++" device with a second larger BAR
> > (containing freely read-writable memory). A subset of tests run with
> > the in-tree EDU device, but coverage is too low.
> >
> > The desirable properties are:
> >
> > - Having a BAR that is pure memory (all locations present, writable
> > without disruptive side-effects) so that mapping aliases can be
> > constructed and detected. This is good to test things like non-zero
> > vm_pgoffs and VA space presentation of physically-discontiguous DMABUFs.
> >
> > - BAR >> hugepage size so we can eyeball huge mappings work (or better,
> > mechanically test for them). At least 32MB would tick this box for 4K,
> > 16K page systems.
> >
> > - Something QEMU supports*, so one can run the test in a VM/TCG system.
> >
> > There were some real device models in QEMU that could be used this way,
> > but needed a fair bit of setup; I didn't want to rathole
> > vfio_dmabuf_mmap_test on including a ton of device-specific code for
> > some video card or similar.
> >
> > I'll dig more for a simple target that provides these properties --
> > obviously it would be better to point this test at an off-the-shelf
> > device (including silicon!). And, proposing EDU extensions to the QEMU
> > folks may be useful (there're uses for a better EDU in other contexts too).
> >
> > Since this test uses MMIO for a specific [class of] function, my first
> > thought is it should be another VFIO driver-type test sibling of
> > vfio_pci_driver_test. For example, we could extend the driver-type
> > tests' backend struct vfio_pci_driver_ops for functions capable of
> > providing a Big Memory BAR, like QEMU EDU++. EDU can also memcpy, so
> > could also support vfio_pci_driver_test.
> >
> > The spirit of the device backends hiding setup of a complex device is
> > handy, and it's plausible that several backends could provide this "big
> > memory BAR" service. What do you think, any concerns with extending
> > vfio_pci_driver_ops like that?
>
> I wouldn't recommend leveraging the driver framework unless absolutely
> necessary. It makes the test harder to run.
>
> The biggest issue I see with the proposed properties is being able to
> treat the BAR as memory. That obviously will depend on the device and
> may require device-specific setup. If we decide that treating the BAR as
> memory is truly required then using the driver framework is the way to
> go. But I'm hoping we can avoid that requirement.
Could you run a test where only a known part of the BAR can be treated
as memory?
A large BAR is likely to have some areas that can be accessed as memory.
David
>
> Instead, I think you can get pretty far by inspecting /proc/pid/pagemap
> to determine if the mmap() set things up correctly, without actually
> accessing the BAR. You can use /proc/pid/pagemap to look up the PFN and
> PAGEMAP_SCAN to detect huge pages.
>
> With that requirement gone, then all you really need is a device with a
> large enough BAR. And even that it not a hard requirement. I'm sure
> there are plenty of test cases that could work with smaller BARs. The
> few tests that want to exercise huge mappings can inspect the device BAR
> sizes first, and if they're all too small, SKIP() the test.
>
> If you structure the test this way, then it's easy for the test to be
> used. It can be run against any device for the basic functional
> coverage, and can be run against a device with a larger BAR for full
> coverage of huge mappings.
>
> Does QEMU emulate any devices that have 32MB or larger BARs?
>