amd iommu: Add ATS support (v2)
PATCH 1/1 amd iommu: Add ATS support (v2)
This patch set enables ats devices on amd systems with following changes:
1) Move vendor independent ATS codes into xen/drivers/passthrough/x86/.
2) Add new ATS helper functions.
3) Add amd specific enablement.
The 2nd try fixes ats code location issue pointed out by Jan. Please review.
Thanks,
Wei
--
Advanced Micro Devices GmbH
Sitz: Dornach, Gemeinde Aschheim,
Landkreis München Registergericht München,
HRB Nr. 43632 WEEE Registrierungsnummer 129 19551
Geschäftsführer:
Alberto Bozzo
PATCH 1/1 ats: Move some ats functions to a new directory
# HG changeset patch
# User Wei Wang <[email protected]>
# Date 1319472683 -7200
# Node ID 217c4a82b202975c2fdff9ae499f065471e5c87b
# Parent 121af976b2988de389db139231103ceedd11bb8a
ats: Move some ats functions to a new directory. passhrough/x86 holds vendor neutral codes for x86 architecture.
xen/drivers/passthrough/Makefile +1 -0
@@ -1,6 +1,7 @@ subdir-$(x86) += vtd subdir-$(ia64) += vtd subdir-$(x86) += amd +subdir-$(x86) += x86 obj-y += iommu.o obj-y += io.o
xen/drivers/passthrough/vtd/extern.h +0 -4
@@ -57,13 +57,9 @@ struct acpi_drhd_unit * iommu_to_drhd(ststruct acpi_rhsa_unit *drhd_to_rhsa (struct acpi_drhd_unit *drhd);#ifdef CONFIG_X86_64 -extern bool_t ats_enabled; -struct acpi_drhd_unit *find_ats_dev_drhd (struct iommu *iommu);int ats_device (int seg,int bus,int devfn); -int enable_ats_device (int seg,int bus,int devfn); -void disable_ats_device (int seg,int bus,int devfn);int invalidate_ats_tcs (struct iommu *iommu); int dev_invalidate_iotlb(struct iommu *iommu, u16 did,
xen/drivers/passthrough/vtd/iommu.c +1 -0
@@ -40,6 +40,7 @@#include "dmar.h" #include "extern.h" #include "vtd.h" +#include "../x86/ats.h" #ifdef __ia64__#define nr_ioapics iosapic_get_nr_iosapics()
xen/drivers/passthrough/vtd/x86/ats.c +1 -133
149 lines not on this page · raw message
xen/drivers/passthrough/x86/Makefile new file +1 -0
@@ -0,0 +1,1 @@ +obj-y += ats.o
xen/drivers/passthrough/x86/ats.c new file +139 -0
139 lines not on this page · raw message
xen/drivers/passthrough/x86/ats.h new file +38 -0
@@ -0,0 +1,38 @@ +/* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, write to the Free Software Foundation, Inc., 59 Temple +* Place - Suite 330, Boston, MA 02111-1307 USA. +*/ + +#ifndef _X86_ATS_H_ +#define _X86_ATS_H_ + +#define ATS_REG_CAP 4 +#define ATS_REG_CTL 6 +#define ATS_QUEUE_DEPTH_MASK 0xF +#define ATS_ENABLE (1<<15) + +struct pci_ats_dev { +struct list_head list; +u16 seg; +u8 bus; +u8 devfn; +u16 ats_queue_depth;/* ATS device invalidation queue depth */ +}; + +extern struct list_head ats_devices; +extern bool_t ats_enabled; + +int enable_ats_device (int seg,int bus,int devfn); +void disable_ats_device (int seg,int bus,int devfn); + +#endif /* _X86_ATS_H_ */
Re: [PATCH 1 of 6] ats: Move some ats functions to a new directory
Quoted 43 lines
Quoted 1 line
Quoted 1 line · Wei Wang
# HG changeset patch
# User Wei Wang <[email protected]>
# Date 1319472683 -7200
# Node ID217c4a82b202975c2fdff9ae499f065471e5c87b
# Parent121af976b2988de389db139231103ceedd11bb8a
ats: Move some ats functions to a new directory. passhrough/x86 holds vendor neutral codes for x86 architecture.Signed-off-by Wei Wang <[email protected]>diff -r
121af976b298-r217c4a82b202xen/drivers/passthrough/Makefilexen/drivers/passthrough/Makefile +1
-0@@ -1,6 +1,7 @@ subdir-$(x86) += vtd subdir-$(ia64) += vtd subdir-$(x86) += amd +subdir-$(x86) += x86 obj-y += iommu.o obj-y += io.odiff -r
121af976b298-r217c4a82b202xen/drivers/passthrough/vtd/extern.hxen/drivers/passthrough/vtd/extern.h +0
-4@@ -57,13 +57,9 @@ struct acpi_drhd_unit * iommu_to_drhd(ststruct acpi_rhsa_unit *drhd_to_rhsa (struct acpi_drhd_unit *drhd);#ifdef CONFIG_X86_64 -extern bool_t ats_enabled; -struct acpi_drhd_unit *find_ats_dev_drhd (struct iommu *iommu);int ats_device (int seg,int bus,int devfn); -int enable_ats_device (int seg,int bus,int devfn); -void disable_ats_device (int seg,int bus,int devfn);int invalidate_ats_tcs (struct iommu *iommu); int dev_invalidate_iotlb(struct iommu *iommu, u16 did,diff -r
121af976b298-r217c4a82b202xen/drivers/passthrough/vtd/iommu.c
xen/drivers/passthrough/vtd/iommu.c line 43
Quoted 4 lines
xen/drivers/passthrough/vtd/iommu.c +1
-0@@ -40,6 +40,7 @@#include "dmar.h" #include "extern.h" #include "vtd.h" +#include "../x86/ats.h"
#include <asm/ats.h>
which would imply that ia64 needs such a header, too, so perhaps even
#include <xen/ats.h>
or maybe
#include "../ats.h"
But there's no way you can include x86-only headers here.
Beyond that, this patch looks fine to me.
Jan
Quoted 360 lines
xen/drivers/passthrough/vtd/iommu.c +0
-0#ifdef __ia64__#define nr_ioapics iosapic_get_nr_iosapics()diff -r
121af976b298-r217c4a82b202xen/drivers/passthrough/vtd/x86/ats.cxen/drivers/passthrough/vtd/x86/ats.c +1
-133@@ -27,51 +27,10 @@#include "../dmar.h" #include "../vtd.h" #include "../extern.h" +#include "../../x86/ats.h" static LIST_HEAD (ats_dev_drhd_units); -#define ATS_REG_CAP 4 -#define ATS_REG_CTL 6 -#define ATS_QUEUE_DEPTH_MASK 0xF -#define ATS_ENABLE (1<<15) - -struct pci_ats_dev { -struct list_head list; -u16 seg; -u8 bus; -u8 devfn; -u16 ats_queue_depth;/* ATS device invalidation queue depth */ -}; -static LIST_HEAD (ats_devices); - -static void parse_ats_param (char *s); -custom_param ("ats" , parse_ats_param); - -bool_t __read_mostly ats_enabled =1 ; - -static void __init parse_ats_param (char *s) -{ -char *ss; - -do { - ss =strchr (s,',' ); -if ( ss ) - *ss ='\0' ; - -switch (parse_bool (s) ) - { -case 0 : - ats_enabled =0 ; -break ; -case 1 : - ats_enabled =1 ; -break ; - } - - s = ss +1 ; - }while ( ss ); -} -struct acpi_drhd_unit *find_ats_dev_drhd (struct iommu *iommu) {struct acpi_drhd_unit *drhd;@@ -121,97 +80,6 @@ int ats_device(int seg, int bus, int devreturn pos; } -int enable_ats_device (int seg,int bus,int devfn) -{ -struct pci_ats_dev *pdev =NULL ; -u32 value; -int pos; - - pos =pci_find_ext_capability (seg, bus, devfn,PCI_EXT_CAP_ID_ATS ); -BUG_ON (!pos); - -if ( iommu_verbose ) - dprintk(XENLOG_INFO VTDPREFIX, -"%04x:%02x:%02x.%u: ATS capability found\n" , - seg, bus,PCI_SLOT (devfn),PCI_FUNC (devfn)); - - value =pci_conf_read16 (seg, bus,PCI_SLOT (devfn), -PCI_FUNC (devfn), pos +ATS_REG_CTL ); -if ( value &ATS_ENABLE ) - { - list_for_each_entry ( pdev, &ats_devices, list ) - { -if ( pdev->seg == seg && pdev->bus == bus && pdev->devfn == devfn ) - { - pos =0 ; -break ; - } - } - } -if ( pos ) - pdev = xmalloc(struct pci_ats_dev); -if ( !pdev ) -return -ENOMEM ; - -if ( !(value &ATS_ENABLE ) ) - { - value |=ATS_ENABLE ; -pci_conf_write16 (seg, bus,PCI_SLOT (devfn),PCI_FUNC (devfn), - pos +ATS_REG_CTL , value); - } - -if ( pos ) - { - pdev->seg = seg; - pdev->bus = bus; - pdev->devfn = devfn; - value =pci_conf_read16 (seg, bus,PCI_SLOT (devfn), -PCI_FUNC (devfn), pos +ATS_REG_CAP ); - pdev->ats_queue_depth = value &ATS_QUEUE_DEPTH_MASK ; -list_add (&pdev->list, &ats_devices); - } - -if ( iommu_verbose ) - dprintk(XENLOG_INFO VTDPREFIX, -"%04x:%02x:%02x.%u: ATS %s enabled\n" , - seg, bus,PCI_SLOT (devfn),PCI_FUNC (devfn), - pos ?"is" :"was" ); - -return pos; -} - -void disable_ats_device (int seg,int bus,int devfn) -{ -struct pci_ats_dev *pdev; -u32 value; -int pos; - - pos =pci_find_ext_capability (seg, bus, devfn,PCI_EXT_CAP_ID_ATS ); -BUG_ON (!pos); - - value =pci_conf_read16 (seg, bus,PCI_SLOT (devfn), -PCI_FUNC (devfn), pos +ATS_REG_CTL ); - value &= ~ATS_ENABLE ; -pci_conf_write16 (seg, bus,PCI_SLOT (devfn),PCI_FUNC (devfn), - pos +ATS_REG_CTL , value); - - list_for_each_entry ( pdev, &ats_devices, list ) - { -if ( pdev->seg == seg && pdev->bus == bus && pdev->devfn == devfn ) - { -list_del (&pdev->list); -xfree (pdev); -break ; - } - } - -if ( iommu_verbose ) - dprintk(XENLOG_INFO VTDPREFIX, -"%04x:%02x:%02x.%u: ATS is disabled\n" , - seg, bus,PCI_SLOT (devfn),PCI_FUNC (devfn)); -} - -static int device_in_domain (struct iommu *iommu,struct pci_ats_dev *pdev,u16 did) {struct root_entry *root_entry = NULL;diff -r
121af976b298-r217c4a82b202xen/drivers/passthrough/x86/Makefilexen/drivers/passthrough/x86/Makefile new file +1
-0@@ -0,0 +1,1 @@ +obj-y += ats.odiff -r
121af976b298-r217c4a82b202xen/drivers/passthrough/x86/ats.cxen/drivers/passthrough/x86/ats.c new file +8
-0@@ -0,0 +1,139 @@ +/* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ */xen/drivers/passthrough/x86/ats.c new file +125
-0+ +#include <xen/sched.h> +#include <xen/pci.h> +#include <xen/pci_regs.h> +#include "ats.h" + +LIST_HEAD (ats_devices); + +static void parse_ats_param (char *s); +custom_param ("ats" , parse_ats_param); + +bool_t __read_mostly ats_enabled =1 ; + +static void __init parse_ats_param (char *s) +{ +char *ss; + +do { + ss =strchr (s,',' ); +if ( ss ) + *ss ='\0' ; + +switch (parse_bool (s) ) + { +case 0 : + ats_enabled =0 ; +break ; +case 1 : + ats_enabled =1 ; +break ; + } + + s = ss +1 ; + }while ( ss ); +} + +int enable_ats_device (int seg,int bus,int devfn) +{ +struct pci_ats_dev *pdev =NULL ; +u32 value; +int pos; + + pos =pci_find_ext_capability (seg, bus, devfn,PCI_EXT_CAP_ID_ATS ); +BUG_ON (!pos); + +if ( iommu_verbose ) + dprintk(XENLOG_INFO VTDPREFIX, +"%04x:%02x:%02x.%u: ATS capability found\n" , + seg, bus,PCI_SLOT (devfn),PCI_FUNC (devfn)); + + value =pci_conf_read16 (seg, bus,PCI_SLOT (devfn), +PCI_FUNC (devfn), pos +ATS_REG_CTL ); +if ( value &ATS_ENABLE ) + { + list_for_each_entry ( pdev, &ats_devices, list ) + { +if ( pdev->seg == seg && pdev->bus == bus && pdev->devfn == devfn ) + { + pos =0 ; +break ; + } + } + } +if ( pos ) + pdev = xmalloc(struct pci_ats_dev); +if ( !pdev ) +return -ENOMEM ; + +if ( !(value &ATS_ENABLE ) ) + { + value |=ATS_ENABLE ; +pci_conf_write16 (seg, bus,PCI_SLOT (devfn),PCI_FUNC (devfn), + pos +ATS_REG_CTL , value); + } + +if ( pos ) + { + pdev->seg = seg; + pdev->bus = bus; + pdev->devfn = devfn; + value =pci_conf_read16 (seg, bus,PCI_SLOT (devfn), +PCI_FUNC (devfn), pos +ATS_REG_CAP ); + pdev->ats_queue_depth = value &ATS_QUEUE_DEPTH_MASK ; +list_add (&pdev->list, &ats_devices); + } + +if ( iommu_verbose ) + dprintk(XENLOG_INFO VTDPREFIX, +"%04x:%02x:%02x.%u: ATS %s enabled\n" , + seg, bus,PCI_SLOT (devfn),PCI_FUNC (devfn), + pos ?"is" :"was" ); + +return pos; +} + +void disable_ats_device (int seg,int bus,int devfn) +{ +struct pci_ats_dev *pdev; +u32 value; +int pos; + + pos =pci_find_ext_capability (seg, bus, devfn,PCI_EXT_CAP_ID_ATS ); +BUG_ON (!pos); + + value =pci_conf_read16 (seg, bus,PCI_SLOT (devfn), +PCI_FUNC (devfn), pos +ATS_REG_CTL ); + value &= ~ATS_ENABLE ; +pci_conf_write16 (seg, bus,PCI_SLOT (devfn),PCI_FUNC (devfn), + pos +ATS_REG_CTL , value); + + list_for_each_entry ( pdev, &ats_devices, list ) + { +if ( pdev->seg == seg && pdev->bus == bus && pdev->devfn == devfn ) + { +list_del (&pdev->list); +xfree (pdev); +break ; + } + } + +if ( iommu_verbose ) + dprintk(XENLOG_INFO VTDPREFIX, +"%04x:%02x:%02x.%u: ATS is disabled\n" , + seg, bus,PCI_SLOT (devfn),PCI_FUNC (devfn)); +}diff -r
121af976b298-r217c4a82b202xen/drivers/passthrough/x86/ats.hxen/drivers/passthrough/x86/ats.h new file +8
-0@@ -0,0 +1,38 @@ +/* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ */xen/drivers/passthrough/x86/ats.h new file +24
-0+ +#ifndef _X86_ATS_H_ +#define _X86_ATS_H_ + +#define ATS_REG_CAP 4 +#define ATS_REG_CTL 6 +#define ATS_QUEUE_DEPTH_MASK 0xF +#define ATS_ENABLE (1<<15) + +struct pci_ats_dev { +struct list_head list; +u16 seg; +u8 bus; +u8 devfn; +u16 ats_queue_depth;/* ATS device invalidation queue depth */ +}; + +extern struct list_head ats_devices; +extern bool_t ats_enabled; + +int enable_ats_device (int seg,int bus,int devfn); +void disable_ats_device (int seg,int bus,int devfn); + +#endif /* _X86_ATS_H_ */ _______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel
PATCH 1/1 ats: Remove VTD prefix from debug output
In reply to Wei Wang# HG changeset patch
# User Wei Wang <[email protected]>
# Date 1319472689 -7200
# Node ID 0d17087f9e495c1b9eb43bc0f6a21319097f3043 # Parent 217c4a82b202975c2fdff9ae499f065471e5c87b
ats: Remove VTD prefix from debug output.
xen/drivers/passthrough/x86/ats.c +4 -3
@@ -58,7 +58,7 @@ int enable_ats_device(int seg, int bus,BUG_ON (!pos);if ( iommu_verbose ) - dprintk(XENLOG_INFO VTDPREFIX, +dprintk (XENLOG_INFO ,"%04x:%02x:%02x.%u: ATS capability found\n" , seg, bus,PCI_SLOT (devfn),PCI_FUNC (devfn));
@@ -99,7 +99,7 @@ int enable_ats_device(int seg, int bus, }if ( iommu_verbose ) - dprintk(XENLOG_INFO VTDPREFIX, +dprintk (XENLOG_INFO ,"%04x:%02x:%02x.%u: ATS %s enabled\n" , seg, bus,PCI_SLOT (devfn),PCI_FUNC (devfn), pos ?"is" :"was" );
@@ -133,7 +133,8 @@ void disable_ats_device(int seg, int bus }if ( iommu_verbose ) - dprintk(XENLOG_INFO VTDPREFIX, +dprintk (XENLOG_INFO ,"%04x:%02x:%02x.%u: ATS is disabled\n" , seg, bus,PCI_SLOT (devfn),PCI_FUNC (devfn)); } +
Re: [PATCH 2 of 6] ats: Remove VTD prefix from debug output
Quoted 7 lines
Quoted 1 line
Quoted 1 line · Wei Wang
# HG changeset patch
# User Wei Wang <[email protected]>
# Date 1319472689 -7200
# Node ID0d17087f9e495c1b9eb43bc0f6a21319097f3043# Parent217c4a82b202975c2fdff9ae499f065471e5c87b
ats: Remove VTD prefix from debug output.
Personally I would prefer if you folded this into patch 1.
Jan
Quoted 39 lines
Signed-off-by Wei Wang <[email protected]>diff -r
217c4a82b202-r0d17087f9e49xen/drivers/passthrough/x86/ats.cxen/drivers/passthrough/x86/ats.c +4
-3@@ -58,7 +58,7 @@ int enable_ats_device(int seg, int bus,BUG_ON (!pos);if ( iommu_verbose ) - dprintk(XENLOG_INFO VTDPREFIX, +dprintk (XENLOG_INFO ,"%04x:%02x:%02x.%u: ATS capability found\n" , seg, bus,PCI_SLOT (devfn),PCI_FUNC (devfn));@@ -99,7 +99,7 @@ int enable_ats_device(int seg, int bus, }if ( iommu_verbose ) - dprintk(XENLOG_INFO VTDPREFIX, +dprintk (XENLOG_INFO ,"%04x:%02x:%02x.%u: ATS %s enabled\n" , seg, bus,PCI_SLOT (devfn),PCI_FUNC (devfn), pos ?"is" :"was" );@@ -133,7 +133,8 @@ void disable_ats_device(int seg, int bus }if ( iommu_verbose ) - dprintk(XENLOG_INFO VTDPREFIX, +dprintk (XENLOG_INFO ,"%04x:%02x:%02x.%u: ATS is disabled\n" , seg, bus,PCI_SLOT (devfn),PCI_FUNC (devfn)); } +_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel
PATCH 1/1 amd iommu: Fix iommu page size encoding when page order > 0
In reply to Wei Wang# HG changeset patch
# User Wei Wang <[email protected]>
# Date 1319472692 -7200
# Node ID 18088bd3e8f6c16b7aef3d8652f2b9878117fcd5 # Parent 0d17087f9e495c1b9eb43bc0f6a21319097f3043 amd iommu: Fix iommu page size encoding when page order > 0
xen/drivers/passthrough/amd/iommu_map.c +14 -13
@@ -77,23 +77,24 @@ static void invalidate_iommu_pages(struc {u64 addr_lo, addr_hi;u32 cmd[4 ], entry; -u64 mask =0 ;int sflag =0 , pde =0 ; +ASSERT ( order ==0 || order ==9 || order ==18 ); + +/* All pages associated with the domainID are invalidated */ +if ( order || (io_addr ==INV_IOMMU_ALL_PAGES_ADDRESS ) ) + { + sflag =1 ; + pde =1 ; + } +/* If sflag == 1, the size of the invalidate command is determined by the first zero bit in the address starting from Address[12] */ -if ( order ==9 || order ==18 ) +if ( order ) { - mask = ((1ULL << (order -1 )) -1 ) <<PAGE_SHIFT ; - io_addr |= mask; - sflag =1 ; - } - -/* All pages associated with the domainID are invalidated */ -else if ( io_addr ==0x7FFFFFFFFFFFF000ULL ) - { - sflag =1 ; - pde =1 ; +u64 mask =1ULL << (order -1 +PAGE_SHIFT ); + io_addr &= ~mask; + io_addr |= mask -1 ; } addr_lo = io_addr &DMA_32BIT_MASK ;
@@ -917,7 +918,7 @@ static void _amd_iommu_flush_pages(strucvoid amd_iommu_flush_all_pages (struct domain *d) { -_amd_iommu_flush_pages (d,0x7FFFFFFFFFFFFULL ,0 ); +_amd_iommu_flush_pages (d,INV_IOMMU_ALL_PAGES_ADDRESS ,0 ); } void amd_iommu_flush_pages(struct domain *d,
xen/include/asm-x86/hvm/svm/amd-iommu-defs.h +2 -0
@@ -407,4 +407,6 @@#define INT_REMAP_ENTRY_VECTOR_MASK 0x00FF0000#define INT_REMAP_ENTRY_VECTOR_SHIFT 16 +#define INV_IOMMU_ALL_PAGES_ADDRESS 0x7FFFFFFFFFFFFULL +#endif /* _ASM_X86_64_AMD_IOMMU_DEFS_H */
Re: [PATCH 3 of 6] amd iommu: Fix iommu page size encoding when page order > 0
Quoted 64 lines
Quoted 1 line
Quoted 1 line · Wei Wang
# HG changeset patch
# User Wei Wang <[email protected]>
# Date 1319472692 -7200
# Node ID18088bd3e8f6c16b7aef3d8652f2b9878117fcd5# Parent0d17087f9e495c1b9eb43bc0f6a21319097f3043amd iommu: Fix iommu page size encoding when page order > 0Signed-off-by Wei Wang <[email protected]>diff -r
0d17087f9e49-r18088bd3e8f6xen/drivers/passthrough/amd/iommu_map.cxen/drivers/passthrough/amd/iommu_map.c +14
-13@@ -77,23 +77,24 @@ static void invalidate_iommu_pages(struc {u64 addr_lo, addr_hi;u32 cmd[4 ], entry; -u64 mask =0 ;int sflag =0 , pde =0 ; +ASSERT ( order ==0 || order ==9 || order ==18 ); + +/* All pages associated with the domainID are invalidated */ +if ( order || (io_addr ==INV_IOMMU_ALL_PAGES_ADDRESS ) ) + { + sflag =1 ; + pde =1 ; + } +/* If sflag == 1, the size of the invalidate command is determined by the first zero bit in the address starting from Address[12] */ -if ( order ==9 || order ==18 ) +if ( order ) { - mask = ((1ULL << (order -1 )) -1 ) <<PAGE_SHIFT ; - io_addr |= mask; - sflag =1 ; - } - -/* All pages associated with the domainID are invalidated */ -else if ( io_addr ==0x7FFFFFFFFFFFF000ULL ) - { - sflag =1 ; - pde =1 ; +u64 mask =1ULL << (order -1 +PAGE_SHIFT ); + io_addr &= ~mask; + io_addr |= mask -1 ; } addr_lo = io_addr &DMA_32BIT_MASK ;@@ -917,7 +918,7 @@ static void _amd_iommu_flush_pages(strucvoid amd_iommu_flush_all_pages (struct domain *d) { -_amd_iommu_flush_pages (d,0x7FFFFFFFFFFFFULL ,0 ); +_amd_iommu_flush_pages (d,INV_IOMMU_ALL_PAGES_ADDRESS ,0 ); } void amd_iommu_flush_pages(struct domain *d,diff -r
0d17087f9e49-r18088bd3e8f6xen/include/asm-x86/hvm/svm/amd-iommu-defs.hxen/include/asm-x86/hvm/svm/amd-iommu-defs.h +1
-0+0200
xen/include/asm-x86/hvm/svm/amd-iommu-defs.h line 410
Quoted 4 lines
xen/include/asm-x86/hvm/svm/amd-iommu-defs.h +1
-0@@ -407,4 +407,6 @@#define INT_REMAP_ENTRY_VECTOR_MASK 0x00FF0000#define INT_REMAP_ENTRY_VECTOR_SHIFT 16 +#define INV_IOMMU_ALL_PAGES_ADDRESS 0x7FFFFFFFFFFFFULL
((1ULL << 51) - 1)
would make this much easier to understand. But - doe the IOMMU really have its limit at 51 bits (as opposed to the architectural limit of 52 in the CPU's MMU)?
Jan
Quoted 8 lines
xen/include/asm-x86/hvm/svm/amd-iommu-defs.h +1
-0+#endif /* _ASM_X86_64_AMD_IOMMU_DEFS_H */ _______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel
Re: [PATCH 3 of 6] amd iommu: Fix iommu page size encoding when page order > 0
Quoted 70 lines · On Wednesday 02 November 2011 14:46:24 Jan Beulich wrote:
Quoted 70 lines
Quoted 1 line
Quoted 1 line · Wei Wang
# HG changeset patch
# User Wei Wang <[email protected]>
# Date 1319472692 -7200
# Node ID18088bd3e8f6c16b7aef3d8652f2b9878117fcd5# Parent0d17087f9e495c1b9eb43bc0f6a21319097f3043amd iommu: Fix iommu page size encoding when page order > 0Signed-off-by Wei Wang <[email protected]>diff -r
0d17087f9e49-r18088bd3e8f6xen/drivers/passthrough/amd/iommu_map.c---a/xen/drivers/passthrough/amd/iommu_map.cMon Oct 24 18:11:29 2011 +0200
+++b/xen/drivers/passthrough/amd/iommu_map.cMon Oct 24 18:11:32 2011
+0200 @@ -77,23 +77,24 @@ static void invalidate_iommu_pages(struc{ u64 addr_lo, addr_hi; u32 cmd[4], entry;xen/drivers/passthrough/amd/iommu_map.c +14
-13-u64 mask =0 ;int sflag =0 , pde =0 ; +ASSERT ( order ==0 || order ==9 || order ==18 ); + +/* All pages associated with the domainID are invalidated */ +if ( order || (io_addr ==INV_IOMMU_ALL_PAGES_ADDRESS ) ) + { + sflag =1 ; + pde =1 ; + } +/* If sflag == 1, the size of the invalidate command is determined by the first zero bit in the address starting from Address[12] */ -if ( order ==9 || order ==18 ) +if ( order ) { - mask = ((1ULL << (order -1 )) -1 ) <<PAGE_SHIFT ; - io_addr |= mask; - sflag =1 ; - } - -/* All pages associated with the domainID are invalidated */ -else if ( io_addr ==0x7FFFFFFFFFFFF000ULL ) - { - sflag =1 ; - pde =1 ; +u64 mask =1ULL << (order -1 +PAGE_SHIFT ); + io_addr &= ~mask; + io_addr |= mask -1 ; } addr_lo = io_addr &DMA_32BIT_MASK ;@@ -917,7 +918,7 @@ static void _amd_iommu_flush_pages(strucvoid amd_iommu_flush_all_pages (struct domain *d) { -_amd_iommu_flush_pages (d,0x7FFFFFFFFFFFFULL ,0 ); +_amd_iommu_flush_pages (d,INV_IOMMU_ALL_PAGES_ADDRESS ,0 ); } void amd_iommu_flush_pages(struct domain *d,diff -r
0d17087f9e49-r18088bd3e8f6xen/include/asm-x86/hvm/svm/amd-iommu-defs.h---a/xen/include/asm-x86/hvm/svm/amd-iommu-defs.hMon Oct 24 18:11:29 2011
+0200 +++b/xen/include/asm-x86/hvm/svm/amd-iommu-defs.hMon Oct 24
18:11:32 2011 +0200xen/include/asm-x86/hvm/svm/amd-iommu-defs.h +0
-0@@ -407,4 +407,6 @@#define INT_REMAP_ENTRY_VECTOR_MASK 0x00FF0000#define INT_REMAP_ENTRY_VECTOR_SHIFT 16
Quoted 7 lines
xen/include/asm-x86/hvm/svm/amd-iommu-defs.h line 410
Quoted 1 line
xen/include/asm-x86/hvm/svm/amd-iommu-defs.h +1
-0+#define INV_IOMMU_ALL_PAGES_ADDRESS 0x7FFFFFFFFFFFFULL((1ULL << 51) - 1)
would make this much easier to understand. But - doe the IOMMU really have its limit at 51 bits (as opposed to the architectural limit of 52 in the CPU's MMU)?
Maybe the name is confusing. Actually it is a special frame number not an address. Bit 63 = 0 indicates all page frames should be invalidated. Or I should use INV_IOMMU_ALL_PAGES_PFN instead. Anyway, I will fix that in the next version. Thanks for all your comments. Other issues will also be fixed in the new version.
Thanks,
Wei
Quoted 10 lines
Jan
Quoted 8 lines
xen/include/asm-x86/hvm/svm/amd-iommu-defs.h +1
-0+#endif /* _ASM_X86_64_AMD_IOMMU_DEFS_H */ _______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel
Re: [PATCH 3 of 6] amd iommu: Fix iommu page size encoding when page order > 0
Quoted 76 lines
Quoted 1 line
Quoted 1 line · On 02.11.11 at 15:52, Wei Wang2 <[email protected]> wrote:
Quoted 74 lines · On Wednesday 02 November 2011 14:46:24 Jan Beulich wrote:
Quoted 67 lines
Quoted 1 line
Quoted 1 line · Wei Wang
# HG changeset patch
# User Wei Wang <[email protected]>
# Date 1319472692 -7200
# Node ID18088bd3e8f6c16b7aef3d8652f2b9878117fcd5# Parent0d17087f9e495c1b9eb43bc0f6a21319097f3043amd iommu: Fix iommu page size encoding when page order > 0Signed-off-by Wei Wang <[email protected]>diff -r
0d17087f9e49-r18088bd3e8f6xen/drivers/passthrough/amd/iommu_map.c---a/xen/drivers/passthrough/amd/iommu_map.cMon Oct 24 18:11:29 2011 +0200
+++b/xen/drivers/passthrough/amd/iommu_map.cMon Oct 24 18:11:32 2011
+0200 @@ -77,23 +77,24 @@ static void invalidate_iommu_pages(struc{ u64 addr_lo, addr_hi; u32 cmd[4], entry;xen/drivers/passthrough/amd/iommu_map.c +14
-13-u64 mask =0 ;int sflag =0 , pde =0 ; +ASSERT ( order ==0 || order ==9 || order ==18 ); + +/* All pages associated with the domainID are invalidated */ +if ( order || (io_addr ==INV_IOMMU_ALL_PAGES_ADDRESS ) ) + { + sflag =1 ; + pde =1 ; + } +/* If sflag == 1, the size of the invalidate command is determined by the first zero bit in the address starting from Address[12] */ -if ( order ==9 || order ==18 ) +if ( order ) { - mask = ((1ULL << (order -1 )) -1 ) <<PAGE_SHIFT ; - io_addr |= mask; - sflag =1 ; - } - -/* All pages associated with the domainID are invalidated */ -else if ( io_addr ==0x7FFFFFFFFFFFF000ULL ) - { - sflag =1 ; - pde =1 ; +u64 mask =1ULL << (order -1 +PAGE_SHIFT ); + io_addr &= ~mask; + io_addr |= mask -1 ; } addr_lo = io_addr &DMA_32BIT_MASK ;@@ -917,7 +918,7 @@ static void _amd_iommu_flush_pages(strucvoid amd_iommu_flush_all_pages (struct domain *d) { -_amd_iommu_flush_pages (d,0x7FFFFFFFFFFFFULL ,0 ); +_amd_iommu_flush_pages (d,INV_IOMMU_ALL_PAGES_ADDRESS ,0 ); } void amd_iommu_flush_pages(struct domain *d,diff -r
0d17087f9e49-r18088bd3e8f6xen/include/asm-x86/hvm/svm/amd-iommu-defs.h---a/xen/include/asm-x86/hvm/svm/amd-iommu-defs.hMon Oct 24 18:11:29 2011
+0200 +++b/xen/include/asm-x86/hvm/svm/amd-iommu-defs.hMon Oct 24
18:11:32 2011 +0200xen/include/asm-x86/hvm/svm/amd-iommu-defs.h line 410
Quoted 4 lines
xen/include/asm-x86/hvm/svm/amd-iommu-defs.h +1
-0@@ -407,4 +407,6 @@#define INT_REMAP_ENTRY_VECTOR_MASK 0x00FF0000#define INT_REMAP_ENTRY_VECTOR_SHIFT 16 +#define INV_IOMMU_ALL_PAGES_ADDRESS 0x7FFFFFFFFFFFFULL((1ULL << 51) - 1)
Quoted 7 lines
Quoted 3 lines
would make this much easier to understand. But - doe the IOMMU really have its limit at 51 bits (as opposed to the architectural limit of 52 in the CPU's MMU)?
Maybe the name is confusing. Actually it is a special frame number not an address. Bit 63 = 0 indicates all page frames should be invalidated. Or I should use
INV_IOMMU_ALL_PAGES_PFNinstead. Anyway, I will fix that in the
Yes, if this is a PFN, then the name should say so. And then it becomes all the more relevant to express this as a decremented shift expression (as it depends on PAGE_SHIFT).
Jan
Quoted 15 lines
next version. Thanks for all your comments. Other issues will also be fixed in the new version.
Thanks,
WeiQuoted 10 lines
Jan
Quoted 8 lines
xen/include/asm-x86/hvm/svm/amd-iommu-defs.h +1
-0+#endif /* _ASM_X86_64_AMD_IOMMU_DEFS_H */ _______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel
PATCH 1/1 ats: Add new ATS helper functions
In reply to Wei Wang# HG changeset patch
# User Wei Wang <[email protected]>
# Date 1319472696 -7200
# Node ID 3dc5e805d9142cbe1074610879e258b6fab43409 # Parent 18088bd3e8f6c16b7aef3d8652f2b9878117fcd5
ats: Add new ATS helper functions
Signed-off-by Wei Wang <[email protected]>
xen/drivers/passthrough/x86/ats.c +39 -0
@@ -138,3 +138,42 @@ void disable_ats_device(int seg, int bus seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); } +int pci_ats_enabled (int seg,int bus,int devfn) +{ +u32 value; +int pos; + + pos =pci_find_ext_capability (seg, bus, devfn,PCI_EXT_CAP_ID_ATS ); +BUG_ON (!pos); + + value =pci_conf_read16 (seg, bus,PCI_SLOT (devfn), +PCI_FUNC (devfn), pos +ATS_REG_CTL ); +return value &ATS_ENABLE ; +} + +int pci_ats_device (int seg,int bus,int devfn) +{ +if ( !ats_enabled ) +return 0 ; + +if ( !pci_find_ext_capability (seg, bus, devfn,PCI_EXT_CAP_ID_ATS ) ) +return 0 ; + +return 1 ; +} + +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 == seg && pdev->bus == bus && pdev->devfn == devfn ) +return pdev; + } + +return NULL ; +}
xen/drivers/passthrough/x86/ats.h +3 -0
@@ -34,5 +34,8 @@ extern bool_t ats_enabled;int enable_ats_device (int seg,int bus,int devfn);void disable_ats_device (int seg,int bus,int devfn); +int pci_ats_enabled (int seg,int bus,int devfn); +int pci_ats_device (int seg,int bus,int devfn); +struct pci_ats_dev *get_ats_device (int seg,int bus,int devfn);#endif /* _X86_ATS_H_ */
Re: [PATCH 4 of 6] ats: Add new ATS helper functions
Quoted 30 lines
Quoted 1 line
Quoted 1 line · Wei Wang
# HG changeset patch
# User Wei Wang <[email protected]>
# Date 1319472696 -7200
# Node ID3dc5e805d9142cbe1074610879e258b6fab43409# Parent18088bd3e8f6c16b7aef3d8652f2b9878117fcd5
ats: Add new ATS helper functionsSigned-off-by Wei Wang <[email protected]>
diff -r
18088bd3e8f6-r3dc5e805d914xen/drivers/passthrough/x86/ats.cxen/drivers/passthrough/x86/ats.c +13
-0@@ -138,3 +138,42 @@ void disable_ats_device(int seg, int bus seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); } +int pci_ats_enabled (int seg,int bus,int devfn) +{ +u32 value; +int pos; + + pos =pci_find_ext_capability (seg, bus, devfn,PCI_EXT_CAP_ID_ATS ); +BUG_ON (!pos); + + value =pci_conf_read16 (seg, bus,PCI_SLOT (devfn), +PCI_FUNC (devfn), pos +ATS_REG_CTL ); +return value &ATS_ENABLE ; +} +
xen/drivers/passthrough/x86/ats.c void disable_ats_device(int seg, int bus · line 163
Quoted 10 lines
xen/drivers/passthrough/x86/ats.c +10
-0+int pci_ats_device (int seg,int bus,int devfn) +{ +if ( !ats_enabled ) +return 0 ; + +if ( !pci_find_ext_capability (seg, bus, devfn,PCI_EXT_CAP_ID_ATS ) ) +return 0 ; + +return 1 ; +}
At least this one would certainly be a candidate for inlining.
xen/drivers/passthrough/x86/ats.c void disable_ats_device(int seg, int bus · line 165
Quoted 2 lines
xen/drivers/passthrough/x86/ats.c +2
-0+ +struct pci_ats_dev *get_ats_device (int seg,int bus,int devfn)
Formatting (asterisk and space should switch places).
Quoted 18 lines
xen/drivers/passthrough/x86/ats.c +14
-0+{ +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 == seg && pdev->bus == bus && pdev->devfn == devfn ) +return pdev; + } + +return NULL ; +}diff -r
18088bd3e8f6-r3dc5e805d914xen/drivers/passthrough/x86/ats.h
xen/drivers/passthrough/x86/ats.h extern bool_t ats_enabled; · line 39
Quoted 6 lines
xen/drivers/passthrough/x86/ats.h +3
-0@@ -34,5 +34,8 @@ extern bool_t ats_enabled;int enable_ats_device (int seg,int bus,int devfn);void disable_ats_device (int seg,int bus,int devfn); +int pci_ats_enabled (int seg,int bus,int devfn); +int pci_ats_device (int seg,int bus,int devfn); +struct pci_ats_dev *get_ats_device (int seg,int bus,int devfn);
Formatting again.
Jan
Quoted 8 lines
xen/drivers/passthrough/x86/ats.h +0
-0#endif /* _X86_ATS_H_ */ _______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel
PATCH 1/1 amd iommu: add iotlb invalidation command
In reply to Wei Wang# HG changeset patch
# User Wei Wang <[email protected]>
# Date 1319472700 -7200
# Node ID 8ec947b278afaf89acadf905237c95ba7b64524a # Parent 3dc5e805d9142cbe1074610879e258b6fab43409 amd iommu: add iotlb invalidation command
xen/drivers/passthrough/amd/iommu_map.c +129 -0
@@ -23,6 +23,7 @@#include <xen/hvm/iommu.h> #include <asm/amd-iommu.h> #include <asm/hvm/svm/amd-iommu-proto.h> +#include "../x86/ats.h" static int queue_iommu_command (struct amd_iommu *iommu,u32 cmd[]) {
@@ -128,6 +129,75 @@ static void invalidate_iommu_pages(strucsend_iommu_command (iommu, cmd); } +static void invalidate_iotlb_pages (struct amd_iommu *iommu, +u16 maxpend,u32 pasid,u16 queueid, +u64 io_addr,u16 dev_id,u16 order) +{ +u64 addr_lo, addr_hi; +u32 cmd[4 ], entry; +int sflag =0 ; + +ASSERT ( order ==0 || order ==9 || order ==18 ); + +if ( order || (io_addr ==INV_IOMMU_ALL_PAGES_ADDRESS ) ) + sflag =1 ; + +/* If sflag == 1, the size of the invalidate command is determined +by the first zero bit in the address starting from Address[12] */ +if ( order ) + { +u64 mask =1ULL << (order -1 +PAGE_SHIFT ); + io_addr &= ~mask; + io_addr |= mask -1 ; + } + + addr_lo = io_addr &DMA_32BIT_MASK ; + addr_hi = io_addr >>32 ; + +set_field_in_reg_u32 (dev_id,0 , +IOMMU_INV_IOTLB_PAGES_DEVICE_ID_MASK , +IOMMU_INV_IOTLB_PAGES_DEVICE_ID_SHIFT , &entry); + +set_field_in_reg_u32 (maxpend, entry, +IOMMU_INV_IOTLB_PAGES_MAXPEND_MASK , +IOMMU_INV_IOTLB_PAGES_MAXPEND_SHIFT , &entry); + +set_field_in_reg_u32 (pasid &0xff , entry, +IOMMU_INV_IOTLB_PAGES_PASID1_MASK , +IOMMU_INV_IOTLB_PAGES_PASID1_SHIFT , &entry); + cmd[0 ] = entry; + +set_field_in_reg_u32 (IOMMU_CMD_INVALIDATE_IOTLB_PAGES ,0 , +IOMMU_CMD_OPCODE_MASK ,IOMMU_CMD_OPCODE_SHIFT , + &entry); + +set_field_in_reg_u32 (pasid >>8 , entry, +IOMMU_INV_IOTLB_PAGES_PASID2_MASK , +IOMMU_INV_IOTLB_PAGES_PASID2_SHIFT , + &entry); + +set_field_in_reg_u32 (queueid, entry, +IOMMU_INV_IOTLB_PAGES_QUEUEID_MASK , +IOMMU_INV_IOTLB_PAGES_QUEUEID_SHIFT , + &entry); + cmd[1 ] = entry; + +set_field_in_reg_u32 (sflag,0 , +IOMMU_INV_IOTLB_PAGES_S_FLAG_MASK , +IOMMU_INV_IOTLB_PAGES_S_FLAG_MASK , &entry); + +set_field_in_reg_u32 ((u32 )addr_lo >>PAGE_SHIFT , entry, +IOMMU_INV_IOTLB_PAGES_ADDR_LOW_MASK , +IOMMU_INV_IOTLB_PAGES_ADDR_LOW_SHIFT , &entry); + cmd[2 ] = entry; + +set_field_in_reg_u32 ((u32 )addr_hi,0 , +IOMMU_INV_IOTLB_PAGES_ADDR_HIGH_MASK , +IOMMU_INV_IOTLB_PAGES_ADDR_HIGH_SHIFT , &entry); + cmd[3 ] = entry; + +send_iommu_command (iommu, cmd); +}void flush_command_buffer (struct amd_iommu *iommu) {u32 cmd[4 ], status;
@@ -896,6 +966,62 @@ int amd_iommu_reserve_domain_unity_map(sreturn 0 ; } +void amd_iommu_flush_iotlb (struct pci_dev *pdev, +uint64_t gaddr,unsigned int order) +{ +unsigned long flags; +struct amd_iommu *iommu; +unsigned int bdf, req_id, queueid, maxpend; +struct pci_ats_dev *ats_pdev; + +if ( !ats_enabled ) +return ; + + ats_pdev =get_ats_device (pdev->seg, pdev->bus, pdev->devfn); +if ( ats_pdev ==NULL ) +return ; +if ( !pci_ats_enabled (ats_pdev->seg, + ats_pdev->bus, ats_pdev->devfn) ) +return ; + + bdf = (ats_pdev->bus <<8 ) | ats_pdev->devfn; + iommu =find_iommu_for_device (ats_pdev->seg, bdf); + +if ( !iommu ) + { +AMD_IOMMU_DEBUG ("%s: Fail to find iommu for device %04x:%02x:%02x.%u\n" , + __func__, ats_pdev->seg, ats_pdev->bus, +PCI_SLOT (ats_pdev->devfn), +PCI_FUNC (ats_pdev->devfn)); +return ; + } + +if ( !iommu->iotlb_support ) +return ; + + req_id =get_dma_requestor_id (iommu->seg, bdf); + queueid = req_id; + maxpend = (ats_pdev->ats_queue_depth +32 ) &0xff ; + +/* send INVALIDATE_IOTLB_PAGES command */ +spin_lock_irqsave (&iommu->lock, flags); +invalidate_iotlb_pages (iommu, maxpend,0 , queueid, + gaddr, req_id, order); +flush_command_buffer (iommu); +spin_unlock_irqrestore (&iommu->lock, flags); +} + +void amd_iommu_flush_all_iotlbs (struct domain *d, +uint64_t gaddr,unsigned int order) +{ +struct pci_dev *pdev; + +if ( !ats_enabled ) +return ; + +for_each_pdev ( d, pdev ) +amd_iommu_flush_iotlb (pdev, gaddr, order); +}/* Flush iommu cache after p2m changes. */ static void _amd_iommu_flush_pages(struct domain *d,
@@ -914,6 +1040,9 @@ static void _amd_iommu_flush_pages(strucflush_command_buffer (iommu);spin_unlock_irqrestore (&iommu->lock, flags); } + +if ( ats_enabled ) +amd_iommu_flush_all_iotlbs (d, gaddr, order); }void amd_iommu_flush_all_pages (struct domain *d)
xen/include/asm-x86/hvm/svm/amd-iommu-defs.h +18 -0
@@ -233,6 +233,24 @@#define IOMMU_INV_INT_TABLE_DEVICE_ID_MASK 0x0000FFFF#define IOMMU_INV_INT_TABLE_DEVICE_ID_SHIFT 0 +/* INVALIDATE_IOTLB_PAGES command */ +#define IOMMU_INV_IOTLB_PAGES_MAXPEND_MASK 0xff000000 +#define IOMMU_INV_IOTLB_PAGES_MAXPEND_SHIFT 24 +#define IOMMU_INV_IOTLB_PAGES_PASID1_MASK 0x00ff0000 +#define IOMMU_INV_IOTLB_PAGES_PASID1_SHIFT 16 +#define IOMMU_INV_IOTLB_PAGES_PASID2_MASK 0x0fff0000 +#define IOMMU_INV_IOTLB_PAGES_PASID2_SHIFT 16 +#define IOMMU_INV_IOTLB_PAGES_QUEUEID_MASK 0x0000ffff +#define IOMMU_INV_IOTLB_PAGES_QUEUEID_SHIFT 0 +#define IOMMU_INV_IOTLB_PAGES_DEVICE_ID_MASK 0x0000FFFF +#define IOMMU_INV_IOTLB_PAGES_DEVICE_ID_SHIFT 0 +#define IOMMU_INV_IOTLB_PAGES_ADDR_LOW_MASK 0xFFFFF000 +#define IOMMU_INV_IOTLB_PAGES_ADDR_LOW_SHIFT 12 +#define IOMMU_INV_IOTLB_PAGES_ADDR_HIGH_MASK 0xFFFFFFFF +#define IOMMU_INV_IOTLB_PAGES_ADDR_HIGH_SHIFT 0 +#define IOMMU_INV_IOTLB_PAGES_S_FLAG_MASK 0x00000001 +#define IOMMU_INV_IOTLB_PAGES_S_FLAG_SHIFT 0 +/* Event Log */ #define IOMMU_EVENT_LOG_BASE_LOW_OFFSET 0x10#define IOMMU_EVENT_LOG_BASE_HIGH_OFFSET 0x14
xen/include/asm-x86/hvm/svm/amd-iommu-proto.h +2 -0
@@ -55,6 +55,8 @@ int amd_iommu_unmap_page(struct domain *void amd_iommu_flush_pages (struct domain *d,unsigned long gfn,unsigned int order);void amd_iommu_flush_all_pages (struct domain *d); +void amd_iommu_flush_iotlb (struct pci_dev *pdev, +uint64_t gaddr,unsigned int order);u64 amd_iommu_get_next_table_from_pte (u32 *entry); int amd_iommu_reserve_domain_unity_map(struct domain *domain,
PATCH 1/1 amd iommu: enable ats devices
In reply to Wei Wang# HG changeset patch
# User Wei Wang <[email protected]>
# Date 1319472702 -7200
# Node ID b84967db0efb875bca4d95f47fc77b46cd065665 # Parent 8ec947b278afaf89acadf905237c95ba7b64524a amd iommu: enable ats devices
xen/drivers/passthrough/amd/iommu_map.c +11 -0
@@ -369,6 +369,17 @@ void amd_iommu_set_root_page_table( dte[0 ] = entry; } +void iommu_dte_set_iotlb (u32 *dte,u8 i) +{ +u32 entry; + + entry = dte[3 ]; +set_field_in_reg_u32 (!!i, entry, +IOMMU_DEV_TABLE_IOTLB_SUPPORT_MASK , +IOMMU_DEV_TABLE_IOTLB_SUPPORT_SHIFT , &entry); + dte[3 ] = entry; +} +void __init amd_iommu_set_intremap_table (u32 *dte,u64 intremap_ptr,u8 int_valid) {
xen/drivers/passthrough/amd/pci_amd_iommu.c +47 -10
146 lines not on this page · raw message
xen/include/asm-x86/hvm/svm/amd-iommu-proto.h +1 -0
@@ -75,6 +75,7 @@ void amd_iommu_set_intremap_table( u32 *dte, u64 intremap_ptr, u8 int_valid);void amd_iommu_set_root_page_table (u32 *dte,u64 root_ptr,u16 domain_id,u8 paging_mode,u8 valid); +void iommu_dte_set_iotlb (u32 *dte,u8 i);void invalidate_dev_table_entry (struct amd_iommu *iommu,u16 devic_id);/* send cmd to iommu */
Re: [PATCH 6 of 6] amd iommu: enable ats devices
Quoted 82 lines
Quoted 1 line
Quoted 1 line · Wei Wang
# HG changeset patch
# User Wei Wang <[email protected]>
# Date 1319472702 -7200
# Node IDb84967db0efb875bca4d95f47fc77b46cd065665# Parent8ec947b278afaf89acadf905237c95ba7b64524aamd iommu: enable ats devicesSigned-off-by Wei Wang <[email protected]diff -r
8ec947b278af-rb84967db0efbxen/drivers/passthrough/amd/iommu_map.cxen/drivers/passthrough/amd/iommu_map.c +11
-0@@ -369,6 +369,17 @@ void amd_iommu_set_root_page_table( dte[0 ] = entry; } +void iommu_dte_set_iotlb (u32 *dte,u8 i) +{ +u32 entry; + + entry = dte[3 ]; +set_field_in_reg_u32 (!!i, entry, +IOMMU_DEV_TABLE_IOTLB_SUPPORT_MASK , +IOMMU_DEV_TABLE_IOTLB_SUPPORT_SHIFT , &entry); + dte[3 ] = entry; +} +void __init amd_iommu_set_intremap_table (u32 *dte,u64 intremap_ptr,u8 int_valid) {diff -r
8ec947b278af-rb84967db0efbxen/drivers/passthrough/amd/pci_amd_iommu.cxen/drivers/passthrough/amd/pci_amd_iommu.c +11
-2+0200 @@ -25,6 +25,7 @@#include <asm/hvm/iommu.h> #include <asm/amd-iommu.h> #include <asm/hvm/svm/amd-iommu-proto.h> +#include "../x86/ats.h" struct amd_iommu *find_iommu_for_device (int seg,int bdf) {@@ -81,11 +82,12 @@ static void disable_translation(u32 *dte }static void amd_iommu_setup_domain_device ( -struct domain *domain,struct amd_iommu *iommu,int bdf) +struct domain *domain,struct amd_iommu *iommu,u8 bus,u8 devfn) {void *dte;unsigned long flags;int req_id, valid =1 ; +int dte_i =0 ;struct hvm_iommu *hd =domain_hvm_iommu (domain);@@ -94,8 +96,11 @@ static void amd_iommu_setup_domain_devicif ( iommu_passthrough && (domain->domain_id ==0 ) ) valid =0 ; +if ( ats_enabled ) + dte_i =1 ; +/* get device-table entry */ - req_id =get_dma_requestor_id (iommu->seg, bdf); + req_id =get_dma_requestor_id (iommu->seg, (bus <<8 ) | devfn); dte = iommu->dev_table.buffer + (req_id *IOMMU_DEV_TABLE_ENTRY_SIZE );spin_lock_irqsave (&iommu->lock, flags);@@ -107,6 +112,9 @@ static void amd_iommu_setup_domain_devic (u32 *)dte,page_to_maddr (hd->root_table), hd->domain_id, hd->paging_mode, valid); +if (pci_ats_device (iommu->seg, bus, devfn) && iommu->iotlb_support ) +iommu_dte_set_iotlb ((u32 *)dte, dte_i); +invalidate_dev_table_entry (iommu, req_id);flush_command_buffer (iommu);
xen/drivers/passthrough/amd/pci_amd_iommu.c static void amd_iommu_setup_domain_devic · line 132
Quoted 7 lines
xen/drivers/passthrough/amd/pci_amd_iommu.c +4
-0@@ -118,6 +126,21 @@ static void amd_iommu_setup_domain_devic }spin_unlock_irqrestore (&iommu->lock, flags); + +ASSERT (spin_is_locked (&pcidevs_lock)); + + if ( pci_ats_device(iommu->seg, bus, devfn) && ats_enabled &&
Iirc pci_ats_device() returning non-zero already implies ats_enabled.
xen/drivers/passthrough/amd/pci_amd_iommu.c static void amd_iommu_setup_domain_devic · line 135
Quoted 3 lines
xen/drivers/passthrough/amd/pci_amd_iommu.c +3
-0+ !pci_ats_enabled(iommu->seg, bus, devfn) ) + { +struct pci_dev * pdev;
Formatting (need a newline here, plus asterisk and space again should switch places).
xen/drivers/passthrough/amd/pci_amd_iommu.c static void amd_iommu_setup_domain_devic · line 141
Quoted 6 lines
xen/drivers/passthrough/amd/pci_amd_iommu.c +6
-0+enable_ats_device (iommu->seg, bus, devfn); + +ASSERT (spin_is_locked (&pcidevs_lock)); + pdev =pci_get_pdev (iommu->seg, bus, devfn); + +if ( pdev )
Is it actually possible/valid for pdev to be NULL here? If not, you'd want ASSERT()/BUG_ON() instead of if() here.
Quoted 16 lines
xen/drivers/passthrough/amd/pci_amd_iommu.c +4
-1+amd_iommu_flush_iotlb (pdev,INV_IOMMU_ALL_PAGES_ADDRESS ,0 ); + } }static void __init amd_iommu_setup_dom0_device (struct pci_dev *pdev)@@ -126,7 +149,8 @@ static void __init amd_iommu_setup_dom0_struct amd_iommu *iommu =find_iommu_for_device (pdev->seg, bdf);if (likely (iommu !=NULL ) ) -amd_iommu_setup_domain_device (pdev->domain, iommu, bdf); +amd_iommu_setup_domain_device (pdev->domain, iommu, pdev->bus, + pdev->devfn);else AMD_IOMMU_DEBUG("No iommu for device %04x:%02x:%02x.%u\n", pdev->seg, pdev->bus,
xen/drivers/passthrough/amd/pci_amd_iommu.c static void __init amd_iommu_dom0_init(s · line 289
Quoted 7 lines
xen/drivers/passthrough/amd/pci_amd_iommu.c +2
-2@@ -261,21 +285,26 @@ static void __init amd_iommu_dom0_init(ssetup_dom0_pci_devices (d, amd_iommu_setup_dom0_device); } -static void amd_iommu_disable_domain_device ( -struct domain *domain,struct amd_iommu *iommu,int bdf) +void amd_iommu_disable_domain_device (struct domain *domain, +struct amd_iommu *iommu,u8 bus,u8 devfn)
If you really want to do this, then ...
xen/drivers/passthrough/amd/pci_amd_iommu.c static void __init amd_iommu_dom0_init(s · line 297
Quoted 9 lines
xen/drivers/passthrough/amd/pci_amd_iommu.c +2
-1{void *dte;unsigned long flags;int req_id;BUG_ON ( iommu->dev_table.buffer ==NULL ); - req_id =get_dma_requestor_id (iommu->seg, bdf); + + req_id =get_dma_requestor_id (iommu->seg, (bus <<8 ) | devfn);
... you want to use PCI_BDF2() here.
Quoted 14 lines
xen/drivers/passthrough/amd/pci_amd_iommu.c +4
-0dte = iommu->dev_table.buffer + (req_id *IOMMU_DEV_TABLE_ENTRY_SIZE );spin_lock_irqsave (&iommu->lock, flags);if (is_translation_valid ((u32 *)dte) ) {disable_translation ((u32 *)dte); + +if (pci_ats_device (iommu->seg, bus, devfn) && iommu->iotlb_support ) +iommu_dte_set_iotlb ((u32 *)dte,0 ); +invalidate_dev_table_entry (iommu, req_id);flush_command_buffer (iommu); AMD_IOMMU_DEBUG("Disable: device id = 0x%04x, "
xen/drivers/passthrough/amd/pci_amd_iommu.c static void amd_iommu_disable_domain_dev · line 319
Quoted 7 lines
xen/drivers/passthrough/amd/pci_amd_iommu.c +4
-0@@ -284,6 +313,12 @@ static void amd_iommu_disable_domain_dev domain_hvm_iommu(domain)->paging_mode); }spin_unlock_irqrestore (&iommu->lock, flags); + +ASSERT (spin_is_locked (&pcidevs_lock)); + + if ( pci_ats_device(iommu->seg, bus, devfn) && ats_enabled &&
See above.
Quoted 56 lines
xen/drivers/passthrough/amd/pci_amd_iommu.c +8
-4+ pci_ats_enabled(iommu->seg, bus, devfn) ) +disable_ats_device (iommu->seg, bus, devfn); } static int reassign_device( struct domain *source, struct domain *target,@@ -310,7 +345,7 @@ static int reassign_device( struct domaireturn -ENODEV ; } -amd_iommu_disable_domain_device (source, iommu, bdf); +amd_iommu_disable_domain_device (source, iommu, bus, devfn);list_move (&pdev->domain_list, &target->arch.pdev_list); pdev->domain = target;@@ -320,7 +355,7 @@ static int reassign_device( struct domaiif ( t->root_table ==NULL )allocate_domain_resources (t); -amd_iommu_setup_domain_device (target, iommu, bdf); +amd_iommu_setup_domain_device (target, iommu, bus, devfn);AMD_IOMMU_DEBUG ("Re-assign %04x:%02x:%02x.%u from dom%d to dom%d\n" , seg, bus,PCI_SLOT (devfn),PCI_FUNC (devfn), source->domain_id, target->domain_id);@@ -432,7 +467,8 @@ static int amd_iommu_add_device(struct preturn -ENODEV ; } -amd_iommu_setup_domain_device (pdev->domain, iommu, bdf); +amd_iommu_setup_domain_device (pdev->domain, iommu, + pdev->bus, pdev->devfn);return 0 ; }@@ -454,7 +490,8 @@ static int amd_iommu_remove_device(strucreturn -ENODEV ; } -amd_iommu_disable_domain_device (pdev->domain, iommu, bdf); +amd_iommu_disable_domain_device (pdev->domain, iommu, + pdev->bus, pdev->devfn);return 0 ; }diff -r
8ec947b278af-rb84967db0efbxen/include/asm-x86/hvm/svm/amd-iommu-proto.hxen/include/asm-x86/hvm/svm/amd-iommu-proto.h +2
-0+0200 @@ -75,6 +75,7 @@ void amd_iommu_set_intremap_table( u32 *dte, u64 intremap_ptr, u8 int_valid);void amd_iommu_set_root_page_table (u32 *dte,u64 root_ptr,u16 domain_id,u8 paging_mode,u8 valid); +void iommu_dte_set_iotlb (u32 *dte,u8 i);void invalidate_dev_table_entry (struct amd_iommu *iommu,u16 devic_id);/* send cmd to iommu */