* [PATCH 1 of 5] ats: Move some ats functions to a new directory
2011-11-03 10:13 [PATCH 0 of 5] amd iommu: Add ATS support (v3) Wei Wang
@ 2011-11-03 10:13 ` Wei Wang
2011-11-03 12:46 ` Jan Beulich
2011-11-03 10:13 ` [PATCH 2 of 5] amd iommu: Fix iommu page size encoding when page order > 0 Wei Wang
` (3 subsequent siblings)
4 siblings, 1 reply; 16+ messages in thread
From: Wei Wang @ 2011-11-03 10:13 UTC (permalink / raw)
To: xen-devel; +Cc: JBeulich
# HG changeset patch
# User Wei Wang <wei.wang2@amd.com>
# Date 1320314537 -3600
# Node ID d422e3cf7976c76c57fc2d455b784d0fcc24d06b
# 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.
Signed-off-by: Wei Wang <wei.wang2@amd.com>
diff -r 119bccb1cc5e -r d422e3cf7976 xen/drivers/passthrough/Makefile
--- a/xen/drivers/passthrough/Makefile Wed Nov 02 13:53:05 2011 +0100
+++ b/xen/drivers/passthrough/Makefile Thu Nov 03 11:02:17 2011 +0100
@@ -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 119bccb1cc5e -r d422e3cf7976 xen/drivers/passthrough/ats.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/drivers/passthrough/ats.h Thu Nov 03 11:02:17 2011 +0100
@@ -0,0 +1,39 @@
+/*
+ * 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 _ATS_H_
+#define _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 /* _ATS_H_ */
+
diff -r 119bccb1cc5e -r d422e3cf7976 xen/drivers/passthrough/vtd/extern.h
--- a/xen/drivers/passthrough/vtd/extern.h Wed Nov 02 13:53:05 2011 +0100
+++ b/xen/drivers/passthrough/vtd/extern.h Thu Nov 03 11:02:17 2011 +0100
@@ -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(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);
diff -r 119bccb1cc5e -r d422e3cf7976 xen/drivers/passthrough/vtd/iommu.c
--- a/xen/drivers/passthrough/vtd/iommu.c Wed Nov 02 13:53:05 2011 +0100
+++ b/xen/drivers/passthrough/vtd/iommu.c Thu Nov 03 11:02:17 2011 +0100
@@ -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 -r d422e3cf7976 xen/drivers/passthrough/vtd/x86/ats.c
--- a/xen/drivers/passthrough/vtd/x86/ats.c Wed Nov 02 13:53:05 2011 +0100
+++ b/xen/drivers/passthrough/vtd/x86/ats.c Thu Nov 03 11:02:17 2011 +0100
@@ -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 *pde
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 119bccb1cc5e -r d422e3cf7976 xen/drivers/passthrough/x86/Makefile
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/drivers/passthrough/x86/Makefile Thu Nov 03 11:02:17 2011 +0100
@@ -0,0 +1,1 @@
+obj-y += ats.o
\ No newline at end of file
diff -r 119bccb1cc5e -r d422e3cf7976 xen/drivers/passthrough/x86/ats.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/drivers/passthrough/x86/ats.c Thu Nov 03 11:02:17 2011 +0100
@@ -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,
+ "%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));
+}
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH 1 of 5] ats: Move some ats functions to a new directory
2011-11-03 10:13 ` [PATCH 1 of 5] ats: Move some ats functions to a new directory Wei Wang
@ 2011-11-03 12:46 ` Jan Beulich
0 siblings, 0 replies; 16+ messages in thread
From: Jan Beulich @ 2011-11-03 12:46 UTC (permalink / raw)
To: Wei Wang; +Cc: xen-devel
>>> On 03.11.11 at 11:13, Wei Wang <wei.wang2@amd.com> wrote:
> # HG changeset patch
> # User Wei Wang <wei.wang2@amd.com>
> # Date 1320314537 -3600
> # Node ID d422e3cf7976c76c57fc2d455b784d0fcc24d06b
> # 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.
>
> Signed-off-by: Wei Wang <wei.wang2@amd.com>
>
> diff -r 119bccb1cc5e -r d422e3cf7976 xen/drivers/passthrough/Makefile
> --- a/xen/drivers/passthrough/Makefile Wed Nov 02 13:53:05 2011 +0100
> +++ b/xen/drivers/passthrough/Makefile Thu Nov 03 11:02:17 2011 +0100
> @@ -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 119bccb1cc5e -r d422e3cf7976 xen/drivers/passthrough/ats.h
> --- /dev/null Thu Jan 01 00:00:00 1970 +0000
> +++ b/xen/drivers/passthrough/ats.h Thu Nov 03 11:02:17 2011 +0100
> @@ -0,0 +1,39 @@
> +/*
> + * 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 _ATS_H_
> +#define _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 /* _ATS_H_ */
> +
> diff -r 119bccb1cc5e -r d422e3cf7976 xen/drivers/passthrough/vtd/extern.h
> --- a/xen/drivers/passthrough/vtd/extern.h Wed Nov 02 13:53:05 2011 +0100
> +++ b/xen/drivers/passthrough/vtd/extern.h Thu Nov 03 11:02:17 2011 +0100
> @@ -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
Did you overlook this conditional? It and the respective inline functions
and #define-s must be added/moved to the new header too.
> -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);
> diff -r 119bccb1cc5e -r d422e3cf7976 xen/drivers/passthrough/vtd/iommu.c
> --- a/xen/drivers/passthrough/vtd/iommu.c Wed Nov 02 13:53:05 2011 +0100
> +++ b/xen/drivers/passthrough/vtd/iommu.c Thu Nov 03 11:02:17 2011 +0100
> @@ -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 -r d422e3cf7976 xen/drivers/passthrough/vtd/x86/ats.c
> --- a/xen/drivers/passthrough/vtd/x86/ats.c Wed Nov 02 13:53:05 2011 +0100
> +++ b/xen/drivers/passthrough/vtd/x86/ats.c Thu Nov 03 11:02:17 2011 +0100
> @@ -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 *pde
> 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 119bccb1cc5e -r d422e3cf7976 xen/drivers/passthrough/x86/Makefile
> --- /dev/null Thu Jan 01 00:00:00 1970 +0000
> +++ b/xen/drivers/passthrough/x86/Makefile Thu Nov 03 11:02:17 2011 +0100
> @@ -0,0 +1,1 @@
> +obj-y += ats.o
obj-$(CONFIG_X86_64) += ats.o
The original file got built for 64-bit only, too.
> \ No newline at end of file
This is self-explanatory, isn't it?
> diff -r 119bccb1cc5e -r d422e3cf7976 xen/drivers/passthrough/x86/ats.c
> --- /dev/null Thu Jan 01 00:00:00 1970 +0000
> +++ b/xen/drivers/passthrough/x86/ats.c Thu Nov 03 11:02:17 2011 +0100
> @@ -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,
> + "%04x:%02x:%02x.%u: ATS capability found\n",
Here and below, the two lines can be folded (together they don't
exceed 80 chars per line) now that the VT-d prefix is gone.
Jan
> + 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));
> +}
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 2 of 5] amd iommu: Fix iommu page size encoding when page order > 0
2011-11-03 10:13 [PATCH 0 of 5] amd iommu: Add ATS support (v3) Wei Wang
2011-11-03 10:13 ` [PATCH 1 of 5] ats: Move some ats functions to a new directory Wei Wang
@ 2011-11-03 10:13 ` Wei Wang
2011-11-03 12:49 ` Jan Beulich
2011-11-03 10:13 ` [PATCH 3 of 5] ats: Add new ATS helper functions Wei Wang
` (2 subsequent siblings)
4 siblings, 1 reply; 16+ messages in thread
From: Wei Wang @ 2011-11-03 10:13 UTC (permalink / raw)
To: xen-devel; +Cc: JBeulich
# HG changeset patch
# User Wei Wang <wei.wang2@amd.com>
# Date 1320314617 -3600
# Node ID d0c38cb215cd96e01de27eadf5ec0a5e711de448
# Parent d422e3cf7976c76c57fc2d455b784d0fcc24d06b
amd iommu: Fix iommu page size encoding when page order > 0
Signed-off-by: Wei Wang <wei.wang2@amd.com>
diff -r d422e3cf7976 -r d0c38cb215cd xen/drivers/passthrough/amd/iommu_map.c
--- a/xen/drivers/passthrough/amd/iommu_map.c Thu Nov 03 11:02:17 2011 +0100
+++ b/xen/drivers/passthrough/amd/iommu_map.c Thu Nov 03 11:03:37 2011 +0100
@@ -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 d422e3cf7976 -r d0c38cb215cd xen/include/asm-x86/hvm/svm/amd-iommu-defs.h
--- a/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h Thu Nov 03 11:02:17 2011 +0100
+++ b/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h Thu Nov 03 11:03:37 2011 +0100
@@ -407,4 +407,6 @@
#define INT_REMAP_ENTRY_VECTOR_MASK 0x00FF0000
#define INT_REMAP_ENTRY_VECTOR_SHIFT 16
+#define INV_IOMMU_ALL_PAGES_ADDRESS 0x7FFFFFFFFFFFFFFFULL
+
#endif /* _ASM_X86_64_AMD_IOMMU_DEFS_H */
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH 2 of 5] amd iommu: Fix iommu page size encoding when page order > 0
2011-11-03 10:13 ` [PATCH 2 of 5] amd iommu: Fix iommu page size encoding when page order > 0 Wei Wang
@ 2011-11-03 12:49 ` Jan Beulich
2011-11-03 12:52 ` Jan Beulich
2011-11-03 13:26 ` Wei Wang2
0 siblings, 2 replies; 16+ messages in thread
From: Jan Beulich @ 2011-11-03 12:49 UTC (permalink / raw)
To: Wei Wang; +Cc: xen-devel
>>> On 03.11.11 at 11:13, Wei Wang <wei.wang2@amd.com> wrote:
> # HG changeset patch
> # User Wei Wang <wei.wang2@amd.com>
> # Date 1320314617 -3600
> # Node ID d0c38cb215cd96e01de27eadf5ec0a5e711de448
> # Parent d422e3cf7976c76c57fc2d455b784d0fcc24d06b
> amd iommu: Fix iommu page size encoding when page order > 0
>
> Signed-off-by: Wei Wang <wei.wang2@amd.com>
>
> diff -r d422e3cf7976 -r d0c38cb215cd xen/drivers/passthrough/amd/iommu_map.c
> --- a/xen/drivers/passthrough/amd/iommu_map.c Thu Nov 03 11:02:17 2011 +0100
> +++ b/xen/drivers/passthrough/amd/iommu_map.c Thu Nov 03 11:03:37 2011 +0100
> @@ -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 )
Note the difference between this and your adjusted definition
of INV_IOMMU_ALL_PAGES_ADDRESS. I don't think this is
correct (or else your patch description should say why).
> - {
> - 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);
Same here, for a slightly different reason.
Jan
> }
>
> void amd_iommu_flush_pages(struct domain *d,
> diff -r d422e3cf7976 -r d0c38cb215cd xen/include/asm-x86/hvm/svm/amd-iommu-defs.h
> --- a/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h Thu Nov 03 11:02:17 2011 +0100
> +++ b/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h Thu Nov 03 11:03:37 2011
> +0100
> @@ -407,4 +407,6 @@
> #define INT_REMAP_ENTRY_VECTOR_MASK 0x00FF0000
> #define INT_REMAP_ENTRY_VECTOR_SHIFT 16
>
> +#define INV_IOMMU_ALL_PAGES_ADDRESS 0x7FFFFFFFFFFFFFFFULL
> +
> #endif /* _ASM_X86_64_AMD_IOMMU_DEFS_H */
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH 2 of 5] amd iommu: Fix iommu page size encoding when page order > 0
2011-11-03 12:49 ` Jan Beulich
@ 2011-11-03 12:52 ` Jan Beulich
2011-11-03 13:29 ` Wei Wang2
2011-11-03 13:26 ` Wei Wang2
1 sibling, 1 reply; 16+ messages in thread
From: Jan Beulich @ 2011-11-03 12:52 UTC (permalink / raw)
To: Wei Wang; +Cc: xen-devel
>>> On 03.11.11 at 13:49, "Jan Beulich" <JBeulich@suse.com> wrote:
>>>> On 03.11.11 at 11:13, Wei Wang <wei.wang2@amd.com> wrote:
>> # HG changeset patch
>> # User Wei Wang <wei.wang2@amd.com>
>> # Date 1320314617 -3600
>> # Node ID d0c38cb215cd96e01de27eadf5ec0a5e711de448
>> # Parent d422e3cf7976c76c57fc2d455b784d0fcc24d06b
>> amd iommu: Fix iommu page size encoding when page order > 0
>>
>> Signed-off-by: Wei Wang <wei.wang2@amd.com>
>>
>> diff -r d422e3cf7976 -r d0c38cb215cd xen/drivers/passthrough/amd/iommu_map.c
>> --- a/xen/drivers/passthrough/amd/iommu_map.c Thu Nov 03 11:02:17 2011 +0100
>> +++ b/xen/drivers/passthrough/amd/iommu_map.c Thu Nov 03 11:03:37 2011 +0100
>> @@ -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 )
>
> Note the difference between this and your adjusted definition
> of INV_IOMMU_ALL_PAGES_ADDRESS. I don't think this is
> correct (or else your patch description should say why).
>
>> - {
>> - 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);
>
> Same here, for a slightly different reason.
>
> Jan
>
>> }
>>
>> void amd_iommu_flush_pages(struct domain *d,
>> diff -r d422e3cf7976 -r d0c38cb215cd xen/include/asm-x86/hvm/svm/amd-iommu-defs.h
>> --- a/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h Thu Nov 03 11:02:17 2011 +0100
>> +++ b/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h Thu Nov 03 11:03:37 2011
>> +0100
>> @@ -407,4 +407,6 @@
>> #define INT_REMAP_ENTRY_VECTOR_MASK 0x00FF0000
>> #define INT_REMAP_ENTRY_VECTOR_SHIFT 16
>>
>> +#define INV_IOMMU_ALL_PAGES_ADDRESS 0x7FFFFFFFFFFFFFFFULL
>> +
Oh, additionally, this still isn't being expressed by a shift expression,
which makes it still badly readable (one has to count F-s in order to
know what this actually represents).
Jan
>> #endif /* _ASM_X86_64_AMD_IOMMU_DEFS_H */
>
>
>
>
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xensource.com
> http://lists.xensource.com/xen-devel
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: Re: [PATCH 2 of 5] amd iommu: Fix iommu page size encoding when page order > 0
2011-11-03 12:52 ` Jan Beulich
@ 2011-11-03 13:29 ` Wei Wang2
2011-11-03 13:35 ` Jan Beulich
0 siblings, 1 reply; 16+ messages in thread
From: Wei Wang2 @ 2011-11-03 13:29 UTC (permalink / raw)
To: Jan Beulich; +Cc: xen-devel@lists.xensource.com
On Thursday 03 November 2011 13:52:18 Jan Beulich wrote:
> >>> On 03.11.11 at 13:49, "Jan Beulich" <JBeulich@suse.com> wrote:
> >>>> On 03.11.11 at 11:13, Wei Wang <wei.wang2@amd.com> wrote:
> >>
> >> # HG changeset patch
> >> # User Wei Wang <wei.wang2@amd.com>
> >> # Date 1320314617 -3600
> >> # Node ID d0c38cb215cd96e01de27eadf5ec0a5e711de448
> >> # Parent d422e3cf7976c76c57fc2d455b784d0fcc24d06b
> >> amd iommu: Fix iommu page size encoding when page order > 0
> >>
> >> Signed-off-by: Wei Wang <wei.wang2@amd.com>
> >>
> >> diff -r d422e3cf7976 -r d0c38cb215cd
> >> xen/drivers/passthrough/amd/iommu_map.c ---
> >> a/xen/drivers/passthrough/amd/iommu_map.c Thu Nov 03 11:02:17 2011 +0100
> >> +++ b/xen/drivers/passthrough/amd/iommu_map.c Thu Nov 03 11:03:37 2011
> >> +0100 @@ -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 )
> >
> > Note the difference between this and your adjusted definition
> > of INV_IOMMU_ALL_PAGES_ADDRESS. I don't think this is
> > correct (or else your patch description should say why).
> >
> >> - {
> >> - 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);
> >
> > Same here, for a slightly different reason.
> >
> > Jan
> >
> >> }
> >>
> >> void amd_iommu_flush_pages(struct domain *d,
> >> diff -r d422e3cf7976 -r d0c38cb215cd
> >> xen/include/asm-x86/hvm/svm/amd-iommu-defs.h ---
> >> a/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h Thu Nov 03 11:02:17 2011
> >> +0100 +++ b/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h Thu Nov 03
> >> 11:03:37 2011 +0100
> >> @@ -407,4 +407,6 @@
> >> #define INT_REMAP_ENTRY_VECTOR_MASK 0x00FF0000
> >> #define INT_REMAP_ENTRY_VECTOR_SHIFT 16
> >>
> >> +#define INV_IOMMU_ALL_PAGES_ADDRESS 0x7FFFFFFFFFFFFFFFULL
> >> +
>
> Oh, additionally, this still isn't being expressed by a shift expression,
> which makes it still badly readable (one has to count F-s in order to
> know what this actually represents).
Well, this is a copy from the spec.. How about using (1<<63) -1?
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
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: Re: [PATCH 2 of 5] amd iommu: Fix iommu page size encoding when page order > 0
2011-11-03 13:29 ` Wei Wang2
@ 2011-11-03 13:35 ` Jan Beulich
0 siblings, 0 replies; 16+ messages in thread
From: Jan Beulich @ 2011-11-03 13:35 UTC (permalink / raw)
To: Wei Wang2; +Cc: xen-devel@lists.xensource.com
>>> On 03.11.11 at 14:29, Wei Wang2 <wei.wang2@amd.com> wrote:
> On Thursday 03 November 2011 13:52:18 Jan Beulich wrote:
>> >>> On 03.11.11 at 13:49, "Jan Beulich" <JBeulich@suse.com> wrote:
>> >>>> On 03.11.11 at 11:13, Wei Wang <wei.wang2@amd.com> wrote:
>> >> diff -r d422e3cf7976 -r d0c38cb215cd
>> >> xen/include/asm-x86/hvm/svm/amd-iommu-defs.h ---
>> >> a/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h Thu Nov 03 11:02:17 2011
>> >> +0100 +++ b/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h Thu Nov 03
>> >> 11:03:37 2011 +0100
>> >> @@ -407,4 +407,6 @@
>> >> #define INT_REMAP_ENTRY_VECTOR_MASK 0x00FF0000
>> >> #define INT_REMAP_ENTRY_VECTOR_SHIFT 16
>> >>
>> >> +#define INV_IOMMU_ALL_PAGES_ADDRESS 0x7FFFFFFFFFFFFFFFULL
>> >> +
>>
>> Oh, additionally, this still isn't being expressed by a shift expression,
>> which makes it still badly readable (one has to count F-s in order to
>> know what this actually represents).
> Well, this is a copy from the spec.. How about using (1<<63) -1?
Yes, that's what I asked for. Ideally with 63 also given a meaningful
#define (matchable to the spec).
Jan
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 2 of 5] amd iommu: Fix iommu page size encoding when page order > 0
2011-11-03 12:49 ` Jan Beulich
2011-11-03 12:52 ` Jan Beulich
@ 2011-11-03 13:26 ` Wei Wang2
2011-11-03 13:28 ` [PATCH 2 of 5] amd iommu: Fix iommu page size encoding when page order> 0 Jan Beulich
1 sibling, 1 reply; 16+ messages in thread
From: Wei Wang2 @ 2011-11-03 13:26 UTC (permalink / raw)
To: Jan Beulich; +Cc: xen-devel@lists.xensource.com
On Thursday 03 November 2011 13:49:39 Jan Beulich wrote:
> >>> On 03.11.11 at 11:13, Wei Wang <wei.wang2@amd.com> wrote:
> >
> > # HG changeset patch
> > # User Wei Wang <wei.wang2@amd.com>
> > # Date 1320314617 -3600
> > # Node ID d0c38cb215cd96e01de27eadf5ec0a5e711de448
> > # Parent d422e3cf7976c76c57fc2d455b784d0fcc24d06b
> > amd iommu: Fix iommu page size encoding when page order > 0
> >
> > Signed-off-by: Wei Wang <wei.wang2@amd.com>
> >
> > diff -r d422e3cf7976 -r d0c38cb215cd
> > xen/drivers/passthrough/amd/iommu_map.c ---
> > a/xen/drivers/passthrough/amd/iommu_map.c Thu Nov 03 11:02:17 2011 +0100
> > +++ b/xen/drivers/passthrough/amd/iommu_map.c Thu Nov 03 11:03:37 2011
> > +0100 @@ -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 )
>
> Note the difference between this and your adjusted definition
> of INV_IOMMU_ALL_PAGES_ADDRESS. I don't think this is
> correct (or else your patch description should say why).
>
> > - {
> > - 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);
>
> Same here, for a slightly different reason.
The old code is wrong, here should be 0x7FFFFFFFFFFFF000ULL (or
0x7FFFFFFFFFFFFULL << PAGE_SHIFT)
iommu does not care about the last 12 bits. So in this patch I just use
INV_IOMMU_ALL_PAGES_ADDRESS = 0x7FFFFFFFFFFFFFFFULL
Wei
> Jan
>
> > }
> >
> > void amd_iommu_flush_pages(struct domain *d,
> > diff -r d422e3cf7976 -r d0c38cb215cd
> > xen/include/asm-x86/hvm/svm/amd-iommu-defs.h ---
> > a/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h Thu Nov 03 11:02:17 2011
> > +0100 +++ b/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h Thu Nov 03
> > 11:03:37 2011 +0100
> > @@ -407,4 +407,6 @@
> > #define INT_REMAP_ENTRY_VECTOR_MASK 0x00FF0000
> > #define INT_REMAP_ENTRY_VECTOR_SHIFT 16
> >
> > +#define INV_IOMMU_ALL_PAGES_ADDRESS 0x7FFFFFFFFFFFFFFFULL
> > +
> > #endif /* _ASM_X86_64_AMD_IOMMU_DEFS_H */
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH 2 of 5] amd iommu: Fix iommu page size encoding when page order> 0
2011-11-03 13:26 ` Wei Wang2
@ 2011-11-03 13:28 ` Jan Beulich
0 siblings, 0 replies; 16+ messages in thread
From: Jan Beulich @ 2011-11-03 13:28 UTC (permalink / raw)
To: Wei Wang2; +Cc: xen-devel@lists.xensource.com
>>> On 03.11.11 at 14:26, Wei Wang2 <wei.wang2@amd.com> wrote:
> On Thursday 03 November 2011 13:49:39 Jan Beulich wrote:
>> >>> On 03.11.11 at 11:13, Wei Wang <wei.wang2@amd.com> wrote:
>> >
>> > # HG changeset patch
>> > # User Wei Wang <wei.wang2@amd.com>
>> > # Date 1320314617 -3600
>> > # Node ID d0c38cb215cd96e01de27eadf5ec0a5e711de448
>> > # Parent d422e3cf7976c76c57fc2d455b784d0fcc24d06b
>> > amd iommu: Fix iommu page size encoding when page order > 0
>> >
>> > Signed-off-by: Wei Wang <wei.wang2@amd.com>
>> >
>> > diff -r d422e3cf7976 -r d0c38cb215cd
>> > xen/drivers/passthrough/amd/iommu_map.c ---
>> > a/xen/drivers/passthrough/amd/iommu_map.c Thu Nov 03 11:02:17 2011 +0100
>> > +++ b/xen/drivers/passthrough/amd/iommu_map.c Thu Nov 03 11:03:37 2011
>> > +0100 @@ -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 )
>>
>> Note the difference between this and your adjusted definition
>> of INV_IOMMU_ALL_PAGES_ADDRESS. I don't think this is
>> correct (or else your patch description should say why).
>>
>> > - {
>> > - 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);
>>
>> Same here, for a slightly different reason.
>
> The old code is wrong, here should be 0x7FFFFFFFFFFFF000ULL (or
> 0x7FFFFFFFFFFFFULL << PAGE_SHIFT)
> iommu does not care about the last 12 bits. So in this patch I just use
> INV_IOMMU_ALL_PAGES_ADDRESS = 0x7FFFFFFFFFFFFFFFULL
Okay, in this case please state so in the patch description.
Jan
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 3 of 5] ats: Add new ATS helper functions
2011-11-03 10:13 [PATCH 0 of 5] amd iommu: Add ATS support (v3) Wei Wang
2011-11-03 10:13 ` [PATCH 1 of 5] ats: Move some ats functions to a new directory Wei Wang
2011-11-03 10:13 ` [PATCH 2 of 5] amd iommu: Fix iommu page size encoding when page order > 0 Wei Wang
@ 2011-11-03 10:13 ` Wei Wang
2011-11-03 10:13 ` [PATCH 4 of 5] amd iommu: add iotlb invalidation command Wei Wang
2011-11-03 10:13 ` [PATCH 5 of 5] amd iommu: enable ats devices Wei Wang
4 siblings, 0 replies; 16+ messages in thread
From: Wei Wang @ 2011-11-03 10:13 UTC (permalink / raw)
To: xen-devel; +Cc: JBeulich
# HG changeset patch
# User Wei Wang <wei.wang2@amd.com>
# Date 1320314663 -3600
# Node ID c839972486f86a0833595bebae0baa0cd2c0d15e
# Parent d0c38cb215cd96e01de27eadf5ec0a5e711de448
ats: Add new ATS helper functions
Signed-off-by Wei Wang <wei.wang2@amd.com>
diff -r d0c38cb215cd -r c839972486f8 xen/drivers/passthrough/ats.h
--- a/xen/drivers/passthrough/ats.h Thu Nov 03 11:03:37 2011 +0100
+++ b/xen/drivers/passthrough/ats.h Thu Nov 03 11:04:23 2011 +0100
@@ -21,6 +21,8 @@
#define ATS_QUEUE_DEPTH_MASK 0xF
#define ATS_ENABLE (1<<15)
+#include <xen/pci_regs.h>
+
struct pci_ats_dev {
struct list_head list;
u16 seg;
@@ -34,6 +36,27 @@ 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);
+}
#endif /* _ATS_H_ */
diff -r d0c38cb215cd -r c839972486f8 xen/drivers/passthrough/x86/ats.c
--- a/xen/drivers/passthrough/x86/ats.c Thu Nov 03 11:03:37 2011 +0100
+++ b/xen/drivers/passthrough/x86/ats.c Thu Nov 03 11:04:23 2011 +0100
@@ -137,3 +137,19 @@ void disable_ats_device(int seg, int bus
"%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;
+}
^ permalink raw reply [flat|nested] 16+ messages in thread* [PATCH 4 of 5] amd iommu: add iotlb invalidation command
2011-11-03 10:13 [PATCH 0 of 5] amd iommu: Add ATS support (v3) Wei Wang
` (2 preceding siblings ...)
2011-11-03 10:13 ` [PATCH 3 of 5] ats: Add new ATS helper functions Wei Wang
@ 2011-11-03 10:13 ` Wei Wang
2011-11-03 10:13 ` [PATCH 5 of 5] amd iommu: enable ats devices Wei Wang
4 siblings, 0 replies; 16+ messages in thread
From: Wei Wang @ 2011-11-03 10:13 UTC (permalink / raw)
To: xen-devel; +Cc: JBeulich
# HG changeset patch
# User Wei Wang <wei.wang2@amd.com>
# Date 1320314694 -3600
# Node ID c9dcbe6d80a355f1e50ff910d618660a78b40653
# Parent c839972486f86a0833595bebae0baa0cd2c0d15e
amd iommu: add iotlb invalidation command
Signed-off-by: Wei Wang <wei.wang2@amd.com>
diff -r c839972486f8 -r c9dcbe6d80a3 xen/drivers/passthrough/amd/iommu_map.c
--- a/xen/drivers/passthrough/amd/iommu_map.c Thu Nov 03 11:04:23 2011 +0100
+++ b/xen/drivers/passthrough/amd/iommu_map.c Thu Nov 03 11:04:54 2011 +0100
@@ -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(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 +967,63 @@ 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 = 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(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 c839972486f8 -r c9dcbe6d80a3 xen/include/asm-x86/hvm/svm/amd-iommu-defs.h
--- a/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h Thu Nov 03 11:04:23 2011 +0100
+++ b/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h Thu Nov 03 11:04:54 2011 +0100
@@ -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 c839972486f8 -r c9dcbe6d80a3 xen/include/asm-x86/hvm/svm/amd-iommu-proto.h
--- a/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h Thu Nov 03 11:04:23 2011 +0100
+++ b/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h Thu Nov 03 11:04:54 2011 +0100
@@ -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,
^ permalink raw reply [flat|nested] 16+ messages in thread* [PATCH 5 of 5] amd iommu: enable ats devices
2011-11-03 10:13 [PATCH 0 of 5] amd iommu: Add ATS support (v3) Wei Wang
` (3 preceding siblings ...)
2011-11-03 10:13 ` [PATCH 4 of 5] amd iommu: add iotlb invalidation command Wei Wang
@ 2011-11-03 10:13 ` Wei Wang
4 siblings, 0 replies; 16+ messages in thread
From: Wei Wang @ 2011-11-03 10:13 UTC (permalink / raw)
To: xen-devel; +Cc: JBeulich
# HG changeset patch
# User Wei Wang <wei.wang2@amd.com>
# Date 1320314731 -3600
# Node ID 7316595e8f47fcf5a106d897f99105a14d7e646c
# Parent c9dcbe6d80a355f1e50ff910d618660a78b40653
amd iommu: enable ats devices
Signed-off-by: Wei Wang <wei.wang2@amd.com>
diff -r c9dcbe6d80a3 -r 7316595e8f47 xen/drivers/passthrough/amd/iommu_map.c
--- a/xen/drivers/passthrough/amd/iommu_map.c Thu Nov 03 11:04:54 2011 +0100
+++ b/xen/drivers/passthrough/amd/iommu_map.c Thu Nov 03 11:05:31 2011 +0100
@@ -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)
{
diff -r c9dcbe6d80a3 -r 7316595e8f47 xen/drivers/passthrough/amd/pci_amd_iommu.c
--- a/xen/drivers/passthrough/amd/pci_amd_iommu.c Thu Nov 03 11:04:54 2011 +0100
+++ b/xen/drivers/passthrough/amd/pci_amd_iommu.c Thu Nov 03 11:05:31 2011 +0100
@@ -25,6 +25,7 @@
#include <asm/hvm/iommu.h>
#include <asm/amd-iommu.h>
#include <asm/hvm/svm/amd-iommu-proto.h>
+#include "../ats.h"
struct amd_iommu *find_iommu_for_device(int seg, int bdf)
{
@@ -86,6 +87,9 @@ static void amd_iommu_setup_domain_devic
void *dte;
unsigned long flags;
int req_id, valid = 1;
+ int dte_i = 0;
+ u8 bus = PCI_BUS(bdf);
+ u8 devfn = PCI_DEVFN2(bdf);
struct hvm_iommu *hd = domain_hvm_iommu(domain);
@@ -94,6 +98,9 @@ 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);
dte = iommu->dev_table.buffer + (req_id * IOMMU_DEV_TABLE_ENTRY_SIZE);
@@ -107,6 +114,10 @@ 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,11 +129,27 @@ 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) &&
+ !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);
+
+ ASSERT( pdev != NULL );
+ amd_iommu_flush_iotlb(pdev, INV_IOMMU_ALL_PAGES_ADDRESS, 0);
+ }
}
static void __init amd_iommu_setup_dom0_device(struct pci_dev *pdev)
{
- int bdf = (pdev->bus << 8) | pdev->devfn;
+ int bdf = PCI_BDF2(pdev->bus, pdev->devfn);
struct amd_iommu *iommu = find_iommu_for_device(pdev->seg, bdf);
if ( likely(iommu != NULL) )
@@ -261,12 +288,14 @@ 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, int bdf)
{
void *dte;
unsigned long flags;
int req_id;
+ u8 bus = PCI_BUS(bdf);
+ u8 devfn = PCI_DEVFN2(bdf);
BUG_ON ( iommu->dev_table.buffer == NULL );
req_id = get_dma_requestor_id(iommu->seg, bdf);
@@ -276,6 +305,11 @@ static void amd_iommu_disable_domain_dev
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 +318,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) &&
+ pci_ats_enabled(iommu->seg, bus, devfn) )
+ disable_ats_device(iommu->seg, bus, devfn);
}
static int reassign_device( struct domain *source, struct domain *target,
@@ -299,7 +339,7 @@ static int reassign_device( struct domai
if ( !pdev )
return -ENODEV;
- bdf = (bus << 8) | devfn;
+ bdf = PCI_BDF2(bus, devfn);
iommu = find_iommu_for_device(seg, bdf);
if ( !iommu )
{
@@ -421,7 +461,7 @@ static int amd_iommu_add_device(struct p
if ( !pdev->domain )
return -EINVAL;
- bdf = (pdev->bus << 8) | pdev->devfn;
+ bdf = PCI_BDF2(pdev->bus, pdev->devfn);
iommu = find_iommu_for_device(pdev->seg, bdf);
if ( !iommu )
{
@@ -443,7 +483,7 @@ static int amd_iommu_remove_device(struc
if ( !pdev->domain )
return -EINVAL;
- bdf = (pdev->bus << 8) | pdev->devfn;
+ bdf = PCI_BDF2(pdev->bus, pdev->devfn);
iommu = find_iommu_for_device(pdev->seg, bdf);
if ( !iommu )
{
diff -r c9dcbe6d80a3 -r 7316595e8f47 xen/include/asm-x86/hvm/svm/amd-iommu-proto.h
--- a/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h Thu Nov 03 11:04:54 2011 +0100
+++ b/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h Thu Nov 03 11:05:31 2011 +0100
@@ -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 */
^ permalink raw reply [flat|nested] 16+ messages in thread