From nobody Mon Feb 9 16:12:59 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=none (zoho.com: 192.237.175.120 is neither permitted nor denied by domain of lists.xenproject.org) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org ARC-Seal: i=1; a=rsa-sha256; t=1569850472; cv=none; d=zoho.com; s=zohoarc; b=QFfQ/tpOVq66xaq+Ok+vGGnbBS+MCOP62MV7tmAT6KeYX6n+Q92HOEJ/GZbRDusFniyJXBYrm4uXVvrHdOobRoK04Rz4hKYSSmxFbmZnsN2Qy/nIVZU0+ztHOo2MYmlg/4aukyiLUrLUUMYXCk5NhfM9gCLdWfuAERbS8tP7Uiw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1569850472; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=5hU6KyxT9frw8RHe0WP/s9unMYecrYlpIJQdkRkc9ls=; b=WUzxoOr7gYrbnZ8oD9S+DDlc71eQuPO7EiB+I7+UFVrFVBolr2ShE9C79zqsakvASQmSZH/GOJWu1Rvd/ZnnmDfD25o3vlGUdbY7+SJtmRrZ1N2azat1imFoci+Ni5Tnem2HhtmU2sOy3+051PWpzmhYRq3GUiGjJ0LNyNFWwUQ= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=fail; spf=none (zoho.com: 192.237.175.120 is neither permitted nor denied by domain of lists.xenproject.org) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1569850472413552.1539449268395; Mon, 30 Sep 2019 06:34:32 -0700 (PDT) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1iEvnv-0005Yk-Ch; Mon, 30 Sep 2019 13:33:31 +0000 Received: from all-amaz-eas1.inumbo.com ([34.197.232.57] helo=us1-amaz-eas2.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1iEvnt-0005XE-EQ for xen-devel@lists.xenproject.org; Mon, 30 Sep 2019 13:33:29 +0000 Received: from esa5.hc3370-68.iphmx.com (unknown [216.71.155.168]) by localhost (Halon) with ESMTPS id e0f66090-e386-11e9-96d3-12813bfff9fa; Mon, 30 Sep 2019 13:33:25 +0000 (UTC) X-Inumbo-ID: e0f66090-e386-11e9-96d3-12813bfff9fa DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=citrix.com; s=securemail; t=1569850405; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=IgKIu7yf7F/J3/6bpWPXUPKO2ikhnvpSyRXkQYfy870=; b=NmLx52bfr23S/k9HNyXFcj+HKDK8RRIR/rDDpKnsP1XIFSQCgauL9v/L nZHQFLK5/hhtzWBK3buyDcLwrehYjcj2Z5fTyZlmyIM8XFnh6ZQJSEZj4 ZMXB4qnNBQfY+uAH+CXHR36j7AQFz2V72ksqhldC9tN3fk/w0MZwdZfnt Q=; Authentication-Results: esa5.hc3370-68.iphmx.com; dkim=none (message not signed) header.i=none; spf=None smtp.pra=roger.pau@citrix.com; spf=Pass smtp.mailfrom=roger.pau@citrix.com; spf=None smtp.helo=postmaster@mail.citrix.com Received-SPF: none (zoho.com: 192.237.175.120 is neither permitted nor denied by domain of lists.xenproject.org) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Received-SPF: None (esa5.hc3370-68.iphmx.com: no sender authenticity information available from domain of roger.pau@citrix.com) identity=pra; client-ip=162.221.158.21; receiver=esa5.hc3370-68.iphmx.com; envelope-from="roger.pau@citrix.com"; x-sender="roger.pau@citrix.com"; x-conformance=sidf_compatible Received-SPF: Pass (esa5.hc3370-68.iphmx.com: domain of roger.pau@citrix.com designates 162.221.158.21 as permitted sender) identity=mailfrom; client-ip=162.221.158.21; receiver=esa5.hc3370-68.iphmx.com; envelope-from="roger.pau@citrix.com"; x-sender="roger.pau@citrix.com"; x-conformance=sidf_compatible; x-record-type="v=spf1"; x-record-text="v=spf1 ip4:209.167.231.154 ip4:178.63.86.133 ip4:195.66.111.40/30 ip4:85.115.9.32/28 ip4:199.102.83.4 ip4:192.28.146.160 ip4:192.28.146.107 ip4:216.52.6.88 ip4:216.52.6.188 ip4:162.221.158.21 ip4:162.221.156.83 ~all" Received-SPF: None (esa5.hc3370-68.iphmx.com: no sender authenticity information available from domain of postmaster@mail.citrix.com) identity=helo; client-ip=162.221.158.21; receiver=esa5.hc3370-68.iphmx.com; envelope-from="roger.pau@citrix.com"; x-sender="postmaster@mail.citrix.com"; x-conformance=sidf_compatible IronPort-SDR: T5u7crorbb86SFo35YfZlzULZTDrTpxRue15H9JQfPDoYsNEa9EC7fWAMRquigy2tiLLDbNzyS /BtldHWOlKpFSfeTFzVoRcPAtfWprXCJUMnZwL36R9w/RoU+YFw8uMXtHLPfyWSaBsCQo7giVX EK4xbh7JDXg+hYb78ifNAJL7TzaUOCzsfjvMTXHTuRHYhyKey6S7rN/0rwI38wyzECpN/0hFIa tM9N6UhN4TQ3DkZS5/9Sil+pfRv+cs3CBG2SxQnbxfeTwTKPncNETXsP5lC72SsRUh1vACFEit BUM= X-SBRS: 2.7 X-MesageID: 6490556 X-Ironport-Server: esa5.hc3370-68.iphmx.com X-Remote-IP: 162.221.158.21 X-Policy: $RELAYED X-IronPort-AV: E=Sophos;i="5.64,567,1559534400"; d="scan'208";a="6490556" From: Roger Pau Monne To: Date: Mon, 30 Sep 2019 15:32:36 +0200 Message-ID: <20190930133238.49868-9-roger.pau@citrix.com> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20190930133238.49868-1-roger.pau@citrix.com> References: <20190930133238.49868-1-roger.pau@citrix.com> MIME-Version: 1.0 Subject: [Xen-devel] [PATCH v3 08/10] vpci: register as an internal ioreq server X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Stefano Stabellini , Wei Liu , Konrad Rzeszutek Wilk , George Dunlap , Andrew Cooper , Paul Durrant , Ian Jackson , Tim Deegan , Julien Grall , Jan Beulich , Roger Pau Monne Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) Switch vPCI to become an internal ioreq server, and hence drop all the vPCI specific decoding and trapping to PCI IO ports and MMCFG regions. This allows to unify the vPCI code with the ioreq infrastructure, opening the door for domains having PCI accesses handled by vPCI and other ioreq servers at the same time. Signed-off-by: Roger Pau Monn=C3=A9 --- Changes since v2: - Remove stray addition of ioreq header to physdev.c. Changes since v1: - Remove prototypes for register_vpci_portio_handler and register_vpci_mmcfg_handler. - Re-add vpci check in hwdom_iommu_map. - Fix test harness. - Remove vpci_{read/write} prototypes and make the functions static. --- tools/tests/vpci/Makefile | 5 +- tools/tests/vpci/emul.h | 4 + xen/arch/x86/hvm/dom0_build.c | 1 + xen/arch/x86/hvm/hvm.c | 5 +- xen/arch/x86/hvm/io.c | 201 ---------------------------------- xen/drivers/vpci/vpci.c | 63 ++++++++++- xen/include/xen/vpci.h | 22 +--- 7 files changed, 79 insertions(+), 222 deletions(-) diff --git a/tools/tests/vpci/Makefile b/tools/tests/vpci/Makefile index 5075bc2be2..c365c4522a 100644 --- a/tools/tests/vpci/Makefile +++ b/tools/tests/vpci/Makefile @@ -25,7 +25,10 @@ install: =20 vpci.c: $(XEN_ROOT)/xen/drivers/vpci/vpci.c # Remove includes and add the test harness header - sed -e '/#include/d' -e '1s/^/#include "emul.h"/' <$< >$@ + sed -e '/#include/d' -e '1s/^/#include "emul.h"/' \ + -e 's/^static uint32_t read/uint32_t vpci_read/' \ + -e 's/^static void write/void vpci_write/' <$< >$@ + =20 list.h: $(XEN_ROOT)/xen/include/xen/list.h vpci.h: $(XEN_ROOT)/xen/include/xen/vpci.h diff --git a/tools/tests/vpci/emul.h b/tools/tests/vpci/emul.h index 2e1d3057c9..5a6494a797 100644 --- a/tools/tests/vpci/emul.h +++ b/tools/tests/vpci/emul.h @@ -125,6 +125,10 @@ typedef union { tx > ty ? tx : ty; \ }) =20 +uint32_t vpci_read(pci_sbdf_t sbdf, unsigned int reg, unsigned int size); +void vpci_write(pci_sbdf_t sbdf, unsigned int reg, unsigned int size, + uint32_t data); + #endif =20 /* diff --git a/xen/arch/x86/hvm/dom0_build.c b/xen/arch/x86/hvm/dom0_build.c index b30042d8f3..dff4d6663c 100644 --- a/xen/arch/x86/hvm/dom0_build.c +++ b/xen/arch/x86/hvm/dom0_build.c @@ -29,6 +29,7 @@ =20 #include #include +#include #include #include #include diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index 5348186c0c..c5c0e3fa2c 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -656,10 +656,13 @@ int hvm_domain_initialise(struct domain *d) d->arch.hvm.io_bitmap =3D hvm_io_bitmap; =20 register_g2m_portio_handler(d); - register_vpci_portio_handler(d); =20 hvm_ioreq_init(d); =20 + rc =3D vpci_register_ioreq(d); + if ( rc ) + goto fail1; + hvm_init_guest_time(d); =20 d->arch.hvm.params[HVM_PARAM_TRIPLE_FAULT_REASON] =3D SHUTDOWN_reboot; diff --git a/xen/arch/x86/hvm/io.c b/xen/arch/x86/hvm/io.c index 3334888136..4c72e68a5b 100644 --- a/xen/arch/x86/hvm/io.c +++ b/xen/arch/x86/hvm/io.c @@ -290,204 +290,6 @@ unsigned int hvm_mmcfg_decode_addr(const struct hvm_m= mcfg *mmcfg, return addr & (PCI_CFG_SPACE_EXP_SIZE - 1); } =20 - -/* Do some sanity checks. */ -static bool vpci_access_allowed(unsigned int reg, unsigned int len) -{ - /* Check access size. */ - if ( len !=3D 1 && len !=3D 2 && len !=3D 4 && len !=3D 8 ) - return false; - - /* Check that access is size aligned. */ - if ( (reg & (len - 1)) ) - return false; - - return true; -} - -/* vPCI config space IO ports handlers (0xcf8/0xcfc). */ -static bool vpci_portio_accept(const struct hvm_io_handler *handler, - const ioreq_t *p) -{ - return (p->addr =3D=3D 0xcf8 && p->size =3D=3D 4) || (p->addr & ~3) = =3D=3D 0xcfc; -} - -static int vpci_portio_read(const struct hvm_io_handler *handler, - uint64_t addr, uint32_t size, uint64_t *data) -{ - const struct domain *d =3D current->domain; - unsigned int reg; - pci_sbdf_t sbdf; - uint32_t cf8; - - *data =3D ~(uint64_t)0; - - if ( addr =3D=3D 0xcf8 ) - { - ASSERT(size =3D=3D 4); - *data =3D d->arch.hvm.pci_cf8; - return X86EMUL_OKAY; - } - - ASSERT((addr & ~3) =3D=3D 0xcfc); - cf8 =3D ACCESS_ONCE(d->arch.hvm.pci_cf8); - if ( !CF8_ENABLED(cf8) ) - return X86EMUL_UNHANDLEABLE; - - reg =3D hvm_pci_decode_addr(cf8, addr, &sbdf); - - if ( !vpci_access_allowed(reg, size) ) - return X86EMUL_OKAY; - - *data =3D vpci_read(sbdf, reg, size); - - return X86EMUL_OKAY; -} - -static int vpci_portio_write(const struct hvm_io_handler *handler, - uint64_t addr, uint32_t size, uint64_t data) -{ - struct domain *d =3D current->domain; - unsigned int reg; - pci_sbdf_t sbdf; - uint32_t cf8; - - if ( addr =3D=3D 0xcf8 ) - { - ASSERT(size =3D=3D 4); - d->arch.hvm.pci_cf8 =3D data; - return X86EMUL_OKAY; - } - - ASSERT((addr & ~3) =3D=3D 0xcfc); - cf8 =3D ACCESS_ONCE(d->arch.hvm.pci_cf8); - if ( !CF8_ENABLED(cf8) ) - return X86EMUL_UNHANDLEABLE; - - reg =3D hvm_pci_decode_addr(cf8, addr, &sbdf); - - if ( !vpci_access_allowed(reg, size) ) - return X86EMUL_OKAY; - - vpci_write(sbdf, reg, size, data); - - return X86EMUL_OKAY; -} - -static const struct hvm_io_ops vpci_portio_ops =3D { - .accept =3D vpci_portio_accept, - .read =3D vpci_portio_read, - .write =3D vpci_portio_write, -}; - -void register_vpci_portio_handler(struct domain *d) -{ - struct hvm_io_handler *handler; - - if ( !has_vpci(d) ) - return; - - handler =3D hvm_next_io_handler(d); - if ( !handler ) - return; - - handler->type =3D IOREQ_TYPE_PIO; - handler->ops =3D &vpci_portio_ops; -} - -/* Handlers to trap PCI MMCFG config accesses. */ -static int vpci_mmcfg_accept(struct vcpu *v, unsigned long addr) -{ - struct domain *d =3D v->domain; - bool found; - - read_lock(&d->arch.hvm.mmcfg_lock); - found =3D hvm_is_mmcfg_address(d, addr); - read_unlock(&d->arch.hvm.mmcfg_lock); - - return found; -} - -static int vpci_mmcfg_read(struct vcpu *v, unsigned long addr, - unsigned int len, unsigned long *data) -{ - struct domain *d =3D v->domain; - const struct hvm_mmcfg *mmcfg; - unsigned int reg; - pci_sbdf_t sbdf; - - *data =3D ~0ul; - - read_lock(&d->arch.hvm.mmcfg_lock); - mmcfg =3D hvm_mmcfg_find(d, addr); - if ( !mmcfg ) - { - read_unlock(&d->arch.hvm.mmcfg_lock); - return X86EMUL_RETRY; - } - - reg =3D hvm_mmcfg_decode_addr(mmcfg, addr, &sbdf); - read_unlock(&d->arch.hvm.mmcfg_lock); - - if ( !vpci_access_allowed(reg, len) || - (reg + len) > PCI_CFG_SPACE_EXP_SIZE ) - return X86EMUL_OKAY; - - /* - * According to the PCIe 3.1A specification: - * - Configuration Reads and Writes must usually be DWORD or smaller - * in size. - * - Because Root Complex implementations are not required to support - * accesses to a RCRB that cross DW boundaries [...] software - * should take care not to cause the generation of such accesses - * when accessing a RCRB unless the Root Complex will support the - * access. - * Xen however supports 8byte accesses by splitting them into two - * 4byte accesses. - */ - *data =3D vpci_read(sbdf, reg, min(4u, len)); - if ( len =3D=3D 8 ) - *data |=3D (uint64_t)vpci_read(sbdf, reg + 4, 4) << 32; - - return X86EMUL_OKAY; -} - -static int vpci_mmcfg_write(struct vcpu *v, unsigned long addr, - unsigned int len, unsigned long data) -{ - struct domain *d =3D v->domain; - const struct hvm_mmcfg *mmcfg; - unsigned int reg; - pci_sbdf_t sbdf; - - read_lock(&d->arch.hvm.mmcfg_lock); - mmcfg =3D hvm_mmcfg_find(d, addr); - if ( !mmcfg ) - { - read_unlock(&d->arch.hvm.mmcfg_lock); - return X86EMUL_RETRY; - } - - reg =3D hvm_mmcfg_decode_addr(mmcfg, addr, &sbdf); - read_unlock(&d->arch.hvm.mmcfg_lock); - - if ( !vpci_access_allowed(reg, len) || - (reg + len) > PCI_CFG_SPACE_EXP_SIZE ) - return X86EMUL_OKAY; - - vpci_write(sbdf, reg, min(4u, len), data); - if ( len =3D=3D 8 ) - vpci_write(sbdf, reg + 4, 4, data >> 32); - - return X86EMUL_OKAY; -} - -static const struct hvm_mmio_ops vpci_mmcfg_ops =3D { - .check =3D vpci_mmcfg_accept, - .read =3D vpci_mmcfg_read, - .write =3D vpci_mmcfg_write, -}; - int hvm_register_mmcfg(struct domain *d, paddr_t addr, unsigned int start_bus, unsigned int end_bus, unsigned int seg) @@ -525,9 +327,6 @@ int hvm_register_mmcfg(struct domain *d, paddr_t addr, return ret; } =20 - if ( list_empty(&d->arch.hvm.mmcfg_regions) && has_vpci(d) ) - register_mmio_handler(d, &vpci_mmcfg_ops); - list_add(&new->next, &d->arch.hvm.mmcfg_regions); write_unlock(&d->arch.hvm.mmcfg_lock); =20 diff --git a/xen/drivers/vpci/vpci.c b/xen/drivers/vpci/vpci.c index cbd1bac7fc..206fcadbc6 100644 --- a/xen/drivers/vpci/vpci.c +++ b/xen/drivers/vpci/vpci.c @@ -20,6 +20,8 @@ #include #include =20 +#include + /* Internal struct to store the emulated PCI registers. */ struct vpci_register { vpci_read_t *read; @@ -302,7 +304,7 @@ static uint32_t merge_result(uint32_t data, uint32_t ne= w, unsigned int size, return (data & ~(mask << (offset * 8))) | ((new & mask) << (offset * 8= )); } =20 -uint32_t vpci_read(pci_sbdf_t sbdf, unsigned int reg, unsigned int size) +static uint32_t read(pci_sbdf_t sbdf, unsigned int reg, unsigned int size) { const struct domain *d =3D current->domain; const struct pci_dev *pdev; @@ -404,8 +406,8 @@ static void vpci_write_helper(const struct pci_dev *pde= v, r->private); } =20 -void vpci_write(pci_sbdf_t sbdf, unsigned int reg, unsigned int size, - uint32_t data) +static void write(pci_sbdf_t sbdf, unsigned int reg, unsigned int size, + uint32_t data) { const struct domain *d =3D current->domain; const struct pci_dev *pdev; @@ -478,6 +480,61 @@ void vpci_write(pci_sbdf_t sbdf, unsigned int reg, uns= igned int size, spin_unlock(&pdev->vpci->lock); } =20 +#ifdef __XEN__ +static int ioreq_handler(ioreq_t *req, void *data) +{ + pci_sbdf_t sbdf; + + /* + * NB: certain requests of type different than PCI are broadcasted to = all + * registered ioreq servers, ignored those. + */ + if ( req->type !=3D IOREQ_TYPE_PCI_CONFIG || req->data_is_ptr ) + return X86EMUL_UNHANDLEABLE; + + sbdf.sbdf =3D req->addr >> 32; + + if ( req->dir ) + req->data =3D read(sbdf, req->addr, req->size); + else + write(sbdf, req->addr, req->size, req->data); + + return X86EMUL_OKAY; +} + +int vpci_register_ioreq(struct domain *d) +{ + ioservid_t id; + int rc; + + if ( !has_vpci(d) ) + return 0; + + rc =3D hvm_create_ioreq_server(d, HVM_IOREQSRV_BUFIOREQ_OFF, &id, true= ); + if ( rc ) + return rc; + + rc =3D hvm_set_ioreq_handler(d, id, ioreq_handler, NULL); + if ( rc ) + return rc; + + if ( is_hardware_domain(d) ) + { + /* Handle all devices in vpci. */ + rc =3D hvm_map_io_range_to_ioreq_server(d, id, XEN_DMOP_IO_RANGE_P= CI, + 0, ~(uint64_t)0); + if ( rc ) + return rc; + } + + rc =3D hvm_set_ioreq_server_state(d, id, true); + if ( rc ) + return rc; + + return rc; +} +#endif + /* * Local variables: * mode: C diff --git a/xen/include/xen/vpci.h b/xen/include/xen/vpci.h index 5295d4c990..4e9591c020 100644 --- a/xen/include/xen/vpci.h +++ b/xen/include/xen/vpci.h @@ -23,6 +23,9 @@ typedef int vpci_register_init_t(struct pci_dev *dev); static vpci_register_init_t *const x##_entry \ __used_section(".data.vpci." p) =3D x =20 +/* Register vPCI handler with ioreq. */ +int vpci_register_ioreq(struct domain *d); + /* Add vPCI handlers to device. */ int __must_check vpci_add_handlers(struct pci_dev *dev); =20 @@ -38,11 +41,6 @@ int __must_check vpci_add_register(struct vpci *vpci, int __must_check vpci_remove_register(struct vpci *vpci, unsigned int offs= et, unsigned int size); =20 -/* Generic read/write handlers for the PCI config space. */ -uint32_t vpci_read(pci_sbdf_t sbdf, unsigned int reg, unsigned int size); -void vpci_write(pci_sbdf_t sbdf, unsigned int reg, unsigned int size, - uint32_t data); - /* Passthrough handlers. */ uint32_t vpci_hw_read16(const struct pci_dev *pdev, unsigned int reg, void *data); @@ -219,20 +217,12 @@ static inline int vpci_add_handlers(struct pci_dev *p= dev) return 0; } =20 -static inline void vpci_dump_msi(void) { } - -static inline uint32_t vpci_read(pci_sbdf_t sbdf, unsigned int reg, - unsigned int size) +static inline int vpci_register_ioreq(struct domain *d) { - ASSERT_UNREACHABLE(); - return ~(uint32_t)0; + return 0; } =20 -static inline void vpci_write(pci_sbdf_t sbdf, unsigned int reg, - unsigned int size, uint32_t data) -{ - ASSERT_UNREACHABLE(); -} +static inline void vpci_dump_msi(void) { } =20 static inline bool vpci_process_pending(struct vcpu *v) { --=20 2.23.0 _______________________________________________ Xen-devel mailing list Xen-devel@lists.xenproject.org https://lists.xenproject.org/mailman/listinfo/xen-devel