From: Ian Campbell <Ian.Campbell@citrix.com>
To: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Cc: <xen-devel@lists.xensource.com>, <linux-kernel@vger.kernel.org>,
<linux-arm-kernel@lists.infradead.org>, <konrad.wilk@oracle.com>
Subject: Re: [PATCH v9 03/18] arm/xen,arm64/xen: introduce p2m
Date: Thu, 7 Nov 2013 14:42:08 +0000 [thread overview]
Message-ID: <1383835328.32399.45.camel@kazak.uk.xensource.com> (raw)
In-Reply-To: <1382698313-13161-3-git-send-email-stefano.stabellini@eu.citrix.com>
On Fri, 2013-10-25 at 11:51 +0100, Stefano Stabellini wrote:
> Introduce physical to machine and machine to physical tracking
> mechanisms based on rbtrees for arm/xen and arm64/xen.
>
> We need it because any guests on ARM are an autotranslate guests,
> therefore a physical address is potentially different from a machine
> address. When programming a device to do DMA, we need to be
> extra-careful to use machine addresses rather than physical addresses to
> program the device. Therefore we need to know the physical to machine
> mappings.
>
> For the moment we assume that dom0 starts with a 1:1 physical to machine
> mapping, in other words physical addresses correspond to machine
> addresses. However when mapping a foreign grant reference, obviously the
> 1:1 model doesn't work anymore. So at the very least we need to be able
> to track grant mappings.
>
> We need locking to protect accesses to the two trees.
>
> Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
>
> Changes in v8:
> - move pfn_to_mfn and mfn_to_pfn to page.h as static inline functions;
> - no need to walk the tree if phys_to_mach.rb_node is NULL;
> - correctly handle multipage p2m entries;
> - substitute the spin_lock with a rwlock.
> ---
> arch/arm/include/asm/xen/page.h | 49 ++++++++--
> arch/arm/xen/Makefile | 2 +-
> arch/arm/xen/p2m.c | 208 +++++++++++++++++++++++++++++++++++++++
> arch/arm64/xen/Makefile | 2 +-
> 4 files changed, 252 insertions(+), 9 deletions(-)
> create mode 100644 arch/arm/xen/p2m.c
>
> diff --git a/arch/arm/include/asm/xen/page.h b/arch/arm/include/asm/xen/page.h
> index 359a7b5..d1b5dd5 100644
> --- a/arch/arm/include/asm/xen/page.h
> +++ b/arch/arm/include/asm/xen/page.h
> @@ -7,11 +7,10 @@
> #include <linux/pfn.h>
> #include <linux/types.h>
>
> +#include <xen/xen.h>
> #include <xen/interface/grant_table.h>
>
> -#define pfn_to_mfn(pfn) (pfn)
> #define phys_to_machine_mapping_valid(pfn) (1)
> -#define mfn_to_pfn(mfn) (mfn)
> #define mfn_to_virt(m) (__va(mfn_to_pfn(m) << PAGE_SHIFT))
>
> #define pte_mfn pte_pfn
> @@ -32,6 +31,44 @@ typedef struct xpaddr {
>
> #define INVALID_P2M_ENTRY (~0UL)
>
> +unsigned long __pfn_to_mfn(unsigned long pfn);
> +unsigned long __mfn_to_pfn(unsigned long mfn);
> +extern struct rb_root phys_to_mach;
> +
> +static inline unsigned long pfn_to_mfn(unsigned long pfn)
> +{
> + unsigned long mfn;
> +
> + if (phys_to_mach.rb_node != NULL) {
> + mfn = __pfn_to_mfn(pfn);
> + if (mfn != INVALID_P2M_ENTRY)
> + return mfn;
> + }
> +
> + if (xen_initial_domain())
> + return pfn;
> + else
> + return INVALID_P2M_ENTRY;
This breaks domU ballooning (for some reason only on 64-bit, I've no
clue why not 32-bit).
decrease_reservation does pfn_to_mfn in order to release the page, and
this ends up passing INVALID_P2M_ENTRY, which the hypervisor rightly
rejects.
> +static inline unsigned long mfn_to_pfn(unsigned long mfn)
> +{
> + unsigned long pfn;
> +
> + if (phys_to_mach.rb_node != NULL) {
> + pfn = __mfn_to_pfn(mfn);
> + if (pfn != INVALID_P2M_ENTRY)
> + return pfn;
> + }
> +
> + if (xen_initial_domain())
> + return mfn;
> + else
> + return INVALID_P2M_ENTRY;
Same here I think.
Both of these should unconditionally return their inputs for !
xen_initial_domain() I think. I presume hys_to_mach.rb_node != NULL
should never trigger for a domU?
> +static int xen_add_phys_to_mach_entry(struct xen_p2m_entry *new)
> +{
> + struct rb_node **link = &phys_to_mach.rb_node;
> + struct rb_node *parent = NULL;
> + struct xen_p2m_entry *entry;
> + int rc = 0;
> +
> + while (*link) {
> + parent = *link;
> + entry = rb_entry(parent, struct xen_p2m_entry, rbnode_phys);
> +
> + if (new->mfn == entry->mfn)
> + goto err_out;
> + if (new->pfn == entry->pfn)
> + goto err_out;
> +
> + if (new->pfn < entry->pfn)
> + link = &(*link)->rb_left;
> + else
> + link = &(*link)->rb_right;
> + }
Are there really no helpers for walking an rbtree?
> + rb_link_node(&new->rbnode_phys, parent, link);
> + rb_insert_color(&new->rbnode_phys, &phys_to_mach);
> + goto out;
> +
> +err_out:
> + rc = -EINVAL;
> + pr_warn("%s: cannot add pfn=%pa -> mfn=%pa: pfn=%pa -> mfn=%pa already exists\n",
> + __func__, &new->pfn, &new->mfn, &entry->pfn, &entry->mfn);
> +out:
> + return rc;
> +}
> +
> +unsigned long __pfn_to_mfn(unsigned long pfn)
> +{
> + struct rb_node *n = phys_to_mach.rb_node;
> + struct xen_p2m_entry *entry;
> + unsigned long irqflags;
> +
> + read_lock_irqsave(&p2m_lock, irqflags);
> + while (n) {
> + entry = rb_entry(n, struct xen_p2m_entry, rbnode_phys);
> + if (entry->pfn <= pfn &&
> + entry->pfn + entry->nr_pages > pfn) {
> + read_unlock_irqrestore(&p2m_lock, irqflags);
> + return entry->mfn + (pfn - entry->pfn);
> + }
> + if (pfn < entry->pfn)
> + n = n->rb_left;
> + else
> + n = n->rb_right;
> + }
> + read_unlock_irqrestore(&p2m_lock, irqflags);
> +
> + return INVALID_P2M_ENTRY;
> +}
> +EXPORT_SYMBOL_GPL(__pfn_to_mfn);
> +
> +static int xen_add_mach_to_phys_entry(struct xen_p2m_entry *new)
> +{
> + struct rb_node **link = &mach_to_phys.rb_node;
> + struct rb_node *parent = NULL;
> + struct xen_p2m_entry *entry;
> + int rc = 0;
> +
> + while (*link) {
> + parent = *link;
> + entry = rb_entry(parent, struct xen_p2m_entry, rbnode_mach);
> +
> + if (new->mfn == entry->mfn)
> + goto err_out;
> + if (new->pfn == entry->pfn)
> + goto err_out;
> +
> + if (new->mfn < entry->mfn)
> + link = &(*link)->rb_left;
> + else
> + link = &(*link)->rb_right;
> + }
This looks close to identical to the one in xen_add_phys_to_mach_entry.
You could combine them with a simple "lookup mfn" boolean.
> + rb_link_node(&new->rbnode_mach, parent, link);
> + rb_insert_color(&new->rbnode_mach, &mach_to_phys);
> + goto out;
> +
> +err_out:
> + rc = -EINVAL;
> + pr_warn("%s: cannot add pfn=%pa -> mfn=%pa: pfn=%pa -> mfn=%pa already exists\n",
> + __func__, &new->pfn, &new->mfn, &entry->pfn, &entry->mfn);
> +out:
> + return rc;
> +}
> +
> +unsigned long __mfn_to_pfn(unsigned long mfn)
> +{
> + struct rb_node *n = mach_to_phys.rb_node;
> + struct xen_p2m_entry *entry;
> + unsigned long irqflags;
> +
> + read_lock_irqsave(&p2m_lock, irqflags);
> + while (n) {
> + entry = rb_entry(n, struct xen_p2m_entry, rbnode_mach);
> + if (entry->mfn <= mfn &&
> + entry->mfn + entry->nr_pages > mfn) {
> + read_unlock_irqrestore(&p2m_lock, irqflags);
> + return entry->pfn + (mfn - entry->mfn);
> + }
> + if (mfn < entry->mfn)
> + n = n->rb_left;
> + else
> + n = n->rb_right;
> + }
and this looks basically identical to __pfn_to_mfn in the same way.
> + read_unlock_irqrestore(&p2m_lock, irqflags);
> +
> + return INVALID_P2M_ENTRY;
> +}
> +EXPORT_SYMBOL_GPL(__mfn_to_pfn);
> +
Ian.
next prev parent reply other threads:[~2013-11-07 14:42 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-10-25 10:51 [PATCH v9 0/18] enable swiotlb-xen on arm and arm64 Stefano Stabellini
2013-10-25 10:51 ` [PATCH v9 01/18] arm: make SWIOTLB available Stefano Stabellini
2013-10-25 11:08 ` Stefano Stabellini
2013-10-29 4:41 ` Stefano Stabellini
2013-10-29 14:20 ` Konrad Rzeszutek Wilk
2013-10-29 14:26 ` Russell King - ARM Linux
2013-10-29 17:24 ` Stefano Stabellini
2013-10-29 18:01 ` Russell King - ARM Linux
2013-10-30 1:17 ` Stefano Stabellini
2013-11-04 18:38 ` Stefano Stabellini
2013-10-25 10:51 ` [PATCH v9 02/18] arm64: define DMA_ERROR_CODE Stefano Stabellini
2013-10-25 10:51 ` [PATCH v9 03/18] arm/xen,arm64/xen: introduce p2m Stefano Stabellini
2013-11-07 14:42 ` Ian Campbell [this message]
2013-11-07 15:52 ` Stefano Stabellini
2013-10-25 10:51 ` [PATCH v9 04/18] xen/x86: allow __set_phys_to_machine for autotranslate guests Stefano Stabellini
2013-10-25 10:51 ` [PATCH v9 05/18] xen: make xen_create_contiguous_region return the dma address Stefano Stabellini
2013-10-25 10:51 ` [PATCH v9 06/18] xen/arm,arm64: enable SWIOTLB_XEN Stefano Stabellini
2013-10-25 10:51 ` [PATCH v9 07/18] swiotlb-xen: introduce xen_swiotlb_set_dma_mask Stefano Stabellini
2013-10-25 10:51 ` [PATCH v9 08/18] arm/xen: get_dma_ops: return xen_dma_ops if we are running as xen_initial_domain Stefano Stabellini
2013-10-25 10:51 ` [PATCH v9 09/18] arm64/xen: " Stefano Stabellini
2013-10-25 10:51 ` [PATCH v9 10/18] xen: introduce xen_alloc/free_coherent_pages Stefano Stabellini
2013-10-25 10:51 ` [PATCH v9 11/18] swiotlb-xen: use xen_alloc/free_coherent_pages Stefano Stabellini
2013-10-25 10:51 ` [PATCH v9 12/18] xen: introduce xen_dma_map/unmap_page and xen_dma_sync_single_for_cpu/device Stefano Stabellini
2013-10-25 10:51 ` [PATCH v9 13/18] swiotlb-xen: use xen_dma_map/unmap_page, xen_dma_sync_single_for_cpu/device Stefano Stabellini
2013-10-25 10:51 ` [PATCH v9 14/18] ASoC: Samsung: Rename dma_ops by samsung_dma_ops Stefano Stabellini
2013-10-25 10:51 ` [PATCH v9 15/18] swiotlb: print a warning when the swiotlb is full Stefano Stabellini
2013-10-25 10:51 ` [PATCH v9 16/18] arm,arm64: do not always merge biovec if we are running on Xen Stefano Stabellini
2013-11-05 22:46 ` Olof Johansson
2013-11-06 12:40 ` Stefano Stabellini
2013-11-06 15:27 ` Olof Johansson
2013-10-25 10:51 ` [PATCH v9 17/18] grant-table: call set_phys_to_machine after mapping grant refs Stefano Stabellini
2013-10-25 10:51 ` [PATCH v9 18/18] swiotlb-xen: static inline xen_phys_to_bus, xen_bus_to_phys, xen_virt_to_bus and range_straddles_page_boundary Stefano Stabellini
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=1383835328.32399.45.camel@kazak.uk.xensource.com \
--to=ian.campbell@citrix.com \
--cc=konrad.wilk@oracle.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=stefano.stabellini@eu.citrix.com \
--cc=xen-devel@lists.xensource.com \
/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: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox