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 _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Wei Wang
2011-Oct-25 13:07 UTC
[Xen-devel] [PATCH 1 of 6] ats: Move some ats functions to a new directory
# HG changeset patch # User Wei Wang <wei.wang2@amd.com> # 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. Signed-off-by: Wei Wang <wei.wang2@amd.com> diff -r 121af976b298 -r 217c4a82b202 xen/drivers/passthrough/Makefile --- a/xen/drivers/passthrough/Makefile Fri Oct 14 10:17:22 2011 +0200 +++ b/xen/drivers/passthrough/Makefile Mon Oct 24 18:11:23 2011 +0200 @@ -1,6 +1,7 @@ subdir-$(x86) += vtd subdir-$(ia64) += vtd subdir-$(x86) += amd +subdir-$(x86) += x86 obj-y += iommu.o obj-y += io.o diff -r 121af976b298 -r 217c4a82b202 xen/drivers/passthrough/vtd/extern.h --- a/xen/drivers/passthrough/vtd/extern.h Fri Oct 14 10:17:22 2011 +0200 +++ b/xen/drivers/passthrough/vtd/extern.h Mon Oct 24 18:11:23 2011 +0200 @@ -57,13 +57,9 @@ struct acpi_drhd_unit * iommu_to_drhd(st struct 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 -r 217c4a82b202 xen/drivers/passthrough/vtd/iommu.c --- a/xen/drivers/passthrough/vtd/iommu.c Fri Oct 14 10:17:22 2011 +0200 +++ b/xen/drivers/passthrough/vtd/iommu.c Mon Oct 24 18:11:23 2011 +0200 @@ -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() diff -r 121af976b298 -r 217c4a82b202 xen/drivers/passthrough/vtd/x86/ats.c --- a/xen/drivers/passthrough/vtd/x86/ats.c Fri Oct 14 10:17:22 2011 +0200 +++ b/xen/drivers/passthrough/vtd/x86/ats.c Mon Oct 24 18:11:23 2011 +0200 @@ -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 dev return 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 -r 217c4a82b202 xen/drivers/passthrough/x86/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xen/drivers/passthrough/x86/Makefile Mon Oct 24 18:11:23 2011 +0200 @@ -0,0 +1,1 @@ +obj-y += ats.o \ No newline at end of file diff -r 121af976b298 -r 217c4a82b202 xen/drivers/passthrough/x86/ats.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xen/drivers/passthrough/x86/ats.c Mon Oct 24 18:11:23 2011 +0200 @@ -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. + */ + +#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 -r 217c4a82b202 xen/drivers/passthrough/x86/ats.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xen/drivers/passthrough/x86/ats.h Mon Oct 24 18:11:23 2011 +0200 @@ -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_ */ _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Wei Wang
2011-Oct-25 13:07 UTC
[Xen-devel] [PATCH 2 of 6] ats: Remove VTD prefix from debug output
# HG changeset patch # User Wei Wang <wei.wang2@amd.com> # Date 1319472689 -7200 # Node ID 0d17087f9e495c1b9eb43bc0f6a21319097f3043 # Parent 217c4a82b202975c2fdff9ae499f065471e5c87b ats: Remove VTD prefix from debug output. Signed-off-by: Wei Wang <wei.wang2@amd.com> diff -r 217c4a82b202 -r 0d17087f9e49 xen/drivers/passthrough/x86/ats.c --- a/xen/drivers/passthrough/x86/ats.c Mon Oct 24 18:11:23 2011 +0200 +++ b/xen/drivers/passthrough/x86/ats.c Mon Oct 24 18:11:29 2011 +0200 @@ -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 Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Wei Wang
2011-Oct-25 13:07 UTC
[Xen-devel] [PATCH 3 of 6] amd iommu: Fix iommu page size encoding when page order > 0
# HG changeset patch # User Wei Wang <wei.wang2@amd.com> # Date 1319472692 -7200 # Node ID 18088bd3e8f6c16b7aef3d8652f2b9878117fcd5 # Parent 0d17087f9e495c1b9eb43bc0f6a21319097f3043 amd iommu: Fix iommu page size encoding when page order > 0 Signed-off-by: Wei Wang <wei.wang2@amd.com> diff -r 0d17087f9e49 -r 18088bd3e8f6 xen/drivers/passthrough/amd/iommu_map.c --- a/xen/drivers/passthrough/amd/iommu_map.c Mon Oct 24 18:11:29 2011 +0200 +++ b/xen/drivers/passthrough/amd/iommu_map.c Mon 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; - 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 0d17087f9e49 -r 18088bd3e8f6 xen/include/asm-x86/hvm/svm/amd-iommu-defs.h --- a/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h Mon Oct 24 18:11:29 2011 +0200 +++ b/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h Mon Oct 24 18:11:32 2011 +0200 @@ -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 */ _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Wei Wang
2011-Oct-25 13:07 UTC
[Xen-devel] [PATCH 4 of 6] ats: Add new ATS helper functions
# HG changeset patch # User Wei Wang <wei.wang2@amd.com> # Date 1319472696 -7200 # Node ID 3dc5e805d9142cbe1074610879e258b6fab43409 # Parent 18088bd3e8f6c16b7aef3d8652f2b9878117fcd5 ats: Add new ATS helper functions Signed-off-by Wei Wang <wei.wang2@amd.com> diff -r 18088bd3e8f6 -r 3dc5e805d914 xen/drivers/passthrough/x86/ats.c --- a/xen/drivers/passthrough/x86/ats.c Mon Oct 24 18:11:32 2011 +0200 +++ b/xen/drivers/passthrough/x86/ats.c Mon Oct 24 18:11:36 2011 +0200 @@ -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; +} diff -r 18088bd3e8f6 -r 3dc5e805d914 xen/drivers/passthrough/x86/ats.h --- a/xen/drivers/passthrough/x86/ats.h Mon Oct 24 18:11:32 2011 +0200 +++ b/xen/drivers/passthrough/x86/ats.h Mon Oct 24 18:11:36 2011 +0200 @@ -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_ */ _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Wei Wang
2011-Oct-25 13:07 UTC
[Xen-devel] [PATCH 5 of 6] amd iommu: add iotlb invalidation command
# HG changeset patch # User Wei Wang <wei.wang2@amd.com> # Date 1319472700 -7200 # Node ID 8ec947b278afaf89acadf905237c95ba7b64524a # Parent 3dc5e805d9142cbe1074610879e258b6fab43409 amd iommu: add iotlb invalidation command Signed-off-by: Wei Wang <wei.wang2@amd.com> diff -r 3dc5e805d914 -r 8ec947b278af xen/drivers/passthrough/amd/iommu_map.c --- a/xen/drivers/passthrough/amd/iommu_map.c Mon Oct 24 18:11:36 2011 +0200 +++ b/xen/drivers/passthrough/amd/iommu_map.c Mon Oct 24 18:11:40 2011 +0200 @@ -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(struc send_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(s return 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(struc flush_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) diff -r 3dc5e805d914 -r 8ec947b278af xen/include/asm-x86/hvm/svm/amd-iommu-defs.h --- a/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h Mon Oct 24 18:11:36 2011 +0200 +++ b/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h Mon Oct 24 18:11:40 2011 +0200 @@ -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 diff -r 3dc5e805d914 -r 8ec947b278af xen/include/asm-x86/hvm/svm/amd-iommu-proto.h --- a/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h Mon Oct 24 18:11:36 2011 +0200 +++ b/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h Mon Oct 24 18:11:40 2011 +0200 @@ -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, _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
# HG changeset patch # User Wei Wang <wei.wang2@amd.com> # Date 1319472702 -7200 # Node ID b84967db0efb875bca4d95f47fc77b46cd065665 # Parent 8ec947b278afaf89acadf905237c95ba7b64524a amd iommu: enable ats devices Signed-off-by: Wei Wang <wei.wang2@amd.com diff -r 8ec947b278af -r b84967db0efb xen/drivers/passthrough/amd/iommu_map.c --- a/xen/drivers/passthrough/amd/iommu_map.c Mon Oct 24 18:11:40 2011 +0200 +++ b/xen/drivers/passthrough/amd/iommu_map.c Mon Oct 24 18:11:42 2011 +0200 @@ -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 -r b84967db0efb xen/drivers/passthrough/amd/pci_amd_iommu.c --- a/xen/drivers/passthrough/amd/pci_amd_iommu.c Mon Oct 24 18:11:40 2011 +0200 +++ b/xen/drivers/passthrough/amd/pci_amd_iommu.c Mon Oct 24 18:11:42 2011 +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_devic if ( 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); @@ -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 && + !pci_ats_enabled(iommu->seg, bus, devfn) ) + { + struct pci_dev* pdev; + enable_ats_device(iommu->seg, bus, devfn); + + ASSERT(spin_is_locked(&pcidevs_lock)); + pdev = pci_get_pdev(iommu->seg, bus, devfn); + + if ( pdev ) + 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, @@ -261,21 +285,26 @@ static void __init amd_iommu_dom0_init(s setup_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) { 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); dte = 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, " @@ -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 && + 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 domai return -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 domai if ( 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 p return -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(struc return -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 -r b84967db0efb xen/include/asm-x86/hvm/svm/amd-iommu-proto.h --- a/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h Mon Oct 24 18:11:40 2011 +0200 +++ b/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h Mon Oct 24 18:11:42 2011 +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 */ _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Jan Beulich
2011-Nov-02 13:41 UTC
Re: [Xen-devel] [PATCH 1 of 6] ats: Move some ats functions to a new directory
>>> On 25.10.11 at 15:07, Wei Wang <wei.wang2@amd.com> wrote: > # HG changeset patch > # User Wei Wang <wei.wang2@amd.com> > # 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. > > Signed-off-by: Wei Wang <wei.wang2@amd.com> > > diff -r 121af976b298 -r 217c4a82b202 xen/drivers/passthrough/Makefile > --- a/xen/drivers/passthrough/Makefile Fri Oct 14 10:17:22 2011 +0200 > +++ b/xen/drivers/passthrough/Makefile Mon Oct 24 18:11:23 2011 +0200 > @@ -1,6 +1,7 @@ > subdir-$(x86) += vtd > subdir-$(ia64) += vtd > subdir-$(x86) += amd > +subdir-$(x86) += x86 > > obj-y += iommu.o > obj-y += io.o > diff -r 121af976b298 -r 217c4a82b202 xen/drivers/passthrough/vtd/extern.h > --- a/xen/drivers/passthrough/vtd/extern.h Fri Oct 14 10:17:22 2011 +0200 > +++ b/xen/drivers/passthrough/vtd/extern.h Mon Oct 24 18:11:23 2011 +0200 > @@ -57,13 +57,9 @@ struct acpi_drhd_unit * iommu_to_drhd(st > struct 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 -r 217c4a82b202 xen/drivers/passthrough/vtd/iommu.c > --- a/xen/drivers/passthrough/vtd/iommu.c Fri Oct 14 10:17:22 2011 +0200 > +++ b/xen/drivers/passthrough/vtd/iommu.c Mon Oct 24 18:11:23 2011 +0200 > @@ -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> #ifdef __ia64__ > #define nr_ioapics iosapic_get_nr_iosapics() > diff -r 121af976b298 -r 217c4a82b202 xen/drivers/passthrough/vtd/x86/ats.c > --- a/xen/drivers/passthrough/vtd/x86/ats.c Fri Oct 14 10:17:22 2011 +0200 > +++ b/xen/drivers/passthrough/vtd/x86/ats.c Mon Oct 24 18:11:23 2011 +0200 > @@ -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 dev > return 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 -r 217c4a82b202 xen/drivers/passthrough/x86/Makefile > --- /dev/null Thu Jan 01 00:00:00 1970 +0000 > +++ b/xen/drivers/passthrough/x86/Makefile Mon Oct 24 18:11:23 2011 +0200 > @@ -0,0 +1,1 @@ > +obj-y += ats.o > \ No newline at end of file > diff -r 121af976b298 -r 217c4a82b202 xen/drivers/passthrough/x86/ats.c > --- /dev/null Thu Jan 01 00:00:00 1970 +0000 > +++ b/xen/drivers/passthrough/x86/ats.c Mon Oct 24 18:11:23 2011 +0200 > @@ -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. > + */ > + > +#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 -r 217c4a82b202 xen/drivers/passthrough/x86/ats.h > --- /dev/null Thu Jan 01 00:00:00 1970 +0000 > +++ b/xen/drivers/passthrough/x86/ats.h Mon Oct 24 18:11:23 2011 +0200 > @@ -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_ */ > > > _______________________________________________ > Xen-devel mailing list > Xen-devel@lists.xensource.com > http://lists.xensource.com/xen-devel_______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Jan Beulich
2011-Nov-02 13:42 UTC
Re: [Xen-devel] [PATCH 2 of 6] ats: Remove VTD prefix from debug output
>>> On 25.10.11 at 15:07, Wei Wang <wei.wang2@amd.com> wrote: > # HG changeset patch > # User Wei Wang <wei.wang2@amd.com> > # Date 1319472689 -7200 > # Node ID 0d17087f9e495c1b9eb43bc0f6a21319097f3043 > # Parent 217c4a82b202975c2fdff9ae499f065471e5c87b > ats: Remove VTD prefix from debug output.Personally I would prefer if you folded this into patch 1. Jan> Signed-off-by: Wei Wang <wei.wang2@amd.com> > > diff -r 217c4a82b202 -r 0d17087f9e49 xen/drivers/passthrough/x86/ats.c > --- a/xen/drivers/passthrough/x86/ats.c Mon Oct 24 18:11:23 2011 +0200 > +++ b/xen/drivers/passthrough/x86/ats.c Mon Oct 24 18:11:29 2011 +0200 > @@ -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 > Xen-devel@lists.xensource.com > http://lists.xensource.com/xen-devel_______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Jan Beulich
2011-Nov-02 13:46 UTC
Re: [Xen-devel] [PATCH 3 of 6] amd iommu: Fix iommu page size encoding when page order > 0
>>> On 25.10.11 at 15:07, Wei Wang <wei.wang2@amd.com> wrote: > # HG changeset patch > # User Wei Wang <wei.wang2@amd.com> > # Date 1319472692 -7200 > # Node ID 18088bd3e8f6c16b7aef3d8652f2b9878117fcd5 > # Parent 0d17087f9e495c1b9eb43bc0f6a21319097f3043 > amd iommu: Fix iommu page size encoding when page order > 0 > > Signed-off-by: Wei Wang <wei.wang2@amd.com> > > diff -r 0d17087f9e49 -r 18088bd3e8f6 xen/drivers/passthrough/amd/iommu_map.c > --- a/xen/drivers/passthrough/amd/iommu_map.c Mon Oct 24 18:11:29 2011 +0200 > +++ b/xen/drivers/passthrough/amd/iommu_map.c Mon 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; > - 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 0d17087f9e49 -r 18088bd3e8f6 xen/include/asm-x86/hvm/svm/amd-iommu-defs.h > --- a/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h Mon Oct 24 18:11:29 2011 +0200 > +++ b/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h Mon Oct 24 18:11:32 2011 > +0200 > @@ -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> + > #endif /* _ASM_X86_64_AMD_IOMMU_DEFS_H */ > > > _______________________________________________ > Xen-devel mailing list > Xen-devel@lists.xensource.com > http://lists.xensource.com/xen-devel_______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Jan Beulich
2011-Nov-02 13:50 UTC
Re: [Xen-devel] [PATCH 4 of 6] ats: Add new ATS helper functions
>>> On 25.10.11 at 15:07, Wei Wang <wei.wang2@amd.com> wrote: > # HG changeset patch > # User Wei Wang <wei.wang2@amd.com> > # Date 1319472696 -7200 > # Node ID 3dc5e805d9142cbe1074610879e258b6fab43409 > # Parent 18088bd3e8f6c16b7aef3d8652f2b9878117fcd5 > ats: Add new ATS helper functions > > Signed-off-by Wei Wang <wei.wang2@amd.com> > > diff -r 18088bd3e8f6 -r 3dc5e805d914 xen/drivers/passthrough/x86/ats.c > --- a/xen/drivers/passthrough/x86/ats.c Mon Oct 24 18:11:32 2011 +0200 > +++ b/xen/drivers/passthrough/x86/ats.c Mon Oct 24 18:11:36 2011 +0200 > @@ -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; > +}At least this one would certainly be a candidate for inlining.> + > +struct pci_ats_dev* get_ats_device(int seg, int bus, int devfn)Formatting (asterisk and space should switch places).> +{ > + 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 -r 3dc5e805d914 xen/drivers/passthrough/x86/ats.h > --- a/xen/drivers/passthrough/x86/ats.h Mon Oct 24 18:11:32 2011 +0200 > +++ b/xen/drivers/passthrough/x86/ats.h Mon Oct 24 18:11:36 2011 +0200 > @@ -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> > #endif /* _X86_ATS_H_ */ > > > _______________________________________________ > Xen-devel mailing list > Xen-devel@lists.xensource.com > http://lists.xensource.com/xen-devel_______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Jan Beulich
2011-Nov-02 13:56 UTC
Re: [Xen-devel] [PATCH 6 of 6] amd iommu: enable ats devices
>>> On 25.10.11 at 15:07, Wei Wang <wei.wang2@amd.com> wrote: > # HG changeset patch > # User Wei Wang <wei.wang2@amd.com> > # Date 1319472702 -7200 > # Node ID b84967db0efb875bca4d95f47fc77b46cd065665 > # Parent 8ec947b278afaf89acadf905237c95ba7b64524a > amd iommu: enable ats devices > > Signed-off-by: Wei Wang <wei.wang2@amd.com > > diff -r 8ec947b278af -r b84967db0efb xen/drivers/passthrough/amd/iommu_map.c > --- a/xen/drivers/passthrough/amd/iommu_map.c Mon Oct 24 18:11:40 2011 +0200 > +++ b/xen/drivers/passthrough/amd/iommu_map.c Mon Oct 24 18:11:42 2011 +0200 > @@ -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 -r b84967db0efb > xen/drivers/passthrough/amd/pci_amd_iommu.c > --- a/xen/drivers/passthrough/amd/pci_amd_iommu.c Mon Oct 24 18:11:40 2011 +0200 > +++ b/xen/drivers/passthrough/amd/pci_amd_iommu.c Mon Oct 24 18:11:42 2011 > +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_devic > if ( 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); > > @@ -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.> + !pci_ats_enabled(iommu->seg, bus, devfn) ) > + { > + struct pci_dev* pdev;Formatting (need a newline here, plus asterisk and space again should switch places).> + 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.> + 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, > @@ -261,21 +285,26 @@ static void __init amd_iommu_dom0_init(s > setup_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 ...> { > 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.> dte = 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, " > @@ -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.> + 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 domai > return -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 domai > if ( 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 p > return -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(struc > return -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 -r b84967db0efb > xen/include/asm-x86/hvm/svm/amd-iommu-proto.h > --- a/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h Mon Oct 24 18:11:40 2011 +0200 > +++ b/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h Mon Oct 24 18:11:42 2011 > +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 */_______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Wei Wang2
2011-Nov-02 14:52 UTC
Re: [Xen-devel] [PATCH 3 of 6] amd iommu: Fix iommu page size encoding when page order > 0
On Wednesday 02 November 2011 14:46:24 Jan Beulich wrote:> >>> On 25.10.11 at 15:07, Wei Wang <wei.wang2@amd.com> wrote: > > > > # HG changeset patch > > # User Wei Wang <wei.wang2@amd.com> > > # Date 1319472692 -7200 > > # Node ID 18088bd3e8f6c16b7aef3d8652f2b9878117fcd5 > > # Parent 0d17087f9e495c1b9eb43bc0f6a21319097f3043 > > amd iommu: Fix iommu page size encoding when page order > 0 > > > > Signed-off-by: Wei Wang <wei.wang2@amd.com> > > > > diff -r 0d17087f9e49 -r 18088bd3e8f6 > > xen/drivers/passthrough/amd/iommu_map.c --- > > a/xen/drivers/passthrough/amd/iommu_map.c Mon Oct 24 18:11:29 2011 +0200 > > +++ b/xen/drivers/passthrough/amd/iommu_map.c Mon 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; > > - 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 0d17087f9e49 -r 18088bd3e8f6 > > xen/include/asm-x86/hvm/svm/amd-iommu-defs.h --- > > a/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h Mon Oct 24 18:11:29 2011 > > +0200 +++ b/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h Mon Oct 24 > > 18:11:32 2011 +0200 > > @@ -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)?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> Jan > > > + > > #endif /* _ASM_X86_64_AMD_IOMMU_DEFS_H */ > > > > > > _______________________________________________ > > Xen-devel mailing list > > Xen-devel@lists.xensource.com > > http://lists.xensource.com/xen-devel_______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Jan Beulich
2011-Nov-02 15:13 UTC
Re: [Xen-devel] [PATCH 3 of 6] amd iommu: Fix iommu page size encoding when page order > 0
>>> On 02.11.11 at 15:52, Wei Wang2 <wei.wang2@amd.com> wrote: > On Wednesday 02 November 2011 14:46:24 Jan Beulich wrote: >> >>> On 25.10.11 at 15:07, Wei Wang <wei.wang2@amd.com> wrote: >> > >> > # HG changeset patch >> > # User Wei Wang <wei.wang2@amd.com> >> > # Date 1319472692 -7200 >> > # Node ID 18088bd3e8f6c16b7aef3d8652f2b9878117fcd5 >> > # Parent 0d17087f9e495c1b9eb43bc0f6a21319097f3043 >> > amd iommu: Fix iommu page size encoding when page order > 0 >> > >> > Signed-off-by: Wei Wang <wei.wang2@amd.com> >> > >> > diff -r 0d17087f9e49 -r 18088bd3e8f6 >> > xen/drivers/passthrough/amd/iommu_map.c --- >> > a/xen/drivers/passthrough/amd/iommu_map.c Mon Oct 24 18:11:29 2011 +0200 >> > +++ b/xen/drivers/passthrough/amd/iommu_map.c Mon 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; >> > - 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 0d17087f9e49 -r 18088bd3e8f6 >> > xen/include/asm-x86/hvm/svm/amd-iommu-defs.h --- >> > a/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h Mon Oct 24 18:11:29 2011 >> > +0200 +++ b/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h Mon Oct 24 >> > 18:11:32 2011 +0200 >> > @@ -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)? > > 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 theYes, 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> next version. Thanks for all your comments. Other issues will also be fixed > in the new version. > Thanks, > Wei > >> Jan >> >> > + >> > #endif /* _ASM_X86_64_AMD_IOMMU_DEFS_H */ >> > >> > >> > _______________________________________________ >> > Xen-devel mailing list >> > Xen-devel@lists.xensource.com >> > http://lists.xensource.com/xen-devel_______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel