[PATCH] bhyve: capabilities: use virBitmap to store capabilities

Roman Bogorodskiy posted 1 patch 1 week ago
src/bhyve/bhyve_capabilities.c  | 107 ++++++++++++++++++++------------
src/bhyve/bhyve_capabilities.h  |  50 +++++++++------
src/bhyve/bhyve_command.c       |  30 ++++-----
src/bhyve/bhyve_domain.c        |   4 +-
src/bhyve/bhyve_driver.c        |  17 ++---
src/bhyve/bhyve_driver.h        |   2 +-
src/bhyve/bhyve_parse_command.c |  16 ++---
src/bhyve/bhyve_parse_command.h |   2 +-
src/bhyve/bhyve_process.c       |   2 +-
src/bhyve/bhyve_utils.h         |   3 +-
tests/bhyveargv2xmltest.c       |   4 +-
tests/bhyvexml2argvtest.c       |  54 +++++++++-------
tests/bhyvexml2xmltest.c        |   9 ++-
tests/domaincapstest.c          |  20 +++---
14 files changed, 187 insertions(+), 133 deletions(-)
[PATCH] bhyve: capabilities: use virBitmap to store capabilities
Posted by Roman Bogorodskiy 1 week ago
Similarly to the qemu driver, store bhyve capabilities in virBitmap.
Add helpers to work with capabilities: virBhyveCapsGet(), virBhyveCapsSet(),
and virBhyveCapsClear().

No functional changes.

Signed-off-by: Roman Bogorodskiy <bogorodskiy@gmail.com>
---
 src/bhyve/bhyve_capabilities.c  | 107 ++++++++++++++++++++------------
 src/bhyve/bhyve_capabilities.h  |  50 +++++++++------
 src/bhyve/bhyve_command.c       |  30 ++++-----
 src/bhyve/bhyve_domain.c        |   4 +-
 src/bhyve/bhyve_driver.c        |  17 ++---
 src/bhyve/bhyve_driver.h        |   2 +-
 src/bhyve/bhyve_parse_command.c |  16 ++---
 src/bhyve/bhyve_parse_command.h |   2 +-
 src/bhyve/bhyve_process.c       |   2 +-
 src/bhyve/bhyve_utils.h         |   3 +-
 tests/bhyveargv2xmltest.c       |   4 +-
 tests/bhyvexml2argvtest.c       |  54 +++++++++-------
 tests/bhyvexml2xmltest.c        |   9 ++-
 tests/domaincapstest.c          |  20 +++---
 14 files changed, 187 insertions(+), 133 deletions(-)

diff --git a/src/bhyve/bhyve_capabilities.c b/src/bhyve/bhyve_capabilities.c
index 5d07d16f69..42da2a7c47 100644
--- a/src/bhyve/bhyve_capabilities.c
+++ b/src/bhyve/bhyve_capabilities.c
@@ -42,6 +42,30 @@
 VIR_LOG_INIT("bhyve.bhyve_capabilities");
 
 
+void
+virBhyveCapsSet(virBitmap *caps,
+                virBhyveCapsFlags flag)
+{
+    ignore_value(virBitmapSetBit(caps, flag));
+}
+
+
+void
+virBhyveCapsClear(virBitmap *caps,
+                  virBhyveCapsFlags flag)
+{
+    ignore_value(virBitmapClearBit(caps, flag));
+}
+
+
+bool
+virBhyveCapsGet(virBitmap *caps,
+                virBhyveCapsFlags flag)
+{
+    return caps && virBitmapIsBitSet(caps, flag);
+}
+
+
 virCaps *
 virBhyveCapsBuild(void)
 {
@@ -69,7 +93,7 @@ virBhyveCapsBuild(void)
 
 int
 virBhyveDomainCapsFill(virDomainCaps *caps,
-                       unsigned int bhyvecaps,
+                       virBitmap *bhyvecaps,
                        virDomainCapsStringValues *firmwares)
 {
     caps->disk.supported = VIR_TRISTATE_BOOL_YES;
@@ -87,7 +111,7 @@ virBhyveDomainCapsFill(virDomainCaps *caps,
     caps->os.supported = VIR_TRISTATE_BOOL_YES;
 
     caps->os.loader.supported = VIR_TRISTATE_BOOL_NO;
-    if (bhyvecaps & BHYVE_CAP_LPC_BOOTROM) {
+    if (virBhyveCapsGet(bhyvecaps, BHYVE_CAP_LPC_BOOTROM)) {
         caps->os.loader.type.report = true;
         caps->os.loader.readonly.report = true;
         caps->os.loader.supported = VIR_TRISTATE_BOOL_YES;
@@ -103,7 +127,7 @@ virBhyveDomainCapsFill(virDomainCaps *caps,
 
     caps->graphics.supported = VIR_TRISTATE_BOOL_NO;
     caps->video.supported = VIR_TRISTATE_BOOL_NO;
-    if (bhyvecaps & BHYVE_CAP_FBUF) {
+    if (virBhyveCapsGet(bhyvecaps, BHYVE_CAP_FBUF)) {
         caps->graphics.supported = VIR_TRISTATE_BOOL_YES;
         caps->graphics.type.report = true;
         caps->video.supported = VIR_TRISTATE_BOOL_YES;
@@ -112,7 +136,7 @@ virBhyveDomainCapsFill(virDomainCaps *caps,
         VIR_DOMAIN_CAPS_ENUM_SET(caps->video.modelType, VIR_DOMAIN_VIDEO_TYPE_GOP);
     }
 
-    if (bhyvecaps & BHYVE_CAP_VIRTIO_RND) {
+    if (virBhyveCapsGet(bhyvecaps, BHYVE_CAP_VIRTIO_RND)) {
         caps->rng.supported = VIR_TRISTATE_BOOL_YES;
         caps->rng.model.report = true;
         caps->rng.backendModel.report = true;
@@ -121,7 +145,7 @@ virBhyveDomainCapsFill(virDomainCaps *caps,
         VIR_DOMAIN_CAPS_ENUM_SET(caps->rng.backendModel,
                                  VIR_DOMAIN_RNG_BACKEND_RANDOM);
     }
-    if (bhyvecaps & BHYVE_CAP_LPC_TPM) {
+    if (virBhyveCapsGet(bhyvecaps, BHYVE_CAP_LPC_TPM)) {
         caps->tpm.supported = VIR_TRISTATE_BOOL_YES;
         caps->tpm.model.report = true;
         caps->tpm.backendModel.report = true;
@@ -156,7 +180,7 @@ virBhyveDomainCapsBuild(struct _bhyveConn *conn,
                         virDomainVirtType virttype)
 {
     virDomainCaps *caps = NULL;
-    unsigned int bhyve_caps = 0;
+    g_autoptr(virBitmap) bhyve_caps = NULL;
     g_autoptr(DIR) dir = NULL;
     struct dirent *entry;
     size_t firmwares_alloc = 0;
@@ -222,12 +246,12 @@ virBhyveProbeGrubCaps(virBhyveGrubCapsFlags *caps)
 }
 
 static int
-bhyveProbeCapsDeviceHelper(unsigned int *caps,
+bhyveProbeCapsDeviceHelper(virBitmap *caps,
                            char *binary,
                            const char *bus,
                            const char *device,
                            const char *errormsg,
-                           unsigned int flag)
+                           virBhyveCapsFlags flag)
 {
     g_autofree char *error = NULL;
     g_autoptr(virCommand) cmd = NULL;
@@ -240,13 +264,13 @@ bhyveProbeCapsDeviceHelper(unsigned int *caps,
         return -1;
 
     if (strstr(error, errormsg) == NULL)
-        *caps |= flag;
+        virBhyveCapsSet(caps, flag);
 
     return 0;
 }
 
 static int
-bhyveProbeCapsFromHelp(unsigned int *caps, char *binary)
+bhyveProbeCapsFromHelp(virBitmap *caps, char *binary)
 {
     g_autofree char *help = NULL;
     g_autoptr(virCommand) cmd = NULL;
@@ -259,52 +283,52 @@ bhyveProbeCapsFromHelp(unsigned int *caps, char *binary)
         return -1;
 
     if (strstr(help, "-u:") != NULL)
-        *caps |= BHYVE_CAP_RTC_UTC;
+        virBhyveCapsSet(caps, BHYVE_CAP_RTC_UTC);
 
     /* "-c vcpus" was there before CPU topology support was introduced,
      * then it became
      * "-c [[cpus=]numcpus][,sockets=n][,cores=n][,threads=n] */
     if (strstr(help, "-c vcpus") == NULL)
-        *caps |= BHYVE_CAP_CPUTOPOLOGY;
+        virBhyveCapsSet(caps, BHYVE_CAP_CPUTOPOLOGY);
 
     if (strstr(help, "-A:") != NULL)
-        *caps |= BHYVE_CAP_ACPI;
+        virBhyveCapsSet(caps, BHYVE_CAP_ACPI);
 
     if (strstr(help, "-n:") != NULL)
-        *caps |= BHYVE_CAP_NUMA;
+        virBhyveCapsSet(caps, BHYVE_CAP_NUMA);
 
     if (strstr(help, "-M:") != NULL)
-        *caps |= BHYVE_CAP_MONITOR;
+        virBhyveCapsSet(caps, BHYVE_CAP_MONITOR);
 
     return 0;
 }
 
 static int
-bhyveFillCapForDevice(unsigned int *caps, const char *device)
+bhyveFillCapForDevice(virBitmap *caps, const char *device)
 {
    if (STREQ(device, "ahci"))
-       *caps |= BHYVE_CAP_AHCI32SLOT;
+       virBhyveCapsSet(caps, BHYVE_CAP_AHCI32SLOT);
    else if (STREQ(device, "e1000"))
-       *caps |= BHYVE_CAP_NET_E1000;
+       virBhyveCapsSet(caps, BHYVE_CAP_NET_E1000);
    else if (STREQ(device, "fbuf"))
-       *caps |= BHYVE_CAP_FBUF;
+       virBhyveCapsSet(caps, BHYVE_CAP_FBUF);
    else if (STREQ(device, "hda"))
-       *caps |= BHYVE_CAP_SOUND_HDA;
+       virBhyveCapsSet(caps, BHYVE_CAP_SOUND_HDA);
    else if (STREQ(device, "nvme"))
-       *caps |= BHYVE_CAP_NVME;
+       virBhyveCapsSet(caps, BHYVE_CAP_NVME);
    else if (STREQ(device, "virtio-9p"))
-       *caps |= BHYVE_CAP_VIRTIO_9P;
+       virBhyveCapsSet(caps, BHYVE_CAP_VIRTIO_9P);
    else if (STREQ(device, "virtio-rnd"))
-       *caps |= BHYVE_CAP_VIRTIO_RND;
+       virBhyveCapsSet(caps, BHYVE_CAP_VIRTIO_RND);
    else if (STREQ(device, "xhci"))
-       *caps |= BHYVE_CAP_XHCI;
+       virBhyveCapsSet(caps, BHYVE_CAP_XHCI);
 
    return 0;
 }
 
 
 static int
-bhyveProbeCapsFromSHelp(unsigned int *caps, char *binary)
+bhyveProbeCapsFromSHelp(virBitmap *caps, char *binary)
 {
     g_autofree char *help = NULL;
     g_autoptr(virCommand) cmd = NULL;
@@ -328,7 +352,7 @@ bhyveProbeCapsFromSHelp(unsigned int *caps, char *binary)
 }
 
 static int
-bhyveProbeCapsLpcBootrom(unsigned int *caps, char *binary)
+bhyveProbeCapsLpcBootrom(virBitmap *caps, char *binary)
 {
     return bhyveProbeCapsDeviceHelper(caps, binary,
                                       "-l",
@@ -339,7 +363,7 @@ bhyveProbeCapsLpcBootrom(unsigned int *caps, char *binary)
 
 
 static int
-bhyveProbeCapsVNCPassword(unsigned int *caps, char *binary)
+bhyveProbeCapsVNCPassword(virBitmap *caps, char *binary)
 {
     return bhyveProbeCapsDeviceHelper(caps, binary,
                                       "-s",
@@ -350,7 +374,7 @@ bhyveProbeCapsVNCPassword(unsigned int *caps, char *binary)
 
 
 static int
-bhyveProbeCapsLpcTpm(unsigned int *caps, char *binary)
+bhyveProbeCapsLpcTpm(virBitmap *caps, char *binary)
 {
     return bhyveProbeCapsDeviceHelper(caps, binary,
                                       "-l",
@@ -361,7 +385,7 @@ bhyveProbeCapsLpcTpm(unsigned int *caps, char *binary)
 
 
 static void
-bhyveProbeCapsRctl(unsigned int *caps)
+bhyveProbeCapsRctl(virBitmap *caps)
 {
     bool racct_enable;
     size_t racct_enable_len;
@@ -376,13 +400,13 @@ bhyveProbeCapsRctl(unsigned int *caps)
         return;
 
     if (racct_enable)
-        *caps |= BHYVE_CAP_RCTL;
+        virBhyveCapsSet(caps, BHYVE_CAP_RCTL);
 
     return;
 }
 
 static int
-bhyveProbeCapsBhyvectl(unsigned int *caps)
+bhyveProbeCapsBhyvectl(virBitmap *caps)
 {
     g_autofree char *binary = virFindFileInPath("bhyvectl");
     g_autofree char *help = NULL;
@@ -399,14 +423,15 @@ bhyveProbeCapsBhyvectl(unsigned int *caps)
         return -1;
 
     if (strstr(help, "--get-vm-pid") != NULL)
-        *caps |= BHYVE_CAP_GET_VMPID;
+        virBhyveCapsSet(caps, BHYVE_CAP_GET_VMPID);
 
     return 0;
 }
 
 int
-virBhyveProbeCaps(unsigned int *caps)
+virBhyveProbeCaps(virBitmap **caps)
 {
+    g_autoptr(virBitmap) bitmap = virBitmapNew(BHYVE_CAP_LAST);
     char *binary;
     int ret = 0;
 
@@ -414,27 +439,29 @@ virBhyveProbeCaps(unsigned int *caps)
     if (binary == NULL)
         goto out;
 
-    if ((ret = bhyveProbeCapsFromHelp(caps, binary)))
+    if ((ret = bhyveProbeCapsFromHelp(bitmap, binary)))
         goto out;
 
-    if ((ret = bhyveProbeCapsFromSHelp(caps, binary)))
+    if ((ret = bhyveProbeCapsFromSHelp(bitmap, binary)))
         goto out;
 
-    if ((ret = bhyveProbeCapsLpcBootrom(caps, binary)))
+    if ((ret = bhyveProbeCapsLpcBootrom(bitmap, binary)))
         goto out;
 
-    if ((ret = bhyveProbeCapsVNCPassword(caps, binary)))
+    if ((ret = bhyveProbeCapsVNCPassword(bitmap, binary)))
         goto out;
 
-    if ((ret = bhyveProbeCapsBhyvectl(caps)))
+    if ((ret = bhyveProbeCapsBhyvectl(bitmap)))
         goto out;
 
-    bhyveProbeCapsRctl(caps);
+    bhyveProbeCapsRctl(bitmap);
 
-    if ((ret = bhyveProbeCapsLpcTpm(caps, binary)))
+    if ((ret = bhyveProbeCapsLpcTpm(bitmap, binary)))
         goto out;
 
  out:
+    if (ret == 0)
+        *caps = g_steal_pointer(&bitmap);
     VIR_FREE(binary);
     return ret;
 }
diff --git a/src/bhyve/bhyve_capabilities.h b/src/bhyve/bhyve_capabilities.h
index 35ca214538..90e604c41b 100644
--- a/src/bhyve/bhyve_capabilities.h
+++ b/src/bhyve/bhyve_capabilities.h
@@ -24,12 +24,13 @@
 
 #include "capabilities.h"
 #include "conf/domain_capabilities.h"
+#include "virbitmap.h"
 
 #include "bhyve_utils.h"
 
 virCaps *virBhyveCapsBuild(void);
 int virBhyveDomainCapsFill(virDomainCaps *caps,
-                           unsigned int bhyvecaps,
+                           virBitmap *bhyvecaps,
                            virDomainCapsStringValues *firmwares);
 virDomainCaps *virBhyveDomainCapsBuild(bhyveConn *conn,
                                        const char *emulatorbin,
@@ -43,25 +44,34 @@ typedef enum {
 } virBhyveGrubCapsFlags;
 
 typedef enum {
-    BHYVE_CAP_RTC_UTC = 1 << 0,
-    BHYVE_CAP_AHCI32SLOT = 1 << 1,
-    BHYVE_CAP_NET_E1000 = 1 << 2,
-    BHYVE_CAP_LPC_BOOTROM = 1 << 3,
-    BHYVE_CAP_FBUF = 1 << 4,
-    BHYVE_CAP_XHCI = 1 << 5,
-    BHYVE_CAP_CPUTOPOLOGY = 1 << 6,
-    BHYVE_CAP_SOUND_HDA = 1 << 7,
-    BHYVE_CAP_VNC_PASSWORD = 1 << 8,
-    BHYVE_CAP_VIRTIO_9P = 1 << 9,
-    BHYVE_CAP_VIRTIO_RND = 1 << 10,
-    BHYVE_CAP_NVME = 1 << 11,
-    BHYVE_CAP_ACPI = 1 << 12,
-    BHYVE_CAP_NUMA = 1 << 13,
-    BHYVE_CAP_RCTL = 1 << 14,
-    BHYVE_CAP_MONITOR = 1 << 15,
-    BHYVE_CAP_GET_VMPID = 1 << 16,
-    BHYVE_CAP_LPC_TPM = 1 << 17,
+    BHYVE_CAP_RTC_UTC,
+    BHYVE_CAP_AHCI32SLOT,
+    BHYVE_CAP_NET_E1000,
+    BHYVE_CAP_LPC_BOOTROM,
+    BHYVE_CAP_FBUF,
+    BHYVE_CAP_XHCI,
+    BHYVE_CAP_CPUTOPOLOGY,
+    BHYVE_CAP_SOUND_HDA,
+    BHYVE_CAP_VNC_PASSWORD,
+    BHYVE_CAP_VIRTIO_9P,
+    BHYVE_CAP_VIRTIO_RND,
+    BHYVE_CAP_NVME,
+    BHYVE_CAP_ACPI,
+    BHYVE_CAP_NUMA,
+    BHYVE_CAP_RCTL,
+    BHYVE_CAP_MONITOR,
+    BHYVE_CAP_GET_VMPID,
+    BHYVE_CAP_LPC_TPM,
+
+    BHYVE_CAP_LAST,
 } virBhyveCapsFlags;
 
+void virBhyveCapsSet(virBitmap *caps,
+                     virBhyveCapsFlags flag) ATTRIBUTE_NONNULL(1);
+void virBhyveCapsClear(virBitmap *caps,
+                       virBhyveCapsFlags flag) ATTRIBUTE_NONNULL(1);
+bool virBhyveCapsGet(virBitmap *caps,
+                     virBhyveCapsFlags flag);
+
 int virBhyveProbeGrubCaps(virBhyveGrubCapsFlags *caps);
-int virBhyveProbeCaps(unsigned int *caps);
+int virBhyveProbeCaps(virBitmap **caps);
diff --git a/src/bhyve/bhyve_command.c b/src/bhyve/bhyve_command.c
index dac3146785..09ef61e798 100644
--- a/src/bhyve/bhyve_command.c
+++ b/src/bhyve/bhyve_command.c
@@ -60,7 +60,7 @@ bhyveBuildNetArgStr(const virDomainDef *def,
     if (net->model == VIR_DOMAIN_NET_MODEL_VIRTIO) {
         nic_model = "virtio-net";
     } else if (net->model == VIR_DOMAIN_NET_MODEL_E1000) {
-        if ((bhyveDriverGetBhyveCaps(driver) & BHYVE_CAP_NET_E1000) != 0) {
+        if (virBhyveCapsGet(bhyveDriverGetBhyveCaps(driver), BHYVE_CAP_NET_E1000)) {
             nic_model = "e1000";
         } else {
             virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
@@ -272,7 +272,7 @@ bhyveBuildTPMArgStr(const virDomainDef *def G_GNUC_UNUSED,
                     struct _bhyveConn *driver,
                     virCommand *cmd)
 {
-    if (!(bhyveDriverGetBhyveCaps(driver) & BHYVE_CAP_LPC_TPM)) {
+    if (!virBhyveCapsGet(bhyveDriverGetBhyveCaps(driver), BHYVE_CAP_LPC_TPM)) {
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                        _("Installed bhyve binary does not support TPM devices"));
         return -1;
@@ -333,13 +333,13 @@ bhyveBuildAHCIControllerArgStr(const virDomainDef *def,
 
         switch (disk->device) {
         case VIR_DOMAIN_DISK_DEVICE_DISK:
-            if ((bhyveDriverGetBhyveCaps(driver) & BHYVE_CAP_AHCI32SLOT))
+            if (virBhyveCapsGet(bhyveDriverGetBhyveCaps(driver), BHYVE_CAP_AHCI32SLOT))
                 virBufferAsprintf(&device, ",hd:%s", disk_source);
             else
                 virBufferAsprintf(&device, "-hd,%s", disk_source);
             break;
         case VIR_DOMAIN_DISK_DEVICE_CDROM:
-            if ((bhyveDriverGetBhyveCaps(driver) & BHYVE_CAP_AHCI32SLOT))
+            if (virBhyveCapsGet(bhyveDriverGetBhyveCaps(driver), BHYVE_CAP_AHCI32SLOT))
                 virBufferAsprintf(&device, ",cd:%s", disk_source);
             else
                 virBufferAsprintf(&device, "-cd,%s", disk_source);
@@ -488,7 +488,7 @@ bhyveBuildNVMeControllerArgStr(const virDomainDef *def,
         if (disk->bus != VIR_DOMAIN_DISK_BUS_NVME)
             continue;
 
-        if (!(bhyveDriverGetBhyveCaps(driver) & BHYVE_CAP_NVME)) {
+        if (!virBhyveCapsGet(bhyveDriverGetBhyveCaps(driver), BHYVE_CAP_NVME)) {
             virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                            _("Bhyve version does not support NVMe"));
             return -1;
@@ -716,7 +716,7 @@ bhyveBuildGraphicsArgStr(const virDomainDef *def,
     bool escapeAddr;
     unsigned short port;
 
-    if (!(bhyveDriverGetBhyveCaps(driver) & BHYVE_CAP_LPC_BOOTROM) ||
+    if (!virBhyveCapsGet(bhyveDriverGetBhyveCaps(driver), BHYVE_CAP_LPC_BOOTROM) ||
         def->os.bootloader ||
         !def->os.loader) {
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
@@ -724,7 +724,7 @@ bhyveBuildGraphicsArgStr(const virDomainDef *def,
         return -1;
     }
 
-    if (!(bhyveDriverGetBhyveCaps(driver) & BHYVE_CAP_FBUF)) {
+    if (!virBhyveCapsGet(bhyveDriverGetBhyveCaps(driver), BHYVE_CAP_FBUF)) {
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                        _("Bhyve version does not support framebuffer"));
         return -1;
@@ -791,7 +791,7 @@ bhyveBuildGraphicsArgStr(const virDomainDef *def,
     }
 
     if (graphics->data.vnc.auth.passwd) {
-        if (!(bhyveDriverGetBhyveCaps(driver) & BHYVE_CAP_VNC_PASSWORD)) {
+        if (!virBhyveCapsGet(bhyveDriverGetBhyveCaps(driver), BHYVE_CAP_VNC_PASSWORD)) {
             virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                            _("VNC Password authentication not supported by bhyve"));
             return -1;
@@ -805,7 +805,7 @@ bhyveBuildGraphicsArgStr(const virDomainDef *def,
 
         virBufferAsprintf(&opt, ",password=%s", graphics->data.vnc.auth.passwd);
     } else {
-        if (!(bhyveDriverGetBhyveCaps(driver) & BHYVE_CAP_VNC_PASSWORD))
+        if (!virBhyveCapsGet(bhyveDriverGetBhyveCaps(driver), BHYVE_CAP_VNC_PASSWORD))
             VIR_WARN("%s", _("Security warning: VNC auth is not supported."));
         else
             VIR_WARN("%s", _("Security warning: VNC is used without authentication."));
@@ -836,7 +836,7 @@ bhyveBuildSoundArgStr(const virDomainDef *def G_GNUC_UNUSED,
 {
     g_auto(virBuffer) params = VIR_BUFFER_INITIALIZER;
 
-    if (!(bhyveDriverGetBhyveCaps(driver) & BHYVE_CAP_SOUND_HDA)) {
+    if (!virBhyveCapsGet(bhyveDriverGetBhyveCaps(driver), BHYVE_CAP_SOUND_HDA)) {
         /* Currently, bhyve only supports "hda" sound devices, so
            if it's not supported, sound devices are not supported at all */
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
@@ -1157,7 +1157,7 @@ virBhyveProcessBuildBhyveCmd(struct _bhyveConn *driver, virDomainDef *def,
             return NULL;
         }
 
-        if ((bhyveDriverGetBhyveCaps(driver) & BHYVE_CAP_CPUTOPOLOGY) != 0) {
+        if (virBhyveCapsGet(bhyveDriverGetBhyveCaps(driver), BHYVE_CAP_CPUTOPOLOGY)) {
             virCommandAddArgFormat(cmd, "cpus=%d,sockets=%d,cores=%d,threads=%d",
                                    nvcpus,
                                    def->cpu->sockets,
@@ -1189,7 +1189,7 @@ virBhyveProcessBuildBhyveCmd(struct _bhyveConn *driver, virDomainDef *def,
 
     /* NUMA */
     if (ncells) {
-        if (!(bhyveDriverGetBhyveCaps(driver) & BHYVE_CAP_NUMA)) {
+        if (!virBhyveCapsGet(bhyveDriverGetBhyveCaps(driver), BHYVE_CAP_NUMA)) {
             virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                            _("Installed bhyve binary does not support NUMA configuration"));
             return NULL;
@@ -1222,7 +1222,7 @@ virBhyveProcessBuildBhyveCmd(struct _bhyveConn *driver, virDomainDef *def,
 
     /* Options */
     if ((def->features[VIR_DOMAIN_FEATURE_ACPI] == VIR_TRISTATE_SWITCH_ON) &&
-        (bhyveDriverGetBhyveCaps(driver) & BHYVE_CAP_ACPI))
+        virBhyveCapsGet(bhyveDriverGetBhyveCaps(driver), BHYVE_CAP_ACPI))
         /* As of FreeBSD commit
          * https://cgit.freebsd.org/src/commit/?id=6a0e7f908802b86ca5d1c0b3c404b8391d0f626e
          * bhyve(8) generates ACPI tables unconditionally, so nothing needs to be done
@@ -1238,7 +1238,7 @@ virBhyveProcessBuildBhyveCmd(struct _bhyveConn *driver, virDomainDef *def,
         /* used by default in bhyve */
         break;
     case VIR_DOMAIN_CLOCK_OFFSET_UTC:
-        if ((bhyveDriverGetBhyveCaps(driver) & BHYVE_CAP_RTC_UTC) != 0) {
+        if (virBhyveCapsGet(bhyveDriverGetBhyveCaps(driver), BHYVE_CAP_RTC_UTC)) {
             virCommandAddArg(cmd, "-u");
         } else {
             virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
@@ -1279,7 +1279,7 @@ virBhyveProcessBuildBhyveCmd(struct _bhyveConn *driver, virDomainDef *def,
         g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
 
         if (ARCH_IS_X86(arch)) {
-            if ((bhyveDriverGetBhyveCaps(driver) & BHYVE_CAP_LPC_BOOTROM)) {
+            if (virBhyveCapsGet(bhyveDriverGetBhyveCaps(driver), BHYVE_CAP_LPC_BOOTROM)) {
                 virBufferAsprintf(&buf, "bootrom,%s", def->os.loader->path);
                 if (def->os.loader->nvram && def->os.loader->nvram->path)
                     virBufferAsprintf(&buf, ",%s", def->os.loader->nvram->path);
diff --git a/src/bhyve/bhyve_domain.c b/src/bhyve/bhyve_domain.c
index 142d01e016..0ee2e06664 100644
--- a/src/bhyve/bhyve_domain.c
+++ b/src/bhyve/bhyve_domain.c
@@ -157,7 +157,7 @@ bhyveDomainDefPostParse(virDomainDef *def,
     /* When not specified in the domain XML, clock.offset defaults to UTC which is
      * not supported by bhyve on ARM64. So force it to LOCALTIME. */
     if ((def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_UTC) &&
-        !(bhyveDriverGetBhyveCaps(driver) & BHYVE_CAP_RTC_UTC))
+        !virBhyveCapsGet(bhyveDriverGetBhyveCaps(driver), BHYVE_CAP_RTC_UTC))
         def->clock.offset = VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME;
 
     /* bhyve/arm64 does not provide the bhyveload(8) tool,
@@ -237,7 +237,7 @@ bhyveDomainDiskDefAssignAddress(struct _bhyveConn *driver,
     case VIR_DOMAIN_DISK_BUS_SATA:
         def->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE;
 
-        if ((driver->bhyvecaps & BHYVE_CAP_AHCI32SLOT) != 0) {
+        if (virBhyveCapsGet(driver->bhyvecaps, BHYVE_CAP_AHCI32SLOT)) {
             def->info.addr.drive.controller = idx / 32;
             def->info.addr.drive.unit = idx % 32;
         } else {
diff --git a/src/bhyve/bhyve_driver.c b/src/bhyve/bhyve_driver.c
index 4c4ba9b0ba..47ed7d6963 100644
--- a/src/bhyve/bhyve_driver.c
+++ b/src/bhyve/bhyve_driver.c
@@ -783,7 +783,7 @@ bhyveConnectDomainXMLToNative(virConnectPtr conn,
             return NULL;
         }
 
-        if ((bhyveDriverGetBhyveCaps(privconn) & BHYVE_CAP_LPC_BOOTROM) == 0) {
+        if (!virBhyveCapsGet(bhyveDriverGetBhyveCaps(privconn), BHYVE_CAP_LPC_BOOTROM)) {
             virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                            _("Installed bhyve binary does not support bootrom"));
             return NULL;
@@ -1377,6 +1377,7 @@ bhyveStateCleanup(void)
     virSysinfoDefFree(bhyve_driver->hostsysinfo);
     virObjectUnref(bhyve_driver->domainEventState);
     virPortAllocatorRangeFree(bhyve_driver->remotePorts);
+    virBitmapFree(bhyve_driver->bhyvecaps);
 
     if (bhyve_driver->lockFD != -1)
         virPidFileRelease(bhyve_driver->config->stateDir, "driver", bhyve_driver->lockFD);
@@ -1421,13 +1422,15 @@ bhyveStateInitialize(bool privileged,
     if (virBhyveProbeCaps(&bhyve_driver->bhyvecaps) < 0)
         goto cleanup;
 
-    if (!privileged && !(bhyveDriverGetBhyveCaps(bhyve_driver) & BHYVE_CAP_MONITOR)) {
+    if (!privileged &&
+        !virBhyveCapsGet(bhyveDriverGetBhyveCaps(bhyve_driver), BHYVE_CAP_MONITOR)) {
         virReportError(VIR_ERR_INVALID_ARG, "%s",
                        _("bhyve does not support monitor mode, cannot run unprivileged"));
         goto cleanup;
     }
 
-    if (!privileged && !(bhyveDriverGetBhyveCaps(bhyve_driver) & BHYVE_CAP_GET_VMPID)) {
+    if (!privileged &&
+        !virBhyveCapsGet(bhyveDriverGetBhyveCaps(bhyve_driver), BHYVE_CAP_GET_VMPID)) {
         virReportError(VIR_ERR_INVALID_ARG, "%s",
                        _("bhyvectl does not support querying the VM PID, cannot run unprivileged"));
         goto cleanup;
@@ -1513,12 +1516,12 @@ bhyveStateInitialize(bool privileged,
     return VIR_DRV_STATE_INIT_ERROR;
 }
 
-unsigned
+virBitmap *
 bhyveDriverGetBhyveCaps(struct _bhyveConn *driver)
 {
     if (driver != NULL)
         return driver->bhyvecaps;
-    return 0;
+    return NULL;
 }
 
 unsigned
@@ -1774,7 +1777,7 @@ bhyveConnectDomainXMLFromNative(virConnectPtr conn,
 {
     g_autoptr(virDomainDef) def = NULL;
     struct _bhyveConn *privconn = conn->privateData;
-    unsigned bhyveCaps = bhyveDriverGetBhyveCaps(privconn);
+    virBitmap *bhyveCaps = bhyveDriverGetBhyveCaps(privconn);
 
     virCheckFlags(0, NULL);
 
@@ -2409,7 +2412,7 @@ bhyveDomainSetMemoryParameters(virDomainPtr domain,
         return -1;
 
     if (def) {
-        if ((bhyveDriverGetBhyveCaps(privconn) & BHYVE_CAP_RCTL) == 0) {
+        if (!virBhyveCapsGet(bhyveDriverGetBhyveCaps(privconn), BHYVE_CAP_RCTL)) {
             virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                            _("Cannot set resource limits: RACCT/RCTL is either not supported or not enabled"));
             goto endjob;
diff --git a/src/bhyve/bhyve_driver.h b/src/bhyve/bhyve_driver.h
index 3f86081910..49ba7bbddb 100644
--- a/src/bhyve/bhyve_driver.h
+++ b/src/bhyve/bhyve_driver.h
@@ -25,7 +25,7 @@
 
 int bhyveRegister(void);
 
-unsigned bhyveDriverGetBhyveCaps(struct _bhyveConn *driver);
+virBitmap *bhyveDriverGetBhyveCaps(struct _bhyveConn *driver);
 
 unsigned bhyveDriverGetGrubCaps(struct _bhyveConn *driver);
 
diff --git a/src/bhyve/bhyve_parse_command.c b/src/bhyve/bhyve_parse_command.c
index 3d9a6f3964..fd8d062c31 100644
--- a/src/bhyve/bhyve_parse_command.c
+++ b/src/bhyve/bhyve_parse_command.c
@@ -253,7 +253,7 @@ bhyveCommandLineToArgv(const char *nativeConfig,
 
 static int
 bhyveParseBhyveLPCArg(virDomainDef *def,
-                      unsigned caps G_GNUC_UNUSED,
+                      virBitmap *caps G_GNUC_UNUSED,
                       const char *arg)
 {
     /* -l emulation[,config] */
@@ -391,7 +391,7 @@ bhyveParsePCISlot(const char *slotdef,
 
 static int
 bhyveParsePCIDisk(virDomainDef *def,
-                  unsigned caps G_GNUC_UNUSED,
+                  virBitmap *caps G_GNUC_UNUSED,
                   unsigned pcibus,
                   unsigned pcislot,
                   unsigned function,
@@ -461,7 +461,7 @@ bhyveParsePCIDisk(virDomainDef *def,
 static int
 bhyveParsePCINet(virDomainDef *def,
                  virDomainXMLOption *xmlopt,
-                 unsigned caps G_GNUC_UNUSED,
+                 virBitmap *caps G_GNUC_UNUSED,
                  unsigned bus,
                  unsigned slot,
                  unsigned function,
@@ -536,7 +536,7 @@ bhyveParsePCINet(virDomainDef *def,
 static int
 bhyveParsePCIFbuf(virDomainDef *def,
                   virDomainXMLOption *xmlopt,
-                  unsigned caps G_GNUC_UNUSED,
+                  virBitmap *caps G_GNUC_UNUSED,
                   unsigned bus,
                   unsigned slot,
                   unsigned function,
@@ -644,7 +644,7 @@ bhyveParsePCIFbuf(virDomainDef *def,
 static int
 bhyveParsePCIRND(virDomainDef *def,
                  virDomainXMLOption *xmlopt G_GNUC_UNUSED,
-                 unsigned caps G_GNUC_UNUSED,
+                 virBitmap *caps G_GNUC_UNUSED,
                  unsigned bus,
                  unsigned slot,
                  unsigned function,
@@ -733,7 +733,7 @@ bhyveParsePassthru(virDomainDef *def G_GNUC_UNUSED,
 static int
 bhyveParseBhyvePCIArg(virDomainDef *def,
                       virDomainXMLOption *xmlopt,
-                      unsigned caps,
+                      virBitmap *caps,
                       unsigned *nvirtiodisk,
                       unsigned *nahcidisk,
                       const char *arg)
@@ -822,7 +822,7 @@ bhyveParseBhyvePCIArg(virDomainDef *def,
 static int
 bhyveParseBhyveCommandLine(virDomainDef *def,
                            virDomainXMLOption *xmlopt,
-                           unsigned caps,
+                           virBitmap *caps,
                            int argc, char **argv)
 {
     int vcpus = 1;
@@ -1025,7 +1025,7 @@ bhyveParseCustomLoaderCommandLine(virDomainDef *def,
 
 virDomainDef *
 bhyveParseCommandLineString(const char* nativeConfig,
-                            unsigned caps,
+                            virBitmap *caps,
                             virDomainXMLOption *xmlopt)
 {
     g_autoptr(virDomainDef) def = NULL;
diff --git a/src/bhyve/bhyve_parse_command.h b/src/bhyve/bhyve_parse_command.h
index 7cf3e70b5e..bf9ad3beb2 100644
--- a/src/bhyve/bhyve_parse_command.h
+++ b/src/bhyve/bhyve_parse_command.h
@@ -21,5 +21,5 @@
 #pragma once
 
 virDomainDef *bhyveParseCommandLineString(const char* nativeConfig,
-                                          unsigned caps,
+                                          virBitmap *caps,
                                           virDomainXMLOption *xmlopt);
diff --git a/src/bhyve/bhyve_process.c b/src/bhyve/bhyve_process.c
index 41b5c118f2..c27a5cf6ed 100644
--- a/src/bhyve/bhyve_process.c
+++ b/src/bhyve/bhyve_process.c
@@ -225,7 +225,7 @@ bhyveSetResourceLimits(struct _bhyveConn *driver, virDomainObj *vm)
         return -1;
     }
 
-    if ((bhyveDriverGetBhyveCaps(driver) & BHYVE_CAP_RCTL) == 0) {
+    if (!virBhyveCapsGet(bhyveDriverGetBhyveCaps(driver), BHYVE_CAP_RCTL)) {
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                        _("Cannot set resource limits: RACCT/RCTL is either not supported or not enabled"));
         return -1;
diff --git a/src/bhyve/bhyve_utils.h b/src/bhyve/bhyve_utils.h
index db2789fe02..6d15035693 100644
--- a/src/bhyve/bhyve_utils.h
+++ b/src/bhyve/bhyve_utils.h
@@ -27,6 +27,7 @@
 #include "virdomainobjlist.h"
 #include "virthread.h"
 #include "hypervisor/virclosecallbacks.h"
+#include "virbitmap.h"
 #include "virportallocator.h"
 
 typedef struct _virBhyveDriverConfig virBhyveDriverConfig;
@@ -69,7 +70,7 @@ struct _bhyveConn {
 
     virPortAllocatorRange *remotePorts;
 
-    unsigned bhyvecaps;
+    virBitmap *bhyvecaps;
     unsigned grubcaps;
 
     bool privileged;
diff --git a/tests/bhyveargv2xmltest.c b/tests/bhyveargv2xmltest.c
index acfaade24c..4cb5045704 100644
--- a/tests/bhyveargv2xmltest.c
+++ b/tests/bhyveargv2xmltest.c
@@ -143,7 +143,8 @@ mymain(void)
     DO_TEST_FULL(name, FLAG_EXPECT_PARSE_ERROR)
 
     driver.grubcaps = BHYVE_GRUB_CAP_CONSDEV;
-    driver.bhyvecaps = BHYVE_CAP_RTC_UTC;
+    driver.bhyvecaps = virBitmapNew(BHYVE_CAP_LAST);
+    virBhyveCapsSet(driver.bhyvecaps, BHYVE_CAP_RTC_UTC);
 
     DO_TEST("base");
     DO_TEST("wired");
@@ -193,6 +194,7 @@ mymain(void)
 
     virObjectUnref(driver.caps);
     virObjectUnref(driver.xmlopt);
+    virBitmapFree(driver.bhyvecaps);
 
     return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
 }
diff --git a/tests/bhyvexml2argvtest.c b/tests/bhyvexml2argvtest.c
index 8a6e044ad0..650563821b 100644
--- a/tests/bhyvexml2argvtest.c
+++ b/tests/bhyvexml2argvtest.c
@@ -214,13 +214,20 @@ mymain(void)
     DO_TEST_FULL(name, FLAG_EXPECT_PREPARE_ERROR)
 
     driver.grubcaps = BHYVE_GRUB_CAP_CONSDEV;
-    driver.bhyvecaps = BHYVE_CAP_RTC_UTC | BHYVE_CAP_AHCI32SLOT | \
-                       BHYVE_CAP_NET_E1000 | BHYVE_CAP_LPC_BOOTROM | \
-                       BHYVE_CAP_FBUF | BHYVE_CAP_XHCI | \
-                       BHYVE_CAP_CPUTOPOLOGY | BHYVE_CAP_SOUND_HDA | \
-                       BHYVE_CAP_VNC_PASSWORD | BHYVE_CAP_VIRTIO_9P | \
-                       BHYVE_CAP_NVME | BHYVE_CAP_NUMA | \
-                       BHYVE_CAP_LPC_TPM;
+    driver.bhyvecaps = virBitmapNew(BHYVE_CAP_LAST);
+    virBhyveCapsSet(driver.bhyvecaps, BHYVE_CAP_RTC_UTC);
+    virBhyveCapsSet(driver.bhyvecaps, BHYVE_CAP_AHCI32SLOT);
+    virBhyveCapsSet(driver.bhyvecaps, BHYVE_CAP_NET_E1000);
+    virBhyveCapsSet(driver.bhyvecaps, BHYVE_CAP_LPC_BOOTROM);
+    virBhyveCapsSet(driver.bhyvecaps, BHYVE_CAP_FBUF);
+    virBhyveCapsSet(driver.bhyvecaps, BHYVE_CAP_XHCI);
+    virBhyveCapsSet(driver.bhyvecaps, BHYVE_CAP_CPUTOPOLOGY);
+    virBhyveCapsSet(driver.bhyvecaps, BHYVE_CAP_SOUND_HDA);
+    virBhyveCapsSet(driver.bhyvecaps, BHYVE_CAP_VNC_PASSWORD);
+    virBhyveCapsSet(driver.bhyvecaps, BHYVE_CAP_VIRTIO_9P);
+    virBhyveCapsSet(driver.bhyvecaps, BHYVE_CAP_NVME);
+    virBhyveCapsSet(driver.bhyvecaps, BHYVE_CAP_NUMA);
+    virBhyveCapsSet(driver.bhyvecaps, BHYVE_CAP_LPC_TPM);
 
     DO_TEST("base");
     DO_TEST_UNPRIVILEGED_FAILURE("base");
@@ -228,7 +235,7 @@ mymain(void)
     DO_TEST_FAILURE("bootorder-invalid-index");
     DO_TEST("wired");
     DO_TEST("acpiapic");
-    driver.bhyvecaps &= ~BHYVE_CAP_ACPI;
+    virBhyveCapsClear(driver.bhyvecaps, BHYVE_CAP_ACPI);
     DO_TEST_FAILURE("acpiapic");
     DO_TEST("disk-cdrom");
     DO_TEST("disk-virtio");
@@ -281,7 +288,7 @@ mymain(void)
     DO_TEST("numa");
     DO_TEST_FAILURE("numa-empty-cpuset");
     DO_TEST_FAILURE("numa-too-many-domains");
-    driver.bhyvecaps &= ~BHYVE_CAP_NUMA;
+    virBhyveCapsClear(driver.bhyvecaps, BHYVE_CAP_NUMA);
     DO_TEST_FAILURE("numa");
     fakefirmwaredir = g_steal_pointer(&driver.config->firmwareDir);
     driver.config->firmwareDir = g_steal_pointer(&fakefirmwareemptydir);
@@ -291,13 +298,13 @@ mymain(void)
     DO_TEST_FAILURE("fs-9p-unsupported-type");
     DO_TEST_FAILURE("fs-9p-unsupported-driver");
     DO_TEST_FAILURE("fs-9p-unsupported-accessmode");
-    driver.bhyvecaps &= ~BHYVE_CAP_VIRTIO_9P;
+    virBhyveCapsClear(driver.bhyvecaps, BHYVE_CAP_VIRTIO_9P);
     DO_TEST_FAILURE("fs-9p");
     DO_TEST("virtio-rnd");
     DO_TEST_FAILURE("virtio-rnd-backend-random-non-default-file");
     DO_TEST_FAILURE("virtio-rnd-backend-builtin");
     DO_TEST_FAILURE("virtio-rnd-transitional");
-    driver.bhyvecaps &= ~BHYVE_CAP_VIRTIO_RND;
+    virBhyveCapsClear(driver.bhyvecaps, BHYVE_CAP_VIRTIO_RND);
     DO_TEST_FAILURE("virtio-rnd");
     DO_TEST("serial-tcp");
     DO_TEST("4-consoles");
@@ -338,7 +345,7 @@ mymain(void)
     DO_TEST_FAILURE("tpm-comma-path");
     DO_TEST_FAILURE("tpm-invalid-model");
     DO_TEST_FAILURE("tpm-multiple-devices");
-    driver.bhyvecaps &= ~BHYVE_CAP_LPC_TPM;
+    virBhyveCapsClear(driver.bhyvecaps, BHYVE_CAP_LPC_TPM);
     DO_TEST_FAILURE("tpm");
 
     /* Address allocation tests */
@@ -352,7 +359,7 @@ mymain(void)
     DO_TEST("addr-non-isa-controller-on-slot-1");
 
     /* The same without 32 devs per controller support */
-    driver.bhyvecaps ^= BHYVE_CAP_AHCI32SLOT;
+    virBhyveCapsClear(driver.bhyvecaps, BHYVE_CAP_AHCI32SLOT);
     DO_TEST("addr-no32devs-single-sata-disk");
     DO_TEST("addr-no32devs-multiple-sata-disks");
     DO_TEST_FAILURE("addr-no32devs-more-than-32-sata-disks");
@@ -362,33 +369,33 @@ mymain(void)
     DO_TEST_FAILURE("xhci-multiple-controllers");
     DO_TEST_FAILURE("xhci-no-devs");
     DO_TEST_FAILURE("xhci-multiple-devs");
-    driver.bhyvecaps ^= BHYVE_CAP_XHCI;
+    virBhyveCapsClear(driver.bhyvecaps, BHYVE_CAP_XHCI);
     DO_TEST_FAILURE("input-xhci-tablet");
 
     driver.grubcaps = 0;
 
     DO_TEST("serial-grub-nocons");
 
-    driver.bhyvecaps &= ~BHYVE_CAP_NET_E1000;
+    virBhyveCapsClear(driver.bhyvecaps, BHYVE_CAP_NET_E1000);
 
     DO_TEST_FAILURE("net-e1000");
 
-    driver.bhyvecaps &= ~BHYVE_CAP_LPC_BOOTROM;
+    virBhyveCapsClear(driver.bhyvecaps, BHYVE_CAP_LPC_BOOTROM);
     DO_TEST_FAILURE("uefi");
 
-    driver.bhyvecaps &= ~BHYVE_CAP_FBUF;
+    virBhyveCapsClear(driver.bhyvecaps, BHYVE_CAP_FBUF);
     DO_TEST_FAILURE("vnc");
 
-    driver.bhyvecaps &= ~BHYVE_CAP_CPUTOPOLOGY;
+    virBhyveCapsClear(driver.bhyvecaps, BHYVE_CAP_CPUTOPOLOGY);
     DO_TEST_FAILURE("cputopology");
 
-    driver.bhyvecaps &= ~BHYVE_CAP_SOUND_HDA;
+    virBhyveCapsClear(driver.bhyvecaps, BHYVE_CAP_SOUND_HDA);
     DO_TEST_FAILURE("sound");
 
-    driver.bhyvecaps &= ~BHYVE_CAP_VNC_PASSWORD;
+    virBhyveCapsClear(driver.bhyvecaps, BHYVE_CAP_VNC_PASSWORD);
     DO_TEST_FAILURE("vnc-password");
 
-    driver.bhyvecaps &= ~BHYVE_CAP_NVME;
+    virBhyveCapsClear(driver.bhyvecaps, BHYVE_CAP_NVME);
     DO_TEST_FAILURE("nvme");
 
     driver.config->bhyveloadTimeout = 300;
@@ -400,9 +407,9 @@ mymain(void)
     virTestSetHostArch(VIR_ARCH_AARCH64);
     driver.caps = virBhyveCapsBuild();
     /* bhyve does not support UTC clock on ARM */
-    driver.bhyvecaps ^= BHYVE_CAP_RTC_UTC;
+    virBhyveCapsClear(driver.bhyvecaps, BHYVE_CAP_RTC_UTC);
     /* bhyve does not support NUMA on ARM */
-    driver.bhyvecaps &= ~BHYVE_CAP_NUMA;
+    virBhyveCapsClear(driver.bhyvecaps, BHYVE_CAP_NUMA);
 
     DO_TEST("base");
     DO_TEST("console");
@@ -411,6 +418,7 @@ mymain(void)
 
     virObjectUnref(driver.caps);
     virObjectUnref(driver.xmlopt);
+    virBitmapFree(driver.bhyvecaps);
     virPortAllocatorRangeFree(driver.remotePorts);
     virObjectUnref(driver.config);
 
diff --git a/tests/bhyvexml2xmltest.c b/tests/bhyvexml2xmltest.c
index a9964f9825..724ba4d85f 100644
--- a/tests/bhyvexml2xmltest.c
+++ b/tests/bhyvexml2xmltest.c
@@ -95,7 +95,9 @@ mymain(void)
 # define DO_TEST_FAILURE(name) \
     DO_TEST_FULL(name, FLAG_EXPECT_FAILURE)
 
-    driver.bhyvecaps = BHYVE_CAP_AHCI32SLOT | BHYVE_CAP_RTC_UTC;
+    driver.bhyvecaps = virBitmapNew(BHYVE_CAP_LAST);
+    virBhyveCapsSet(driver.bhyvecaps, BHYVE_CAP_AHCI32SLOT);
+    virBhyveCapsSet(driver.bhyvecaps, BHYVE_CAP_RTC_UTC);
 
     DO_TEST_DIFFERENT("acpiapic");
     DO_TEST_DIFFERENT("base");
@@ -174,7 +176,7 @@ mymain(void)
     DO_TEST_DIFFERENT("addr-isa-controller-on-slot-31");
 
     /* The same without 32 devs per controller support */
-    driver.bhyvecaps ^= BHYVE_CAP_AHCI32SLOT;
+    virBhyveCapsClear(driver.bhyvecaps, BHYVE_CAP_AHCI32SLOT);
     DO_TEST_DIFFERENT("addr-no32devs-single-sata-disk");
     DO_TEST_DIFFERENT("addr-no32devs-multiple-sata-disks");
     DO_TEST_FAILURE("addr-no32devs-more-than-32-sata-disks");
@@ -186,7 +188,7 @@ mymain(void)
     virTestSetHostArch(VIR_ARCH_AARCH64);
     driver.caps = virBhyveCapsBuild();
     /* bhyve does not support UTC clock on ARM */
-    driver.bhyvecaps ^= BHYVE_CAP_RTC_UTC;
+    virBhyveCapsClear(driver.bhyvecaps, BHYVE_CAP_RTC_UTC);
 
     DO_TEST_DIFFERENT("base");
     DO_TEST_DIFFERENT("console");
@@ -194,6 +196,7 @@ mymain(void)
 
     virObjectUnref(driver.caps);
     virObjectUnref(driver.xmlopt);
+    virBitmapFree(driver.bhyvecaps);
     virObjectUnref(driver.config);
 
     return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
diff --git a/tests/domaincapstest.c b/tests/domaincapstest.c
index b3e9ff7051..b4ade48f91 100644
--- a/tests/domaincapstest.c
+++ b/tests/domaincapstest.c
@@ -147,7 +147,7 @@ fillXenCaps(virDomainCaps *domCaps)
 # include "bhyve/bhyve_capabilities.h"
 
 static int
-fillBhyveCaps(virDomainCaps *domCaps, unsigned int *bhyve_caps)
+fillBhyveCaps(virDomainCaps *domCaps, virBitmap *bhyve_caps)
 {
     g_autofree virDomainCapsStringValues *firmwares = NULL;
 
@@ -156,7 +156,7 @@ fillBhyveCaps(virDomainCaps *domCaps, unsigned int *bhyve_caps)
     if (fillStringValues(firmwares, "/foo/bar", "/foo/baz", NULL) < 0)
         return -1;
 
-    if (virBhyveDomainCapsFill(domCaps, *bhyve_caps, firmwares) < 0)
+    if (virBhyveDomainCapsFill(domCaps, bhyve_caps, firmwares) < 0)
         return -1;
 
     return 0;
@@ -420,7 +420,7 @@ mymain(void)
     int ret = 0;
 
 #if WITH_BHYVE
-    unsigned int bhyve_caps = 0;
+    g_autoptr(virBitmap) bhyve_caps = virBitmapNew(BHYVE_CAP_LAST);
 #endif
 
 #if WITH_QEMU
@@ -523,16 +523,16 @@ mymain(void)
 #endif /* WITH_LIBXL */
 
 #if WITH_BHYVE
-    DO_TEST_BHYVE("basic", "/usr/sbin/bhyve", &bhyve_caps, VIR_DOMAIN_VIRT_BHYVE);
+    DO_TEST_BHYVE("basic", "/usr/sbin/bhyve", bhyve_caps, VIR_DOMAIN_VIRT_BHYVE);
 
-    bhyve_caps |= BHYVE_CAP_LPC_BOOTROM;
-    DO_TEST_BHYVE("uefi", "/usr/sbin/bhyve", &bhyve_caps, VIR_DOMAIN_VIRT_BHYVE);
+    virBhyveCapsSet(bhyve_caps, BHYVE_CAP_LPC_BOOTROM);
+    DO_TEST_BHYVE("uefi", "/usr/sbin/bhyve", bhyve_caps, VIR_DOMAIN_VIRT_BHYVE);
 
-    bhyve_caps |= BHYVE_CAP_FBUF;
-    DO_TEST_BHYVE("fbuf", "/usr/sbin/bhyve", &bhyve_caps, VIR_DOMAIN_VIRT_BHYVE);
+    virBhyveCapsSet(bhyve_caps, BHYVE_CAP_FBUF);
+    DO_TEST_BHYVE("fbuf", "/usr/sbin/bhyve", bhyve_caps, VIR_DOMAIN_VIRT_BHYVE);
 
-    bhyve_caps |= BHYVE_CAP_LPC_TPM;
-    DO_TEST_BHYVE("tpm", "/usr/sbin/bhyve", &bhyve_caps, VIR_DOMAIN_VIRT_BHYVE);
+    virBhyveCapsSet(bhyve_caps, BHYVE_CAP_LPC_TPM);
+    DO_TEST_BHYVE("tpm", "/usr/sbin/bhyve", bhyve_caps, VIR_DOMAIN_VIRT_BHYVE);
 #endif /* WITH_BHYVE */
 
     return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
-- 
2.55.0
Re: [PATCH] bhyve: capabilities: use virBitmap to store capabilities
Posted by Michal Prívozník via Devel 6 days, 1 hour ago
On 10/18/26 12:47, Roman Bogorodskiy wrote:
> Similarly to the qemu driver, store bhyve capabilities in virBitmap.
> Add helpers to work with capabilities: virBhyveCapsGet(), virBhyveCapsSet(),
> and virBhyveCapsClear().
> 
> No functional changes.
> 
> Signed-off-by: Roman Bogorodskiy <bogorodskiy@gmail.com>
> ---
>  src/bhyve/bhyve_capabilities.c  | 107 ++++++++++++++++++++------------
>  src/bhyve/bhyve_capabilities.h  |  50 +++++++++------
>  src/bhyve/bhyve_command.c       |  30 ++++-----
>  src/bhyve/bhyve_domain.c        |   4 +-
>  src/bhyve/bhyve_driver.c        |  17 ++---
>  src/bhyve/bhyve_driver.h        |   2 +-
>  src/bhyve/bhyve_parse_command.c |  16 ++---
>  src/bhyve/bhyve_parse_command.h |   2 +-
>  src/bhyve/bhyve_process.c       |   2 +-
>  src/bhyve/bhyve_utils.h         |   3 +-
>  tests/bhyveargv2xmltest.c       |   4 +-
>  tests/bhyvexml2argvtest.c       |  54 +++++++++-------
>  tests/bhyvexml2xmltest.c        |   9 ++-
>  tests/domaincapstest.c          |  20 +++---
>  14 files changed, 187 insertions(+), 133 deletions(-)

Reviewed-by: Michal Privoznik <mprivozn@redhat.com>

Michal