All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v5 0/8] Implement the XEN_DOMCTL_memory_mapping hypercall for ARM
@ 2014-04-06 23:31 Arianna Avanzini
  2014-04-06 23:31 ` [PATCH v5 1/8] arch, arm: domain build: let dom0 access I/O memory of mapped devices Arianna Avanzini
                   ` (7 more replies)
  0 siblings, 8 replies; 19+ messages in thread
From: Arianna Avanzini @ 2014-04-06 23:31 UTC (permalink / raw)
  To: xen-devel
  Cc: Ian.Campbell, paolo.valente, keir, stefano.stabellini,
	Ian.Jackson, dario.faggioli, tim, julien.grall, etrudeau,
	JBeulich, avanzini.arianna, viktor.kleinik

Hello,

here is my fifth attempt at proposing an implementation of the memory_mapping
DOMCTL for the ARM architecture. The following patchset adds both the proposed
implementation of the hypercall and some related changes made to existing code
after having the benefit of many comments to the previous proposal attempts
([1]). As of those previous discussions, I'm not summarizing them in the below
description to prevent this cover letter from becoming much longer than
appropriate, but more details should be available, if needed, in the cover
letter of the third and fourth patchsets ([2]).

I am aware of the fact that there is still on-going discussion about the
previous version of this patchset ([3]), but, as also suggested by Stefano
Stabellini, I thought I'd send this new version to try to get rid of the most
immediate issues that have been highlighted.

The first commit in this patchset implements the bookkeeping operations deemed
necessary to make a domain's iomem_caps coherent with the I/O-memory mapping
operations performed during domain build. As of now, the change is dom0-related,
even if the function affected by the change if generic.

The second commit adds to the apply_p2m_changes() function some consistency
checks useful for the REMOVE operation. More in detail, the REMOVE switch of
the function now checks:
. the validity of the mapping: if the mapping is found not to be valid, the
  page is skipped;
. the fact that the gfn whose mapping is to be removed is actually mapped to
  the machine address given as parameter.
With respect to v4, this commit uses the "maddr" parameter of the function to
keep the machine address used for the above-described comparison, incrementing
it where necessary (also when first and second level mappings are not valid), as
suggested by Julien Grall and Ian Campbell. It also gets the actual mfn mapped
to the gfn given as parameter to the function in the REMOVE case of the switch
construct, as in other cases it might be invalid and its value might be
uncorrectly used, as pointed out by Julien Grall. It also removes a harmful
ASSERT on the validity of the mapping, which was introduced by the v4 patchset
in the REMOVE case; the v5 commit turns it to an if(), as suggested by Julien
Grall.

The third commit changes the interface of the existing map_mmio_regions()
function for ARM. As of now, the function takes parameters of paddr_t type; this
interface needs caller functions to correctly page-align addresses. This commit
lets this function take page frame numbers as parameters instead, trying also to
modify callers to use the new interface. With respect to v4, the v5 commit adds
a macro for the paddr_to_pfn(PAGE_ALIGN(...)) pattern which was repeatedly used
throughout the patch, as pointed out by Julien Grall.
This commit still attempts to produce the minimum necessary changes; as a
consequence, it still does not modify also the interface of apply_p2m_changes(),
which instead was suggested by Stefano Stabellini.

The fourth commit adds to clear_mmio_p2m_entry() a check on the actual existence
of a mapping between the guest frame number and a machine frame number given as
parameter; the check is performed before removing such a mapping. This change
has been implemented after having been discussed with Jan Beulich, and should be
the equivalent of that added by commit 0002 of this patchset to the ARM-specific
code removing a p2m mapping.

The fifth commit moves the existing memory_mapping DOMCTL for x86 to
xen/common/domctl.c and attempts to adapt the code to be used for both the x86
and ARM architectures. More in detail, the arch-specific operations necessary to
map and unmap memory ranges are abstracted out in a pair of map_mmio_regions()
and unmap_mmio_regions() functions.
With respect to the v4 patchset, this commit attempts to address the following
issues.
. The unmap_mmio_regions() function for the x86 architecture now returns a
  proper error code, instead of relying on a wrongly-used true/false return
  value, as suggested by Jan Beulich.
. It restores the correct handling of return values from the iomem_deny_access()
  and unmap_mmio_regions() in the remove path of the hypercall, while the v4
  version uncorrectly let an error code returned by unmap_mmio_regions() be
  ignored, as pointed out by Jan Beulich and discussed with Stefano Stabellini.
. It adds to the new DOMCTL a comment which attempts to explain how error codes
  from the above functions are handled.
. It lets the DOMCTL compute gfn_end - 1 and mfn_end - 1 only once, as suggested
  by Jan Beulich.
. It uses a new local variable to keep the return value instead of re-using the
  "add" local variable, which was confusing as pointed out by Ian Campbell.
. It renames the newly-added header, common to the x86 and ARM architectures,
  from p2m.h to p2m-common.h, as suggested by Jan Beulich.  

The sixth commit adds to libxl the handling code for a new optional parameter to
the "iomem" configuration option. The new parameter, called "gfn", allows to
specify the start guest address used for the mapping of the given machine
address range; in case no start guest address is specified, the patch lets libxl
default its value to the start machine address.
With respect to the v4 corresponding one, this commit tries to address the
following issues, pointed out by Julien Grall and Ian Campbell.
. It uses -1 as a default value for the optional "gfn" parameter.
. It lets the default value of "gfn" be initialized with a proper call to the
  libxl_iomem_range_init() function.
. It defers to libxl the assignment of the "gfn" parameter to the start machine
  address, if "gfn" was initialized to its default value.
. It uses a local variable to keep the return value of the sscanf() function
  as to makes the code more readable.

The seventh commit adds two new architecture helpers to libxl: these helpers
should allow the caller to establish if a domain uses an auto-translated
physmap. This is instrumental to commit 0008, which needs to call the newly-
added DOMCTL only for auto-translated guests.

The eighth commit adds to libxl code to handle the iomem configuration option by
invoking the memory_mapping DOMCTL. The hypercall is invoked only if the domain
is auto-translated, by using the arch-specific helpers introduced with the
previous commit.

The code has been tested on a cubieboard2, with Linux v3.13 as a dom0 and ERIKA
Enterprise ([4]) as a domU.
As usual, any feedback about this new version is more than welcome.
Arianna

[1] http://markmail.org/message/d5vhhiin5tr2yee7
    http://markmail.org/message/dtzsvauzob332gnq
    http://markmail.org/message/fy7ioiv37gbp22an
    http://markmail.org/message/qca2nxrpe2dfwdks
[2] http://lists.xen.org/archives/html/xen-devel/2014-03/msg01724.html
    http://lists.xen.org/archives/html/xen-devel/2014-03/msg03138.html
[3] http://lists.xen.org/archives/html/xen-devel/2014-04/msg00118.html
    http://lists.xen.org/archives/html/xen-devel/2014-04/msg00123.html
[4] http://erika.tuxfamily.org/drupal/

Arianna Avanzini (8):
  arch, arm: domain build: let dom0 access I/O memory of mapped devices
  arch, arm: add consistency check to REMOVE p2m changes
  arch, arm: let map_mmio_regions() take pfn as parameters
  arch, x86: check if mapping exists before memory_mapping removes it
  xen, common: add the XEN_DOMCTL_memory_mapping hypercall
  tools, libxl: parse optional start gfn from the iomem config option
  tools, libxl: add helpers to establish if guest is auto-translated
  tools, libxl: handle the iomem parameter with the memory_mapping hcall

 docs/man/xl.cfg.pod.5                | 13 +++++--
 tools/libxl/libxl.h                  | 10 +++++
 tools/libxl/libxl_arch.h             |  2 +
 tools/libxl/libxl_arm.c              |  5 +++
 tools/libxl/libxl_create.c           | 19 ++++++++++
 tools/libxl/libxl_types.idl          |  7 +++-
 tools/libxl/libxl_x86.c              |  6 +++
 tools/libxl/xl_cmdimpl.c             | 19 +++++-----
 xen/arch/arm/domain_build.c          | 18 +++++++--
 xen/arch/arm/gic.c                   | 21 ++++++-----
 xen/arch/arm/p2m.c                   | 52 ++++++++++++++++++++++----
 xen/arch/arm/platforms/exynos5.c     | 12 +++---
 xen/arch/arm/platforms/omap5.c       | 21 ++++++-----
 xen/arch/arm/platforms/xgene-storm.c |  4 +-
 xen/arch/x86/domctl.c                | 70 -----------------------------------
 xen/arch/x86/mm/p2m.c                | 65 ++++++++++++++++++++++++++++++---
 xen/common/domctl.c                  | 71 ++++++++++++++++++++++++++++++++++++
 xen/include/asm-arm/mm.h             |  2 +
 xen/include/asm-arm/p2m.h            |  8 ++--
 xen/include/asm-x86/p2m.h            |  3 +-
 xen/include/xen/p2m-common.h         | 16 ++++++++
 21 files changed, 313 insertions(+), 131 deletions(-)
 create mode 100644 xen/include/xen/p2m-common.h

-- 
1.9.1

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH v5 1/8] arch, arm: domain build: let dom0 access I/O memory of mapped devices
  2014-04-06 23:31 [PATCH v5 0/8] Implement the XEN_DOMCTL_memory_mapping hypercall for ARM Arianna Avanzini
@ 2014-04-06 23:31 ` Arianna Avanzini
  2014-04-06 23:31 ` [PATCH v5 2/8] arch, arm: add consistency check to REMOVE p2m changes Arianna Avanzini
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 19+ messages in thread
From: Arianna Avanzini @ 2014-04-06 23:31 UTC (permalink / raw)
  To: xen-devel
  Cc: Ian.Campbell, paolo.valente, keir, stefano.stabellini,
	Ian.Jackson, dario.faggioli, tim, julien.grall, etrudeau,
	JBeulich, avanzini.arianna, viktor.kleinik

Currently, dom0 is allowed access to the I/O memory ranges used
to access devices exposed to it, but it doesn't have those
ranges in its iomem_caps. This commit attempts to implement the
correct bookkeeping in the generic function which actually maps
a device's I/O memory to the domain, adding the ranges to the
domain's iomem_caps.

Signed-off-by: Arianna Avanzini <avanzini.arianna@gmail.com>
Acked-by: Ian Campbell <Ian.Campbell@eu.citrix.com>
Acked-by: Julien Grall <julien.grall@citrix.com>
Cc: Dario Faggioli <dario.faggioli@citrix.com>
Cc: Paolo Valente <paolo.valente@unimore.it>
Cc: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Cc: Jan Beulich <JBeulich@suse.com>
Cc: Keir Fraser <keir@xen.org>
Cc: Tim Deegan <tim@xen.org>
Cc: Ian Jackson <Ian.Jackson@eu.citrix.com>
Cc: Eric Trudeau <etrudeau@broadcom.com>
Cc: Viktor Kleinik <viktor.kleinik@globallogic.com>

---

    v4:
        - Hopefully improve commit description.

    v3:
        - Print the domain id in the error message instead of always
          printing "dom0".
        - Fix commit description. 

---
 xen/arch/arm/domain_build.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 502db84..f4902bb 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -11,6 +11,7 @@
 #include <xen/device_tree.h>
 #include <xen/libfdt/libfdt.h>
 #include <xen/guest_access.h>
+#include <xen/iocap.h>
 #include <asm/setup.h>
 #include <asm/platform.h>
 #include <asm/psci.h>
@@ -733,6 +734,16 @@ static int map_device(struct domain *d, const struct dt_device_node *dev)
         DPRINT("addr %u = 0x%"PRIx64" - 0x%"PRIx64"\n",
                i, addr, addr + size - 1);
 
+        res = iomem_permit_access(d, paddr_to_pfn(addr & PAGE_MASK),
+                                  paddr_to_pfn(PAGE_ALIGN(addr + size - 1)));
+        if ( res )
+        {
+            printk(XENLOG_ERR "Unable to permit to dom%d access to"
+                   " 0x%"PRIx64" - 0x%"PRIx64"\n",
+                   d->domain_id,
+                   addr & PAGE_MASK, PAGE_ALIGN(addr + size) - 1);
+            return res;
+        }
         res = map_mmio_regions(d, addr & PAGE_MASK,
                                PAGE_ALIGN(addr + size) - 1,
                                addr & PAGE_MASK);
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v5 2/8] arch, arm: add consistency check to REMOVE p2m changes
  2014-04-06 23:31 [PATCH v5 0/8] Implement the XEN_DOMCTL_memory_mapping hypercall for ARM Arianna Avanzini
  2014-04-06 23:31 ` [PATCH v5 1/8] arch, arm: domain build: let dom0 access I/O memory of mapped devices Arianna Avanzini
@ 2014-04-06 23:31 ` Arianna Avanzini
  2014-04-07 11:05   ` Julien Grall
  2014-04-06 23:31 ` [PATCH v5 3/8] arch, arm: let map_mmio_regions() take pfn as parameters Arianna Avanzini
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 19+ messages in thread
From: Arianna Avanzini @ 2014-04-06 23:31 UTC (permalink / raw)
  To: xen-devel
  Cc: Ian.Campbell, paolo.valente, keir, stefano.stabellini,
	Ian.Jackson, dario.faggioli, tim, julien.grall, etrudeau,
	JBeulich, avanzini.arianna, viktor.kleinik

Currently, the REMOVE case of the switch in apply_p2m_changes()
does not perform any consistency check on the mapping to be removed.
More in detail, the code does not check if the guest address to be
unmapped is actually mapped to the machine address given as a
parameter.
This commit attempts to add the above-described consistency check
to the REMOVE path of apply_p2m_changes(). This is instrumental to
one of the following commits which implements the possibility to
trigger the removal of p2m ranges via the memory_mapping DOMCTL
for ARM.

Signed-off-by: Arianna Avanzini <avanzini.arianna@gmail.com>
Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Cc: Dario Faggioli <dario.faggioli@citrix.com>
Cc: Paolo Valente <paolo.valente@unimore.it>
Cc: Julien Grall <julien.grall@citrix.com>
Cc: Ian Campbell <Ian.Campbell@eu.citrix.com>
Cc: Jan Beulich <JBeulich@suse.com>
Cc: Keir Fraser <keir@xen.org>
Cc: Tim Deegan <tim@xen.org>
Cc: Ian Jackson <Ian.Jackson@eu.citrix.com>
Cc: Eric Trudeau <etrudeau@broadcom.com>
Cc: Viktor Kleinik <viktor.kleinik@globallogic.com>

---

    v5:
        - Do not use a temporary variable to hold the machine address:
          use the "maddr" function parameter itself.
        - Increment the machine address also when first and second level
          mappings are not valid.
        - Get the actual machine frame number mapped to the guest frame
          number given as parameter to the function directly in the
          REMOVE case of the switch construct, as it might not be valid
          in other cases and its value might be uncorrectly used in the
          future.
        - Remove useless and/or harmful ASSERT; check however if the
          mapping is valid and skip the page if it is not.

    v4:
        - Remove useless and slow lookup and use already-available
          data from pte instead.
        - Correctly increment the local variable used to keep the
          machine address whose mapping is currently being removed.
        - Return with an error upon finding a mismatch between the
          actual machine address mapped to the guest address and
          the machine address passed as parameter, instead of just
          skipping the page.

---
 xen/arch/arm/p2m.c | 27 +++++++++++++++++++++++++--
 1 file changed, 25 insertions(+), 2 deletions(-)

diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
index 403fd89..395a0b2 100644
--- a/xen/arch/arm/p2m.c
+++ b/xen/arch/arm/p2m.c
@@ -319,6 +319,7 @@ static int apply_p2m_changes(struct domain *d,
             if ( !populate )
             {
                 addr = (addr + FIRST_SIZE) & FIRST_MASK;
+                maddr = (maddr + FIRST_SIZE) & FIRST_MASK;
                 continue;
             }
 
@@ -345,6 +346,7 @@ static int apply_p2m_changes(struct domain *d,
             if ( !populate )
             {
                 addr = (addr + SECOND_SIZE) & SECOND_MASK;
+                maddr = (maddr + SECOND_SIZE) & SECOND_MASK;
                 continue;
             }
 
@@ -406,12 +408,32 @@ static int apply_p2m_changes(struct domain *d,
                 {
                     pte = mfn_to_p2m_entry(maddr >> PAGE_SHIFT, mattr, t);
                     write_pte(&third[third_table_offset(addr)], pte);
-                    maddr += PAGE_SIZE;
                 }
                 break;
-            case RELINQUISH:
             case REMOVE:
                 {
+                    unsigned long mfn;
+
+                    if ( !pte.p2m.valid )
+                    {
+                        count++;
+                        break;
+                    }
+                    mfn = pte.p2m.base;
+                    /*
+                     * Ensure that the guest address given as argument to
+                     * this function is actually mapped to the specified
+                     * machine address. maddr here is the machine address
+                     * given to the function, while mfn is the machine
+                     * frame number actually mapped to the guest address:
+                     * check if the two correspond.
+                     */
+                    if ( maddr != pfn_to_paddr(mfn) )
+                        return -EINVAL;
+                }
+                /* fall through */
+            case RELINQUISH:
+                {
                     if ( !pte.p2m.valid )
                     {
                         count++;
@@ -450,6 +472,7 @@ static int apply_p2m_changes(struct domain *d,
 
         /* Got the next page */
         addr += PAGE_SIZE;
+        maddr += PAGE_SIZE;
     }
 
     if ( flush )
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v5 3/8] arch, arm: let map_mmio_regions() take pfn as parameters
  2014-04-06 23:31 [PATCH v5 0/8] Implement the XEN_DOMCTL_memory_mapping hypercall for ARM Arianna Avanzini
  2014-04-06 23:31 ` [PATCH v5 1/8] arch, arm: domain build: let dom0 access I/O memory of mapped devices Arianna Avanzini
  2014-04-06 23:31 ` [PATCH v5 2/8] arch, arm: add consistency check to REMOVE p2m changes Arianna Avanzini
@ 2014-04-06 23:31 ` Arianna Avanzini
  2014-04-07 14:56   ` Julien Grall
  2014-04-09 13:54   ` Ian Campbell
  2014-04-06 23:31 ` [PATCH v5 4/8] arch, x86: check if mapping exists before memory_mapping removes it Arianna Avanzini
                   ` (4 subsequent siblings)
  7 siblings, 2 replies; 19+ messages in thread
From: Arianna Avanzini @ 2014-04-06 23:31 UTC (permalink / raw)
  To: xen-devel
  Cc: Ian.Campbell, paolo.valente, keir, stefano.stabellini,
	Ian.Jackson, dario.faggioli, tim, julien.grall, etrudeau,
	JBeulich, avanzini.arianna, viktor.kleinik

Currently, the map_mmio_regions() function, defined for the ARM
architecture, has parameters with paddr_t type. This interface,
however, needs caller functions to correctly page-align addresses
given as parameters to map_mmio_regions(). This commit changes the
function's interface to accept page frame numbers as parameters.
This commit also modifies caller functions in an attempt to adapt
them to the new interface.
This commit attempts to produce the minimum indispensable needed
changes; these are also instrumental to making the interface of
map_mmio_regions() symmetric with the unmap_mmio_regions() function,
that will be introduced in one of the next commits of the series
and will feature a pfn-based interface.

NOTE: platform-specific code has not been tested.

Signed-off-by: Arianna Avanzini <avanzini.arianna@gmail.com>
Cc: Dario Faggioli <dario.faggioli@citrix.com>
Cc: Paolo Valente <paolo.valente@unimore.it>
Cc: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Cc: Julien Grall <julien.grall@citrix.com>
Cc: Ian Campbell <Ian.Campbell@eu.citrix.com>
Cc: Jan Beulich <JBeulich@suse.com>
Cc: Keir Fraser <keir@xen.org>
Cc: Tim Deegan <tim@xen.org>
Cc: Ian Jackson <Ian.Jackson@eu.citrix.com>
Cc: Eric Trudeau <etrudeau@broadcom.com>
Cc: Viktor Kleinik <viktor.kleinik@globallogic.com>

---

    v5:
        - Add a macro for the paddr_to_pfn(PAGE_ALIGN(...)) pattern.
        - Hopefully improve commit description.

---
 xen/arch/arm/domain_build.c          |  7 ++++---
 xen/arch/arm/gic.c                   | 21 ++++++++++++---------
 xen/arch/arm/p2m.c                   | 13 ++++++++-----
 xen/arch/arm/platforms/exynos5.c     | 12 +++++++-----
 xen/arch/arm/platforms/omap5.c       | 21 ++++++++++++---------
 xen/arch/arm/platforms/xgene-storm.c |  4 +++-
 xen/include/asm-arm/mm.h             |  2 ++
 xen/include/asm-arm/p2m.h            | 11 ++++++-----
 8 files changed, 54 insertions(+), 37 deletions(-)

diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index f4902bb..3c75672 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -744,9 +744,10 @@ static int map_device(struct domain *d, const struct dt_device_node *dev)
                    addr & PAGE_MASK, PAGE_ALIGN(addr + size) - 1);
             return res;
         }
-        res = map_mmio_regions(d, addr & PAGE_MASK,
-                               PAGE_ALIGN(addr + size) - 1,
-                               addr & PAGE_MASK);
+        res = map_mmio_regions(d,
+                               paddr_to_pfn(addr & PAGE_MASK),
+                               paddr_to_pfn_aligned(addr + size - 1),
+                               paddr_to_pfn(addr & PAGE_MASK));
         if ( res )
         {
             printk(XENLOG_ERR "Unable to map 0x%"PRIx64
diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
index 0095b97..0ba31d0 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -888,20 +888,23 @@ int gicv_setup(struct domain *d)
      * The second page is always mapped at +4K irrespective of the
      * GIC_64K_STRIDE quirk. The DTB passed to the guest reflects this.
      */
-    ret = map_mmio_regions(d, d->arch.vgic.cbase,
-                           d->arch.vgic.cbase + PAGE_SIZE - 1,
-                           gic.vbase);
+    ret = map_mmio_regions(d, paddr_to_pfn(d->arch.vgic.cbase),
+                           paddr_to_pfn_aligned(d->arch.vgic.cbase +
+                                                PAGE_SIZE - 1),
+                           paddr_to_pfn(gic.vbase));
     if (ret)
         return ret;
 
     if ( !platform_has_quirk(PLATFORM_QUIRK_GIC_64K_STRIDE) )
-        ret = map_mmio_regions(d, d->arch.vgic.cbase + PAGE_SIZE,
-                               d->arch.vgic.cbase + (2 * PAGE_SIZE) - 1,
-                               gic.vbase + PAGE_SIZE);
+        ret = map_mmio_regions(d, paddr_to_pfn(d->arch.vgic.cbase + PAGE_SIZE),
+                               paddr_to_pfn_aligned(d->arch.vgic.cbase +
+			                            (2 * PAGE_SIZE) - 1),
+                               paddr_to_pfn(gic.vbase + PAGE_SIZE));
     else
-        ret = map_mmio_regions(d, d->arch.vgic.cbase + PAGE_SIZE,
-                               d->arch.vgic.cbase + (2 * PAGE_SIZE) - 1,
-                               gic.vbase + 16*PAGE_SIZE);
+        ret = map_mmio_regions(d, paddr_to_pfn(d->arch.vgic.cbase + PAGE_SIZE),
+                               paddr_to_pfn_aligned(d->arch.vgic.cbase +
+			                            (2 * PAGE_SIZE) - 1),
+                               paddr_to_pfn(gic.vbase + 16*PAGE_SIZE));
 
     return ret;
 
diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
index 395a0b2..110b63a 100644
--- a/xen/arch/arm/p2m.c
+++ b/xen/arch/arm/p2m.c
@@ -518,12 +518,15 @@ int p2m_populate_ram(struct domain *d,
 }
 
 int map_mmio_regions(struct domain *d,
-                     paddr_t start_gaddr,
-                     paddr_t end_gaddr,
-                     paddr_t maddr)
+                     unsigned long start_gfn,
+                     unsigned long end_gfn,
+                     unsigned long mfn)
 {
-    return apply_p2m_changes(d, INSERT, start_gaddr, end_gaddr,
-                             maddr, MATTR_DEV, p2m_mmio_direct);
+    return apply_p2m_changes(d, INSERT,
+                             pfn_to_paddr(start_gfn),
+                             pfn_to_paddr(end_gfn),
+                             pfn_to_paddr(mfn),
+                             MATTR_DEV, p2m_mmio_direct);
 }
 
 int guest_physmap_add_entry(struct domain *d,
diff --git a/xen/arch/arm/platforms/exynos5.c b/xen/arch/arm/platforms/exynos5.c
index 65e584f..acd8781 100644
--- a/xen/arch/arm/platforms/exynos5.c
+++ b/xen/arch/arm/platforms/exynos5.c
@@ -54,13 +54,15 @@ static int exynos5_init_time(void)
 static int exynos5_specific_mapping(struct domain *d)
 {
     /* Map the chip ID */
-    map_mmio_regions(d, EXYNOS5_PA_CHIPID, EXYNOS5_PA_CHIPID + PAGE_SIZE - 1,
-                     EXYNOS5_PA_CHIPID);
+    map_mmio_regions(d, paddr_to_pfn(EXYNOS5_PA_CHIPID),
+                     paddr_to_pfn_aligned(EXYNOS5_PA_CHIPID + PAGE_SIZE - 1),
+                     paddr_to_pfn(EXYNOS5_PA_CHIPID));
 
     /* Map the PWM region */
-    map_mmio_regions(d, EXYNOS5_PA_TIMER,
-                     EXYNOS5_PA_TIMER + (PAGE_SIZE * 2) - 1,
-                     EXYNOS5_PA_TIMER);
+    map_mmio_regions(d, paddr_to_pfn(EXYNOS5_PA_TIMER),
+                     paddr_to_pfn_aligned(EXYNOS5_PA_TIMER +
+                                          (PAGE_SIZE * 2) - 1),
+                     paddr_to_pfn(EXYNOS5_PA_TIMER));
 
     return 0;
 }
diff --git a/xen/arch/arm/platforms/omap5.c b/xen/arch/arm/platforms/omap5.c
index 76d4d9b..c975020 100644
--- a/xen/arch/arm/platforms/omap5.c
+++ b/xen/arch/arm/platforms/omap5.c
@@ -102,21 +102,24 @@ static int omap5_init_time(void)
 static int omap5_specific_mapping(struct domain *d)
 {
     /* Map the PRM module */
-    map_mmio_regions(d, OMAP5_PRM_BASE, OMAP5_PRM_BASE + (PAGE_SIZE * 2) - 1,
-                     OMAP5_PRM_BASE);
+    map_mmio_regions(d, paddr_to_pfn(OMAP5_PRM_BASE),
+                     paddr_to_pfn_aligned(OMAP5_PRM_BASE + (PAGE_SIZE * 2) - 1),
+                     paddr_to_pfn(OMAP5_PRM_BASE));
 
     /* Map the PRM_MPU */
-    map_mmio_regions(d, OMAP5_PRCM_MPU_BASE,
-                     OMAP5_PRCM_MPU_BASE + PAGE_SIZE - 1,
-                     OMAP5_PRCM_MPU_BASE);
+    map_mmio_regions(d, paddr_to_pfn(OMAP5_PRCM_MPU_BASE),
+                     paddr_to_pfn_aligned(OMAP5_PRCM_MPU_BASE + PAGE_SIZE - 1),
+                     paddr_to_pfn(OMAP5_PRCM_MPU_BASE));
 
     /* Map the Wakeup Gen */
-    map_mmio_regions(d, OMAP5_WKUPGEN_BASE, OMAP5_WKUPGEN_BASE + PAGE_SIZE - 1,
-                     OMAP5_WKUPGEN_BASE);
+    map_mmio_regions(d, paddr_to_pfn(OMAP5_WKUPGEN_BASE),
+                     paddr_to_pfn_aligned(OMAP5_WKUPGEN_BASE + PAGE_SIZE - 1),
+                     paddr_to_pfn(OMAP5_WKUPGEN_BASE));
 
     /* Map the on-chip SRAM */
-    map_mmio_regions(d, OMAP5_SRAM_PA, OMAP5_SRAM_PA + (PAGE_SIZE * 32) - 1,
-                     OMAP5_SRAM_PA);
+    map_mmio_regions(d, paddr_to_pfn(OMAP5_SRAM_PA),
+                     paddr_to_pfn_aligned(OMAP5_SRAM_PA + (PAGE_SIZE * 32) - 1),
+                     paddr_to_pfn(OMAP5_SRAM_PA));
 
     return 0;
 }
diff --git a/xen/arch/arm/platforms/xgene-storm.c b/xen/arch/arm/platforms/xgene-storm.c
index af3b71c..f3662fd 100644
--- a/xen/arch/arm/platforms/xgene-storm.c
+++ b/xen/arch/arm/platforms/xgene-storm.c
@@ -47,7 +47,9 @@ static int map_one_mmio(struct domain *d, const char *what,
 
     printk("Additional MMIO %"PRIpaddr"-%"PRIpaddr" (%s)\n",
            start, end, what);
-    ret = map_mmio_regions(d, start, end, start);
+    ret = map_mmio_regions(d, paddr_to_pfn(start),
+                           paddr_to_pfn_aligned(end),
+                           paddr_to_pfn(start));
     if ( ret )
         printk("Failed to map %s @ %"PRIpaddr" to dom%d\n",
                what, start, d->domain_id);
diff --git a/xen/include/asm-arm/mm.h b/xen/include/asm-arm/mm.h
index b8d4e7d..97e0a7b 100644
--- a/xen/include/asm-arm/mm.h
+++ b/xen/include/asm-arm/mm.h
@@ -209,6 +209,8 @@ static inline void __iomem *ioremap_wc(paddr_t start, size_t len)
 #define paddr_to_pfn(pa)  ((unsigned long)((pa) >> PAGE_SHIFT))
 #define paddr_to_pdx(pa)    pfn_to_pdx(paddr_to_pfn(pa))
 
+/* Page-align address and convert to frame number format */
+#define paddr_to_pfn_aligned(paddr)    paddr_to_pfn(PAGE_ALIGN(paddr))
 
 static inline paddr_t __virt_to_maddr(vaddr_t va)
 {
diff --git a/xen/include/asm-arm/p2m.h b/xen/include/asm-arm/p2m.h
index bd71abe..c7dd6aa 100644
--- a/xen/include/asm-arm/p2m.h
+++ b/xen/include/asm-arm/p2m.h
@@ -84,11 +84,12 @@ int p2m_cache_flush(struct domain *d, xen_pfn_t start_mfn, xen_pfn_t end_mfn);
 
 /* Setup p2m RAM mapping for domain d from start-end. */
 int p2m_populate_ram(struct domain *d, paddr_t start, paddr_t end);
-/* Map MMIO regions in the p2m: start_gaddr and end_gaddr is the range
- * in the guest physical address space to map, starting from the machine
- * address maddr. */
-int map_mmio_regions(struct domain *d, paddr_t start_gaddr,
-                     paddr_t end_gaddr, paddr_t maddr);
+/* Map MMIO regions in the p2m: start_gfn and end_gfn is the range in the guest
+ * physical address space to map, starting from the machine frame number mfn. */
+int map_mmio_regions(struct domain *d,
+                     unsigned long start_gfn,
+                     unsigned long end_gfn,
+                     unsigned long mfn);
 
 int guest_physmap_add_entry(struct domain *d,
                             unsigned long gfn,
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v5 4/8] arch, x86: check if mapping exists before memory_mapping removes it
  2014-04-06 23:31 [PATCH v5 0/8] Implement the XEN_DOMCTL_memory_mapping hypercall for ARM Arianna Avanzini
                   ` (2 preceding siblings ...)
  2014-04-06 23:31 ` [PATCH v5 3/8] arch, arm: let map_mmio_regions() take pfn as parameters Arianna Avanzini
@ 2014-04-06 23:31 ` Arianna Avanzini
  2014-04-06 23:31 ` [PATCH v5 5/8] xen, common: add the XEN_DOMCTL_memory_mapping hypercall Arianna Avanzini
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 19+ messages in thread
From: Arianna Avanzini @ 2014-04-06 23:31 UTC (permalink / raw)
  To: xen-devel
  Cc: Ian.Campbell, paolo.valente, keir, stefano.stabellini,
	Ian.Jackson, dario.faggioli, tim, julien.grall, etrudeau,
	JBeulich, avanzini.arianna, viktor.kleinik

Currently, when a memory mapping is removed with the memory_mapping
DOMCTL, no check is performed on the existence of such a mapping.
This commit attempts to add such a consistency check to the code
performing the unmap.

Signed-off-by: Arianna Avanzini <avanzini.arianna@gmail.com>
Cc: Dario Faggioli <dario.faggioli@citrix.com>
Cc: Paolo Valente <paolo.valente@unimore.it>
Cc: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Cc: Julien Grall <julien.grall@citrix.com>
Cc: Ian Campbell <Ian.Campbell@eu.citrix.com>
Cc: Jan Beulich <JBeulich@suse.com>
Cc: Keir Fraser <keir@xen.org>
Cc: Tim Deegan <tim@xen.org>
Cc: Ian Jackson <Ian.Jackson@eu.citrix.com>
Cc: Eric Trudeau <etrudeau@broadcom.com>
Cc: Viktor Kleinik <viktor.kleinik@globallogic.com>
---
 xen/arch/x86/domctl.c     |  4 ++--
 xen/arch/x86/mm/p2m.c     | 23 +++++++++++++++++------
 xen/include/asm-x86/p2m.h |  2 +-
 3 files changed, 20 insertions(+), 9 deletions(-)

diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c
index 26635ff..1e51289 100644
--- a/xen/arch/x86/domctl.c
+++ b/xen/arch/x86/domctl.c
@@ -679,7 +679,7 @@ long arch_do_domctl(
                            "memory_map:fail: dom%d gfn=%lx mfn=%lx\n",
                            d->domain_id, gfn + i, mfn + i);
                     while ( i-- )
-                        clear_mmio_p2m_entry(d, gfn + i);
+                        clear_mmio_p2m_entry(d, gfn + i, _mfn(mfn + i));
                     if ( iomem_deny_access(d, mfn, mfn + nr_mfns - 1) &&
                          is_hardware_domain(current->domain) )
                         printk(XENLOG_ERR
@@ -696,7 +696,7 @@ long arch_do_domctl(
 
             if ( paging_mode_translate(d) )
                 for ( i = 0; i < nr_mfns; i++ )
-                    add |= !clear_mmio_p2m_entry(d, gfn + i);
+                    add |= !clear_mmio_p2m_entry(d, gfn + i, _mfn(mfn + i));
             ret = iomem_deny_access(d, mfn, mfn + nr_mfns - 1);
             if ( !ret && add )
                 ret = -EIO;
diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c
index c38f334..2c894b8 100644
--- a/xen/arch/x86/mm/p2m.c
+++ b/xen/arch/x86/mm/p2m.c
@@ -778,10 +778,10 @@ set_mmio_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn)
 }
 
 int
-clear_mmio_p2m_entry(struct domain *d, unsigned long gfn)
+clear_mmio_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn)
 {
     int rc = 0;
-    mfn_t mfn;
+    mfn_t actual_mfn;
     p2m_access_t a;
     p2m_type_t t;
     struct p2m_domain *p2m = p2m_get_hostp2m(d);
@@ -790,16 +790,27 @@ clear_mmio_p2m_entry(struct domain *d, unsigned long gfn)
         return 0;
 
     gfn_lock(p2m, gfn, 0);
-    mfn = p2m->get_entry(p2m, gfn, &t, &a, 0, NULL);
+    actual_mfn = p2m->get_entry(p2m, gfn, &t, &a, 0, NULL);
 
     /* Do not use mfn_valid() here as it will usually fail for MMIO pages. */
-    if ( (INVALID_MFN == mfn_x(mfn)) || (t != p2m_mmio_direct) )
+    if ( (INVALID_MFN == mfn_x(actual_mfn)) || (t != p2m_mmio_direct) )
+    {
+        gdprintk(XENLOG_ERR,
+            "clear_mmio_p2m_entry: gfn_to_mfn failed! gfn=%08lx\n",
+            gfn);
+        goto out;
+    }
+
+    if ( mfn_x(mfn) != mfn_x(actual_mfn) )
     {
         gdprintk(XENLOG_ERR,
-            "clear_mmio_p2m_entry: gfn_to_mfn failed! gfn=%08lx\n", gfn);
+            "clear_mmio_p2m_entry: mapping between mfn %08lx and "
+            "gfn %08lx does not exist (mapped to %08lx)\n",
+            mfn_x(mfn), gfn, mfn_x(actual_mfn));
         goto out;
     }
-    rc = set_p2m_entry(p2m, gfn, _mfn(INVALID_MFN), PAGE_ORDER_4K, p2m_invalid, p2m->default_access);
+    rc = set_p2m_entry(p2m, gfn, _mfn(INVALID_MFN), PAGE_ORDER_4K,
+                       p2m_invalid, p2m->default_access);
 
 out:
     gfn_unlock(p2m, gfn, 0);
diff --git a/xen/include/asm-x86/p2m.h b/xen/include/asm-x86/p2m.h
index d644f82..c403534 100644
--- a/xen/include/asm-x86/p2m.h
+++ b/xen/include/asm-x86/p2m.h
@@ -508,7 +508,7 @@ p2m_type_t p2m_change_type(struct domain *d, unsigned long gfn,
 
 /* Set mmio addresses in the p2m table (for pass-through) */
 int set_mmio_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn);
-int clear_mmio_p2m_entry(struct domain *d, unsigned long gfn);
+int clear_mmio_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn);
 
 
 /* 
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v5 5/8] xen, common: add the XEN_DOMCTL_memory_mapping hypercall
  2014-04-06 23:31 [PATCH v5 0/8] Implement the XEN_DOMCTL_memory_mapping hypercall for ARM Arianna Avanzini
                   ` (3 preceding siblings ...)
  2014-04-06 23:31 ` [PATCH v5 4/8] arch, x86: check if mapping exists before memory_mapping removes it Arianna Avanzini
@ 2014-04-06 23:31 ` Arianna Avanzini
  2014-04-07  7:55   ` Jan Beulich
  2014-04-09 14:03   ` Ian Campbell
  2014-04-06 23:31 ` [PATCH v5 6/8] tools, libxl: parse optional start gfn from the iomem config option Arianna Avanzini
                   ` (2 subsequent siblings)
  7 siblings, 2 replies; 19+ messages in thread
From: Arianna Avanzini @ 2014-04-06 23:31 UTC (permalink / raw)
  To: xen-devel
  Cc: Ian.Campbell, paolo.valente, keir, stefano.stabellini,
	Ian.Jackson, dario.faggioli, tim, julien.grall, etrudeau,
	JBeulich, avanzini.arianna, viktor.kleinik

This commit introduces a first attempt of implementation of the
XEN_DOMCTL_memory_mapping hypercall for ARM. As the implementation
would have been almost identical to the one for x86, this code has
been made common to both the architectures. The only difference
between the two procedures lies in the arch-specific implementation
of the map_mmio_regions() and unmap_mmio_regions() functions.

Signed-off-by: Arianna Avanzini <avanzini.arianna@gmail.com>
Cc: Dario Faggioli <dario.faggioli@citrix.com>
Cc: Paolo Valente <paolo.valente@unimore.it>
Cc: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Cc: Julien Grall <julien.grall@citrix.com>
Cc: Ian Campbell <Ian.Campbell@eu.citrix.com>
Cc: Jan Beulich <JBeulich@suse.com>
Cc: Keir Fraser <keir@xen.org>
Cc: Tim Deegan <tim@xen.org>
Cc: Jan Beulich <JBeulich@suse.com>
Cc: Keir Fraser <keir@xen.org>
Cc: Tim Deegan <tim@xen.org>
Cc: Ian Jackson <Ian.Jackson@eu.citrix.com>
Cc: Eric Trudeau <etrudeau@broadcom.com>
Cc: Viktor Kleinik <viktor.kleinik@globallogic.com>

---

    v5:
        - Let the unmap_mmio_regions() function for x86 return a proper
          error code upon failure.
        - Restore correct handling of errors in the remove path of the
          hypercall, assigning to the "ret" local variable the error
          code returned by the unmap_mmio_regions() function only if
          iomem_deny_access() didn't return with an error.
        - Compute gfn_end - 1 and mfn_end - 1 only once in the DOMCTL.
        - Use a local variable to keep the return value of the function
          unmap_mmio_regions() instead of re-using the "add" variable.
        - Add a comment to make hopefully clearer how error values of
          functions are handled in the remove path of the DOMCTL.
        - Rename new header to p2m-common.h.

    v4:
        - Use a define for paddr_bits instead of a new variable.
        - Define prototypes for common functions map_mmio_regions() and
          unmap_mmio_regions() only once in a common header.
        - Fix type and signedness of local variables used as indexes in
          map_mmio_regions() and unmap_mmio_regions() for x86.
        - Clear p2m entries in map_mmio_regions() for x86 only if
          set_mmio_p2m_entry() returned with an error.
        - Make ranges inclusive of the end address in map_mmio_regions()
          and unmap_mmio_regions() for x86.
        - Turn hard tabs into spaces.

    v3:
        - Move code to xen/common/domctl.c; abstract out differences between
          the x86 and ARM code:
          . add map_mmio_regions() and unmap_mmio_regions() functions for x86;
          . add a paddr_bits variable for ARM.
        - Use pfn as parameters to the unmap_mmio_regions() function.
        - Compute gfn + nr_mfns and mfn + nr_mfns only once.

    v2:
        - Move code to xen/arm/domctl.c.
        - Use the already-defined PADDR_BITS constant in the new DOMCTL.
        - Use paddr_t as arguments to the map_mmio_regions() function.
        - Page-align addresses given as arguments to map_mmio_regions() and
          unmap_mmio_regions(). 

---
 xen/arch/arm/p2m.c           | 12 ++++++++
 xen/arch/x86/domctl.c        | 70 -------------------------------------------
 xen/arch/x86/mm/p2m.c        | 42 ++++++++++++++++++++++++++
 xen/common/domctl.c          | 71 ++++++++++++++++++++++++++++++++++++++++++++
 xen/include/asm-arm/p2m.h    |  9 ++----
 xen/include/asm-x86/p2m.h    |  1 +
 xen/include/xen/p2m-common.h | 16 ++++++++++
 7 files changed, 145 insertions(+), 76 deletions(-)
 create mode 100644 xen/include/xen/p2m-common.h

diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
index 110b63a..cc71a5d 100644
--- a/xen/arch/arm/p2m.c
+++ b/xen/arch/arm/p2m.c
@@ -529,6 +529,18 @@ int map_mmio_regions(struct domain *d,
                              MATTR_DEV, p2m_mmio_direct);
 }
 
+int unmap_mmio_regions(struct domain *d,
+                       unsigned long start_gfn,
+                       unsigned long end_gfn,
+                       unsigned long mfn)
+{
+    return apply_p2m_changes(d, REMOVE,
+                             pfn_to_paddr(start_gfn),
+                             pfn_to_paddr(end_gfn),
+                             pfn_to_paddr(mfn),
+                             MATTR_DEV, p2m_mmio_direct);
+}
+
 int guest_physmap_add_entry(struct domain *d,
                             unsigned long gpfn,
                             unsigned long mfn,
diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c
index 1e51289..69a7fbf 100644
--- a/xen/arch/x86/domctl.c
+++ b/xen/arch/x86/domctl.c
@@ -639,76 +639,6 @@ long arch_do_domctl(
     }
     break;
 
-    case XEN_DOMCTL_memory_mapping:
-    {
-        unsigned long gfn = domctl->u.memory_mapping.first_gfn;
-        unsigned long mfn = domctl->u.memory_mapping.first_mfn;
-        unsigned long nr_mfns = domctl->u.memory_mapping.nr_mfns;
-        int add = domctl->u.memory_mapping.add_mapping;
-        unsigned long i;
-
-        ret = -EINVAL;
-        if ( (mfn + nr_mfns - 1) < mfn || /* wrap? */
-             ((mfn | (mfn + nr_mfns - 1)) >> (paddr_bits - PAGE_SHIFT)) ||
-             (gfn + nr_mfns - 1) < gfn ) /* wrap? */
-            break;
-
-        ret = -EPERM;
-        if ( !iomem_access_permitted(current->domain, mfn, mfn + nr_mfns - 1) )
-            break;
-
-        ret = xsm_iomem_mapping(XSM_HOOK, d, mfn, mfn + nr_mfns - 1, add);
-        if ( ret )
-            break;
-
-        if ( add )
-        {
-            printk(XENLOG_G_INFO
-                   "memory_map:add: dom%d gfn=%lx mfn=%lx nr=%lx\n",
-                   d->domain_id, gfn, mfn, nr_mfns);
-
-            ret = iomem_permit_access(d, mfn, mfn + nr_mfns - 1);
-            if ( !ret && paging_mode_translate(d) )
-            {
-                for ( i = 0; !ret && i < nr_mfns; i++ )
-                    if ( !set_mmio_p2m_entry(d, gfn + i, _mfn(mfn + i)) )
-                        ret = -EIO;
-                if ( ret )
-                {
-                    printk(XENLOG_G_WARNING
-                           "memory_map:fail: dom%d gfn=%lx mfn=%lx\n",
-                           d->domain_id, gfn + i, mfn + i);
-                    while ( i-- )
-                        clear_mmio_p2m_entry(d, gfn + i, _mfn(mfn + i));
-                    if ( iomem_deny_access(d, mfn, mfn + nr_mfns - 1) &&
-                         is_hardware_domain(current->domain) )
-                        printk(XENLOG_ERR
-                               "memory_map: failed to deny dom%d access to [%lx,%lx]\n",
-                               d->domain_id, mfn, mfn + nr_mfns - 1);
-                }
-            }
-        }
-        else
-        {
-            printk(XENLOG_G_INFO
-                   "memory_map:remove: dom%d gfn=%lx mfn=%lx nr=%lx\n",
-                   d->domain_id, gfn, mfn, nr_mfns);
-
-            if ( paging_mode_translate(d) )
-                for ( i = 0; i < nr_mfns; i++ )
-                    add |= !clear_mmio_p2m_entry(d, gfn + i, _mfn(mfn + i));
-            ret = iomem_deny_access(d, mfn, mfn + nr_mfns - 1);
-            if ( !ret && add )
-                ret = -EIO;
-            if ( ret && is_hardware_domain(current->domain) )
-                printk(XENLOG_ERR
-                       "memory_map: error %ld %s dom%d access to [%lx,%lx]\n",
-                       ret, add ? "removing" : "denying", d->domain_id,
-                       mfn, mfn + nr_mfns - 1);
-        }
-    }
-    break;
-
     case XEN_DOMCTL_ioport_mapping:
     {
 #define MAX_IOPORTS    0x10000
diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c
index 2c894b8..2c6ef24 100644
--- a/xen/arch/x86/mm/p2m.c
+++ b/xen/arch/x86/mm/p2m.c
@@ -1631,6 +1631,48 @@ unsigned long paging_gva_to_gfn(struct vcpu *v,
     return hostmode->gva_to_gfn(v, hostp2m, va, pfec);
 }
 
+int map_mmio_regions(struct domain *d,
+                     unsigned long start_gfn,
+                     unsigned long end_gfn,
+                     unsigned long mfn)
+{
+    int ret = 0;
+    unsigned long i;
+    unsigned long nr_mfns = end_gfn - start_gfn + 1;
+
+    if ( !paging_mode_translate(d) )
+        return 0;
+
+    for ( i = 0; !ret && i < nr_mfns; i++ )
+        if ( !set_mmio_p2m_entry(d, start_gfn + i, _mfn(mfn + i)) )
+            ret = -EIO;
+    if ( ret )
+        while ( i-- )
+            clear_mmio_p2m_entry(d, start_gfn + i, _mfn(mfn + i));
+
+    return ret;
+}
+
+int unmap_mmio_regions(struct domain *d,
+                       unsigned long start_gfn,
+                       unsigned long end_gfn,
+                       unsigned long mfn)
+{
+    int ret = 0;
+    unsigned long nr_mfns = end_gfn - start_gfn + 1;
+    unsigned long i;
+
+    if ( !paging_mode_translate(d) )
+        return 0;
+
+    for ( i = 0; i < nr_mfns; i++ )
+        ret |= !clear_mmio_p2m_entry(d, start_gfn + i, _mfn(mfn + i));
+
+    if ( ret )
+        return -EIO;
+    return 0;
+}
+
 /*** Audit ***/
 
 #if P2M_AUDIT
diff --git a/xen/common/domctl.c b/xen/common/domctl.c
index 5342e5d..fe228fb 100644
--- a/xen/common/domctl.c
+++ b/xen/common/domctl.c
@@ -818,6 +818,77 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
     }
     break;
 
+    case XEN_DOMCTL_memory_mapping:
+    {
+        unsigned long gfn = op->u.memory_mapping.first_gfn;
+        unsigned long mfn = op->u.memory_mapping.first_mfn;
+        unsigned long nr_mfns = op->u.memory_mapping.nr_mfns;
+        unsigned long mfn_end = mfn + nr_mfns - 1;
+        unsigned long gfn_end = gfn + nr_mfns - 1;
+        int add = op->u.memory_mapping.add_mapping;
+
+        ret = -EINVAL;
+        if ( (mfn_end - 1) < mfn || /* wrap? */
+             ((mfn | (mfn_end - 1)) >> (paddr_bits - PAGE_SHIFT)) ||
+             (gfn_end - 1) < gfn ) /* wrap? */
+            return ret;
+
+        ret = -EPERM;
+        if ( !iomem_access_permitted(current->domain, mfn, mfn_end) )
+            return ret;
+
+        ret = xsm_iomem_mapping(XSM_HOOK, d, mfn, mfn_end, add);
+        if ( ret )
+            return ret;
+
+        if ( add )
+        {
+            printk(XENLOG_G_INFO
+                   "memory_map: add: dom%d gfn=%lx mfn=%lx nr=%lx\n",
+                   d->domain_id, gfn, mfn, nr_mfns);
+            ret = iomem_permit_access(d, mfn, mfn_end);
+            if ( !ret )
+            {
+                ret = map_mmio_regions(d, gfn, gfn_end, mfn);
+                if ( ret )
+                {
+                    printk(XENLOG_G_WARNING
+                           "memory_map: fail: dom%d gfn=%lx mfn=%lx\n",
+                           d->domain_id, gfn, mfn);
+                    if ( iomem_deny_access(d, mfn, mfn_end) &&
+                         is_hardware_domain(current->domain) )
+                        printk(XENLOG_ERR
+                               "memory_map: failed to deny dom%d access "
+                               "to [%lx,%lx]\n",
+                               d->domain_id, mfn, mfn_end);
+                }
+            }
+        }
+        else
+        {
+	    long unmap_ret;
+
+            printk(XENLOG_G_INFO
+                   "memory_map: remove: dom%d gfn=%lx mfn=%lx nr=%lx\n",
+                   d->domain_id, gfn, mfn, nr_mfns);
+
+            unmap_ret = unmap_mmio_regions(d, gfn, gfn_end, mfn);
+            ret = iomem_deny_access(d, mfn, mfn_end);
+            /*
+             * Let an error value returned by iomem_deny_access() prevail on
+             * the one possibly returned by unmap_mmio_regions().
+             */
+            if ( !ret && unmap_ret )
+                ret = unmap_ret;
+            if ( ret && is_hardware_domain(current->domain) )
+                printk(XENLOG_ERR
+                       "memory_map: error %ld %s dom%d access to [%lx,%lx]\n",
+                       ret, unmap_ret ? "removing" : "denying", d->domain_id,
+                       mfn, mfn_end);
+        }
+    }
+    break;
+
     case XEN_DOMCTL_settimeoffset:
     {
         domain_set_time_offset(d, op->u.settimeoffset.time_offset_seconds);
diff --git a/xen/include/asm-arm/p2m.h b/xen/include/asm-arm/p2m.h
index c7dd6aa..e9ece8d 100644
--- a/xen/include/asm-arm/p2m.h
+++ b/xen/include/asm-arm/p2m.h
@@ -2,6 +2,9 @@
 #define _XEN_P2M_H
 
 #include <xen/mm.h>
+#include <xen/p2m-common.h>
+
+#define paddr_bits PADDR_BITS
 
 struct domain;
 
@@ -84,12 +87,6 @@ int p2m_cache_flush(struct domain *d, xen_pfn_t start_mfn, xen_pfn_t end_mfn);
 
 /* Setup p2m RAM mapping for domain d from start-end. */
 int p2m_populate_ram(struct domain *d, paddr_t start, paddr_t end);
-/* Map MMIO regions in the p2m: start_gfn and end_gfn is the range in the guest
- * physical address space to map, starting from the machine frame number mfn. */
-int map_mmio_regions(struct domain *d,
-                     unsigned long start_gfn,
-                     unsigned long end_gfn,
-                     unsigned long mfn);
 
 int guest_physmap_add_entry(struct domain *d,
                             unsigned long gfn,
diff --git a/xen/include/asm-x86/p2m.h b/xen/include/asm-x86/p2m.h
index c403534..af53816 100644
--- a/xen/include/asm-x86/p2m.h
+++ b/xen/include/asm-x86/p2m.h
@@ -29,6 +29,7 @@
 
 #include <xen/config.h>
 #include <xen/paging.h>
+#include <xen/p2m-common.h>
 #include <asm/mem_sharing.h>
 #include <asm/page.h>    /* for pagetable_t */
 
diff --git a/xen/include/xen/p2m-common.h b/xen/include/xen/p2m-common.h
new file mode 100644
index 0000000..2be9a86
--- /dev/null
+++ b/xen/include/xen/p2m-common.h
@@ -0,0 +1,16 @@
+#ifndef _XEN_P2M_COMMON_H
+#define _XEN_P2M_COMMON_H
+
+/* Map MMIO regions in the p2m: start_gfn and end_gfn is the range
+ * in the guest physical address space to map, starting from the
+ * machine frame number mfn. */
+int map_mmio_regions(struct domain *d,
+                     unsigned long start_gfn,
+                     unsigned long end_gfn,
+                     unsigned long mfn);
+int unmap_mmio_regions(struct domain *d,
+                       unsigned long start_gfn,
+                       unsigned long end_gfn,
+                       unsigned long mfn);
+
+#endif /* _XEN_P2M_COMMON_H */
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v5 6/8] tools, libxl: parse optional start gfn from the iomem config option
  2014-04-06 23:31 [PATCH v5 0/8] Implement the XEN_DOMCTL_memory_mapping hypercall for ARM Arianna Avanzini
                   ` (4 preceding siblings ...)
  2014-04-06 23:31 ` [PATCH v5 5/8] xen, common: add the XEN_DOMCTL_memory_mapping hypercall Arianna Avanzini
@ 2014-04-06 23:31 ` Arianna Avanzini
  2014-04-09 14:10   ` Ian Campbell
  2014-04-06 23:31 ` [PATCH v5 7/8] tools, libxl: add helpers to establish if guest is auto-translated Arianna Avanzini
  2014-04-06 23:32 ` [PATCH v5 8/8] tools, libxl: handle the iomem parameter with the memory_mapping hcall Arianna Avanzini
  7 siblings, 1 reply; 19+ messages in thread
From: Arianna Avanzini @ 2014-04-06 23:31 UTC (permalink / raw)
  To: xen-devel
  Cc: Ian.Campbell, paolo.valente, keir, stefano.stabellini,
	Ian.Jackson, dario.faggioli, tim, julien.grall, etrudeau,
	JBeulich, avanzini.arianna, viktor.kleinik

Currently, the "iomem" domU config option allows to specify a machine
address range to be mapped to the domU. However, there is no way to
specify the guest address range used for the mapping. This commit
extends the iomem option handling code to parse an additional, optional
parameter: this parameter, if given, specifies the start guest address
used for the mapping; if no start guest address is given, a 1:1 mapping
is performed as default.

Signed-off-by: Arianna Avanzini <avanzini.arianna@gmail.com>
Cc: Dario Faggioli <dario.faggioli@citrix.com>
Cc: Paolo Valente <paolo.valente@unimore.it>
Cc: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Cc: Julien Grall <julien.grall@citrix.com>
Cc: Ian Campbell <Ian.Campbell@eu.citrix.com>
Cc: Jan Beulich <JBeulich@suse.com>
Cc: Keir Fraser <keir@xen.org>
Cc: Tim Deegan <tim@xen.org>
Cc: Ian Jackson <Ian.Jackson@eu.citrix.com>
Cc: Eric Trudeau <etrudeau@broadcom.com>
Cc: Viktor Kleinik <viktor.kleinik@globallogic.com>

---

    v5:
        - Initialize the gfn field of the iomem structure with the
          value "(uint64_t)-1".
        - Defer the assignment of the value of "start" to "gfn", if
          "gfn" has been initialized to the default value, in libxl.
        - Use a local variable to keep the return value of sscanf()
          for better code readability.

    v4:
        - Add definition of a LIBXL_HAVE_BUILDINFO_IOMEM_START_GFN macro
          to indicate the availability of the new option.
        - Simplify the code parsing the new optional parameter by using
          the switch construct on the return value of the sscanf() function
          instead of calling the function twice.
        - Add a short paragraph to the manpage about the use of the iomem
          option to passthrough devices protected by an IOMMU.
        - Add comments to the fields of the "iomem" structure.

---
 docs/man/xl.cfg.pod.5       | 13 +++++++++----
 tools/libxl/libxl.h         | 10 ++++++++++
 tools/libxl/libxl_create.c  |  6 ++++++
 tools/libxl/libxl_types.idl |  7 +++++--
 tools/libxl/xl_cmdimpl.c    | 19 ++++++++++---------
 5 files changed, 40 insertions(+), 15 deletions(-)

diff --git a/docs/man/xl.cfg.pod.5 b/docs/man/xl.cfg.pod.5
index a6663b9..d54f601 100644
--- a/docs/man/xl.cfg.pod.5
+++ b/docs/man/xl.cfg.pod.5
@@ -602,12 +602,17 @@ is given in hexadecimal and may either a span e.g. C<2f8-2ff>
 It is recommended to use this option only for trusted VMs under
 administrator control.
 
-=item B<iomem=[ "IOMEM_START,NUM_PAGES", "IOMEM_START,NUM_PAGES", ... ]>
+=item B<iomem=[ "IOMEM_START,NUM_PAGES[@GFN]", "IOMEM_START,NUM_PAGES[@GFN]", ... ]>
 
 Allow guest to access specific hardware I/O memory pages. B<IOMEM_START>
-is a physical page number. B<NUM_PAGES> is the number
-of pages beginning with B<START_PAGE> to allow access. Both values
-must be given in hexadecimal.
+is a physical page number. B<NUM_PAGES> is the number of pages beginning
+with B<START_PAGE> to allow access. B<GFN> specifies the guest frame number
+where the mapping will start in the domU's address space.
+All of these values must be given in hexadecimal.
+
+Note that the IOMMU won't be updated with the mappings specified with this
+option. This option therefore should not be used to passthrough any
+IOMMU-protected device.
 
 It is recommended to use this option only for trusted VMs under
 administrator control.
diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
index b2c3015..e4a1128 100644
--- a/tools/libxl/libxl.h
+++ b/tools/libxl/libxl.h
@@ -95,6 +95,16 @@
 #define LIBXL_HAVE_BUILDINFO_EVENT_CHANNELS 1
 
 /*
+ * LIBXL_HAVE_BUILDINFO_IOMEM_START_GFN indicated that it is possible
+ * to specify the start guest frame number used to map a range of I/O
+ * memory machine frame numbers via the 'gfn' field (of type uint64)
+ * of the 'iomem' structure. An array of iomem structures is embedded
+ * in libxl_domain_build_info and used to map the indicated memory
+ * ranges during domain build.
+ */
+#define LIBXL_HAVE_BUILDINFO_IOMEM_START_GFN 1
+
+/*
  * libxl ABI compatibility
  *
  * The only guarantee which libxl makes regarding ABI compatibility
diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c
index d015cf4..369cd77 100644
--- a/tools/libxl/libxl_create.c
+++ b/tools/libxl/libxl_create.c
@@ -102,6 +102,8 @@ static int sched_params_valid(libxl__gc *gc,
 int libxl__domain_build_info_setdefault(libxl__gc *gc,
                                         libxl_domain_build_info *b_info)
 {
+    int i;
+
     if (b_info->type != LIBXL_DOMAIN_TYPE_HVM &&
         b_info->type != LIBXL_DOMAIN_TYPE_PV)
         return ERROR_INVAL;
@@ -212,6 +214,10 @@ int libxl__domain_build_info_setdefault(libxl__gc *gc,
 
     libxl_defbool_setdefault(&b_info->disable_migrate, false);
 
+    for (i = 0 ; i < b_info->num_iomem; i++)
+        if (b_info->iomem[i].gfn == (uint64_t)-1)
+            b_info->iomem[i].gfn = b_info->iomem[i].start;
+
     if (!b_info->event_channels)
         b_info->event_channels = 1023;
 
diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
index 612645c..69f8ea3 100644
--- a/tools/libxl/libxl_types.idl
+++ b/tools/libxl/libxl_types.idl
@@ -170,8 +170,11 @@ libxl_ioport_range = Struct("ioport_range", [
     ])
 
 libxl_iomem_range = Struct("iomem_range", [
-    ("start", uint64),
-    ("number", uint64),
+    ("start", uint64),                 # start host frame number to be mapped
+                                       # to the guest
+    ("number", uint64),                # number of frames to be mapped
+    ("gfn", uint64, {'init_val': -1}), # guest frame number used as a start
+                                       # for the mapping
     ])
 
 libxl_vga_interface_info = Struct("vga_interface_info", [
diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
index 8389468..10df96c 100644
--- a/tools/libxl/xl_cmdimpl.c
+++ b/tools/libxl/xl_cmdimpl.c
@@ -1200,6 +1200,7 @@ static void parse_config_data(const char *config_source,
     }
 
     if (!xlu_cfg_get_list(config, "iomem", &iomem, &num_iomem, 0)) {
+        int ret;
         b_info->num_iomem = num_iomem;
         b_info->iomem = calloc(num_iomem, sizeof(*b_info->iomem));
         if (b_info->iomem == NULL) {
@@ -1213,19 +1214,19 @@ static void parse_config_data(const char *config_source,
                         "xl: Unable to get element %d in iomem list\n", i);
                 exit(1);
             }
-            if(sscanf(buf, "%" SCNx64",%" SCNx64,
-                     &b_info->iomem[i].start,
-                     &b_info->iomem[i].number)
-                  != 2) {
-               fprintf(stderr,
-                       "xl: Invalid argument parsing iomem: %s\n", buf);
-               exit(1);
+            libxl_iomem_range_init(&b_info->iomem[i]);
+            ret = sscanf(buf, "%" SCNx64",%" SCNx64"@%" SCNx64,
+                         &b_info->iomem[i].start,
+                         &b_info->iomem[i].number,
+                         &b_info->iomem[i].gfn);
+            if (ret < 2) {
+                fprintf(stderr,
+                        "xl: Invalid argument parsing iomem: %s\n", buf);
+                exit(1);
             }
         }
     }
 
-
-
     if (!xlu_cfg_get_list (config, "disk", &vbds, 0, 0)) {
         d_config->num_disks = 0;
         d_config->disks = NULL;
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v5 7/8] tools, libxl: add helpers to establish if guest is auto-translated
  2014-04-06 23:31 [PATCH v5 0/8] Implement the XEN_DOMCTL_memory_mapping hypercall for ARM Arianna Avanzini
                   ` (5 preceding siblings ...)
  2014-04-06 23:31 ` [PATCH v5 6/8] tools, libxl: parse optional start gfn from the iomem config option Arianna Avanzini
@ 2014-04-06 23:31 ` Arianna Avanzini
  2014-04-06 23:32 ` [PATCH v5 8/8] tools, libxl: handle the iomem parameter with the memory_mapping hcall Arianna Avanzini
  7 siblings, 0 replies; 19+ messages in thread
From: Arianna Avanzini @ 2014-04-06 23:31 UTC (permalink / raw)
  To: xen-devel
  Cc: Ian.Campbell, paolo.valente, keir, stefano.stabellini,
	Ian.Jackson, dario.faggioli, tim, julien.grall, etrudeau,
	JBeulich, avanzini.arianna, viktor.kleinik

This commit adds, for each architecture supported by libxl, a helper
function which establishes if a domain uses an auto-translated
physmap from the libxl_domain_config structure related to it.

Signed-off-by: Arianna Avanzini <avanzini.arianna@gmail.com>
Cc: Dario Faggioli <dario.faggioli@citrix.com>
Cc: Paolo Valente <paolo.valente@unimore.it>
Cc: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Cc: Julien Grall <julien.grall@citrix.com>
Cc: Ian Campbell <Ian.Campbell@eu.citrix.com>
Cc: Jan Beulich <JBeulich@suse.com>
Cc: Keir Fraser <keir@xen.org>
Cc: Tim Deegan <tim@xen.org>
Cc: Ian Jackson <Ian.Jackson@eu.citrix.com>
Cc: Eric Trudeau <etrudeau@broadcom.com>
Cc: Viktor Kleinik <viktor.kleinik@globallogic.com>
---
 tools/libxl/libxl_arch.h | 2 ++
 tools/libxl/libxl_arm.c  | 5 +++++
 tools/libxl/libxl_x86.c  | 6 ++++++
 3 files changed, 13 insertions(+)

diff --git a/tools/libxl/libxl_arch.h b/tools/libxl/libxl_arch.h
index aee0a91..963d98b 100644
--- a/tools/libxl/libxl_arch.h
+++ b/tools/libxl/libxl_arch.h
@@ -22,4 +22,6 @@ int libxl__arch_domain_create(libxl__gc *gc, libxl_domain_config *d_config,
 int libxl__arch_domain_configure(libxl__gc *gc,
                                  libxl_domain_build_info *info,
                                  struct xc_dom_image *dom);
+
+int libxl__arch_auto_translated_physmap(libxl_domain_config *d_config);
 #endif
diff --git a/tools/libxl/libxl_arm.c b/tools/libxl/libxl_arm.c
index 0cfd0cf..637f906 100644
--- a/tools/libxl/libxl_arm.c
+++ b/tools/libxl/libxl_arm.c
@@ -11,6 +11,11 @@ int libxl__arch_domain_create(libxl__gc *gc, libxl_domain_config *d_config,
     return 0;
 }
 
+int libxl__arch_auto_translated_physmap(libxl_domain_config *d_config)
+{
+    return 1;
+}
+
 static struct arch_info {
     const char *guest_type;
     const char *timer_compat;
diff --git a/tools/libxl/libxl_x86.c b/tools/libxl/libxl_x86.c
index b11d036..c6f9c68 100644
--- a/tools/libxl/libxl_x86.c
+++ b/tools/libxl/libxl_x86.c
@@ -317,3 +317,9 @@ int libxl__arch_domain_configure(libxl__gc *gc,
 {
     return 0;
 }
+
+int libxl__arch_auto_translated_physmap(libxl_domain_config *d_config)
+{
+    return (d_config->b_info.type == LIBXL_DOMAIN_TYPE_HVM ||
+            libxl_defbool_val(d_config->c_info.pvh));
+}
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH v5 8/8] tools, libxl: handle the iomem parameter with the memory_mapping hcall
  2014-04-06 23:31 [PATCH v5 0/8] Implement the XEN_DOMCTL_memory_mapping hypercall for ARM Arianna Avanzini
                   ` (6 preceding siblings ...)
  2014-04-06 23:31 ` [PATCH v5 7/8] tools, libxl: add helpers to establish if guest is auto-translated Arianna Avanzini
@ 2014-04-06 23:32 ` Arianna Avanzini
  2014-04-09 14:25   ` Ian Campbell
  7 siblings, 1 reply; 19+ messages in thread
From: Arianna Avanzini @ 2014-04-06 23:32 UTC (permalink / raw)
  To: xen-devel
  Cc: Ian.Campbell, paolo.valente, keir, stefano.stabellini,
	Ian.Jackson, dario.faggioli, tim, julien.grall, etrudeau,
	JBeulich, avanzini.arianna, viktor.kleinik

Currently, the configuration-parsing code concerning the handling of the
iomem parameter only invokes the XEN_DOMCTL_iomem_permission hypercall.
This commit lets the XEN_DOMCTL_memory_mapping hypercall be invoked
after XEN_DOMCTL_iomem_permission when the iomem parameter is parsed
from a domU configuration file, so that the address range can be mapped
to the address space of the domU. The hypercall is invoked only in case
of domains using an auto-translated physmap.

Signed-off-by: Arianna Avanzini <avanzini.arianna@gmail.com>
Cc: Dario Faggioli <dario.faggioli@citrix.com>
Cc: Paolo Valente <paolo.valente@unimore.it>
Cc: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Cc: Julien Grall <julien.grall@citrix.com>
Cc: Ian Campbell <Ian.Campbell@eu.citrix.com>
Cc: Jan Beulich <JBeulich@suse.com>
Cc: Keir Fraser <keir@xen.org>
Cc: Tim Deegan <tim@xen.org>
Cc: Ian Jackson <Ian.Jackson@eu.citrix.com>
Cc: Eric Trudeau <etrudeau@broadcom.com>
Cc: Viktor Kleinik <viktor.kleinik@globallogic.com>

---

    v4:
        - Let the hypercall be called only in case the guest uses an
          auto-translated physmap.

    v3:
        - Add ifdefs to let the hypercall be called only by ARM or x86
          HVM guests, with a whitelist approach.
        - Remove the NOTE comment.

    v2:
        - Add a comment explaining outstanding issues. 

---
 tools/libxl/libxl_create.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c
index 369cd77..5ca3b37 100644
--- a/tools/libxl/libxl_create.c
+++ b/tools/libxl/libxl_create.c
@@ -1113,6 +1113,19 @@ static void domcreate_launch_dm(libxl__egc *egc, libxl__multidev *multidev,
                  "failed give dom%d access to iomem range %"PRIx64"-%"PRIx64,
                  domid, io->start, io->start + io->number - 1);
             ret = ERROR_FAIL;
+            continue;
+        }
+        if (!libxl__arch_auto_translated_physmap(d_config))
+            continue;
+        ret = xc_domain_memory_mapping(CTX->xch, domid,
+                                       io->gfn, io->start,
+                                       io->number, 1);
+        if (ret < 0) {
+            LOGE(ERROR,
+                 "failed to map to dom%d iomem range %"PRIx64"-%"PRIx64
+                 " to guest address %"PRIx64,
+                 domid, io->start, io->start + io->number - 1, io->gfn);
+            ret = ERROR_FAIL;
         }
     }
 
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [PATCH v5 5/8] xen, common: add the XEN_DOMCTL_memory_mapping hypercall
  2014-04-06 23:31 ` [PATCH v5 5/8] xen, common: add the XEN_DOMCTL_memory_mapping hypercall Arianna Avanzini
@ 2014-04-07  7:55   ` Jan Beulich
  2014-04-09 14:03   ` Ian Campbell
  1 sibling, 0 replies; 19+ messages in thread
From: Jan Beulich @ 2014-04-07  7:55 UTC (permalink / raw)
  To: Arianna Avanzini
  Cc: Ian.Campbell, paolo.valente, keir, stefano.stabellini, tim,
	dario.faggioli, Ian.Jackson, xen-devel, julien.grall, etrudeau,
	viktor.kleinik

>>> On 07.04.14 at 01:31, <avanzini.arianna@gmail.com> wrote:
> --- a/xen/common/domctl.c
> +++ b/xen/common/domctl.c
> @@ -818,6 +818,77 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
>      }
>      break;
>  
> +    case XEN_DOMCTL_memory_mapping:
> +    {
> +        unsigned long gfn = op->u.memory_mapping.first_gfn;
> +        unsigned long mfn = op->u.memory_mapping.first_mfn;
> +        unsigned long nr_mfns = op->u.memory_mapping.nr_mfns;
> +        unsigned long mfn_end = mfn + nr_mfns - 1;
> +        unsigned long gfn_end = gfn + nr_mfns - 1;
> +        int add = op->u.memory_mapping.add_mapping;
> +
> +        ret = -EINVAL;
> +        if ( (mfn_end - 1) < mfn || /* wrap? */
> +             ((mfn | (mfn_end - 1)) >> (paddr_bits - PAGE_SHIFT)) ||
> +             (gfn_end - 1) < gfn ) /* wrap? */

You subtracted 1 from [mg]fn_end above already.

> +            return ret;
> +
> +        ret = -EPERM;
> +        if ( !iomem_access_permitted(current->domain, mfn, mfn_end) )
> +            return ret;
> +
> +        ret = xsm_iomem_mapping(XSM_HOOK, d, mfn, mfn_end, add);
> +        if ( ret )
> +            return ret;
> +
> +        if ( add )
> +        {
> +            printk(XENLOG_G_INFO
> +                   "memory_map: add: dom%d gfn=%lx mfn=%lx nr=%lx\n",
> +                   d->domain_id, gfn, mfn, nr_mfns);
> +            ret = iomem_permit_access(d, mfn, mfn_end);
> +            if ( !ret )
> +            {
> +                ret = map_mmio_regions(d, gfn, gfn_end, mfn);
> +                if ( ret )
> +                {
> +                    printk(XENLOG_G_WARNING
> +                           "memory_map: fail: dom%d gfn=%lx mfn=%lx\n",
> +                           d->domain_id, gfn, mfn);
> +                    if ( iomem_deny_access(d, mfn, mfn_end) &&
> +                         is_hardware_domain(current->domain) )
> +                        printk(XENLOG_ERR
> +                               "memory_map: failed to deny dom%d access "
> +                               "to [%lx,%lx]\n",
> +                               d->domain_id, mfn, mfn_end);
> +                }
> +            }
> +        }
> +        else
> +        {
> +	    long unmap_ret;

Hard tab.

> +
> +            printk(XENLOG_G_INFO
> +                   "memory_map: remove: dom%d gfn=%lx mfn=%lx nr=%lx\n",
> +                   d->domain_id, gfn, mfn, nr_mfns);
> +
> +            unmap_ret = unmap_mmio_regions(d, gfn, gfn_end, mfn);
> +            ret = iomem_deny_access(d, mfn, mfn_end);
> +            /*
> +             * Let an error value returned by iomem_deny_access() prevail on
> +             * the one possibly returned by unmap_mmio_regions().
> +             */

I would omit this comment - it's not that important which of the two
errors we return, what is important is that we don't drop either of the
two possible failures.

> --- /dev/null
> +++ b/xen/include/xen/p2m-common.h
> @@ -0,0 +1,16 @@
> +#ifndef _XEN_P2M_COMMON_H
> +#define _XEN_P2M_COMMON_H
> +
> +/* Map MMIO regions in the p2m: start_gfn and end_gfn is the range

To make things entirely obvious, please add the word "inclusive" here.

> + * in the guest physical address space to map, starting from the
> + * machine frame number mfn. */
> +int map_mmio_regions(struct domain *d,
> +                     unsigned long start_gfn,
> +                     unsigned long end_gfn,
> +                     unsigned long mfn);
> +int unmap_mmio_regions(struct domain *d,
> +                       unsigned long start_gfn,
> +                       unsigned long end_gfn,
> +                       unsigned long mfn);
> +
> +#endif /* _XEN_P2M_COMMON_H */

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v5 2/8] arch, arm: add consistency check to REMOVE p2m changes
  2014-04-06 23:31 ` [PATCH v5 2/8] arch, arm: add consistency check to REMOVE p2m changes Arianna Avanzini
@ 2014-04-07 11:05   ` Julien Grall
  2014-04-09 13:39     ` Ian Campbell
  0 siblings, 1 reply; 19+ messages in thread
From: Julien Grall @ 2014-04-07 11:05 UTC (permalink / raw)
  To: Arianna Avanzini
  Cc: julien.grall, paolo.valente, keir, stefano.stabellini, tim,
	dario.faggioli, Ian.Jackson, xen-devel, Ian.Campbell, etrudeau,
	JBeulich, viktor.kleinik

Hi Arianna,

Thank you for the patch.

On 04/07/2014 12:31 AM, Arianna Avanzini wrote:
> ---
>  xen/arch/arm/p2m.c | 27 +++++++++++++++++++++++++--
>  1 file changed, 25 insertions(+), 2 deletions(-)
> 
> diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
> index 403fd89..395a0b2 100644
> --- a/xen/arch/arm/p2m.c
> +++ b/xen/arch/arm/p2m.c
> @@ -319,6 +319,7 @@ static int apply_p2m_changes(struct domain *d,
>              if ( !populate )
>              {
>                  addr = (addr + FIRST_SIZE) & FIRST_MASK;
> +                maddr = (maddr + FIRST_SIZE) & FIRST_MASK;
>                  continue;
>              }
>  
> @@ -345,6 +346,7 @@ static int apply_p2m_changes(struct domain *d,
>              if ( !populate )
>              {
>                  addr = (addr + SECOND_SIZE) & SECOND_MASK;
> +                maddr = (maddr + SECOND_SIZE) & SECOND_MASK;
>                  continue;
>              }
>  
> @@ -406,12 +408,32 @@ static int apply_p2m_changes(struct domain *d,
>                  {
>                      pte = mfn_to_p2m_entry(maddr >> PAGE_SHIFT, mattr, t);
>                      write_pte(&third[third_table_offset(addr)], pte);
> -                    maddr += PAGE_SIZE;
>                  }
>                  break;
> -            case RELINQUISH:
>              case REMOVE:
>                  {
> +                    unsigned long mfn;
> +
> +                    if ( !pte.p2m.valid )
> +                    {
> +                        count++;

count is only used for RELINQUISH mapping, you don't need to update here.

> +                        break;

I think we should fail if we can't remove rather than continuing.

Regards,

-- 
Julien Grall

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v5 3/8] arch, arm: let map_mmio_regions() take pfn as parameters
  2014-04-06 23:31 ` [PATCH v5 3/8] arch, arm: let map_mmio_regions() take pfn as parameters Arianna Avanzini
@ 2014-04-07 14:56   ` Julien Grall
  2014-04-09 13:54   ` Ian Campbell
  1 sibling, 0 replies; 19+ messages in thread
From: Julien Grall @ 2014-04-07 14:56 UTC (permalink / raw)
  To: Arianna Avanzini
  Cc: julien.grall, paolo.valente, keir, stefano.stabellini, tim,
	dario.faggioli, Ian.Jackson, xen-devel, Ian.Campbell, etrudeau,
	JBeulich, viktor.kleinik

Hi Arianna,

Thank you for the patch.

On 04/07/2014 12:31 AM, Arianna Avanzini wrote:
> Currently, the map_mmio_regions() function, defined for the ARM
> architecture, has parameters with paddr_t type. This interface,
> however, needs caller functions to correctly page-align addresses
> given as parameters to map_mmio_regions(). This commit changes the
> function's interface to accept page frame numbers as parameters.
> This commit also modifies caller functions in an attempt to adapt
> them to the new interface.
> This commit attempts to produce the minimum indispensable needed
> changes; these are also instrumental to making the interface of
> map_mmio_regions() symmetric with the unmap_mmio_regions() function,
> that will be introduced in one of the next commits of the series
> and will feature a pfn-based interface.
> 
> NOTE: platform-specific code has not been tested.
> 
> Signed-off-by: Arianna Avanzini <avanzini.arianna@gmail.com>
> Cc: Dario Faggioli <dario.faggioli@citrix.com>
> Cc: Paolo Valente <paolo.valente@unimore.it>
> Cc: Stefano Stabellini <stefano.stabellini@eu.citrix.com>

Acked-by: Julien Grall <julien.grall@linaro.org>

Regards,

-- 
Julien Grall

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v5 2/8] arch, arm: add consistency check to REMOVE p2m changes
  2014-04-07 11:05   ` Julien Grall
@ 2014-04-09 13:39     ` Ian Campbell
  2014-04-22 19:27       ` Julien Grall
  0 siblings, 1 reply; 19+ messages in thread
From: Ian Campbell @ 2014-04-09 13:39 UTC (permalink / raw)
  To: Julien Grall
  Cc: paolo.valente, keir, stefano.stabellini, tim, dario.faggioli,
	Ian.Jackson, xen-devel, julien.grall, etrudeau, JBeulich,
	Arianna Avanzini, viktor.kleinik

On Mon, 2014-04-07 at 12:05 +0100, Julien Grall wrote:
> count is only used for RELINQUISH mapping, you don't need to update here.

Not related to this patch, but the current code is:

                   if ( !pte.p2m.valid )
                    {
                        count++;
                        break;
                    }

                    count += 0x10;

                    memset(&pte, 0x00, sizeof(pte));
                    write_pte(&third[third_table_offset(addr)], pte);
                    count++;
                }

It seems like that final count++ is unnecessary/wrong.

Ian.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v5 3/8] arch, arm: let map_mmio_regions() take pfn as parameters
  2014-04-06 23:31 ` [PATCH v5 3/8] arch, arm: let map_mmio_regions() take pfn as parameters Arianna Avanzini
  2014-04-07 14:56   ` Julien Grall
@ 2014-04-09 13:54   ` Ian Campbell
  2014-04-12  9:20     ` Arianna Avanzini
  1 sibling, 1 reply; 19+ messages in thread
From: Ian Campbell @ 2014-04-09 13:54 UTC (permalink / raw)
  To: Arianna Avanzini
  Cc: paolo.valente, keir, stefano.stabellini, Ian.Jackson,
	dario.faggioli, tim, xen-devel, julien.grall, etrudeau, JBeulich,
	viktor.kleinik

On Mon, 2014-04-07 at 01:31 +0200, Arianna Avanzini wrote:
> -        res = map_mmio_regions(d, addr & PAGE_MASK,
> -                               PAGE_ALIGN(addr + size) - 1,
> -                               addr & PAGE_MASK);
> +        res = map_mmio_regions(d,
> +                               paddr_to_pfn(addr & PAGE_MASK),
> +                               paddr_to_pfn_aligned(addr + size - 1),


With
+#define paddr_to_pfn_aligned(paddr)    paddr_to_pfn(PAGE_ALIGN(paddr))

There is a subtle difference here, which is that the "- 1" is now inside
the align. Does this always have the same result? I'm not sure.

If addr+size == 0x1000 (page aligned) then:

        PAGE_ALIGN(0x10000)-1 = 0x10000-1 = 0xffff

But

        paddr_to_pfn_aligned(0x10000 - 1) =
        paddr_to_pfn(PAGE_ALIGN(0xffff)) = paddr_to_pfn(0x10000) = 0x10

The new map_mmio_regions uses pfn_to_paddr which is:
#define pfn_to_paddr(pfn) ((paddr_t)(pfn) << PAGE_SHIFT)

So with the old code the end address would be 0xffff, while with the new
code it is 0x10<<12 = 0x10000.

I suspect the implementation of apply_to_p2m_changes is such that it
doesn't actually change anything. Can you confirm that this was your
intention?

Is the end argument tio map_mmio_regions now intended to be inclusive or
exclusive? This sort of issue can be avoided by using a count instead of
an end in the interface.

Ian.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v5 5/8] xen, common: add the XEN_DOMCTL_memory_mapping hypercall
  2014-04-06 23:31 ` [PATCH v5 5/8] xen, common: add the XEN_DOMCTL_memory_mapping hypercall Arianna Avanzini
  2014-04-07  7:55   ` Jan Beulich
@ 2014-04-09 14:03   ` Ian Campbell
  1 sibling, 0 replies; 19+ messages in thread
From: Ian Campbell @ 2014-04-09 14:03 UTC (permalink / raw)
  To: Arianna Avanzini
  Cc: paolo.valente, keir, stefano.stabellini, Ian.Jackson,
	dario.faggioli, tim, xen-devel, julien.grall, etrudeau, JBeulich,
	viktor.kleinik

On Mon, 2014-04-07 at 01:31 +0200, Arianna Avanzini wrote:
> This commit introduces a first attempt of implementation of the
> XEN_DOMCTL_memory_mapping hypercall for ARM. As the implementation
> would have been almost identical to the one for x86, this code has
> been made common to both the architectures. The only difference
> between the two procedures lies in the arch-specific implementation
> of the map_mmio_regions() and unmap_mmio_regions() functions.
> 
> Signed-off-by: Arianna Avanzini <avanzini.arianna@gmail.com>
> Cc: Dario Faggioli <dario.faggioli@citrix.com>
> Cc: Paolo Valente <paolo.valente@unimore.it>
> Cc: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
> Cc: Julien Grall <julien.grall@citrix.com>
> Cc: Ian Campbell <Ian.Campbell@eu.citrix.com>
> Cc: Jan Beulich <JBeulich@suse.com>
> Cc: Keir Fraser <keir@xen.org>
> Cc: Tim Deegan <tim@xen.org>
> Cc: Jan Beulich <JBeulich@suse.com>
> Cc: Keir Fraser <keir@xen.org>
> Cc: Tim Deegan <tim@xen.org>
> Cc: Ian Jackson <Ian.Jackson@eu.citrix.com>
> Cc: Eric Trudeau <etrudeau@broadcom.com>
> Cc: Viktor Kleinik <viktor.kleinik@globallogic.com>
> 
> ---
> 
>     v5:
>         - Let the unmap_mmio_regions() function for x86 return a proper
>           error code upon failure.
>         - Restore correct handling of errors in the remove path of the
>           hypercall, assigning to the "ret" local variable the error
>           code returned by the unmap_mmio_regions() function only if
>           iomem_deny_access() didn't return with an error.
>         - Compute gfn_end - 1 and mfn_end - 1 only once in the DOMCTL.
>         - Use a local variable to keep the return value of the function
>           unmap_mmio_regions() instead of re-using the "add" variable.
>         - Add a comment to make hopefully clearer how error values of
>           functions are handled in the remove path of the DOMCTL.
>         - Rename new header to p2m-common.h.
> 
>     v4:
>         - Use a define for paddr_bits instead of a new variable.
>         - Define prototypes for common functions map_mmio_regions() and
>           unmap_mmio_regions() only once in a common header.
>         - Fix type and signedness of local variables used as indexes in
>           map_mmio_regions() and unmap_mmio_regions() for x86.
>         - Clear p2m entries in map_mmio_regions() for x86 only if
>           set_mmio_p2m_entry() returned with an error.
>         - Make ranges inclusive of the end address in map_mmio_regions()
>           and unmap_mmio_regions() for x86.
>         - Turn hard tabs into spaces.
> 
>     v3:
>         - Move code to xen/common/domctl.c; abstract out differences between
>           the x86 and ARM code:
>           . add map_mmio_regions() and unmap_mmio_regions() functions for x86;
>           . add a paddr_bits variable for ARM.
>         - Use pfn as parameters to the unmap_mmio_regions() function.
>         - Compute gfn + nr_mfns and mfn + nr_mfns only once.
> 
>     v2:
>         - Move code to xen/arm/domctl.c.
>         - Use the already-defined PADDR_BITS constant in the new DOMCTL.
>         - Use paddr_t as arguments to the map_mmio_regions() function.
>         - Page-align addresses given as arguments to map_mmio_regions() and
>           unmap_mmio_regions(). 
> 
> ---
>  xen/arch/arm/p2m.c           | 12 ++++++++
>  xen/arch/x86/domctl.c        | 70 -------------------------------------------
>  xen/arch/x86/mm/p2m.c        | 42 ++++++++++++++++++++++++++
>  xen/common/domctl.c          | 71 ++++++++++++++++++++++++++++++++++++++++++++
>  xen/include/asm-arm/p2m.h    |  9 ++----
>  xen/include/asm-x86/p2m.h    |  1 +
>  xen/include/xen/p2m-common.h | 16 ++++++++++
>  7 files changed, 145 insertions(+), 76 deletions(-)
>  create mode 100644 xen/include/xen/p2m-common.h
> 
> diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
> index 110b63a..cc71a5d 100644
> --- a/xen/arch/arm/p2m.c
> +++ b/xen/arch/arm/p2m.c
> @@ -529,6 +529,18 @@ int map_mmio_regions(struct domain *d,
>                               MATTR_DEV, p2m_mmio_direct);
>  }
>  
> +int unmap_mmio_regions(struct domain *d,
> +                       unsigned long start_gfn,
> +                       unsigned long end_gfn,
> +                       unsigned long mfn)
> +{
> +    return apply_p2m_changes(d, REMOVE,
> +                             pfn_to_paddr(start_gfn),
> +                             pfn_to_paddr(end_gfn),
> +                             pfn_to_paddr(mfn),
> +                             MATTR_DEV, p2m_mmio_direct);

The final argument here is not used in the REMOVE case. Please pass
p2m_invalid here, unless/until that changes.

> +}
> +
>  int guest_physmap_add_entry(struct domain *d,
>                              unsigned long gpfn,
>                              unsigned long mfn,
> diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c
> index 1e51289..69a7fbf 100644
> --- a/xen/arch/x86/domctl.c
> +++ b/xen/arch/x86/domctl.c
> @@ -639,76 +639,6 @@ long arch_do_domctl(
>      }
>      break;
>  
> -    case XEN_DOMCTL_memory_mapping:
> -    {
> -        unsigned long gfn = domctl->u.memory_mapping.first_gfn;
> -        unsigned long mfn = domctl->u.memory_mapping.first_mfn;
> -        unsigned long nr_mfns = domctl->u.memory_mapping.nr_mfns;
> -        int add = domctl->u.memory_mapping.add_mapping;
> -        unsigned long i;
> -
> -        ret = -EINVAL;
> -        if ( (mfn + nr_mfns - 1) < mfn || /* wrap? */
> -             ((mfn | (mfn + nr_mfns - 1)) >> (paddr_bits - PAGE_SHIFT)) ||
> -             (gfn + nr_mfns - 1) < gfn ) /* wrap? */
> -            break;
> -
> -        ret = -EPERM;
> -        if ( !iomem_access_permitted(current->domain, mfn, mfn + nr_mfns - 1) )
> -            break;
> -
> -        ret = xsm_iomem_mapping(XSM_HOOK, d, mfn, mfn + nr_mfns - 1, add);
> -        if ( ret )
> -            break;
> -
> -        if ( add )
> -        {
> -            printk(XENLOG_G_INFO
> -                   "memory_map:add: dom%d gfn=%lx mfn=%lx nr=%lx\n",
> -                   d->domain_id, gfn, mfn, nr_mfns);
> -
> -            ret = iomem_permit_access(d, mfn, mfn + nr_mfns - 1);
> -            if ( !ret && paging_mode_translate(d) )
> -            {
> -                for ( i = 0; !ret && i < nr_mfns; i++ )
> -                    if ( !set_mmio_p2m_entry(d, gfn + i, _mfn(mfn + i)) )
> -                        ret = -EIO;
> -                if ( ret )
> -                {
> -                    printk(XENLOG_G_WARNING
> -                           "memory_map:fail: dom%d gfn=%lx mfn=%lx\n",
> -                           d->domain_id, gfn + i, mfn + i);
> -                    while ( i-- )
> -                        clear_mmio_p2m_entry(d, gfn + i, _mfn(mfn + i));
> -                    if ( iomem_deny_access(d, mfn, mfn + nr_mfns - 1) &&
> -                         is_hardware_domain(current->domain) )
> -                        printk(XENLOG_ERR
> -                               "memory_map: failed to deny dom%d access to [%lx,%lx]\n",
> -                               d->domain_id, mfn, mfn + nr_mfns - 1);
> -                }
> -            }
> -        }
> -        else
> -        {
> -            printk(XENLOG_G_INFO
> -                   "memory_map:remove: dom%d gfn=%lx mfn=%lx nr=%lx\n",
> -                   d->domain_id, gfn, mfn, nr_mfns);
> -
> -            if ( paging_mode_translate(d) )
> -                for ( i = 0; i < nr_mfns; i++ )
> -                    add |= !clear_mmio_p2m_entry(d, gfn + i, _mfn(mfn + i));
> -            ret = iomem_deny_access(d, mfn, mfn + nr_mfns - 1);
> -            if ( !ret && add )
> -                ret = -EIO;
> -            if ( ret && is_hardware_domain(current->domain) )
> -                printk(XENLOG_ERR
> -                       "memory_map: error %ld %s dom%d access to [%lx,%lx]\n",
> -                       ret, add ? "removing" : "denying", d->domain_id,
> -                       mfn, mfn + nr_mfns - 1);
> -        }
> -    }
> -    break;
> -
>      case XEN_DOMCTL_ioport_mapping:
>      {
>  #define MAX_IOPORTS    0x10000
> diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c
> index 2c894b8..2c6ef24 100644
> --- a/xen/arch/x86/mm/p2m.c
> +++ b/xen/arch/x86/mm/p2m.c
> @@ -1631,6 +1631,48 @@ unsigned long paging_gva_to_gfn(struct vcpu *v,
>      return hostmode->gva_to_gfn(v, hostp2m, va, pfec);
>  }
>  
> +int map_mmio_regions(struct domain *d,
> +                     unsigned long start_gfn,
> +                     unsigned long end_gfn,
> +                     unsigned long mfn)

Personally I would have preferred to see x86 switch to this interface
separately from moving the implementation of the user from x86 to
generic code, since doing them at the same time makes it hard to see
what actually changes in XEN_DOMCTL_memory_mapping.

> +	    long unmap_ret;

Stray hard tab.

> diff --git a/xen/include/asm-x86/p2m.h b/xen/include/asm-x86/p2m.h
> index c403534..af53816 100644
> --- a/xen/include/asm-x86/p2m.h
> +++ b/xen/include/asm-x86/p2m.h
> @@ -29,6 +29,7 @@
>  
>  #include <xen/config.h>
>  #include <xen/paging.h>
> +#include <xen/p2m-common.h>

More normally xen/p2m.h (which you have as p2m-common.h) would include
the asm version. But I suppose that involves a lot more code changes.

Ian.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v5 6/8] tools, libxl: parse optional start gfn from the iomem config option
  2014-04-06 23:31 ` [PATCH v5 6/8] tools, libxl: parse optional start gfn from the iomem config option Arianna Avanzini
@ 2014-04-09 14:10   ` Ian Campbell
  0 siblings, 0 replies; 19+ messages in thread
From: Ian Campbell @ 2014-04-09 14:10 UTC (permalink / raw)
  To: Arianna Avanzini
  Cc: paolo.valente, keir, stefano.stabellini, Ian.Jackson,
	dario.faggioli, tim, xen-devel, julien.grall, etrudeau, JBeulich,
	viktor.kleinik

On Mon, 2014-04-07 at 01:31 +0200, Arianna Avanzini wrote:
> Currently, the "iomem" domU config option allows to specify a machine
> address range to be mapped to the domU. However, there is no way to
> specify the guest address range used for the mapping. This commit
> extends the iomem option handling code to parse an additional, optional
> parameter: this parameter, if given, specifies the start guest address
> used for the mapping; if no start guest address is given, a 1:1 mapping
> is performed as default.
> 
> Signed-off-by: Arianna Avanzini <avanzini.arianna@gmail.com>
> Cc: Dario Faggioli <dario.faggioli@citrix.com>
> Cc: Paolo Valente <paolo.valente@unimore.it>
> Cc: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
> Cc: Julien Grall <julien.grall@citrix.com>
> Cc: Ian Campbell <Ian.Campbell@eu.citrix.com>
> Cc: Jan Beulich <JBeulich@suse.com>
> Cc: Keir Fraser <keir@xen.org>
> Cc: Tim Deegan <tim@xen.org>
> Cc: Ian Jackson <Ian.Jackson@eu.citrix.com>
> Cc: Eric Trudeau <etrudeau@broadcom.com>
> Cc: Viktor Kleinik <viktor.kleinik@globallogic.com>
> 
> ---
> 
>     v5:
>         - Initialize the gfn field of the iomem structure with the
>           value "(uint64_t)-1".
>         - Defer the assignment of the value of "start" to "gfn", if
>           "gfn" has been initialized to the default value, in libxl.
>         - Use a local variable to keep the return value of sscanf()
>           for better code readability.
> 
>     v4:
>         - Add definition of a LIBXL_HAVE_BUILDINFO_IOMEM_START_GFN macro
>           to indicate the availability of the new option.
>         - Simplify the code parsing the new optional parameter by using
>           the switch construct on the return value of the sscanf() function
>           instead of calling the function twice.
>         - Add a short paragraph to the manpage about the use of the iomem
>           option to passthrough devices protected by an IOMMU.
>         - Add comments to the fields of the "iomem" structure.
> 
> ---
>  docs/man/xl.cfg.pod.5       | 13 +++++++++----
>  tools/libxl/libxl.h         | 10 ++++++++++
>  tools/libxl/libxl_create.c  |  6 ++++++
>  tools/libxl/libxl_types.idl |  7 +++++--
>  tools/libxl/xl_cmdimpl.c    | 19 ++++++++++---------
>  5 files changed, 40 insertions(+), 15 deletions(-)
> 
> diff --git a/docs/man/xl.cfg.pod.5 b/docs/man/xl.cfg.pod.5
> index a6663b9..d54f601 100644
> --- a/docs/man/xl.cfg.pod.5
> +++ b/docs/man/xl.cfg.pod.5
> @@ -602,12 +602,17 @@ is given in hexadecimal and may either a span e.g. C<2f8-2ff>
>  It is recommended to use this option only for trusted VMs under
>  administrator control.
>  
> -=item B<iomem=[ "IOMEM_START,NUM_PAGES", "IOMEM_START,NUM_PAGES", ... ]>
> +=item B<iomem=[ "IOMEM_START,NUM_PAGES[@GFN]", "IOMEM_START,NUM_PAGES[@GFN]", ... ]>
>  
>  Allow guest to access specific hardware I/O memory pages. B<IOMEM_START>
> -is a physical page number. B<NUM_PAGES> is the number
> -of pages beginning with B<START_PAGE> to allow access. Both values
> -must be given in hexadecimal.
> +is a physical page number. B<NUM_PAGES> is the number of pages beginning
> +with B<START_PAGE> to allow access. B<GFN> specifies the guest frame number
> +where the mapping will start in the domU's address space.

"If B<GFN> is not given then ..."

> diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
> index b2c3015..e4a1128 100644
> --- a/tools/libxl/libxl.h
> +++ b/tools/libxl/libxl.h
> @@ -95,6 +95,16 @@
>  #define LIBXL_HAVE_BUILDINFO_EVENT_CHANNELS 1
>  
>  /*
> + * LIBXL_HAVE_BUILDINFO_IOMEM_START_GFN indicated that it is possible

s/indicated/indicates/

> diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c
> index d015cf4..369cd77 100644
> --- a/tools/libxl/libxl_create.c
> +++ b/tools/libxl/libxl_create.c
> +        if (b_info->iomem[i].gfn == (uint64_t)-1)

Please can you #define something like LIBXL_INVALID_GFN and use it both
here and in the idl. The value should probably be "~(uint64_t)0" rather
than -1.

Other than those small nits:
Acked-by: Ian Campbell <ian.campbell@citrix.com>

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v5 8/8] tools, libxl: handle the iomem parameter with the memory_mapping hcall
  2014-04-06 23:32 ` [PATCH v5 8/8] tools, libxl: handle the iomem parameter with the memory_mapping hcall Arianna Avanzini
@ 2014-04-09 14:25   ` Ian Campbell
  0 siblings, 0 replies; 19+ messages in thread
From: Ian Campbell @ 2014-04-09 14:25 UTC (permalink / raw)
  To: Arianna Avanzini
  Cc: paolo.valente, keir, stefano.stabellini, Ian.Jackson,
	dario.faggioli, tim, xen-devel, julien.grall, etrudeau, JBeulich,
	Daniel De Graaf, viktor.kleinik

On Mon, 2014-04-07 at 01:32 +0200, Arianna Avanzini wrote:
> Currently, the configuration-parsing code concerning the handling of the
> iomem parameter only invokes the XEN_DOMCTL_iomem_permission hypercall.
> This commit lets the XEN_DOMCTL_memory_mapping hypercall be invoked
> after XEN_DOMCTL_iomem_permission when the iomem parameter is parsed
> from a domU configuration file, so that the address range can be mapped
> to the address space of the domU. The hypercall is invoked only in case
> of domains using an auto-translated physmap.

I suppose http://article.gmane.org/gmane.comp.emulators.xen.devel/194504
applies here, hence this patch and patch #7 haven't changed this time
round.

IIRC the main issue to be decided is the one from:
http://article.gmane.org/gmane.comp.emulators.xen.devel/193808 and
http://article.gmane.org/gmane.comp.emulators.xen.devel/194058 .

The question is whether XEN_DOMCTL_memory_mapping should also implicitly
grant permissions to the region or if it should require that a call to
XEN_DOMCTL_iomem_permission has already been made.

In the former case (implicitly granting) the calls to
xc_domain_memory_mapping replace xc_domain_iomem_permission in this
patch instead of being added.

In the latter case (require iomem_perm first) then te
iomem_permit_access should be removed from the
XEN_DOMCTL_memory_mapping implementation and be replaced with a
permissions check instead of grant. We'd also want to make sure that
e.g. libxl_pci.c was making the correct xc_domain_iomem_permission calls
to subsequently allow qemu to use xc_domain_memory_mapping (which would
mean refactoring do_pci_add to make those calls for both HVM and PV
guests, AFAICT).

Although the first change seems simpler the second way has the advantage
of separating the permission from the mapping, which might be beneficial
because it handles the case of two mappings of the same thing better. It
might also have implications for XSM and the separation of privilege
into toolstack and qemu.

Ian.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v5 3/8] arch, arm: let map_mmio_regions() take pfn as parameters
  2014-04-09 13:54   ` Ian Campbell
@ 2014-04-12  9:20     ` Arianna Avanzini
  0 siblings, 0 replies; 19+ messages in thread
From: Arianna Avanzini @ 2014-04-12  9:20 UTC (permalink / raw)
  To: Ian Campbell
  Cc: paolo.valente, keir, stefano.stabellini, Ian.Jackson,
	dario.faggioli, tim, xen-devel, julien.grall, etrudeau, JBeulich,
	viktor.kleinik

Hello,

thank you for your comments, and sorry for the huge delay in replying.

On 04/09/2014 03:54 PM, Ian Campbell wrote:
> On Mon, 2014-04-07 at 01:31 +0200, Arianna Avanzini wrote:
>> -        res = map_mmio_regions(d, addr & PAGE_MASK,
>> -                               PAGE_ALIGN(addr + size) - 1,
>> -                               addr & PAGE_MASK);
>> +        res = map_mmio_regions(d,
>> +                               paddr_to_pfn(addr & PAGE_MASK),
>> +                               paddr_to_pfn_aligned(addr + size - 1),
> 
> 
> With
> +#define paddr_to_pfn_aligned(paddr)    paddr_to_pfn(PAGE_ALIGN(paddr))
> 
> There is a subtle difference here, which is that the "- 1" is now inside
> the align. Does this always have the same result? I'm not sure.
> 
> If addr+size == 0x1000 (page aligned) then:
> 
>         PAGE_ALIGN(0x10000)-1 = 0x10000-1 = 0xffff
> 
> But
> 
>         paddr_to_pfn_aligned(0x10000 - 1) =
>         paddr_to_pfn(PAGE_ALIGN(0xffff)) = paddr_to_pfn(0x10000) = 0x10
> 
> The new map_mmio_regions uses pfn_to_paddr which is:
> #define pfn_to_paddr(pfn) ((paddr_t)(pfn) << PAGE_SHIFT)
> 
> So with the old code the end address would be 0xffff, while with the new
> code it is 0x10<<12 = 0x10000.
> 
> I suspect the implementation of apply_to_p2m_changes is such that it
> doesn't actually change anything. Can you confirm that this was your
> intention?
> 

It wasn't my intention to change the size of the address range to be mapped,
thank you for pointing that out. As far as I can understand, the changes in this
patch would let apply_p2m_changes() use one extra address for the mapping; sorry
for that.

While preparing the patch I saw that, e.g., with addr + size = 0x10000,

end_gfn = paddr_to_pfn(PAGE_ALIGN(0x10000) - 1) =
          paddr_to_pfn(PAGE_ALIGN(0x10000)) - 1 = 0xf

and

pfn_to_paddr(end_gfn) = 0xf000

which seemed to me to be wrong, as the previous end address was, as you wrote,
0xffff.

Instead, if

end_gfn = paddr_to_pfn(PAGE_ALIGN(0x10000 - 1)) = 0x10

then

pfn_to_paddr(end_gfn) = 0x10000

which I thought lets the needed address range be mapped; however I didn't see
what you pointed out, that it also lets one extra address be used for the mapping.

> Is the end argument tio map_mmio_regions now intended to be inclusive or
> exclusive? 

As far as I understand, apply_p2m_changes(), which is called by the ARM version
of map_mmio_regions(), seems to take it as exclusive, as the mapping is
performed while (addr < end_gpaddr).
In the x86 version of map_mmio_regions() it is instead intended to be inclusive;
sorry for this mismatch, I'll try to make the behavior of the two versions
consistent.

> This sort of issue can be avoided by using a count instead of
> an end in the interface.
> 

Thank you very much for the hint.


> Ian.
> 



-- 
/*
 * Arianna Avanzini
 * avanzini.arianna@gmail.com
 * 73628@studenti.unimore.it
 */

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH v5 2/8] arch, arm: add consistency check to REMOVE p2m changes
  2014-04-09 13:39     ` Ian Campbell
@ 2014-04-22 19:27       ` Julien Grall
  0 siblings, 0 replies; 19+ messages in thread
From: Julien Grall @ 2014-04-22 19:27 UTC (permalink / raw)
  To: Ian Campbell
  Cc: paolo.valente, keir, stefano.stabellini, tim, dario.faggioli,
	Ian.Jackson, xen-devel, julien.grall, etrudeau, JBeulich,
	Arianna Avanzini, viktor.kleinik



On 09/04/14 14:39, Ian Campbell wrote:
> On Mon, 2014-04-07 at 12:05 +0100, Julien Grall wrote:
>> count is only used for RELINQUISH mapping, you don't need to update here.
>
> Not related to this patch, but the current code is:
>
>                     if ( !pte.p2m.valid )
>                      {
>                          count++;
>                          break;
>                      }
>
>                      count += 0x10;
>
>                      memset(&pte, 0x00, sizeof(pte));
>                      write_pte(&third[third_table_offset(addr)], pte);
>                      count++;
>                  }
>
> It seems like that final count++ is unnecessary/wrong.

Right. I will send a patch to fix it.

Regards,

-- 
Julien Grall

^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2014-04-22 19:27 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-04-06 23:31 [PATCH v5 0/8] Implement the XEN_DOMCTL_memory_mapping hypercall for ARM Arianna Avanzini
2014-04-06 23:31 ` [PATCH v5 1/8] arch, arm: domain build: let dom0 access I/O memory of mapped devices Arianna Avanzini
2014-04-06 23:31 ` [PATCH v5 2/8] arch, arm: add consistency check to REMOVE p2m changes Arianna Avanzini
2014-04-07 11:05   ` Julien Grall
2014-04-09 13:39     ` Ian Campbell
2014-04-22 19:27       ` Julien Grall
2014-04-06 23:31 ` [PATCH v5 3/8] arch, arm: let map_mmio_regions() take pfn as parameters Arianna Avanzini
2014-04-07 14:56   ` Julien Grall
2014-04-09 13:54   ` Ian Campbell
2014-04-12  9:20     ` Arianna Avanzini
2014-04-06 23:31 ` [PATCH v5 4/8] arch, x86: check if mapping exists before memory_mapping removes it Arianna Avanzini
2014-04-06 23:31 ` [PATCH v5 5/8] xen, common: add the XEN_DOMCTL_memory_mapping hypercall Arianna Avanzini
2014-04-07  7:55   ` Jan Beulich
2014-04-09 14:03   ` Ian Campbell
2014-04-06 23:31 ` [PATCH v5 6/8] tools, libxl: parse optional start gfn from the iomem config option Arianna Avanzini
2014-04-09 14:10   ` Ian Campbell
2014-04-06 23:31 ` [PATCH v5 7/8] tools, libxl: add helpers to establish if guest is auto-translated Arianna Avanzini
2014-04-06 23:32 ` [PATCH v5 8/8] tools, libxl: handle the iomem parameter with the memory_mapping hcall Arianna Avanzini
2014-04-09 14:25   ` Ian Campbell

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.