[PATCH v2 1/2] virtio: silence KCSAN warning in virtqueue_get_buf_ctx_split

Johannes Thumshirn posted 2 patches 1 week, 6 days ago
[PATCH v2 1/2] virtio: silence KCSAN warning in virtqueue_get_buf_ctx_split
Posted by Johannes Thumshirn 1 week, 6 days ago
When booting a Qemu VM with virtio-blk and KCSAN enabled, KCSAN emits
the following warning about a data-race in virtqueue_get_buf_ctx_split().

 ==================================================================
 BUG: KCSAN: data-race in virtqueue_get_buf_ctx_split+0x6e/0x260

 race at unknown origin, with read to 0xffff8881020f1942 of 2 bytes by task 1 on cpu 7:
  virtqueue_get_buf_ctx_split+0x6e/0x260
  virtqueue_get_buf+0x4b/0x60
  __send_to_port+0x156/0x170
  put_chars+0xcb/0x110
  hvc_console_print+0x1d6/0x2a0
  console_flush_one_record+0x3dd/0x510
  console_unlock+0x8c/0x160
  vprintk_emit+0x2fe/0x380
  vprintk_default+0x1d/0x30
  vprintk+0xe/0x20
  _printk+0x4c/0x60
  btrfs_test_raid_stripe_tree+0x25/0x90
  btrfs_run_sanity_tests.cold+0xf1/0x13b
  init_btrfs_fs+0x73/0x110
  do_one_initcall+0x5b/0x2d0
  kernel_init_freeable+0x2a2/0x340
  kernel_init+0x1e/0x1b0
  ret_from_fork+0x137/0x1b0
  ret_from_fork_asm+0x1a/0x30

 value changed: 0x0160 -> 0x0161

 Reported by Kernel Concurrency Sanitizer on:
 CPU: 7 UID: 0 PID: 1 Comm: swapper/0 Not tainted 6.19.0-rc7+ #219 PREEMPT(none)
 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.17.0-9.fc43 06/10/2025
 ==================================================================

This warning is likely a false positive as the change happens on the
virtio vring.

Annotate the return of more_used_split() with data_race() to silence
the warning.

Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
---
 drivers/virtio/virtio_ring.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index ddab68959671..1db27ee2d89f 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -808,8 +808,8 @@ static void detach_buf_split(struct vring_virtqueue *vq, unsigned int head,
 
 static bool more_used_split(const struct vring_virtqueue *vq)
 {
-	return vq->last_used_idx != virtio16_to_cpu(vq->vq.vdev,
-			vq->split.vring.used->idx);
+	return data_race(vq->last_used_idx != virtio16_to_cpu(vq->vq.vdev,
+				vq->split.vring.used->idx));
 }
 
 static void *virtqueue_get_buf_ctx_split(struct virtqueue *_vq,
-- 
2.52.0
Re: [PATCH v2 1/2] virtio: silence KCSAN warning in virtqueue_get_buf_ctx_split
Posted by Alexander Graf 1 week, 6 days ago
On 27.01.26 16:25, Johannes Thumshirn wrote:
> When booting a Qemu VM with virtio-blk and KCSAN enabled, KCSAN emits
> the following warning about a data-race in virtqueue_get_buf_ctx_split().
>
>   ==================================================================
>   BUG: KCSAN: data-race in virtqueue_get_buf_ctx_split+0x6e/0x260
>
>   race at unknown origin, with read to 0xffff8881020f1942 of 2 bytes by task 1 on cpu 7:
>    virtqueue_get_buf_ctx_split+0x6e/0x260
>    virtqueue_get_buf+0x4b/0x60
>    __send_to_port+0x156/0x170
>    put_chars+0xcb/0x110
>    hvc_console_print+0x1d6/0x2a0
>    console_flush_one_record+0x3dd/0x510
>    console_unlock+0x8c/0x160
>    vprintk_emit+0x2fe/0x380
>    vprintk_default+0x1d/0x30
>    vprintk+0xe/0x20
>    _printk+0x4c/0x60
>    btrfs_test_raid_stripe_tree+0x25/0x90
>    btrfs_run_sanity_tests.cold+0xf1/0x13b
>    init_btrfs_fs+0x73/0x110
>    do_one_initcall+0x5b/0x2d0
>    kernel_init_freeable+0x2a2/0x340
>    kernel_init+0x1e/0x1b0
>    ret_from_fork+0x137/0x1b0
>    ret_from_fork_asm+0x1a/0x30
>
>   value changed: 0x0160 -> 0x0161
>
>   Reported by Kernel Concurrency Sanitizer on:
>   CPU: 7 UID: 0 PID: 1 Comm: swapper/0 Not tainted 6.19.0-rc7+ #219 PREEMPT(none)
>   Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.17.0-9.fc43 06/10/2025
>   ==================================================================
>
> This warning is likely a false positive as the change happens on the
> virtio vring.
>
> Annotate the return of more_used_split() with data_race() to silence
> the warning.
>
> Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
> ---
>   drivers/virtio/virtio_ring.c | 4 ++--
>   1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> index ddab68959671..1db27ee2d89f 100644
> --- a/drivers/virtio/virtio_ring.c
> +++ b/drivers/virtio/virtio_ring.c
> @@ -808,8 +808,8 @@ static void detach_buf_split(struct vring_virtqueue *vq, unsigned int head,
>
>   static bool more_used_split(const struct vring_virtqueue *vq)


This patches the split vring format, but does not touch the packed one. 
What happens if you run the same test with the packed format? You can do 
so by passing "packed=on" as argument to your -device parameter.


Alex





Amazon Web Services Development Center Germany GmbH
Tamara-Danz-Str. 13
10243 Berlin
Geschaeftsfuehrung: Christof Hellmis, Andreas Stieger
Eingetragen am Amtsgericht Charlottenburg unter HRB 257764 B
Sitz: Berlin
Ust-ID: DE 365 538 597
Re: [PATCH v2 1/2] virtio: silence KCSAN warning in virtqueue_get_buf_ctx_split
Posted by Johannes Thumshirn 1 week, 5 days ago
On 1/27/26 5:30 PM, Alexander Graf wrote:
> This patches the split vring format, but does not touch the packed one.
> What happens if you run the same test with the packed format? You can do
> so by passing "packed=on" as argument to your -device parameter.

This opened up a whole new can of worms... :(

Re: [PATCH v2 1/2] virtio: silence KCSAN warning in virtqueue_get_buf_ctx_split
Posted by Alexander Graf 1 week, 5 days ago
On 28.01.26 09:47, Johannes Thumshirn wrote:
> On 1/27/26 5:30 PM, Alexander Graf wrote:
>> This patches the split vring format, but does not touch the packed one.
>> What happens if you run the same test with the packed format? You can do
>> so by passing "packed=on" as argument to your -device parameter.
> This opened up a whole new can of worms... :(


That's what I expected :).

How do other DMA based devices handle this? Is the real problem that 
virtio by default does not use the DMA API and so it confuses generic 
KCSAN logic that would otherwise track DMA regions as "can be modified 
by DMA at any time"?

If that is the case, maybe what we really want is to force enable use of 
the DMA API when KCSAN is active. Does something like the (whitespace 
broken) patch below work?

Alex

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index ddab68959671..b1dd790ce622 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -284,6 +284,13 @@ static bool vring_use_map_api(const struct 
virtio_device *vdev)
      if (xen_domain())
          return true;

+    /*
+     * KCSAN needs to track who can modify memory. DMA API gets
+     * us that, so always use it.
+     */
+    if (IS_ENABLED(CONFIG_KCSAN))
+        return true;
+
      return false;
  }




Amazon Web Services Development Center Germany GmbH
Tamara-Danz-Str. 13
10243 Berlin
Geschaeftsfuehrung: Christof Hellmis, Andreas Stieger
Eingetragen am Amtsgericht Charlottenburg unter HRB 257764 B
Sitz: Berlin
Ust-ID: DE 365 538 597
Re: [PATCH v2 1/2] virtio: silence KCSAN warning in virtqueue_get_buf_ctx_split
Posted by Johannes Thumshirn 1 week, 5 days ago
On 1/28/26 10:03 AM, Alexander Graf wrote:
> On 28.01.26 09:47, Johannes Thumshirn wrote:
>> On 1/27/26 5:30 PM, Alexander Graf wrote:
>>> This patches the split vring format, but does not touch the packed one.
>>> What happens if you run the same test with the packed format? You can do
>>> so by passing "packed=on" as argument to your -device parameter.
>> This opened up a whole new can of worms... :(
>
> That's what I expected :).
>
> How do other DMA based devices handle this? Is the real problem that
> virtio by default does not use the DMA API and so it confuses generic
> KCSAN logic that would otherwise track DMA regions as "can be modified
> by DMA at any time"?
>
> If that is the case, maybe what we really want is to force enable use of
> the DMA API when KCSAN is active. Does something like the (whitespace
> broken) patch below work?
>
> Alex
>
> diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> index ddab68959671..b1dd790ce622 100644
> --- a/drivers/virtio/virtio_ring.c
> +++ b/drivers/virtio/virtio_ring.c
> @@ -284,6 +284,13 @@ static bool vring_use_map_api(const struct
> virtio_device *vdev)
>        if (xen_domain())
>            return true;
>
> +    /*
> +     * KCSAN needs to track who can modify memory. DMA API gets
> +     * us that, so always use it.
> +     */
> +    if (IS_ENABLED(CONFIG_KCSAN))
> +        return true;
> +
>        return false;
>    }


Unfortunately this doesn't get us any further (I'd love though, it looks 
way cleaner!)

I still see the KCSAN messages even on boot.

Re: [PATCH v2 1/2] virtio: silence KCSAN warning in virtqueue_get_buf_ctx_split
Posted by Alexander Graf 1 week, 5 days ago
On 28.01.26 10:13, Johannes Thumshirn wrote:
> On 1/28/26 10:03 AM, Alexander Graf wrote:
>> On 28.01.26 09:47, Johannes Thumshirn wrote:
>>> On 1/27/26 5:30 PM, Alexander Graf wrote:
>>>> This patches the split vring format, but does not touch the packed one.
>>>> What happens if you run the same test with the packed format? You can do
>>>> so by passing "packed=on" as argument to your -device parameter.
>>> This opened up a whole new can of worms... :(
>> That's what I expected :).
>>
>> How do other DMA based devices handle this? Is the real problem that
>> virtio by default does not use the DMA API and so it confuses generic
>> KCSAN logic that would otherwise track DMA regions as "can be modified
>> by DMA at any time"?
>>
>> If that is the case, maybe what we really want is to force enable use of
>> the DMA API when KCSAN is active. Does something like the (whitespace
>> broken) patch below work?
>>
>> Alex
>>
>> diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
>> index ddab68959671..b1dd790ce622 100644
>> --- a/drivers/virtio/virtio_ring.c
>> +++ b/drivers/virtio/virtio_ring.c
>> @@ -284,6 +284,13 @@ static bool vring_use_map_api(const struct
>> virtio_device *vdev)
>>         if (xen_domain())
>>             return true;
>>
>> +    /*
>> +     * KCSAN needs to track who can modify memory. DMA API gets
>> +     * us that, so always use it.
>> +     */
>> +    if (IS_ENABLED(CONFIG_KCSAN))
>> +        return true;
>> +
>>         return false;
>>     }
>
> Unfortunately this doesn't get us any further (I'd love though, it looks
> way cleaner!)
>
> I still see the KCSAN messages even on boot.


Ah, looks like the important bit for KCSAN is not the mapping mechanism, 
it's the actual compiler annotation for the read. So these virtio ring 
reads should all be annotated as READ_ONCE() to make sure KCSAN knows 
the read itself is atomic.

Alex




Amazon Web Services Development Center Germany GmbH
Tamara-Danz-Str. 13
10243 Berlin
Geschaeftsfuehrung: Christof Hellmis, Andreas Stieger
Eingetragen am Amtsgericht Charlottenburg unter HRB 257764 B
Sitz: Berlin
Ust-ID: DE 365 538 597
Re: [PATCH v2 1/2] virtio: silence KCSAN warning in virtqueue_get_buf_ctx_split
Posted by Michael S. Tsirkin 1 week, 5 days ago
On Wed, Jan 28, 2026 at 11:30:20AM +0100, Alexander Graf wrote:
> 
> On 28.01.26 10:13, Johannes Thumshirn wrote:
> > On 1/28/26 10:03 AM, Alexander Graf wrote:
> > > On 28.01.26 09:47, Johannes Thumshirn wrote:
> > > > On 1/27/26 5:30 PM, Alexander Graf wrote:
> > > > > This patches the split vring format, but does not touch the packed one.
> > > > > What happens if you run the same test with the packed format? You can do
> > > > > so by passing "packed=on" as argument to your -device parameter.
> > > > This opened up a whole new can of worms... :(
> > > That's what I expected :).
> > > 
> > > How do other DMA based devices handle this? Is the real problem that
> > > virtio by default does not use the DMA API and so it confuses generic
> > > KCSAN logic that would otherwise track DMA regions as "can be modified
> > > by DMA at any time"?
> > > 
> > > If that is the case, maybe what we really want is to force enable use of
> > > the DMA API when KCSAN is active. Does something like the (whitespace
> > > broken) patch below work?
> > > 
> > > Alex
> > > 
> > > diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> > > index ddab68959671..b1dd790ce622 100644
> > > --- a/drivers/virtio/virtio_ring.c
> > > +++ b/drivers/virtio/virtio_ring.c
> > > @@ -284,6 +284,13 @@ static bool vring_use_map_api(const struct
> > > virtio_device *vdev)
> > >         if (xen_domain())
> > >             return true;
> > > 
> > > +    /*
> > > +     * KCSAN needs to track who can modify memory. DMA API gets
> > > +     * us that, so always use it.
> > > +     */
> > > +    if (IS_ENABLED(CONFIG_KCSAN))
> > > +        return true;
> > > +
> > >         return false;
> > >     }
> > 
> > Unfortunately this doesn't get us any further (I'd love though, it looks
> > way cleaner!)
> > 
> > I still see the KCSAN messages even on boot.
> 
> 
> Ah, looks like the important bit for KCSAN is not the mapping mechanism,
> it's the actual compiler annotation for the read. So these virtio ring reads
> should all be annotated as READ_ONCE() to make sure KCSAN knows the read
> itself is atomic.
> 
> Alex
> 

so then:

       return vq->last_used_idx != virtio16_to_cpu(vq->vq.vdev,
                       READ_ONCE(vq->split.vring.used->idx));


?




> 
> 
> Amazon Web Services Development Center Germany GmbH
> Tamara-Danz-Str. 13
> 10243 Berlin
> Geschaeftsfuehrung: Christof Hellmis, Andreas Stieger
> Eingetragen am Amtsgericht Charlottenburg unter HRB 257764 B
> Sitz: Berlin
> Ust-ID: DE 365 538 597
Re: [PATCH v2 1/2] virtio: silence KCSAN warning in virtqueue_get_buf_ctx_split
Posted by Alexander Graf 1 week, 5 days ago
On 28.01.26 11:34, Michael S. Tsirkin wrote:
> On Wed, Jan 28, 2026 at 11:30:20AM +0100, Alexander Graf wrote:
>> On 28.01.26 10:13, Johannes Thumshirn wrote:
>>> On 1/28/26 10:03 AM, Alexander Graf wrote:
>>>> On 28.01.26 09:47, Johannes Thumshirn wrote:
>>>>> On 1/27/26 5:30 PM, Alexander Graf wrote:
>>>>>> This patches the split vring format, but does not touch the packed one.
>>>>>> What happens if you run the same test with the packed format? You can do
>>>>>> so by passing "packed=on" as argument to your -device parameter.
>>>>> This opened up a whole new can of worms... :(
>>>> That's what I expected :).
>>>>
>>>> How do other DMA based devices handle this? Is the real problem that
>>>> virtio by default does not use the DMA API and so it confuses generic
>>>> KCSAN logic that would otherwise track DMA regions as "can be modified
>>>> by DMA at any time"?
>>>>
>>>> If that is the case, maybe what we really want is to force enable use of
>>>> the DMA API when KCSAN is active. Does something like the (whitespace
>>>> broken) patch below work?
>>>>
>>>> Alex
>>>>
>>>> diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
>>>> index ddab68959671..b1dd790ce622 100644
>>>> --- a/drivers/virtio/virtio_ring.c
>>>> +++ b/drivers/virtio/virtio_ring.c
>>>> @@ -284,6 +284,13 @@ static bool vring_use_map_api(const struct
>>>> virtio_device *vdev)
>>>>          if (xen_domain())
>>>>              return true;
>>>>
>>>> +    /*
>>>> +     * KCSAN needs to track who can modify memory. DMA API gets
>>>> +     * us that, so always use it.
>>>> +     */
>>>> +    if (IS_ENABLED(CONFIG_KCSAN))
>>>> +        return true;
>>>> +
>>>>          return false;
>>>>      }
>>> Unfortunately this doesn't get us any further (I'd love though, it looks
>>> way cleaner!)
>>>
>>> I still see the KCSAN messages even on boot.
>>
>> Ah, looks like the important bit for KCSAN is not the mapping mechanism,
>> it's the actual compiler annotation for the read. So these virtio ring reads
>> should all be annotated as READ_ONCE() to make sure KCSAN knows the read
>> itself is atomic.
>>
>> Alex
>>
> so then:
>
>         return vq->last_used_idx != virtio16_to_cpu(vq->vq.vdev,
>                         READ_ONCE(vq->split.vring.used->idx));


Yes, which is on the verge of getting unreadable. I'll work with 
Johannes on v3. We'll play with ways to make it a bit more maintainable. 
Please discard the current patches for now.


Alex




Amazon Web Services Development Center Germany GmbH
Tamara-Danz-Str. 13
10243 Berlin
Geschaeftsfuehrung: Christof Hellmis, Andreas Stieger
Eingetragen am Amtsgericht Charlottenburg unter HRB 257764 B
Sitz: Berlin
Ust-ID: DE 365 538 597
Re: [PATCH v2 1/2] virtio: silence KCSAN warning in virtqueue_get_buf_ctx_split
Posted by Michael S. Tsirkin 1 week, 5 days ago
On Wed, Jan 28, 2026 at 11:38:48AM +0100, Alexander Graf wrote:
> 
> On 28.01.26 11:34, Michael S. Tsirkin wrote:
> > On Wed, Jan 28, 2026 at 11:30:20AM +0100, Alexander Graf wrote:
> > > On 28.01.26 10:13, Johannes Thumshirn wrote:
> > > > On 1/28/26 10:03 AM, Alexander Graf wrote:
> > > > > On 28.01.26 09:47, Johannes Thumshirn wrote:
> > > > > > On 1/27/26 5:30 PM, Alexander Graf wrote:
> > > > > > > This patches the split vring format, but does not touch the packed one.
> > > > > > > What happens if you run the same test with the packed format? You can do
> > > > > > > so by passing "packed=on" as argument to your -device parameter.
> > > > > > This opened up a whole new can of worms... :(
> > > > > That's what I expected :).
> > > > > 
> > > > > How do other DMA based devices handle this? Is the real problem that
> > > > > virtio by default does not use the DMA API and so it confuses generic
> > > > > KCSAN logic that would otherwise track DMA regions as "can be modified
> > > > > by DMA at any time"?
> > > > > 
> > > > > If that is the case, maybe what we really want is to force enable use of
> > > > > the DMA API when KCSAN is active. Does something like the (whitespace
> > > > > broken) patch below work?
> > > > > 
> > > > > Alex
> > > > > 
> > > > > diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> > > > > index ddab68959671..b1dd790ce622 100644
> > > > > --- a/drivers/virtio/virtio_ring.c
> > > > > +++ b/drivers/virtio/virtio_ring.c
> > > > > @@ -284,6 +284,13 @@ static bool vring_use_map_api(const struct
> > > > > virtio_device *vdev)
> > > > >          if (xen_domain())
> > > > >              return true;
> > > > > 
> > > > > +    /*
> > > > > +     * KCSAN needs to track who can modify memory. DMA API gets
> > > > > +     * us that, so always use it.
> > > > > +     */
> > > > > +    if (IS_ENABLED(CONFIG_KCSAN))
> > > > > +        return true;
> > > > > +
> > > > >          return false;
> > > > >      }
> > > > Unfortunately this doesn't get us any further (I'd love though, it looks
> > > > way cleaner!)
> > > > 
> > > > I still see the KCSAN messages even on boot.
> > > 
> > > Ah, looks like the important bit for KCSAN is not the mapping mechanism,
> > > it's the actual compiler annotation for the read. So these virtio ring reads
> > > should all be annotated as READ_ONCE() to make sure KCSAN knows the read
> > > itself is atomic.
> > > 
> > > Alex
> > > 
> > so then:
> > 
> >         return vq->last_used_idx != virtio16_to_cpu(vq->vq.vdev,
> >                         READ_ONCE(vq->split.vring.used->idx));
> 
> 
> Yes, which is on the verge of getting unreadable.

Well we can wrap virtio16_to_cpu and READ_ONCE in a single macro
if you like.  VIRTIO16_READ ?


> I'll work with Johannes on
> v3. We'll play with ways to make it a bit more maintainable. Please discard
> the current patches for now.

Sure.

> 
> Alex
> 
> 
> 
> 
> Amazon Web Services Development Center Germany GmbH
> Tamara-Danz-Str. 13
> 10243 Berlin
> Geschaeftsfuehrung: Christof Hellmis, Andreas Stieger
> Eingetragen am Amtsgericht Charlottenburg unter HRB 257764 B
> Sitz: Berlin
> Ust-ID: DE 365 538 597