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
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
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... :(
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
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.
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
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
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
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
© 2016 - 2026 Red Hat, Inc.