Escape Road 2 transforms a simple escape concept into an exciting challenge filled with action and suspense. Its engaging gameplay, evolving difficulty, and urban setting make it a standout choice for players seeking fast-paced entertainment. Whether you're aiming to beat your personal record or simply enjoy the thrill of the chase, Escape Road 2 offers plenty of reasons to get behind the wheel. Many driving games focus solely on speed, but Escape Road 2 combines speed with strategy. The constant pressure of the pursuit, the variety of escape routes, and the progression system work together to create a highly replayable experience.
Every chase tells a different story. Some end in dramatic crashes, while others become legendary escapes that last far longer than expected. This unpredictability is one of the game's greatest strengths. Play https://escaperoad2.io
On Fri, Jun 12, 2026 at 10:17 PM Danilo Krummrich <dakr(a)kernel.org> wrote:
>
> As far as I'm concerned there's no need to do that for things that are not
> rendered anyway. But also feel free to do it anyway of course.
It is not a huge deal if there are gaps here or there, but we use
Markdown in comments too for consistency.
What we don't do is intra-doc links there -- it would have been nice
if `rustdoc` could use those in comments for the source view, but it
doesn't, and while I talked with upstream about it, it isn't likely it
will happen soon if at all...
Cheers,
Miguel
Hi,
On Mon, Oct 23, 2023 at 10:25:50AM -0700, Doug Anderson wrote:
> On Mon, Oct 23, 2023 at 9:31 AM Yuran Pereira <yuran.pereira(a)hotmail.com> wrote:
> >
> > Since "Clean up checks for already prepared/enabled in panels" has
> > already been done and merged [1], I think there is no longer a need
> > for this item to be in the gpu TODO.
> >
> > [1] https://patchwork.freedesktop.org/patch/551421/
> >
> > Signed-off-by: Yuran Pereira <yuran.pereira(a)hotmail.com>
> > ---
> > Documentation/gpu/todo.rst | 25 -------------------------
> > 1 file changed, 25 deletions(-)
>
> It's not actually all done. It's in a bit of a limbo state right now,
> unfortunately. I landed all of the "simple" cases where panels were
> needlessly tracking prepare/enable, but the less simple cases are
> still outstanding.
>
> Specifically the issue is that many panels have code to properly power
> cycle themselves off at shutdown time and in order to do that they
> need to keep track of the prepare/enable state. After a big, long
> discussion [1] it was decided that we could get rid of all the panel
> code handling shutdown if only all relevant DRM KMS drivers would
> properly call drm_atomic_helper_shutdown().
>
> I made an attempt to get DRM KMS drivers to call
> drm_atomic_helper_shutdown() [2] [3] [4]. I was able to land the
> patches that went through drm-misc, but currently many of the
> non-drm-misc ones are blocked waiting for attention.
>
> ...so things that could be done to help out:
>
> a) Could review patches that haven't landed in [4]. Maybe adding a
> Reviewed-by tag would help wake up maintainers?
>
> b) Could see if you can identify panels that are exclusively used w/
> DRM drivers that have already been converted and then we could post
> patches for just those panels. I have no idea how easy this task would
> be. Is it enough to look at upstream dts files by "compatible" string?
I think it is, yes.
Maxime
I’ve played a lot of casual browser games over the years. Some lasted a few days before I forgot about them, while others became little habits that I’d revisit whenever I had a few spare minutes. One game that somehow keeps finding its way back into my bookmarks is agario.
Play now: https://agario-free.com
At first glance, it looks ridiculously simple. You control a tiny circle, move around a giant map, eat pellets, grow bigger, and avoid getting eaten by larger players. That's basically it.
But if you've ever spent more than ten minutes playing, you know there's something strangely addictive hiding beneath that simple concept.
I've had moments where I felt unstoppable, moments where I laughed out loud at my own mistakes, and moments where I seriously questioned why I kept clicking "Play Again" after losing everything in three seconds.
And somehow, that's exactly why I love it.
The First Time I Played Agario
The first time I opened agario, I honestly didn't expect much.
The graphics were basic. There was no tutorial. No complicated progression system. No cinematic introduction.
I spawned as a tiny cell and started wandering around collecting colorful dots.
For about thirty seconds, everything felt peaceful.
Then a giant player appeared from nowhere and swallowed me instantly.
Game over.
I remember staring at my screen thinking, "Wait... that's it?"
A few seconds later, I clicked Play Again.
Then again.
Then again.
Before I knew it, an hour had disappeared.
That's when I realized the magic of the game isn't in complexity. It's in the constant cycle of risk, growth, and loss.
Every match feels like a fresh start.
Why Growing Bigger Feels So Satisfying
There's something deeply satisfying about watching your tiny cell slowly become a giant blob.
At the beginning of each game, you're vulnerable.
Everybody looks dangerous.
You spend your time avoiding threats and carefully collecting mass wherever you can find it.
Then something changes.
You start getting bigger.
Suddenly, the players that terrified you a few minutes ago become your targets.
That shift in power creates an incredible feeling of progression, even though nothing carries over between matches.
One of my favorite memories was surviving for nearly twenty minutes and climbing into the top ten players on the server.
I wasn't even trying to be aggressive.
I was just playing carefully, avoiding traps, and picking smart opportunities.
Watching my name slowly rise on the leaderboard felt surprisingly rewarding.
Of course, that success didn't last.
Because this is agario.
Success never lasts forever.
The Funniest Mistakes I've Made
The "Easy Target" Disaster
One thing I've learned is that confidence can be dangerous.
I once spotted a smaller player moving awkwardly near the edge of the map.
They looked trapped.
I thought I had an easy meal.
I rushed toward them without thinking.
The next thing I knew, they split into multiple pieces, baited me into a bad position, and led me directly into a player that was twice my size.
Within two seconds, I went from hunter to lunch.
I couldn't even be mad.
The trap was honestly impressive.
Accidentally Helping My Enemy
Another embarrassing moment happened when I tried to escape from a larger player.
In my panic, I ejected mass in the wrong direction.
Instead of creating distance, I essentially fed the person chasing me.
I made them bigger.
They caught me almost immediately.
It felt like handing a thief the keys to my own house.
The Wall Corner Panic
Every experienced player knows this feeling.
You're trying to escape.
A massive player is gaining on you.
You glance at the map.
And suddenly realize you've backed yourself into a corner.
There is no escape route.
No clever strategy.
No miracle play.
Just acceptance.
Those moments always make me laugh because they feel so avoidable in hindsight.
The Most Frustrating Experience
Getting Huge and Losing Everything
If you've played agario, you've probably experienced this.
You spend fifteen or twenty minutes building your mass.
You're focused.
You're careful.
You're making smart decisions.
You finally reach a size that feels powerful.
Then one tiny mistake destroys everything.
Maybe you split at the wrong moment.
Maybe you get trapped between multiple players.
Maybe a virus launches you into a terrible position.
Whatever the reason, your giant empire disappears in seconds.
I still remember one match where I had my best run of the week.
I was sitting comfortably on the leaderboard and feeling invincible.
Then I got greedy.
I chased a player that wasn't worth the risk.
A larger opponent appeared from off-screen.
Game over.
Twenty minutes of progress vanished instantly.
For about five seconds, I considered quitting.
Then I clicked Play Again.
Surprising Things I Learned From Playing
Patience Beats Aggression
When I first started, I thought the goal was to chase every smaller player I saw.
That strategy rarely worked.
The more I played, the more I realized that patience wins far more games.
Some of my best runs happened when I focused on survival instead of domination.
Avoiding unnecessary risks often leads to bigger rewards later.
Bigger Isn't Always Better
One thing that surprised me was how difficult movement becomes when you're enormous.
A huge cell has power, but it also becomes slower and less flexible.
Sometimes medium-sized players can outmaneuver giants and create opportunities that larger players can't respond to quickly enough.
The game has a surprisingly balanced risk-reward system.
Reading Other Players Matters
Many players develop recognizable habits.
Some are aggressive.
Some are cautious.
Some rely heavily on split attacks.
After enough matches, I started paying attention to player behavior rather than just player size.
That small adjustment improved my survival rate dramatically.
My Personal Tips for New Players
Stay Near Open Space
Getting trapped is one of the most common ways to lose.
Whenever possible, I try to keep multiple escape routes available.
Don't Chase Everything
Not every smaller player is worth pursuing.
Sometimes the safest choice is to continue farming pellets and wait for better opportunities.
Watch the Entire Screen
Tunnel vision is dangerous.
It's easy to focus on a target and forget to monitor surrounding threats.
Many of my worst defeats happened because I ignored what was happening just outside my field of view.
Learn From Every Defeat
This sounds obvious, but it helps.
Whenever I lose a large amount of mass, I try to identify exactly what went wrong.
Most deaths aren't random.
They're usually the result of a decision I made thirty seconds earlier.
Why Agario Still Feels Fresh
What impresses me most about agario is how simple mechanics continue creating unique stories.
Every match feels different.
Some games are calm and strategic.
Others become chaotic battles involving dozens of players.
Sometimes I spend ten minutes surviving against impossible odds.
Other times I get eaten within fifteen seconds.
That unpredictability keeps the experience interesting.
No unlocks are required.
No battle passes.
No complicated systems.
Just pure player interaction creating unexpected moments.
And honestly, that's refreshing.
Final Thoughts
Even after all these years, agario remains one of those games I can launch when I want something quick, competitive, and entertaining.
It's simple enough for anyone to understand within minutes, yet deep enough to produce memorable stories every time you play.
I've laughed at ridiculous mistakes, celebrated unlikely victories, and experienced the heartbreak of losing massive cells after long runs. Somehow, all those emotions are packed into a game built around colorful circles eating each other.
That's probably why I keep coming back.
No matter how many times I get eaten, there's always that feeling that the next run might be the one where everything goes perfectly.
Or at least lasts a little longer.
Have you tried it yet? Share your funniest agario moment, or let me know if you've discovered any other fun games worth checking out!
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.
Selftests use udmabuf, but udmabuf sgtables were previously hardcoded to
PAGE_SIZE. This series modifies udmabuf to respect folio sizes in its exported
sgtable. The result is that when backing udmabuf with MFD_HUGETLB 2MB pages,
the sgtable is populated with 2MB entries, allowing devmem's gen_pool to carve
out large (eg. 64K) niovs.
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 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 (4):
net: devmem: allow rx-buf-size > PAGE_SIZE per dmabuf binding
udmabuf: emit one sg entry per pinned folio
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 +++
drivers/dma-buf/udmabuf.c | 52 +++++++++++++++++--
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/config | 1 +
tools/testing/selftests/drivers/net/hw/devmem.py | 12 ++++-
.../testing/selftests/drivers/net/hw/devmem_lib.py | 58 +++++++++++++++++++++-
tools/testing/selftests/drivers/net/hw/ncdevmem.c | 36 ++++++++++++--
.../testing/selftests/drivers/net/hw/nk_devmem.py | 11 +++-
13 files changed, 225 insertions(+), 43 deletions(-)
---
base-commit: 518d8d0199538a4d6d5e51064044ece71e0c42e7
change-id: 20260602-tcpdm-large-niovs-56523a3a1077
Best regards,
--
Bobby Eshleman <bobbyeshleman(a)meta.com>
On Wed, Jun 10, 2026 at 04:43:21PM +0100, Matt Evans wrote:
Hi Matt,
[...]
> + *
> + * With the goal of taking vdev->memory_lock in a world where
> + * vdev might not still exist:
> + *
> + * 1. Take the resv lock on the DMABUF:
> + * - If racing cleanup got in first, the buffer is revoked;
> + * stop/exit if so.
> + * - If we got in first, the buffer is not revoked so vdev is
> + * non-NULL, accessible, and cleanup _has not yet put the
> + * VFIO device registration_. So, the device refcount must
> + * be >0.
> + *
> + * 2. Take vfio_device registration (refcount guaranteed >0
> + * hereafter).
> + *
> + * 3. Unlock the DMABUF's resv lock:
> + * - A racing cleanup can now complete.
> + * - But, the device refcount >0, meaning the vfio_device
> + * (and vfio_pcie_core device vdev) have not yet been
> + * freed. vdev is accessible, even if the DMABUF has been
> + * revoked or cleanup has happened, because
> + * vfio_unregister_group_dev() can't complete.
> + *
> + * 4. Take the vdev->memory_lock
> + * - Either the DMABUF is usable, or has been cleaned up.
> + * Whichever, it can no longer change under us.
> + * - Test the DMABUF revocation status again: if it was
> + * revoked between 1 and 4 return a SIGBUS. Otherwise,
> + * return a PFN.
> + * - It's not necessary to also take the resv lock, because
> + * the status/vdev can't change while memory_lock is held.
> + *
> + * 5. Unlock, done.
> */
> +
> + dma_resv_lock(priv->dmabuf->resv, NULL);
> +
> + if (priv->revoked) {
> + pr_debug_ratelimited("%s VA 0x%lx, pgoff 0x%lx: DMABUF revoked/cleaned up\n",
> + __func__, vmf->address, vma->vm_pgoff);
> + dma_resv_unlock(priv->dmabuf->resv);
> + return VM_FAULT_SIGBUS;
> + }
> +
> + /* If the buffer isn't revoked, vdev is valid */
> vdev = priv->vdev;
>
> + if (!vfio_device_try_get_registration(&vdev->vdev)) {
> + /*
> + * If vdev != NULL (above), the registration should
> + * already be >0 and so this try_get should never
> + * fail.
> + */
> + dev_warn(&vdev->pdev->dev, "%s: Unexpected registration failure\n",
> + __func__);
> + dma_resv_unlock(priv->dmabuf->resv);
> + return VM_FAULT_SIGBUS;
> + }
> + dma_resv_unlock(priv->dmabuf->resv);
> +
> scoped_guard(rwsem_read, &vdev->memory_lock) {
> + /* Revocation status must be re-read, under memory_lock */
> if (!priv->revoked) {
> int pres = vfio_pci_dma_buf_find_pfn(priv, vma,
> vmf->address,
Wait, I noticed that the is_aligned_for_order() check from mainline was
removed here. Was that intentional?
For hugepage faults (order > 0), we must ensure the PFN and address are
properly aligned before calling vfio_pci_vmf_insert_pfn().
In the current upstream code, we have:
if (is_aligned_for_order(vma, addr, pfn, order))
Should we restore that check here?
> @@ -1766,6 +1827,7 @@ static vm_fault_t vfio_pci_mmap_huge_fault(struct vm_fault *vmf,
> __func__, order, pfn, vmf->address,
> vma->vm_pgoff, (unsigned int)ret);
>
> + vfio_device_put_registration(&vdev->vdev);
> return ret;
> }
>
> @@ -1774,7 +1836,7 @@ static vm_fault_t vfio_pci_mmap_page_fault(struct vm_fault *vmf)
> return vfio_pci_mmap_huge_fault(vmf, 0);
> }
>
> -static const struct vm_operations_struct vfio_pci_mmap_ops = {
> +const struct vm_operations_struct vfio_pci_mmap_ops = {
> .fault = vfio_pci_mmap_page_fault,
Nit: Instead of making this global, should we add a helper? E.g.:
void vfio_pci_set_vma_ops(struct vm_area_struct *vma)
{
vma->vm_ops = &vfio_pci_mmap_ops;
}
[...]
> +
> +static int vfio_pci_dma_buf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma)
> +{
> + struct vfio_pci_dma_buf *priv = dmabuf->priv;
> +
> + /*
> + * If we observe that the buffer is revoked now then refuse
> + * the mmap(). This is a belt-and-braces early failure to
> + * ease debugging a revoked buffer being used. Userspace
> + * might also race an mmap() against an explicit revocation,
> + * or an action doing a temporary revoke; race scenarios are
> + * still safe because the fault handler ultimately prevents
> + * access to a revoked buffer if it isn't caught here.
> + */
> + if (READ_ONCE(priv->revoked))
> + return -ENODEV;
> + if ((vma->vm_flags & VM_SHARED) == 0)
> + return -EINVAL;
> +
> + /*
> + * dma_buf_mmap_internal() has asserted that the VMA is
> + * contained within the DMABUF size before calling this.
> + */
> +
> + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
> + vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot);
> +
> + /* See comments in vfio_pci_core_mmap() re VM_ALLOW_ANY_UNCACHED. */
> + vm_flags_set(vma, VM_ALLOW_ANY_UNCACHED | VM_IO | VM_PFNMAP |
> + VM_DONTEXPAND | VM_DONTDUMP);
> + vma->vm_private_data = priv;
> + vma->vm_ops = &vfio_pci_mmap_ops;
> +
> + return 0;
> +}
> #endif /* CONFIG_VFIO_PCI_DMABUF */
>
Thanks,
Praan
On Fri, Jun 12, 2026 at 04:22:12PM +0100, Matt Evans wrote:
> Hi Pranjal,
>
> On 12/06/2026 11:41, Pranjal Shrivastava wrote:
> > On Wed, Jun 10, 2026 at 04:43:18PM +0100, Matt Evans wrote:
> >> Convert the VFIO device fd fops->mmap to create a DMABUF representing
> >> the BAR mapping, and make the VMA fault handler look up PFNs from the
> >> corresponding DMABUF. This supports future code mmap()ing BAR
> >> DMABUFs, and iommufd work to support Type1 P2P.
> >>
> >> First, vfio_pci_core_mmap() uses the new
> >> vfio_pci_core_mmap_prep_dmabuf() helper to export a DMABUF
> >> representing a single BAR range. Then, the vfio_pci_mmap_huge_fault()
> >> callback is updated to understand revoked buffers, and uses the new
> >> vfio_pci_dma_buf_find_pfn() helper to determine the PFN for a given
> >> fault address.
> >>
> >> Now that the VFIO DMABUFs can be mmap()ed, vfio_pci_dma_buf_move()
> >> zaps PTEs (used on the revocation and cleanup paths).
> >>
> >> CONFIG_VFIO_PCI_CORE now unconditionally depends on
> >> CONFIG_DMA_SHARED_BUFFER and CONFIG_PCI_P2PDMA_CORE. The
> >> CONFIG_VFIO_PCI_DMABUF feature conditionally includes support for
> >> VFIO_DEVICE_FEATURE_DMA_BUF, depending on the availability of
> >> CONFIG_PCI_P2PDMA.
> >>
> >> Signed-off-by: Matt Evans <matt(a)ozlabs.org>
> >> ---
> >> drivers/vfio/pci/Kconfig | 5 +-
> >> drivers/vfio/pci/Makefile | 3 +-
> >> drivers/vfio/pci/vfio_pci_core.c | 75 +++++++++++++++++++-----------
> >> drivers/vfio/pci/vfio_pci_dmabuf.c | 12 +++++
> >> drivers/vfio/pci/vfio_pci_priv.h | 11 +----
> >> 5 files changed, 67 insertions(+), 39 deletions(-)
Hi Matt,
[...]
> >> int vfio_pci_core_mmap_prep_dmabuf(struct vfio_pci_core_device *vdev,
> >> struct vm_area_struct *vma,
> >> @@ -532,6 +538,10 @@ void vfio_pci_dma_buf_move(struct vfio_pci_core_device *vdev, bool revoked)
> >> struct vfio_pci_dma_buf *tmp;
> >>
> >> lockdep_assert_held_write(&vdev->memory_lock);
> >> + /*
> >> + * Holding memory_lock ensures a racing VMA fault observes
> >> + * priv->revoked properly.
> >> + */
> >
> > Nit: This comment should appear before the lockdep_assert_held_write()
> > Also, it is slightly verbose.. (not against it though).
>
> Right, I'll move it. Agree it's wordy but if anyone changes that I want
> them to "think faulthandler".
>
That's fair I guess.
> >> list_for_each_entry_safe(priv, tmp, &vdev->dmabufs, dmabufs_elm) {
> >> if (!get_file_active(&priv->dmabuf->file))
> >> @@ -549,6 +559,8 @@ void vfio_pci_dma_buf_move(struct vfio_pci_core_device *vdev, bool revoked)
> >> if (revoked) {
> >> kref_put(&priv->kref, vfio_pci_dma_buf_done);
> >> wait_for_completion(&priv->comp);
> >> + unmap_mapping_range(priv->dmabuf->file->f_mapping,
> >> + 0, priv->size, 1);
> >
> > Have we run this series with lockdep enabled?
> > I guess it'd be nice to check with lockdep once..
>
> I've (generally) always run testing of this series with lockdep. (No
> issues (anymore).)
That sounds good! Thanks for confirming! :)
Praan
Most of this patch series has already been pushed upstream, this is just
the second half of the patch series that has not been pushed yet + some
additional changes which were required to implement changes requested by
the mailing list. This patch series is originally from Asahi, previously
posted by Daniel Almeida.
The previous version of the patch series can be found here:
https://patchwork.freedesktop.org/series/164580/
Branch with patches applied available here:
https://gitlab.freedesktop.org/lyudess/linux/-/commits/rust/gem-shmem
This patch series applies on top of drm-rust-next
Patch-series wide changes since V15:
* Fix some major rebasing errors I somehow didn't notice :(
* Drop the dependency on LazyInit, use the trick that Alice suggested
instead.
* Fix dependency ordering so that Tyr can get the vmap stuff first
without the other bits.
Patch-series wide changes since V16:
* Fix ordering one more time (SetOnce::reset() doesn't need to come
before adding vmap functions)
* Rebase against the latest DeviceContext changes from me that got
pushed.
Patch-series wide changes since V20:
* Lots of Sashiko fixes, excluding the comments that I couldn't prove
weren't just bogus.
Lyude Paul (4):
rust: drm: gem: shmem: Add DmaResvGuard helper
rust: drm: gem: shmem: Add vmap functions
rust: faux: Allow retrieving a bound Device
rust: drm: gem: Introduce shmem::Object::sg_table()
rust/kernel/drm/gem/shmem.rs | 547 ++++++++++++++++++++++++++++++++++-
rust/kernel/faux.rs | 18 +-
2 files changed, 549 insertions(+), 16 deletions(-)
base-commit: 550dc7536644db2d67c6f8cf525bba682fba08d9
--
2.54.0
On Wed, Jun 10, 2026 at 04:43:20PM +0100, Matt Evans wrote:
> Previously, vfio_pci_zap_bars() (and the wrapper
> vfio_pci_zap_and_down_write_memory_lock()) calls were paired with
> calls to vfio_pci_dma_buf_move().
>
> This commit replaces them with a unified new function,
> vfio_pci_zap_revoke_bars() containing both the vfio_pci_dma_buf_move()
> and the unmap_mapping_range(), making it harder for callers to omit
> one. It adds a wrapper, vfio_pci_lock_zap_revoke_bars(), which takes
> the write memory_lock before zapping, and adds a new
> vfio_pci_unrevoke_bars() for the re-enable path.
>
> As of "vfio/pci: Convert BAR mmap() to use a DMABUF", the
> unmap_mapping_range() to zap is no longer performed for vfio-pci since
> the DMABUFs used for BAR mappings already zap PTEs when the
> vfio_pci_dma_buf_move() occurs.
>
> However, it must be assumed that VFIO drivers which override the .mmap
> op could create mappings _not_ backed by DMABUFs. So, the zap is
> still performed on revoke if .mmap is overridden, using a new
> zap_bars_on_revoke flag. A driver can explicitly opt out; the flag is
> cleared by the hisi_acc_vfio_pci driver, since its .mmap just wraps
> vfio_pci_core_mmap() and so still uses DMABUFs.
>
> Signed-off-by: Matt Evans <matt(a)ozlabs.org>
> ---
> .../vfio/pci/hisilicon/hisi_acc_vfio_pci.c | 8 +++
> drivers/vfio/pci/vfio_pci_config.c | 30 ++++----
> drivers/vfio/pci/vfio_pci_core.c | 70 +++++++++++++------
> drivers/vfio/pci/vfio_pci_priv.h | 3 +-
> include/linux/vfio_pci_core.h | 1 +
> 5 files changed, 73 insertions(+), 39 deletions(-)
>
> diff --git a/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c b/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c
> index 86362ec424a5..51990f6d66d5 100644
> --- a/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c
> +++ b/drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c
> @@ -1692,6 +1692,14 @@ static int hisi_acc_vfio_pci_probe(struct pci_dev *pdev, const struct pci_device
> if (ret)
> goto out_put_vdev;
>
> + /*
> + * hisi_acc_vfio_pci_mmap() calls down to
> + * vfio_pci_core_mmap(), so BAR mappings are still
> + * DMABUF-backed. They don't require a zap on revoke, so opt
> + * out:
> + */
> + hisi_acc_vdev->core_device.zap_bars_on_revoke = false;
> +
This seems to be happening after we vfio_pci_core_register_device, which
could be slightly problematic if another device in the same group races
to trigger a hot reset before we can set this to false. Could we
initialize this flag before registration instead?
> hisi_acc_vfio_debug_init(hisi_acc_vdev);
> return 0;
>
> diff --git a/drivers/vfio/pci/vfio_pci_config.c b/drivers/vfio/pci/vfio_pci_config.c
> index a10ed733f0e3..8bfab0da481c 100644
> --- a/drivers/vfio/pci/vfio_pci_config.c
> +++ b/drivers/vfio/pci/vfio_pci_config.c
> @@ -590,12 +590,10 @@ static int vfio_basic_config_write(struct vfio_pci_core_device *vdev, int pos,
> virt_mem = !!(le16_to_cpu(*virt_cmd) & PCI_COMMAND_MEMORY);
> new_mem = !!(new_cmd & PCI_COMMAND_MEMORY);
>
> - if (!new_mem) {
> - vfio_pci_zap_and_down_write_memory_lock(vdev);
> - vfio_pci_dma_buf_move(vdev, true);
> - } else {
> + if (!new_mem)
> + vfio_pci_lock_zap_revoke_bars(vdev);
> + else
> down_write(&vdev->memory_lock);
> - }
>
> /*
> * If the user is writing mem/io enable (new_mem/io) and we
> @@ -631,7 +629,7 @@ static int vfio_basic_config_write(struct vfio_pci_core_device *vdev, int pos,
> *virt_cmd |= cpu_to_le16(new_cmd & mask);
>
> if (__vfio_pci_memory_enabled(vdev))
> - vfio_pci_dma_buf_move(vdev, false);
> + vfio_pci_unrevoke_bars(vdev);
> up_write(&vdev->memory_lock);
> }
>
> @@ -712,16 +710,14 @@ static int __init init_pci_cap_basic_perm(struct perm_bits *perm)
> static void vfio_lock_and_set_power_state(struct vfio_pci_core_device *vdev,
> pci_power_t state)
> {
> - if (state >= PCI_D3hot) {
> - vfio_pci_zap_and_down_write_memory_lock(vdev);
> - vfio_pci_dma_buf_move(vdev, true);
> - } else {
> + if (state >= PCI_D3hot)
> + vfio_pci_lock_zap_revoke_bars(vdev);
> + else
> down_write(&vdev->memory_lock);
> - }
>
> vfio_pci_set_power_state(vdev, state);
> if (__vfio_pci_memory_enabled(vdev))
> - vfio_pci_dma_buf_move(vdev, false);
> + vfio_pci_unrevoke_bars(vdev);
> up_write(&vdev->memory_lock);
> }
>
> @@ -908,11 +904,10 @@ static int vfio_exp_config_write(struct vfio_pci_core_device *vdev, int pos,
> &cap);
>
> if (!ret && (cap & PCI_EXP_DEVCAP_FLR)) {
> - vfio_pci_zap_and_down_write_memory_lock(vdev);
> - vfio_pci_dma_buf_move(vdev, true);
> + vfio_pci_lock_zap_revoke_bars(vdev);
> pci_try_reset_function(vdev->pdev);
> if (__vfio_pci_memory_enabled(vdev))
> - vfio_pci_dma_buf_move(vdev, false);
> + vfio_pci_unrevoke_bars(vdev);
> up_write(&vdev->memory_lock);
> }
> }
> @@ -993,11 +988,10 @@ static int vfio_af_config_write(struct vfio_pci_core_device *vdev, int pos,
> &cap);
>
> if (!ret && (cap & PCI_AF_CAP_FLR) && (cap & PCI_AF_CAP_TP)) {
> - vfio_pci_zap_and_down_write_memory_lock(vdev);
> - vfio_pci_dma_buf_move(vdev, true);
> + vfio_pci_lock_zap_revoke_bars(vdev);
> pci_try_reset_function(vdev->pdev);
> if (__vfio_pci_memory_enabled(vdev))
> - vfio_pci_dma_buf_move(vdev, false);
> + vfio_pci_unrevoke_bars(vdev);
> up_write(&vdev->memory_lock);
> }
> }
> diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c
> index f9636d8f9e2a..5ea0bd4e7876 100644
> --- a/drivers/vfio/pci/vfio_pci_core.c
> +++ b/drivers/vfio/pci/vfio_pci_core.c
> @@ -319,8 +319,7 @@ static int vfio_pci_runtime_pm_entry(struct vfio_pci_core_device *vdev,
> * The vdev power related flags are protected with 'memory_lock'
> * semaphore.
> */
> - vfio_pci_zap_and_down_write_memory_lock(vdev);
> - vfio_pci_dma_buf_move(vdev, true);
> + vfio_pci_lock_zap_revoke_bars(vdev);
>
> if (vdev->pm_runtime_engaged) {
> up_write(&vdev->memory_lock);
> @@ -406,7 +405,7 @@ static void vfio_pci_runtime_pm_exit(struct vfio_pci_core_device *vdev)
> down_write(&vdev->memory_lock);
> __vfio_pci_runtime_pm_exit(vdev);
> if (__vfio_pci_memory_enabled(vdev))
> - vfio_pci_dma_buf_move(vdev, false);
> + vfio_pci_unrevoke_bars(vdev);
> up_write(&vdev->memory_lock);
> }
>
> @@ -1256,6 +1255,8 @@ static int vfio_pci_ioctl_set_irqs(struct vfio_pci_core_device *vdev,
> return ret;
> }
>
> +static void vfio_pci_zap_revoke_bars(struct vfio_pci_core_device *vdev);
> +
> static int vfio_pci_ioctl_reset(struct vfio_pci_core_device *vdev,
> void __user *arg)
> {
> @@ -1264,7 +1265,7 @@ static int vfio_pci_ioctl_reset(struct vfio_pci_core_device *vdev,
> if (!vdev->reset_works)
> return -EINVAL;
>
> - vfio_pci_zap_and_down_write_memory_lock(vdev);
> + down_write(&vdev->memory_lock);
>
> /*
> * This function can be invoked while the power state is non-D0. If
> @@ -1277,10 +1278,11 @@ static int vfio_pci_ioctl_reset(struct vfio_pci_core_device *vdev,
> */
> vfio_pci_set_power_state(vdev, PCI_D0);
>
> - vfio_pci_dma_buf_move(vdev, true);
> + vfio_pci_zap_revoke_bars(vdev);
I'm wondering if this change in behavior is correct?
BEFORE this patch the sequence was:
1. zap vma mappings
2. Enter D0
After this patch the sequence becomes
1. Take the lock
2. Enter D0
3. zap vma mappings
My worry is if user-space accesses a BAR *during* the transition to D0,
it could crash since the mappings still exist during the transition?
The old code is immune to it because it removed user-mappings first.
Following the discussion from v1 regarding the ordering of
vfio_pci_dma_buf_move() and the D0 transition.. while it makes sense to
perform the DMABUF revocation/move after the hardware is in D0.. I'm not
too confident about moving zap after D0 :/
I mean, sure, the user would just see all Fs on a read and writes will
be dropped silently until we are in D0.. but the behaviour before this
change was that the user access will fault and hang on the memory_lock
instead which ensures that the user observes a consistent dev state..
> +
> ret = pci_try_reset_function(vdev->pdev);
> if (__vfio_pci_memory_enabled(vdev))
> - vfio_pci_dma_buf_move(vdev, false);
> + vfio_pci_unrevoke_bars(vdev);
> up_write(&vdev->memory_lock);
>
> return ret;
> @@ -1648,20 +1650,37 @@ ssize_t vfio_pci_core_write(struct vfio_device *core_vdev, const char __user *bu
> }
Thanks,
Praan
Most of this patch series has already been pushed upstream, this is just
the second half of the patch series that has not been pushed yet + some
additional changes which were required to implement changes requested by
the mailing list. This patch series is originally from Asahi, previously
posted by Daniel Almeida.
The previous version of the patch series can be found here:
https://patchwork.freedesktop.org/series/164580/
Branch with patches applied available here:
https://gitlab.freedesktop.org/lyudess/linux/-/commits/rust/gem-shmem
This patch series applies on top of drm-rust-next
Patch-series wide changes since V15:
* Fix some major rebasing errors I somehow didn't notice :(
* Drop the dependency on LazyInit, use the trick that Alice suggested
instead.
* Fix dependency ordering so that Tyr can get the vmap stuff first
without the other bits.
Patch-series wide changes since V16:
* Fix ordering one more time (SetOnce::reset() doesn't need to come
before adding vmap functions)
* Rebase against the latest DeviceContext changes from me that got
pushed.
Patch-series wide changes since V20:
* Lots of Sashiko fixes, excluding the comments that I couldn't prove
weren't just bogus.
Lyude Paul (4):
rust: drm: gem: shmem: Add DmaResvGuard helper
rust: drm: gem: shmem: Add vmap functions
rust: faux: Allow retrieving a bound Device
rust: drm: gem: Introduce shmem::Object::sg_table()
rust/kernel/drm/gem/shmem.rs | 546 ++++++++++++++++++++++++++++++++++-
rust/kernel/faux.rs | 16 +-
2 files changed, 546 insertions(+), 16 deletions(-)
base-commit: 848bf57e98e1678ce7a49eb4e0bf0502da95dc07
--
2.54.0