[libvirt] [PATCH v4 3/3] bhyve: implement PCI address allocation

Ján Tomko jtomko at redhat.com
Tue May 13 09:21:13 UTC 2014


On 05/11/2014 08:48 AM, Roman Bogorodskiy wrote:
> Automatically allocate PCI addresses for devices instead
> of hardcoding them in the driver code. The current
> allocation schema is to dedicate an entire slot for each devices.
> 

> Also, allow having arbitrary number of devices.

I think this can be split in a separate patch.

> ---
>  po/POTFILES.in                                     |   1 +
>  src/Makefile.am                                    |   4 +
>  src/bhyve/bhyve_command.c                          | 142 ++++++++---------
>  src/bhyve/bhyve_device.c                           | 174 +++++++++++++++++++++
>  src/bhyve/bhyve_device.h                           |  38 +++++
>  src/bhyve/bhyve_domain.c                           |  75 +++++++++
>  src/bhyve/bhyve_domain.h                           |  39 +++++
>  src/bhyve/bhyve_driver.c                           |  12 +-
>  .../bhyvexml2argvdata/bhyvexml2argv-acpiapic.args  |   2 +-
>  tests/bhyvexml2argvdata/bhyvexml2argv-acpiapic.xml |   2 +
>  tests/bhyvexml2argvdata/bhyvexml2argv-base.args    |   2 +-
>  tests/bhyvexml2argvdata/bhyvexml2argv-base.xml     |   2 +
>  tests/bhyvexml2argvdata/bhyvexml2argv-console.args |   4 +-
>  tests/bhyvexml2argvdata/bhyvexml2argv-console.xml  |   2 +
>  .../bhyvexml2argv-disk-virtio.args                 |   2 +-
>  .../bhyvexml2argv-disk-virtio.xml                  |   2 +
>  tests/bhyvexml2argvdata/bhyvexml2argv-macaddr.args |   2 +-
>  tests/bhyvexml2argvdata/bhyvexml2argv-macaddr.xml  |   2 +
>  tests/bhyvexml2argvdata/bhyvexml2argv-serial.args  |   4 +-
>  tests/bhyvexml2argvdata/bhyvexml2argv-serial.xml   |   2 +
>  20 files changed, 429 insertions(+), 84 deletions(-)
>  create mode 100644 src/bhyve/bhyve_device.c
>  create mode 100644 src/bhyve/bhyve_device.h
>  create mode 100644 src/bhyve/bhyve_domain.c
>  create mode 100644 src/bhyve/bhyve_domain.h
> 
> diff --git a/po/POTFILES.in b/po/POTFILES.in
> index 6e8d465..ef2f114 100644
> --- a/po/POTFILES.in
> +++ b/po/POTFILES.in
> @@ -9,6 +9,7 @@ gnulib/lib/regcomp.c
>  src/access/viraccessdriverpolkit.c
>  src/access/viraccessmanager.c
>  src/bhyve/bhyve_command.c
> +src/bhyve/bhyve_device.c
>  src/bhyve/bhyve_driver.c
>  src/bhyve/bhyve_process.c
>  src/conf/capabilities.c
> diff --git a/src/Makefile.am b/src/Makefile.am
> index cfb7097..dc7f794 100644
> --- a/src/Makefile.am
> +++ b/src/Makefile.am
> @@ -787,6 +787,10 @@ BHYVE_DRIVER_SOURCES =						\
>  		bhyve/bhyve_capabilities.h			\
>  		bhyve/bhyve_command.c				\
>  		bhyve/bhyve_command.h				\
> +		bhyve/bhyve_device.c				\
> +		bhyve/bhyve_device.h				\
> +		bhyve/bhyve_domain.c				\
> +		bhyve/bhyve_domain.h				\
>  		bhyve/bhyve_driver.h				\
>  		bhyve/bhyve_driver.c				\
>  		bhyve/bhyve_process.c				\
> diff --git a/src/bhyve/bhyve_command.c b/src/bhyve/bhyve_command.c
> index 91a8731..bc7ec5c 100644
> --- a/src/bhyve/bhyve_command.c
> +++ b/src/bhyve/bhyve_command.c
> @@ -41,21 +41,14 @@ VIR_LOG_INIT("bhyve.bhyve_command");
>  static int
>  bhyveBuildNetArgStr(const virDomainDef *def, virCommandPtr cmd, bool dryRun)
>  {
> -    virDomainNetDefPtr net = NULL;
> -    char *brname = NULL;
> -    char *realifname = NULL;
> -    int *tapfd = NULL;
>      char macaddr[VIR_MAC_STRING_BUFLEN];
> +    size_t i;
>  
> -    if (def->nnets != 1) {
> -        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> -                       _("domain should have one and only one net defined"));
> -        return -1;
> -    }
> -
> -    net = def->nets[0];
> -
> -    if (net) {
> +    for (i = 0; i < def->nnets; i++) {

Moving this loop to the caller of the function would reduce the extra
indentation level.

> +        char *realifname = NULL;
> +        int *tapfd = NULL;
> +        char *brname = NULL;
> +        virDomainNetDefPtr net = net = def->nets[i];;

No need to assign it twice and one semicolon would be enough. :)

>          int actualType = virDomainNetGetActualType(net);
>  
>          if (actualType == VIR_DOMAIN_NET_TYPE_BRIDGE) {

> @@ -146,7 +141,7 @@ bhyveBuildConsoleArgStr(const virDomainDef *def, virCommandPtr cmd)
>          return -1;
>      }
>  
> -    virCommandAddArgList(cmd, "-s", "31,lpc", NULL);
> +    virCommandAddArgList(cmd, "-s", "1,lpc", NULL);

Are both slot numbers arbitrary? And do we care about backwards compatibility?

>      virCommandAddArg(cmd, "-l");
>      virCommandAddArgFormat(cmd, "com%d,%s",
>                             chr->target.port + 1, chr->source.data.file.path);
> @@ -157,46 +152,43 @@ bhyveBuildConsoleArgStr(const virDomainDef *def, virCommandPtr cmd)
>  static int
>  bhyveBuildDiskArgStr(const virDomainDef *def, virCommandPtr cmd)
>  {
> -    virDomainDiskDefPtr disk;
>      const char *bus_type;
> +    size_t i;
> +
> +    for (i = 0; i < def->ndisks; i++) {
> +        virDomainDiskDefPtr disk = def->disks[i];
> +
> +        switch (disk->bus) {
> +        case VIR_DOMAIN_DISK_BUS_SATA:
> +            bus_type = "ahci-hd";
> +            break;
> +        case VIR_DOMAIN_DISK_BUS_VIRTIO:
> +            bus_type = "virtio-blk";
> +            break;
> +        default:
> +            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> +                           _("unsupported disk bus type"));
> +            return -1;
> +        }
>  
> -    if (def->ndisks != 1) {
> -        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> -                       _("domain should have one and only one disk defined"));
> -        return -1;
> -    }
> -
> -    disk = def->disks[0];
> -
> -    switch (disk->bus) {
> -    case VIR_DOMAIN_DISK_BUS_SATA:
> -        bus_type = "ahci-hd";
> -        break;
> -    case VIR_DOMAIN_DISK_BUS_VIRTIO:
> -        bus_type = "virtio-blk";
> -        break;
> -    default:
> -        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> -                       _("unsupported disk bus type"));
> -        return -1;
> -    }
> +        if (disk->device != VIR_DOMAIN_DISK_DEVICE_DISK) {
> +            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> +                           _("unsupported disk device"));
> +            return -1;
> +        }
>  
> -    if (disk->device != VIR_DOMAIN_DISK_DEVICE_DISK) {
> -        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> -                       _("unsupported disk device"));
> -        return -1;
> -    }
> +        if (virDomainDiskGetType(disk) != VIR_STORAGE_TYPE_FILE) {
> +            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> +                           _("unsupported disk type"));
> +            return -1;
> +        }
>  
> -    if (virDomainDiskGetType(disk) != VIR_STORAGE_TYPE_FILE) {
> -        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> -                       _("unsupported disk type"));
> -        return -1;
> +        virCommandAddArg(cmd, "-s");
> +        virCommandAddArgFormat(cmd, "%d:0,%s,%s",
> +                               disk->info.addr.pci.slot, bus_type,
> +                               virDomainDiskGetSource(disk));

Do SATA disks use a PCI slot too?

>      }
>  
> -    virCommandAddArg(cmd, "-s");
> -    virCommandAddArgFormat(cmd, "2:0,%s,%s", bus_type,
> -                           virDomainDiskGetSource(disk));
> -
>      return 0;
>  }
>  
> @@ -279,9 +271,9 @@ virBhyveProcessBuildLoadCmd(bhyveConnPtr driver ATTRIBUTE_UNUSED,
>      virCommandPtr cmd;
>      virDomainDiskDefPtr disk;
>  
> -    if (def->ndisks != 1) {
> +    if (def->ndisks < 1) {
>          virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> -                       _("domain should have one and only one disk defined"));
> +                       _("domain should have more than one disk defined"));

s/more than/at least/

>          return NULL;
>      }
>  
> diff --git a/src/bhyve/bhyve_device.c b/src/bhyve/bhyve_device.c
> new file mode 100644
> index 0000000..c18665f
> --- /dev/null
> +++ b/src/bhyve/bhyve_device.c
> @@ -0,0 +1,174 @@
> +/*
> + * bhyve_device.c: bhyve device management
> + *
> + * Copyright (C) 2014 Roman Bogorodskiy
> + *
> + * This library is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * This library is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with this library.  If not, see
> + * <http://www.gnu.org/licenses/>.
> + *
> + * Author: Roman Bogorodskiy
> + */
> +
> +#include <config.h>
> +
> +#include "bhyve_device.h"
> +#include "domain_addr.h"
> +#include "viralloc.h"
> +#include "virlog.h"
> +#include "virstring.h"
> +
> +#define VIR_FROM_THIS VIR_FROM_BHYVE
> +
> +VIR_LOG_INIT("bhyve.bhyve_device");
> +
> +static int
> +bhyveCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED,
> +                       virDomainDeviceDefPtr device ATTRIBUTE_UNUSED,
> +                       virDomainDeviceInfoPtr info,
> +                       void *opaque)
> +{
> +    int ret = -1;
> +    virDomainPCIAddressSetPtr addrs = opaque;
> +    virDevicePCIAddressPtr addr = &info->addr.pci;
> +
> +    if (addr->domain == 0 && addr->bus == 0) {
> +        if (addr->slot == 0) {
> +            return 0;
> +        } else if (addr->slot == 1) {
> +            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> +                           _("PCI bus 0 slot 1 is reserved for the implicit "
> +                             "LPC PCI-ISA bridge"));

It's only implied when the console is present. Does it make sense to let
someone use the address if they don't want the ISA bridge?

Maybe we should generate an explicit <controller> element for it too.

> +            return -1;
> +        }
> +    }
> +
> +    if (virDomainPCIAddressReserveSlot(addrs, addr, VIR_PCI_CONNECT_TYPE_PCI) < 0)
> +        goto cleanup;
> +
> +    ret = 0;
> + cleanup:
> +    return ret;
> +}
> +

> +bhyveAssignDevicePCISlots(virDomainDefPtr def,
> +                          virDomainPCIAddressSetPtr addrs)
> +{
> +    size_t i;
> +    virDevicePCIAddress lpc_addr;
> +
> +    /* explicitly reserve slot 1 for LPC-ISA bridge */
> +    memset(&lpc_addr, 0, sizeof(lpc_addr));
> +    lpc_addr.slot = 0x1;
> +
> +    if (virDomainPCIAddressReserveSlot(addrs, &lpc_addr, VIR_PCI_CONNECT_TYPE_PCI) < 0)
> +        goto error;
> +
> +    for (i = 0; i < def->ndisks; i++) {
> +        if (def->disks[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
> +            def->disks[i]->info.addr.pci.slot != 0)
> +            continue;
> +        if (virDomainPCIAddressReserveNextSlot(addrs,
> +                                               &def->disks[i]->info,
> +                                               VIR_PCI_CONNECT_TYPE_PCI) < 0)
> +            goto error;
> +    }
> +
> +    for (i = 0; i < def->nnets; i++) {
> +        if (def->nets[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
> +            continue;
> +        if (virDomainPCIAddressReserveNextSlot(addrs,
> +                                               &def->nets[i]->info,
> +                                               VIR_PCI_CONNECT_TYPE_PCI) < 0)
> +            goto error;
> +    }

Assigning nets before disks would match the hardcoded slots that were used by
a domain with one net and one disk before.

> +
> +    for (i = 0; i < def->ncontrollers; i++) {
> +        if (def->controllers[i]->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI) {
> +            if (def->controllers[i]->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
> +                continue;
> +            if (def->controllers[i]->model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT)
> +                continue;
> +
> +            if (virDomainPCIAddressReserveNextSlot(addrs,
> +                                                   &def->controllers[i]->info,
> +                                                   VIR_PCI_CONNECT_TYPE_PCI) < 0)
> +                goto error;
> +        }

I think unsupported controllers don't need PCI slots.

> +
> +    }
> +
> +    return 0;
> +
> + error:
> +    return -1;
> +}
> +

> diff --git a/src/bhyve/bhyve_domain.h b/src/bhyve/bhyve_domain.h
> new file mode 100644
> index 0000000..d59fe58
> --- /dev/null
> +++ b/src/bhyve/bhyve_domain.h
> @@ -0,0 +1,39 @@
> +/*
> + * bhyve_domain.h: bhyve domain private state headers
> + *
> + * Copyright (C) 2014 Roman Bogorodskiy
> + *
> + * This library is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * This library is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with this library.  If not, see
> + * <http://www.gnu.org/licenses/>.
> + *
> + * Author: Roman Bogorodskiy
> + */
> +
> +#ifndef __BHYVE_DOMAIN_H__
> +# define __BHYVE_DOMAIN_H__
> +
> +# include "domain_addr.h"
> +# include "domain_conf.h"
> +
> +typedef struct _bhyveDomainObjPrivate bhyveDomainObjPrivate;
> +typedef bhyveDomainObjPrivate *bhyveDomainObjPrivatePtr;
> +struct _bhyveDomainObjPrivate {
> +    virDomainPCIAddressSetPtr pciaddrs;
> +    int persistentAddrs;

bool would be enough.

> +};
> +
> +extern virDomainXMLPrivateDataCallbacks virBhyveDriverPrivateDataCallbacks;
> +extern virDomainDefParserConfig virBhyveDriverDomainDefParserConfig;
> +
> +#endif /* __BHYVE_DOMAIN_H__ */

Jan

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: OpenPGP digital signature
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20140513/764a3b5b/attachment-0001.sig>


More information about the libvir-list mailing list