From mboxrd@z Thu Jan 1 00:00:00 1970 From: "Jan Beulich" Subject: [PATCH v15 1/3] IOMMU/ATS: use a struct pci_dev * instead of SBDF Date: Fri, 08 Jul 2016 00:44:23 -0600 Message-ID: <577F67E702000078000FC74E@prv-mh.provo.novell.com> References: <577F66BC02000078000FC743@prv-mh.provo.novell.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=__PartDCEAF9D7.5__=" Return-path: Received: from mail6.bemta5.messagelabs.com ([195.245.231.135]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1bLPWX-0003zd-13 for xen-devel@lists.xenproject.org; Fri, 08 Jul 2016 06:44:29 +0000 In-Reply-To: <577F66BC02000078000FC743@prv-mh.provo.novell.com> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xen.org Sender: "Xen-devel" To: xen-devel Cc: Kevin Tian , Stefano Stabellini , Feng Wu , George Dunlap , Andrew Cooper , Ian Jackson , Tim Deegan , Suravee Suthikulpanit , Wei Liu List-Id: xen-devel@lists.xenproject.org This is a MIME message. If you are reading this text, you may want to consider changing to a mail reader or gateway that understands how to properly handle MIME multipart messages. --=__PartDCEAF9D7.5__= Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: quoted-printable Content-Disposition: inline From: Quan Xu Do away with struct pci_ats_dev; integrate the few bits of information in struct pci_dev (and as a result drop get_ats_device() altogether). Hook ATS devices onto a linked list off of each IOMMU instead of on a global one.=20 Signed-off-by: Quan Xu Signed-off-by: Jan Beulich --- v15: See rewritten description. Ditch changes to vtd/intremap.c. --- a/xen/drivers/passthrough/amd/iommu_cmd.c +++ b/xen/drivers/passthrough/amd/iommu_cmd.c @@ -289,35 +289,29 @@ void amd_iommu_flush_iotlb(u8 devfn, con unsigned long flags; struct amd_iommu *iommu; unsigned int req_id, queueid, maxpend; - struct pci_ats_dev *ats_pdev; =20 if ( !ats_enabled ) return; =20 - ats_pdev =3D get_ats_device(pdev->seg, pdev->bus, pdev->devfn); - if ( ats_pdev =3D=3D NULL ) + if ( !pci_ats_enabled(pdev->seg, pdev->bus, pdev->devfn) ) return; =20 - if ( !pci_ats_enabled(ats_pdev->seg, ats_pdev->bus, ats_pdev->devfn) = ) - return; - - iommu =3D find_iommu_for_device(ats_pdev->seg, - PCI_BDF2(ats_pdev->bus, ats_pdev->devfn)= ); + iommu =3D find_iommu_for_device(pdev->seg, PCI_BDF2(pdev->bus, = pdev->devfn)); =20 if ( !iommu ) { AMD_IOMMU_DEBUG("%s: Can't find iommu for %04x:%02x:%02x.%u\n", - __func__, ats_pdev->seg, ats_pdev->bus, - PCI_SLOT(ats_pdev->devfn), PCI_FUNC(ats_pdev->devf= n)); + __func__, pdev->seg, pdev->bus, + PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); return; } =20 if ( !iommu_has_cap(iommu, PCI_CAP_IOTLB_SHIFT) ) return; =20 - req_id =3D get_dma_requestor_id(iommu->seg, PCI_BDF2(ats_pdev->bus, = devfn)); + req_id =3D get_dma_requestor_id(iommu->seg, PCI_BDF2(pdev->bus, = devfn)); queueid =3D req_id; - maxpend =3D ats_pdev->ats_queue_depth & 0xff; + maxpend =3D pdev->ats.queue_depth & 0xff; =20 /* send INVALIDATE_IOTLB_PAGES command */ spin_lock_irqsave(&iommu->lock, flags); --- a/xen/drivers/passthrough/amd/iommu_detect.c +++ b/xen/drivers/passthrough/amd/iommu_detect.c @@ -128,6 +128,7 @@ int __init amd_iommu_detect_one_acpi( } =20 spin_lock_init(&iommu->lock); + INIT_LIST_HEAD(&iommu->ats_devices); =20 iommu->seg =3D ivhd_block->pci_segment_group; iommu->bdf =3D ivhd_block->header.device_id; --- a/xen/drivers/passthrough/amd/pci_amd_iommu.c +++ b/xen/drivers/passthrough/amd/pci_amd_iommu.c @@ -162,7 +162,7 @@ static void amd_iommu_setup_domain_devic !pci_ats_enabled(iommu->seg, bus, pdev->devfn) ) { if ( devfn =3D=3D pdev->devfn ) - enable_ats_device(iommu->seg, bus, devfn, iommu); + enable_ats_device(pdev, &iommu->ats_devices); =20 amd_iommu_flush_iotlb(devfn, pdev, INV_IOMMU_ALL_PAGES_ADDRESS, = 0); } @@ -356,7 +356,7 @@ void amd_iommu_disable_domain_device(str if ( devfn =3D=3D pdev->devfn && pci_ats_device(iommu->seg, bus, devfn) && pci_ats_enabled(iommu->seg, bus, devfn) ) - disable_ats_device(iommu->seg, bus, devfn); + disable_ats_device(pdev); } =20 static int reassign_device(struct domain *source, struct domain *target, --- a/xen/drivers/passthrough/ats.h +++ b/xen/drivers/passthrough/ats.h @@ -17,26 +17,15 @@ =20 #include =20 -struct pci_ats_dev { - struct list_head list; - u16 seg; - u8 bus; - u8 devfn; - u16 ats_queue_depth; /* ATS device invalidation queue depth */ - const void *iommu; /* No common IOMMU struct so use void pointer = */ -}; - #define ATS_REG_CAP 4 #define ATS_REG_CTL 6 #define ATS_QUEUE_DEPTH_MASK 0x1f #define ATS_ENABLE (1<<15) =20 -extern struct list_head ats_devices; extern bool_t ats_enabled; =20 -int enable_ats_device(int seg, int bus, int devfn, const void *iommu); -void disable_ats_device(int seg, int bus, int devfn); -struct pci_ats_dev *get_ats_device(int seg, int bus, int devfn); +int enable_ats_device(struct pci_dev *pdev, struct list_head *ats_list); +void disable_ats_device(struct pci_dev *pdev); =20 static inline int pci_ats_enabled(int seg, int bus, int devfn) { --- a/xen/drivers/passthrough/vtd/iommu.c +++ b/xen/drivers/passthrough/vtd/iommu.c @@ -1162,6 +1162,7 @@ int __init iommu_alloc(struct acpi_drhd_ return -ENOMEM; =20 iommu->msi.irq =3D -1; /* No irq assigned yet. */ + INIT_LIST_HEAD(&iommu->ats_devices); =20 iommu->intel =3D alloc_intel_iommu(); if ( iommu->intel =3D=3D NULL ) @@ -1461,8 +1462,8 @@ int domain_context_mapping_one( return rc; } =20 -static int domain_context_mapping( - struct domain *domain, u8 devfn, const struct pci_dev *pdev) +static int domain_context_mapping(struct domain *domain, u8 devfn, + struct pci_dev *pdev) { struct acpi_drhd_unit *drhd; int ret =3D 0; @@ -1498,7 +1499,7 @@ static int domain_context_mapping( ret =3D domain_context_mapping_one(domain, drhd->iommu, bus, = devfn, pdev); if ( !ret && devfn =3D=3D pdev->devfn && ats_device(pdev, drhd) > = 0 ) - enable_ats_device(seg, bus, devfn, drhd->iommu); + enable_ats_device(pdev, &drhd->iommu->ats_devices); =20 break; =20 @@ -1611,8 +1612,8 @@ int domain_context_unmap_one( return rc; } =20 -static int domain_context_unmap( - struct domain *domain, u8 devfn, const struct pci_dev *pdev) +static int domain_context_unmap(struct domain *domain, u8 devfn, + struct pci_dev *pdev) { struct acpi_drhd_unit *drhd; struct iommu *iommu; @@ -1648,7 +1649,7 @@ static int domain_context_unmap( PCI_SLOT(devfn), PCI_FUNC(devfn)); ret =3D domain_context_unmap_one(domain, iommu, bus, devfn); if ( !ret && devfn =3D=3D pdev->devfn && ats_device(pdev, drhd) > = 0 ) - disable_ats_device(seg, bus, devfn); + disable_ats_device(pdev); =20 break; =20 @@ -1994,7 +1995,7 @@ static int intel_iommu_enable_device(str if ( ret <=3D 0 ) return ret; =20 - ret =3D enable_ats_device(pdev->seg, pdev->bus, pdev->devfn, = drhd->iommu); + ret =3D enable_ats_device(pdev, &drhd->iommu->ats_devices); =20 return ret >=3D 0 ? 0 : ret; } --- a/xen/drivers/passthrough/vtd/iommu.h +++ b/xen/drivers/passthrough/vtd/iommu.h @@ -542,6 +542,7 @@ struct iommu { u64 root_maddr; /* root entry machine address */ struct msi_desc msi; struct intel_iommu *intel; + struct list_head ats_devices; unsigned long *domid_bitmap; /* domain id bitmap */ u16 *domid_map; /* domain id mapping array */ }; --- a/xen/drivers/passthrough/vtd/x86/ats.c +++ b/xen/drivers/passthrough/vtd/x86/ats.c @@ -71,7 +71,8 @@ int ats_device(const struct pci_dev *pde return pos; } =20 -static int device_in_domain(struct iommu *iommu, struct pci_ats_dev = *pdev, u16 did) +static int device_in_domain(const struct iommu *iommu, + const struct pci_dev *pdev, u16 did) { struct root_entry *root_entry =3D NULL; struct context_entry *ctxt_entry =3D NULL; @@ -108,22 +109,18 @@ out: int dev_invalidate_iotlb(struct iommu *iommu, u16 did, u64 addr, unsigned int size_order, u64 type) { - struct pci_ats_dev *pdev; + const struct pci_dev *pdev; int ret =3D 0; =20 if ( !ecap_dev_iotlb(iommu->ecap) ) return ret; =20 - list_for_each_entry( pdev, &ats_devices, list ) + list_for_each_entry( pdev, &iommu->ats_devices, ats.list ) { u16 sid =3D PCI_BDF2(pdev->bus, pdev->devfn); bool_t sbit; int rc =3D 0; =20 - /* Only invalidate devices that belong to this IOMMU */ - if ( pdev->iommu !=3D iommu ) - continue; - switch ( type ) { case DMA_TLB_DSI_FLUSH: @@ -134,7 +131,7 @@ int dev_invalidate_iotlb(struct iommu *i /* invalidate all translations: sbit=3D1,bit_63=3D0,bit[62:12]= =3D1 */ sbit =3D 1; addr =3D (~0UL << PAGE_SHIFT_4K) & 0x7FFFFFFFFFFFFFFF; - rc =3D qinval_device_iotlb_sync(iommu, pdev->ats_queue_depth, + rc =3D qinval_device_iotlb_sync(iommu, pdev->ats.queue_depth, sid, sbit, addr); break; case DMA_TLB_PSI_FLUSH: @@ -154,7 +151,7 @@ int dev_invalidate_iotlb(struct iommu *i addr |=3D (((u64)1 << (size_order - 1)) - 1) << PAGE_SHIFT= _4K; } =20 - rc =3D qinval_device_iotlb_sync(iommu, pdev->ats_queue_depth, + rc =3D qinval_device_iotlb_sync(iommu, pdev->ats.queue_depth, sid, sbit, addr); break; default: --- a/xen/drivers/passthrough/x86/ats.c +++ b/xen/drivers/passthrough/x86/ats.c @@ -17,15 +17,14 @@ #include #include "../ats.h" =20 -LIST_HEAD(ats_devices); - bool_t __read_mostly ats_enabled =3D 0; boolean_param("ats", ats_enabled); =20 -int enable_ats_device(int seg, int bus, int devfn, const void *iommu) +int enable_ats_device(struct pci_dev *pdev, struct list_head *ats_list) { - struct pci_ats_dev *pdev =3D NULL; u32 value; + u16 seg =3D pdev->seg; + u8 bus =3D pdev->bus, devfn =3D pdev->devfn; int pos; =20 pos =3D pci_find_ext_capability(seg, bus, devfn, PCI_EXT_CAP_ID_ATS); @@ -39,19 +38,15 @@ int enable_ats_device(int seg, int bus, PCI_FUNC(devfn), pos + ATS_REG_CTL); if ( value & ATS_ENABLE ) { - list_for_each_entry ( pdev, &ats_devices, list ) - { - if ( pdev->seg =3D=3D seg && pdev->bus =3D=3D bus && = pdev->devfn =3D=3D devfn ) + struct pci_dev *other; + + list_for_each_entry ( other, ats_list, ats.list ) + if ( other =3D=3D pdev ) { pos =3D 0; break; } - } } - if ( pos ) - pdev =3D xmalloc(struct pci_ats_dev); - if ( !pdev ) - return -ENOMEM; =20 if ( !(value & ATS_ENABLE) ) { @@ -62,15 +57,12 @@ int enable_ats_device(int seg, int bus, =20 if ( pos ) { - pdev->seg =3D seg; - pdev->bus =3D bus; - pdev->devfn =3D devfn; - pdev->iommu =3D iommu; + pdev->ats.cap_pos =3D pos; value =3D pci_conf_read16(seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn), pos + ATS_REG_CAP); - pdev->ats_queue_depth =3D value & ATS_QUEUE_DEPTH_MASK ?: + pdev->ats.queue_depth =3D value & ATS_QUEUE_DEPTH_MASK ?: ATS_QUEUE_DEPTH_MASK + 1; - list_add(&pdev->list, &ats_devices); + list_add(&pdev->ats.list, ats_list); } =20 if ( iommu_verbose ) @@ -81,48 +73,23 @@ int enable_ats_device(int seg, int bus, return pos; } =20 -void disable_ats_device(int seg, int bus, int devfn) +void disable_ats_device(struct pci_dev *pdev) { - struct pci_ats_dev *pdev; u32 value; - int pos; + u16 seg =3D pdev->seg; + u8 bus =3D pdev->bus, devfn =3D pdev->devfn; =20 - pos =3D pci_find_ext_capability(seg, bus, devfn, PCI_EXT_CAP_ID_ATS); - BUG_ON(!pos); + BUG_ON(!pdev->ats.cap_pos); =20 - value =3D pci_conf_read16(seg, bus, PCI_SLOT(devfn), - PCI_FUNC(devfn), pos + ATS_REG_CTL); + value =3D pci_conf_read16(seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn), + pdev->ats.cap_pos + ATS_REG_CTL); value &=3D ~ATS_ENABLE; pci_conf_write16(seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn), - pos + ATS_REG_CTL, value); + pdev->ats.cap_pos + ATS_REG_CTL, value); =20 - list_for_each_entry ( pdev, &ats_devices, list ) - { - if ( pdev->seg =3D=3D seg && pdev->bus =3D=3D bus && pdev->devfn = =3D=3D devfn ) - { - list_del(&pdev->list); - xfree(pdev); - break; - } - } + list_del(&pdev->ats.list); =20 if ( iommu_verbose ) dprintk(XENLOG_INFO, "%04x:%02x:%02x.%u: ATS is disabled\n", seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); } - -struct pci_ats_dev *get_ats_device(int seg, int bus, int devfn) -{ - struct pci_ats_dev *pdev; - - if ( !pci_ats_device(seg, bus, devfn) ) - return NULL; - - list_for_each_entry ( pdev, &ats_devices, list ) - { - if ( pdev->seg =3D=3D seg && pdev->bus =3D=3D bus && pdev->devfn = =3D=3D devfn ) - return pdev; - } - - return NULL; -} --- a/xen/include/asm-x86/amd-iommu.h +++ b/xen/include/asm-x86/amd-iommu.h @@ -104,6 +104,8 @@ struct amd_iommu { uint64_t exclusion_limit; =20 int enabled; + + struct list_head ats_devices; }; =20 struct ivrs_mappings { --- a/xen/include/xen/pci.h +++ b/xen/include/xen/pci.h @@ -78,6 +78,11 @@ struct pci_dev { struct pci_dev_info info; struct arch_pci_dev arch; struct { + struct list_head list; + unsigned int cap_pos; + unsigned int queue_depth; + } ats; + struct { s_time_t time; unsigned int count; #define PT_FAULT_THRESHOLD 10 --=__PartDCEAF9D7.5__= Content-Type: text/plain; name="IOMMU-ATS-info-reorg.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="IOMMU-ATS-info-reorg.patch" IOMMU/ATS: use a struct pci_dev * instead of SBDF=0A=0AFrom: Quan Xu = =0A=0ADo away with struct pci_ats_dev; integrate the = few bits of information=0Ain struct pci_dev (and as a result drop = get_ats_device() altogether).=0AHook ATS devices onto a linked list off of = each IOMMU instead of on a=0Aglobal one. =0A=0ASigned-off-by: Quan Xu = =0ASigned-off-by: Jan Beulich =0A---= =0Av15: See rewritten description. Ditch changes to vtd/intremap.c.=0A=0A--= - a/xen/drivers/passthrough/amd/iommu_cmd.c=0A+++ b/xen/drivers/passthrough= /amd/iommu_cmd.c=0A@@ -289,35 +289,29 @@ void amd_iommu_flush_iotlb(u8 = devfn, con=0A unsigned long flags;=0A struct amd_iommu *iommu;=0A = unsigned int req_id, queueid, maxpend;=0A- struct pci_ats_dev = *ats_pdev;=0A =0A if ( !ats_enabled )=0A return;=0A =0A- = ats_pdev =3D get_ats_device(pdev->seg, pdev->bus, pdev->devfn);=0A- if = ( ats_pdev =3D=3D NULL )=0A+ if ( !pci_ats_enabled(pdev->seg, pdev->bus,= pdev->devfn) )=0A return;=0A =0A- if ( !pci_ats_enabled(ats_pde= v->seg, ats_pdev->bus, ats_pdev->devfn) )=0A- return;=0A-=0A- = iommu =3D find_iommu_for_device(ats_pdev->seg,=0A- = PCI_BDF2(ats_pdev->bus, ats_pdev->devfn));=0A+ iommu =3D = find_iommu_for_device(pdev->seg, PCI_BDF2(pdev->bus, pdev->devfn));=0A =0A = if ( !iommu )=0A {=0A AMD_IOMMU_DEBUG("%s: Can't find = iommu for %04x:%02x:%02x.%u\n",=0A- __func__, = ats_pdev->seg, ats_pdev->bus,=0A- PCI_SLOT(ats_pdev-= >devfn), PCI_FUNC(ats_pdev->devfn));=0A+ __func__, = pdev->seg, pdev->bus,=0A+ PCI_SLOT(pdev->devfn), = PCI_FUNC(pdev->devfn));=0A return;=0A }=0A =0A if ( = !iommu_has_cap(iommu, PCI_CAP_IOTLB_SHIFT) )=0A return;=0A =0A- = req_id =3D get_dma_requestor_id(iommu->seg, PCI_BDF2(ats_pdev->bus, = devfn));=0A+ req_id =3D get_dma_requestor_id(iommu->seg, PCI_BDF2(pdev->= bus, devfn));=0A queueid =3D req_id;=0A- maxpend =3D ats_pdev->ats_q= ueue_depth & 0xff;=0A+ maxpend =3D pdev->ats.queue_depth & 0xff;=0A =0A = /* send INVALIDATE_IOTLB_PAGES command */=0A spin_lock_irqsave(&iom= mu->lock, flags);=0A--- a/xen/drivers/passthrough/amd/iommu_detect.c=0A+++ = b/xen/drivers/passthrough/amd/iommu_detect.c=0A@@ -128,6 +128,7 @@ int = __init amd_iommu_detect_one_acpi(=0A }=0A =0A spin_lock_init(&iommu= ->lock);=0A+ INIT_LIST_HEAD(&iommu->ats_devices);=0A =0A iommu->seg = =3D ivhd_block->pci_segment_group;=0A iommu->bdf =3D ivhd_block->header= .device_id;=0A--- a/xen/drivers/passthrough/amd/pci_amd_iommu.c=0A+++ = b/xen/drivers/passthrough/amd/pci_amd_iommu.c=0A@@ -162,7 +162,7 @@ static = void amd_iommu_setup_domain_devic=0A !pci_ats_enabled(iommu->seg, = bus, pdev->devfn) )=0A {=0A if ( devfn =3D=3D pdev->devfn = )=0A- enable_ats_device(iommu->seg, bus, devfn, iommu);=0A+ = enable_ats_device(pdev, &iommu->ats_devices);=0A =0A = amd_iommu_flush_iotlb(devfn, pdev, INV_IOMMU_ALL_PAGES_ADDRESS, 0);=0A = }=0A@@ -356,7 +356,7 @@ void amd_iommu_disable_domain_device(str=0A if = ( devfn =3D=3D pdev->devfn &&=0A pci_ats_device(iommu->seg, bus, = devfn) &&=0A pci_ats_enabled(iommu->seg, bus, devfn) )=0A- = disable_ats_device(iommu->seg, bus, devfn);=0A+ disable_ats_device(p= dev);=0A }=0A =0A static int reassign_device(struct domain *source, struct = domain *target,=0A--- a/xen/drivers/passthrough/ats.h=0A+++ b/xen/drivers/p= assthrough/ats.h=0A@@ -17,26 +17,15 @@=0A =0A #include =0A = =0A-struct pci_ats_dev {=0A- struct list_head list;=0A- u16 seg;=0A- = u8 bus;=0A- u8 devfn;=0A- u16 ats_queue_depth; /* ATS device = invalidation queue depth */=0A- const void *iommu; /* No common = IOMMU struct so use void pointer */=0A-};=0A-=0A #define ATS_REG_CAP = 4=0A #define ATS_REG_CTL 6=0A #define ATS_QUEUE_DEPTH_MASK 0x1f=0A = #define ATS_ENABLE (1<<15)=0A =0A-extern struct list_head = ats_devices;=0A extern bool_t ats_enabled;=0A =0A-int enable_ats_device(int= seg, int bus, int devfn, const void *iommu);=0A-void disable_ats_device(in= t seg, int bus, int devfn);=0A-struct pci_ats_dev *get_ats_device(int seg, = int bus, int devfn);=0A+int enable_ats_device(struct pci_dev *pdev, struct = list_head *ats_list);=0A+void disable_ats_device(struct pci_dev *pdev);=0A = =0A static inline int pci_ats_enabled(int seg, int bus, int devfn)=0A = {=0A--- a/xen/drivers/passthrough/vtd/iommu.c=0A+++ b/xen/drivers/passthrou= gh/vtd/iommu.c=0A@@ -1162,6 +1162,7 @@ int __init iommu_alloc(struct = acpi_drhd_=0A return -ENOMEM;=0A =0A iommu->msi.irq =3D -1; /* = No irq assigned yet. */=0A+ INIT_LIST_HEAD(&iommu->ats_devices);=0A =0A = iommu->intel =3D alloc_intel_iommu();=0A if ( iommu->intel =3D=3D = NULL )=0A@@ -1461,8 +1462,8 @@ int domain_context_mapping_one(=0A = return rc;=0A }=0A =0A-static int domain_context_mapping(=0A- struct = domain *domain, u8 devfn, const struct pci_dev *pdev)=0A+static int = domain_context_mapping(struct domain *domain, u8 devfn,=0A+ = struct pci_dev *pdev)=0A {=0A struct acpi_drhd_unit = *drhd;=0A int ret =3D 0;=0A@@ -1498,7 +1499,7 @@ static int domain_cont= ext_mapping(=0A ret =3D domain_context_mapping_one(domain, = drhd->iommu, bus, devfn,=0A = pdev);=0A if ( !ret && devfn =3D=3D pdev->devfn && ats_device(pdev,= drhd) > 0 )=0A- enable_ats_device(seg, bus, devfn, drhd->iommu)= ;=0A+ enable_ats_device(pdev, &drhd->iommu->ats_devices);=0A = =0A break;=0A =0A@@ -1611,8 +1612,8 @@ int domain_context_unmap_one= (=0A return rc;=0A }=0A =0A-static int domain_context_unmap(=0A- = struct domain *domain, u8 devfn, const struct pci_dev *pdev)=0A+static int = domain_context_unmap(struct domain *domain, u8 devfn,=0A+ = struct pci_dev *pdev)=0A {=0A struct acpi_drhd_unit = *drhd;=0A struct iommu *iommu;=0A@@ -1648,7 +1649,7 @@ static int = domain_context_unmap(=0A PCI_SLOT(devfn), PCI_FUNC(devfn= ));=0A ret =3D domain_context_unmap_one(domain, iommu, bus, = devfn);=0A if ( !ret && devfn =3D=3D pdev->devfn && ats_device(pdev= , drhd) > 0 )=0A- disable_ats_device(seg, bus, devfn);=0A+ = disable_ats_device(pdev);=0A =0A break;=0A =0A@@ -1994,7 = +1995,7 @@ static int intel_iommu_enable_device(str=0A if ( ret <=3D 0 = )=0A return ret;=0A =0A- ret =3D enable_ats_device(pdev->seg, = pdev->bus, pdev->devfn, drhd->iommu);=0A+ ret =3D enable_ats_device(pdev= , &drhd->iommu->ats_devices);=0A =0A return ret >=3D 0 ? 0 : ret;=0A = }=0A--- a/xen/drivers/passthrough/vtd/iommu.h=0A+++ b/xen/drivers/passthrou= gh/vtd/iommu.h=0A@@ -542,6 +542,7 @@ struct iommu {=0A u64 root_maddr; = /* root entry machine address */=0A struct msi_desc msi;=0A struct = intel_iommu *intel;=0A+ struct list_head ats_devices;=0A unsigned = long *domid_bitmap; /* domain id bitmap */=0A u16 *domid_map; = /* domain id mapping array */=0A };=0A--- a/xen/drivers/passthrough/v= td/x86/ats.c=0A+++ b/xen/drivers/passthrough/vtd/x86/ats.c=0A@@ -71,7 = +71,8 @@ int ats_device(const struct pci_dev *pde=0A return pos;=0A = }=0A =0A-static int device_in_domain(struct iommu *iommu, struct pci_ats_de= v *pdev, u16 did)=0A+static int device_in_domain(const struct iommu = *iommu,=0A+ const struct pci_dev *pdev, u16 = did)=0A {=0A struct root_entry *root_entry =3D NULL;=0A struct = context_entry *ctxt_entry =3D NULL;=0A@@ -108,22 +109,18 @@ out:=0A int = dev_invalidate_iotlb(struct iommu *iommu, u16 did,=0A u64 addr, = unsigned int size_order, u64 type)=0A {=0A- struct pci_ats_dev = *pdev;=0A+ const struct pci_dev *pdev;=0A int ret =3D 0;=0A =0A = if ( !ecap_dev_iotlb(iommu->ecap) )=0A return ret;=0A =0A- = list_for_each_entry( pdev, &ats_devices, list )=0A+ list_for_each_entry(= pdev, &iommu->ats_devices, ats.list )=0A {=0A u16 sid =3D = PCI_BDF2(pdev->bus, pdev->devfn);=0A bool_t sbit;=0A int = rc =3D 0;=0A =0A- /* Only invalidate devices that belong to this = IOMMU */=0A- if ( pdev->iommu !=3D iommu )=0A- = continue;=0A-=0A switch ( type )=0A {=0A case = DMA_TLB_DSI_FLUSH:=0A@@ -134,7 +131,7 @@ int dev_invalidate_iotlb(struct = iommu *i=0A /* invalidate all translations: sbit=3D1,bit_63=3D0= ,bit[62:12]=3D1 */=0A sbit =3D 1;=0A addr =3D = (~0UL << PAGE_SHIFT_4K) & 0x7FFFFFFFFFFFFFFF;=0A- rc =3D = qinval_device_iotlb_sync(iommu, pdev->ats_queue_depth,=0A+ rc = =3D qinval_device_iotlb_sync(iommu, pdev->ats.queue_depth,=0A = sid, sbit, addr);=0A break;=0A = case DMA_TLB_PSI_FLUSH:=0A@@ -154,7 +151,7 @@ int dev_invalidate_iotlb= (struct iommu *i=0A addr |=3D (((u64)1 << (size_order - = 1)) - 1) << PAGE_SHIFT_4K;=0A }=0A =0A- rc =3D = qinval_device_iotlb_sync(iommu, pdev->ats_queue_depth,=0A+ rc = =3D qinval_device_iotlb_sync(iommu, pdev->ats.queue_depth,=0A = sid, sbit, addr);=0A break;=0A = default:=0A--- a/xen/drivers/passthrough/x86/ats.c=0A+++ b/xen/drivers= /passthrough/x86/ats.c=0A@@ -17,15 +17,14 @@=0A #include = =0A #include "../ats.h"=0A =0A-LIST_HEAD(ats_devices);=0A-=0A bool_t = __read_mostly ats_enabled =3D 0;=0A boolean_param("ats", ats_enabled);=0A = =0A-int enable_ats_device(int seg, int bus, int devfn, const void = *iommu)=0A+int enable_ats_device(struct pci_dev *pdev, struct list_head = *ats_list)=0A {=0A- struct pci_ats_dev *pdev =3D NULL;=0A u32 = value;=0A+ u16 seg =3D pdev->seg;=0A+ u8 bus =3D pdev->bus, devfn = =3D pdev->devfn;=0A int pos;=0A =0A pos =3D pci_find_ext_capability= (seg, bus, devfn, PCI_EXT_CAP_ID_ATS);=0A@@ -39,19 +38,15 @@ int enable_ats= _device(int seg, int bus,=0A PCI_FUNC(devfn), = pos + ATS_REG_CTL);=0A if ( value & ATS_ENABLE )=0A {=0A- = list_for_each_entry ( pdev, &ats_devices, list )=0A- {=0A- = if ( pdev->seg =3D=3D seg && pdev->bus =3D=3D bus && pdev->devfn =3D=3D = devfn )=0A+ struct pci_dev *other;=0A+=0A+ list_for_each_entr= y ( other, ats_list, ats.list )=0A+ if ( other =3D=3D pdev )=0A = {=0A pos =3D 0;=0A break;=0A = }=0A- }=0A }=0A- if ( pos )=0A- pdev =3D = xmalloc(struct pci_ats_dev);=0A- if ( !pdev )=0A- return = -ENOMEM;=0A =0A if ( !(value & ATS_ENABLE) )=0A {=0A@@ -62,15 = +57,12 @@ int enable_ats_device(int seg, int bus,=0A =0A if ( pos )=0A = {=0A- pdev->seg =3D seg;=0A- pdev->bus =3D bus;=0A- = pdev->devfn =3D devfn;=0A- pdev->iommu =3D iommu;=0A+ = pdev->ats.cap_pos =3D pos;=0A value =3D pci_conf_read16(seg, bus, = PCI_SLOT(devfn),=0A PCI_FUNC(devfn), pos + = ATS_REG_CAP);=0A- pdev->ats_queue_depth =3D value & ATS_QUEUE_DEPTH_= MASK ?:=0A+ pdev->ats.queue_depth =3D value & ATS_QUEUE_DEPTH_MASK = ?:=0A ATS_QUEUE_DEPTH_MASK + 1;=0A- = list_add(&pdev->list, &ats_devices);=0A+ list_add(&pdev->ats.list, = ats_list);=0A }=0A =0A if ( iommu_verbose )=0A@@ -81,48 +73,23 @@ = int enable_ats_device(int seg, int bus,=0A return pos;=0A }=0A = =0A-void disable_ats_device(int seg, int bus, int devfn)=0A+void disable_at= s_device(struct pci_dev *pdev)=0A {=0A- struct pci_ats_dev *pdev;=0A = u32 value;=0A- int pos;=0A+ u16 seg =3D pdev->seg;=0A+ u8 bus = =3D pdev->bus, devfn =3D pdev->devfn;=0A =0A- pos =3D pci_find_ext_capab= ility(seg, bus, devfn, PCI_EXT_CAP_ID_ATS);=0A- BUG_ON(!pos);=0A+ = BUG_ON(!pdev->ats.cap_pos);=0A =0A- value =3D pci_conf_read16(seg, bus, = PCI_SLOT(devfn),=0A- PCI_FUNC(devfn), pos + = ATS_REG_CTL);=0A+ value =3D pci_conf_read16(seg, bus, PCI_SLOT(devfn), = PCI_FUNC(devfn),=0A+ pdev->ats.cap_pos + = ATS_REG_CTL);=0A value &=3D ~ATS_ENABLE;=0A pci_conf_write16(seg, = bus, PCI_SLOT(devfn), PCI_FUNC(devfn),=0A- pos + = ATS_REG_CTL, value);=0A+ pdev->ats.cap_pos + ATS_REG_CT= L, value);=0A =0A- list_for_each_entry ( pdev, &ats_devices, list )=0A- = {=0A- if ( pdev->seg =3D=3D seg && pdev->bus =3D=3D bus && = pdev->devfn =3D=3D devfn )=0A- {=0A- list_del(&pdev->list= );=0A- xfree(pdev);=0A- break;=0A- }=0A- = }=0A+ list_del(&pdev->ats.list);=0A =0A if ( iommu_verbose )=0A = dprintk(XENLOG_INFO, "%04x:%02x:%02x.%u: ATS is disabled\n",=0A = seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn));=0A }=0A-=0A-struct = pci_ats_dev *get_ats_device(int seg, int bus, int devfn)=0A-{=0A- = struct pci_ats_dev *pdev;=0A-=0A- if ( !pci_ats_device(seg, bus, devfn) = )=0A- return NULL;=0A-=0A- list_for_each_entry ( pdev, &ats_devic= es, list )=0A- {=0A- if ( pdev->seg =3D=3D seg && pdev->bus = =3D=3D bus && pdev->devfn =3D=3D devfn )=0A- return pdev;=0A- = }=0A-=0A- return NULL;=0A-}=0A--- a/xen/include/asm-x86/amd-iommu.h=0A+= ++ b/xen/include/asm-x86/amd-iommu.h=0A@@ -104,6 +104,8 @@ struct = amd_iommu {=0A uint64_t exclusion_limit;=0A =0A int enabled;=0A+=0A= + struct list_head ats_devices;=0A };=0A =0A struct ivrs_mappings = {=0A--- a/xen/include/xen/pci.h=0A+++ b/xen/include/xen/pci.h=0A@@ -78,6 = +78,11 @@ struct pci_dev {=0A struct pci_dev_info info;=0A struct = arch_pci_dev arch;=0A struct {=0A+ struct list_head list;=0A+ = unsigned int cap_pos;=0A+ unsigned int queue_depth;=0A+ } = ats;=0A+ struct {=0A s_time_t time;=0A unsigned int = count;=0A #define PT_FAULT_THRESHOLD 10=0A --=__PartDCEAF9D7.5__= Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: base64 Content-Disposition: inline X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KWGVuLWRldmVs IG1haWxpbmcgbGlzdApYZW4tZGV2ZWxAbGlzdHMueGVuLm9yZwpodHRwczovL2xpc3RzLnhlbi5v cmcveGVuLWRldmVsCg== --=__PartDCEAF9D7.5__=--