From: Julien Grall <julien.grall@linaro.org> To: linux-kernel@vger.kernel.org, stefano.stabellini@eu.citrix.com Cc: linux-arm-kernel@lists.infradead.org, ian.campbell@citrix.com, xen-devel@lists.xenproject.org, Julien Grall <julien.grall@linaro.org>, Rob Herring <robh+dt@kernel.org>, Pawel Moll <pawel.moll@arm.com>, Mark Rutland <mark.rutland@arm.com>, Ian Campbell <ijc+devicetree@hellion.org.uk>, Kumar Gala <galak@codeaurora.org>, Rob Landley <rob@landley.net>, Russell King <linux@arm.linux.org.uk>, devicetree@vger.kernel.org Subject: [PATCH 2/2] arm/xen: Don't use xen DMA ops when the device is protected by an IOMMU Date: Thu, 20 Feb 2014 16:21:41 +0000 [thread overview] Message-ID: <1392913301-25524-1-git-send-email-julien.grall@linaro.org> (raw) Only Xen is able to know if a device can safely avoid to use xen-swiotlb. This patch introduce a new property "protected-devices" for the hypervisor node which list device which the IOMMU are been correctly programmed by Xen. During Linux boot, Xen specific code will create an hash table which contains all these devices. The hash table will be used in need_xen_dma_ops to check if the Xen DMA ops needs to be used for the current device. Signed-off-by: Julien Grall <julien.grall@linaro.org> Cc: Rob Herring <robh+dt@kernel.org> Cc: Pawel Moll <pawel.moll@arm.com> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Ian Campbell <ijc+devicetree@hellion.org.uk> Cc: Kumar Gala <galak@codeaurora.org> Cc: Rob Landley <rob@landley.net> Cc: Russell King <linux@arm.linux.org.uk> Cc: devicetree@vger.kernel.org --- Documentation/devicetree/bindings/arm/xen.txt | 2 + arch/arm/include/asm/xen/dma-mapping.h | 11 +++- arch/arm/xen/enlighten.c | 75 +++++++++++++++++++++++++ 3 files changed, 87 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/arm/xen.txt b/Documentation/devicetree/bindings/arm/xen.txt index 0f7b9c2..ee25a57 100644 --- a/Documentation/devicetree/bindings/arm/xen.txt +++ b/Documentation/devicetree/bindings/arm/xen.txt @@ -15,6 +15,8 @@ the following properties: - interrupts: the interrupt used by Xen to inject event notifications. A GIC node is also required. +- protected-devices: (optional) List of phandles to device node where the +IOMMU has been programmed by Xen. Example (assuming #address-cells = <2> and #size-cells = <2>): diff --git a/arch/arm/include/asm/xen/dma-mapping.h b/arch/arm/include/asm/xen/dma-mapping.h index 002fc57..da8e4fe 100644 --- a/arch/arm/include/asm/xen/dma-mapping.h +++ b/arch/arm/include/asm/xen/dma-mapping.h @@ -5,9 +5,18 @@ extern struct dma_map_ops *xen_dma_ops; +#ifdef CONFIG_XEN +bool xen_is_protected_device(const struct device *dev); +#else +static inline bool xen_is_protected_device(const struct device *dev) +{ + return 0; +} +#endif + static inline bool need_xen_dma_ops(struct device *dev) { - return xen_initial_domain(); + return xen_initial_domain() && !xen_is_protected_device(dev); } #endif /* _ASM_ARM_XEN_DMA_MAPPING_H */ diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c index b96723e..f124c8c 100644 --- a/arch/arm/xen/enlighten.c +++ b/arch/arm/xen/enlighten.c @@ -24,6 +24,7 @@ #include <linux/cpuidle.h> #include <linux/cpufreq.h> #include <linux/cpu.h> +#include <linux/hashtable.h> #include <linux/mm.h> @@ -53,6 +54,42 @@ EXPORT_SYMBOL_GPL(xen_platform_pci_unplug); static __read_mostly int xen_events_irq = -1; +/* Hash table for list of devices protected by an IOMMU in Xen */ +#define DEV_HASH_BITS 4 +#define DEV_HASH_SIZE (1 << DEV_HASH_BITS) + +static struct hlist_head *protected_devices; + +struct protected_device +{ + struct hlist_node hlist; + struct device_node *node; +}; + +static unsigned long pdev_hash(const struct device_node *node) +{ + return (node->phandle % DEV_HASH_SIZE); +} + +bool xen_is_protected_device(const struct device *dev) +{ + const struct device_node *node = dev->of_node; + unsigned long hash; + const struct protected_device *pdev; + + if (!node->phandle) + return 0; + + hash = pdev_hash(node); + + hlist_for_each_entry(pdev, &protected_devices[hash], hlist) { + if (node == pdev->node) + return 1; + } + + return 0; +} + /* map fgmfn of domid to lpfn in the current domain */ static int map_foreign_page(unsigned long lpfn, unsigned long fgmfn, unsigned int domid) @@ -235,6 +272,8 @@ static int __init xen_guest_init(void) const char *xen_prefix = "xen,xen-"; struct resource res; phys_addr_t grant_frames; + int i = 0; + struct device_node *dev; node = of_find_compatible_node(NULL, NULL, "xen,xen"); if (!node) { @@ -259,6 +298,31 @@ static int __init xen_guest_init(void) if (xen_events_irq < 0) return -ENODEV; + protected_devices = kmalloc(DEV_HASH_SIZE * sizeof (*protected_devices), + GFP_KERNEL); + if (!protected_devices) + return -ENOMEM; + + for (i = 0; i < DEV_HASH_SIZE; i++) + INIT_HLIST_HEAD(&protected_devices[i]); + + pr_info("List of protected devices:\n"); + i = 0; + while ((dev = of_parse_phandle(node, "protected-devices", i))) { + struct protected_device *pdev; + unsigned long hash; + + pr_info(" - %s\n", of_node_full_name(dev)); + pdev = kmalloc(sizeof (*pdev), GFP_KERNEL); + if (!pdev) + goto free_hash; + + pdev->node = dev; + hash = pdev_hash(dev); + hlist_add_head(&pdev->hlist, &protected_devices[hash]); + i++; + } + xen_domain_type = XEN_HVM_DOMAIN; xen_setup_features(); @@ -324,6 +388,17 @@ static int __init xen_guest_init(void) register_cpu_notifier(&xen_cpu_notifier); return 0; +free_hash: + for (i = 0; i < DEV_HASH_SIZE; i++) { + struct protected_device *pdev; + struct hlist_node *next; + + hlist_for_each_entry_safe(pdev, next, &protected_devices[i], + hlist) + kfree(pdev); + } + kfree(protected_devices); + return -ENOMEM; } early_initcall(xen_guest_init); -- 1.7.10.4
WARNING: multiple messages have this Message-ID (diff)
From: julien.grall@linaro.org (Julien Grall) To: linux-arm-kernel@lists.infradead.org Subject: [PATCH 2/2] arm/xen: Don't use xen DMA ops when the device is protected by an IOMMU Date: Thu, 20 Feb 2014 16:21:41 +0000 [thread overview] Message-ID: <1392913301-25524-1-git-send-email-julien.grall@linaro.org> (raw) Only Xen is able to know if a device can safely avoid to use xen-swiotlb. This patch introduce a new property "protected-devices" for the hypervisor node which list device which the IOMMU are been correctly programmed by Xen. During Linux boot, Xen specific code will create an hash table which contains all these devices. The hash table will be used in need_xen_dma_ops to check if the Xen DMA ops needs to be used for the current device. Signed-off-by: Julien Grall <julien.grall@linaro.org> Cc: Rob Herring <robh+dt@kernel.org> Cc: Pawel Moll <pawel.moll@arm.com> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Ian Campbell <ijc+devicetree@hellion.org.uk> Cc: Kumar Gala <galak@codeaurora.org> Cc: Rob Landley <rob@landley.net> Cc: Russell King <linux@arm.linux.org.uk> Cc: devicetree at vger.kernel.org --- Documentation/devicetree/bindings/arm/xen.txt | 2 + arch/arm/include/asm/xen/dma-mapping.h | 11 +++- arch/arm/xen/enlighten.c | 75 +++++++++++++++++++++++++ 3 files changed, 87 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/arm/xen.txt b/Documentation/devicetree/bindings/arm/xen.txt index 0f7b9c2..ee25a57 100644 --- a/Documentation/devicetree/bindings/arm/xen.txt +++ b/Documentation/devicetree/bindings/arm/xen.txt @@ -15,6 +15,8 @@ the following properties: - interrupts: the interrupt used by Xen to inject event notifications. A GIC node is also required. +- protected-devices: (optional) List of phandles to device node where the +IOMMU has been programmed by Xen. Example (assuming #address-cells = <2> and #size-cells = <2>): diff --git a/arch/arm/include/asm/xen/dma-mapping.h b/arch/arm/include/asm/xen/dma-mapping.h index 002fc57..da8e4fe 100644 --- a/arch/arm/include/asm/xen/dma-mapping.h +++ b/arch/arm/include/asm/xen/dma-mapping.h @@ -5,9 +5,18 @@ extern struct dma_map_ops *xen_dma_ops; +#ifdef CONFIG_XEN +bool xen_is_protected_device(const struct device *dev); +#else +static inline bool xen_is_protected_device(const struct device *dev) +{ + return 0; +} +#endif + static inline bool need_xen_dma_ops(struct device *dev) { - return xen_initial_domain(); + return xen_initial_domain() && !xen_is_protected_device(dev); } #endif /* _ASM_ARM_XEN_DMA_MAPPING_H */ diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c index b96723e..f124c8c 100644 --- a/arch/arm/xen/enlighten.c +++ b/arch/arm/xen/enlighten.c @@ -24,6 +24,7 @@ #include <linux/cpuidle.h> #include <linux/cpufreq.h> #include <linux/cpu.h> +#include <linux/hashtable.h> #include <linux/mm.h> @@ -53,6 +54,42 @@ EXPORT_SYMBOL_GPL(xen_platform_pci_unplug); static __read_mostly int xen_events_irq = -1; +/* Hash table for list of devices protected by an IOMMU in Xen */ +#define DEV_HASH_BITS 4 +#define DEV_HASH_SIZE (1 << DEV_HASH_BITS) + +static struct hlist_head *protected_devices; + +struct protected_device +{ + struct hlist_node hlist; + struct device_node *node; +}; + +static unsigned long pdev_hash(const struct device_node *node) +{ + return (node->phandle % DEV_HASH_SIZE); +} + +bool xen_is_protected_device(const struct device *dev) +{ + const struct device_node *node = dev->of_node; + unsigned long hash; + const struct protected_device *pdev; + + if (!node->phandle) + return 0; + + hash = pdev_hash(node); + + hlist_for_each_entry(pdev, &protected_devices[hash], hlist) { + if (node == pdev->node) + return 1; + } + + return 0; +} + /* map fgmfn of domid to lpfn in the current domain */ static int map_foreign_page(unsigned long lpfn, unsigned long fgmfn, unsigned int domid) @@ -235,6 +272,8 @@ static int __init xen_guest_init(void) const char *xen_prefix = "xen,xen-"; struct resource res; phys_addr_t grant_frames; + int i = 0; + struct device_node *dev; node = of_find_compatible_node(NULL, NULL, "xen,xen"); if (!node) { @@ -259,6 +298,31 @@ static int __init xen_guest_init(void) if (xen_events_irq < 0) return -ENODEV; + protected_devices = kmalloc(DEV_HASH_SIZE * sizeof (*protected_devices), + GFP_KERNEL); + if (!protected_devices) + return -ENOMEM; + + for (i = 0; i < DEV_HASH_SIZE; i++) + INIT_HLIST_HEAD(&protected_devices[i]); + + pr_info("List of protected devices:\n"); + i = 0; + while ((dev = of_parse_phandle(node, "protected-devices", i))) { + struct protected_device *pdev; + unsigned long hash; + + pr_info(" - %s\n", of_node_full_name(dev)); + pdev = kmalloc(sizeof (*pdev), GFP_KERNEL); + if (!pdev) + goto free_hash; + + pdev->node = dev; + hash = pdev_hash(dev); + hlist_add_head(&pdev->hlist, &protected_devices[hash]); + i++; + } + xen_domain_type = XEN_HVM_DOMAIN; xen_setup_features(); @@ -324,6 +388,17 @@ static int __init xen_guest_init(void) register_cpu_notifier(&xen_cpu_notifier); return 0; +free_hash: + for (i = 0; i < DEV_HASH_SIZE; i++) { + struct protected_device *pdev; + struct hlist_node *next; + + hlist_for_each_entry_safe(pdev, next, &protected_devices[i], + hlist) + kfree(pdev); + } + kfree(protected_devices); + return -ENOMEM; } early_initcall(xen_guest_init); -- 1.7.10.4
next reply other threads:[~2014-02-20 16:22 UTC|newest] Thread overview: 35+ messages / expand[flat|nested] mbox.gz Atom feed top 2014-02-20 16:21 Julien Grall [this message] 2014-02-20 16:21 ` [PATCH 2/2] arm/xen: Don't use xen DMA ops when the device is protected by an IOMMU Julien Grall 2014-02-20 16:35 ` Ian Campbell 2014-02-20 16:35 ` Ian Campbell 2014-02-20 16:35 ` Ian Campbell 2014-02-20 16:35 ` Ian Campbell 2014-02-24 12:19 ` Stefano Stabellini 2014-02-24 12:19 ` Stefano Stabellini 2014-02-24 12:19 ` Stefano Stabellini 2014-02-24 15:16 ` gregkh 2014-02-24 15:16 ` gregkh at linuxfoundation.org 2014-02-24 15:16 ` gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r 2014-02-24 20:49 ` Stefano Stabellini 2014-02-24 20:49 ` Stefano Stabellini 2014-02-24 20:49 ` Stefano Stabellini 2014-03-01 15:33 ` Julien Grall 2014-03-01 15:33 ` Julien Grall 2014-03-01 15:33 ` Julien Grall 2014-03-01 15:33 ` Julien Grall 2014-03-14 16:50 ` Julien Grall 2014-03-14 16:50 ` Julien Grall 2014-03-14 16:50 ` Julien Grall 2014-03-14 16:50 ` Julien Grall 2014-03-14 23:56 ` gregkh 2014-03-14 23:56 ` gregkh 2014-03-14 23:56 ` gregkh at linuxfoundation.org 2014-03-14 23:56 ` gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r 2014-02-24 20:49 ` Stefano Stabellini 2014-02-24 15:16 ` gregkh 2014-02-24 12:19 ` Stefano Stabellini 2014-02-20 17:13 ` Ian Campbell 2014-02-20 17:13 ` Ian Campbell 2014-02-20 17:13 ` Ian Campbell 2014-02-20 17:13 ` Ian Campbell 2014-02-20 16:21 Julien Grall
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=1392913301-25524-1-git-send-email-julien.grall@linaro.org \ --to=julien.grall@linaro.org \ --cc=devicetree@vger.kernel.org \ --cc=galak@codeaurora.org \ --cc=ian.campbell@citrix.com \ --cc=ijc+devicetree@hellion.org.uk \ --cc=linux-arm-kernel@lists.infradead.org \ --cc=linux-kernel@vger.kernel.org \ --cc=linux@arm.linux.org.uk \ --cc=mark.rutland@arm.com \ --cc=pawel.moll@arm.com \ --cc=rob@landley.net \ --cc=robh+dt@kernel.org \ --cc=stefano.stabellini@eu.citrix.com \ --cc=xen-devel@lists.xenproject.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.