amd iommu: Add ATS support (v4)
PATCH 1/1 amd iommu: Add ATS support (v4)
Hi Jan,
Please see the version 4. Fixed issues from last version. Build test passed on both 32 and 64 bit systems.
This patch set enables ats devices on amd systems with following changes:
1) Make vendor independent ATS codes more public.
2) Add additional helper functions for ats.
3) Add amd specific enablement.
Thanks,
Wei
PATCH 1/1 ats: Move some ats functions to a new directory
# HG changeset patch
# User Wei Wang <[email protected]>
# Date 1320334551 -3600
# Node ID ef46c471a11f83d07e256ad2e0b868828f45ef63
# Parent 119bccb1cc5eee1364bbbd3bd1a30f22e9db703a
ats: Move some ats functions to a new directory. Remove VTD prefix from debug output.
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_64) += x86 obj-y += iommu.o obj-y += io.o
xen/drivers/passthrough/ats.h new file +56 -0
56 lines not on this page · raw message
xen/drivers/passthrough/vtd/extern.h +0 -14
@@ -57,18 +57,13 @@ 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 (const struct pci_dev *,const struct acpi_drhd_unit *); -int enable_ats_device (int seg,int bus,int devfn); -void disable_ats_device (int seg,int bus,int devfn);int dev_invalidate_iotlb (struct iommu *iommu,u16 did,u64 addr,unsigned int size_order,u64 type);#else -#define ats_enabled 0static inline struct acpi_drhd_unit *find_ats_dev_drhd (struct iommu *iommu) {
@@ -80,15 +75,6 @@ static inline int ats_device(const struc {return 0 ; } -static inline int enable_ats_device (int seg,int bus,int devfn) -{ -BUG (); -return -ENOSYS ; -} -static inline void disable_ats_device (int seg,int bus,int devfn) -{ -BUG (); -}static inline int dev_invalidate_iotlb (struct iommu *iommu,u16 did,u64 addr,unsigned int size_order,u64 type)
xen/drivers/passthrough/vtd/iommu.c +1 -0
@@ -40,6 +40,7 @@#include "dmar.h" #include "extern.h" #include "vtd.h" +#include "../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-$(CONFIG_X86_64) += ats.o
xen/drivers/passthrough/x86/ats.c new file +136 -0
136 lines not on this page · raw message
Re: [PATCH 1 of 5] ats: Move some ats functions to a new directory
Quoted 11 lines
Quoted 1 line
Quoted 1 line · Wei Wang
# HG changeset patch
# User Wei Wang <[email protected]>
# Date 1320334551 -3600
# Node IDef46c471a11f83d07e256ad2e0b868828f45ef63
# Parent119bccb1cc5eee1364bbbd3bd1a30f22e9db703a
ats: Move some ats functions to a new directory. Remove VTD prefix from debug output.
passhrough/x86 holds vendor neutral codes for x86 architecture.Signed-off-by Wei Wang <[email protected]>
Quoted 434 lines
diff -r
119bccb1cc5e-ref46c471a11fxen/drivers/passthrough/Makefilexen/drivers/passthrough/Makefile +1
-0@@ -1,6 +1,7 @@ subdir-$(x86) += vtd subdir-$(ia64) += vtd subdir-$(x86) += amd +subdir-$(x86_64) += x86 obj-y += iommu.o obj-y += io.odiff -r
119bccb1cc5e-ref46c471a11fxen/drivers/passthrough/ats.hxen/drivers/passthrough/ats.h new file +8
-0@@ -0,0 +1,56 @@ +/* +* 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/ats.h new file +42
-0+ +#ifndef _ATS_H_ +#define _ATS_H_ + +struct pci_ats_dev { +struct list_head list; +u16 seg; +u8 bus; +u8 devfn; +u16 ats_queue_depth;/* ATS device invalidation queue depth */ +}; + +#ifdef CONFIG_X86_64 + +#define ATS_REG_CAP 4 +#define ATS_REG_CTL 6 +#define ATS_QUEUE_DEPTH_MASK 0xF +#define ATS_ENABLE (1<<15) + +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); + +#else + +#define ats_enabled 0 +static inline int enable_ats_device (int seg,int bus,int devfn) +{ +BUG (); +return -ENOSYS ; +} + +static inline void disable_ats_device (int seg,int bus,int devfn) +{ +BUG (); +} +#endif + +#endif /* _ATS_H_ */ +diff -r
119bccb1cc5e-ref46c471a11fxen/drivers/passthrough/vtd/extern.hxen/drivers/passthrough/vtd/extern.h +0
-14@@ -57,18 +57,13 @@ 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 (const struct pci_dev *,const struct acpi_drhd_unit *); -int enable_ats_device (int seg,int bus,int devfn); -void disable_ats_device (int seg,int bus,int devfn);int dev_invalidate_iotlb (struct iommu *iommu,u16 did,u64 addr,unsigned int size_order,u64 type);#else -#define ats_enabled 0static inline struct acpi_drhd_unit *find_ats_dev_drhd (struct iommu *iommu) {@@ -80,15 +75,6 @@ static inline int ats_device(const struc {return 0 ; } -static inline int enable_ats_device (int seg,int bus,int devfn) -{ -BUG (); -return -ENOSYS ; -} -static inline void disable_ats_device (int seg,int bus,int devfn) -{ -BUG (); -} static inline int dev_invalidate_iotlb(struct iommu *iommu, u16 did, u64 addr,unsigned int
size_order, u64 type)
diff -r119bccb1cc5e-ref46c471a11fxen/drivers/passthrough/vtd/iommu.cxen/drivers/passthrough/vtd/iommu.c +1
-0@@ -40,6 +40,7 @@#include "dmar.h" #include "extern.h" #include "vtd.h" +#include "../ats.h" #ifdef __ia64__#define nr_ioapics iosapic_get_nr_iosapics()diff -r
119bccb1cc5e-ref46c471a11fxen/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 "../../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;@@ -113,97 +72,6 @@ int ats_device(const struct pci_dev *pdereturn 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
119bccb1cc5e-ref46c471a11fxen/drivers/passthrough/x86/Makefilexen/drivers/passthrough/x86/Makefile new file +1
-0@@ -0,0 +1,1 @@ +obj-$(CONFIG_X86_64) += ats.odiff -r
119bccb1cc5e-ref46c471a11fxen/drivers/passthrough/x86/ats.cxen/drivers/passthrough/x86/ats.c new file +8
-0@@ -0,0 +1,136 @@ +/* +* 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 +122
-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 ,"%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 ,"%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 ,"%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 1320334553 -3600
# Node ID 1bf06c8d2c70e9af610e12a7592c466a799b0de1 # Parent ef46c471a11f83d07e256ad2e0b868828f45ef63 amd iommu: Fix iommu page size encoding when page order > 0. Fix io address in invalid all pages command.
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 (1ULL << 63) - 1 +#endif /* _ASM_X86_64_AMD_IOMMU_DEFS_H */
Re: [PATCH 2 of 5] amd iommu: Fix iommu page size encoding when page order > 0
Quoted 65 lines
Quoted 1 line
Quoted 1 line · Wei Wang
# HG changeset patch
# User Wei Wang <[email protected]>
# Date 1320334553 -3600
# Node ID1bf06c8d2c70e9af610e12a7592c466a799b0de1# Parentef46c471a11f83d07e256ad2e0b868828f45ef63amd iommu: Fix iommu page size encoding when page order > 0. Fix io address in invalid all pages command.Signed-off-by Wei Wang <[email protected]>diff -r
ef46c471a11f-r1bf06c8d2c70xen/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
ef46c471a11f-r1bf06c8d2c70xen/include/asm-x86/hvm/svm/amd-iommu-defs.hxen/include/asm-x86/hvm/svm/amd-iommu-defs.h +1
-0+0100
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 (1ULL << 63) - 1
Please parenthesize this properly.
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 2 of 5] amd iommu: Fix iommu page size encoding when page order > 0
Quoted 71 lines · On Thursday 03 November 2011 17:19:47 Jan Beulich wrote:
Quoted 71 lines
Quoted 1 line
Quoted 1 line · Wei Wang
# HG changeset patch
# User Wei Wang <[email protected]>
# Date 1320334553 -3600
# Node ID1bf06c8d2c70e9af610e12a7592c466a799b0de1# Parentef46c471a11f83d07e256ad2e0b868828f45ef63amd iommu: Fix iommu page size encoding when page order > 0. Fix io address in invalid all pages command.Signed-off-by Wei Wang <[email protected]>diff -r
ef46c471a11f-r1bf06c8d2c70xen/drivers/passthrough/amd/iommu_map.c---a/xen/drivers/passthrough/amd/iommu_map.cThu Nov 03 16:35:51 2011 +0100
+++b/xen/drivers/passthrough/amd/iommu_map.cThu Nov 03 16:35:53 2011
+0100 @@ -77,23 +77,24 @@ static void invalidate_iommu_pages(struc{ u64 addr_lo, addr_hi; u32 cmd[4], entry;(quoted diff) +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(struc void 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
ef46c471a11f-r1bf06c8d2c70xen/include/asm-x86/hvm/svm/amd-iommu-defs.h---a/xen/include/asm-x86/hvm/svm/amd-iommu-defs.hThu Nov 03 16:35:51 2011
+0100 +++b/xen/include/asm-x86/hvm/svm/amd-iommu-defs.hThu Nov 03
16:35:53 2011 +0100(quoted diff) +0
-0@@ -407,4 +407,6 @@ #define INT_REMAP_ENTRY_VECTOR_MASK 0x00FF0000 #define INT_REMAP_ENTRY_VECTOR_SHIFT 16
Quoted 3 lines
Review line 410
Quoted 1 line
(quoted diff) +1
-0+#define INV_IOMMU_ALL_PAGES_ADDRESS (1ULL << 63) - 1Please parenthesize this properly.
Fixed, please see attachment.
Thanks,
Wei
Quoted 8 lines
Quoted 8 lines
(quoted diff) +1
-0+ #endif /* _ASM_X86_64_AMD_IOMMU_DEFS_H */_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel
# HG changeset patch
# Parent ef46c471a11f83d07e256ad2e0b868828f45ef63 # User Wei Wang <[email protected]>
amd iommu: Fix iommu page size encoding when page order > 0. Fix io address in invalid all pages command.
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 ((1ULL << 63) - 1) +#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 1320334760 -3600
# Node ID f1b4373838dd5e082755201745f87654e2eaa59f # Parent 1bf06c8d2c70e9af610e12a7592c466a799b0de1
ats: Add new ATS helper functions
Signed-off-by Wei Wang <[email protected]>
xen/drivers/passthrough/ats.h +40 -0
@@ -16,6 +16,8 @@ #ifndef _ATS_H_ #define _ATS_H_ +#include <xen/pci_regs.h> + struct pci_ats_dev { struct list_head list; u16 seg;
@@ -36,6 +38,28 @@ 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); +struct pci_ats_dev *get_ats_device (int seg,int bus,int devfn); + +static inline 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 ; +} + +static inline int pci_ats_device (int seg,int bus,int devfn) +{ +if ( !ats_enabled ) +return 0 ; + +return pci_find_ext_capability (seg, bus, devfn,PCI_EXT_CAP_ID_ATS ); +}#else
@@ -50,6 +74,22 @@ static inline void disable_ats_device(in {BUG (); } + +static inline int pci_ats_enabled (int seg,int bus,int devfn) +{ +return 0 ; +} + +static inline int pci_ats_device (int seg,int bus,int devfn) +{ +return 0 ; +} + +static inline struct pci_ats_dev *get_ats_device (int seg,int bus,int devfn) +{ +return NULL ; +} +#endif #endif /* _ATS_H_ */
xen/drivers/passthrough/x86/ats.c +16 -0
@@ -134,3 +134,19 @@ void disable_ats_device(int seg, int busdprintk (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 == seg && pdev->bus == bus && pdev->devfn == devfn ) +return pdev; + } + +return NULL ; +}
Re: [PATCH 3 of 5] ats: Add new ATS helper functions
Quoted 9 lines
Quoted 1 line
Quoted 1 line · Wei Wang
# HG changeset patch
# User Wei Wang <[email protected]>
# Date 1320334760 -3600
# Node IDf1b4373838dd5e082755201745f87654e2eaa59f# Parent1bf06c8d2c70e9af610e12a7592c466a799b0de1
ats: Add new ATS helper functionsSigned-off-by Wei Wang <[email protected]>
Quoted 95 lines
diff -r
1bf06c8d2c70-rf1b4373838ddxen/drivers/passthrough/ats.hxen/drivers/passthrough/ats.h +40
-0@@ -16,6 +16,8 @@ #ifndef _ATS_H_ #define _ATS_H_ +#include <xen/pci_regs.h> + struct pci_ats_dev { struct list_head list; u16 seg;@@ -36,6 +38,28 @@ 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); +struct pci_ats_dev *get_ats_device (int seg,int bus,int devfn); + +static inline 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 ; +} + +static inline int pci_ats_device (int seg,int bus,int devfn) +{ +if ( !ats_enabled ) +return 0 ; + +return pci_find_ext_capability (seg, bus, devfn,PCI_EXT_CAP_ID_ATS ); +}#else @@ -50,6 +74,22 @@ static inline void disable_ats_device(in {BUG (); } + +static inline int pci_ats_enabled (int seg,int bus,int devfn) +{ +return 0 ; +} + +static inline int pci_ats_device (int seg,int bus,int devfn) +{ +return 0 ; +} + +static inline struct pci_ats_dev *get_ats_device (int seg,int bus,int devfn) +{ +return NULL ; +} +#endif #endif /* _ATS_H_ */
diff -r1bf06c8d2c70-rf1b4373838ddxen/drivers/passthrough/x86/ats.cxen/drivers/passthrough/x86/ats.c +16
-0@@ -134,3 +134,19 @@ void disable_ats_device(int seg, int busdprintk (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 == seg && pdev->bus == bus && pdev->devfn == devfn ) +return pdev; + } + +return NULL ; +}_______________________________________________
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 1320334783 -3600
# Node ID acfe5b608724cb06c644a61b73599c748a81274a # Parent f1b4373838dd5e082755201745f87654e2eaa59f amd iommu: add iotlb invalidation command
xen/drivers/passthrough/amd/iommu_map.c +131 -0
@@ -23,6 +23,8 @@#include <xen/hvm/iommu.h> #include <asm/amd-iommu.h> #include <asm/hvm/svm/amd-iommu-proto.h> +#include "../ats.h" +#include <xen/pci.h> static int queue_iommu_command (struct amd_iommu *iommu,u32 cmd[]) {
@@ -128,6 +130,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 +967,63 @@ 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 =PCI_BDF2 (ats_pdev->bus, 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); +} + +static 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 +1042,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 1320334827 -3600
# Node ID 59b7d9f9b571d6de35e5c5dae81a3890752271fe # Parent acfe5b608724cb06c644a61b73599c748a81274a amd iommu: enable ats devices
xen/drivers/passthrough/amd/iommu_map.c +11 -0
@@ -370,6 +370,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 +46 -6
126 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 */