* Re: [PATCH 05/13] mm: prefer mm->def_vma_flags in mm logic
From: Zi Yan @ 2026-07-08 2:06 UTC (permalink / raw)
To: Lorenzo Stoakes, Andrew Morton
Cc: Thomas Bogendoerfer, Madhavan Srinivasan, Michael Ellerman,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Lucas Stach, Inki Dae, Seung-Woo Kim,
Kyungmin Park, Krzysztof Kozlowski, Peter Griffin, Jani Nikula,
Joonas Lahtinen, Rodrigo Vivi, Tvrtko Ursulin, Rob Clark,
Dmitry Baryshkov, Lyude Paul, Danilo Krummrich, Tomi Valkeinen,
Sandy Huang, Heiko Stübner, Andy Yan, Thierry Reding,
Mikko Perttunen, Jonathan Hunter, Gerd Hoffmann, Dmitry Osipenko,
Zack Rusin, Matthew Brost, Thomas Hellstrom,
Oleksandr Andrushchenko, Helge Deller, Benjamin LaHaise,
Alexander Viro, Christian Brauner, Muchun Song, Oscar Salvador,
David Hildenbrand, Baolin Wang, Liam R . Howlett, Nico Pache,
Ryan Roberts, Dev Jain, Barry Song, Lance Yang, Hugh Dickins,
Vlastimil Babka, Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
Jann Horn, Pedro Falcato, Kees Cook, Jaroslav Kysela,
Takashi Iwai, linux-mips, linux-kernel, linuxppc-dev, dri-devel,
etnaviv, linux-arm-kernel, linux-samsung-soc, intel-gfx,
linux-arm-msm, freedreno, nouveau, linux-rockchip, linux-tegra,
virtualization, intel-xe, xen-devel, linux-fbdev, linux-aio,
linux-fsdevel, linux-mm, linux-sound
In-Reply-To: <3b4ccdc38819b42ddc79ee5a795831208ac7986c.1782760670.git.ljs@kernel.org>
On Mon Jun 29, 2026 at 3:25 PM EDT, Lorenzo Stoakes wrote:
> Currently mm->def_flags (of type vm_flags_t) is union'd with
> mm->def_vma_flags (of type vma_flags_t).
>
> As part of the effort to convert vm_flags_t usage to vma_flags_t (in order
> to no longer be arbitrarily limited to a system word size for VMA flags),
> prefer mm->def_vma_flags to mm->def_flags throughout the mm logic.
>
> No functional change intended.
>
> Signed-off-by: Lorenzo Stoakes <ljs@kernel.org>
> ---
> mm/debug.c | 2 +-
> mm/mlock.c | 13 +++++++------
> mm/mmap.c | 11 ++++++-----
> mm/vma.c | 4 ++--
> 4 files changed, 16 insertions(+), 14 deletions(-)
>
LGTM.
Reviewed-by: Zi Yan <ziy@nvidia.com>
--
Best Regards,
Yan, Zi
^ permalink raw reply
* [PATCH v4] virtio_balloon: prime stats vq after virtio_device_ready()
From: Michael S. Tsirkin @ 2026-07-07 21:00 UTC (permalink / raw)
To: linux-kernel
Cc: David Hildenbrand, Jason Wang, Xuan Zhuo, Eugenio Pérez,
Adam Litke, Rusty Russell, virtualization
The virtio spec requires the driver not to kick the device before
DRIVER_OK is set. init_vqs() primes the stats virtqueue with a buffer
and kicks the device before virtio_device_ready() is called in
virtballoon_probe(), violating this requirement.
Further, if the device responds to the early kick by processing the
buffer before DRIVER_OK, stats_request() fires and queues
update_balloon_stats_work. Should probe then fail and free vb, the work
runs against freed memory.
To fix, move buffer setup to after DRIVER_OK. Be careful to
disable update_balloon_stats_work while this is going on,
to make sure it does not race with the setup.
Testing: tested that stats still work after the change.
Fixes: 9564e138b1f6 ("virtio: Add memory statistics reporting to the balloon driver (V4)")
Reported-by: Sashiko:gemini-3.1-pro-preview
Cc: David Hildenbrand <david@kernel.org>
Assisted-by: Claude:claude-sonnet-4-6
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
v4: extract stats_update_and_send() helper; call get_buf() before
updating stats buffer in stats_handle_request().
also ignore add bug failures (never trigger anyway) (reported by sashiko)
v3: add disable_work comment and BUG_ON -> WARN_ON_ONCE (David Hildenbrand)
v2: check that work enable/disable is balanced; explain how add_outbuf
never fails in probe/restore
drivers/virtio/virtio_balloon.c | 67 +++++++++++++++++++--------------
1 file changed, 39 insertions(+), 28 deletions(-)
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
index 088b3a0e6ce6..4c4b9bea4356 100644
--- a/drivers/virtio/virtio_balloon.c
+++ b/drivers/virtio/virtio_balloon.c
@@ -417,6 +417,17 @@ static unsigned int update_balloon_stats(struct virtio_balloon *vb)
return idx;
}
+static void stats_update_and_send(struct virtio_balloon *vb)
+{
+ struct scatterlist sg;
+ unsigned int num_stats;
+
+ num_stats = update_balloon_stats(vb);
+ sg_init_one(&sg, vb->stats, sizeof(vb->stats[0]) * num_stats);
+ virtqueue_add_outbuf(vb->stats_vq, &sg, 1, vb, GFP_KERNEL);
+ virtqueue_kick(vb->stats_vq);
+}
+
/*
* While most virtqueues communicate guest-initiated requests to the hypervisor,
* the stats queue operates in reverse. The driver initializes the virtqueue
@@ -440,18 +451,11 @@ static void stats_request(struct virtqueue *vq)
static void stats_handle_request(struct virtio_balloon *vb)
{
- struct virtqueue *vq;
- struct scatterlist sg;
- unsigned int len, num_stats;
+ unsigned int len;
- num_stats = update_balloon_stats(vb);
-
- vq = vb->stats_vq;
- if (!virtqueue_get_buf(vq, &len))
+ if (!virtqueue_get_buf(vb->stats_vq, &len))
return;
- sg_init_one(&sg, vb->stats, sizeof(vb->stats[0]) * num_stats);
- virtqueue_add_outbuf(vq, &sg, 1, vb, GFP_KERNEL);
- virtqueue_kick(vq);
+ stats_update_and_send(vb);
}
static inline s64 towards_target(struct virtio_balloon *vb)
@@ -611,25 +615,9 @@ static int init_vqs(struct virtio_balloon *vb)
vb->inflate_vq = vqs[VIRTIO_BALLOON_VQ_INFLATE];
vb->deflate_vq = vqs[VIRTIO_BALLOON_VQ_DEFLATE];
if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_STATS_VQ)) {
- struct scatterlist sg;
- unsigned int num_stats;
vb->stats_vq = vqs[VIRTIO_BALLOON_VQ_STATS];
-
- /*
- * Prime this virtqueue with one buffer so the hypervisor can
- * use it to signal us later (it can't be broken yet!).
- */
- num_stats = update_balloon_stats(vb);
-
- sg_init_one(&sg, vb->stats, sizeof(vb->stats[0]) * num_stats);
- err = virtqueue_add_outbuf(vb->stats_vq, &sg, 1, vb,
- GFP_KERNEL);
- if (err) {
- dev_warn(&vb->vdev->dev, "%s: add stat_vq failed\n",
- __func__);
- return err;
- }
- virtqueue_kick(vb->stats_vq);
+ /* Prevent update_balloon_stats_work from accessing the stats vq. */
+ disable_work(&vb->update_balloon_stats_work);
}
if (virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT))
@@ -916,6 +904,25 @@ static int virtio_balloon_register_shrinker(struct virtio_balloon *vb)
return 0;
}
+static void setup_vqs(struct virtio_balloon *vb)
+{
+ bool ret;
+
+ if (!virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_STATS_VQ))
+ return;
+
+ /*
+ * Prime this virtqueue with one buffer so the hypervisor can
+ * use it to signal us later (it can't be broken yet!).
+ */
+ stats_update_and_send(vb);
+
+ ret = enable_and_queue_work(system_freezable_wq,
+ &vb->update_balloon_stats_work);
+ /* Make sure we balanced enable/disable, or we won't report stats. */
+ WARN_ON_ONCE(!ret);
+}
+
static int virtballoon_probe(struct virtio_device *vdev)
{
struct virtio_balloon *vb;
@@ -1059,6 +1066,8 @@ static int virtballoon_probe(struct virtio_device *vdev)
virtio_device_ready(vdev);
+ setup_vqs(vb);
+
if (towards_target(vb))
virtballoon_changed(vdev);
return 0;
@@ -1148,6 +1157,8 @@ static int virtballoon_restore(struct virtio_device *vdev)
virtio_device_ready(vdev);
+ setup_vqs(vb);
+
if (towards_target(vb))
virtballoon_changed(vdev);
update_balloon_size(vb);
--
MST
^ permalink raw reply related
* Re: [PATCH] drm/virtio: Don't detach GEM from a non-created context
From: Yiwei Zhang @ 2026-07-07 19:01 UTC (permalink / raw)
To: Dmitry Osipenko
Cc: Jason Macnak, David Airlie, Gerd Hoffmann, Gurchetan Singh,
dri-devel, virtualization, linux-kernel, stable
In-Reply-To: <7202d2dc-b6fe-440e-88b0-aefb26c38b86@collabora.com>
On Mon, Jun 29, 2026 at 2:39 PM Dmitry Osipenko
<dmitry.osipenko@collabora.com> wrote:
>
> Hi,
>
> On 6/25/26 20:08, Jason Macnak wrote:
> > Applies the same treatment as commit 7cf6dd467e87 ("drm/virtio:
> > Don't attach GEM to a non-created context in gem_object_open()")
> > to virtio_gpu_gem_object_close() to avoid trying to detach
> > a resource that was never attached due to a context
> > never being created when context_init is supported.
> >
> > Fixes: 086b9f27f0ab ("drm/virtio: Don't create a context with default param if context_init is supported")
> > Cc: <stable@vger.kernel.org> # v6.14+
> > Signed-off-by: Jason Macnak <natsu@google.com>
> > ---
> > drivers/gpu/drm/virtio/virtgpu_gem.c | 14 ++++++++------
> > 1 file changed, 8 insertions(+), 6 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/virtio/virtgpu_gem.c b/drivers/gpu/drm/virtio/virtgpu_gem.c
> > index 435d37d36034..66c3f6f74e9c 100644
> > --- a/drivers/gpu/drm/virtio/virtgpu_gem.c
> > +++ b/drivers/gpu/drm/virtio/virtgpu_gem.c
> > @@ -139,13 +139,15 @@ void virtio_gpu_gem_object_close(struct drm_gem_object *obj,
> > if (!vgdev->has_virgl_3d)
> > return;
> >
> > - objs = virtio_gpu_array_alloc(1);
> > - if (!objs)
> > - return;
> > - virtio_gpu_array_add_obj(objs, obj);
> > + if (vfpriv->context_created) {
> > + objs = virtio_gpu_array_alloc(1);
> > + if (!objs)
> > + return;
> > + virtio_gpu_array_add_obj(objs, obj);
> >
> > - virtio_gpu_cmd_context_detach_resource(vgdev, vfpriv->ctx_id,
> > - objs);
> > + virtio_gpu_cmd_context_detach_resource(vgdev, vfpriv->ctx_id,
> > + objs);
> > + }
> > virtio_gpu_notify(vgdev);
> > }
>
> The following scenario still will be troubling:
>
> 1. vgdev->has_context_init = true
> 2. virtio_gpu_gem_object_open() invoked, GEM created and not attached to ctx
> 3. virtio_gpu_context_init_ioctl() invoked, now vfpriv->context_created
> = true
> 4. virtio_gpu_gem_object_close() will detach resource that wasn't attached
>
> Add obj->ctx_attached member to struct virtio_gpu_object. See
> virtio_gpu_object_attach() that uses obj->attached, do the same for
> virtio_gpu_cmd_context_attach_resource().
>
> --
> Best regards,
> Dmitry
Hi Dmitry,
WIth context_init, resource attach/detach is per-context based. So a
simple obj->ctx_attached won't work. One would have to track in the
guest context_init ctx for whether a bo has been attached or not.
Another option is to accept this patch and live with the case you
mentioned. We can consider that "invalid" user behavior.
Best,
Yiwei
^ permalink raw reply
* [PATCH v2] drm/qxl: remove dependency on DRM simple helpers
From: Diogo Silva @ 2026-07-07 16:14 UTC (permalink / raw)
To: Dave Airlie, Gerd Hoffmann, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, David Airlie, Simona Vetter
Cc: virtualization, spice-devel, dri-devel, linux-kernel, Diogo Silva
Simple KMS helper are deprecated since they only add an intermediate
layer between drivers and the atomic modesetting.
This patch removes the drm_simple_encoder_init() helper usage in the
qxl display driver by open coding it and using the encoder atomic
helpers directly. This is a step to eventually get rid of this simple
KMS helper, once all drivers that use it have been converted.
Signed-off-by: Diogo Silva <diogompaissilva@gmail.com>
---
Changes in v2:
- fix type error
- Link to v1: https://lore.kernel.org/r/20260707-qxl-simple-v1-1-524f6316b5d5@gmail.com
---
drivers/gpu/drm/qxl/qxl_display.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
index a026bd35ef485..7f4178800afd7 100644
--- a/drivers/gpu/drm/qxl/qxl_display.c
+++ b/drivers/gpu/drm/qxl/qxl_display.c
@@ -31,12 +31,12 @@
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_edid.h>
+#include <drm/drm_encoder.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_plane_helper.h>
#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>
-#include <drm/drm_simple_kms_helper.h>
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_vblank.h>
#include <drm/drm_vblank_helper.h>
@@ -1095,6 +1095,10 @@ static const struct drm_connector_helper_funcs qxl_connector_helper_funcs = {
.best_encoder = qxl_best_encoder,
};
+static const struct drm_encoder_funcs qxl_encoder_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
static enum drm_connector_status qxl_conn_detect(
struct drm_connector *connector,
bool force)
@@ -1169,10 +1173,10 @@ static int qdev_output_init(struct drm_device *dev, int num_output)
drm_connector_init(dev, &qxl_output->base,
&qxl_connector_funcs, DRM_MODE_CONNECTOR_VIRTUAL);
- ret = drm_simple_encoder_init(dev, &qxl_output->enc,
- DRM_MODE_ENCODER_VIRTUAL);
+ ret = drm_encoder_init(dev, &qxl_output->enc, &qxl_encoder_funcs,
+ DRM_MODE_ENCODER_VIRTUAL, NULL);
if (ret) {
- drm_err(dev, "drm_simple_encoder_init() failed, error %d\n",
+ drm_err(dev, "drm_encoder_init() failed, error %d\n",
ret);
goto err_drm_connector_cleanup;
}
---
base-commit: ee2867b79f9bac3a6fc3221139b09598ce79099c
change-id: 20260707-qxl-simple-c01aa1a5c4eb
Best regards,
--
Diogo Silva <diogompaissilva@gmail.com>
^ permalink raw reply related
* [PATCH] drm/qxl: remove dependency on DRM simple helpers
From: Diogo Silva @ 2026-07-07 15:49 UTC (permalink / raw)
To: Dave Airlie, Gerd Hoffmann, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, David Airlie, Simona Vetter
Cc: virtualization, spice-devel, dri-devel, linux-kernel, Diogo Silva
Simple KMS helper are deprecated since they only add an intermediate
layer between drivers and the atomic modesetting.
This patch removes the drm_simple_encoder_init() helper usage in the
qxl display driver by open coding it and using the encoder atomic
helpers directly. This is a step to eventually get rid of this simple
KMS helper, once all drivers that use it have been converted.
Signed-off-by: Diogo Silva <diogompaissilva@gmail.com>
---
drivers/gpu/drm/qxl/qxl_display.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
index a026bd35ef485..236d027fbc9fe 100644
--- a/drivers/gpu/drm/qxl/qxl_display.c
+++ b/drivers/gpu/drm/qxl/qxl_display.c
@@ -31,12 +31,12 @@
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_edid.h>
+#include <drm/drm_encoder.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_plane_helper.h>
#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>
-#include <drm/drm_simple_kms_helper.h>
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_vblank.h>
#include <drm/drm_vblank_helper.h>
@@ -1095,6 +1095,10 @@ static const struct drm_connector_helper_funcs qxl_connector_helper_funcs = {
.best_encoder = qxl_best_encoder,
};
+static const struct drm_connector_funcs qxl_connector_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
static enum drm_connector_status qxl_conn_detect(
struct drm_connector *connector,
bool force)
@@ -1169,10 +1173,10 @@ static int qdev_output_init(struct drm_device *dev, int num_output)
drm_connector_init(dev, &qxl_output->base,
&qxl_connector_funcs, DRM_MODE_CONNECTOR_VIRTUAL);
- ret = drm_simple_encoder_init(dev, &qxl_output->enc,
- DRM_MODE_ENCODER_VIRTUAL);
+ ret = drm_encoder_init(dev, &qxl_output->enc, &qxl_connector_funcs,
+ DRM_MODE_ENCODER_VIRTUAL, NULL);
if (ret) {
- drm_err(dev, "drm_simple_encoder_init() failed, error %d\n",
+ drm_err(dev, "drm_encoder_init() failed, error %d\n",
ret);
goto err_drm_connector_cleanup;
}
---
base-commit: ee2867b79f9bac3a6fc3221139b09598ce79099c
change-id: 20260707-qxl-simple-c01aa1a5c4eb
Best regards,
--
Diogo Silva <diogompaissilva@gmail.com>
^ permalink raw reply related
* Re: [PATCH v2 2/3] drm/virtio: honor blob_alignment requirements
From: Dmitry Osipenko @ 2026-07-07 15:25 UTC (permalink / raw)
To: Alyssa Ross, Sergio Lopez, Yiwei Zhang, Sergi Blanch Torne,
Valentine Burley
Cc: Chia-I Wu, Jason Wang, Michael S. Tsirkin, Eugenio Pérez,
Xuan Zhuo, linux-kernel, Simona Vetter, Thomas Zimmermann,
David Airlie, Gurchetan Singh, Gerd Hoffmann, virtualization,
dri-devel, Maxime Ripard, Maarten Lankhorst
In-Reply-To: <akT1XEW766c7Imst@mbp.qyliss.net>
On 7/1/26 14:10, Alyssa Ross wrote:
> On Tue, Apr 28, 2026 at 09:44:49PM +0200, Sergio Lopez wrote:
>> If VIRTIO_GPU_F_BLOB_ALIGNMENT has been negotiated, blob size must be
>> aligned to blob_alignment. Validate this in verify_blob() so that
>> invalid requests are rejected early.
>>
>> Signed-off-by: Sergio Lopez <slp@redhat.com>
>
> FYI: this change breaks crosvm, which is squatting the 5 and 6 values
> of VIRTIO_GPU_F_* with different meanings. I've reported it as a
> crosvm bug, so hopefully it can be taken care of there.
>
> https://issuetracker.google.com/issues/529852979
>
>> ---
>> drivers/gpu/drm/virtio/virtgpu_ioctl.c | 5 +++++
>> 1 file changed, 5 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/virtio/virtgpu_ioctl.c b/drivers/gpu/drm/virtio/virtgpu_ioctl.c
>> index c33c057365f8..d0c4edf1eaf4 100644
>> --- a/drivers/gpu/drm/virtio/virtgpu_ioctl.c
>> +++ b/drivers/gpu/drm/virtio/virtgpu_ioctl.c
>> @@ -489,6 +489,11 @@ static int verify_blob(struct virtio_gpu_device *vgdev,
>> params->size = rc_blob->size;
>> params->blob = true;
>> params->blob_flags = rc_blob->blob_flags;
>> +
>> + if (vgdev->has_blob_alignment &&
>> + !IS_ALIGNED(params->size, vgdev->blob_alignment))
>> + return -EINVAL;
>> +
>> return 0;
>> }
>>
>> --
>> 2.53.0
>>
Thanks for the report. Indeed, crosvm will need to fix its experimental
caps. CI will likely run into this problem first once it will update
guest to 7.2+ kernel.
--
Best regards,
Dmitry
^ permalink raw reply
* Re: [PATCH] drm/virtio: defer hotplug event from dequeue worker to avoid deadlock
From: Dmitry Osipenko @ 2026-07-07 15:10 UTC (permalink / raw)
To: Ryosuke Yasuoka, David Airlie, Gerd Hoffmann, Gurchetan Singh,
Chia-I Wu, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Simona Vetter, Dmitry Baryshkov, Javier Martinez Canillas
Cc: dri-devel, virtualization, linux-kernel
In-Reply-To: <18beb213335dd544.57cdc20d9a554be2.724d3e176f79ad9@ryasuoka-thinkpadx1carbongen9.tokyo.csb>
On 7/3/26 08:58, Ryosuke Yasuoka wrote:
>
>
> On 02/07/2026 14:26, Dmitry Osipenko wrote:
>> On 7/1/26 12:23, Ryosuke Yasuoka wrote:
>>>
>>>
>>> On 30/06/2026 16:46, Dmitry Osipenko wrote:
>>>> Hi,
>>>>
>>>> On 6/30/26 12:16, Ryosuke Yasuoka wrote:
>>>>> A probe-time deadlock can occur between the dequeue worker and
>>>>> drm_client_register(). During probe, drm_client_register() holds
>>>>> clientlist_mutex and calls the fbdev hotplug callback, which triggers an
>>>>> atomic commit that ends up sleeping in virtio_gpu_queue_ctrl_sgs()
>>>>> waiting for virtqueue space. The dequeue worker that would free that
>>>>> space calls virtio_gpu_cmd_get_display_info_cb(), which invokes
>>>>> drm_kms_helper_hotplug_event() -> drm_client_dev_hotplug(), attempting
>>>>> to acquire the same clientlist_mutex. Since wake_up() is only called
>>>>> after the resp_cb loop, the probe thread is never woken and both threads
>>>>> deadlock.
>>>>>
>>>>> Fix this by deferring the hotplug notification from
>>>>> virtio_gpu_cmd_get_display_info_cb() to a separate work item. The
>>>>> display data (outputs[i].info) is still updated synchronously in the
>>>>> callback, and the deferred work only triggers a re-probe notification to
>>>>> DRM clients.
>>>>>
>>>>> Fixes: 27655b9bb9f0 ("drm/client: Send hotplug event after registering a client")
>>>>> Closes: https://syzkaller.appspot.com/bug?id=d6dd6f86d3aaf7eebe7406e45c1c6e549453f224
>>>>> Closes: https://syzkaller.appspot.com/bug?id=908bd910da5dd79b88de4cf7baf376cc873a922e
>>>>> Signed-off-by: Ryosuke Yasuoka <ryasuoka@redhat.com>
>>>>> ---
>>>>> drivers/gpu/drm/virtio/virtgpu_drv.h | 3 +++
>>>>> drivers/gpu/drm/virtio/virtgpu_kms.c | 3 +++
>>>>> drivers/gpu/drm/virtio/virtgpu_vq.c | 12 ++++++++++--
>>>>> 3 files changed, 16 insertions(+), 2 deletions(-)
>>>>>
>>>>> diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h
>>>>> index 7449907754a4..27ffa4697ae9 100644
>>>>> --- a/drivers/gpu/drm/virtio/virtgpu_drv.h
>>>>> +++ b/drivers/gpu/drm/virtio/virtgpu_drv.h
>>>>> @@ -264,6 +264,8 @@ struct virtio_gpu_device {
>>>>>
>>>>> struct work_struct config_changed_work;
>>>>>
>>>>> + struct work_struct hotplug_work;
>>>>> +
>>>>> struct work_struct obj_free_work;
>>>>> spinlock_t obj_free_lock;
>>>>> struct list_head obj_free_list;
>>>>> @@ -350,6 +352,7 @@ void virtio_gpu_cmd_transfer_to_host_2d(struct virtio_gpu_device *vgdev,
>>>>> uint32_t x, uint32_t y,
>>>>> struct virtio_gpu_object_array *objs,
>>>>> struct virtio_gpu_fence *fence);
>>>>> +void virtio_gpu_hotplug_work_func(struct work_struct *work);
>>>>> void virtio_gpu_panic_cmd_resource_flush(struct virtio_gpu_device *vgdev,
>>>>> uint32_t resource_id,
>>>>> uint32_t x, uint32_t y,
>>>>> diff --git a/drivers/gpu/drm/virtio/virtgpu_kms.c b/drivers/gpu/drm/virtio/virtgpu_kms.c
>>>>> index cfde9f573df6..cfb532ba43a4 100644
>>>>> --- a/drivers/gpu/drm/virtio/virtgpu_kms.c
>>>>> +++ b/drivers/gpu/drm/virtio/virtgpu_kms.c
>>>>> @@ -154,6 +154,8 @@ int virtio_gpu_init(struct virtio_device *vdev, struct drm_device *dev)
>>>>> INIT_WORK(&vgdev->config_changed_work,
>>>>> virtio_gpu_config_changed_work_func);
>>>>>
>>>>> + INIT_WORK(&vgdev->hotplug_work, virtio_gpu_hotplug_work_func);
>>>>> +
>>>>> INIT_WORK(&vgdev->obj_free_work,
>>>>> virtio_gpu_array_put_free_work);
>>>>> INIT_LIST_HEAD(&vgdev->obj_free_list);
>>>>> @@ -293,6 +295,7 @@ void virtio_gpu_deinit(struct drm_device *dev)
>>>>> flush_work(&vgdev->obj_free_work);
>>>>> flush_work(&vgdev->ctrlq.dequeue_work);
>>>>> flush_work(&vgdev->cursorq.dequeue_work);
>>>>> + flush_work(&vgdev->hotplug_work);
>>>>> flush_work(&vgdev->config_changed_work);
>>>>> virtio_reset_device(vgdev->vdev);
>>>>> vgdev->vdev->config->del_vqs(vgdev->vdev);
>>>>> diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c
>>>>> index 67865810a2e7..084d98f5dc7b 100644
>>>>> --- a/drivers/gpu/drm/virtio/virtgpu_vq.c
>>>>> +++ b/drivers/gpu/drm/virtio/virtgpu_vq.c
>>>>> @@ -816,6 +816,15 @@ virtio_gpu_cmd_resource_detach_backing(struct virtio_gpu_device *vgdev,
>>>>> virtio_gpu_queue_fenced_ctrl_buffer(vgdev, vbuf, fence);
>>>>> }
>>>>>
>>>>> +void virtio_gpu_hotplug_work_func(struct work_struct *work)
>>>>> +{
>>>>> + struct virtio_gpu_device *vgdev =
>>>>> + container_of(work, struct virtio_gpu_device, hotplug_work);
>>>>> +
>>>>> + if (!drm_helper_hpd_irq_event(vgdev->ddev))
>>>>> + drm_kms_helper_hotplug_event(vgdev->ddev);
>>>>> +}
>>>>> +
>>>>> static void virtio_gpu_cmd_get_display_info_cb(struct virtio_gpu_device *vgdev,
>>>>> struct virtio_gpu_vbuffer *vbuf)
>>>>> {
>>>>> @@ -841,8 +850,7 @@ static void virtio_gpu_cmd_get_display_info_cb(struct virtio_gpu_device *vgdev,
>>>>> spin_unlock(&vgdev->display_info_lock);
>>>>> wake_up(&vgdev->resp_wq);
>>>>>
>>>>> - if (!drm_helper_hpd_irq_event(vgdev->ddev))
>>>>> - drm_kms_helper_hotplug_event(vgdev->ddev);
>>>>> + schedule_work(&vgdev->hotplug_work);
>>>>> }
>>>>>
>>>>> static void virtio_gpu_cmd_get_capset_info_cb(struct virtio_gpu_device *vgdev,
>>>>
>>>
>>> Hi,
>>> Thank you for your review.
>>>
>>>> Could you please move drm_kms_helper_hotplug_event() to virtio_gpu_init(), placing it after wait_event_timeout(display_info_pending)? This will avoid additional work_struct that otherwise needs to be cancelled in virtio_gpu_init() on the timeout.
>>>
>>> IIUC, moving the drm_kms_helper_hotplug_event() and _hpd_irq_event()
>>> into virtio_gpu_init() after wait_event_timeout() would not prevent the
>>> issue.
>>>
>>> Looking at the syzbot call traces[1][2], the deadlock occurs during
>>> drm_client_setup(), which runs after virtio_gpu_init() has already
>>> returned. The display_info_cb that triggers the deadlock is called from
>>> the dequeue worker while drm_client_register() holds clientlist_mutex.
>>>
>>> Thread A:
>>> virtio_gpu_probe()
>>> -> virtio_gpu_init() // sends GET_DISPLAY_INFO and waits up to 5s
>>
>> You mean that the timeout happens and it's again syzkaller report for a
>> broken host. A day ago I applied [1] that should fix this "bogus"
>> syzkaller report.
>>
>> [1] https://patchwork.freedesktop.org/patch/735301/
>
> Thank you for [1] and the clarificaiton. I agree that [1] addresses the
> broken host scenario where virtio_gpu_init() times out and probe
> continues with a pending display_info response. I think there is another
> scenario causing the same deadlock reported by syzbot and my patch
> addresses both cases.
>
> The deadlock can also occur with the following scenario:
> after virtio_gpu_init() completes successfully (wait_event_timeout
> returns), if a config_changed event arrives before drm_client_setup()
> completes, config_changed_work_func() sends a new GET_DISPLAY_INFO. Its
> display_info_cb fires in the dequeue worker and blocks on
> clientlist_mutex held by drm_client_register(). This is the same
> deadlock path reported by syzbot.
>
> Since [1] only prevents the timeout case, I believe the schedule_work()
> approach is still needed to prevent display_info_cb from blocking on
> clientlist_mutex in the dequeue worker context, regardless of the
> trigger.
The config_changed_work_func() already invokes
drm_helper_hpd_irq_event() by itself [1].
[1]
https://elixir.bootlin.com/linux/v7.1.2/source/drivers/gpu/drm/virtio/virtgpu_kms.c#L52
The drm_helper_hpd_irq_event() itself calls
drm_kms_helper_hotplug_event() [2].
[2]
https://elixir.bootlin.com/linux/v7.1.2/source/drivers/gpu/drm/drm_probe_helper.c#L1113
Isn't drm_helper_hpd_irq_event() call done by
virtio_gpu_cmd_get_display_info_cb() already partially redundant? I.e.
only it's needed by virtio_gpu_init() and not by
config_changed_work_func(). And then we can move
drm_helper_hpd_irq_event() to virtio_gpu_init():
```
diff --git a/drivers/gpu/drm/virtio/virtgpu_kms.c
b/drivers/gpu/drm/virtio/virtgpu_kms.c
index 922782bdc9cd..9805283683c1 100644
--- a/drivers/gpu/drm/virtio/virtgpu_kms.c
+++ b/drivers/gpu/drm/virtio/virtgpu_kms.c
@@ -303,6 +303,7 @@ int virtio_gpu_init(struct virtio_device *vdev,
struct drm_device *dev)
virtio_gpu_notify(vgdev);
wait_event_timeout(vgdev->resp_wq,
!vgdev->display_info_pending,
5 * HZ);
+ drm_helper_hpd_irq_event(vgdev->ddev);
}
vgdev->pm_nb.notifier_call = virtio_gpu_pm_notifier;
diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c
b/drivers/gpu/drm/virtio/virtgpu_vq.c
index 68d097ad9d1d..aa6440a9b81e 100644
--- a/drivers/gpu/drm/virtio/virtgpu_vq.c
+++ b/drivers/gpu/drm/virtio/virtgpu_vq.c
@@ -880,9 +880,6 @@ static void
virtio_gpu_cmd_get_display_info_cb(struct virtio_gpu_device *vgdev,
vgdev->display_info_pending = false;
spin_unlock(&vgdev->display_info_lock);
wake_up(&vgdev->resp_wq);
-
- if (!drm_helper_hpd_irq_event(vgdev->ddev))
- drm_kms_helper_hotplug_event(vgdev->ddev);
}
static void virtio_gpu_cmd_get_capset_info_cb(struct virtio_gpu_device
*vgdev,
```
Isn't it a bug that config_changed_work_func() doesn't wait for
display_info_pending event?
```
diff --git a/drivers/gpu/drm/virtio/virtgpu_kms.c
b/drivers/gpu/drm/virtio/virtgpu_kms.c
index 922782bdc9cd..dd2d5c896c39 100644
--- a/drivers/gpu/drm/virtio/virtgpu_kms.c
+++ b/drivers/gpu/drm/virtio/virtgpu_kms.c
@@ -50,6 +50,8 @@ static void virtio_gpu_config_changed_work_func(struct
work_struct *work)
virtio_gpu_cmd_get_edids(vgdev);
virtio_gpu_cmd_get_display_info(vgdev);
virtio_gpu_notify(vgdev);
+ wait_event_timeout(vgdev->resp_wq,
!vgdev->display_info_pending,
+ 5 * HZ);
drm_helper_hpd_irq_event(vgdev->ddev);
}
events_clear |= VIRTIO_GPU_EVENT_DISPLAY;
```
--
Best regards,
Dmitry
^ permalink raw reply related
* [PATCH v5 2/2] vduse: Add suspend
From: Eugenio Pérez @ 2026-07-07 12:33 UTC (permalink / raw)
To: Michael S . Tsirkin
Cc: Jason Wang, linux-kernel, Laurent Vivier, Yongji Xie, Xuan Zhuo,
Stefano Garzarella, virtualization, Eugenio Pérez,
Maxime Coquelin
In-Reply-To: <20260707123344.244575-1-eperezma@redhat.com>
Implement suspend operation for vduse devices, so vhost-vdpa will offer
that backend feature and userspace can effectively suspend the device.
This is a must before get virtqueue indexes (base) for live migration,
since the device could modify them after userland gets them.
This patch does not implement resume, so VMM resets the whole device
to recover from a live migration failure. Resume optimization can be
implemented on top of these patches, as other vDPA devices have done in
the past.
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
---
drivers/vdpa/vdpa_user/vduse_dev.c | 95 +++++++++++++++++++++++++++---
include/uapi/linux/vduse.h | 4 ++
2 files changed, 92 insertions(+), 7 deletions(-)
diff --git a/drivers/vdpa/vdpa_user/vduse_dev.c b/drivers/vdpa/vdpa_user/vduse_dev.c
index 347afe7c6d92..0064891a08b2 100644
--- a/drivers/vdpa/vdpa_user/vduse_dev.c
+++ b/drivers/vdpa/vdpa_user/vduse_dev.c
@@ -54,7 +54,8 @@
#define IRQ_UNBOUND -1
/* Supported VDUSE features */
-static const uint64_t vduse_features = BIT_U64(VDUSE_F_QUEUE_READY);
+static const uint64_t vduse_features = BIT_U64(VDUSE_F_QUEUE_READY) |
+ BIT_U64(VDUSE_F_SUSPEND);
/*
* VDUSE instance have not asked the vduse API version, so assume 0.
@@ -86,6 +87,7 @@ struct vduse_virtqueue {
int irq_effective_cpu;
struct cpumask irq_affinity;
struct kobject kobj;
+ struct vduse_dev *dev;
};
struct vduse_dev;
@@ -135,6 +137,7 @@ struct vduse_dev {
int minor;
bool broken;
bool connected;
+ bool suspended;
u64 api_version;
u64 device_features;
u64 driver_features;
@@ -504,6 +507,7 @@ static void vduse_dev_reset(struct vduse_dev *dev)
}
scoped_guard(rwsem_write, &dev->rwsem) {
+ dev->suspended = false;
dev->status = 0;
dev->driver_features = 0;
dev->generation++;
@@ -564,6 +568,10 @@ static int vduse_vdpa_set_vq_address(struct vdpa_device *vdpa, u16 idx,
static void vduse_vq_kick(struct vduse_virtqueue *vq)
{
+ guard(rwsem_read)(&vq->dev->rwsem);
+ if (vq->dev->suspended)
+ return;
+
guard(spinlock)(&vq->kick_lock);
scoped_guard(spinlock_bh, &vq->ready_lock)
if (!vq->ready)
@@ -928,6 +936,27 @@ static int vduse_vdpa_set_map(struct vdpa_device *vdpa,
return 0;
}
+static int vduse_vdpa_suspend(struct vdpa_device *vdpa)
+{
+ struct vduse_dev *dev = vdpa_to_vduse(vdpa);
+ struct vduse_dev_msg msg = { 0 };
+ int ret;
+
+ msg.req.type = VDUSE_SUSPEND;
+
+ ret = vduse_dev_msg_sync(dev, &msg);
+ if (ret == 0) {
+ scoped_guard(rwsem_write, &dev->rwsem)
+ dev->suspended = true;
+
+ cancel_work_sync(&dev->inject);
+ for (u32 i = 0; i < dev->vq_num; i++)
+ cancel_work_sync(&dev->vqs[i]->inject);
+ }
+
+ return ret;
+}
+
static void vduse_vdpa_free(struct vdpa_device *vdpa)
{
struct vduse_dev *dev = vdpa_to_vduse(vdpa);
@@ -969,6 +998,41 @@ static const struct vdpa_config_ops vduse_vdpa_config_ops = {
.free = vduse_vdpa_free,
};
+static const struct vdpa_config_ops vduse_vdpa_config_ops_with_suspend = {
+ .set_vq_address = vduse_vdpa_set_vq_address,
+ .kick_vq = vduse_vdpa_kick_vq,
+ .set_vq_cb = vduse_vdpa_set_vq_cb,
+ .set_vq_num = vduse_vdpa_set_vq_num,
+ .get_vq_size = vduse_vdpa_get_vq_size,
+ .get_vq_group = vduse_get_vq_group,
+ .set_vq_ready = vduse_vdpa_set_vq_ready,
+ .get_vq_ready = vduse_vdpa_get_vq_ready,
+ .set_vq_state = vduse_vdpa_set_vq_state,
+ .get_vq_state = vduse_vdpa_get_vq_state,
+ .get_vq_align = vduse_vdpa_get_vq_align,
+ .get_device_features = vduse_vdpa_get_device_features,
+ .set_driver_features = vduse_vdpa_set_driver_features,
+ .get_driver_features = vduse_vdpa_get_driver_features,
+ .set_config_cb = vduse_vdpa_set_config_cb,
+ .get_vq_num_max = vduse_vdpa_get_vq_num_max,
+ .get_device_id = vduse_vdpa_get_device_id,
+ .get_vendor_id = vduse_vdpa_get_vendor_id,
+ .get_status = vduse_vdpa_get_status,
+ .set_status = vduse_vdpa_set_status,
+ .get_config_size = vduse_vdpa_get_config_size,
+ .get_config = vduse_vdpa_get_config,
+ .set_config = vduse_vdpa_set_config,
+ .get_generation = vduse_vdpa_get_generation,
+ .set_vq_affinity = vduse_vdpa_set_vq_affinity,
+ .get_vq_affinity = vduse_vdpa_get_vq_affinity,
+ .reset = vduse_vdpa_reset,
+ .set_map = vduse_vdpa_set_map,
+ .set_group_asid = vduse_set_group_asid,
+ .get_vq_map = vduse_get_vq_map,
+ .suspend = vduse_vdpa_suspend,
+ .free = vduse_vdpa_free,
+};
+
static void vduse_dev_sync_single_for_device(union virtio_map token,
dma_addr_t dma_addr, size_t size,
enum dma_data_direction dir)
@@ -1181,6 +1245,10 @@ static void vduse_dev_irq_inject(struct work_struct *work)
{
struct vduse_dev *dev = container_of(work, struct vduse_dev, inject);
+ guard(rwsem_read)(&dev->rwsem);
+ if (dev->suspended)
+ return;
+
spin_lock_bh(&dev->irq_lock);
if (dev->config_cb.callback)
dev->config_cb.callback(dev->config_cb.private);
@@ -1192,6 +1260,10 @@ static void vduse_vq_irq_inject(struct work_struct *work)
struct vduse_virtqueue *vq = container_of(work,
struct vduse_virtqueue, inject);
+ guard(rwsem_read)(&vq->dev->rwsem);
+ if (vq->dev->suspended)
+ return;
+
guard(spinlock_bh)(&vq->irq_lock);
guard(spinlock_bh)(&vq->ready_lock);
if (vq->ready && vq->cb.callback)
@@ -1202,6 +1274,10 @@ static bool vduse_vq_signal_irqfd(struct vduse_virtqueue *vq)
{
bool signal = false;
+ guard(rwsem_read)(&vq->dev->rwsem);
+ if (vq->dev->suspended)
+ return false;
+
if (!vq->cb.trigger)
return false;
@@ -1221,9 +1297,9 @@ static int vduse_dev_queue_irq_work(struct vduse_dev *dev,
{
int ret = -EINVAL;
- down_read(&dev->rwsem);
- if (!(dev->status & VIRTIO_CONFIG_S_DRIVER_OK))
- goto unlock;
+ guard(rwsem_read)(&dev->rwsem);
+ if (dev->suspended || !(dev->status & VIRTIO_CONFIG_S_DRIVER_OK))
+ return ret;
ret = 0;
if (irq_effective_cpu == IRQ_UNBOUND)
@@ -1231,8 +1307,6 @@ static int vduse_dev_queue_irq_work(struct vduse_dev *dev,
else
queue_work_on(irq_effective_cpu,
vduse_irq_bound_wq, irq_work);
-unlock:
- up_read(&dev->rwsem);
return ret;
}
@@ -1990,6 +2064,7 @@ static int vduse_dev_init_vqs(struct vduse_dev *dev, u32 vq_align, u32 vq_num)
}
dev->vqs[i]->index = i;
+ dev->vqs[i]->dev = dev;
dev->vqs[i]->irq_effective_cpu = IRQ_UNBOUND;
INIT_WORK(&dev->vqs[i]->inject, vduse_vq_irq_inject);
INIT_WORK(&dev->vqs[i]->kick, vduse_vq_kick_work);
@@ -2466,12 +2541,18 @@ static struct vduse_mgmt_dev *vduse_mgmt;
static int vduse_dev_init_vdpa(struct vduse_dev *dev, const char *name)
{
struct vduse_vdpa *vdev;
+ const struct vdpa_config_ops *ops;
if (dev->vdev)
return -EEXIST;
+ if (dev->vduse_features & BIT_U64(VDUSE_F_SUSPEND))
+ ops = &vduse_vdpa_config_ops_with_suspend;
+ else
+ ops = &vduse_vdpa_config_ops;
+
vdev = vdpa_alloc_device(struct vduse_vdpa, vdpa, dev->dev,
- &vduse_vdpa_config_ops, &vduse_map_ops,
+ ops, &vduse_map_ops,
dev->ngroups, dev->nas, name, true);
if (IS_ERR(vdev))
return PTR_ERR(vdev);
diff --git a/include/uapi/linux/vduse.h b/include/uapi/linux/vduse.h
index 7285f8570237..b7f8c04a0a44 100644
--- a/include/uapi/linux/vduse.h
+++ b/include/uapi/linux/vduse.h
@@ -17,6 +17,9 @@
/* The VDUSE instance expects a request for vq ready */
#define VDUSE_F_QUEUE_READY 0
+/* The VDUSE instance expects a request for suspend */
+#define VDUSE_F_SUSPEND 1
+
/*
* Get the version of VDUSE API that kernel supported (VDUSE_API_VERSION).
* This is used for future extension.
@@ -335,6 +338,7 @@ enum vduse_req_type {
VDUSE_UPDATE_IOTLB,
VDUSE_SET_VQ_GROUP_ASID,
VDUSE_SET_VQ_READY,
+ VDUSE_SUSPEND,
};
/**
--
2.55.0
^ permalink raw reply related
* [PATCH v5 1/2] vduse: do not take rwsem at reset work flush
From: Eugenio Pérez @ 2026-07-07 12:33 UTC (permalink / raw)
To: Michael S . Tsirkin
Cc: Jason Wang, linux-kernel, Laurent Vivier, Yongji Xie, Xuan Zhuo,
Stefano Garzarella, virtualization, Eugenio Pérez,
Maxime Coquelin
In-Reply-To: <20260707123344.244575-1-eperezma@redhat.com>
Next patches need to check suspend flag at this work item, and the
rwlock is used to protect the suspend flag update. If the work takes
the rwlock too it will produce a deadlock.
Make flushing work do nothing when called by de-initializing everything:
vq->ready, vq->kickfd, vq->cb.callback.
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
---
drivers/vdpa/vdpa_user/vduse_dev.c | 67 ++++++++++++++++--------------
1 file changed, 35 insertions(+), 32 deletions(-)
diff --git a/drivers/vdpa/vdpa_user/vduse_dev.c b/drivers/vdpa/vdpa_user/vduse_dev.c
index 307d13fbe942..347afe7c6d92 100644
--- a/drivers/vdpa/vdpa_user/vduse_dev.c
+++ b/drivers/vdpa/vdpa_user/vduse_dev.c
@@ -503,46 +503,49 @@ static void vduse_dev_reset(struct vduse_dev *dev)
vduse_domain_reset_bounce_map(domain);
}
- down_write(&dev->rwsem);
+ scoped_guard(rwsem_write, &dev->rwsem) {
+ dev->status = 0;
+ dev->driver_features = 0;
+ dev->generation++;
+ spin_lock(&dev->irq_lock);
+ dev->config_cb.callback = NULL;
+ dev->config_cb.private = NULL;
+ spin_unlock(&dev->irq_lock);
+
+ for (i = 0; i < dev->vq_num; i++) {
+ struct vduse_virtqueue *vq = dev->vqs[i];
+
+ scoped_guard(spinlock_bh, &vq->ready_lock) {
+ vq->ready = false;
+ }
+ vq->desc_addr = 0;
+ vq->driver_addr = 0;
+ vq->device_addr = 0;
+ vq->num = 0;
+ memset(&vq->state, 0, sizeof(vq->state));
+
+ spin_lock(&vq->kick_lock);
+ vq->kicked = false;
+ if (vq->kickfd)
+ eventfd_ctx_put(vq->kickfd);
+ vq->kickfd = NULL;
+ spin_unlock(&vq->kick_lock);
+
+ spin_lock(&vq->irq_lock);
+ vq->cb.callback = NULL;
+ vq->cb.private = NULL;
+ vq->cb.trigger = NULL;
+ spin_unlock(&vq->irq_lock);
+ }
+ }
- dev->status = 0;
- dev->driver_features = 0;
- dev->generation++;
- spin_lock(&dev->irq_lock);
- dev->config_cb.callback = NULL;
- dev->config_cb.private = NULL;
- spin_unlock(&dev->irq_lock);
flush_work(&dev->inject);
-
for (i = 0; i < dev->vq_num; i++) {
struct vduse_virtqueue *vq = dev->vqs[i];
- scoped_guard(spinlock_bh, &vq->ready_lock) {
- vq->ready = false;
- }
- vq->desc_addr = 0;
- vq->driver_addr = 0;
- vq->device_addr = 0;
- vq->num = 0;
- memset(&vq->state, 0, sizeof(vq->state));
-
- spin_lock(&vq->kick_lock);
- vq->kicked = false;
- if (vq->kickfd)
- eventfd_ctx_put(vq->kickfd);
- vq->kickfd = NULL;
- spin_unlock(&vq->kick_lock);
-
- spin_lock(&vq->irq_lock);
- vq->cb.callback = NULL;
- vq->cb.private = NULL;
- vq->cb.trigger = NULL;
- spin_unlock(&vq->irq_lock);
flush_work(&vq->inject);
flush_work(&vq->kick);
}
-
- up_write(&dev->rwsem);
}
static int vduse_vdpa_set_vq_address(struct vdpa_device *vdpa, u16 idx,
--
2.55.0
^ permalink raw reply related
* [PATCH v5 0/2] vduse: Add suspend
From: Eugenio Pérez @ 2026-07-07 12:33 UTC (permalink / raw)
To: Michael S . Tsirkin
Cc: Jason Wang, linux-kernel, Laurent Vivier, Yongji Xie, Xuan Zhuo,
Stefano Garzarella, virtualization, Eugenio Pérez,
Maxime Coquelin
Implement suspend operation for vduse devices, so vhost-vdpa will offer
that backend feature and userspace can effectively suspend the device.
This is a must before get virtqueue indexes (base) for live migration,
since the device could modify them after userland gets them.
This patch does not implement resume, so VMM resets the whole device
to recover from a live migration failure. Resume optimization can be
implemented on top of these patches, as other vDPA devices have done in
the past.
This series applies on top of
https://lore.kernel.org/lkml/20260707122502.239022-1-eperezma@redhat.com/
v5:
* Rebase on latest enable series
v4:
* Add preparatory patch to not flush the kick and irq works under rwsem
(MST).
* Fix jump over a semaphore guard (Nathan Chancellor).
* Fix take the device semaphore in the vq spinlock context (MST).
* Add suspend guard at vq_signal_irqfd so the device will not send an
IRQ after suspend.
v3:
* Expand the patch message with information about resume operation.
v2:
* Take the rwsem only before the actual kick, not in vduse_vdpa_kick_vq.
This assures that we're not in a critical section.
Eugenio Pérez (2):
vduse: do not take rwsem at reset work flush
vduse: Add suspend
drivers/vdpa/vdpa_user/vduse_dev.c | 162 ++++++++++++++++++++++-------
include/uapi/linux/vduse.h | 4 +
2 files changed, 127 insertions(+), 39 deletions(-)
--
2.55.0
^ permalink raw reply
* [PATCH v4 4/4] vduse: add F_QUEUE_READY feature
From: Eugenio Pérez @ 2026-07-07 12:25 UTC (permalink / raw)
To: Michael S . Tsirkin
Cc: Eugenio Pérez, Laurent Vivier, Yongji Xie, linux-kernel,
Stefano Garzarella, Jason Wang, Xuan Zhuo, virtualization,
Maxime Coquelin
In-Reply-To: <20260707122502.239022-1-eperezma@redhat.com>
Add the VDUSE_F_QUEUE_READY feature flag. This allows the kernel module
to explicitly signal userspace when a specific virtqueue has been
enabled.
In scenarios like Live Migration of VirtIO net devices, the dataplane
starts after the control virtqueue allowing QEMU to apply configuration
in the destination device.
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
---
v4:
* Create its own spinlock for vq->ready instead of relying on kick and
call spinlocks.
v2:
* Fix comment of vduse_dev_request.vq_ready
* Set vq_ready before sending the message to the VDUSE userland
instance, avoiding the need for SMP sync after receiving the message.
---
drivers/vdpa/vdpa_user/vduse_dev.c | 73 +++++++++++++++++++++++-------
include/uapi/linux/vduse.h | 18 ++++++++
2 files changed, 74 insertions(+), 17 deletions(-)
diff --git a/drivers/vdpa/vdpa_user/vduse_dev.c b/drivers/vdpa/vdpa_user/vduse_dev.c
index 4d561b9fbf5e..307d13fbe942 100644
--- a/drivers/vdpa/vdpa_user/vduse_dev.c
+++ b/drivers/vdpa/vdpa_user/vduse_dev.c
@@ -9,6 +9,7 @@
*/
#include "linux/virtio_net.h"
+#include <linux/bits.h>
#include <linux/cleanup.h>
#include <linux/init.h>
#include <linux/module.h>
@@ -53,7 +54,7 @@
#define IRQ_UNBOUND -1
/* Supported VDUSE features */
-static const uint64_t vduse_features;
+static const uint64_t vduse_features = BIT_U64(VDUSE_F_QUEUE_READY);
/*
* VDUSE instance have not asked the vduse API version, so assume 0.
@@ -77,6 +78,7 @@ struct vduse_virtqueue {
u32 group;
spinlock_t kick_lock;
spinlock_t irq_lock;
+ spinlock_t ready_lock;
struct eventfd_ctx *kickfd;
struct vdpa_callback cb;
struct work_struct inject;
@@ -120,6 +122,7 @@ struct vduse_dev {
char *name;
struct mutex lock;
spinlock_t msg_lock;
+ u64 vduse_features;
u64 msg_unique;
u32 msg_timeout;
wait_queue_head_t waitq;
@@ -514,7 +517,9 @@ static void vduse_dev_reset(struct vduse_dev *dev)
for (i = 0; i < dev->vq_num; i++) {
struct vduse_virtqueue *vq = dev->vqs[i];
- vq->ready = false;
+ scoped_guard(spinlock_bh, &vq->ready_lock) {
+ vq->ready = false;
+ }
vq->desc_addr = 0;
vq->driver_addr = 0;
vq->device_addr = 0;
@@ -556,16 +561,15 @@ static int vduse_vdpa_set_vq_address(struct vdpa_device *vdpa, u16 idx,
static void vduse_vq_kick(struct vduse_virtqueue *vq)
{
- spin_lock(&vq->kick_lock);
- if (!vq->ready)
- goto unlock;
+ guard(spinlock)(&vq->kick_lock);
+ scoped_guard(spinlock_bh, &vq->ready_lock)
+ if (!vq->ready)
+ return;
if (vq->kickfd)
eventfd_signal(vq->kickfd);
else
vq->kicked = true;
-unlock:
- spin_unlock(&vq->kick_lock);
}
static void vduse_vq_kick_work(struct work_struct *work)
@@ -625,7 +629,30 @@ static void vduse_vdpa_set_vq_ready(struct vdpa_device *vdpa,
{
struct vduse_dev *dev = vdpa_to_vduse(vdpa);
struct vduse_virtqueue *vq = dev->vqs[idx];
+ struct vduse_dev_msg msg = { 0 };
+ int r;
+
+ if (dev->vduse_features & BIT_U64(VDUSE_F_QUEUE_READY)) {
+ msg.req.type = VDUSE_SET_VQ_READY;
+ msg.req.vq_ready.num = idx;
+ msg.req.vq_ready.ready = !!ready;
+
+ r = vduse_dev_msg_sync(dev, &msg);
+
+ if (r < 0) {
+ dev_dbg(&vdpa->dev, "device refuses to set vq %u ready %u",
+ idx, ready);
+ /* We can't do better than break the device in this case */
+ spin_lock(&dev->msg_lock);
+ vduse_dev_broken(dev);
+ spin_unlock(&dev->msg_lock);
+
+ return;
+ }
+ }
+
+ guard(spinlock_bh)(&vq->ready_lock);
vq->ready = ready;
}
@@ -634,6 +661,7 @@ static bool vduse_vdpa_get_vq_ready(struct vdpa_device *vdpa, u16 idx)
struct vduse_dev *dev = vdpa_to_vduse(vdpa);
struct vduse_virtqueue *vq = dev->vqs[idx];
+ guard(spinlock_bh)(&vq->ready_lock);
return vq->ready;
}
@@ -1121,15 +1149,16 @@ static int vduse_kickfd_setup(struct vduse_dev *dev,
} else if (eventfd->fd != VDUSE_EVENTFD_DEASSIGN)
return 0;
- spin_lock(&vq->kick_lock);
+ guard(spinlock)(&vq->kick_lock);
if (vq->kickfd)
eventfd_ctx_put(vq->kickfd);
vq->kickfd = ctx;
+
+ guard(spinlock_bh)(&vq->ready_lock);
if (vq->ready && vq->kicked && vq->kickfd) {
eventfd_signal(vq->kickfd);
vq->kicked = false;
}
- spin_unlock(&vq->kick_lock);
return 0;
}
@@ -1160,10 +1189,10 @@ static void vduse_vq_irq_inject(struct work_struct *work)
struct vduse_virtqueue *vq = container_of(work,
struct vduse_virtqueue, inject);
- spin_lock_bh(&vq->irq_lock);
+ guard(spinlock_bh)(&vq->irq_lock);
+ guard(spinlock_bh)(&vq->ready_lock);
if (vq->ready && vq->cb.callback)
vq->cb.callback(vq->cb.private);
- spin_unlock_bh(&vq->irq_lock);
}
static bool vduse_vq_signal_irqfd(struct vduse_virtqueue *vq)
@@ -1173,12 +1202,12 @@ static bool vduse_vq_signal_irqfd(struct vduse_virtqueue *vq)
if (!vq->cb.trigger)
return false;
- spin_lock_irq(&vq->irq_lock);
+ guard(spinlock_irq)(&vq->irq_lock);
+ guard(spinlock_irq)(&vq->ready_lock);
if (vq->ready && vq->cb.trigger) {
eventfd_signal(vq->cb.trigger);
signal = true;
}
- spin_unlock_irq(&vq->irq_lock);
return signal;
}
@@ -1516,7 +1545,9 @@ static long vduse_dev_ioctl(struct file *file, unsigned int cmd,
vq_info.split.avail_index =
vq->state.split.avail_index;
- vq_info.ready = vq->ready;
+ scoped_guard(spinlock_bh, &vq->ready_lock) {
+ vq_info.ready = vq->ready;
+ }
ret = -EFAULT;
if (copy_to_user(argp, &vq_info, sizeof(vq_info)))
@@ -1746,7 +1777,9 @@ static long vduse_dev_compat_ioctl(struct file *file, unsigned int cmd,
vq_info.split.avail_index =
vq->state.split.avail_index;
- vq_info.ready = vq->ready;
+ scoped_guard(spinlock_bh, &vq->ready_lock) {
+ vq_info.ready = vq->ready;
+ }
ret = -EFAULT;
if (copy_to_user(argp, &vq_info,
@@ -1959,6 +1992,7 @@ static int vduse_dev_init_vqs(struct vduse_dev *dev, u32 vq_align, u32 vq_num)
INIT_WORK(&dev->vqs[i]->kick, vduse_vq_kick_work);
spin_lock_init(&dev->vqs[i]->kick_lock);
spin_lock_init(&dev->vqs[i]->irq_lock);
+ spin_lock_init(&dev->vqs[i]->ready_lock);
cpumask_setall(&dev->vqs[i]->irq_affinity);
kobject_init(&dev->vqs[i]->kobj, &vq_type);
@@ -2194,7 +2228,8 @@ static struct attribute *vduse_dev_attrs[] = {
ATTRIBUTE_GROUPS(vduse_dev);
static int vduse_create_dev(struct vduse_dev_config *config,
- void *config_buf, u64 api_version)
+ void *config_buf, u64 api_version,
+ uint64_t vduse_features)
{
int ret;
struct vduse_dev *dev;
@@ -2216,6 +2251,9 @@ static int vduse_create_dev(struct vduse_dev_config *config,
dev->device_features = config->features;
dev->device_id = config->device_id;
dev->vendor_id = config->vendor_id;
+ dev->vduse_features = vduse_features;
+ dev_dbg(vduse_ctrl_dev, "Creating device %s with features 0x%llx",
+ config->name, vduse_features);
dev->nas = (dev->api_version < VDUSE_API_VERSION_1) ? 1 : config->nas;
dev->as = kzalloc_objs(dev->as[0], dev->nas);
@@ -2331,7 +2369,8 @@ static long vduse_ioctl(struct file *file, unsigned int cmd,
break;
}
config.name[VDUSE_NAME_MAX - 1] = '\0';
- ret = vduse_create_dev(&config, buf, control->api_version);
+ ret = vduse_create_dev(&config, buf, control->api_version,
+ control->vduse_features);
if (ret)
kvfree(buf);
break;
diff --git a/include/uapi/linux/vduse.h b/include/uapi/linux/vduse.h
index f14c965bb7f6..7285f8570237 100644
--- a/include/uapi/linux/vduse.h
+++ b/include/uapi/linux/vduse.h
@@ -14,6 +14,9 @@
#define VDUSE_API_VERSION_1 1
+/* The VDUSE instance expects a request for vq ready */
+#define VDUSE_F_QUEUE_READY 0
+
/*
* Get the version of VDUSE API that kernel supported (VDUSE_API_VERSION).
* This is used for future extension.
@@ -331,6 +334,7 @@ enum vduse_req_type {
VDUSE_SET_STATUS,
VDUSE_UPDATE_IOTLB,
VDUSE_SET_VQ_GROUP_ASID,
+ VDUSE_SET_VQ_READY,
};
/**
@@ -378,6 +382,15 @@ struct vduse_iova_range_v2 {
__u32 padding;
};
+/**
+ * struct vduse_vq_ready - Virtqueue ready request message
+ * @num: Virtqueue number
+ */
+struct vduse_vq_ready {
+ __u32 num;
+ __u32 ready;
+};
+
/**
* struct vduse_dev_request - control request
* @type: request type
@@ -388,6 +401,7 @@ struct vduse_iova_range_v2 {
* @iova: IOVA range for updating
* @iova_v2: IOVA range for updating if API_VERSION >= 1
* @vq_group_asid: ASID of a virtqueue group
+ * @vq_ready: Virtqueue ready request
* @padding: padding
*
* Structure used by read(2) on /dev/vduse/$NAME.
@@ -405,6 +419,10 @@ struct vduse_dev_request {
*/
struct vduse_iova_range_v2 iova_v2;
struct vduse_vq_group_asid vq_group_asid;
+
+ /* Only if VDUSE_F_QUEUE_READY is negotiated */
+ struct vduse_vq_ready vq_ready;
+
__u32 padding[32];
};
};
--
2.55.0
^ permalink raw reply related
* [PATCH v4 3/4] vduse: add VDUSE_SET_FEATURES ioctl
From: Eugenio Pérez @ 2026-07-07 12:25 UTC (permalink / raw)
To: Michael S . Tsirkin
Cc: Eugenio Pérez, Laurent Vivier, Yongji Xie, linux-kernel,
Stefano Garzarella, Jason Wang, Xuan Zhuo, virtualization,
Maxime Coquelin
In-Reply-To: <20260707122502.239022-1-eperezma@redhat.com>
Add an ioctl to allow VDUSE instances to set the VDUSE features
supported by the userland VDUSE instance.
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
---
v4: New in v4.
---
drivers/vdpa/vdpa_user/vduse_dev.c | 24 ++++++++++++++++++++++++
include/uapi/linux/vduse.h | 3 +++
2 files changed, 27 insertions(+)
diff --git a/drivers/vdpa/vdpa_user/vduse_dev.c b/drivers/vdpa/vdpa_user/vduse_dev.c
index e1930e38df7a..4d561b9fbf5e 100644
--- a/drivers/vdpa/vdpa_user/vduse_dev.c
+++ b/drivers/vdpa/vdpa_user/vduse_dev.c
@@ -160,6 +160,7 @@ struct vduse_dev_msg {
struct vduse_control {
u64 api_version;
+ u64 vduse_features;
};
static DEFINE_MUTEX(vduse_lock);
@@ -2349,7 +2350,29 @@ static long vduse_ioctl(struct file *file, unsigned int cmd,
case VDUSE_GET_FEATURES:
ret = put_user(vduse_features, (u64 __user *)argp);
break;
+ case VDUSE_SET_FEATURES: {
+ u64 features;
+ ret = -EFAULT;
+ if (get_user(features, (u64 __user *)argp)) {
+ dev_dbg(vduse_ctrl_dev, "Could not get vduse features");
+ break;
+ }
+
+ ret = -EINVAL;
+ if (features & ~vduse_features) {
+ dev_dbg(vduse_ctrl_dev,
+ "Invalid features in %llx, expected %llx",
+ features, vduse_features);
+ break;
+ }
+
+ ret = 0;
+ control->vduse_features = features;
+ dev_dbg(vduse_ctrl_dev, "Set features %llx", features);
+
+ break;
+ }
default:
ret = -EINVAL;
break;
@@ -2376,6 +2399,7 @@ static int vduse_open(struct inode *inode, struct file *file)
return -ENOMEM;
control->api_version = VDUSE_API_VERSION_NOT_ASKED;
+ control->vduse_features = 0;
file->private_data = control;
return 0;
diff --git a/include/uapi/linux/vduse.h b/include/uapi/linux/vduse.h
index 89aa3b448c0a..f14c965bb7f6 100644
--- a/include/uapi/linux/vduse.h
+++ b/include/uapi/linux/vduse.h
@@ -66,6 +66,9 @@ struct vduse_dev_config {
/* Get the VDUSE supported features */
#define VDUSE_GET_FEATURES _IOR(VDUSE_BASE, 0x04, __u64)
+/* Set the VDUSE features */
+#define VDUSE_SET_FEATURES _IOW(VDUSE_BASE, 0x05, __u64)
+
/* The ioctls for VDUSE device (/dev/vduse/$NAME) */
/**
--
2.55.0
^ permalink raw reply related
* [PATCH v4 2/4] vduse: add VDUSE_GET_FEATURES ioctl
From: Eugenio Pérez @ 2026-07-07 12:25 UTC (permalink / raw)
To: Michael S . Tsirkin
Cc: Eugenio Pérez, Laurent Vivier, Yongji Xie, linux-kernel,
Stefano Garzarella, Jason Wang, Xuan Zhuo, virtualization,
Maxime Coquelin
In-Reply-To: <20260707122502.239022-1-eperezma@redhat.com>
Add an ioctl to allow VDUSE instances to query the available features
supported by the kernel module.
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
---
v4:
* Store the features in VDUSE control instead of vduse device config.
v3:
* Remove check for API_VERSION < 2
* Add comment about struct vduse_dev_config:vduse_features is only valid
if VDUSE_GET_FEATURES success.
v2:
* return -EINVAL if ioctl called with version < 2, so userland visible
reply is kept (Jason).
---
drivers/vdpa/vdpa_user/vduse_dev.c | 7 +++++++
include/uapi/linux/vduse.h | 3 +++
2 files changed, 10 insertions(+)
diff --git a/drivers/vdpa/vdpa_user/vduse_dev.c b/drivers/vdpa/vdpa_user/vduse_dev.c
index 2af5cb5e1ec6..e1930e38df7a 100644
--- a/drivers/vdpa/vdpa_user/vduse_dev.c
+++ b/drivers/vdpa/vdpa_user/vduse_dev.c
@@ -52,6 +52,9 @@
#define IRQ_UNBOUND -1
+/* Supported VDUSE features */
+static const uint64_t vduse_features;
+
/*
* VDUSE instance have not asked the vduse API version, so assume 0.
*
@@ -2343,6 +2346,10 @@ static long vduse_ioctl(struct file *file, unsigned int cmd,
ret = vduse_destroy_dev(name);
break;
}
+ case VDUSE_GET_FEATURES:
+ ret = put_user(vduse_features, (u64 __user *)argp);
+ break;
+
default:
ret = -EINVAL;
break;
diff --git a/include/uapi/linux/vduse.h b/include/uapi/linux/vduse.h
index 361eea511c21..89aa3b448c0a 100644
--- a/include/uapi/linux/vduse.h
+++ b/include/uapi/linux/vduse.h
@@ -63,6 +63,9 @@ struct vduse_dev_config {
*/
#define VDUSE_DESTROY_DEV _IOW(VDUSE_BASE, 0x03, char[VDUSE_NAME_MAX])
+/* Get the VDUSE supported features */
+#define VDUSE_GET_FEATURES _IOR(VDUSE_BASE, 0x04, __u64)
+
/* The ioctls for VDUSE device (/dev/vduse/$NAME) */
/**
--
2.55.0
^ permalink raw reply related
* [PATCH v4 1/4] vduse: store control device pointer
From: Eugenio Pérez @ 2026-07-07 12:24 UTC (permalink / raw)
To: Michael S . Tsirkin
Cc: Eugenio Pérez, Laurent Vivier, Yongji Xie, linux-kernel,
Stefano Garzarella, Jason Wang, Xuan Zhuo, virtualization,
Maxime Coquelin
In-Reply-To: <20260707122502.239022-1-eperezma@redhat.com>
This helps log the errors in next patches. The alternative is to
perform a linear search for it with class_find_device_by_devt(class, devt),
as device_destroy do for cleaning.
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
---
v4: Set control device pointer to NULL at device create error.
---
drivers/vdpa/vdpa_user/vduse_dev.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/drivers/vdpa/vdpa_user/vduse_dev.c b/drivers/vdpa/vdpa_user/vduse_dev.c
index f15ad425e01f..2af5cb5e1ec6 100644
--- a/drivers/vdpa/vdpa_user/vduse_dev.c
+++ b/drivers/vdpa/vdpa_user/vduse_dev.c
@@ -164,6 +164,7 @@ static DEFINE_IDR(vduse_idr);
static dev_t vduse_major;
static struct cdev vduse_ctrl_cdev;
+static const struct device *vduse_ctrl_dev;
static struct cdev vduse_cdev;
static struct workqueue_struct *vduse_irq_wq;
static struct workqueue_struct *vduse_irq_bound_wq;
@@ -2532,7 +2533,6 @@ static void vduse_mgmtdev_exit(void)
static int vduse_init(void)
{
int ret;
- struct device *dev;
ret = class_register(&vduse_class);
if (ret)
@@ -2549,9 +2549,10 @@ static int vduse_init(void)
if (ret)
goto err_ctrl_cdev;
- dev = device_create(&vduse_class, NULL, vduse_major, NULL, "control");
- if (IS_ERR(dev)) {
- ret = PTR_ERR(dev);
+ vduse_ctrl_dev = device_create(&vduse_class, NULL, vduse_major, NULL, "control");
+ if (IS_ERR(vduse_ctrl_dev)) {
+ ret = PTR_ERR(vduse_ctrl_dev);
+ vduse_ctrl_dev = NULL;
goto err_device;
}
--
2.55.0
^ permalink raw reply related
* [PATCH v4 0/4] Add queue ready message to VDUSE
From: Eugenio Pérez @ 2026-07-07 12:24 UTC (permalink / raw)
To: Michael S . Tsirkin
Cc: Eugenio Pérez, Laurent Vivier, Yongji Xie, linux-kernel,
Stefano Garzarella, Jason Wang, Xuan Zhuo, virtualization,
Maxime Coquelin
This series introduces a new VDUSE message for VDUSE userland instance
to detect when a VirtQueue (VQ) is enabled, replacing the polling.
VirtIO net devices' dataplane is started after the control virtqueue so
QEMU can apply the configuration in the destination of a Live Migration.
Without this feature, the VDUSE instance must poll the VQs to check when
(and if) a VQ has been enabled.
This series also implements VDUSE feature flags allowing the VDUSE
devices to opt-in to the VQ ready message. Devices that opt-in to this
feature will receive explicit notifications when a VQ is ready. Devices
that do not set this flag remain unaffected, ensuring backward
compatibility without indefinitely incrementing API versions.
The VDUSE features is a 64 bit bitmap for simplicity, the same way as
vhost and vhost-net started. It can be extended as a flexible array of
bits when we reach so many features, but it seems unlikely at this
point.
Error cases tested:
* Call VDUSE_GET_FEATURES without get the API VERSION (so API == 0) and
with API VERSION set to 1 with VDUSE_SET_API_VERSION (-EINVAL returned
from VDUSE_GET_FEATURES ioctl).
* Try to set invalid features.
* Test regular initialization of single queue devices with and without
VDUSE_F_QUEUE_READY set.
* Test expected behavior when VDUSE userland instance returns
VDUSE_REQ_RESULT_FAILED from VDUSE_SET_VQ_READY message.
* Repeat all the tests with multiqueue devices, by reverting
56e71885b0349 ("vduse: Temporarily fail if control queue feature requested").
v4:
* Create its own spinlock for vq->ready instead of relying on kick and
call spinlocks.
* Add VDUSE_SET_FEATURES ioctl and the corresponding validation paths instead
of using device config.
v3:
* Remove API_VERSION bump to 2
* Add comment about struct vduse_dev_config:vduse_features is only valid
if VDUSE_GET_FEATURES success.
v2:
* Fix comment of vduse_dev_request.vq_ready
* Set vq_ready before sending the message to the VDUSE userland
instance, avoiding the need for SMP sync after receiving the message.
* Return -EINVAL if control ioctl called with version < 2, so userland
visible reply is kept (Jason).
Eugenio Pérez (4):
vduse: store control device pointer
vduse: add VDUSE_GET_FEATURES ioctl
vduse: add VDUSE_SET_FEATURES ioctl
vduse: add F_QUEUE_READY feature
drivers/vdpa/vdpa_user/vduse_dev.c | 111 +++++++++++++++++++++++------
include/uapi/linux/vduse.h | 24 +++++++
2 files changed, 115 insertions(+), 20 deletions(-)
--
2.55.0
^ permalink raw reply
* Re: [PATCH 03/13] mm: convert __get_unmapped_area() to use vma_flags_t
From: Lorenzo Stoakes @ 2026-07-07 10:16 UTC (permalink / raw)
To: Zi Yan
Cc: Andrew Morton, Thomas Bogendoerfer, Madhavan Srinivasan,
Michael Ellerman, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, David Airlie, Simona Vetter, Lucas Stach,
Inki Dae, Seung-Woo Kim, Kyungmin Park, Krzysztof Kozlowski,
Peter Griffin, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
Tvrtko Ursulin, Rob Clark, Dmitry Baryshkov, Lyude Paul,
Danilo Krummrich, Tomi Valkeinen, Sandy Huang, Heiko Stübner,
Andy Yan, Thierry Reding, Mikko Perttunen, Jonathan Hunter,
Gerd Hoffmann, Dmitry Osipenko, Zack Rusin, Matthew Brost,
Thomas Hellstrom, Oleksandr Andrushchenko, Helge Deller,
Benjamin LaHaise, Alexander Viro, Christian Brauner, Muchun Song,
Oscar Salvador, David Hildenbrand, Baolin Wang, Liam R . Howlett,
Nico Pache, Ryan Roberts, Dev Jain, Barry Song, Lance Yang,
Hugh Dickins, Vlastimil Babka, Mike Rapoport, Suren Baghdasaryan,
Michal Hocko, Jann Horn, Pedro Falcato, Kees Cook,
Jaroslav Kysela, Takashi Iwai, linux-mips, linux-kernel,
linuxppc-dev, dri-devel, etnaviv, linux-arm-kernel,
linux-samsung-soc, intel-gfx, linux-arm-msm, freedreno, nouveau,
linux-rockchip, linux-tegra, virtualization, intel-xe, xen-devel,
linux-fbdev, linux-aio, linux-fsdevel, linux-mm, linux-sound
In-Reply-To: <DJRZGEZU5ESV.3IP5LEAUQJCBK@nvidia.com>
On Mon, Jul 06, 2026 at 10:28:24PM -0400, Zi Yan wrote:
> On Mon Jun 29, 2026 at 3:25 PM EDT, Lorenzo Stoakes wrote:
> > Update __get_unmapped_area() to be parameterised by vma_flags_t rather than
> > vm_flags_t as part of the effort to move VMA flags from a system word to a
> > bitmap.
> >
> > We cascade the changes up to arch_get_unmapped_area_topdown() and
> > arch_get_unmapped_area(), where, for now, we use vma_flags_to_legacy() in
> > order to propagate the VMA flags.
> >
> > No functional change intended.
> >
> > Signed-off-by: Lorenzo Stoakes <ljs@kernel.org>
> > ---
> > fs/hugetlbfs/inode.c | 3 ++-
> > include/linux/huge_mm.h | 10 +++++-----
> > include/linux/mm.h | 6 ++++--
> > include/linux/sched/mm.h | 12 ++++++------
> > mm/huge_memory.c | 21 ++++++++++++---------
> > mm/mmap.c | 27 ++++++++++++++-------------
> > 6 files changed, 43 insertions(+), 36 deletions(-)
> >
> <snip>
>
> > diff --git a/include/linux/sched/mm.h b/include/linux/sched/mm.h
> > index 95d0040df584..b301ec90740a 100644
> > --- a/include/linux/sched/mm.h
> > +++ b/include/linux/sched/mm.h
> > @@ -193,12 +193,12 @@ unsigned long mm_get_unmapped_area(struct file *filp, unsigned long addr,
> > unsigned long len, unsigned long pgoff,
> > unsigned long flags);
> >
> > -unsigned long mm_get_unmapped_area_vmflags(struct file *filp,
> > - unsigned long addr,
> > - unsigned long len,
> > - unsigned long pgoff,
> > - unsigned long flags,
> > - vm_flags_t vm_flags);
> > +unsigned long mm_get_unmapped_area_vmaflags(struct file *filp,
> > + unsigned long addr,
> > + unsigned long len,
> > + unsigned long pgoff,
> > + unsigned long flags,
> > + vma_flags_t vma_flags);
>
> Want to use two-tab indentation while at it?
Yeah sure will fix on respin!
>
> <snip>
>
> > @@ -812,19 +811,20 @@ arch_get_unmapped_area_topdown(struct file *filp, unsigned long addr,
> > }
> > #endif
> >
> > -unsigned long mm_get_unmapped_area_vmflags(struct file *filp, unsigned long addr,
> > - unsigned long len, unsigned long pgoff,
> > - unsigned long flags, vm_flags_t vm_flags)
> > +unsigned long mm_get_unmapped_area_vmaflags(struct file *filp, unsigned long addr,
> > + unsigned long len, unsigned long pgoff,
> > + unsigned long flags, vma_flags_t vma_flags)
>
> Ditto.
Ack will fix!
>
> LGTM.
>
> Reviewed-by: Zi Yan <ziy@nvidia.com>
Thanks!
>
>
> --
> Best Regards,
> Yan, Zi
>
Cheers, Lorenzo
^ permalink raw reply
* Re: [PATCH 02/13] mm/vma: update do_mmap() to use vma_flags_t
From: Lorenzo Stoakes @ 2026-07-07 10:15 UTC (permalink / raw)
To: Zi Yan
Cc: Andrew Morton, Thomas Bogendoerfer, Madhavan Srinivasan,
Michael Ellerman, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, David Airlie, Simona Vetter, Lucas Stach,
Inki Dae, Seung-Woo Kim, Kyungmin Park, Krzysztof Kozlowski,
Peter Griffin, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
Tvrtko Ursulin, Rob Clark, Dmitry Baryshkov, Lyude Paul,
Danilo Krummrich, Tomi Valkeinen, Sandy Huang, Heiko Stübner,
Andy Yan, Thierry Reding, Mikko Perttunen, Jonathan Hunter,
Gerd Hoffmann, Dmitry Osipenko, Zack Rusin, Matthew Brost,
Thomas Hellstrom, Oleksandr Andrushchenko, Helge Deller,
Benjamin LaHaise, Alexander Viro, Christian Brauner, Muchun Song,
Oscar Salvador, David Hildenbrand, Baolin Wang, Liam R . Howlett,
Nico Pache, Ryan Roberts, Dev Jain, Barry Song, Lance Yang,
Hugh Dickins, Vlastimil Babka, Mike Rapoport, Suren Baghdasaryan,
Michal Hocko, Jann Horn, Pedro Falcato, Kees Cook,
Jaroslav Kysela, Takashi Iwai, linux-mips, linux-kernel,
linuxppc-dev, dri-devel, etnaviv, linux-arm-kernel,
linux-samsung-soc, intel-gfx, linux-arm-msm, freedreno, nouveau,
linux-rockchip, linux-tegra, virtualization, intel-xe, xen-devel,
linux-fbdev, linux-aio, linux-fsdevel, linux-mm, linux-sound
In-Reply-To: <DJRZ2QCEIVA6.1AZF5S891NKS4@nvidia.com>
On Mon, Jul 06, 2026 at 10:10:32PM -0400, Zi Yan wrote:
> On Mon Jun 29, 2026 at 3:25 PM EDT, Lorenzo Stoakes wrote:
> > The core do_mmap() function accepts a vm_flags_t parameter which it then
> > manipulates before passing to mmap_region() to do the heavy lifting of the
> > memory mapping.
> >
> > Update do_mmap() to instead accept a vma_flags_t parameter, and adjust all
> > the logic within do_mmap() to manipulate this instead.
> >
> > This is as part of the ongoing effort to convert VMA flags from a system
> > word size to a bitmap type which allows us to unrestrict the number of VMA
> > flags, as well as gain control over how VMA flag manipulation occurs.
> >
> > We do not cascade these changes to all functions which accept vm_flags_t,
> > but rather use vma_flags_to_legacy() where necessary, specifically
> > deferring converting calc_vm_prot_bits(), calc_vm_flag_bits() and
> > __get_unmapped_area() to vma_flags_t.
> >
> > Also utilise the new vma_flags_can_grow() predicate which correctly handles
> > the case of architectures without upward growing stacks.
> >
> > As part of this change, introduce VMA_SHADOW_STACK so we can correctly
> > handle the case of the shadow stack not being defined.
> >
> > No functional change intended.
> >
> > Signed-off-by: Lorenzo Stoakes <ljs@kernel.org>
> > ---
> > arch/mips/kernel/vdso.c | 4 +--
> > fs/aio.c | 2 +-
> > include/linux/memfd.h | 6 ++--
> > include/linux/mm.h | 6 ++--
> > ipc/shm.c | 3 +-
> > mm/memfd.c | 15 ++++-----
> > mm/mmap.c | 67 ++++++++++++++++++++++++-----------------
> > mm/nommu.c | 3 +-
> > mm/util.c | 10 +++---
> > mm/vma.c | 7 ++---
> > mm/vma.h | 2 +-
> > 11 files changed, 69 insertions(+), 56 deletions(-)
> >
>
> <snip>
>
> >
> > -static int check_write_seal(vm_flags_t *vm_flags_ptr)
> > +static int check_write_seal(vma_flags_t *vma_flags_ptr)
> > {
> > - vm_flags_t vm_flags = *vm_flags_ptr;
> > - vm_flags_t mask = vm_flags & (VM_SHARED | VM_WRITE);
> > -
> > /* If a private mapping then writability is irrelevant. */
> > - if (!(mask & VM_SHARED))
> > + if (!vma_flags_test(vma_flags_ptr, VMA_SHARED_BIT))
> > return 0;
> >
> > /*
> > * New PROT_WRITE and MAP_SHARED mmaps are not allowed when
> > * write seals are active.
> > */
> > - if (mask & VM_WRITE)
> > + if (vma_flags_test(vma_flags_ptr, VMA_WRITE_BIT))
> > return -EPERM;
> >
> > /*
> > * This is a read-only mapping, disallow mprotect() from making a
> > * write-sealed mapping writable in future.
> > */
> > - *vm_flags_ptr &= ~VM_MAYWRITE;
> > + vma_flags_clear(vma_flags_ptr, VMA_MAYWRITE_BIT);
> >
> > return 0;
> > }
>
> This function alone changed its original behavior, since vm_flags is a
> snapshot of *vm_flags_ptr, but after the change this snapshot is gone.
> But its only caller memfd_check_seals_mmap() gets vm_flags_ptr from the
> input parameter of do_mmap(), so the overall behavior does not change.
Right yeah, the snapshot was always just a convenience thing :)
>
> <snip>
>
> > + case MAP_DROPPABLE: {
> > + vma_flags_t droppable = VMA_DROPPABLE;
> > +
> > + if (vma_flags_empty(&droppable))
> > return -EOPNOTSUPP;
> > + vma_flags_set_mask(&vma_flags, droppable);
> > +
> > /*
> > * A locked or stack area makes no sense to be droppable.
> > *
> > @@ -515,23 +527,24 @@ unsigned long do_mmap(struct file *file, unsigned long addr,
> > */
> > if (flags & (MAP_LOCKED | MAP_HUGETLB))
> > return -EINVAL;
> > - if (vm_flags & (VM_GROWSDOWN | VM_GROWSUP))
> > + if (vma_flags_can_grow(&vma_flags))
> > return -EINVAL;
> >
> > - vm_flags |= VM_DROPPABLE;
> > -
>
> Lance pointed out the reordering of setting VMA_DROPPABLE and checking
> of can_grow, but these flags are not overlapped and there is no parallel
> writer to vma_flags. So it is still no functional change, just not
> mechanical changes. :)
Right yes exactly :)
>
> Otherwise, LGTM.
>
> Reviewed-by: Zi Yan <ziy@nvidia.com>
Thanks!
>
> --
> Best Regards,
> Yan, Zi
>
Cheers, Lorenzo
^ permalink raw reply
* Re: [PATCH net 1/2] vsock/virtio: collapse receive queue under memory pressure
From: Stefano Garzarella @ 2026-07-07 9:27 UTC (permalink / raw)
To: Bobby Eshleman
Cc: netdev, Jason Wang, Jakub Kicinski, Paolo Abeni,
Michael S. Tsirkin, kvm, virtualization, Xuan Zhuo, Eric Dumazet,
Simon Horman, linux-kernel, Stefan Hajnoczi, David S. Miller,
Eugenio Pérez, stable, Brien Oberstein
In-Reply-To: <akbFcMHenseQW7mJ@devvm29614.prn0.facebook.com>
On Thu, Jul 02, 2026 at 01:09:20PM -0700, Bobby Eshleman wrote:
>On Thu, Jul 02, 2026 at 10:56:04AM +0200, Stefano Garzarella wrote:
>> On Wed, Jul 01, 2026 at 09:34:35AM -0700, Bobby Eshleman wrote:
>> > On Fri, Jun 26, 2026 at 03:48:22PM +0200, Stefano Garzarella wrote:
>>
>> [...]
>>
>> > > +out:
>> > > + if (new_skb)
>> > > + __skb_queue_tail(&new_queue, new_skb);
>> > > +
>> > > + skb_queue_splice(&new_queue, &vvs->rx_queue);
>> >
>> > I think the new skbs will also need skb_set_owner_sk_safe(skb, sk)
>> > when adding to rx_queue?
>>
>> IIRC we added it in the rx path, mainily for loopback to pass the ownership
>> from the tx socket to the rx socket, but here we are already in the rx path,
>> so the skb will never leave this socket.
>>
>
>Ah that's right, I stand corrected. There is no sender to leak in this
>case.
>
>> Maybe it's necessary for the eBPF path?
>
>Looking through sockmap, I don't think it depends on skb->sk being
>non-null either (it reassigns owner to the redirect socket anyway using
>skb_set_owner_r()).
>
>Sorry for the false alarm. LGTM.
Thanks for checking!
>
>Reviewed-by: Bobby Eshleman <bobbyeshleman@meta.com>
>
I'm going to add a threashold as Paolo suggested. Do you prefer to look
at v2 or should I carry your R-b ?
Thanks,
Stefano
^ permalink raw reply
* Re: [PATCH v3] vdpa/mlx5: Fix buffer length in create_direct_keys()
From: Christian Borntraeger @ 2026-07-07 7:17 UTC (permalink / raw)
To: Dragos Tatulea
Cc: Michael S . Tsirkin, Jason Wang, virtualization, linux-kernel
In-Reply-To: <20260706141537.3510294-1-borntraeger@linux.ibm.com>
Am 06.07.26 um 16:15 schrieb Christian Borntraeger:
> We have seen in our CI the following KASAN message:
> BUG: KASAN: slab-out-of-bounds in cmd_exec+0x550/0xca0 [mlx5_core]
> Read of size 272 at addr 0000000176795020 by task qemu-system-s39/82764
> [...]
> [<000011388ab3a7a0>] cmd_exec+0x550/0xca0 [mlx5_core]
> [<000011388ab3b61c>] mlx5_cmd_exec_cb+0x25c/0x4f0 [mlx5_core]
> [<000011388b21e82e>] mlx5_vdpa_exec_async_cmds+0x22e/0x5e0 [mlx5_vdpa]
> [<000011388b21fd44>] create_direct_keys+0x954/0xef0 [mlx5_vdpa]
> [...]
> The buggy address is located 4128 bytes inside of
> allocated 4384-byte region [0000000176794000, 0000000176795120)
>
> So in essence we read 16 bytes beyond 4384-byte allocation.
> create_direct_keys calculates the pointer and length for in and out
> buffers.
> The size calculation for in includes the entire structure
> size (out + in + mtt[]) but the pointer passed to cmd_exec points only
> to the 'in' field, skipping the 'out' field.
>
> This causes mlx5_copy_to_msg() to read beyond the allocated buffer
> by sizeof(out) bytes when copying command data.
>
> Properly calculate the input size to match the pointer and allocation size.
>
> Fixes: 0071b138d44a ("vdpa/mlx5: Create direct MKEYs in parallel")
> Signed-off-by: Christian Borntraeger <borntraeger@linux.ibm.com>
Dragos,
With this fix our nighly CI did not result in a kasan message. As I only have
limited test coverage a full regression on your side might still be the right
thing to do.
^ permalink raw reply
* Re: [PATCH 04/13] mm: update generic_get_unmapped_area[_topdown]() to use vma_flags_t
From: Zi Yan @ 2026-07-07 2:29 UTC (permalink / raw)
To: Lorenzo Stoakes, Andrew Morton
Cc: Thomas Bogendoerfer, Madhavan Srinivasan, Michael Ellerman,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Lucas Stach, Inki Dae, Seung-Woo Kim,
Kyungmin Park, Krzysztof Kozlowski, Peter Griffin, Jani Nikula,
Joonas Lahtinen, Rodrigo Vivi, Tvrtko Ursulin, Rob Clark,
Dmitry Baryshkov, Lyude Paul, Danilo Krummrich, Tomi Valkeinen,
Sandy Huang, Heiko Stübner, Andy Yan, Thierry Reding,
Mikko Perttunen, Jonathan Hunter, Gerd Hoffmann, Dmitry Osipenko,
Zack Rusin, Matthew Brost, Thomas Hellstrom,
Oleksandr Andrushchenko, Helge Deller, Benjamin LaHaise,
Alexander Viro, Christian Brauner, Muchun Song, Oscar Salvador,
David Hildenbrand, Baolin Wang, Liam R . Howlett, Nico Pache,
Ryan Roberts, Dev Jain, Barry Song, Lance Yang, Hugh Dickins,
Vlastimil Babka, Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
Jann Horn, Pedro Falcato, Kees Cook, Jaroslav Kysela,
Takashi Iwai, linux-mips, linux-kernel, linuxppc-dev, dri-devel,
etnaviv, linux-arm-kernel, linux-samsung-soc, intel-gfx,
linux-arm-msm, freedreno, nouveau, linux-rockchip, linux-tegra,
virtualization, intel-xe, xen-devel, linux-fbdev, linux-aio,
linux-fsdevel, linux-mm, linux-sound
In-Reply-To: <cef55b19f86c110952f13829aefa4859db3a70ed.1782760670.git.ljs@kernel.org>
On Mon Jun 29, 2026 at 3:25 PM EDT, Lorenzo Stoakes wrote:
> As part of the changes converting VMA flags from a system word size to a
> bitmap, extend this change to generic_get_unmapped_area() and
> generic_get_unmapped_area_topdown(), which also allows us to convert
> stack_guard_placement() as well.
>
> We retain arch_get_unmapped_area() and arch_get_unmapped_area_topdown()
> as-is for now, using legacy_to_vma_flags() as necessary to do so.
>
> No functional change intended.
>
> Signed-off-by: Lorenzo Stoakes <ljs@kernel.org>
> ---
> arch/powerpc/mm/book3s64/slice.c | 6 ++++--
> include/linux/sched/mm.h | 4 ++--
> mm/mmap.c | 16 ++++++++--------
> 3 files changed, 14 insertions(+), 12 deletions(-)
>
LGTM.
Reviewed-by: Zi Yan <ziy@nvidia.com>
--
Best Regards,
Yan, Zi
^ permalink raw reply
* Re: [PATCH 03/13] mm: convert __get_unmapped_area() to use vma_flags_t
From: Zi Yan @ 2026-07-07 2:28 UTC (permalink / raw)
To: Lorenzo Stoakes, Andrew Morton
Cc: Thomas Bogendoerfer, Madhavan Srinivasan, Michael Ellerman,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Lucas Stach, Inki Dae, Seung-Woo Kim,
Kyungmin Park, Krzysztof Kozlowski, Peter Griffin, Jani Nikula,
Joonas Lahtinen, Rodrigo Vivi, Tvrtko Ursulin, Rob Clark,
Dmitry Baryshkov, Lyude Paul, Danilo Krummrich, Tomi Valkeinen,
Sandy Huang, Heiko Stübner, Andy Yan, Thierry Reding,
Mikko Perttunen, Jonathan Hunter, Gerd Hoffmann, Dmitry Osipenko,
Zack Rusin, Matthew Brost, Thomas Hellstrom,
Oleksandr Andrushchenko, Helge Deller, Benjamin LaHaise,
Alexander Viro, Christian Brauner, Muchun Song, Oscar Salvador,
David Hildenbrand, Baolin Wang, Liam R . Howlett, Nico Pache,
Ryan Roberts, Dev Jain, Barry Song, Lance Yang, Hugh Dickins,
Vlastimil Babka, Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
Jann Horn, Pedro Falcato, Kees Cook, Jaroslav Kysela,
Takashi Iwai, linux-mips, linux-kernel, linuxppc-dev, dri-devel,
etnaviv, linux-arm-kernel, linux-samsung-soc, intel-gfx,
linux-arm-msm, freedreno, nouveau, linux-rockchip, linux-tegra,
virtualization, intel-xe, xen-devel, linux-fbdev, linux-aio,
linux-fsdevel, linux-mm, linux-sound
In-Reply-To: <b1ad7c4443f5cba622e4c48c5a9ef15427001a93.1782760670.git.ljs@kernel.org>
On Mon Jun 29, 2026 at 3:25 PM EDT, Lorenzo Stoakes wrote:
> Update __get_unmapped_area() to be parameterised by vma_flags_t rather than
> vm_flags_t as part of the effort to move VMA flags from a system word to a
> bitmap.
>
> We cascade the changes up to arch_get_unmapped_area_topdown() and
> arch_get_unmapped_area(), where, for now, we use vma_flags_to_legacy() in
> order to propagate the VMA flags.
>
> No functional change intended.
>
> Signed-off-by: Lorenzo Stoakes <ljs@kernel.org>
> ---
> fs/hugetlbfs/inode.c | 3 ++-
> include/linux/huge_mm.h | 10 +++++-----
> include/linux/mm.h | 6 ++++--
> include/linux/sched/mm.h | 12 ++++++------
> mm/huge_memory.c | 21 ++++++++++++---------
> mm/mmap.c | 27 ++++++++++++++-------------
> 6 files changed, 43 insertions(+), 36 deletions(-)
>
<snip>
> diff --git a/include/linux/sched/mm.h b/include/linux/sched/mm.h
> index 95d0040df584..b301ec90740a 100644
> --- a/include/linux/sched/mm.h
> +++ b/include/linux/sched/mm.h
> @@ -193,12 +193,12 @@ unsigned long mm_get_unmapped_area(struct file *filp, unsigned long addr,
> unsigned long len, unsigned long pgoff,
> unsigned long flags);
>
> -unsigned long mm_get_unmapped_area_vmflags(struct file *filp,
> - unsigned long addr,
> - unsigned long len,
> - unsigned long pgoff,
> - unsigned long flags,
> - vm_flags_t vm_flags);
> +unsigned long mm_get_unmapped_area_vmaflags(struct file *filp,
> + unsigned long addr,
> + unsigned long len,
> + unsigned long pgoff,
> + unsigned long flags,
> + vma_flags_t vma_flags);
Want to use two-tab indentation while at it?
<snip>
> @@ -812,19 +811,20 @@ arch_get_unmapped_area_topdown(struct file *filp, unsigned long addr,
> }
> #endif
>
> -unsigned long mm_get_unmapped_area_vmflags(struct file *filp, unsigned long addr,
> - unsigned long len, unsigned long pgoff,
> - unsigned long flags, vm_flags_t vm_flags)
> +unsigned long mm_get_unmapped_area_vmaflags(struct file *filp, unsigned long addr,
> + unsigned long len, unsigned long pgoff,
> + unsigned long flags, vma_flags_t vma_flags)
Ditto.
LGTM.
Reviewed-by: Zi Yan <ziy@nvidia.com>
--
Best Regards,
Yan, Zi
^ permalink raw reply
* Re: [PATCH 02/13] mm/vma: update do_mmap() to use vma_flags_t
From: Zi Yan @ 2026-07-07 2:10 UTC (permalink / raw)
To: Lorenzo Stoakes, Andrew Morton
Cc: Thomas Bogendoerfer, Madhavan Srinivasan, Michael Ellerman,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Lucas Stach, Inki Dae, Seung-Woo Kim,
Kyungmin Park, Krzysztof Kozlowski, Peter Griffin, Jani Nikula,
Joonas Lahtinen, Rodrigo Vivi, Tvrtko Ursulin, Rob Clark,
Dmitry Baryshkov, Lyude Paul, Danilo Krummrich, Tomi Valkeinen,
Sandy Huang, Heiko Stübner, Andy Yan, Thierry Reding,
Mikko Perttunen, Jonathan Hunter, Gerd Hoffmann, Dmitry Osipenko,
Zack Rusin, Matthew Brost, Thomas Hellstrom,
Oleksandr Andrushchenko, Helge Deller, Benjamin LaHaise,
Alexander Viro, Christian Brauner, Muchun Song, Oscar Salvador,
David Hildenbrand, Baolin Wang, Liam R . Howlett, Nico Pache,
Ryan Roberts, Dev Jain, Barry Song, Lance Yang, Hugh Dickins,
Vlastimil Babka, Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
Jann Horn, Pedro Falcato, Kees Cook, Jaroslav Kysela,
Takashi Iwai, linux-mips, linux-kernel, linuxppc-dev, dri-devel,
etnaviv, linux-arm-kernel, linux-samsung-soc, intel-gfx,
linux-arm-msm, freedreno, nouveau, linux-rockchip, linux-tegra,
virtualization, intel-xe, xen-devel, linux-fbdev, linux-aio,
linux-fsdevel, linux-mm, linux-sound
In-Reply-To: <e0ac58ad2b88ff7e2f0024e3286b2e786f79ca32.1782760670.git.ljs@kernel.org>
On Mon Jun 29, 2026 at 3:25 PM EDT, Lorenzo Stoakes wrote:
> The core do_mmap() function accepts a vm_flags_t parameter which it then
> manipulates before passing to mmap_region() to do the heavy lifting of the
> memory mapping.
>
> Update do_mmap() to instead accept a vma_flags_t parameter, and adjust all
> the logic within do_mmap() to manipulate this instead.
>
> This is as part of the ongoing effort to convert VMA flags from a system
> word size to a bitmap type which allows us to unrestrict the number of VMA
> flags, as well as gain control over how VMA flag manipulation occurs.
>
> We do not cascade these changes to all functions which accept vm_flags_t,
> but rather use vma_flags_to_legacy() where necessary, specifically
> deferring converting calc_vm_prot_bits(), calc_vm_flag_bits() and
> __get_unmapped_area() to vma_flags_t.
>
> Also utilise the new vma_flags_can_grow() predicate which correctly handles
> the case of architectures without upward growing stacks.
>
> As part of this change, introduce VMA_SHADOW_STACK so we can correctly
> handle the case of the shadow stack not being defined.
>
> No functional change intended.
>
> Signed-off-by: Lorenzo Stoakes <ljs@kernel.org>
> ---
> arch/mips/kernel/vdso.c | 4 +--
> fs/aio.c | 2 +-
> include/linux/memfd.h | 6 ++--
> include/linux/mm.h | 6 ++--
> ipc/shm.c | 3 +-
> mm/memfd.c | 15 ++++-----
> mm/mmap.c | 67 ++++++++++++++++++++++++-----------------
> mm/nommu.c | 3 +-
> mm/util.c | 10 +++---
> mm/vma.c | 7 ++---
> mm/vma.h | 2 +-
> 11 files changed, 69 insertions(+), 56 deletions(-)
>
<snip>
>
> -static int check_write_seal(vm_flags_t *vm_flags_ptr)
> +static int check_write_seal(vma_flags_t *vma_flags_ptr)
> {
> - vm_flags_t vm_flags = *vm_flags_ptr;
> - vm_flags_t mask = vm_flags & (VM_SHARED | VM_WRITE);
> -
> /* If a private mapping then writability is irrelevant. */
> - if (!(mask & VM_SHARED))
> + if (!vma_flags_test(vma_flags_ptr, VMA_SHARED_BIT))
> return 0;
>
> /*
> * New PROT_WRITE and MAP_SHARED mmaps are not allowed when
> * write seals are active.
> */
> - if (mask & VM_WRITE)
> + if (vma_flags_test(vma_flags_ptr, VMA_WRITE_BIT))
> return -EPERM;
>
> /*
> * This is a read-only mapping, disallow mprotect() from making a
> * write-sealed mapping writable in future.
> */
> - *vm_flags_ptr &= ~VM_MAYWRITE;
> + vma_flags_clear(vma_flags_ptr, VMA_MAYWRITE_BIT);
>
> return 0;
> }
This function alone changed its original behavior, since vm_flags is a
snapshot of *vm_flags_ptr, but after the change this snapshot is gone.
But its only caller memfd_check_seals_mmap() gets vm_flags_ptr from the
input parameter of do_mmap(), so the overall behavior does not change.
<snip>
> + case MAP_DROPPABLE: {
> + vma_flags_t droppable = VMA_DROPPABLE;
> +
> + if (vma_flags_empty(&droppable))
> return -EOPNOTSUPP;
> + vma_flags_set_mask(&vma_flags, droppable);
> +
> /*
> * A locked or stack area makes no sense to be droppable.
> *
> @@ -515,23 +527,24 @@ unsigned long do_mmap(struct file *file, unsigned long addr,
> */
> if (flags & (MAP_LOCKED | MAP_HUGETLB))
> return -EINVAL;
> - if (vm_flags & (VM_GROWSDOWN | VM_GROWSUP))
> + if (vma_flags_can_grow(&vma_flags))
> return -EINVAL;
>
> - vm_flags |= VM_DROPPABLE;
> -
Lance pointed out the reordering of setting VMA_DROPPABLE and checking
of can_grow, but these flags are not overlapped and there is no parallel
writer to vma_flags. So it is still no functional change, just not
mechanical changes. :)
Otherwise, LGTM.
Reviewed-by: Zi Yan <ziy@nvidia.com>
--
Best Regards,
Yan, Zi
^ permalink raw reply
* Re: [PATCH v5 01/51] x86/apic: Provide helpers to set local APIC timer period in hz and khz
From: Sean Christopherson @ 2026-07-06 18:00 UTC (permalink / raw)
To: Michael Kelley
Cc: Jonathan Corbet, Paolo Bonzini, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, Dave Hansen, x86@kernel.org, Kiryl Shutsemau,
Rick Edgecombe, K. Y. Srinivasan, Haiyang Zhang, Wei Liu,
Dexuan Cui, Long Li, Ajay Kaher, Alexey Makhalov, Jan Kiszka,
Andy Lutomirski, Peter Zijlstra, Juergen Gross, Daniel Lezcano,
John Stultz, Shuah Khan, H. Peter Anvin, Vitaly Kuznetsov,
Broadcom internal kernel review list, Boris Ostrovsky,
Stephen Boyd, linux-doc@vger.kernel.org, kvm@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-coco@lists.linux.dev,
linux-hyperv@vger.kernel.org, virtualization@lists.linux.dev,
xen-devel@lists.xenproject.org, Tom Lendacky, Nikunj A Dadhania,
David Woodhouse, David Woodhouse, Thomas Gleixner
In-Reply-To: <SN6PR02MB41578D3C34AB283B892C27A4D4F52@SN6PR02MB4157.namprd02.prod.outlook.com>
On Thu, Jul 02, 2026, Michael Kelley wrote:
> > @@ -796,6 +796,16 @@ bool __init apic_needs_pit(void)
> > return lapic_timer_period == 0;
> > }
> >
> > +void apic_set_timer_period_khz(u64 period_khz, const char *source)
> > +{
> > + lapic_timer_period = mul_u64_u32_div(period_khz, 1000, HZ);
> > +}
> > +
> > +void apic_set_timer_period_hz(u64 period_hz, const char *source)
> > +{
> > + lapic_timer_period = div_u64(period_hz, HZ);
> > +}
>
> A string "source" argument is passed in, but not used. Is there an
> envisioned future use? Also, this function doesn't output a pr_info()
> message like the existing Hyper-V and VMware code does.
It was a complete goof on my part (Sashiko also pointed out the oddity[*]). I
fully intended to log a message and provide equivalent Hyper-V/VMware behavior,
and totally spaced it.
[*] https://lore.kernel.org/all/20260701194621.4BD691F000E9@smtp.kernel.org
> I don't know that the message is all that useful, though I do remember one
> case where I was debugging some clock/timer issue when I looked at it.
^ permalink raw reply
* [PATCH v1] virtio-pci: Drop inclusion of <linux/mod_devicetable.h>
From: Uwe Kleine-König (The Capable Hub) @ 2026-07-06 16:22 UTC (permalink / raw)
To: Michael S. Tsirkin, Jason Wang
Cc: Xuan Zhuo, Eugenio Pérez, virtualization, linux-kernel
Among the different device id structures <linux/virtio_pci_legacy.h>
only uses struct virtio_device_id. Include <linux/device-id/virtio.h>
instead of <linux/mod_devicetable.h> to provide that which is more
lightweight and doesn't introduce that many dependencies.
The users of <linux/virtio_pci_legacy.h> also don't rely on this header
to provide the full plethora of definitions. (There are only
drivers/vdpa/alibaba/eni_vdpa.c and drivers/virtio/virtio_pci_common.c
using pci_device_id and these include <linux/pci.h> which is enough to
get it.)
Signed-off-by: Uwe Kleine-König (The Capable Hub) <u.kleine-koenig@baylibre.com>
---
Hello,
note that <linux/device-id/virtio.h> only exists since v7.2-rc2, so make
sure your base is new enough when applying this patch.
Best regards
Uwe
include/linux/virtio_pci_legacy.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/linux/virtio_pci_legacy.h b/include/linux/virtio_pci_legacy.h
index a8dc757d0367..96a9523e985d 100644
--- a/include/linux/virtio_pci_legacy.h
+++ b/include/linux/virtio_pci_legacy.h
@@ -2,7 +2,7 @@
#ifndef _LINUX_VIRTIO_PCI_LEGACY_H
#define _LINUX_VIRTIO_PCI_LEGACY_H
-#include "linux/mod_devicetable.h"
+#include <linux/device-id/virtio.h>
#include <linux/pci.h>
#include <linux/virtio_pci.h>
base-commit: 8cdeaa50eae8dad34885515f62559ee83e7e8dda
--
2.55.0.11.g153666a7d9bb
^ permalink raw reply related
* [PATCH v3] vdpa/mlx5: Fix buffer length in create_direct_keys()
From: Christian Borntraeger @ 2026-07-06 14:15 UTC (permalink / raw)
To: Dragos Tatulea
Cc: Michael S . Tsirkin, Jason Wang, virtualization, linux-kernel,
Christian Borntraeger
We have seen in our CI the following KASAN message:
BUG: KASAN: slab-out-of-bounds in cmd_exec+0x550/0xca0 [mlx5_core]
Read of size 272 at addr 0000000176795020 by task qemu-system-s39/82764
[...]
[<000011388ab3a7a0>] cmd_exec+0x550/0xca0 [mlx5_core]
[<000011388ab3b61c>] mlx5_cmd_exec_cb+0x25c/0x4f0 [mlx5_core]
[<000011388b21e82e>] mlx5_vdpa_exec_async_cmds+0x22e/0x5e0 [mlx5_vdpa]
[<000011388b21fd44>] create_direct_keys+0x954/0xef0 [mlx5_vdpa]
[...]
The buggy address is located 4128 bytes inside of
allocated 4384-byte region [0000000176794000, 0000000176795120)
So in essence we read 16 bytes beyond 4384-byte allocation.
create_direct_keys calculates the pointer and length for in and out
buffers.
The size calculation for in includes the entire structure
size (out + in + mtt[]) but the pointer passed to cmd_exec points only
to the 'in' field, skipping the 'out' field.
This causes mlx5_copy_to_msg() to read beyond the allocated buffer
by sizeof(out) bytes when copying command data.
Properly calculate the input size to match the pointer and allocation size.
Fixes: 0071b138d44a ("vdpa/mlx5: Create direct MKEYs in parallel")
Signed-off-by: Christian Borntraeger <borntraeger@linux.ibm.com>
---
v2->v3: use full size - offset to handle padding and alignment
RFC->v2: use flex_array_size
drivers/vdpa/mlx5/core/mr.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/vdpa/mlx5/core/mr.c b/drivers/vdpa/mlx5/core/mr.c
index 6d02ccf9eb91..d422f3faeb48 100644
--- a/drivers/vdpa/mlx5/core/mr.c
+++ b/drivers/vdpa/mlx5/core/mr.c
@@ -233,7 +233,8 @@ static int create_direct_keys(struct mlx5_vdpa_dev *mvdev, struct mlx5_vdpa_mr *
cmds[i].out = cmd_mem->out;
cmds[i].outlen = sizeof(cmd_mem->out);
cmds[i].in = cmd_mem->in;
- cmds[i].inlen = struct_size(cmd_mem, mtt, mttcount);
+ cmds[i].inlen = struct_size(cmd_mem, mtt, mttcount) -
+ offsetof(struct mlx5_create_mkey_mem, in);
fill_create_direct_mr(mvdev, dmr, cmd_mem);
--
2.53.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox