From nobody Thu Nov 28 17:39:25 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1521099438717682.4351943353669; Thu, 15 Mar 2018 00:37:18 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 6F370C025019; Thu, 15 Mar 2018 07:37:17 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 40B78537B3; Thu, 15 Mar 2018 07:37:17 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id F330C4CAAC; Thu, 15 Mar 2018 07:37:16 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id w2EHNhCE025598 for ; Wed, 14 Mar 2018 13:23:55 -0400 Received: by smtp.corp.redhat.com (Postfix) id 2CACF5D6B2; Wed, 14 Mar 2018 17:23:43 +0000 (UTC) Received: from mx1.redhat.com (ext-mx07.extmail.prod.ext.phx2.redhat.com [10.5.110.31]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 22C305D753 for ; Wed, 14 Mar 2018 17:23:40 +0000 (UTC) Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 4A10CC0467DD for ; Wed, 14 Mar 2018 17:23:38 +0000 (UTC) Received: from pps.filterd (m0098396.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.22/8.16.0.22) with SMTP id w2EHKNAk086658 for ; Wed, 14 Mar 2018 13:23:38 -0400 Received: from e06smtp10.uk.ibm.com (e06smtp10.uk.ibm.com [195.75.94.106]) by mx0a-001b2d01.pphosted.com with ESMTP id 2gq515hc7y-1 (version=TLSv1.2 cipher=AES256-SHA256 bits=256 verify=NOT) for ; Wed, 14 Mar 2018 13:23:37 -0400 Received: from localhost by e06smtp10.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Wed, 14 Mar 2018 17:23:34 -0000 Received: from b06cxnps4076.portsmouth.uk.ibm.com (9.149.109.198) by e06smtp10.uk.ibm.com (192.168.101.140) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Wed, 14 Mar 2018 17:23:32 -0000 Received: from d06av25.portsmouth.uk.ibm.com (d06av25.portsmouth.uk.ibm.com [9.149.105.61]) by b06cxnps4076.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id w2EHNVG456295628 for ; Wed, 14 Mar 2018 17:23:31 GMT Received: from d06av25.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id E3F6E11C054 for ; Wed, 14 Mar 2018 17:16:09 +0000 (GMT) Received: from d06av25.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 386E011C04C for ; Wed, 14 Mar 2018 17:16:09 +0000 (GMT) Received: from localhost.localdomain (unknown [9.79.182.166]) by d06av25.portsmouth.uk.ibm.com (Postfix) with ESMTP for ; Wed, 14 Mar 2018 17:16:08 +0000 (GMT) From: Shivaprasad G Bhat To: libvir-list@redhat.com Date: Wed, 14 Mar 2018 22:53:29 +0530 In-Reply-To: <152104711186.10112.1077788328340024644.stgit@localhost.localdomain> References: <152104711186.10112.1077788328340024644.stgit@localhost.localdomain> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 X-TM-AS-GCONF: 00 x-cbid: 18031417-0040-0000-0000-000004207A21 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 18031417-0041-0000-0000-000026237F8C Message-Id: <152104820338.10112.16359313256631575931.stgit@localhost.localdomain> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2018-03-14_09:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 malwarescore=0 suspectscore=3 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 impostorscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1709140000 definitions=main-1803140193 X-Greylist: Sender passed SPF test, Sender IP whitelisted by DNSRBL, ACL 207 matched, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Wed, 14 Mar 2018 17:23:38 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Wed, 14 Mar 2018 17:23:38 +0000 (UTC) for IP:'148.163.156.1' DOMAIN:'mx0a-001b2d01.pphosted.com' HELO:'mx0a-001b2d01.pphosted.com' FROM:'sbhat@linux.vnet.ibm.com' RCPT:'' X-RedHat-Spam-Score: -0.701 (RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H2) 148.163.156.1 mx0a-001b2d01.pphosted.com 148.163.156.1 mx0a-001b2d01.pphosted.com X-Scanned-By: MIMEDefang 2.78 on 10.5.110.31 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-loop: libvir-list@redhat.com Subject: [libvirt] [RFC PATCH 25/28] qemu: hotplug: Implement multifunction device hotplug X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Thu, 15 Mar 2018 07:37:17 +0000 (UTC) X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" Signed-off-by: Shivaprasad G Bhat --- src/qemu/qemu_domain.c | 2=20 src/qemu/qemu_domain_address.c | 68 +++++++++++++++++ src/qemu/qemu_domain_address.h | 5 + src/qemu/qemu_driver.c | 66 ++++++++++------ src/qemu/qemu_hotplug.c | 82 ++++++++++++++++= ++++ src/qemu/qemu_hotplug.h | 4 + tests/qemuhotplugtest.c | 39 ++++++++-- .../qemuhotplug-multifunction-hostdev-pci-2.xml | 14 +++ .../qemuhotplug-multifunction-hostdev-pci.xml | 20 +++++ ...hotplug-base-live+multifunction-hostdev-pci.xml | 76 ++++++++++++++++= +++ ...eries-base-live+multifunction-hostdev-pci-2.xml | 61 +++++++++++++++ ...pseries-base-live+multifunction-hostdev-pci.xml | 69 +++++++++++++++++ 12 files changed, 475 insertions(+), 31 deletions(-) create mode 100644 tests/qemuhotplugtestdevices/qemuhotplug-multifunction-= hostdev-pci-2.xml create mode 100644 tests/qemuhotplugtestdevices/qemuhotplug-multifunction-= hostdev-pci.xml create mode 100644 tests/qemuhotplugtestdomains/qemuhotplug-base-live+mult= ifunction-hostdev-pci.xml create mode 100644 tests/qemuhotplugtestdomains/qemuhotplug-pseries-base-l= ive+multifunction-hostdev-pci-2.xml create mode 100644 tests/qemuhotplugtestdomains/qemuhotplug-pseries-base-l= ive+multifunction-hostdev-pci.xml diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index c0a0af525f..1cfaf01540 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -33,6 +33,8 @@ #include "qemu_capabilities.h" #include "qemu_migration.h" #include "qemu_security.h" +#include "qemu_hotplug.h" +#include "qemu_hostdev.h" #include "viralloc.h" #include "virlog.h" #include "virerror.h" diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c index 7bee4fb937..ee743321dd 100644 --- a/src/qemu/qemu_domain_address.c +++ b/src/qemu/qemu_domain_address.c @@ -25,6 +25,7 @@ =20 #include "qemu_domain_address.h" #include "qemu_domain.h" +#include "domain_conf.h" #include "viralloc.h" #include "virhostdev.h" #include "virerror.h" @@ -3206,6 +3207,73 @@ qemuDomainEnsurePCIAddress(virDomainObjPtr obj, info->pciConnectFlags); } =20 + +int +qemuDomainPCIMultifunctionHostdevEnsurePCIAddresses(virDomainObjPtr vm, + virDomainDeviceDefList= Ptr devlist, + virQEMUDriverPtr drive= r) +{ + int ret =3D -1, aggrslotidx =3D 0; + virBitmapPtr slotmap =3D NULL; + size_t i; + qemuDomainObjPrivatePtr priv =3D vm->privateData; + virDomainPCIMultifunctionAddressInfoPtr devinfos =3D NULL; + + if (devlist->count > VIR_PCI_MAX_FUNCTIONS) { + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", + _("More devices per slot found")); + return -1; + } + + for (i =3D 0; i < devlist->count; i++) + qemuDomainFillDevicePCIConnectFlags(vm->def, devlist->devs[i], pri= v->qemuCaps, driver); + + if (VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs + devlist->cou= nt) < 0) + return -1; + + /* Temporarily add the devices to the domain def to get the + * next aggregateIdx */ + for (i =3D 0; i < devlist->count; i++) + vm->def->hostdevs[vm->def->nhostdevs++] =3D devlist->devs[i]->data= .hostdev; + + for (i =3D 0; i < devlist->count; i++) { + if (qemuDomainIsPSeries(vm->def)) { + /* Isolation groups are only relevant for pSeries guests */ + if (qemuDomainFillDeviceIsolationGroup(vm->def, devlist->devs[= i]) < 0) + return -1; + } + qemuDomainSetDeviceSlotAggregateIdx(vm->def, devlist->devs[i]); + aggrslotidx =3D aggrslotidx ? aggrslotidx : devlist->devs[i]->data= .hostdev->info->aggregateSlotIdx; + if (aggrslotidx !=3D devlist->devs[i]->data.hostdev->info->aggrega= teSlotIdx) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Devices belong to different PCI slots")); + return -1; + } + } + + for (i =3D 0; i < devlist->count; i++) + vm->def->hostdevs[--(vm->def->nhostdevs)] =3D NULL; + + slotmap =3D virDomainDefHostdevGetPCIOnlineFunctionMap(vm->def, aggrsl= otidx); + if (!virBitmapIsAllClear(slotmap)) { + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", + _("Device already assigned to guest")); + return -1; + } + + if (VIR_ALLOC(devinfos) < 0) + return -1; + + for (i =3D 0; i < devlist->count; i++) { + virPCIDeviceAddress addr =3D devlist->devs[i]->data.hostdev->sour= ce.subsys.u.pci.addr; + devinfos->infos[addr.function] =3D devlist->devs[i]->data.hostde= v->info; + } + + ret =3D virDomainPCIAddressEnsureMultifunctionAddress(priv->pciaddrs, = devinfos); + VIR_FREE(devinfos); + return ret; +} + void qemuDomainReleaseDeviceAddress(virDomainObjPtr vm, virDomainDeviceInfoPtr info, diff --git a/src/qemu/qemu_domain_address.h b/src/qemu/qemu_domain_address.h index e1cc467714..43d1de889e 100644 --- a/src/qemu/qemu_domain_address.h +++ b/src/qemu/qemu_domain_address.h @@ -51,6 +51,11 @@ int qemuDomainEnsurePCIAddress(virDomainObjPtr obj, virQEMUDriverPtr driver) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3); =20 +int +qemuDomainPCIMultifunctionHostdevEnsurePCIAddresses(virDomainObjPtr obj, + virDomainDeviceDefList= Ptr devlist, + virQEMUDriverPtr drive= r); + int qemuDomainFillDeviceIsolationGroup(virDomainDefPtr def, virDomainDeviceDefPtr dev) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index d2e10082ea..fb14475d8c 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -7744,15 +7744,26 @@ qemuDomainAttachDeviceLiveInternal(virDomainObjPtr = vm, =20 static int qemuDomainAttachDeviceLive(virDomainObjPtr vm, - virDomainDeviceDefPtr dev, + virDomainDeviceDefListPtr devlist, virQEMUDriverPtr driver) { int ret =3D -1; + size_t i; =20 - if (virDomainDefCompatibleDevice(vm->def, dev, NULL) < 0) - return -1; + for (i =3D 0; i < devlist->count; i++) + if (virDomainDefCompatibleDevice(vm->def, devlist->devs[i], NULL) = < 0) + return ret; + + if (devlist->count > 1) { + ret =3D qemuDomainAttachMultifunctionDevice(vm, devlist, driver); + if (ret =3D=3D 0) { + for (i =3D 0; i < devlist->count; i++) + devlist->devs[i]->data.hostdev =3D NULL; + } + } else if (devlist->count =3D=3D 1) { + ret =3D qemuDomainAttachDeviceLiveInternal(vm, devlist->devs[0], d= river); + } =20 - ret =3D qemuDomainAttachDeviceLiveInternal(vm, dev, driver); if (ret =3D=3D 0) ret =3D qemuDomainUpdateDeviceList(driver, vm, QEMU_ASYNC_JOB_NONE= ); =20 @@ -8178,16 +8189,22 @@ qemuDomainAttachDeviceConfigInternal(virDomainDefPt= r vmdef, =20 static int qemuDomainAttachDeviceConfig(virDomainDefPtr vmdef, - virDomainDeviceDefPtr dev, + virDomainDeviceDefListPtr devlist, virCapsPtr caps, unsigned int parse_flags, virDomainXMLOptionPtr xmlopt) { - if (virDomainDefCompatibleDevice(vmdef, dev, NULL) < 0) - return -1; + size_t i; =20 - if (qemuDomainAttachDeviceConfigInternal(vmdef, dev)) - return -1; + for (i =3D 0; i < devlist->count; i++) { + if (virDomainDefCompatibleDevice(vmdef, devlist->devs[i], NULL) < 0) + return -1; + } + + for (i =3D 0; i < devlist->count; i++) { + if (qemuDomainAttachDeviceConfigInternal(vmdef, devlist->devs[i])) + return -1; + } =20 if (virDomainDefPostParse(vmdef, caps, parse_flags, xmlopt, NULL) < 0) return -1; @@ -8493,9 +8510,11 @@ qemuDomainAttachDeviceLiveAndConfig(virDomainObjPtr = vm, const char *xml, unsigned int flags) { + size_t i; virDomainDefPtr vmdef =3D NULL; virQEMUDriverConfigPtr cfg =3D NULL; - virDomainDeviceDefPtr dev =3D NULL, dev_copy =3D NULL; + virDomainDeviceDefListPtr devlist =3D NULL, devcopylist =3D NULL; + virDomainDeviceDefListData data =3D {.def =3D vm->def, .xmlopt =3D dri= ver->xmlopt, .caps =3D NULL}; int ret =3D -1; virCapsPtr caps =3D NULL; unsigned int parse_flags =3D VIR_DOMAIN_DEF_PARSE_INACTIVE | @@ -8508,15 +8527,16 @@ qemuDomainAttachDeviceLiveAndConfig(virDomainObjPtr= vm, =20 if (!(caps =3D virQEMUDriverGetCapabilities(driver, false))) goto cleanup; + data.caps =3D caps; =20 - dev =3D dev_copy =3D virDomainDeviceDefParse(xml, vm->def, - caps, driver->xmlopt, - parse_flags); - if (dev =3D=3D NULL) + devlist =3D qemuDomainDeviceParseXMLMany(xml, &data, parse_flags); + if (!devlist) goto cleanup; + devcopylist =3D devlist; =20 - if (virDomainDeviceValidateAliasForHotplug(vm, dev, flags) < 0) - goto cleanup; + for (i =3D 0; i < devlist->count; i++) + if (virDomainDeviceValidateAliasForHotplug(vm, devlist->devs[i], f= lags) < 0) + goto cleanup; =20 if (flags & VIR_DOMAIN_AFFECT_CONFIG && flags & VIR_DOMAIN_AFFECT_LIVE) { @@ -8524,8 +8544,8 @@ qemuDomainAttachDeviceLiveAndConfig(virDomainObjPtr v= m, * create a deep copy of device as adding * to CONFIG takes one instance. */ - dev_copy =3D virDomainDeviceDefCopy(dev, vm->def, caps, driver->xm= lopt); - if (!dev_copy) + devcopylist =3D virDomainDeviceDefListCopy(devlist, &data); + if (!devcopylist) goto cleanup; } =20 @@ -8535,14 +8555,14 @@ qemuDomainAttachDeviceLiveAndConfig(virDomainObjPtr= vm, if (!vmdef) goto cleanup; =20 - if ((ret =3D qemuDomainAttachDeviceConfig(vmdef, dev, caps, + if ((ret =3D qemuDomainAttachDeviceConfig(vmdef, devlist, caps, parse_flags, driver->xmlopt)) < 0) goto cleanup; } =20 if (flags & VIR_DOMAIN_AFFECT_LIVE) { - if ((ret =3D qemuDomainAttachDeviceLive(vm, dev_copy, driver)) < 0) + if ((ret =3D qemuDomainAttachDeviceLive(vm, devcopylist, driver)) = < 0) goto cleanup; /* * update domain status forcibly because the domain status may be @@ -8566,9 +8586,9 @@ qemuDomainAttachDeviceLiveAndConfig(virDomainObjPtr v= m, =20 cleanup: virDomainDefFree(vmdef); - if (dev !=3D dev_copy) - virDomainDeviceDefFree(dev_copy); - virDomainDeviceDefFree(dev); + if (devlist !=3D devcopylist) + virDomainDeviceDefListFree(devcopylist); + virDomainDeviceDefListFree(devlist); virObjectUnref(cfg); virObjectUnref(caps); =20 diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 7dffaf9502..a339e92bfa 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -1402,6 +1402,88 @@ qemuDomainAttachHostPCIDevice(virQEMUDriverPtr drive= r, } =20 =20 +static int +qemuiHostdevPCIMultifunctionDevicesListSort(const void *p1, + const void *p2) +{ + virDomainDeviceDefPtr a =3D *(virDomainDeviceDefPtr *) p1; + virDomainDeviceDefPtr b =3D *(virDomainDeviceDefPtr *) p2; + virPCIDeviceAddressPtr addr1 =3D &a->data.hostdev->source.subsys.u.pci= .addr; + virPCIDeviceAddressPtr addr2 =3D &b->data.hostdev->source.subsys.u.pci= .addr; + + return addr1->function - addr2->function; +} + + +int +qemuDomainAttachMultifunctionDevice(virDomainObjPtr vm, + virDomainDeviceDefListPtr devlist, + virQEMUDriverPtr driver) +{ + size_t i, d, h =3D devlist->count; + int ret =3D -1; + char *alias; + virObjectEventPtr event; + virQEMUCapsPtr qemuCaps =3D NULL; + virDomainHostdevDefPtr hostdev =3D NULL; + + if (!(qemuCaps =3D virQEMUCapsCacheLookup(driver->qemuCapsCache, + vm->def->emulator))) + return -1; + + qsort(devlist->devs, devlist->count, sizeof(*devlist->devs), qemuiHost= devPCIMultifunctionDevicesListSort); + + if (qemuDomainPCIMultifunctionHostdevEnsurePCIAddresses(vm, devlist, d= river) < 0) + return -1; + + for (d =3D 0; d < devlist->count; d++) + if (qemuDomainAttachPCIHostDevicePrepare(driver, vm->def, devlist-= >devs[d]->data.hostdev, qemuCaps) < 0) + goto cleanup; + + /* Hotplug all functions, and Primary at last */ + for (h =3D devlist->count; h > 0; h--) { + /* The functions need not be contiguous, as a card may be sold with + * minimal functionality and then install the additional functions= on + * purchase into any of the daughter-card connectors. + */ + hostdev =3D devlist->devs[h-1]->data.hostdev; + ret =3D qemuDomainAttachHostPCIDevice(driver, vm, hostdev); + if (ret) + goto release; + + alias =3D hostdev->info->alias; + hostdev =3D NULL; + + event =3D virDomainEventDeviceAddedNewFromObj(vm, alias); + qemuDomainEventQueue(driver, event); + } + + release: + /* Release addresses for the device which are not hotplugged. + */ + for (i =3D 0; i < h; i++) + qemuDomainReleaseDeviceAddress(vm, devlist->devs[i]->data.hostdev-= >info, NULL); + + cleanup: + /* If none are actually hotplugged and just detached from the + * host driver reattach the devices to host driver. + * + * If one of the hotplug failed, those which are already hotplugged ca= nnot + * be unplugged as they are released by qemu only on guest reboot even + * if we issue device_del on them. + * So, dont attempt to reattach any of them. + * NB: Let them be in the guest as they are not used anyway without + * function-zero? + */ + if (d > 0 && h =3D=3D devlist->count) { + for (i =3D 0; i < d; i++) + qemuHostdevReAttachPCIDevices(driver, vm->def->name, &devlist-= >devs[i]->data.hostdev, 1); + } + + return ret; +} + + void qemuDomainDelTLSObjects(virQEMUDriverPtr driver, virDomainObjPtr vm, diff --git a/src/qemu/qemu_hotplug.h b/src/qemu/qemu_hotplug.h index db0e1df79a..7a6e2dfb60 100644 --- a/src/qemu/qemu_hotplug.h +++ b/src/qemu/qemu_hotplug.h @@ -158,6 +158,10 @@ int qemuDomainAttachPCIHostDevicePrepare(virQEMUDriver= Ptr driver, virDomainDefPtr def, virDomainHostdevDefPtr dev, virQEMUCapsPtr qemuCaps); +int +qemuDomainAttachMultifunctionDevice(virDomainObjPtr vm, + virDomainDeviceDefListPtr devlist, + virQEMUDriverPtr driver); =20 int qemuDomainChrInsert(virDomainDefPtr vmdef, diff --git a/tests/qemuhotplugtest.c b/tests/qemuhotplugtest.c index b5dca5e5c9..39f122e083 100644 --- a/tests/qemuhotplugtest.c +++ b/tests/qemuhotplugtest.c @@ -82,6 +82,8 @@ qemuHotplugCreateObjects(virDomainXMLOptionPtr xmlopt, virQEMUCapsSet(priv->qemuCaps, QEMU_CAPS_DEVICE_VFIO_PCI); virQEMUCapsSet(priv->qemuCaps, QEMU_CAPS_DEVICE_SPAPR_PCI_HOST_BRIDGE); virQEMUCapsSet(priv->qemuCaps, QEMU_CAPS_VIRTIO_PCI_DISABLE_LEGACY); + virQEMUCapsSet(priv->qemuCaps, QEMU_CAPS_HOST_PCI_MULTIDOMAIN); + virQEMUCapsSet(priv->qemuCaps, QEMU_CAPS_PCI_MULTIFUNCTION); if (event) virQEMUCapsSet(priv->qemuCaps, QEMU_CAPS_DEVICE_DEL_EVENT); =20 @@ -115,9 +117,14 @@ qemuHotplugCreateObjects(virDomainXMLOptionPtr xmlopt, =20 static int testQemuHotplugAttach(virDomainObjPtr vm, - virDomainDeviceDefPtr dev) + virDomainDeviceDefListPtr devlist) { int ret =3D -1; + virDomainDeviceDefPtr dev; + + if (devlist->count > 1) + return qemuDomainAttachMultifunctionDevice(vm, devlist, &driver); + dev =3D devlist->devs[0]; =20 switch (dev->type) { case VIR_DOMAIN_DEVICE_DISK: @@ -249,7 +256,9 @@ testQemuHotplug(const void *data) bool keep =3D test->keep; unsigned int device_parse_flags =3D 0; virDomainObjPtr vm =3D NULL; - virDomainDeviceDefPtr dev =3D NULL; + virDomainDeviceDefPtr dev =3D NULL; /*temperory */ + virDomainDeviceDefListPtr devlist =3D NULL; + virDomainDeviceDefListData listdata; virCapsPtr caps =3D NULL; qemuMonitorTestPtr test_mon =3D NULL; qemuDomainObjPrivatePtr priv =3D NULL; @@ -286,10 +295,13 @@ testQemuHotplug(const void *data) if (test->action =3D=3D ATTACH) device_parse_flags =3D VIR_DOMAIN_DEF_PARSE_INACTIVE; =20 - if (!(dev =3D virDomainDeviceDefParse(device_xml, vm->def, - caps, driver.xmlopt, - device_parse_flags))) + listdata.def =3D vm->def; + listdata.xmlopt =3D driver.xmlopt; + listdata.caps =3D caps; + devlist =3D qemuDomainDeviceParseXMLMany(device_xml, &listdata, device= _parse_flags); + if (!devlist) goto cleanup; + dev =3D devlist->devs[0]; /* temporary */ =20 /* Now is the best time to feed the spoofed monitor with predefined * replies. */ @@ -319,11 +331,11 @@ testQemuHotplug(const void *data) =20 switch (test->action) { case ATTACH: - ret =3D testQemuHotplugAttach(vm, dev); + ret =3D testQemuHotplugAttach(vm, devlist); if (ret =3D=3D 0) { /* vm->def stolen dev->data.* so we just need to free the dev * envelope */ - VIR_FREE(dev); + virDomainDeviceDefListFreeShallow(devlist); } if (ret =3D=3D 0 || fail) ret =3D testQemuHotplugCheckResult(vm, result_xml, @@ -357,7 +369,7 @@ testQemuHotplug(const void *data) virObjectUnref(vm); test->vm =3D NULL; } - virDomainDeviceDefFree(dev); + virDomainDeviceDefListFree(devlist); virObjectUnref(caps); qemuMonitorTestFree(test_mon); return ((ret < 0 && fail) || (!ret && !fail)) ? 0 : -1; @@ -856,6 +868,17 @@ mymain(void) "device_add", QMP_OK); DO_TEST_DETACH("pseries-base-live", "hostdev-pci", false, false, "device_del", QMP_DEVICE_DELETED("hostdev0") QMP_OK); + DO_TEST_ATTACH("base-live", "multifunction-hostdev-pci", false, false, + "device_add", QMP_OK, + "device_add", QMP_OK, + "device_add", QMP_OK); + + qemuTestSetHostArch(driver.caps, VIR_ARCH_PPC64); + DO_TEST_ATTACH("pseries-base-live", "multifunction-hostdev-pci-2", fal= se, false, + "device_add", QMP_OK, + "device_add", QMP_OK, + "device_add", QMP_OK); + qemuTestSetHostArch(driver.caps, VIR_ARCH_X86_64); =20 DO_TEST_ATTACH("base-live", "watchdog", false, true, "watchdog-set-action", QMP_OK, diff --git a/tests/qemuhotplugtestdevices/qemuhotplug-multifunction-hostdev= -pci-2.xml b/tests/qemuhotplugtestdevices/qemuhotplug-multifunction-hostdev= -pci-2.xml new file mode 100644 index 0000000000..02e2236e5d --- /dev/null +++ b/tests/qemuhotplugtestdevices/qemuhotplug-multifunction-hostdev-pci-2.= xml @@ -0,0 +1,14 @@ + + + + +
+ + + + + +
+ + + diff --git a/tests/qemuhotplugtestdevices/qemuhotplug-multifunction-hostdev= -pci.xml b/tests/qemuhotplugtestdevices/qemuhotplug-multifunction-hostdev-p= ci.xml new file mode 100644 index 0000000000..54bb627e30 --- /dev/null +++ b/tests/qemuhotplugtestdevices/qemuhotplug-multifunction-hostdev-pci.xml @@ -0,0 +1,20 @@ + + + + +
+ + + + + +
+ + + + + +
+ + + diff --git a/tests/qemuhotplugtestdomains/qemuhotplug-base-live+multifuncti= on-hostdev-pci.xml b/tests/qemuhotplugtestdomains/qemuhotplug-base-live+mul= tifunction-hostdev-pci.xml new file mode 100644 index 0000000000..f53fe7601b --- /dev/null +++ b/tests/qemuhotplugtestdomains/qemuhotplug-base-live+multifunction-host= dev-pci.xml @@ -0,0 +1,76 @@ + + hotplug + d091ea82-29e6-2e34-3005-f02617b36e87 + 4194304 + 4194304 + 4 + + hvm + + + + + + + + + destroy + restart + restart + + /usr/bin/qemu-system-x86_64 + + +
+ + + +
+ + + +
+ + + + + + +
+ + + + + + + + + + +
+ + +
+ + + + +
+ + +
+ + + + +
+ + +
+ + + + + + + diff --git a/tests/qemuhotplugtestdomains/qemuhotplug-pseries-base-live+mul= tifunction-hostdev-pci-2.xml b/tests/qemuhotplugtestdomains/qemuhotplug-pse= ries-base-live+multifunction-hostdev-pci-2.xml new file mode 100644 index 0000000000..85dc48fdb8 --- /dev/null +++ b/tests/qemuhotplugtestdomains/qemuhotplug-pseries-base-live+multifunct= ion-hostdev-pci-2.xml @@ -0,0 +1,61 @@ + + hotplug + d091ea82-29e6-2e34-3005-f02617b36e87 + 4194304 + 4194304 + 4 + + hvm + + + + destroy + restart + destroy + + /usr/bin/qemu-system-ppc64 + + + + + + + + + + + + +
+ + + +
+ + + +
+ + + + +
+ + +
+ + + + +
+ + +
+ + + + + + + + diff --git a/tests/qemuhotplugtestdomains/qemuhotplug-pseries-base-live+mul= tifunction-hostdev-pci.xml b/tests/qemuhotplugtestdomains/qemuhotplug-pseri= es-base-live+multifunction-hostdev-pci.xml new file mode 100644 index 0000000000..9338d42e2e --- /dev/null +++ b/tests/qemuhotplugtestdomains/qemuhotplug-pseries-base-live+multifunct= ion-hostdev-pci.xml @@ -0,0 +1,69 @@ + + hotplug + d091ea82-29e6-2e34-3005-f02617b36e87 + 4194304 + 4194304 + 4 + + hvm + + + + destroy + restart + destroy + + /usr/bin/qemu-system-ppc64 + + + + + + + + + + + + +
+ + + +
+ + + +
+ + + + +
+ + +
+ + + + +
+ + +
+ + + + +
+ + +
+ + + + + + + + -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list