From nobody Sun Nov 24 17:08:31 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1722508616; cv=none; d=zohomail.com; s=zohoarc; b=VTrOwGiopFwTvWx0Ud8as4kGZiSMt00ytCknGur6PDXULIo07jn6rKfVtmLO+yXZpPE0lM1A7BOxx34Rw2DrWh77ymbKi2WofpBUQWcnALQp5b/9OndPMJcuEj0TKELeEyZ7q1sFgNVUQuPU0txktwaPIdgbJOcF37A90+yusrE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1722508616; h=Content-Type:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=ugSEKs2cZK1SSCVwSLS6qJ+0laBmwuBRQ+6Ul2jMCzQ=; b=fyeeimZmHeO4tQTS76hOj4j2d5+Qhp7nUg/zE5UO455bvt2zp0bPgOXWFfWuhwvRD9HEItSpEMe710s5Xj2jNz9iBYQgx3HU3CH19xK97bLvYp84ToQFxVusWvTr1nezLzuAsKlkbD6SFHmB1BLigr4ZHTqUf6Brl7Sv7trVurs= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1722508616855714.2655997726945; Thu, 1 Aug 2024 03:36:56 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sZTAL-00032M-54; Thu, 01 Aug 2024 06:36:13 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sZTAJ-00031K-A2 for qemu-devel@nongnu.org; Thu, 01 Aug 2024 06:36:11 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sZTAG-0001Zd-T8 for qemu-devel@nongnu.org; Thu, 01 Aug 2024 06:36:11 -0400 Received: from mail-lf1-f71.google.com (mail-lf1-f71.google.com [209.85.167.71]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-255-hPb5S-zyMtisu7lJ6xsk1A-1; Thu, 01 Aug 2024 06:36:06 -0400 Received: by mail-lf1-f71.google.com with SMTP id 2adb3069b0e04-52f02f1773fso7684133e87.3 for ; Thu, 01 Aug 2024 03:36:06 -0700 (PDT) Received: from redhat.com ([2.55.44.248]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-a7acab2310fsm874820566b.42.2024.08.01.03.35.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 01 Aug 2024 03:36:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1722508568; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=ugSEKs2cZK1SSCVwSLS6qJ+0laBmwuBRQ+6Ul2jMCzQ=; b=E1hgMvhVMRGOllT7b3Ef5VzMPsqqxtiYPgh+1u2r/wMVb20Kj+atXT3O4TA9kbNXYF0nwl slLcw/6twmGbdCGVVI+giQKdMQ1qOIy3aZiDh+5HXmagL2nSQob1z3ci1jGaVVBFACP6JW D+Dm+OAo1eEyfaJo2/KZ0hrx0mlYp0w= X-MC-Unique: hPb5S-zyMtisu7lJ6xsk1A-1 X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1722508564; x=1723113364; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=ugSEKs2cZK1SSCVwSLS6qJ+0laBmwuBRQ+6Ul2jMCzQ=; b=b//EZ/nxGb1XkOVYzRNINIHVrB3CTNnQ/Sk2RLZG8VLdAtdODfQYulCvpdM2j9OQ0m xKoWV1y/Zz4BK2Igb+kKRzMGTyzemRg35tzfbgsOGTAS7YnkmlDIxtSXscHUHclksW8Y KnUijsAMQfjZG3MYf1hexTewZK/KcUM+qkxXvuf/W4j9nYA7444+jU6tFV7fU97oJTjC X3MHEn4ddF6HTJ/rIGEoFF0xbLSj/4+WTOZiln4GF6Nu0MPOywaz4hGXV1/fgD8zCcYf TxSg7vBwAttJHnBnC21sitYy4CQwoh6N7gnXZyO3Xp0MC2h56DAg7arp/3MRL4V13jlN jiTA== X-Gm-Message-State: AOJu0YzGTcCEg5w/nIR1WJ8cgo8JUlnPnpF7DricbLrBK8fbz8XJ4cx/ NkebssllUv9jWhHqbqyCJmFGU+ghc53Y+DGPwclIJ8pC41TsQwd6oUzH4DLi6sXkgCz5vlvQfQy YElBbjk3idgOsTEmAcX5FLaea1eecO0+kzT+f4tMgVNL++8Db9D/NnE6OVpxAOSxydqnS7vNe5I Wt/crV+vq7H+9Em7rSq2vtUU3F8Tnasw== X-Received: by 2002:a05:6512:250c:b0:52e:9be7:91aa with SMTP id 2adb3069b0e04-530b619a948mr1469839e87.10.1722508564232; Thu, 01 Aug 2024 03:36:04 -0700 (PDT) X-Google-Smtp-Source: AGHT+IEr8eH5cOvva/QTn6roOFD6lTShcXME0/GcpKx97I1M7UUZmzOzgludeyL6aJmdRCLw6B+OaQ== X-Received: by 2002:a05:6512:250c:b0:52e:9be7:91aa with SMTP id 2adb3069b0e04-530b619a948mr1469773e87.10.1722508563280; Thu, 01 Aug 2024 03:36:03 -0700 (PDT) Date: Thu, 1 Aug 2024 06:35:58 -0400 From: "Michael S. Tsirkin" To: qemu-devel@nongnu.org Cc: Peter Maydell , Marcel Apfelbaum Subject: [PULL 05/19] Revert "pcie_sriov: Allow user to create SR-IOV device" Message-ID: References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: X-Mailer: git-send-email 2.27.0.106.g8ac3dc51b1 X-Mutt-Fcc: =sent Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=mst@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -21 X-Spam_score: -2.2 X-Spam_bar: -- X-Spam_report: (-2.2 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.126, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1722508617417116600 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" This reverts commit 122173a5830f7757f8a94a3b1559582f312e140b. Signed-off-by: Michael S. Tsirkin --- include/hw/pci/pci_device.h | 6 +- include/hw/pci/pcie_sriov.h | 18 --- hw/pci/pci.c | 62 +++----- hw/pci/pcie_sriov.c | 290 ++++++++---------------------------- 4 files changed, 83 insertions(+), 293 deletions(-) diff --git a/include/hw/pci/pci_device.h b/include/hw/pci/pci_device.h index e7e41cb939..1ff3ce94e2 100644 --- a/include/hw/pci/pci_device.h +++ b/include/hw/pci/pci_device.h @@ -38,8 +38,6 @@ struct PCIDeviceClass { uint16_t subsystem_id; /* only for header type =3D 0 */ =20 const char *romfile; /* rom bar */ - - bool sriov_vf_user_creatable; }; =20 enum PCIReqIDType { @@ -169,8 +167,6 @@ struct PCIDevice { /* ID of standby device in net_failover pair */ char *failover_pair_id; uint32_t acpi_index; - - char *sriov_pf; }; =20 static inline int pci_intx(PCIDevice *pci_dev) @@ -203,7 +199,7 @@ static inline int pci_is_express_downstream_port(const = PCIDevice *d) =20 static inline int pci_is_vf(const PCIDevice *d) { - return d->sriov_pf || d->exp.sriov_vf.pf !=3D NULL; + return d->exp.sriov_vf.pf !=3D NULL; } =20 static inline uint32_t pci_config_size(const PCIDevice *d) diff --git a/include/hw/pci/pcie_sriov.h b/include/hw/pci/pcie_sriov.h index f75b8f22ee..c5d2d318d3 100644 --- a/include/hw/pci/pcie_sriov.h +++ b/include/hw/pci/pcie_sriov.h @@ -18,7 +18,6 @@ typedef struct PCIESriovPF { uint8_t vf_bar_type[PCI_NUM_REGIONS]; /* Store type for each VF bar = */ PCIDevice **vf; /* Pointer to an array of num_vfs VF devices */ - bool vf_user_created; /* If VFs are created by user */ } PCIESriovPF; =20 typedef struct PCIESriovVF { @@ -41,23 +40,6 @@ void pcie_sriov_pf_init_vf_bar(PCIDevice *dev, int regio= n_num, void pcie_sriov_vf_register_bar(PCIDevice *dev, int region_num, MemoryRegion *memory); =20 -/** - * pcie_sriov_pf_init_from_user_created_vfs() - Initialize PF with user-cr= eated - * VFs. - * @dev: A PCIe device being realized. - * @offset: The offset of the SR-IOV capability. - * @errp: pointer to Error*, to store an error if it happens. - * - * Return: The size of added capability. 0 if the user did not create VFs. - * -1 if failed. - */ -int16_t pcie_sriov_pf_init_from_user_created_vfs(PCIDevice *dev, - uint16_t offset, - Error **errp); - -bool pcie_sriov_register_device(PCIDevice *dev, Error **errp); -void pcie_sriov_unregister_device(PCIDevice *dev); - /* * Default (minimal) page size support values * as required by the SR/IOV standard: diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 8ad5d7e2d8..cf2794879d 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -85,7 +85,6 @@ static Property pci_props[] =3D { QEMU_PCIE_ERR_UNC_MASK_BITNR, true), DEFINE_PROP_BIT("x-pcie-ari-nextfn-1", PCIDevice, cap_present, QEMU_PCIE_ARI_NEXTFN_1_BITNR, false), - DEFINE_PROP_STRING("sriov-pf", PCIDevice, sriov_pf), DEFINE_PROP_END_OF_LIST() }; =20 @@ -960,8 +959,13 @@ static void pci_init_multifunction(PCIBus *bus, PCIDev= ice *dev, Error **errp) dev->config[PCI_HEADER_TYPE] |=3D PCI_HEADER_TYPE_MULTI_FUNCTION; } =20 - /* SR/IOV is not handled here. */ - if (pci_is_vf(dev)) { + /* + * With SR/IOV and ARI, a device at function 0 need not be a multifunc= tion + * device, as it may just be a VF that ended up with function 0 in + * the legacy PCI interpretation. Avoid failing in such cases: + */ + if (pci_is_vf(dev) && + dev->exp.sriov_vf.pf->cap_present & QEMU_PCI_CAP_MULTIFUNCTION) { return; } =20 @@ -994,8 +998,7 @@ static void pci_init_multifunction(PCIBus *bus, PCIDevi= ce *dev, Error **errp) } /* function 0 indicates single function, so function > 0 must be NULL = */ for (func =3D 1; func < PCI_FUNC_MAX; ++func) { - PCIDevice *device =3D bus->devices[PCI_DEVFN(slot, func)]; - if (device && !pci_is_vf(device)) { + if (bus->devices[PCI_DEVFN(slot, func)]) { error_setg(errp, "PCI: %x.0 indicates single function, " "but %x.%x is already populated.", slot, slot, func); @@ -1280,7 +1283,6 @@ static void pci_qdev_unrealize(DeviceState *dev) =20 pci_unregister_io_regions(pci_dev); pci_del_option_rom(pci_dev); - pcie_sriov_unregister_device(pci_dev); =20 if (pc->exit) { pc->exit(pci_dev); @@ -1312,6 +1314,7 @@ void pci_register_bar(PCIDevice *pci_dev, int region_= num, pcibus_t size =3D memory_region_size(memory); uint8_t hdr_type; =20 + assert(!pci_is_vf(pci_dev)); /* VFs must use pcie_sriov_vf_register_ba= r */ assert(region_num >=3D 0); assert(region_num < PCI_NUM_REGIONS); assert(is_power_of_2(size)); @@ -1322,6 +1325,7 @@ void pci_register_bar(PCIDevice *pci_dev, int region_= num, assert(hdr_type !=3D PCI_HEADER_TYPE_BRIDGE || region_num < 2); =20 r =3D &pci_dev->io_regions[region_num]; + r->addr =3D PCI_BAR_UNMAPPED; r->size =3D size; r->type =3D type; r->memory =3D memory; @@ -1329,35 +1333,22 @@ void pci_register_bar(PCIDevice *pci_dev, int regio= n_num, ? pci_get_bus(pci_dev)->address_space_io : pci_get_bus(pci_dev)->address_space_mem; =20 - if (pci_is_vf(pci_dev)) { - PCIDevice *pf =3D pci_dev->exp.sriov_vf.pf; - assert(!pf || type =3D=3D pf->exp.sriov_pf.vf_bar_type[region_num]= ); + wmask =3D ~(size - 1); + if (region_num =3D=3D PCI_ROM_SLOT) { + /* ROM enable bit is writable */ + wmask |=3D PCI_ROM_ADDRESS_ENABLE; + } =20 - r->addr =3D pci_bar_address(pci_dev, region_num, r->type, r->size); - if (r->addr !=3D PCI_BAR_UNMAPPED) { - memory_region_add_subregion_overlap(r->address_space, - r->addr, r->memory, 1); - } + addr =3D pci_bar(pci_dev, region_num); + pci_set_long(pci_dev->config + addr, type); + + if (!(r->type & PCI_BASE_ADDRESS_SPACE_IO) && + r->type & PCI_BASE_ADDRESS_MEM_TYPE_64) { + pci_set_quad(pci_dev->wmask + addr, wmask); + pci_set_quad(pci_dev->cmask + addr, ~0ULL); } else { - r->addr =3D PCI_BAR_UNMAPPED; - - wmask =3D ~(size - 1); - if (region_num =3D=3D PCI_ROM_SLOT) { - /* ROM enable bit is writable */ - wmask |=3D PCI_ROM_ADDRESS_ENABLE; - } - - addr =3D pci_bar(pci_dev, region_num); - pci_set_long(pci_dev->config + addr, type); - - if (!(r->type & PCI_BASE_ADDRESS_SPACE_IO) && - r->type & PCI_BASE_ADDRESS_MEM_TYPE_64) { - pci_set_quad(pci_dev->wmask + addr, wmask); - pci_set_quad(pci_dev->cmask + addr, ~0ULL); - } else { - pci_set_long(pci_dev->wmask + addr, wmask & 0xffffffff); - pci_set_long(pci_dev->cmask + addr, 0xffffffff); - } + pci_set_long(pci_dev->wmask + addr, wmask & 0xffffffff); + pci_set_long(pci_dev->cmask + addr, 0xffffffff); } } =20 @@ -2118,11 +2109,6 @@ static void pci_qdev_realize(DeviceState *qdev, Erro= r **errp) } } =20 - if (!pcie_sriov_register_device(pci_dev, errp)) { - pci_qdev_unrealize(DEVICE(pci_dev)); - return; - } - /* * A PCIe Downstream Port that do not have ARI Forwarding enabled must * associate only Device 0 with the device attached to the bus diff --git a/hw/pci/pcie_sriov.c b/hw/pci/pcie_sriov.c index 0fc9f810b9..15a4aac1f4 100644 --- a/hw/pci/pcie_sriov.c +++ b/hw/pci/pcie_sriov.c @@ -20,8 +20,6 @@ #include "qapi/error.h" #include "trace.h" =20 -static GHashTable *pfs; - static void unparent_vfs(PCIDevice *dev, uint16_t total_vfs) { for (uint16_t i =3D 0; i < total_vfs; i++) { @@ -33,49 +31,14 @@ static void unparent_vfs(PCIDevice *dev, uint16_t total= _vfs) dev->exp.sriov_pf.vf =3D NULL; } =20 -static void clear_ctrl_vfe(PCIDevice *dev) -{ - uint8_t *ctrl =3D dev->config + dev->exp.sriov_cap + PCI_SRIOV_CTRL; - pci_set_word(ctrl, pci_get_word(ctrl) & ~PCI_SRIOV_CTRL_VFE); -} - -static void register_vfs(PCIDevice *dev) -{ - uint16_t num_vfs; - uint16_t i; - uint16_t sriov_cap =3D dev->exp.sriov_cap; - - assert(sriov_cap > 0); - num_vfs =3D pci_get_word(dev->config + sriov_cap + PCI_SRIOV_NUM_VF); - if (num_vfs > pci_get_word(dev->config + sriov_cap + PCI_SRIOV_TOTAL_V= F)) { - clear_ctrl_vfe(dev); - return; - } - - trace_sriov_register_vfs(dev->name, PCI_SLOT(dev->devfn), - PCI_FUNC(dev->devfn), num_vfs); - for (i =3D 0; i < num_vfs; i++) { - pci_set_enabled(dev->exp.sriov_pf.vf[i], true); - } -} - -static void unregister_vfs(PCIDevice *dev) -{ - uint16_t i; - uint8_t *cfg =3D dev->config + dev->exp.sriov_cap; - - trace_sriov_unregister_vfs(dev->name, PCI_SLOT(dev->devfn), - PCI_FUNC(dev->devfn)); - for (i =3D 0; i < pci_get_word(cfg + PCI_SRIOV_TOTAL_VF); i++) { - pci_set_enabled(dev->exp.sriov_pf.vf[i], false); - } -} - -static bool pcie_sriov_pf_init_common(PCIDevice *dev, uint16_t offset, - uint16_t vf_dev_id, uint16_t init_vf= s, - uint16_t total_vfs, uint16_t vf_offs= et, - uint16_t vf_stride, Error **errp) +bool pcie_sriov_pf_init(PCIDevice *dev, uint16_t offset, + const char *vfname, uint16_t vf_dev_id, + uint16_t init_vfs, uint16_t total_vfs, + uint16_t vf_offset, uint16_t vf_stride, + Error **errp) { + BusState *bus =3D qdev_get_parent_bus(&dev->qdev); + int32_t devfn =3D dev->devfn + vf_offset; uint8_t *cfg =3D dev->config + offset; uint8_t *wmask; =20 @@ -137,28 +100,6 @@ static bool pcie_sriov_pf_init_common(PCIDevice *dev, = uint16_t offset, =20 qdev_prop_set_bit(&dev->qdev, "multifunction", true); =20 - return true; -} - -bool pcie_sriov_pf_init(PCIDevice *dev, uint16_t offset, - const char *vfname, uint16_t vf_dev_id, - uint16_t init_vfs, uint16_t total_vfs, - uint16_t vf_offset, uint16_t vf_stride, - Error **errp) -{ - BusState *bus =3D qdev_get_parent_bus(&dev->qdev); - int32_t devfn =3D dev->devfn + vf_offset; - - if (pfs && g_hash_table_contains(pfs, dev->qdev.id)) { - error_setg(errp, "attaching user-created SR-IOV VF unsupported"); - return false; - } - - if (!pcie_sriov_pf_init_common(dev, offset, vf_dev_id, init_vfs, - total_vfs, vf_offset, vf_stride, errp))= { - return false; - } - dev->exp.sriov_pf.vf =3D g_new(PCIDevice *, total_vfs); =20 for (uint16_t i =3D 0; i < total_vfs; i++) { @@ -188,24 +129,7 @@ void pcie_sriov_pf_exit(PCIDevice *dev) { uint8_t *cfg =3D dev->config + dev->exp.sriov_cap; =20 - if (dev->exp.sriov_pf.vf_user_created) { - uint16_t ven_id =3D pci_get_word(dev->config + PCI_VENDOR_ID); - uint16_t total_vfs =3D pci_get_word(dev->config + PCI_SRIOV_TOTAL_= VF); - uint16_t vf_dev_id =3D pci_get_word(dev->config + PCI_SRIOV_VF_DID= ); - - unregister_vfs(dev); - - for (uint16_t i =3D 0; i < total_vfs; i++) { - PCIDevice *vf =3D dev->exp.sriov_pf.vf[i]; - - vf->exp.sriov_vf.pf =3D NULL; - - pci_config_set_vendor_id(vf->config, ven_id); - pci_config_set_device_id(vf->config, vf_dev_id); - } - } else { - unparent_vfs(dev, pci_get_word(cfg + PCI_SRIOV_TOTAL_VF)); - } + unparent_vfs(dev, pci_get_word(cfg + PCI_SRIOV_TOTAL_VF)); } =20 void pcie_sriov_pf_init_vf_bar(PCIDevice *dev, int region_num, @@ -238,172 +162,74 @@ void pcie_sriov_pf_init_vf_bar(PCIDevice *dev, int r= egion_num, void pcie_sriov_vf_register_bar(PCIDevice *dev, int region_num, MemoryRegion *memory) { + PCIIORegion *r; + PCIBus *bus =3D pci_get_bus(dev); uint8_t type; + pcibus_t size =3D memory_region_size(memory); =20 - assert(dev->exp.sriov_vf.pf); + assert(pci_is_vf(dev)); /* PFs must use pci_register_bar */ + assert(region_num >=3D 0); + assert(region_num < PCI_NUM_REGIONS); type =3D dev->exp.sriov_vf.pf->exp.sriov_pf.vf_bar_type[region_num]; =20 - return pci_register_bar(dev, region_num, type, memory); + if (!is_power_of_2(size)) { + error_report("%s: PCI region size must be a power" + " of two - type=3D0x%x, size=3D0x%"FMT_PCIBUS, + __func__, type, size); + exit(1); + } + + r =3D &dev->io_regions[region_num]; + r->memory =3D memory; + r->address_space =3D + type & PCI_BASE_ADDRESS_SPACE_IO + ? bus->address_space_io + : bus->address_space_mem; + r->size =3D size; + r->type =3D type; + + r->addr =3D pci_bar_address(dev, region_num, r->type, r->size); + if (r->addr !=3D PCI_BAR_UNMAPPED) { + memory_region_add_subregion_overlap(r->address_space, + r->addr, r->memory, 1); + } } =20 -static gint compare_vf_devfns(gconstpointer a, gconstpointer b) +static void clear_ctrl_vfe(PCIDevice *dev) { - return (*(PCIDevice **)a)->devfn - (*(PCIDevice **)b)->devfn; + uint8_t *ctrl =3D dev->config + dev->exp.sriov_cap + PCI_SRIOV_CTRL; + pci_set_word(ctrl, pci_get_word(ctrl) & ~PCI_SRIOV_CTRL_VFE); } =20 -int16_t pcie_sriov_pf_init_from_user_created_vfs(PCIDevice *dev, - uint16_t offset, - Error **errp) +static void register_vfs(PCIDevice *dev) { - GPtrArray *pf; - PCIDevice **vfs; - BusState *bus =3D qdev_get_parent_bus(DEVICE(dev)); - uint16_t ven_id =3D pci_get_word(dev->config + PCI_VENDOR_ID); - uint16_t vf_dev_id; - uint16_t vf_offset; - uint16_t vf_stride; + uint16_t num_vfs; uint16_t i; + uint16_t sriov_cap =3D dev->exp.sriov_cap; =20 - if (!pfs || !dev->qdev.id) { - return 0; + assert(sriov_cap > 0); + num_vfs =3D pci_get_word(dev->config + sriov_cap + PCI_SRIOV_NUM_VF); + if (num_vfs > pci_get_word(dev->config + sriov_cap + PCI_SRIOV_TOTAL_V= F)) { + clear_ctrl_vfe(dev); + return; } =20 - pf =3D g_hash_table_lookup(pfs, dev->qdev.id); - if (!pf) { - return 0; + trace_sriov_register_vfs(dev->name, PCI_SLOT(dev->devfn), + PCI_FUNC(dev->devfn), num_vfs); + for (i =3D 0; i < num_vfs; i++) { + pci_set_enabled(dev->exp.sriov_pf.vf[i], true); } - - if (pf->len > UINT16_MAX) { - error_setg(errp, "too many VFs"); - return -1; - } - - g_ptr_array_sort(pf, compare_vf_devfns); - vfs =3D (void *)pf->pdata; - - if (vfs[0]->devfn <=3D dev->devfn) { - error_setg(errp, "a VF function number is less than the PF functio= n number"); - return -1; - } - - vf_dev_id =3D pci_get_word(vfs[0]->config + PCI_DEVICE_ID); - vf_offset =3D vfs[0]->devfn - dev->devfn; - vf_stride =3D pf->len < 2 ? 0 : vfs[1]->devfn - vfs[0]->devfn; - - for (i =3D 0; i < pf->len; i++) { - if (bus !=3D qdev_get_parent_bus(&vfs[i]->qdev)) { - error_setg(errp, "SR-IOV VF parent bus mismatches with PF"); - return -1; - } - - if (ven_id !=3D pci_get_word(vfs[i]->config + PCI_VENDOR_ID)) { - error_setg(errp, "SR-IOV VF vendor ID mismatches with PF"); - return -1; - } - - if (vf_dev_id !=3D pci_get_word(vfs[i]->config + PCI_DEVICE_ID)) { - error_setg(errp, "inconsistent SR-IOV VF device IDs"); - return -1; - } - - for (size_t j =3D 0; j < PCI_NUM_REGIONS; j++) { - if (vfs[i]->io_regions[j].size !=3D vfs[0]->io_regions[j].size= || - vfs[i]->io_regions[j].type !=3D vfs[0]->io_regions[j].type= ) { - error_setg(errp, "inconsistent SR-IOV BARs"); - return -1; - } - } - - if (vfs[i]->devfn - vfs[0]->devfn !=3D vf_stride * i) { - error_setg(errp, "inconsistent SR-IOV stride"); - return -1; - } - } - - if (!pcie_sriov_pf_init_common(dev, offset, vf_dev_id, pf->len, - pf->len, vf_offset, vf_stride, errp)) { - return -1; - } - - for (i =3D 0; i < pf->len; i++) { - vfs[i]->exp.sriov_vf.pf =3D dev; - vfs[i]->exp.sriov_vf.vf_number =3D i; - - /* set vid/did according to sr/iov spec - they are not used */ - pci_config_set_vendor_id(vfs[i]->config, 0xffff); - pci_config_set_device_id(vfs[i]->config, 0xffff); - } - - dev->exp.sriov_pf.vf =3D vfs; - dev->exp.sriov_pf.vf_user_created =3D true; - - for (i =3D 0; i < PCI_NUM_REGIONS; i++) { - PCIIORegion *region =3D &vfs[0]->io_regions[i]; - - if (region->size) { - pcie_sriov_pf_init_vf_bar(dev, i, region->type, region->size); - } - } - - return PCI_EXT_CAP_SRIOV_SIZEOF; } =20 -bool pcie_sriov_register_device(PCIDevice *dev, Error **errp) +static void unregister_vfs(PCIDevice *dev) { - if (!dev->exp.sriov_pf.vf && dev->qdev.id && - pfs && g_hash_table_contains(pfs, dev->qdev.id)) { - error_setg(errp, "attaching user-created SR-IOV VF unsupported"); - return false; - } + uint16_t i; + uint8_t *cfg =3D dev->config + dev->exp.sriov_cap; =20 - if (dev->sriov_pf) { - PCIDevice *pci_pf; - GPtrArray *pf; - - if (!PCI_DEVICE_GET_CLASS(dev)->sriov_vf_user_creatable) { - error_setg(errp, "user cannot create SR-IOV VF with this devic= e type"); - return false; - } - - if (!pci_is_express(dev)) { - error_setg(errp, "PCI Express is required for SR-IOV VF"); - return false; - } - - if (!pci_qdev_find_device(dev->sriov_pf, &pci_pf)) { - error_setg(errp, "PCI device specified as SR-IOV PF already ex= ists"); - return false; - } - - if (!pfs) { - pfs =3D g_hash_table_new_full(g_str_hash, g_str_equal, g_free,= NULL); - } - - pf =3D g_hash_table_lookup(pfs, dev->sriov_pf); - if (!pf) { - pf =3D g_ptr_array_new(); - g_hash_table_insert(pfs, g_strdup(dev->sriov_pf), pf); - } - - g_ptr_array_add(pf, dev); - } - - return true; -} - -void pcie_sriov_unregister_device(PCIDevice *dev) -{ - if (dev->sriov_pf && pfs) { - GPtrArray *pf =3D g_hash_table_lookup(pfs, dev->sriov_pf); - - if (pf) { - g_ptr_array_remove_fast(pf, dev); - - if (!pf->len) { - g_hash_table_remove(pfs, dev->sriov_pf); - g_ptr_array_free(pf, FALSE); - } - } + trace_sriov_unregister_vfs(dev->name, PCI_SLOT(dev->devfn), + PCI_FUNC(dev->devfn)); + for (i =3D 0; i < pci_get_word(cfg + PCI_SRIOV_TOTAL_VF); i++) { + pci_set_enabled(dev->exp.sriov_pf.vf[i], false); } } =20 @@ -490,7 +316,7 @@ void pcie_sriov_pf_add_sup_pgsize(PCIDevice *dev, uint1= 6_t opt_sup_pgsize) =20 uint16_t pcie_sriov_vf_number(PCIDevice *dev) { - assert(dev->exp.sriov_vf.pf); + assert(pci_is_vf(dev)); return dev->exp.sriov_vf.vf_number; } =20 --=20 MST