Page MenuHomeFreeBSD

bhyve: missing mutex initialisations
ClosedPublic

Authored by andy_omniosce.org on Feb 25 2022, 10:45 AM.
Tags
None
Referenced Files
Unknown Object (File)
Sat, Apr 20, 5:53 AM
Unknown Object (File)
Fri, Apr 12, 3:58 PM
Unknown Object (File)
Tue, Apr 9, 7:09 PM
Unknown Object (File)
Feb 20 2024, 7:19 PM
Unknown Object (File)
Feb 8 2024, 12:50 PM
Unknown Object (File)
Jan 14 2024, 10:13 AM
Unknown Object (File)
Dec 20 2023, 6:33 AM
Unknown Object (File)
Dec 13 2023, 4:55 AM

Details

Summary
There are three PCI virtio modules which never initialise the mutex
that's passed back to virtio.

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Not Applicable
Unit
Tests Not Applicable

Event Timeline

chuck added a subscriber: chuck.

LGTM

This revision is now accepted and ready to land.Feb 26 2022, 6:27 PM

looking at the comment above the struct virtio_softc definition in usr.sbin/bhyve/virtio.h:

[ ... snipped ... ]
* Note: inside each hypervisor virtio driver, changes to these
* data structures must be locked against other threads, if any.
* Except for PCI config space register read/write, we assume each
* driver does the required locking, but we need a pointer to the
* lock (if there is one) for PCI config space read/write ops.
[ ... snipped ... ]

suggests that vs_mtx is not required to be passed back to virtio - so I'm curious why these ones were omitted, was it by accident or purpose?

looking at virtio-scsi it creates threads in the driver, but virtio-rnd doesn't. So looking at virtio-rnd, what threads does it need the mutex for? The vcpu threads?

Two more missing mutex initialisations.

This revision now requires review to proceed.Feb 26 2022, 11:51 PM
In D34372#778732, @rew wrote:

suggests that vs_mtx is not required to be passed back to virtio - so I'm curious why these ones were omitted, was it by accident or purpose?

looking at virtio-scsi it creates threads in the driver, but virtio-rnd doesn't. So looking at virtio-rnd, what threads does it need the mutex for? The vcpu threads?

It was just the initialisation that was omitted. Each of these drivers has a mutex in their soft state and passes it back to virtio, which uses it around the bar reads and writes.
With the changes I'm making in illumos, locking an uninitialised mutex is fatal there, hence this showed up.

If the modules don't need the mutex, then removing it completely would work too.

I didn't realize that these mutex's get initialized on FreeBSD, even without your patch.

so, yea, I think this looks good - for FreeBSD there is no functional change here.

usr.sbin/bhyve/pci_virtio_rnd.c
185

without your patch applied:

I thought that sc->vsrc_vs.vs_mtx == NULL after this line, but its not.

in usr.sbin/bhyve/virtio.c, we have checks like:

if (vs->vs_mtx) 
        pthread_mutex_lock(vs->vs_mtx);

These checks evaluate as true and looking at pthread_mutex_lock()...it looks like it will initialize the mutex if it isn't already.

In D34372#778858, @rew wrote:

I didn't realize that these mutex's get initialized on FreeBSD, even without your patch.

I didn't either, but it seems that the rest of bhyve is not relying on that behaviour and it's not defined by POSIX nor in the pthread_mutex_lock.3 man page.

That would explain why the other part of this change, pci_nvme.c failing to initialise the last queue mutexes, hasn't shown up earlier either. With these changes in place on illumos, and running with full mutex checking, I have now run a wide range of guests without hitting any more issues.

Thanks

In D34372#778858, @rew wrote:

I didn't realize that these mutex's get initialized on FreeBSD, even without your patch.

I didn't either, but it seems that the rest of bhyve is not relying on that behaviour and it's not defined by POSIX nor in the pthread_mutex_lock.3 man page.

Perhaps I'm getting confused. Are we saying on FreeBSD mutex's are initialized automatically, or in this particular case? If so, where/how does the initialization happen?

That would explain why the other part of this change, pci_nvme.c failing to initialise the last queue mutexes, hasn't shown up earlier either. With these changes in place on illumos, and running with full mutex checking, I have now run a wide range of guests without hitting any more issues.

<smacks forehead/> yup, NVMe change looks good.

Perhaps I'm getting confused. Are we saying on FreeBSD mutex's are initialized automatically, or in this particular case? If so, where/how does the initialization happen?

yea, on FreeBSD, the mutexes without explicit initialization get initialized regardless.

The mutex initialization is happening where we make the checks in usr.sbin/bhyve/virtio.c:

if (vs->vs_mtx) 
        pthread_mutex_lock(vs->vs_mtx);

vs->vs_mtx evaluates to true (even when the mutex is not initialized) and then when pthread_mutex_lock() is called, it will initialize the mutex if it wasn't previously initialized.

If I'm not mistaken, we can toss those checks along with VS_LOCK()/VS_UNLOCK(), but that would be a separate change.

This revision is now accepted and ready to land.Feb 28 2022, 4:55 PM
jhb added a subscriber: jhb.

I suspect this is working by accident on FreeBSD as PTHREAD_MUTEX_INITIALIZER (which is in POSIX) happens to be 0 so the same thing you get from calloc().

Great, thanks all. Is there anything else I need to do to get this merged?

I’ll commit this tomorrow.

This revision was automatically updated to reflect the committed changes.