All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v14 00/11] x86: guest resource mapping
@ 2017-11-28 15:08 Paul Durrant
  2017-11-28 15:08 ` [PATCH v14 01/11] x86/hvm/ioreq: maintain an array of ioreq servers rather than a list Paul Durrant
                   ` (10 more replies)
  0 siblings, 11 replies; 30+ messages in thread
From: Paul Durrant @ 2017-11-28 15:08 UTC (permalink / raw)
  To: xen-devel
  Cc: Stefano Stabellini, Wei Liu, George Dunlap, Andrew Cooper,
	Ian Jackson, Marek Marczykowski-Górecki, Tim Deegan,
	Julien Grall, Paul Durrant, Jan Beulich, Daniel De Graaf

This series introduces support for direct mapping of guest resources.
The resources are:
 - IOREQ server pages
 - Grant tables

v14:
 - Responded to more comments from Jan.

v13:
 - Responded to more comments from Jan and Julien.
 - Build-tested using ARM cross-compilation.

v12:
 - Responded to more comments from Jan.

v11:
 - Responded to more comments from Jan.

v10:
 - Responded to comments from Jan.

v9:
 - Change to patch #1 only.

v8:
 - Re-ordered series and dropped two patches that have already been
    committed.

v7:
 - Fixed assertion failure hit during domain destroy.

v6:
 - Responded to missed comments from Roger.

v5:
 - Responded to review comments from Wei.

v4:
 - Responded to further review comments from Roger.

v3:
 - Dropped original patch #1 since it is covered by Juergen's patch.
 - Added new xenforeignmemorycleanup patch (#4).
 - Replaced the patch introducing the ioreq server 'is_default' flag with
   one that changes the ioreq server list into an array (#8).
      
Paul Durrant (11):
  x86/hvm/ioreq: maintain an array of ioreq servers rather than a list
  x86/hvm/ioreq: simplify code and use consistent naming
  x86/hvm/ioreq: use gfn_t in struct hvm_ioreq_page
  x86/hvm/ioreq: defer mapping gfns until they are actually requsted
  x86/mm: add HYPERVISOR_memory_op to acquire guest resources
  x86/hvm/ioreq: add a new mappable resource type...
  x86/mm: add an extra command to HYPERVISOR_mmu_update...
  tools/libxenforeignmemory: add support for resource mapping
  tools/libxenforeignmemory: reduce xenforeignmemory_restrict code
    footprint
  common: add a new mappable resource type: XENMEM_resource_grant_table
  tools/libxenctrl: use new xenforeignmemory API to seed grant table

 tools/flask/policy/modules/xen.if                  |   4 +-
 tools/include/xen-sys/Linux/privcmd.h              |  11 +
 tools/libs/devicemodel/core.c                      |   8 +
 tools/libs/devicemodel/include/xendevicemodel.h    |   6 +-
 tools/libs/foreignmemory/Makefile                  |   2 +-
 tools/libs/foreignmemory/core.c                    |  53 ++
 tools/libs/foreignmemory/freebsd.c                 |   7 -
 .../libs/foreignmemory/include/xenforeignmemory.h  |  41 +
 tools/libs/foreignmemory/libxenforeignmemory.map   |   5 +
 tools/libs/foreignmemory/linux.c                   |  45 ++
 tools/libs/foreignmemory/minios.c                  |   7 -
 tools/libs/foreignmemory/netbsd.c                  |   7 -
 tools/libs/foreignmemory/private.h                 |  43 +-
 tools/libs/foreignmemory/solaris.c                 |   7 -
 tools/libxc/include/xc_dom.h                       |   8 +-
 tools/libxc/xc_dom_boot.c                          | 114 ++-
 tools/libxc/xc_sr_restore_x86_hvm.c                |  10 +-
 tools/libxc/xc_sr_restore_x86_pv.c                 |   2 +-
 tools/libxl/libxl_dom.c                            |   1 -
 tools/python/xen/lowlevel/xc/xc.c                  |   6 +-
 xen/arch/x86/hvm/dm.c                              |   9 +-
 xen/arch/x86/hvm/ioreq.c                           | 831 ++++++++++++---------
 xen/arch/x86/mm.c                                  |  54 +-
 xen/arch/x86/mm/p2m.c                              |   3 +-
 xen/common/compat/memory.c                         |  95 +++
 xen/common/grant_table.c                           |  63 +-
 xen/common/memory.c                                | 133 ++++
 xen/include/asm-arm/mm.h                           |   7 +
 xen/include/asm-arm/p2m.h                          |  10 +
 xen/include/asm-x86/hvm/domain.h                   |  14 +-
 xen/include/asm-x86/hvm/ioreq.h                    |   2 +
 xen/include/asm-x86/mm.h                           |   5 +
 xen/include/asm-x86/p2m.h                          |   3 +
 xen/include/public/hvm/dm_op.h                     |  36 +-
 xen/include/public/memory.h                        |  58 +-
 xen/include/public/xen.h                           |  12 +-
 xen/include/xen/grant_table.h                      |   4 +
 xen/include/xlat.lst                               |   1 +
 xen/include/xsm/dummy.h                            |   6 +
 xen/include/xsm/xsm.h                              |   6 +
 xen/xsm/dummy.c                                    |   1 +
 xen/xsm/flask/hooks.c                              |   6 +
 xen/xsm/flask/policy/access_vectors                |   2 +
 43 files changed, 1253 insertions(+), 495 deletions(-)

---
Cc: Daniel De Graaf <dgdegra@tycho.nsa.gov>
Cc: Ian Jackson <ian.jackson@eu.citrix.com>
Cc: Wei Liu <wei.liu2@citrix.com>
Cc: Andrew Cooper <andrew.cooper3@citrix.com>
Cc: George Dunlap <George.Dunlap@eu.citrix.com>
Cc: Jan Beulich <jbeulich@suse.com>
Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Tim Deegan <tim@xen.org>
Cc: "Marek Marczykowski-Górecki" <marmarek@invisiblethingslab.com>
Cc: Paul Durrant <paul.durrant@citrix.com>
Cc: George Dunlap <george.dunlap@eu.citrix.com>
Cc: Julien Grall <julien.grall@arm.com>

-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* [PATCH v14 01/11] x86/hvm/ioreq: maintain an array of ioreq servers rather than a list
  2017-11-28 15:08 [PATCH v14 00/11] x86: guest resource mapping Paul Durrant
@ 2017-11-28 15:08 ` Paul Durrant
  2017-11-28 15:08 ` [PATCH v14 02/11] x86/hvm/ioreq: simplify code and use consistent naming Paul Durrant
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 30+ messages in thread
From: Paul Durrant @ 2017-11-28 15:08 UTC (permalink / raw)
  To: xen-devel; +Cc: Andrew Cooper, Paul Durrant

A subsequent patch will remove the current implicit limitation on creation
of ioreq servers which is due to the allocation of gfns for the ioreq
structures and buffered ioreq ring.

It will therefore be necessary to introduce an explicit limit and, since
this limit should be small, it simplifies the code to maintain an array of
that size rather than using a list.

Also, by reserving an array slot for the default server and populating
array slots early in create, the need to pass an 'is_default' boolean
to sub-functions can be avoided.

Some function return values are changed by this patch: Specifically, in
the case where the id of the default ioreq server is passed in, -EOPNOTSUPP
is now returned rather than -ENOENT.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
---
Cc: Andrew Cooper <andrew.cooper3@citrix.com>

v10:
 - modified FOR_EACH... macro as suggested by Jan.
 - check for NULL in IS_DEFAULT macro as suggested by Jan.

v9:
 - modified FOR_EACH... macro as requested by Andrew.

v8:
 - Addressed various comments from Jan.

v7:
 - Fixed assertion failure found in testing.

v6:
 - Updated according to comments made by Roger on v4 that I'd missed.

v5:
 - Switched GET/SET_IOREQ_SERVER() macros to get/set_ioreq_server()
   functions to avoid possible double-evaluation issues.

v4:
 - Introduced more helper macros and relocated them to the top of the
   code.

v3:
 - New patch (replacing "move is_default into struct hvm_ioreq_server") in
   response to review comments.
---
 xen/arch/x86/hvm/ioreq.c         | 502 +++++++++++++++++++--------------------
 xen/include/asm-x86/hvm/domain.h |  10 +-
 2 files changed, 245 insertions(+), 267 deletions(-)

diff --git a/xen/arch/x86/hvm/ioreq.c b/xen/arch/x86/hvm/ioreq.c
index d5afe20cc8..da31918bb1 100644
--- a/xen/arch/x86/hvm/ioreq.c
+++ b/xen/arch/x86/hvm/ioreq.c
@@ -33,6 +33,37 @@
 
 #include <public/hvm/ioreq.h>
 
+static void set_ioreq_server(struct domain *d, unsigned int id,
+                             struct hvm_ioreq_server *s)
+{
+    ASSERT(id < MAX_NR_IOREQ_SERVERS);
+    ASSERT(!s || !d->arch.hvm_domain.ioreq_server.server[id]);
+
+    d->arch.hvm_domain.ioreq_server.server[id] = s;
+}
+
+#define GET_IOREQ_SERVER(d, id) \
+    (d)->arch.hvm_domain.ioreq_server.server[id]
+
+static struct hvm_ioreq_server *get_ioreq_server(const struct domain *d,
+                                                 unsigned int id)
+{
+    if ( id >= MAX_NR_IOREQ_SERVERS )
+        return NULL;
+
+    return GET_IOREQ_SERVER(d, id);
+}
+
+#define IS_DEFAULT(s) \
+    ((s) && (s) == GET_IOREQ_SERVER((s)->domain, DEFAULT_IOSERVID))
+
+/* Iterate over all possible ioreq servers */
+#define FOR_EACH_IOREQ_SERVER(d, id, s) \
+    for ( (id) = 0; (id) < MAX_NR_IOREQ_SERVERS; (id)++ ) \
+        if ( !(s = GET_IOREQ_SERVER(d, id)) ) \
+            continue; \
+        else
+
 static ioreq_t *get_ioreq(struct hvm_ioreq_server *s, struct vcpu *v)
 {
     shared_iopage_t *p = s->ioreq.va;
@@ -47,10 +78,9 @@ bool hvm_io_pending(struct vcpu *v)
 {
     struct domain *d = v->domain;
     struct hvm_ioreq_server *s;
+    unsigned int id;
 
-    list_for_each_entry ( s,
-                          &d->arch.hvm_domain.ioreq_server.list,
-                          list_entry )
+    FOR_EACH_IOREQ_SERVER(d, id, s)
     {
         struct hvm_ioreq_vcpu *sv;
 
@@ -127,10 +157,9 @@ bool handle_hvm_io_completion(struct vcpu *v)
     struct hvm_vcpu_io *vio = &v->arch.hvm_vcpu.hvm_io;
     struct hvm_ioreq_server *s;
     enum hvm_io_completion io_completion;
+    unsigned int id;
 
-      list_for_each_entry ( s,
-                          &d->arch.hvm_domain.ioreq_server.list,
-                          list_entry )
+    FOR_EACH_IOREQ_SERVER(d, id, s)
     {
         struct hvm_ioreq_vcpu *sv;
 
@@ -243,13 +272,12 @@ static int hvm_map_ioreq_page(
 bool is_ioreq_server_page(struct domain *d, const struct page_info *page)
 {
     const struct hvm_ioreq_server *s;
+    unsigned int id;
     bool found = false;
 
     spin_lock_recursive(&d->arch.hvm_domain.ioreq_server.lock);
 
-    list_for_each_entry ( s,
-                          &d->arch.hvm_domain.ioreq_server.list,
-                          list_entry )
+    FOR_EACH_IOREQ_SERVER(d, id, s)
     {
         if ( (s->ioreq.va && s->ioreq.page == page) ||
              (s->bufioreq.va && s->bufioreq.page == page) )
@@ -302,7 +330,7 @@ static void hvm_update_ioreq_evtchn(struct hvm_ioreq_server *s,
 }
 
 static int hvm_ioreq_server_add_vcpu(struct hvm_ioreq_server *s,
-                                     bool is_default, struct vcpu *v)
+                                     struct vcpu *v)
 {
     struct hvm_ioreq_vcpu *sv;
     int rc;
@@ -331,7 +359,7 @@ static int hvm_ioreq_server_add_vcpu(struct hvm_ioreq_server *s,
             goto fail3;
 
         s->bufioreq_evtchn = rc;
-        if ( is_default )
+        if ( IS_DEFAULT(s) )
             d->arch.hvm_domain.params[HVM_PARAM_BUFIOREQ_EVTCHN] =
                 s->bufioreq_evtchn;
     }
@@ -431,7 +459,6 @@ static int hvm_ioreq_server_map_pages(struct hvm_ioreq_server *s,
 }
 
 static int hvm_ioreq_server_setup_pages(struct hvm_ioreq_server *s,
-                                        bool is_default,
                                         bool handle_bufioreq)
 {
     struct domain *d = s->domain;
@@ -439,7 +466,7 @@ static int hvm_ioreq_server_setup_pages(struct hvm_ioreq_server *s,
     unsigned long bufioreq_gfn = gfn_x(INVALID_GFN);
     int rc;
 
-    if ( is_default )
+    if ( IS_DEFAULT(s) )
     {
         /*
          * The default ioreq server must handle buffered ioreqs, for
@@ -468,8 +495,7 @@ static int hvm_ioreq_server_setup_pages(struct hvm_ioreq_server *s,
     return rc;
 }
 
-static void hvm_ioreq_server_unmap_pages(struct hvm_ioreq_server *s,
-                                         bool is_default)
+static void hvm_ioreq_server_unmap_pages(struct hvm_ioreq_server *s)
 {
     struct domain *d = s->domain;
     bool handle_bufioreq = !!s->bufioreq.va;
@@ -479,7 +505,7 @@ static void hvm_ioreq_server_unmap_pages(struct hvm_ioreq_server *s,
 
     hvm_unmap_ioreq_page(s, false);
 
-    if ( !is_default )
+    if ( !IS_DEFAULT(s) )
     {
         if ( handle_bufioreq )
             hvm_free_ioreq_gfn(d, s->bufioreq.gfn);
@@ -488,12 +514,11 @@ static void hvm_ioreq_server_unmap_pages(struct hvm_ioreq_server *s,
     }
 }
 
-static void hvm_ioreq_server_free_rangesets(struct hvm_ioreq_server *s,
-                                            bool is_default)
+static void hvm_ioreq_server_free_rangesets(struct hvm_ioreq_server *s)
 {
     unsigned int i;
 
-    if ( is_default )
+    if ( IS_DEFAULT(s) )
         return;
 
     for ( i = 0; i < NR_IO_RANGE_TYPES; i++ )
@@ -501,19 +526,21 @@ static void hvm_ioreq_server_free_rangesets(struct hvm_ioreq_server *s,
 }
 
 static int hvm_ioreq_server_alloc_rangesets(struct hvm_ioreq_server *s,
-                                            bool is_default)
+                                            ioservid_t id)
 {
     unsigned int i;
     int rc;
 
-    if ( is_default )
+    if ( id == DEFAULT_IOSERVID )
         goto done;
 
+    ASSERT(!IS_DEFAULT(s));
+
     for ( i = 0; i < NR_IO_RANGE_TYPES; i++ )
     {
         char *name;
 
-        rc = asprintf(&name, "ioreq_server %d %s", s->id,
+        rc = asprintf(&name, "ioreq_server %d %s", id,
                       (i == XEN_DMOP_IO_RANGE_PORT) ? "port" :
                       (i == XEN_DMOP_IO_RANGE_MEMORY) ? "memory" :
                       (i == XEN_DMOP_IO_RANGE_PCI) ? "pci" :
@@ -537,13 +564,12 @@ static int hvm_ioreq_server_alloc_rangesets(struct hvm_ioreq_server *s,
     return 0;
 
  fail:
-    hvm_ioreq_server_free_rangesets(s, false);
+    hvm_ioreq_server_free_rangesets(s);
 
     return rc;
 }
 
-static void hvm_ioreq_server_enable(struct hvm_ioreq_server *s,
-                                    bool is_default)
+static void hvm_ioreq_server_enable(struct hvm_ioreq_server *s)
 {
     struct domain *d = s->domain;
     struct hvm_ioreq_vcpu *sv;
@@ -554,7 +580,7 @@ static void hvm_ioreq_server_enable(struct hvm_ioreq_server *s,
     if ( s->enabled )
         goto done;
 
-    if ( !is_default )
+    if ( !IS_DEFAULT(s) )
     {
         hvm_remove_ioreq_gfn(d, &s->ioreq);
 
@@ -573,8 +599,7 @@ static void hvm_ioreq_server_enable(struct hvm_ioreq_server *s,
     spin_unlock(&s->lock);
 }
 
-static void hvm_ioreq_server_disable(struct hvm_ioreq_server *s,
-                                     bool is_default)
+static void hvm_ioreq_server_disable(struct hvm_ioreq_server *s)
 {
     struct domain *d = s->domain;
     bool handle_bufioreq = !!s->bufioreq.va;
@@ -584,7 +609,7 @@ static void hvm_ioreq_server_disable(struct hvm_ioreq_server *s,
     if ( !s->enabled )
         goto done;
 
-    if ( !is_default )
+    if ( !IS_DEFAULT(s) )
     {
         if ( handle_bufioreq )
             hvm_add_ioreq_gfn(d, &s->bufioreq);
@@ -600,13 +625,11 @@ static void hvm_ioreq_server_disable(struct hvm_ioreq_server *s,
 
 static int hvm_ioreq_server_init(struct hvm_ioreq_server *s,
                                  struct domain *d, domid_t domid,
-                                 bool is_default, int bufioreq_handling,
-                                 ioservid_t id)
+                                 int bufioreq_handling, ioservid_t id)
 {
     struct vcpu *v;
     int rc;
 
-    s->id = id;
     s->domain = d;
     s->domid = domid;
 
@@ -614,7 +637,7 @@ static int hvm_ioreq_server_init(struct hvm_ioreq_server *s,
     INIT_LIST_HEAD(&s->ioreq_vcpu_list);
     spin_lock_init(&s->bufioreq_lock);
 
-    rc = hvm_ioreq_server_alloc_rangesets(s, is_default);
+    rc = hvm_ioreq_server_alloc_rangesets(s, id);
     if ( rc )
         return rc;
 
@@ -622,13 +645,13 @@ static int hvm_ioreq_server_init(struct hvm_ioreq_server *s,
         s->bufioreq_atomic = true;
 
     rc = hvm_ioreq_server_setup_pages(
-             s, is_default, bufioreq_handling != HVM_IOREQSRV_BUFIOREQ_OFF);
+             s, bufioreq_handling != HVM_IOREQSRV_BUFIOREQ_OFF);
     if ( rc )
         goto fail_map;
 
     for_each_vcpu ( d, v )
     {
-        rc = hvm_ioreq_server_add_vcpu(s, is_default, v);
+        rc = hvm_ioreq_server_add_vcpu(s, v);
         if ( rc )
             goto fail_add;
     }
@@ -637,47 +660,20 @@ static int hvm_ioreq_server_init(struct hvm_ioreq_server *s,
 
  fail_add:
     hvm_ioreq_server_remove_all_vcpus(s);
-    hvm_ioreq_server_unmap_pages(s, is_default);
+    hvm_ioreq_server_unmap_pages(s);
 
  fail_map:
-    hvm_ioreq_server_free_rangesets(s, is_default);
+    hvm_ioreq_server_free_rangesets(s);
 
     return rc;
 }
 
-static void hvm_ioreq_server_deinit(struct hvm_ioreq_server *s,
-                                    bool is_default)
+static void hvm_ioreq_server_deinit(struct hvm_ioreq_server *s)
 {
     ASSERT(!s->enabled);
     hvm_ioreq_server_remove_all_vcpus(s);
-    hvm_ioreq_server_unmap_pages(s, is_default);
-    hvm_ioreq_server_free_rangesets(s, is_default);
-}
-
-static ioservid_t next_ioservid(struct domain *d)
-{
-    struct hvm_ioreq_server *s;
-    ioservid_t id;
-
-    ASSERT(spin_is_locked(&d->arch.hvm_domain.ioreq_server.lock));
-
-    id = d->arch.hvm_domain.ioreq_server.id;
-
- again:
-    id++;
-
-    /* Check for uniqueness */
-    list_for_each_entry ( s,
-                          &d->arch.hvm_domain.ioreq_server.list,
-                          list_entry )
-    {
-        if ( id == s->id )
-            goto again;
-    }
-
-    d->arch.hvm_domain.ioreq_server.id = id;
-
-    return id;
+    hvm_ioreq_server_unmap_pages(s);
+    hvm_ioreq_server_free_rangesets(s);
 }
 
 int hvm_create_ioreq_server(struct domain *d, domid_t domid,
@@ -685,52 +681,64 @@ int hvm_create_ioreq_server(struct domain *d, domid_t domid,
                             ioservid_t *id)
 {
     struct hvm_ioreq_server *s;
+    unsigned int i;
     int rc;
 
     if ( bufioreq_handling > HVM_IOREQSRV_BUFIOREQ_ATOMIC )
         return -EINVAL;
 
-    rc = -ENOMEM;
     s = xzalloc(struct hvm_ioreq_server);
     if ( !s )
-        goto fail1;
+        return -ENOMEM;
 
     domain_pause(d);
     spin_lock_recursive(&d->arch.hvm_domain.ioreq_server.lock);
 
-    rc = -EEXIST;
-    if ( is_default && d->arch.hvm_domain.default_ioreq_server != NULL )
-        goto fail2;
-
-    rc = hvm_ioreq_server_init(s, d, domid, is_default, bufioreq_handling,
-                               next_ioservid(d));
-    if ( rc )
-        goto fail3;
-
-    list_add(&s->list_entry,
-             &d->arch.hvm_domain.ioreq_server.list);
-
     if ( is_default )
     {
-        d->arch.hvm_domain.default_ioreq_server = s;
-        hvm_ioreq_server_enable(s, true);
+        i = DEFAULT_IOSERVID;
+
+        rc = -EEXIST;
+        if ( GET_IOREQ_SERVER(d, i) )
+            goto fail;
+    }
+    else
+    {
+        for ( i = 0; i < MAX_NR_IOREQ_SERVERS; i++ )
+        {
+            if ( i != DEFAULT_IOSERVID && !GET_IOREQ_SERVER(d, i) )
+                break;
+        }
+
+        rc = -ENOSPC;
+        if ( i >= MAX_NR_IOREQ_SERVERS )
+            goto fail;
     }
 
+    set_ioreq_server(d, i, s);
+
+    rc = hvm_ioreq_server_init(s, d, domid, bufioreq_handling, i);
+    if ( rc )
+        goto fail;
+
+    if ( i == DEFAULT_IOSERVID )
+        hvm_ioreq_server_enable(s);
+
     if ( id )
-        *id = s->id;
+        *id = i;
 
     spin_unlock_recursive(&d->arch.hvm_domain.ioreq_server.lock);
     domain_unpause(d);
 
     return 0;
 
- fail3:
- fail2:
+ fail:
+    set_ioreq_server(d, i, NULL);
+
     spin_unlock_recursive(&d->arch.hvm_domain.ioreq_server.lock);
     domain_unpause(d);
 
     xfree(s);
- fail1:
     return rc;
 }
 
@@ -739,37 +747,34 @@ int hvm_destroy_ioreq_server(struct domain *d, ioservid_t id)
     struct hvm_ioreq_server *s;
     int rc;
 
-    spin_lock_recursive(&d->arch.hvm_domain.ioreq_server.lock);
+    if ( id == DEFAULT_IOSERVID )
+        return -EPERM;
 
-    rc = -ENOENT;
-    list_for_each_entry ( s,
-                          &d->arch.hvm_domain.ioreq_server.list,
-                          list_entry )
-    {
-        if ( s == d->arch.hvm_domain.default_ioreq_server )
-            continue;
+    spin_lock_recursive(&d->arch.hvm_domain.ioreq_server.lock);
 
-        if ( s->id != id )
-            continue;
+    s = get_ioreq_server(d, id);
 
-        domain_pause(d);
+    rc = -ENOENT;
+    if ( !s )
+        goto out;
 
-        p2m_set_ioreq_server(d, 0, s);
+    ASSERT(!IS_DEFAULT(s));
 
-        hvm_ioreq_server_disable(s, false);
+    domain_pause(d);
 
-        list_del(&s->list_entry);
+    p2m_set_ioreq_server(d, 0, s);
 
-        hvm_ioreq_server_deinit(s, false);
+    hvm_ioreq_server_disable(s);
+    hvm_ioreq_server_deinit(s);
 
-        domain_unpause(d);
+    domain_unpause(d);
 
-        xfree(s);
+    set_ioreq_server(d, id, NULL);
+    xfree(s);
 
-        rc = 0;
-        break;
-    }
+    rc = 0;
 
+ out:
     spin_unlock_recursive(&d->arch.hvm_domain.ioreq_server.lock);
 
     return rc;
@@ -783,31 +788,30 @@ int hvm_get_ioreq_server_info(struct domain *d, ioservid_t id,
     struct hvm_ioreq_server *s;
     int rc;
 
+    if ( id == DEFAULT_IOSERVID )
+        return -EOPNOTSUPP;
+
     spin_lock_recursive(&d->arch.hvm_domain.ioreq_server.lock);
 
-    rc = -ENOENT;
-    list_for_each_entry ( s,
-                          &d->arch.hvm_domain.ioreq_server.list,
-                          list_entry )
-    {
-        if ( s == d->arch.hvm_domain.default_ioreq_server )
-            continue;
+    s = get_ioreq_server(d, id);
 
-        if ( s->id != id )
-            continue;
+    rc = -ENOENT;
+    if ( !s )
+        goto out;
 
-        *ioreq_gfn = s->ioreq.gfn;
+    ASSERT(!IS_DEFAULT(s));
 
-        if ( s->bufioreq.va != NULL )
-        {
-            *bufioreq_gfn = s->bufioreq.gfn;
-            *bufioreq_port = s->bufioreq_evtchn;
-        }
+    *ioreq_gfn = s->ioreq.gfn;
 
-        rc = 0;
-        break;
+    if ( s->bufioreq.va != NULL )
+    {
+        *bufioreq_gfn = s->bufioreq.gfn;
+        *bufioreq_port = s->bufioreq_evtchn;
     }
 
+    rc = 0;
+
+ out:
     spin_unlock_recursive(&d->arch.hvm_domain.ioreq_server.lock);
 
     return rc;
@@ -818,51 +822,49 @@ int hvm_map_io_range_to_ioreq_server(struct domain *d, ioservid_t id,
                                      uint64_t end)
 {
     struct hvm_ioreq_server *s;
+    struct rangeset *r;
     int rc;
 
     if ( start > end )
         return -EINVAL;
 
+    if ( id == DEFAULT_IOSERVID )
+        return -EOPNOTSUPP;
+
     spin_lock_recursive(&d->arch.hvm_domain.ioreq_server.lock);
 
+    s = get_ioreq_server(d, id);
+
     rc = -ENOENT;
-    list_for_each_entry ( s,
-                          &d->arch.hvm_domain.ioreq_server.list,
-                          list_entry )
-    {
-        if ( s == d->arch.hvm_domain.default_ioreq_server )
-            continue;
+    if ( !s )
+        goto out;
 
-        if ( s->id == id )
-        {
-            struct rangeset *r;
+    ASSERT(!IS_DEFAULT(s));
 
-            switch ( type )
-            {
-            case XEN_DMOP_IO_RANGE_PORT:
-            case XEN_DMOP_IO_RANGE_MEMORY:
-            case XEN_DMOP_IO_RANGE_PCI:
-                r = s->range[type];
-                break;
+    switch ( type )
+    {
+    case XEN_DMOP_IO_RANGE_PORT:
+    case XEN_DMOP_IO_RANGE_MEMORY:
+    case XEN_DMOP_IO_RANGE_PCI:
+        r = s->range[type];
+        break;
 
-            default:
-                r = NULL;
-                break;
-            }
+    default:
+        r = NULL;
+        break;
+    }
 
-            rc = -EINVAL;
-            if ( !r )
-                break;
+    rc = -EINVAL;
+    if ( !r )
+        goto out;
 
-            rc = -EEXIST;
-            if ( rangeset_overlaps_range(r, start, end) )
-                break;
+    rc = -EEXIST;
+    if ( rangeset_overlaps_range(r, start, end) )
+        goto out;
 
-            rc = rangeset_add_range(r, start, end);
-            break;
-        }
-    }
+    rc = rangeset_add_range(r, start, end);
 
+ out:
     spin_unlock_recursive(&d->arch.hvm_domain.ioreq_server.lock);
 
     return rc;
@@ -873,51 +875,49 @@ int hvm_unmap_io_range_from_ioreq_server(struct domain *d, ioservid_t id,
                                          uint64_t end)
 {
     struct hvm_ioreq_server *s;
+    struct rangeset *r;
     int rc;
 
     if ( start > end )
         return -EINVAL;
 
+    if ( id == DEFAULT_IOSERVID )
+        return -EOPNOTSUPP;
+
     spin_lock_recursive(&d->arch.hvm_domain.ioreq_server.lock);
 
+    s = get_ioreq_server(d, id);
+
     rc = -ENOENT;
-    list_for_each_entry ( s,
-                          &d->arch.hvm_domain.ioreq_server.list,
-                          list_entry )
-    {
-        if ( s == d->arch.hvm_domain.default_ioreq_server )
-            continue;
+    if ( !s )
+        goto out;
 
-        if ( s->id == id )
-        {
-            struct rangeset *r;
+    ASSERT(!IS_DEFAULT(s));
 
-            switch ( type )
-            {
-            case XEN_DMOP_IO_RANGE_PORT:
-            case XEN_DMOP_IO_RANGE_MEMORY:
-            case XEN_DMOP_IO_RANGE_PCI:
-                r = s->range[type];
-                break;
+    switch ( type )
+    {
+    case XEN_DMOP_IO_RANGE_PORT:
+    case XEN_DMOP_IO_RANGE_MEMORY:
+    case XEN_DMOP_IO_RANGE_PCI:
+        r = s->range[type];
+        break;
 
-            default:
-                r = NULL;
-                break;
-            }
+    default:
+        r = NULL;
+        break;
+    }
 
-            rc = -EINVAL;
-            if ( !r )
-                break;
+    rc = -EINVAL;
+    if ( !r )
+        goto out;
 
-            rc = -ENOENT;
-            if ( !rangeset_contains_range(r, start, end) )
-                break;
+    rc = -ENOENT;
+    if ( !rangeset_contains_range(r, start, end) )
+        goto out;
 
-            rc = rangeset_remove_range(r, start, end);
-            break;
-        }
-    }
+    rc = rangeset_remove_range(r, start, end);
 
+ out:
     spin_unlock_recursive(&d->arch.hvm_domain.ioreq_server.lock);
 
     return rc;
@@ -937,6 +937,9 @@ int hvm_map_mem_type_to_ioreq_server(struct domain *d, ioservid_t id,
     struct hvm_ioreq_server *s;
     int rc;
 
+    if ( id == DEFAULT_IOSERVID )
+        return -EOPNOTSUPP;
+
     if ( type != HVMMEM_ioreq_server )
         return -EINVAL;
 
@@ -945,19 +948,14 @@ int hvm_map_mem_type_to_ioreq_server(struct domain *d, ioservid_t id,
 
     spin_lock_recursive(&d->arch.hvm_domain.ioreq_server.lock);
 
-    rc = -ENOENT;
-    list_for_each_entry ( s,
-                          &d->arch.hvm_domain.ioreq_server.list,
-                          list_entry )
-    {
-        if ( s == d->arch.hvm_domain.default_ioreq_server )
-            continue;
+    s = get_ioreq_server(d, id);
 
-        if ( s->id == id )
-        {
-            rc = p2m_set_ioreq_server(d, flags, s);
-            break;
-        }
+    if ( !s )
+        rc = -ENOENT;
+    else
+    {
+        ASSERT(!IS_DEFAULT(s));
+        rc = p2m_set_ioreq_server(d, flags, s);
     }
 
     spin_unlock_recursive(&d->arch.hvm_domain.ioreq_server.lock);
@@ -976,38 +974,34 @@ int hvm_map_mem_type_to_ioreq_server(struct domain *d, ioservid_t id,
 int hvm_set_ioreq_server_state(struct domain *d, ioservid_t id,
                                bool enabled)
 {
-    struct list_head *entry;
+    struct hvm_ioreq_server *s;
     int rc;
 
+    if ( id == DEFAULT_IOSERVID )
+        return -EOPNOTSUPP;
+
     spin_lock_recursive(&d->arch.hvm_domain.ioreq_server.lock);
 
-    rc = -ENOENT;
-    list_for_each ( entry,
-                    &d->arch.hvm_domain.ioreq_server.list )
-    {
-        struct hvm_ioreq_server *s = list_entry(entry,
-                                                struct hvm_ioreq_server,
-                                                list_entry);
+    s = get_ioreq_server(d, id);
 
-        if ( s == d->arch.hvm_domain.default_ioreq_server )
-            continue;
+    rc = -ENOENT;
+    if ( !s )
+        goto out;
 
-        if ( s->id != id )
-            continue;
+    ASSERT(!IS_DEFAULT(s));
 
-        domain_pause(d);
+    domain_pause(d);
 
-        if ( enabled )
-            hvm_ioreq_server_enable(s, false);
-        else
-            hvm_ioreq_server_disable(s, false);
+    if ( enabled )
+        hvm_ioreq_server_enable(s);
+    else
+        hvm_ioreq_server_disable(s);
 
-        domain_unpause(d);
+    domain_unpause(d);
 
-        rc = 0;
-        break;
-    }
+    rc = 0;
 
+ out:
     spin_unlock_recursive(&d->arch.hvm_domain.ioreq_server.lock);
     return rc;
 }
@@ -1015,17 +1009,14 @@ int hvm_set_ioreq_server_state(struct domain *d, ioservid_t id,
 int hvm_all_ioreq_servers_add_vcpu(struct domain *d, struct vcpu *v)
 {
     struct hvm_ioreq_server *s;
+    unsigned int id;
     int rc;
 
     spin_lock_recursive(&d->arch.hvm_domain.ioreq_server.lock);
 
-    list_for_each_entry ( s,
-                          &d->arch.hvm_domain.ioreq_server.list,
-                          list_entry )
+    FOR_EACH_IOREQ_SERVER(d, id, s)
     {
-        bool is_default = (s == d->arch.hvm_domain.default_ioreq_server);
-
-        rc = hvm_ioreq_server_add_vcpu(s, is_default, v);
+        rc = hvm_ioreq_server_add_vcpu(s, v);
         if ( rc )
             goto fail;
     }
@@ -1035,10 +1026,15 @@ int hvm_all_ioreq_servers_add_vcpu(struct domain *d, struct vcpu *v)
     return 0;
 
  fail:
-    list_for_each_entry ( s,
-                          &d->arch.hvm_domain.ioreq_server.list,
-                          list_entry )
+    while ( id-- != 0 )
+    {
+        s = GET_IOREQ_SERVER(d, id);
+
+        if ( !s )
+            continue;
+
         hvm_ioreq_server_remove_vcpu(s, v);
+    }
 
     spin_unlock_recursive(&d->arch.hvm_domain.ioreq_server.lock);
 
@@ -1048,12 +1044,11 @@ int hvm_all_ioreq_servers_add_vcpu(struct domain *d, struct vcpu *v)
 void hvm_all_ioreq_servers_remove_vcpu(struct domain *d, struct vcpu *v)
 {
     struct hvm_ioreq_server *s;
+    unsigned int id;
 
     spin_lock_recursive(&d->arch.hvm_domain.ioreq_server.lock);
 
-    list_for_each_entry ( s,
-                          &d->arch.hvm_domain.ioreq_server.list,
-                          list_entry )
+    FOR_EACH_IOREQ_SERVER(d, id, s)
         hvm_ioreq_server_remove_vcpu(s, v);
 
     spin_unlock_recursive(&d->arch.hvm_domain.ioreq_server.lock);
@@ -1061,28 +1056,19 @@ void hvm_all_ioreq_servers_remove_vcpu(struct domain *d, struct vcpu *v)
 
 void hvm_destroy_all_ioreq_servers(struct domain *d)
 {
-    struct hvm_ioreq_server *s, *next;
+    struct hvm_ioreq_server *s;
+    unsigned int id;
 
     spin_lock_recursive(&d->arch.hvm_domain.ioreq_server.lock);
 
     /* No need to domain_pause() as the domain is being torn down */
 
-    list_for_each_entry_safe ( s,
-                               next,
-                               &d->arch.hvm_domain.ioreq_server.list,
-                               list_entry )
+    FOR_EACH_IOREQ_SERVER(d, id, s)
     {
-        bool is_default = (s == d->arch.hvm_domain.default_ioreq_server);
-
-        hvm_ioreq_server_disable(s, is_default);
-
-        if ( is_default )
-            d->arch.hvm_domain.default_ioreq_server = NULL;
-
-        list_del(&s->list_entry);
-
-        hvm_ioreq_server_deinit(s, is_default);
+        hvm_ioreq_server_disable(s);
+        hvm_ioreq_server_deinit(s);
 
+        set_ioreq_server(d, id, NULL);
         xfree(s);
     }
 
@@ -1117,7 +1103,7 @@ int hvm_set_dm_domain(struct domain *d, domid_t domid)
      * still be set and thus, when the server is created, it will have
      * the correct domid.
      */
-    s = d->arch.hvm_domain.default_ioreq_server;
+    s = GET_IOREQ_SERVER(d, DEFAULT_IOSERVID);
     if ( !s )
         goto done;
 
@@ -1170,12 +1156,10 @@ struct hvm_ioreq_server *hvm_select_ioreq_server(struct domain *d,
     uint32_t cf8;
     uint8_t type;
     uint64_t addr;
-
-    if ( list_empty(&d->arch.hvm_domain.ioreq_server.list) )
-        return NULL;
+    unsigned int id;
 
     if ( p->type != IOREQ_TYPE_COPY && p->type != IOREQ_TYPE_PIO )
-        return d->arch.hvm_domain.default_ioreq_server;
+        return GET_IOREQ_SERVER(d, DEFAULT_IOSERVID);
 
     cf8 = d->arch.hvm_domain.pci_cf8;
 
@@ -1215,16 +1199,11 @@ struct hvm_ioreq_server *hvm_select_ioreq_server(struct domain *d,
         addr = p->addr;
     }
 
-    list_for_each_entry ( s,
-                          &d->arch.hvm_domain.ioreq_server.list,
-                          list_entry )
+    FOR_EACH_IOREQ_SERVER(d, id, s)
     {
         struct rangeset *r;
 
-        if ( s == d->arch.hvm_domain.default_ioreq_server )
-            continue;
-
-        if ( !s->enabled )
+        if ( IS_DEFAULT(s) )
             continue;
 
         r = s->range[type];
@@ -1257,7 +1236,7 @@ struct hvm_ioreq_server *hvm_select_ioreq_server(struct domain *d,
         }
     }
 
-    return d->arch.hvm_domain.default_ioreq_server;
+    return GET_IOREQ_SERVER(d, DEFAULT_IOSERVID);
 }
 
 static int hvm_send_buffered_ioreq(struct hvm_ioreq_server *s, ioreq_t *p)
@@ -1416,13 +1395,13 @@ unsigned int hvm_broadcast_ioreq(ioreq_t *p, bool buffered)
 {
     struct domain *d = current->domain;
     struct hvm_ioreq_server *s;
-    unsigned int failed = 0;
+    unsigned int id, failed = 0;
 
-    list_for_each_entry ( s,
-                          &d->arch.hvm_domain.ioreq_server.list,
-                          list_entry )
+    FOR_EACH_IOREQ_SERVER(d, id, s)
+    {
         if ( hvm_send_ioreq(s, p, buffered) == X86EMUL_UNHANDLEABLE )
             failed++;
+    }
 
     return failed;
 }
@@ -1442,7 +1421,6 @@ static int hvm_access_cf8(
 void hvm_ioreq_init(struct domain *d)
 {
     spin_lock_init(&d->arch.hvm_domain.ioreq_server.lock);
-    INIT_LIST_HEAD(&d->arch.hvm_domain.ioreq_server.list);
 
     register_portio_handler(d, 0xcf8, 4, hvm_access_cf8);
 }
diff --git a/xen/include/asm-x86/hvm/domain.h b/xen/include/asm-x86/hvm/domain.h
index 7f128c05ff..e17bbe4004 100644
--- a/xen/include/asm-x86/hvm/domain.h
+++ b/xen/include/asm-x86/hvm/domain.h
@@ -60,7 +60,6 @@ struct hvm_ioreq_server {
 
     /* Domain id of emulating domain */
     domid_t                domid;
-    ioservid_t             id;
     struct hvm_ioreq_page  ioreq;
     struct list_head       ioreq_vcpu_list;
     struct hvm_ioreq_page  bufioreq;
@@ -100,6 +99,9 @@ struct hvm_pi_ops {
     void (*do_resume)(struct vcpu *v);
 };
 
+#define MAX_NR_IOREQ_SERVERS 8
+#define DEFAULT_IOSERVID 0
+
 struct hvm_domain {
     /* Guest page range used for non-default ioreq servers */
     struct {
@@ -109,11 +111,9 @@ struct hvm_domain {
 
     /* Lock protects all other values in the sub-struct and the default */
     struct {
-        spinlock_t       lock;
-        ioservid_t       id;
-        struct list_head list;
+        spinlock_t              lock;
+        struct hvm_ioreq_server *server[MAX_NR_IOREQ_SERVERS];
     } ioreq_server;
-    struct hvm_ioreq_server *default_ioreq_server;
 
     /* Cached CF8 for guest PCI config cycles */
     uint32_t                pci_cf8;
-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* [PATCH v14 02/11] x86/hvm/ioreq: simplify code and use consistent naming
  2017-11-28 15:08 [PATCH v14 00/11] x86: guest resource mapping Paul Durrant
  2017-11-28 15:08 ` [PATCH v14 01/11] x86/hvm/ioreq: maintain an array of ioreq servers rather than a list Paul Durrant
@ 2017-11-28 15:08 ` Paul Durrant
  2017-11-28 15:08 ` [PATCH v14 03/11] x86/hvm/ioreq: use gfn_t in struct hvm_ioreq_page Paul Durrant
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 30+ messages in thread
From: Paul Durrant @ 2017-11-28 15:08 UTC (permalink / raw)
  To: xen-devel; +Cc: Andrew Cooper, Paul Durrant

This patch re-works much of the ioreq server initialization and teardown
code:

- The hvm_map/unmap_ioreq_gfn() functions are expanded to call through
  to hvm_alloc/free_ioreq_gfn() rather than expecting them to be called
  separately by outer functions.
- Several functions now test the validity of the hvm_ioreq_page gfn value
  to determine whether they need to act. This means can be safely called
  for the bufioreq page even when it is not used.
- hvm_add/remove_ioreq_gfn() simply return in the case of the default
  IOREQ server so callers no longer need to test before calling.
- hvm_ioreq_server_setup_pages() is renamed to hvm_ioreq_server_map_pages()
  to mirror the existing hvm_ioreq_server_unmap_pages().

All of this significantly shortens the code.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
Reviewed-by: Wei Liu <wei.liu2@citrix.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
---
Cc: Andrew Cooper <andrew.cooper3@citrix.com>

v3:
 - Rebased on top of 's->is_default' to 'IS_DEFAULT(s)' changes.
 - Minor updates in response to review comments from Roger.
---
 xen/arch/x86/hvm/ioreq.c | 182 ++++++++++++++++++-----------------------------
 1 file changed, 69 insertions(+), 113 deletions(-)

diff --git a/xen/arch/x86/hvm/ioreq.c b/xen/arch/x86/hvm/ioreq.c
index da31918bb1..c21fa9f280 100644
--- a/xen/arch/x86/hvm/ioreq.c
+++ b/xen/arch/x86/hvm/ioreq.c
@@ -210,63 +210,75 @@ bool handle_hvm_io_completion(struct vcpu *v)
     return true;
 }
 
-static int hvm_alloc_ioreq_gfn(struct domain *d, unsigned long *gfn)
+static unsigned long hvm_alloc_ioreq_gfn(struct hvm_ioreq_server *s)
 {
+    struct domain *d = s->domain;
     unsigned int i;
-    int rc;
 
-    rc = -ENOMEM;
+    ASSERT(!IS_DEFAULT(s));
+
     for ( i = 0; i < sizeof(d->arch.hvm_domain.ioreq_gfn.mask) * 8; i++ )
     {
         if ( test_and_clear_bit(i, &d->arch.hvm_domain.ioreq_gfn.mask) )
-        {
-            *gfn = d->arch.hvm_domain.ioreq_gfn.base + i;
-            rc = 0;
-            break;
-        }
+            return d->arch.hvm_domain.ioreq_gfn.base + i;
     }
 
-    return rc;
+    return gfn_x(INVALID_GFN);
 }
 
-static void hvm_free_ioreq_gfn(struct domain *d, unsigned long gfn)
+static void hvm_free_ioreq_gfn(struct hvm_ioreq_server *s,
+                               unsigned long gfn)
 {
+    struct domain *d = s->domain;
     unsigned int i = gfn - d->arch.hvm_domain.ioreq_gfn.base;
 
-    if ( gfn != gfn_x(INVALID_GFN) )
-        set_bit(i, &d->arch.hvm_domain.ioreq_gfn.mask);
+    ASSERT(!IS_DEFAULT(s));
+    ASSERT(gfn != gfn_x(INVALID_GFN));
+
+    set_bit(i, &d->arch.hvm_domain.ioreq_gfn.mask);
 }
 
-static void hvm_unmap_ioreq_page(struct hvm_ioreq_server *s, bool buf)
+static void hvm_unmap_ioreq_gfn(struct hvm_ioreq_server *s, bool buf)
 {
     struct hvm_ioreq_page *iorp = buf ? &s->bufioreq : &s->ioreq;
 
+    if ( iorp->gfn == gfn_x(INVALID_GFN) )
+        return;
+
     destroy_ring_for_helper(&iorp->va, iorp->page);
+    iorp->page = NULL;
+
+    if ( !IS_DEFAULT(s) )
+        hvm_free_ioreq_gfn(s, iorp->gfn);
+
+    iorp->gfn = gfn_x(INVALID_GFN);
 }
 
-static int hvm_map_ioreq_page(
-    struct hvm_ioreq_server *s, bool buf, unsigned long gfn)
+static int hvm_map_ioreq_gfn(struct hvm_ioreq_server *s, bool buf)
 {
     struct domain *d = s->domain;
     struct hvm_ioreq_page *iorp = buf ? &s->bufioreq : &s->ioreq;
-    struct page_info *page;
-    void *va;
     int rc;
 
-    if ( (rc = prepare_ring_for_helper(d, gfn, &page, &va)) )
-        return rc;
-
-    if ( (iorp->va != NULL) || d->is_dying )
-    {
-        destroy_ring_for_helper(&va, page);
+    if ( d->is_dying )
         return -EINVAL;
-    }
 
-    iorp->va = va;
-    iorp->page = page;
-    iorp->gfn = gfn;
+    if ( IS_DEFAULT(s) )
+        iorp->gfn = buf ?
+                    d->arch.hvm_domain.params[HVM_PARAM_BUFIOREQ_PFN] :
+                    d->arch.hvm_domain.params[HVM_PARAM_IOREQ_PFN];
+    else
+        iorp->gfn = hvm_alloc_ioreq_gfn(s);
 
-    return 0;
+    if ( iorp->gfn == gfn_x(INVALID_GFN) )
+        return -ENOMEM;
+
+    rc = prepare_ring_for_helper(d, iorp->gfn, &iorp->page, &iorp->va);
+
+    if ( rc )
+        hvm_unmap_ioreq_gfn(s, buf);
+
+    return rc;
 }
 
 bool is_ioreq_server_page(struct domain *d, const struct page_info *page)
@@ -279,8 +291,7 @@ bool is_ioreq_server_page(struct domain *d, const struct page_info *page)
 
     FOR_EACH_IOREQ_SERVER(d, id, s)
     {
-        if ( (s->ioreq.va && s->ioreq.page == page) ||
-             (s->bufioreq.va && s->bufioreq.page == page) )
+        if ( (s->ioreq.page == page) || (s->bufioreq.page == page) )
         {
             found = true;
             break;
@@ -292,20 +303,30 @@ bool is_ioreq_server_page(struct domain *d, const struct page_info *page)
     return found;
 }
 
-static void hvm_remove_ioreq_gfn(
-    struct domain *d, struct hvm_ioreq_page *iorp)
+static void hvm_remove_ioreq_gfn(struct hvm_ioreq_server *s, bool buf)
+
 {
+    struct domain *d = s->domain;
+    struct hvm_ioreq_page *iorp = buf ? &s->bufioreq : &s->ioreq;
+
+    if ( IS_DEFAULT(s) || iorp->gfn == gfn_x(INVALID_GFN) )
+        return;
+
     if ( guest_physmap_remove_page(d, _gfn(iorp->gfn),
                                    _mfn(page_to_mfn(iorp->page)), 0) )
         domain_crash(d);
     clear_page(iorp->va);
 }
 
-static int hvm_add_ioreq_gfn(
-    struct domain *d, struct hvm_ioreq_page *iorp)
+static int hvm_add_ioreq_gfn(struct hvm_ioreq_server *s, bool buf)
 {
+    struct domain *d = s->domain;
+    struct hvm_ioreq_page *iorp = buf ? &s->bufioreq : &s->ioreq;
     int rc;
 
+    if ( IS_DEFAULT(s) || iorp->gfn == gfn_x(INVALID_GFN) )
+        return 0;
+
     clear_page(iorp->va);
 
     rc = guest_physmap_add_page(d, _gfn(iorp->gfn),
@@ -440,78 +461,25 @@ static void hvm_ioreq_server_remove_all_vcpus(struct hvm_ioreq_server *s)
 }
 
 static int hvm_ioreq_server_map_pages(struct hvm_ioreq_server *s,
-                                      unsigned long ioreq_gfn,
-                                      unsigned long bufioreq_gfn)
+                                      bool handle_bufioreq)
 {
     int rc;
 
-    rc = hvm_map_ioreq_page(s, false, ioreq_gfn);
-    if ( rc )
-        return rc;
-
-    if ( bufioreq_gfn != gfn_x(INVALID_GFN) )
-        rc = hvm_map_ioreq_page(s, true, bufioreq_gfn);
-
-    if ( rc )
-        hvm_unmap_ioreq_page(s, false);
-
-    return rc;
-}
-
-static int hvm_ioreq_server_setup_pages(struct hvm_ioreq_server *s,
-                                        bool handle_bufioreq)
-{
-    struct domain *d = s->domain;
-    unsigned long ioreq_gfn = gfn_x(INVALID_GFN);
-    unsigned long bufioreq_gfn = gfn_x(INVALID_GFN);
-    int rc;
-
-    if ( IS_DEFAULT(s) )
-    {
-        /*
-         * The default ioreq server must handle buffered ioreqs, for
-         * backwards compatibility.
-         */
-        ASSERT(handle_bufioreq);
-        return hvm_ioreq_server_map_pages(s,
-                   d->arch.hvm_domain.params[HVM_PARAM_IOREQ_PFN],
-                   d->arch.hvm_domain.params[HVM_PARAM_BUFIOREQ_PFN]);
-    }
-
-    rc = hvm_alloc_ioreq_gfn(d, &ioreq_gfn);
+    rc = hvm_map_ioreq_gfn(s, false);
 
     if ( !rc && handle_bufioreq )
-        rc = hvm_alloc_ioreq_gfn(d, &bufioreq_gfn);
-
-    if ( !rc )
-        rc = hvm_ioreq_server_map_pages(s, ioreq_gfn, bufioreq_gfn);
+        rc = hvm_map_ioreq_gfn(s, true);
 
     if ( rc )
-    {
-        hvm_free_ioreq_gfn(d, ioreq_gfn);
-        hvm_free_ioreq_gfn(d, bufioreq_gfn);
-    }
+        hvm_unmap_ioreq_gfn(s, false);
 
     return rc;
 }
 
 static void hvm_ioreq_server_unmap_pages(struct hvm_ioreq_server *s)
 {
-    struct domain *d = s->domain;
-    bool handle_bufioreq = !!s->bufioreq.va;
-
-    if ( handle_bufioreq )
-        hvm_unmap_ioreq_page(s, true);
-
-    hvm_unmap_ioreq_page(s, false);
-
-    if ( !IS_DEFAULT(s) )
-    {
-        if ( handle_bufioreq )
-            hvm_free_ioreq_gfn(d, s->bufioreq.gfn);
-
-        hvm_free_ioreq_gfn(d, s->ioreq.gfn);
-    }
+    hvm_unmap_ioreq_gfn(s, true);
+    hvm_unmap_ioreq_gfn(s, false);
 }
 
 static void hvm_ioreq_server_free_rangesets(struct hvm_ioreq_server *s)
@@ -571,22 +539,15 @@ static int hvm_ioreq_server_alloc_rangesets(struct hvm_ioreq_server *s,
 
 static void hvm_ioreq_server_enable(struct hvm_ioreq_server *s)
 {
-    struct domain *d = s->domain;
     struct hvm_ioreq_vcpu *sv;
-    bool handle_bufioreq = !!s->bufioreq.va;
 
     spin_lock(&s->lock);
 
     if ( s->enabled )
         goto done;
 
-    if ( !IS_DEFAULT(s) )
-    {
-        hvm_remove_ioreq_gfn(d, &s->ioreq);
-
-        if ( handle_bufioreq )
-            hvm_remove_ioreq_gfn(d, &s->bufioreq);
-    }
+    hvm_remove_ioreq_gfn(s, false);
+    hvm_remove_ioreq_gfn(s, true);
 
     s->enabled = true;
 
@@ -601,21 +562,13 @@ static void hvm_ioreq_server_enable(struct hvm_ioreq_server *s)
 
 static void hvm_ioreq_server_disable(struct hvm_ioreq_server *s)
 {
-    struct domain *d = s->domain;
-    bool handle_bufioreq = !!s->bufioreq.va;
-
     spin_lock(&s->lock);
 
     if ( !s->enabled )
         goto done;
 
-    if ( !IS_DEFAULT(s) )
-    {
-        if ( handle_bufioreq )
-            hvm_add_ioreq_gfn(d, &s->bufioreq);
-
-        hvm_add_ioreq_gfn(d, &s->ioreq);
-    }
+    hvm_add_ioreq_gfn(s, true);
+    hvm_add_ioreq_gfn(s, false);
 
     s->enabled = false;
 
@@ -637,6 +590,9 @@ static int hvm_ioreq_server_init(struct hvm_ioreq_server *s,
     INIT_LIST_HEAD(&s->ioreq_vcpu_list);
     spin_lock_init(&s->bufioreq_lock);
 
+    s->ioreq.gfn = gfn_x(INVALID_GFN);
+    s->bufioreq.gfn = gfn_x(INVALID_GFN);
+
     rc = hvm_ioreq_server_alloc_rangesets(s, id);
     if ( rc )
         return rc;
@@ -644,7 +600,7 @@ static int hvm_ioreq_server_init(struct hvm_ioreq_server *s,
     if ( bufioreq_handling == HVM_IOREQSRV_BUFIOREQ_ATOMIC )
         s->bufioreq_atomic = true;
 
-    rc = hvm_ioreq_server_setup_pages(
+    rc = hvm_ioreq_server_map_pages(
              s, bufioreq_handling != HVM_IOREQSRV_BUFIOREQ_OFF);
     if ( rc )
         goto fail_map;
-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* [PATCH v14 03/11] x86/hvm/ioreq: use gfn_t in struct hvm_ioreq_page
  2017-11-28 15:08 [PATCH v14 00/11] x86: guest resource mapping Paul Durrant
  2017-11-28 15:08 ` [PATCH v14 01/11] x86/hvm/ioreq: maintain an array of ioreq servers rather than a list Paul Durrant
  2017-11-28 15:08 ` [PATCH v14 02/11] x86/hvm/ioreq: simplify code and use consistent naming Paul Durrant
@ 2017-11-28 15:08 ` Paul Durrant
  2017-11-28 15:08 ` [PATCH v14 04/11] x86/hvm/ioreq: defer mapping gfns until they are actually requsted Paul Durrant
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 30+ messages in thread
From: Paul Durrant @ 2017-11-28 15:08 UTC (permalink / raw)
  To: xen-devel; +Cc: Andrew Cooper, Paul Durrant

This patch adjusts the ioreq server code to use type-safe gfn_t values
where possible. No functional change.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
Reviewed-by: Wei Liu <wei.liu2@citrix.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
---
Cc: Andrew Cooper <andrew.cooper3@citrix.com>
---
 xen/arch/x86/hvm/ioreq.c         | 44 ++++++++++++++++++++--------------------
 xen/include/asm-x86/hvm/domain.h |  2 +-
 2 files changed, 23 insertions(+), 23 deletions(-)

diff --git a/xen/arch/x86/hvm/ioreq.c b/xen/arch/x86/hvm/ioreq.c
index c21fa9f280..eec4e4771e 100644
--- a/xen/arch/x86/hvm/ioreq.c
+++ b/xen/arch/x86/hvm/ioreq.c
@@ -210,7 +210,7 @@ bool handle_hvm_io_completion(struct vcpu *v)
     return true;
 }
 
-static unsigned long hvm_alloc_ioreq_gfn(struct hvm_ioreq_server *s)
+static gfn_t hvm_alloc_ioreq_gfn(struct hvm_ioreq_server *s)
 {
     struct domain *d = s->domain;
     unsigned int i;
@@ -220,20 +220,19 @@ static unsigned long hvm_alloc_ioreq_gfn(struct hvm_ioreq_server *s)
     for ( i = 0; i < sizeof(d->arch.hvm_domain.ioreq_gfn.mask) * 8; i++ )
     {
         if ( test_and_clear_bit(i, &d->arch.hvm_domain.ioreq_gfn.mask) )
-            return d->arch.hvm_domain.ioreq_gfn.base + i;
+            return _gfn(d->arch.hvm_domain.ioreq_gfn.base + i);
     }
 
-    return gfn_x(INVALID_GFN);
+    return INVALID_GFN;
 }
 
-static void hvm_free_ioreq_gfn(struct hvm_ioreq_server *s,
-                               unsigned long gfn)
+static void hvm_free_ioreq_gfn(struct hvm_ioreq_server *s, gfn_t gfn)
 {
     struct domain *d = s->domain;
-    unsigned int i = gfn - d->arch.hvm_domain.ioreq_gfn.base;
+    unsigned int i = gfn_x(gfn) - d->arch.hvm_domain.ioreq_gfn.base;
 
     ASSERT(!IS_DEFAULT(s));
-    ASSERT(gfn != gfn_x(INVALID_GFN));
+    ASSERT(!gfn_eq(gfn, INVALID_GFN));
 
     set_bit(i, &d->arch.hvm_domain.ioreq_gfn.mask);
 }
@@ -242,7 +241,7 @@ static void hvm_unmap_ioreq_gfn(struct hvm_ioreq_server *s, bool buf)
 {
     struct hvm_ioreq_page *iorp = buf ? &s->bufioreq : &s->ioreq;
 
-    if ( iorp->gfn == gfn_x(INVALID_GFN) )
+    if ( gfn_eq(iorp->gfn, INVALID_GFN) )
         return;
 
     destroy_ring_for_helper(&iorp->va, iorp->page);
@@ -251,7 +250,7 @@ static void hvm_unmap_ioreq_gfn(struct hvm_ioreq_server *s, bool buf)
     if ( !IS_DEFAULT(s) )
         hvm_free_ioreq_gfn(s, iorp->gfn);
 
-    iorp->gfn = gfn_x(INVALID_GFN);
+    iorp->gfn = INVALID_GFN;
 }
 
 static int hvm_map_ioreq_gfn(struct hvm_ioreq_server *s, bool buf)
@@ -264,16 +263,17 @@ static int hvm_map_ioreq_gfn(struct hvm_ioreq_server *s, bool buf)
         return -EINVAL;
 
     if ( IS_DEFAULT(s) )
-        iorp->gfn = buf ?
-                    d->arch.hvm_domain.params[HVM_PARAM_BUFIOREQ_PFN] :
-                    d->arch.hvm_domain.params[HVM_PARAM_IOREQ_PFN];
+        iorp->gfn = _gfn(buf ?
+                         d->arch.hvm_domain.params[HVM_PARAM_BUFIOREQ_PFN] :
+                         d->arch.hvm_domain.params[HVM_PARAM_IOREQ_PFN]);
     else
         iorp->gfn = hvm_alloc_ioreq_gfn(s);
 
-    if ( iorp->gfn == gfn_x(INVALID_GFN) )
+    if ( gfn_eq(iorp->gfn, INVALID_GFN) )
         return -ENOMEM;
 
-    rc = prepare_ring_for_helper(d, iorp->gfn, &iorp->page, &iorp->va);
+    rc = prepare_ring_for_helper(d, gfn_x(iorp->gfn), &iorp->page,
+                                 &iorp->va);
 
     if ( rc )
         hvm_unmap_ioreq_gfn(s, buf);
@@ -309,10 +309,10 @@ static void hvm_remove_ioreq_gfn(struct hvm_ioreq_server *s, bool buf)
     struct domain *d = s->domain;
     struct hvm_ioreq_page *iorp = buf ? &s->bufioreq : &s->ioreq;
 
-    if ( IS_DEFAULT(s) || iorp->gfn == gfn_x(INVALID_GFN) )
+    if ( IS_DEFAULT(s) || gfn_eq(iorp->gfn, INVALID_GFN) )
         return;
 
-    if ( guest_physmap_remove_page(d, _gfn(iorp->gfn),
+    if ( guest_physmap_remove_page(d, iorp->gfn,
                                    _mfn(page_to_mfn(iorp->page)), 0) )
         domain_crash(d);
     clear_page(iorp->va);
@@ -324,12 +324,12 @@ static int hvm_add_ioreq_gfn(struct hvm_ioreq_server *s, bool buf)
     struct hvm_ioreq_page *iorp = buf ? &s->bufioreq : &s->ioreq;
     int rc;
 
-    if ( IS_DEFAULT(s) || iorp->gfn == gfn_x(INVALID_GFN) )
+    if ( IS_DEFAULT(s) || gfn_eq(iorp->gfn, INVALID_GFN) )
         return 0;
 
     clear_page(iorp->va);
 
-    rc = guest_physmap_add_page(d, _gfn(iorp->gfn),
+    rc = guest_physmap_add_page(d, iorp->gfn,
                                 _mfn(page_to_mfn(iorp->page)), 0);
     if ( rc == 0 )
         paging_mark_dirty(d, _mfn(page_to_mfn(iorp->page)));
@@ -590,8 +590,8 @@ static int hvm_ioreq_server_init(struct hvm_ioreq_server *s,
     INIT_LIST_HEAD(&s->ioreq_vcpu_list);
     spin_lock_init(&s->bufioreq_lock);
 
-    s->ioreq.gfn = gfn_x(INVALID_GFN);
-    s->bufioreq.gfn = gfn_x(INVALID_GFN);
+    s->ioreq.gfn = INVALID_GFN;
+    s->bufioreq.gfn = INVALID_GFN;
 
     rc = hvm_ioreq_server_alloc_rangesets(s, id);
     if ( rc )
@@ -757,11 +757,11 @@ int hvm_get_ioreq_server_info(struct domain *d, ioservid_t id,
 
     ASSERT(!IS_DEFAULT(s));
 
-    *ioreq_gfn = s->ioreq.gfn;
+    *ioreq_gfn = gfn_x(s->ioreq.gfn);
 
     if ( s->bufioreq.va != NULL )
     {
-        *bufioreq_gfn = s->bufioreq.gfn;
+        *bufioreq_gfn = gfn_x(s->bufioreq.gfn);
         *bufioreq_port = s->bufioreq_evtchn;
     }
 
diff --git a/xen/include/asm-x86/hvm/domain.h b/xen/include/asm-x86/hvm/domain.h
index e17bbe4004..3bd9c5d7c0 100644
--- a/xen/include/asm-x86/hvm/domain.h
+++ b/xen/include/asm-x86/hvm/domain.h
@@ -36,7 +36,7 @@
 #include <public/hvm/dm_op.h>
 
 struct hvm_ioreq_page {
-    unsigned long gfn;
+    gfn_t gfn;
     struct page_info *page;
     void *va;
 };
-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* [PATCH v14 04/11] x86/hvm/ioreq: defer mapping gfns until they are actually requsted
  2017-11-28 15:08 [PATCH v14 00/11] x86: guest resource mapping Paul Durrant
                   ` (2 preceding siblings ...)
  2017-11-28 15:08 ` [PATCH v14 03/11] x86/hvm/ioreq: use gfn_t in struct hvm_ioreq_page Paul Durrant
@ 2017-11-28 15:08 ` Paul Durrant
  2017-12-06 21:49   ` Chao Gao
  2017-11-28 15:08 ` [PATCH v14 05/11] x86/mm: add HYPERVISOR_memory_op to acquire guest resources Paul Durrant
                   ` (6 subsequent siblings)
  10 siblings, 1 reply; 30+ messages in thread
From: Paul Durrant @ 2017-11-28 15:08 UTC (permalink / raw)
  To: xen-devel
  Cc: Stefano Stabellini, George Dunlap, Andrew Cooper, Ian Jackson,
	Tim Deegan, Paul Durrant

A subsequent patch will introduce a new scheme to allow an emulator to
map ioreq server pages directly from Xen rather than the guest P2M.

This patch lays the groundwork for that change by deferring mapping of
gfns until their values are requested by an emulator. To that end, the
pad field of the xen_dm_op_get_ioreq_server_info structure is re-purposed
to a flags field and new flag, XEN_DMOP_no_gfns, defined which modifies the
behaviour of XEN_DMOP_get_ioreq_server_info to allow the caller to avoid
requesting the gfn values.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
Acked-by: Wei Liu <wei.liu2@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
---
Cc: Ian Jackson <ian.jackson@eu.citrix.com>
Cc: Andrew Cooper <andrew.cooper3@citrix.com>
Cc: George Dunlap <George.Dunlap@eu.citrix.com>
Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Tim Deegan <tim@xen.org>

v8:
 - For safety make all of the pointers passed to
   hvm_get_ioreq_server_info() optional.
 - Shrink bufioreq_handling down to a uint8_t.

v3:
 - Updated in response to review comments from Wei and Roger.
 - Added a HANDLE_BUFIOREQ macro to make the code neater.
 - This patch no longer introduces a security vulnerability since there
   is now an explicit limit on the number of ioreq servers that may be
   created for any one domain.
---
 tools/libs/devicemodel/core.c                   |  8 +++++
 tools/libs/devicemodel/include/xendevicemodel.h |  6 ++--
 xen/arch/x86/hvm/dm.c                           |  9 +++--
 xen/arch/x86/hvm/ioreq.c                        | 47 ++++++++++++++-----------
 xen/include/asm-x86/hvm/domain.h                |  2 +-
 xen/include/public/hvm/dm_op.h                  | 32 ++++++++++-------
 6 files changed, 63 insertions(+), 41 deletions(-)

diff --git a/tools/libs/devicemodel/core.c b/tools/libs/devicemodel/core.c
index b66d4f9294..e684e657b6 100644
--- a/tools/libs/devicemodel/core.c
+++ b/tools/libs/devicemodel/core.c
@@ -204,6 +204,14 @@ int xendevicemodel_get_ioreq_server_info(
 
     data->id = id;
 
+    /*
+     * If the caller is not requesting gfn values then instruct the
+     * hypercall not to retrieve them as this may cause them to be
+     * mapped.
+     */
+    if (!ioreq_gfn && !bufioreq_gfn)
+        data->flags |= XEN_DMOP_no_gfns;
+
     rc = xendevicemodel_op(dmod, domid, 1, &op, sizeof(op));
     if (rc)
         return rc;
diff --git a/tools/libs/devicemodel/include/xendevicemodel.h b/tools/libs/devicemodel/include/xendevicemodel.h
index dda0bc7695..fffee3a4a0 100644
--- a/tools/libs/devicemodel/include/xendevicemodel.h
+++ b/tools/libs/devicemodel/include/xendevicemodel.h
@@ -61,11 +61,11 @@ int xendevicemodel_create_ioreq_server(
  * @parm domid the domain id to be serviced
  * @parm id the IOREQ Server id.
  * @parm ioreq_gfn pointer to a xen_pfn_t to receive the synchronous ioreq
- *                  gfn
+ *                  gfn. (May be NULL if not required)
  * @parm bufioreq_gfn pointer to a xen_pfn_t to receive the buffered ioreq
- *                    gfn
+ *                    gfn. (May be NULL if not required)
  * @parm bufioreq_port pointer to a evtchn_port_t to receive the buffered
- *                     ioreq event channel
+ *                     ioreq event channel. (May be NULL if not required)
  * @return 0 on success, -1 on failure.
  */
 int xendevicemodel_get_ioreq_server_info(
diff --git a/xen/arch/x86/hvm/dm.c b/xen/arch/x86/hvm/dm.c
index a787f43737..3c617bd754 100644
--- a/xen/arch/x86/hvm/dm.c
+++ b/xen/arch/x86/hvm/dm.c
@@ -416,16 +416,19 @@ static int dm_op(const struct dmop_args *op_args)
     {
         struct xen_dm_op_get_ioreq_server_info *data =
             &op.u.get_ioreq_server_info;
+        const uint16_t valid_flags = XEN_DMOP_no_gfns;
 
         const_op = false;
 
         rc = -EINVAL;
-        if ( data->pad )
+        if ( data->flags & ~valid_flags )
             break;
 
         rc = hvm_get_ioreq_server_info(d, data->id,
-                                       &data->ioreq_gfn,
-                                       &data->bufioreq_gfn,
+                                       (data->flags & XEN_DMOP_no_gfns) ?
+                                       NULL : &data->ioreq_gfn,
+                                       (data->flags & XEN_DMOP_no_gfns) ?
+                                       NULL : &data->bufioreq_gfn,
                                        &data->bufioreq_port);
         break;
     }
diff --git a/xen/arch/x86/hvm/ioreq.c b/xen/arch/x86/hvm/ioreq.c
index eec4e4771e..39de659ddf 100644
--- a/xen/arch/x86/hvm/ioreq.c
+++ b/xen/arch/x86/hvm/ioreq.c
@@ -350,6 +350,9 @@ static void hvm_update_ioreq_evtchn(struct hvm_ioreq_server *s,
     }
 }
 
+#define HANDLE_BUFIOREQ(s) \
+    ((s)->bufioreq_handling != HVM_IOREQSRV_BUFIOREQ_OFF)
+
 static int hvm_ioreq_server_add_vcpu(struct hvm_ioreq_server *s,
                                      struct vcpu *v)
 {
@@ -371,7 +374,7 @@ static int hvm_ioreq_server_add_vcpu(struct hvm_ioreq_server *s,
 
     sv->ioreq_evtchn = rc;
 
-    if ( v->vcpu_id == 0 && s->bufioreq.va != NULL )
+    if ( v->vcpu_id == 0 && HANDLE_BUFIOREQ(s) )
     {
         struct domain *d = s->domain;
 
@@ -422,7 +425,7 @@ static void hvm_ioreq_server_remove_vcpu(struct hvm_ioreq_server *s,
 
         list_del(&sv->list_entry);
 
-        if ( v->vcpu_id == 0 && s->bufioreq.va != NULL )
+        if ( v->vcpu_id == 0 && HANDLE_BUFIOREQ(s) )
             free_xen_event_channel(v->domain, s->bufioreq_evtchn);
 
         free_xen_event_channel(v->domain, sv->ioreq_evtchn);
@@ -449,7 +452,7 @@ static void hvm_ioreq_server_remove_all_vcpus(struct hvm_ioreq_server *s)
 
         list_del(&sv->list_entry);
 
-        if ( v->vcpu_id == 0 && s->bufioreq.va != NULL )
+        if ( v->vcpu_id == 0 && HANDLE_BUFIOREQ(s) )
             free_xen_event_channel(v->domain, s->bufioreq_evtchn);
 
         free_xen_event_channel(v->domain, sv->ioreq_evtchn);
@@ -460,14 +463,13 @@ static void hvm_ioreq_server_remove_all_vcpus(struct hvm_ioreq_server *s)
     spin_unlock(&s->lock);
 }
 
-static int hvm_ioreq_server_map_pages(struct hvm_ioreq_server *s,
-                                      bool handle_bufioreq)
+static int hvm_ioreq_server_map_pages(struct hvm_ioreq_server *s)
 {
     int rc;
 
     rc = hvm_map_ioreq_gfn(s, false);
 
-    if ( !rc && handle_bufioreq )
+    if ( !rc && HANDLE_BUFIOREQ(s) )
         rc = hvm_map_ioreq_gfn(s, true);
 
     if ( rc )
@@ -597,13 +599,7 @@ static int hvm_ioreq_server_init(struct hvm_ioreq_server *s,
     if ( rc )
         return rc;
 
-    if ( bufioreq_handling == HVM_IOREQSRV_BUFIOREQ_ATOMIC )
-        s->bufioreq_atomic = true;
-
-    rc = hvm_ioreq_server_map_pages(
-             s, bufioreq_handling != HVM_IOREQSRV_BUFIOREQ_OFF);
-    if ( rc )
-        goto fail_map;
+    s->bufioreq_handling = bufioreq_handling;
 
     for_each_vcpu ( d, v )
     {
@@ -618,9 +614,6 @@ static int hvm_ioreq_server_init(struct hvm_ioreq_server *s,
     hvm_ioreq_server_remove_all_vcpus(s);
     hvm_ioreq_server_unmap_pages(s);
 
- fail_map:
-    hvm_ioreq_server_free_rangesets(s);
-
     return rc;
 }
 
@@ -757,12 +750,23 @@ int hvm_get_ioreq_server_info(struct domain *d, ioservid_t id,
 
     ASSERT(!IS_DEFAULT(s));
 
-    *ioreq_gfn = gfn_x(s->ioreq.gfn);
+    if ( ioreq_gfn || bufioreq_gfn )
+    {
+        rc = hvm_ioreq_server_map_pages(s);
+        if ( rc )
+            goto out;
+    }
 
-    if ( s->bufioreq.va != NULL )
+    if ( ioreq_gfn )
+        *ioreq_gfn = gfn_x(s->ioreq.gfn);
+
+    if ( HANDLE_BUFIOREQ(s) )
     {
-        *bufioreq_gfn = gfn_x(s->bufioreq.gfn);
-        *bufioreq_port = s->bufioreq_evtchn;
+        if ( bufioreq_gfn )
+            *bufioreq_gfn = gfn_x(s->bufioreq.gfn);
+
+        if ( bufioreq_port )
+            *bufioreq_port = s->bufioreq_evtchn;
     }
 
     rc = 0;
@@ -1270,7 +1274,8 @@ static int hvm_send_buffered_ioreq(struct hvm_ioreq_server *s, ioreq_t *p)
     pg->ptrs.write_pointer += qw ? 2 : 1;
 
     /* Canonicalize read/write pointers to prevent their overflow. */
-    while ( s->bufioreq_atomic && qw++ < IOREQ_BUFFER_SLOT_NUM &&
+    while ( (s->bufioreq_handling == HVM_IOREQSRV_BUFIOREQ_ATOMIC) &&
+            qw++ < IOREQ_BUFFER_SLOT_NUM &&
             pg->ptrs.read_pointer >= IOREQ_BUFFER_SLOT_NUM )
     {
         union bufioreq_pointers old = pg->ptrs, new;
diff --git a/xen/include/asm-x86/hvm/domain.h b/xen/include/asm-x86/hvm/domain.h
index 3bd9c5d7c0..8b798ee4e9 100644
--- a/xen/include/asm-x86/hvm/domain.h
+++ b/xen/include/asm-x86/hvm/domain.h
@@ -69,7 +69,7 @@ struct hvm_ioreq_server {
     evtchn_port_t          bufioreq_evtchn;
     struct rangeset        *range[NR_IO_RANGE_TYPES];
     bool                   enabled;
-    bool                   bufioreq_atomic;
+    uint8_t                bufioreq_handling;
 };
 
 /*
diff --git a/xen/include/public/hvm/dm_op.h b/xen/include/public/hvm/dm_op.h
index e17308575a..13b3737c2f 100644
--- a/xen/include/public/hvm/dm_op.h
+++ b/xen/include/public/hvm/dm_op.h
@@ -79,28 +79,34 @@ struct xen_dm_op_create_ioreq_server {
  * XEN_DMOP_get_ioreq_server_info: Get all the information necessary to
  *                                 access IOREQ Server <id>.
  *
- * The emulator needs to map the synchronous ioreq structures and buffered
- * ioreq ring (if it exists) that Xen uses to request emulation. These are
- * hosted in the target domain's gmfns <ioreq_gfn> and <bufioreq_gfn>
- * respectively. In addition, if the IOREQ Server is handling buffered
- * emulation requests, the emulator needs to bind to event channel
- * <bufioreq_port> to listen for them. (The event channels used for
- * synchronous emulation requests are specified in the per-CPU ioreq
- * structures in <ioreq_gfn>).
- * If the IOREQ Server is not handling buffered emulation requests then the
- * values handed back in <bufioreq_gfn> and <bufioreq_port> will both be 0.
+ * If the IOREQ Server is handling buffered emulation requests, the
+ * emulator needs to bind to event channel <bufioreq_port> to listen for
+ * them. (The event channels used for synchronous emulation requests are
+ * specified in the per-CPU ioreq structures).
+ * In addition, if the XENMEM_acquire_resource memory op cannot be used,
+ * the emulator will need to map the synchronous ioreq structures and
+ * buffered ioreq ring (if it exists) from guest memory. If <flags> does
+ * not contain XEN_DMOP_no_gfns then these pages will be made available and
+ * the frame numbers passed back in gfns <ioreq_gfn> and <bufioreq_gfn>
+ * respectively. (If the IOREQ Server is not handling buffered emulation
+ * only <ioreq_gfn> will be valid).
  */
 #define XEN_DMOP_get_ioreq_server_info 2
 
 struct xen_dm_op_get_ioreq_server_info {
     /* IN - server id */
     ioservid_t id;
-    uint16_t pad;
+    /* IN - flags */
+    uint16_t flags;
+
+#define _XEN_DMOP_no_gfns 0
+#define XEN_DMOP_no_gfns (1u << _XEN_DMOP_no_gfns)
+
     /* OUT - buffered ioreq port */
     evtchn_port_t bufioreq_port;
-    /* OUT - sync ioreq gfn */
+    /* OUT - sync ioreq gfn (see block comment above) */
     uint64_aligned_t ioreq_gfn;
-    /* OUT - buffered ioreq gfn */
+    /* OUT - buffered ioreq gfn (see block comment above)*/
     uint64_aligned_t bufioreq_gfn;
 };
 
-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* [PATCH v14 05/11] x86/mm: add HYPERVISOR_memory_op to acquire guest resources
  2017-11-28 15:08 [PATCH v14 00/11] x86: guest resource mapping Paul Durrant
                   ` (3 preceding siblings ...)
  2017-11-28 15:08 ` [PATCH v14 04/11] x86/hvm/ioreq: defer mapping gfns until they are actually requsted Paul Durrant
@ 2017-11-28 15:08 ` Paul Durrant
  2017-11-28 18:50   ` Daniel De Graaf
  2017-11-28 15:08 ` [PATCH v14 06/11] x86/hvm/ioreq: add a new mappable resource type Paul Durrant
                   ` (5 subsequent siblings)
  10 siblings, 1 reply; 30+ messages in thread
From: Paul Durrant @ 2017-11-28 15:08 UTC (permalink / raw)
  To: xen-devel
  Cc: Stefano Stabellini, Wei Liu, George Dunlap, Andrew Cooper,
	Ian Jackson, Tim Deegan, Julien Grall, Paul Durrant,
	Daniel De Graaf

Certain memory resources associated with a guest are not necessarily
present in the guest P2M.

This patch adds the boilerplate for new memory op to allow such a resource
to be priv-mapped directly, by either a PV or HVM tools domain.

NOTE: Whilst the new op is not intrinsicly specific to the x86 architecture,
      I have no means to test it on an ARM platform and so cannot verify
      that it functions correctly.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
---
Cc: George Dunlap <george.dunlap@eu.citrix.com>
Cc: Andrew Cooper <andrew.cooper3@citrix.com>
Cc: George Dunlap <George.Dunlap@eu.citrix.com>
Cc: Ian Jackson <ian.jackson@eu.citrix.com>
Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Tim Deegan <tim@xen.org>
Cc: Wei Liu <wei.liu2@citrix.com>
Cc: Daniel De Graaf <dgdegra@tycho.nsa.gov>
Cc: Julien Grall <julien.grall@arm.com>

v14:
 - Addressed more comments from Jan.

v13:
 - Use xen_pfn_t for mfn_list.
 - Addressed further comments from Jan and Julien.

v12:
 - Addressed more comments form Jan.
 - Removed #ifdef CONFIG_X86 from common code and instead introduced a
   stub set_foreign_p2m_entry() in asm-arm/p2m.h returning -EOPNOTSUPP.
 - Restricted mechanism for querying implementation limit on nr_frames
   and simplified compat code.

v11:
 - Addressed more comments from Jan.

v9:
 - Addressed more comments from Jan.

v8:
 - Move the code into common as requested by Jan.
 - Make the gmfn_list handle a 64-bit type to avoid limiting the MFN
   range for a 32-bit tools domain.
 - Add missing pad.
 - Add compat code.
 - Make this patch deal with purely boilerplate.
 - Drop George's A-b and Wei's R-b because the changes are non-trivial,
   and update Cc list now the boilerplate is common.

v5:
 - Switched __copy_to/from_guest_offset() to copy_to/from_guest_offset().
---
 tools/flask/policy/modules/xen.if   |  4 +-
 xen/arch/x86/mm/p2m.c               |  3 +-
 xen/common/compat/memory.c          | 95 +++++++++++++++++++++++++++++++++++++
 xen/common/memory.c                 | 89 ++++++++++++++++++++++++++++++++++
 xen/include/asm-arm/p2m.h           | 10 ++++
 xen/include/asm-x86/p2m.h           |  3 ++
 xen/include/public/memory.h         | 43 ++++++++++++++++-
 xen/include/xlat.lst                |  1 +
 xen/include/xsm/dummy.h             |  6 +++
 xen/include/xsm/xsm.h               |  6 +++
 xen/xsm/dummy.c                     |  1 +
 xen/xsm/flask/hooks.c               |  6 +++
 xen/xsm/flask/policy/access_vectors |  2 +
 13 files changed, 265 insertions(+), 4 deletions(-)

diff --git a/tools/flask/policy/modules/xen.if b/tools/flask/policy/modules/xen.if
index 55437496f6..07cba8a15d 100644
--- a/tools/flask/policy/modules/xen.if
+++ b/tools/flask/policy/modules/xen.if
@@ -52,7 +52,8 @@ define(`create_domain_common', `
 			settime setdomainhandle getvcpucontext set_misc_info };
 	allow $1 $2:domain2 { set_cpuid settsc setscheduler setclaim
 			set_max_evtchn set_vnumainfo get_vnumainfo cacheflush
-			psr_cmt_op psr_cat_op soft_reset set_gnttab_limits };
+			psr_cmt_op psr_cat_op soft_reset set_gnttab_limits
+			resource_map };
 	allow $1 $2:security check_context;
 	allow $1 $2:shadow enable;
 	allow $1 $2:mmu { map_read map_write adjust memorymap physmap pinpage mmuext_op updatemp };
@@ -152,6 +153,7 @@ define(`device_model', `
 	allow $1 $2_target:domain { getdomaininfo shutdown };
 	allow $1 $2_target:mmu { map_read map_write adjust physmap target_hack };
 	allow $1 $2_target:hvm { getparam setparam hvmctl cacheattr dm };
+	allow $1 $2_target:domain2 resource_map;
 ')
 
 # make_device_model(priv, dm_dom, hvm_dom)
diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c
index c72a3cdebb..71bb9b4f93 100644
--- a/xen/arch/x86/mm/p2m.c
+++ b/xen/arch/x86/mm/p2m.c
@@ -1132,8 +1132,7 @@ static int set_typed_p2m_entry(struct domain *d, unsigned long gfn_l,
 }
 
 /* Set foreign mfn in the given guest's p2m table. */
-static int set_foreign_p2m_entry(struct domain *d, unsigned long gfn,
-                                 mfn_t mfn)
+int set_foreign_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn)
 {
     return set_typed_p2m_entry(d, gfn, mfn, PAGE_ORDER_4K, p2m_map_foreign,
                                p2m_get_hostp2m(d)->default_access);
diff --git a/xen/common/compat/memory.c b/xen/common/compat/memory.c
index 35bb259808..9a7cb1a71b 100644
--- a/xen/common/compat/memory.c
+++ b/xen/common/compat/memory.c
@@ -71,6 +71,7 @@ int compat_memory_op(unsigned int cmd, XEN_GUEST_HANDLE_PARAM(void) compat)
             struct xen_remove_from_physmap *xrfp;
             struct xen_vnuma_topology_info *vnuma;
             struct xen_mem_access_op *mao;
+            struct xen_mem_acquire_resource *mar;
         } nat;
         union {
             struct compat_memory_reservation rsrv;
@@ -79,6 +80,7 @@ int compat_memory_op(unsigned int cmd, XEN_GUEST_HANDLE_PARAM(void) compat)
             struct compat_add_to_physmap_batch atpb;
             struct compat_vnuma_topology_info vnuma;
             struct compat_mem_access_op mao;
+            struct compat_mem_acquire_resource mar;
         } cmp;
 
         set_xen_guest_handle(nat.hnd, COMPAT_ARG_XLAT_VIRT_BASE);
@@ -395,6 +397,57 @@ int compat_memory_op(unsigned int cmd, XEN_GUEST_HANDLE_PARAM(void) compat)
         }
 #endif
 
+        case XENMEM_acquire_resource:
+        {
+            xen_pfn_t *xen_frame_list;
+            unsigned int max_nr_frames;
+
+            if ( copy_from_guest(&cmp.mar, compat, 1) )
+                return -EFAULT;
+
+            /*
+             * The number of frames handled is currently limited to a
+             * small number by the underlying implementation, so the
+             * scratch space should be sufficient for bouncing the
+             * frame addresses.
+             */
+            max_nr_frames = (COMPAT_ARG_XLAT_SIZE - sizeof(*nat.mar)) /
+                sizeof(*xen_frame_list);
+
+            if ( cmp.mar.nr_frames > max_nr_frames )
+                return -E2BIG;
+
+            if ( compat_handle_is_null(cmp.mar.frame_list) )
+                xen_frame_list = NULL;
+            else
+            {
+                xen_frame_list = (xen_pfn_t *)(nat.mar + 1);
+
+                if ( !compat_handle_okay(cmp.mar.frame_list,
+                                         cmp.mar.nr_frames) )
+                    return -EFAULT;
+
+                for ( i = 0; i < cmp.mar.nr_frames; i++ )
+                {
+                    compat_pfn_t frame;
+
+                    if ( __copy_from_compat_offset(
+                             &frame, cmp.mar.frame_list, i, 1) )
+                        return -EFAULT;
+
+                    xen_frame_list[i] = frame;
+                }
+            }
+
+#define XLAT_mem_acquire_resource_HNDL_frame_list(_d_, _s_) \
+            set_xen_guest_handle((_d_)->frame_list, xen_frame_list)
+
+            XLAT_mem_acquire_resource(nat.mar, &cmp.mar);
+
+#undef XLAT_mem_acquire_resource_HNDL_frame_list
+
+            break;
+        }
         default:
             return compat_arch_memory_op(cmd, compat);
         }
@@ -535,6 +588,48 @@ int compat_memory_op(unsigned int cmd, XEN_GUEST_HANDLE_PARAM(void) compat)
                 rc = -EFAULT;
             break;
 
+        case XENMEM_acquire_resource:
+        {
+            const xen_pfn_t *xen_frame_list = (xen_pfn_t *)(nat.mar + 1);
+            compat_pfn_t *compat_frame_list = (compat_pfn_t *)(nat.mar + 1);
+
+            if ( compat_handle_is_null(cmp.mar.frame_list) )
+            {
+                DEFINE_XEN_GUEST_HANDLE(compat_mem_acquire_resource_t);
+
+                if ( __copy_field_to_guest(
+                         guest_handle_cast(compat,
+                                           compat_mem_acquire_resource_t),
+                         &cmp.mar, nr_frames) )
+                    return -EFAULT;
+            }
+            else
+            {
+                /*
+                 * NOTE: the smaller compat array overwrites the native
+                 *       array.
+                 */
+                BUILD_BUG_ON(sizeof(compat_pfn_t) > sizeof(xen_pfn_t));
+
+                for ( i = 0; i < cmp.mar.nr_frames; i++ )
+                {
+                    compat_pfn_t frame = xen_frame_list[i];
+
+                    if ( frame != xen_frame_list[i] )
+                        return -ERANGE;
+
+                    compat_frame_list[i] = frame;
+                }
+
+                if ( __copy_to_compat_offset(cmp.mar.frame_list, 0,
+                                             compat_frame_list,
+                                             cmp.mar.nr_frames) )
+                    return -EFAULT;
+            }
+
+            break;
+        }
+
         default:
             domain_crash(current->domain);
             split = 0;
diff --git a/xen/common/memory.c b/xen/common/memory.c
index a6ba33fdcb..6c385a2328 100644
--- a/xen/common/memory.c
+++ b/xen/common/memory.c
@@ -970,6 +970,90 @@ static long xatp_permission_check(struct domain *d, unsigned int space)
     return xsm_add_to_physmap(XSM_TARGET, current->domain, d);
 }
 
+static int acquire_resource(
+    XEN_GUEST_HANDLE_PARAM(xen_mem_acquire_resource_t) arg)
+{
+    struct domain *d, *currd = current->domain;
+    xen_mem_acquire_resource_t xmar;
+    /*
+     * The mfn_list and gfn_list (below) arrays are ok on stack for the
+     * moment since they are small, but if they need to grow in future
+     * use-cases then per-CPU arrays or heap allocations may be required.
+     */
+    xen_pfn_t mfn_list[2];
+    int rc;
+
+    if ( copy_from_guest(&xmar, arg, 1) )
+        return -EFAULT;
+
+    if ( xmar.pad != 0 )
+        return -EINVAL;
+
+    if ( guest_handle_is_null(xmar.frame_list) )
+    {
+        if ( xmar.nr_frames )
+            return -EINVAL;
+
+        xmar.nr_frames = ARRAY_SIZE(mfn_list);
+
+        if ( __copy_field_to_guest(arg, &xmar, nr_frames) )
+            return -EFAULT;
+
+        return 0;
+    }
+
+    if ( xmar.nr_frames > ARRAY_SIZE(mfn_list) )
+        return -E2BIG;
+
+    rc = rcu_lock_remote_domain_by_id(xmar.domid, &d);
+    if ( rc )
+        return rc;
+
+    rc = xsm_domain_resource_map(XSM_DM_PRIV, d);
+    if ( rc )
+        goto out;
+
+    switch ( xmar.type )
+    {
+    default:
+        rc = -EOPNOTSUPP;
+        break;
+    }
+
+    if ( rc )
+        goto out;
+
+    if ( !paging_mode_translate(currd) )
+    {
+        if ( copy_to_guest(xmar.frame_list, mfn_list, xmar.nr_frames) )
+            rc = -EFAULT;
+    }
+    else
+    {
+        xen_pfn_t gfn_list[ARRAY_SIZE(mfn_list)];
+        unsigned int i;
+
+        if ( copy_from_guest(gfn_list, xmar.frame_list, xmar.nr_frames) )
+            rc = -EFAULT;
+
+        for ( i = 0; !rc && i < xmar.nr_frames; i++ )
+        {
+            rc = set_foreign_p2m_entry(currd, gfn_list[i],
+                                       _mfn(mfn_list[i]));
+            if ( rc )
+                /*
+                 * Make sure rc is -EIO for any iteration other than
+                 * the first.
+                 */
+                rc = i ? -EIO : rc;
+        }
+    }
+
+ out:
+    rcu_unlock_domain(d);
+    return rc;
+}
+
 long do_memory_op(unsigned long cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
 {
     struct domain *d, *curr_d = current->domain;
@@ -1408,6 +1492,11 @@ long do_memory_op(unsigned long cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
     }
 #endif
 
+    case XENMEM_acquire_resource:
+        rc = acquire_resource(
+            guest_handle_cast(arg, xen_mem_acquire_resource_t));
+        break;
+
     default:
         rc = arch_memory_op(cmd, arg);
         break;
diff --git a/xen/include/asm-arm/p2m.h b/xen/include/asm-arm/p2m.h
index faadcfe8fe..db2cc5d7a3 100644
--- a/xen/include/asm-arm/p2m.h
+++ b/xen/include/asm-arm/p2m.h
@@ -346,6 +346,16 @@ static inline gfn_t gfn_next_boundary(gfn_t gfn, unsigned int order)
     return gfn_add(gfn, 1UL << order);
 }
 
+static inline int set_foreign_p2m_entry(struct domain *d, unsigned long gfn,
+                                        mfn_t mfn)
+{
+    /*
+     * NOTE: If this is implemented then proper reference counting of
+     *       foreign entries will need to be impmemented.
+     */
+    return -EOPNOTSUPP;
+}
+
 #endif /* _XEN_P2M_H */
 
 /*
diff --git a/xen/include/asm-x86/p2m.h b/xen/include/asm-x86/p2m.h
index 17b1d0c8d3..44f7ec088c 100644
--- a/xen/include/asm-x86/p2m.h
+++ b/xen/include/asm-x86/p2m.h
@@ -620,6 +620,9 @@ void p2m_memory_type_changed(struct domain *d);
 int p2m_is_logdirty_range(struct p2m_domain *, unsigned long start,
                           unsigned long end);
 
+/* Set foreign entry in the p2m table (for priv-mapping) */
+int set_foreign_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn);
+
 /* Set mmio addresses in the p2m table (for pass-through) */
 int set_mmio_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn,
                        unsigned int order, p2m_access_t access);
diff --git a/xen/include/public/memory.h b/xen/include/public/memory.h
index 29386df98b..83e60b6603 100644
--- a/xen/include/public/memory.h
+++ b/xen/include/public/memory.h
@@ -599,6 +599,47 @@ struct xen_reserved_device_memory_map {
 typedef struct xen_reserved_device_memory_map xen_reserved_device_memory_map_t;
 DEFINE_XEN_GUEST_HANDLE(xen_reserved_device_memory_map_t);
 
+/*
+ * Get the pages for a particular guest resource, so that they can be
+ * mapped directly by a tools domain.
+ */
+#define XENMEM_acquire_resource 28
+struct xen_mem_acquire_resource {
+    /* IN - the domain whose resource is to be mapped */
+    domid_t domid;
+    /* IN - the type of resource */
+    uint16_t type;
+    /*
+     * IN - a type-specific resource identifier, which must be zero
+     *      unless stated otherwise.
+     */
+    uint32_t id;
+    /* IN/OUT - As an IN parameter number of frames of the resource
+     *          to be mapped. However, if the specified value is 0 and
+     *          frame_list is NULL then this field will be set to the
+     *          maximum value supported by the implementation on return.
+     */
+    uint32_t nr_frames;
+    uint32_t pad;
+    /* IN - the index of the initial frame to be mapped. This parameter
+     *      is ignored if nr_frames is 0.
+     */
+    uint64_aligned_t frame;
+    /* IN/OUT - If the tools domain is PV then, upon return, frame_list
+     *          will be populated with the MFNs of the resource.
+     *          If the tools domain is HVM then it is expected that, on
+     *          entry, frame_list will be populated with a list of GFNs
+     *          that will be mapped to the MFNs of the resource.
+     *          If -EIO is returned then the frame_list has only been
+     *          partially mapped and it is up to the caller to unmap all
+     *          the GFNs.
+     *          This parameter may be NULL if nr_frames is 0.
+     */
+    XEN_GUEST_HANDLE(xen_pfn_t) frame_list;
+};
+typedef struct xen_mem_acquire_resource xen_mem_acquire_resource_t;
+DEFINE_XEN_GUEST_HANDLE(xen_mem_acquire_resource_t);
+
 #endif /* defined(__XEN__) || defined(__XEN_TOOLS__) */
 
 /*
@@ -650,7 +691,7 @@ struct xen_vnuma_topology_info {
 typedef struct xen_vnuma_topology_info xen_vnuma_topology_info_t;
 DEFINE_XEN_GUEST_HANDLE(xen_vnuma_topology_info_t);
 
-/* Next available subop number is 28 */
+/* Next available subop number is 29 */
 
 #endif /* __XEN_PUBLIC_MEMORY_H__ */
 
diff --git a/xen/include/xlat.lst b/xen/include/xlat.lst
index 4346cbedcf..5806ef0ad8 100644
--- a/xen/include/xlat.lst
+++ b/xen/include/xlat.lst
@@ -84,6 +84,7 @@
 !	memory_map			memory.h
 !	memory_reservation		memory.h
 !	mem_access_op			memory.h
+!	mem_acquire_resource		memory.h
 !	pod_target			memory.h
 !	remove_from_physmap		memory.h
 !	reserved_device_memory_map	memory.h
diff --git a/xen/include/xsm/dummy.h b/xen/include/xsm/dummy.h
index b2cd56cdc5..54dae7ae8a 100644
--- a/xen/include/xsm/dummy.h
+++ b/xen/include/xsm/dummy.h
@@ -724,3 +724,9 @@ static XSM_INLINE int xsm_xen_version (XSM_DEFAULT_ARG uint32_t op)
         return xsm_default_action(XSM_PRIV, current->domain, NULL);
     }
 }
+
+static XSM_INLINE int xsm_domain_resource_map(XSM_DEFAULT_ARG struct domain *d)
+{
+    XSM_ASSERT_ACTION(XSM_DM_PRIV);
+    return xsm_default_action(action, current->domain, d);
+}
diff --git a/xen/include/xsm/xsm.h b/xen/include/xsm/xsm.h
index 7f7feffc68..d0db860ae0 100644
--- a/xen/include/xsm/xsm.h
+++ b/xen/include/xsm/xsm.h
@@ -180,6 +180,7 @@ struct xsm_operations {
     int (*dm_op) (struct domain *d);
 #endif
     int (*xen_version) (uint32_t cmd);
+    int (*domain_resource_map) (struct domain *d);
 };
 
 #ifdef CONFIG_XSM
@@ -692,6 +693,11 @@ static inline int xsm_xen_version (xsm_default_t def, uint32_t op)
     return xsm_ops->xen_version(op);
 }
 
+static inline int xsm_domain_resource_map(xsm_default_t def, struct domain *d)
+{
+    return xsm_ops->domain_resource_map(d);
+}
+
 #endif /* XSM_NO_WRAPPERS */
 
 #ifdef CONFIG_MULTIBOOT
diff --git a/xen/xsm/dummy.c b/xen/xsm/dummy.c
index 479b103614..6e751199ee 100644
--- a/xen/xsm/dummy.c
+++ b/xen/xsm/dummy.c
@@ -157,4 +157,5 @@ void __init xsm_fixup_ops (struct xsm_operations *ops)
     set_to_dummy_if_null(ops, dm_op);
 #endif
     set_to_dummy_if_null(ops, xen_version);
+    set_to_dummy_if_null(ops, domain_resource_map);
 }
diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c
index f01b4cfaaa..39851fe61f 100644
--- a/xen/xsm/flask/hooks.c
+++ b/xen/xsm/flask/hooks.c
@@ -1718,6 +1718,11 @@ static int flask_xen_version (uint32_t op)
     }
 }
 
+static int flask_domain_resource_map(struct domain *d)
+{
+    return current_has_perm(d, SECCLASS_DOMAIN2, DOMAIN2__RESOURCE_MAP);
+}
+
 long do_flask_op(XEN_GUEST_HANDLE_PARAM(xsm_op_t) u_flask_op);
 int compat_flask_op(XEN_GUEST_HANDLE_PARAM(xsm_op_t) u_flask_op);
 
@@ -1851,6 +1856,7 @@ static struct xsm_operations flask_ops = {
     .dm_op = flask_dm_op,
 #endif
     .xen_version = flask_xen_version,
+    .domain_resource_map = flask_domain_resource_map,
 };
 
 void __init flask_init(const void *policy_buffer, size_t policy_size)
diff --git a/xen/xsm/flask/policy/access_vectors b/xen/xsm/flask/policy/access_vectors
index 3a2d863b8f..341ade1f7d 100644
--- a/xen/xsm/flask/policy/access_vectors
+++ b/xen/xsm/flask/policy/access_vectors
@@ -250,6 +250,8 @@ class domain2
     psr_cat_op
 # XEN_DOMCTL_set_gnttab_limits
     set_gnttab_limits
+# XENMEM_resource_map
+    resource_map
 }
 
 # Similar to class domain, but primarily contains domctls related to HVM domains
-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* [PATCH v14 06/11] x86/hvm/ioreq: add a new mappable resource type...
  2017-11-28 15:08 [PATCH v14 00/11] x86: guest resource mapping Paul Durrant
                   ` (4 preceding siblings ...)
  2017-11-28 15:08 ` [PATCH v14 05/11] x86/mm: add HYPERVISOR_memory_op to acquire guest resources Paul Durrant
@ 2017-11-28 15:08 ` Paul Durrant
  2017-12-14  9:51   ` Paul Durrant
  2017-11-28 15:08 ` [PATCH v14 07/11] x86/mm: add an extra command to HYPERVISOR_mmu_update Paul Durrant
                   ` (4 subsequent siblings)
  10 siblings, 1 reply; 30+ messages in thread
From: Paul Durrant @ 2017-11-28 15:08 UTC (permalink / raw)
  To: xen-devel
  Cc: Stefano Stabellini, Wei Liu, George Dunlap, Andrew Cooper,
	Ian Jackson, Tim Deegan, Julien Grall, Paul Durrant

... XENMEM_resource_ioreq_server

This patch adds support for a new resource type that can be mapped using
the XENMEM_acquire_resource memory op.

If an emulator makes use of this resource type then, instead of mapping
gfns, the IOREQ server will allocate pages from the heap. These pages
will never be present in the P2M of the guest at any point and so are
not vulnerable to any direct attack by the guest. They are only ever
accessible by Xen and any domain that has mapping privilege over the
guest (which may or may not be limited to the domain running the emulator).

NOTE: Use of the new resource type is not compatible with use of
      XEN_DMOP_get_ioreq_server_info unless the XEN_DMOP_no_gfns flag is
      set.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
---
Cc: George Dunlap <George.Dunlap@eu.citrix.com>
Cc: Wei Liu <wei.liu2@citrix.com>
Cc: Andrew Cooper <andrew.cooper3@citrix.com>
Cc: Ian Jackson <ian.jackson@eu.citrix.com>
Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Tim Deegan <tim@xen.org>
Cc: Julien Grall <julien.grall@arm.com>

v14:
 - Addressed more comments from Jan.

v13:
 - Introduce an arch_acquire_resource() as suggested by Julien (and have
   the ARM varient simply return -EOPNOTSUPP).
 - Check for ioreq server id truncation as requested by Jan.
 - Not added Jan's R-b due to substantive change from v12.

v12:
 - Addressed more comments from Jan.
 - Dropped George's A-b and Wei's R-b because of material change.

v11:
 - Addressed more comments from Jan.

v10:
 - Addressed comments from Jan.

v8:
 - Re-base on new boilerplate.
 - Adjust function signature of hvm_get_ioreq_server_frame(), and test
   whether the bufioreq page is present.

v5:
 - Use get_ioreq_server() function rather than indexing array directly.
 - Add more explanation into comments to state than mapping guest frames
   and allocation of pages for ioreq servers are not simultaneously
   permitted.
 - Add a comment into asm/ioreq.h stating the meaning of the index
   value passed to hvm_get_ioreq_server_frame().
---
 xen/arch/x86/hvm/ioreq.c        | 156 ++++++++++++++++++++++++++++++++++++++++
 xen/arch/x86/mm.c               |  41 +++++++++++
 xen/common/memory.c             |   3 +-
 xen/include/asm-arm/mm.h        |   7 ++
 xen/include/asm-x86/hvm/ioreq.h |   2 +
 xen/include/asm-x86/mm.h        |   5 ++
 xen/include/public/hvm/dm_op.h  |   4 ++
 xen/include/public/memory.h     |   9 +++
 8 files changed, 226 insertions(+), 1 deletion(-)

diff --git a/xen/arch/x86/hvm/ioreq.c b/xen/arch/x86/hvm/ioreq.c
index 39de659ddf..d991ac9cdc 100644
--- a/xen/arch/x86/hvm/ioreq.c
+++ b/xen/arch/x86/hvm/ioreq.c
@@ -259,6 +259,19 @@ static int hvm_map_ioreq_gfn(struct hvm_ioreq_server *s, bool buf)
     struct hvm_ioreq_page *iorp = buf ? &s->bufioreq : &s->ioreq;
     int rc;
 
+    if ( iorp->page )
+    {
+        /*
+         * If a page has already been allocated (which will happen on
+         * demand if hvm_get_ioreq_server_frame() is called), then
+         * mapping a guest frame is not permitted.
+         */
+        if ( gfn_eq(iorp->gfn, INVALID_GFN) )
+            return -EPERM;
+
+        return 0;
+    }
+
     if ( d->is_dying )
         return -EINVAL;
 
@@ -281,6 +294,70 @@ static int hvm_map_ioreq_gfn(struct hvm_ioreq_server *s, bool buf)
     return rc;
 }
 
+static int hvm_alloc_ioreq_mfn(struct hvm_ioreq_server *s, bool buf)
+{
+    struct domain *currd = current->domain;
+    struct hvm_ioreq_page *iorp = buf ? &s->bufioreq : &s->ioreq;
+
+    if ( iorp->page )
+    {
+        /*
+         * If a guest frame has already been mapped (which may happen
+         * on demand if hvm_get_ioreq_server_info() is called), then
+         * allocating a page is not permitted.
+         */
+        if ( !gfn_eq(iorp->gfn, INVALID_GFN) )
+            return -EPERM;
+
+        return 0;
+    }
+
+    /*
+     * Allocated IOREQ server pages are assigned to the emulating
+     * domain, not the target domain. This is because the emulator is
+     * likely to be destroyed after the target domain has been torn
+     * down, and we must use MEMF_no_refcount otherwise page allocation
+     * could fail if the emulating domain has already reached its
+     * maximum allocation.
+     */
+    iorp->page = alloc_domheap_page(currd, MEMF_no_refcount);
+    if ( !iorp->page )
+        return -ENOMEM;
+
+    if ( !get_page_type(iorp->page, PGT_writable_page) )
+    {
+        ASSERT_UNREACHABLE();
+        put_page(iorp->page);
+        iorp->page = NULL;
+        return -ENOMEM;
+    }
+
+    iorp->va = __map_domain_page_global(iorp->page);
+    if ( !iorp->va )
+    {
+        put_page_and_type(iorp->page);
+        iorp->page = NULL;
+        return -ENOMEM;
+    }
+
+    clear_page(iorp->va);
+    return 0;
+}
+
+static void hvm_free_ioreq_mfn(struct hvm_ioreq_server *s, bool buf)
+{
+    struct hvm_ioreq_page *iorp = buf ? &s->bufioreq : &s->ioreq;
+
+    if ( !iorp->page )
+        return;
+
+    unmap_domain_page_global(iorp->va);
+    iorp->va = NULL;
+
+    put_page_and_type(iorp->page);
+    iorp->page = NULL;
+}
+
 bool is_ioreq_server_page(struct domain *d, const struct page_info *page)
 {
     const struct hvm_ioreq_server *s;
@@ -484,6 +561,27 @@ static void hvm_ioreq_server_unmap_pages(struct hvm_ioreq_server *s)
     hvm_unmap_ioreq_gfn(s, false);
 }
 
+static int hvm_ioreq_server_alloc_pages(struct hvm_ioreq_server *s)
+{
+    int rc;
+
+    rc = hvm_alloc_ioreq_mfn(s, false);
+
+    if ( !rc && (s->bufioreq_handling != HVM_IOREQSRV_BUFIOREQ_OFF) )
+        rc = hvm_alloc_ioreq_mfn(s, true);
+
+    if ( rc )
+        hvm_free_ioreq_mfn(s, false);
+
+    return rc;
+}
+
+static void hvm_ioreq_server_free_pages(struct hvm_ioreq_server *s)
+{
+    hvm_free_ioreq_mfn(s, true);
+    hvm_free_ioreq_mfn(s, false);
+}
+
 static void hvm_ioreq_server_free_rangesets(struct hvm_ioreq_server *s)
 {
     unsigned int i;
@@ -612,7 +710,18 @@ static int hvm_ioreq_server_init(struct hvm_ioreq_server *s,
 
  fail_add:
     hvm_ioreq_server_remove_all_vcpus(s);
+
+    /*
+     * NOTE: It is safe to call both hvm_ioreq_server_unmap_pages() and
+     *       hvm_ioreq_server_free_pages() in that order.
+     *       This is because the former will do nothing if the pages
+     *       are not mapped, leaving the page to be freed by the latter.
+     *       However if the pages are mapped then the former will set
+     *       the page_info pointer to NULL, meaning the latter will do
+     *       nothing.
+     */
     hvm_ioreq_server_unmap_pages(s);
+    hvm_ioreq_server_free_pages(s);
 
     return rc;
 }
@@ -622,6 +731,7 @@ static void hvm_ioreq_server_deinit(struct hvm_ioreq_server *s)
     ASSERT(!s->enabled);
     hvm_ioreq_server_remove_all_vcpus(s);
     hvm_ioreq_server_unmap_pages(s);
+    hvm_ioreq_server_free_pages(s);
     hvm_ioreq_server_free_rangesets(s);
 }
 
@@ -777,6 +887,52 @@ int hvm_get_ioreq_server_info(struct domain *d, ioservid_t id,
     return rc;
 }
 
+int hvm_get_ioreq_server_frame(struct domain *d, ioservid_t id,
+                               unsigned long idx, mfn_t *mfn)
+{
+    struct hvm_ioreq_server *s;
+    int rc;
+
+    spin_lock_recursive(&d->arch.hvm_domain.ioreq_server.lock);
+
+    if ( id == DEFAULT_IOSERVID )
+        return -EOPNOTSUPP;
+
+    s = get_ioreq_server(d, id);
+
+    ASSERT(!IS_DEFAULT(s));
+
+    rc = hvm_ioreq_server_alloc_pages(s);
+    if ( rc )
+        goto out;
+
+    switch ( idx )
+    {
+    case XENMEM_resource_ioreq_server_frame_bufioreq:
+        rc = -ENOENT;
+        if ( !HANDLE_BUFIOREQ(s) )
+            goto out;
+
+        *mfn = _mfn(page_to_mfn(s->bufioreq.page));
+        rc = 0;
+        break;
+
+    case XENMEM_resource_ioreq_server_frame_ioreq(0):
+        *mfn = _mfn(page_to_mfn(s->ioreq.page));
+        rc = 0;
+        break;
+
+    default:
+        rc = -EINVAL;
+        break;
+    }
+
+ out:
+    spin_unlock_recursive(&d->arch.hvm_domain.ioreq_server.lock);
+
+    return rc;
+}
+
 int hvm_map_io_range_to_ioreq_server(struct domain *d, ioservid_t id,
                                      uint32_t type, uint64_t start,
                                      uint64_t end)
diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
index 6ec6e68afe..2656eb181a 100644
--- a/xen/arch/x86/mm.c
+++ b/xen/arch/x86/mm.c
@@ -122,6 +122,7 @@
 #include <asm/fixmap.h>
 #include <asm/io_apic.h>
 #include <asm/pci.h>
+#include <asm/hvm/ioreq.h>
 
 #include <asm/hvm/grant_table.h>
 #include <asm/pv/grant_table.h>
@@ -4170,6 +4171,46 @@ int xenmem_add_to_physmap_one(
     return rc;
 }
 
+int arch_acquire_resource(struct domain *d, unsigned int type,
+                          unsigned int id, unsigned long frame,
+                          unsigned int nr_frames, xen_pfn_t mfn_list[])
+{
+    int rc;
+
+    switch ( type )
+    {
+    case XENMEM_resource_ioreq_server:
+    {
+        ioservid_t ioservid = id;
+        unsigned int i;
+
+        rc = -EINVAL;
+        if ( id != (unsigned int)ioservid )
+            break;
+
+        rc = 0;
+        for ( i = 0; i < nr_frames; i++ )
+        {
+            mfn_t mfn;
+
+            rc = hvm_get_ioreq_server_frame(d, id, frame + i, &mfn);
+            if ( rc )
+                break;
+
+            mfn_list[i] = mfn_x(mfn);
+        }
+
+        break;
+    }
+
+    default:
+        rc = -EOPNOTSUPP;
+        break;
+    }
+
+    return rc;
+}
+
 long arch_memory_op(unsigned long cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
 {
     int rc;
diff --git a/xen/common/memory.c b/xen/common/memory.c
index 6c385a2328..0167d9788b 100644
--- a/xen/common/memory.c
+++ b/xen/common/memory.c
@@ -1016,7 +1016,8 @@ static int acquire_resource(
     switch ( xmar.type )
     {
     default:
-        rc = -EOPNOTSUPP;
+        rc = arch_acquire_resource(d, xmar.type, xmar.id, xmar.frame,
+                                   xmar.nr_frames, mfn_list);
         break;
     }
 
diff --git a/xen/include/asm-arm/mm.h b/xen/include/asm-arm/mm.h
index ad2f2a43dc..bd146dee3c 100644
--- a/xen/include/asm-arm/mm.h
+++ b/xen/include/asm-arm/mm.h
@@ -381,6 +381,13 @@ static inline void put_page_and_type(struct page_info *page)
 
 void clear_and_clean_page(struct page_info *page);
 
+static inline int arch_acquire_resource(
+    struct domain *d, unsigned int type, unsigned int id,
+    unsigned long frame,unsigned int nr_frames, xen_pfn_t mfn_list[])
+{
+    return -EOPNOTSUPP;
+}
+
 #endif /*  __ARCH_ARM_MM__ */
 /*
  * Local variables:
diff --git a/xen/include/asm-x86/hvm/ioreq.h b/xen/include/asm-x86/hvm/ioreq.h
index 1829fcf43e..9e37c97a37 100644
--- a/xen/include/asm-x86/hvm/ioreq.h
+++ b/xen/include/asm-x86/hvm/ioreq.h
@@ -31,6 +31,8 @@ int hvm_get_ioreq_server_info(struct domain *d, ioservid_t id,
                               unsigned long *ioreq_gfn,
                               unsigned long *bufioreq_gfn,
                               evtchn_port_t *bufioreq_port);
+int hvm_get_ioreq_server_frame(struct domain *d, ioservid_t id,
+                               unsigned long idx, mfn_t *mfn);
 int hvm_map_io_range_to_ioreq_server(struct domain *d, ioservid_t id,
                                      uint32_t type, uint64_t start,
                                      uint64_t end);
diff --git a/xen/include/asm-x86/mm.h b/xen/include/asm-x86/mm.h
index 83626085e0..10e5b6cd14 100644
--- a/xen/include/asm-x86/mm.h
+++ b/xen/include/asm-x86/mm.h
@@ -629,4 +629,9 @@ static inline bool arch_mfn_in_directmap(unsigned long mfn)
     return mfn <= (virt_to_mfn(eva - 1) + 1);
 }
 
+int arch_acquire_resource(struct domain *d, unsigned int type,
+                          unsigned int id, unsigned long frame,
+                          unsigned int nr_frames,
+                          xen_pfn_t mfn_list[]);
+
 #endif /* __ASM_X86_MM_H__ */
diff --git a/xen/include/public/hvm/dm_op.h b/xen/include/public/hvm/dm_op.h
index 13b3737c2f..add68ea192 100644
--- a/xen/include/public/hvm/dm_op.h
+++ b/xen/include/public/hvm/dm_op.h
@@ -90,6 +90,10 @@ struct xen_dm_op_create_ioreq_server {
  * the frame numbers passed back in gfns <ioreq_gfn> and <bufioreq_gfn>
  * respectively. (If the IOREQ Server is not handling buffered emulation
  * only <ioreq_gfn> will be valid).
+ *
+ * NOTE: To access the synchronous ioreq structures and buffered ioreq
+ *       ring, it is preferable to use the XENMEM_acquire_resource memory
+ *       op specifying resource type XENMEM_resource_ioreq_server.
  */
 #define XEN_DMOP_get_ioreq_server_info 2
 
diff --git a/xen/include/public/memory.h b/xen/include/public/memory.h
index 83e60b6603..838f248a59 100644
--- a/xen/include/public/memory.h
+++ b/xen/include/public/memory.h
@@ -609,9 +609,14 @@ struct xen_mem_acquire_resource {
     domid_t domid;
     /* IN - the type of resource */
     uint16_t type;
+
+#define XENMEM_resource_ioreq_server 0
+
     /*
      * IN - a type-specific resource identifier, which must be zero
      *      unless stated otherwise.
+     *
+     * type == XENMEM_resource_ioreq_server -> id == ioreq server id
      */
     uint32_t id;
     /* IN/OUT - As an IN parameter number of frames of the resource
@@ -625,6 +630,10 @@ struct xen_mem_acquire_resource {
      *      is ignored if nr_frames is 0.
      */
     uint64_aligned_t frame;
+
+#define XENMEM_resource_ioreq_server_frame_bufioreq 0
+#define XENMEM_resource_ioreq_server_frame_ioreq(n) (1 + (n))
+
     /* IN/OUT - If the tools domain is PV then, upon return, frame_list
      *          will be populated with the MFNs of the resource.
      *          If the tools domain is HVM then it is expected that, on
-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* [PATCH v14 07/11] x86/mm: add an extra command to HYPERVISOR_mmu_update...
  2017-11-28 15:08 [PATCH v14 00/11] x86: guest resource mapping Paul Durrant
                   ` (5 preceding siblings ...)
  2017-11-28 15:08 ` [PATCH v14 06/11] x86/hvm/ioreq: add a new mappable resource type Paul Durrant
@ 2017-11-28 15:08 ` Paul Durrant
  2017-12-12 13:25   ` Jan Beulich
  2017-11-28 15:08 ` [PATCH v14 08/11] tools/libxenforeignmemory: add support for resource mapping Paul Durrant
                   ` (3 subsequent siblings)
  10 siblings, 1 reply; 30+ messages in thread
From: Paul Durrant @ 2017-11-28 15:08 UTC (permalink / raw)
  To: xen-devel
  Cc: Stefano Stabellini, Wei Liu, George Dunlap, Andrew Cooper,
	Ian Jackson, Tim Deegan, Paul Durrant

...to allow the calling domain to prevent translation of specified l1e
value.

Despite what the comment in public/xen.h might imply, specifying a
command value of MMU_NORMAL_PT_UPDATE will not simply update an l1e with
the specified value. Instead, mod_l1_entry() tests whether foreign_dom
has PG_translate set in its paging mode and, if it does, assumes that the
the pfn value in the l1e is a gfn rather than an mfn.

To allow PV tools domain to map mfn values from a previously issued
HYPERVISOR_memory_op:XENMEM_acquire_resource, there needs to be a way
to tell HYPERVISOR_mmu_update that the specific l1e value does not
require translation regardless of the paging mode of foreign_dom. This
patch therefore defines a new command value, MMU_PT_UPDATE_NO_TRANSLATE,
which has the same semantics as MMU_NORMAL_PT_UPDATE except that the
paging mode of foreign_dom is ignored and the l1e value is used verbatim.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
---
Cc: Andrew Cooper <andrew.cooper3@citrix.com>
Cc: George Dunlap <George.Dunlap@eu.citrix.com>
Cc: Ian Jackson <ian.jackson@eu.citrix.com>
Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Tim Deegan <tim@xen.org>
Cc: Wei Liu <wei.liu2@citrix.com>

v13:
 - Re-base.

v8:
 - New in this version, replacing "allow a privileged PV domain to map
   guest mfns".
---
 xen/arch/x86/mm.c        | 13 ++++++++-----
 xen/include/public/xen.h | 12 +++++++++---
 2 files changed, 17 insertions(+), 8 deletions(-)

diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
index 2656eb181a..4428b7c2d2 100644
--- a/xen/arch/x86/mm.c
+++ b/xen/arch/x86/mm.c
@@ -1881,9 +1881,10 @@ void page_unlock(struct page_info *page)
 
 /* Update the L1 entry at pl1e to new value nl1e. */
 static int mod_l1_entry(l1_pgentry_t *pl1e, l1_pgentry_t nl1e,
-                        unsigned long gl1mfn, int preserve_ad,
+                        unsigned long gl1mfn, unsigned int cmd,
                         struct vcpu *pt_vcpu, struct domain *pg_dom)
 {
+    bool preserve_ad = (cmd == MMU_PT_UPDATE_PRESERVE_AD);
     l1_pgentry_t ol1e;
     struct domain *pt_dom = pt_vcpu->domain;
     int rc = 0;
@@ -1905,7 +1906,8 @@ static int mod_l1_entry(l1_pgentry_t *pl1e, l1_pgentry_t nl1e,
         }
 
         /* Translate foreign guest address. */
-        if ( paging_mode_translate(pg_dom) )
+        if ( cmd != MMU_PT_UPDATE_NO_TRANSLATE &&
+             paging_mode_translate(pg_dom) )
         {
             p2m_type_t p2mt;
             p2m_query_t q = l1e_get_flags(nl1e) & _PAGE_RW ?
@@ -3592,6 +3594,7 @@ long do_mmu_update(
              */
         case MMU_NORMAL_PT_UPDATE:
         case MMU_PT_UPDATE_PRESERVE_AD:
+        case MMU_PT_UPDATE_NO_TRANSLATE:
         {
             p2m_type_t p2mt;
 
@@ -3651,8 +3654,7 @@ long do_mmu_update(
                 {
                 case PGT_l1_page_table:
                     rc = mod_l1_entry(va, l1e_from_intpte(req.val), mfn,
-                                      cmd == MMU_PT_UPDATE_PRESERVE_AD, v,
-                                      pg_owner);
+                                      cmd, v, pg_owner);
                     break;
                 case PGT_l2_page_table:
                     rc = mod_l2_entry(va, l2e_from_intpte(req.val), mfn,
@@ -3927,7 +3929,8 @@ static int __do_update_va_mapping(
         goto out;
     }
 
-    rc = mod_l1_entry(pl1e, val, mfn_x(gl1mfn), 0, v, pg_owner);
+    rc = mod_l1_entry(pl1e, val, mfn_x(gl1mfn), MMU_NORMAL_PT_UPDATE, v,
+                      pg_owner);
 
     page_unlock(gl1pg);
     put_page(gl1pg);
diff --git a/xen/include/public/xen.h b/xen/include/public/xen.h
index 308109f176..fb1df8f293 100644
--- a/xen/include/public/xen.h
+++ b/xen/include/public/xen.h
@@ -268,6 +268,10 @@ DEFINE_XEN_GUEST_HANDLE(xen_ulong_t);
  * As MMU_NORMAL_PT_UPDATE above, but A/D bits currently in the PTE are ORed
  * with those in @val.
  *
+ * ptr[1:0] == MMU_PT_UPDATE_NO_TRANSLATE:
+ * As MMU_NORMAL_PT_UPDATE above, but @val is not translated though FD
+ * page tables.
+ *
  * @val is usually the machine frame number along with some attributes.
  * The attributes by default follow the architecture defined bits. Meaning that
  * if this is a X86_64 machine and four page table layout is used, the layout
@@ -334,9 +338,11 @@ DEFINE_XEN_GUEST_HANDLE(xen_ulong_t);
  *
  * PAT (bit 7 on) --> PWT (bit 3 on) and clear bit 7.
  */
-#define MMU_NORMAL_PT_UPDATE      0 /* checked '*ptr = val'. ptr is MA.      */
-#define MMU_MACHPHYS_UPDATE       1 /* ptr = MA of frame to modify entry for */
-#define MMU_PT_UPDATE_PRESERVE_AD 2 /* atomically: *ptr = val | (*ptr&(A|D)) */
+#define MMU_NORMAL_PT_UPDATE       0 /* checked '*ptr = val'. ptr is MA.      */
+#define MMU_MACHPHYS_UPDATE        1 /* ptr = MA of frame to modify entry for */
+#define MMU_PT_UPDATE_PRESERVE_AD  2 /* atomically: *ptr = val | (*ptr&(A|D)) */
+#define MMU_PT_UPDATE_NO_TRANSLATE 3 /* checked '*ptr = val'. ptr is MA.      */
+                                     /* val never translated.                 */
 
 /*
  * MMU EXTENDED OPERATIONS
-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* [PATCH v14 08/11] tools/libxenforeignmemory: add support for resource mapping
  2017-11-28 15:08 [PATCH v14 00/11] x86: guest resource mapping Paul Durrant
                   ` (6 preceding siblings ...)
  2017-11-28 15:08 ` [PATCH v14 07/11] x86/mm: add an extra command to HYPERVISOR_mmu_update Paul Durrant
@ 2017-11-28 15:08 ` Paul Durrant
  2017-11-28 15:08 ` [PATCH v14 09/11] tools/libxenforeignmemory: reduce xenforeignmemory_restrict code footprint Paul Durrant
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 30+ messages in thread
From: Paul Durrant @ 2017-11-28 15:08 UTC (permalink / raw)
  To: xen-devel; +Cc: Paul Durrant, Ian Jackson

A previous patch introduced a new HYPERVISOR_memory_op to acquire guest
resources for direct priv-mapping.

This patch adds new functionality into libxenforeignmemory to make use
of a new privcmd ioctl [1] that uses the new memory op to make such
resources available via mmap(2).

[1] http://xenbits.xen.org/gitweb/?p=people/pauldu/linux.git;a=commit;h=ce59a05e6712

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
Reviewed-by: Wei Liu <wei.liu2@citrix.com>
---
Cc: Ian Jackson <ian.jackson@eu.citrix.com>

v4:
 - Fixed errno and removed single-use label
 - The unmap call now returns a status
 - Use C99 initialization for ioctl struct

v2:
 - Bump minor version up to 3.
---
 tools/include/xen-sys/Linux/privcmd.h              | 11 +++++
 tools/libs/foreignmemory/Makefile                  |  2 +-
 tools/libs/foreignmemory/core.c                    | 53 ++++++++++++++++++++++
 .../libs/foreignmemory/include/xenforeignmemory.h  | 41 +++++++++++++++++
 tools/libs/foreignmemory/libxenforeignmemory.map   |  5 ++
 tools/libs/foreignmemory/linux.c                   | 45 ++++++++++++++++++
 tools/libs/foreignmemory/private.h                 | 31 +++++++++++++
 7 files changed, 187 insertions(+), 1 deletion(-)

diff --git a/tools/include/xen-sys/Linux/privcmd.h b/tools/include/xen-sys/Linux/privcmd.h
index 732ff7c15a..9531b728f9 100644
--- a/tools/include/xen-sys/Linux/privcmd.h
+++ b/tools/include/xen-sys/Linux/privcmd.h
@@ -86,6 +86,15 @@ typedef struct privcmd_dm_op {
 	const privcmd_dm_op_buf_t __user *ubufs;
 } privcmd_dm_op_t;
 
+typedef struct privcmd_mmap_resource {
+	domid_t dom;
+	__u32 type;
+	__u32 id;
+	__u32 idx;
+	__u64 num;
+	__u64 addr;
+} privcmd_mmap_resource_t;
+
 /*
  * @cmd: IOCTL_PRIVCMD_HYPERCALL
  * @arg: &privcmd_hypercall_t
@@ -103,5 +112,7 @@ typedef struct privcmd_dm_op {
 	_IOC(_IOC_NONE, 'P', 5, sizeof(privcmd_dm_op_t))
 #define IOCTL_PRIVCMD_RESTRICT					\
 	_IOC(_IOC_NONE, 'P', 6, sizeof(domid_t))
+#define IOCTL_PRIVCMD_MMAP_RESOURCE				\
+	_IOC(_IOC_NONE, 'P', 7, sizeof(privcmd_mmap_resource_t))
 
 #endif /* __LINUX_PUBLIC_PRIVCMD_H__ */
diff --git a/tools/libs/foreignmemory/Makefile b/tools/libs/foreignmemory/Makefile
index cbe815fce8..ee5c3fd67e 100644
--- a/tools/libs/foreignmemory/Makefile
+++ b/tools/libs/foreignmemory/Makefile
@@ -2,7 +2,7 @@ XEN_ROOT = $(CURDIR)/../../..
 include $(XEN_ROOT)/tools/Rules.mk
 
 MAJOR    = 1
-MINOR    = 2
+MINOR    = 3
 SHLIB_LDFLAGS += -Wl,--version-script=libxenforeignmemory.map
 
 CFLAGS   += -Werror -Wmissing-prototypes
diff --git a/tools/libs/foreignmemory/core.c b/tools/libs/foreignmemory/core.c
index 79b24d273b..efa915015c 100644
--- a/tools/libs/foreignmemory/core.c
+++ b/tools/libs/foreignmemory/core.c
@@ -17,6 +17,8 @@
 #include <assert.h>
 #include <errno.h>
 
+#include <sys/mman.h>
+
 #include "private.h"
 
 static int all_restrict_cb(Xentoolcore__Active_Handle *ah, domid_t domid) {
@@ -135,6 +137,57 @@ int xenforeignmemory_restrict(xenforeignmemory_handle *fmem,
     return osdep_xenforeignmemory_restrict(fmem, domid);
 }
 
+xenforeignmemory_resource_handle *xenforeignmemory_map_resource(
+    xenforeignmemory_handle *fmem, domid_t domid, unsigned int type,
+    unsigned int id, unsigned long frame, unsigned long nr_frames,
+    void **paddr, int prot, int flags)
+{
+    xenforeignmemory_resource_handle *fres;
+    int rc;
+
+    /* Check flags only contains POSIX defined values */
+    if ( flags & ~(MAP_SHARED | MAP_PRIVATE) )
+    {
+        errno = EINVAL;
+        return NULL;
+    }
+
+    fres = calloc(1, sizeof(*fres));
+    if ( !fres )
+    {
+        errno = ENOMEM;
+        return NULL;
+    }
+
+    fres->domid = domid;
+    fres->type = type;
+    fres->id = id;
+    fres->frame = frame;
+    fres->nr_frames = nr_frames;
+    fres->addr = *paddr;
+    fres->prot = prot;
+    fres->flags = flags;
+
+    rc = osdep_xenforeignmemory_map_resource(fmem, fres);
+    if ( rc )
+    {
+        free(fres);
+        fres = NULL;
+    } else
+        *paddr = fres->addr;
+
+    return fres;
+}
+
+int xenforeignmemory_unmap_resource(
+    xenforeignmemory_handle *fmem, xenforeignmemory_resource_handle *fres)
+{
+    int rc = osdep_xenforeignmemory_unmap_resource(fmem, fres);
+
+    free(fres);
+    return rc;
+}
+
 /*
  * Local variables:
  * mode: C
diff --git a/tools/libs/foreignmemory/include/xenforeignmemory.h b/tools/libs/foreignmemory/include/xenforeignmemory.h
index f4814c390f..d594be8df0 100644
--- a/tools/libs/foreignmemory/include/xenforeignmemory.h
+++ b/tools/libs/foreignmemory/include/xenforeignmemory.h
@@ -138,6 +138,47 @@ int xenforeignmemory_unmap(xenforeignmemory_handle *fmem,
 int xenforeignmemory_restrict(xenforeignmemory_handle *fmem,
                               domid_t domid);
 
+typedef struct xenforeignmemory_resource_handle xenforeignmemory_resource_handle;
+
+/**
+ * This function maps a guest resource.
+ *
+ * @parm fmem handle to the open foreignmemory interface
+ * @parm domid the domain id
+ * @parm type the resource type
+ * @parm id the type-specific resource identifier
+ * @parm frame base frame index within the resource
+ * @parm nr_frames number of frames to map
+ * @parm paddr pointer to an address passed through to mmap(2)
+ * @parm prot passed through to mmap(2)
+ * @parm POSIX-only flags passed through to mmap(2)
+ * @return pointer to foreignmemory resource handle on success, NULL on
+ *         failure
+ *
+ * *paddr is used, on entry, as a hint address for foreign map placement
+ * (see mmap(2)) so should be set to NULL if no specific placement is
+ * required. On return *paddr contains the address where the resource is
+ * mapped.
+ * As for xenforeignmemory_map2() flags is a set of additional flags
+ * for mmap(2). Not all of the flag combinations are possible due to
+ * implementation details on different platforms.
+ */
+xenforeignmemory_resource_handle *xenforeignmemory_map_resource(
+    xenforeignmemory_handle *fmem, domid_t domid, unsigned int type,
+    unsigned int id, unsigned long frame, unsigned long nr_frames,
+    void **paddr, int prot, int flags);
+
+/**
+ * This function releases a previously acquired resource.
+ *
+ * @parm fmem handle to the open foreignmemory interface
+ * @parm fres handle to the acquired resource
+ *
+ * Returns 0 on success on failure sets errno and returns -1.
+ */
+int xenforeignmemory_unmap_resource(
+    xenforeignmemory_handle *fmem, xenforeignmemory_resource_handle *fres);
+
 #endif
 
 /*
diff --git a/tools/libs/foreignmemory/libxenforeignmemory.map b/tools/libs/foreignmemory/libxenforeignmemory.map
index 716ecaf15c..d5323c87d9 100644
--- a/tools/libs/foreignmemory/libxenforeignmemory.map
+++ b/tools/libs/foreignmemory/libxenforeignmemory.map
@@ -14,3 +14,8 @@ VERS_1.2 {
 	global:
 		xenforeignmemory_map2;
 } VERS_1.1;
+VERS_1.3 {
+	global:
+		xenforeignmemory_map_resource;
+		xenforeignmemory_unmap_resource;
+} VERS_1.2;
diff --git a/tools/libs/foreignmemory/linux.c b/tools/libs/foreignmemory/linux.c
index 374e45aed5..a6b41b0b7f 100644
--- a/tools/libs/foreignmemory/linux.c
+++ b/tools/libs/foreignmemory/linux.c
@@ -277,6 +277,51 @@ int osdep_xenforeignmemory_restrict(xenforeignmemory_handle *fmem,
     return ioctl(fmem->fd, IOCTL_PRIVCMD_RESTRICT, &domid);
 }
 
+int osdep_xenforeignmemory_unmap_resource(
+    xenforeignmemory_handle *fmem, xenforeignmemory_resource_handle *fres)
+{
+    return munmap(fres->addr, fres->nr_frames << PAGE_SHIFT);
+}
+
+int osdep_xenforeignmemory_map_resource(
+    xenforeignmemory_handle *fmem, xenforeignmemory_resource_handle *fres)
+{
+    privcmd_mmap_resource_t mr = {
+        .dom = fres->domid,
+        .type = fres->type,
+        .id = fres->id,
+        .idx = fres->frame,
+        .num = fres->nr_frames,
+    };
+    int rc;
+
+    fres->addr = mmap(fres->addr, fres->nr_frames << PAGE_SHIFT,
+                      fres->prot, fres->flags | MAP_SHARED, fmem->fd, 0);
+    if ( fres->addr == MAP_FAILED )
+        return -1;
+
+    mr.addr = (uintptr_t)fres->addr;
+
+    rc = ioctl(fmem->fd, IOCTL_PRIVCMD_MMAP_RESOURCE, &mr);
+    if ( rc )
+    {
+        int saved_errno;
+
+        if ( errno != ENOTTY )
+            PERROR("ioctl failed");
+        else
+            errno = EOPNOTSUPP;
+
+        saved_errno = errno;
+        (void)osdep_xenforeignmemory_unmap_resource(fmem, fres);
+        errno = saved_errno;
+
+        return -1;
+    }
+
+    return 0;
+}
+
 /*
  * Local variables:
  * mode: C
diff --git a/tools/libs/foreignmemory/private.h b/tools/libs/foreignmemory/private.h
index 2470f3c46c..b191000b49 100644
--- a/tools/libs/foreignmemory/private.h
+++ b/tools/libs/foreignmemory/private.h
@@ -45,6 +45,37 @@ void *compat_mapforeign_batch(xenforeignmem_handle *fmem, uint32_t dom,
                               xen_pfn_t *arr, int num);
 #endif
 
+struct xenforeignmemory_resource_handle {
+    domid_t domid;
+    unsigned int type;
+    unsigned int id;
+    unsigned long frame;
+    unsigned long nr_frames;
+    void *addr;
+    int prot;
+    int flags;
+};
+
+#ifndef __linux__
+static inline int osdep_xenforeignmemory_map_resource(
+    xenforeignmemory_handle *fmem, xenforeignmemory_resource_handle *fres)
+{
+    errno = EOPNOTSUPP;
+    return -1;
+}
+
+static inline int osdep_xenforeignmemory_unmap_resource(
+    xenforeignmemory_handle *fmem, xenforeignmemory_resource_handle *fres)
+{
+    return 0;
+}
+#else
+int osdep_xenforeignmemory_map_resource(
+    xenforeignmemory_handle *fmem, xenforeignmemory_resource_handle *fres);
+int osdep_xenforeignmemory_unmap_resource(
+    xenforeignmemory_handle *fmem, xenforeignmemory_resource_handle *fres);
+#endif
+
 #define PERROR(_f...) \
     xtl_log(fmem->logger, XTL_ERROR, errno, "xenforeignmemory", _f)
 
-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* [PATCH v14 09/11] tools/libxenforeignmemory: reduce xenforeignmemory_restrict code footprint
  2017-11-28 15:08 [PATCH v14 00/11] x86: guest resource mapping Paul Durrant
                   ` (7 preceding siblings ...)
  2017-11-28 15:08 ` [PATCH v14 08/11] tools/libxenforeignmemory: add support for resource mapping Paul Durrant
@ 2017-11-28 15:08 ` Paul Durrant
  2017-11-28 15:08 ` [PATCH v14 10/11] common: add a new mappable resource type: XENMEM_resource_grant_table Paul Durrant
  2017-11-28 15:08 ` [PATCH v14 11/11] tools/libxenctrl: use new xenforeignmemory API to seed grant table Paul Durrant
  10 siblings, 0 replies; 30+ messages in thread
From: Paul Durrant @ 2017-11-28 15:08 UTC (permalink / raw)
  To: xen-devel; +Cc: Paul Durrant, Ian Jackson

By using a static inline stub in private.h for OS where this functionality
is not implemented, the various duplicate stubs in the OS-specific source
modules can be avoided.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
Acked-by: Wei Liu <wei.liu2@citrix.com>
---
Cc: Ian Jackson <ian.jackson@eu.citrix.com>

v4:
 - Removed extraneous freebsd code.

v3:
 - Patch added in response to review comments.
---
 tools/libs/foreignmemory/freebsd.c |  7 -------
 tools/libs/foreignmemory/minios.c  |  7 -------
 tools/libs/foreignmemory/netbsd.c  |  7 -------
 tools/libs/foreignmemory/private.h | 12 +++++++++---
 tools/libs/foreignmemory/solaris.c |  7 -------
 5 files changed, 9 insertions(+), 31 deletions(-)

diff --git a/tools/libs/foreignmemory/freebsd.c b/tools/libs/foreignmemory/freebsd.c
index dec447485a..6e6bc4b11f 100644
--- a/tools/libs/foreignmemory/freebsd.c
+++ b/tools/libs/foreignmemory/freebsd.c
@@ -95,13 +95,6 @@ int osdep_xenforeignmemory_unmap(xenforeignmemory_handle *fmem,
     return munmap(addr, num << PAGE_SHIFT);
 }
 
-int osdep_xenforeignmemory_restrict(xenforeignmemory_handle *fmem,
-                                    domid_t domid)
-{
-    errno = -EOPNOTSUPP;
-    return -1;
-}
-
 /*
  * Local variables:
  * mode: C
diff --git a/tools/libs/foreignmemory/minios.c b/tools/libs/foreignmemory/minios.c
index 75f340122e..43341ca301 100644
--- a/tools/libs/foreignmemory/minios.c
+++ b/tools/libs/foreignmemory/minios.c
@@ -58,13 +58,6 @@ int osdep_xenforeignmemory_unmap(xenforeignmemory_handle *fmem,
     return munmap(addr, num << PAGE_SHIFT);
 }
 
-int osdep_xenforeignmemory_restrict(xenforeignmemory_handle *fmem,
-                                    domid_t domid)
-{
-    errno = -EOPNOTSUPP;
-    return -1;
-}
-
 /*
  * Local variables:
  * mode: C
diff --git a/tools/libs/foreignmemory/netbsd.c b/tools/libs/foreignmemory/netbsd.c
index 9bf95ef4f0..54a418ebd6 100644
--- a/tools/libs/foreignmemory/netbsd.c
+++ b/tools/libs/foreignmemory/netbsd.c
@@ -100,13 +100,6 @@ int osdep_xenforeignmemory_unmap(xenforeignmemory_handle *fmem,
     return munmap(addr, num*XC_PAGE_SIZE);
 }
 
-int osdep_xenforeignmemory_restrict(xenforeignmemory_handle *fmem,
-                                    domid_t domid)
-{
-    errno = -EOPNOTSUPP;
-    return -1;
-}
-
 /*
  * Local variables:
  * mode: C
diff --git a/tools/libs/foreignmemory/private.h b/tools/libs/foreignmemory/private.h
index b191000b49..b06ce12583 100644
--- a/tools/libs/foreignmemory/private.h
+++ b/tools/libs/foreignmemory/private.h
@@ -35,9 +35,6 @@ void *osdep_xenforeignmemory_map(xenforeignmemory_handle *fmem,
 int osdep_xenforeignmemory_unmap(xenforeignmemory_handle *fmem,
                                  void *addr, size_t num);
 
-int osdep_xenforeignmemory_restrict(xenforeignmemory_handle *fmem,
-                                    domid_t domid);
-
 #if defined(__NetBSD__) || defined(__sun__)
 /* Strictly compat for those two only only */
 void *compat_mapforeign_batch(xenforeignmem_handle *fmem, uint32_t dom,
@@ -57,6 +54,13 @@ struct xenforeignmemory_resource_handle {
 };
 
 #ifndef __linux__
+static inline int osdep_xenforeignmemory_restrict(xenforeignmemory_handle *fmem,
+                                                  domid_t domid)
+{
+    errno = EOPNOTSUPP;
+    return -1;
+}
+
 static inline int osdep_xenforeignmemory_map_resource(
     xenforeignmemory_handle *fmem, xenforeignmemory_resource_handle *fres)
 {
@@ -70,6 +74,8 @@ static inline int osdep_xenforeignmemory_unmap_resource(
     return 0;
 }
 #else
+int osdep_xenforeignmemory_restrict(xenforeignmemory_handle *fmem,
+                                    domid_t domid);
 int osdep_xenforeignmemory_map_resource(
     xenforeignmemory_handle *fmem, xenforeignmemory_resource_handle *fres);
 int osdep_xenforeignmemory_unmap_resource(
diff --git a/tools/libs/foreignmemory/solaris.c b/tools/libs/foreignmemory/solaris.c
index a33decb4ae..ee8aae4fbd 100644
--- a/tools/libs/foreignmemory/solaris.c
+++ b/tools/libs/foreignmemory/solaris.c
@@ -97,13 +97,6 @@ int osdep_xenforeignmemory_unmap(xenforeignmemory_handle *fmem,
     return munmap(addr, num*XC_PAGE_SIZE);
 }
 
-int osdep_xenforeignmemory_restrict(xenforeignmemory_handle *fmem,
-                                    domid_t domid)
-{
-    errno = -EOPNOTSUPP;
-    return -1;
-}
-
 /*
  * Local variables:
  * mode: C
-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* [PATCH v14 10/11] common: add a new mappable resource type: XENMEM_resource_grant_table
  2017-11-28 15:08 [PATCH v14 00/11] x86: guest resource mapping Paul Durrant
                   ` (8 preceding siblings ...)
  2017-11-28 15:08 ` [PATCH v14 09/11] tools/libxenforeignmemory: reduce xenforeignmemory_restrict code footprint Paul Durrant
@ 2017-11-28 15:08 ` Paul Durrant
  2017-11-28 15:08 ` [PATCH v14 11/11] tools/libxenctrl: use new xenforeignmemory API to seed grant table Paul Durrant
  10 siblings, 0 replies; 30+ messages in thread
From: Paul Durrant @ 2017-11-28 15:08 UTC (permalink / raw)
  To: xen-devel
  Cc: Stefano Stabellini, Wei Liu, George Dunlap, Andrew Cooper,
	Ian Jackson, Tim Deegan, Paul Durrant

This patch allows grant table frames to be mapped using the
XENMEM_acquire_resource memory op.

NOTE: This patch expands the on-stack mfn_list array in acquire_resource()
      but it is still small enough to remain on-stack.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
---
Cc: Andrew Cooper <andrew.cooper3@citrix.com>
Cc: George Dunlap <George.Dunlap@eu.citrix.com>
Cc: Ian Jackson <ian.jackson@eu.citrix.com>
Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Tim Deegan <tim@xen.org>
Cc: Wei Liu <wei.liu2@citrix.com>

v13:
 - Re-work the internals to avoid using the XENMAPIDX_grant_table_status
   hack.

v12:
 - Dropped limit checks as requested by Jan.

v10:
 - Addressed comments from Jan.

v8:
 - The functionality was originally incorporated into the earlier patch
   "x86/mm: add HYPERVISOR_memory_op to acquire guest resources".
---
 xen/common/grant_table.c      | 63 +++++++++++++++++++++++++++++++++++++------
 xen/common/memory.c           | 45 ++++++++++++++++++++++++++++++-
 xen/include/public/memory.h   |  6 +++++
 xen/include/xen/grant_table.h |  4 +++
 4 files changed, 109 insertions(+), 9 deletions(-)

diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
index c5950f2b3f..6dc5489a47 100644
--- a/xen/common/grant_table.c
+++ b/xen/common/grant_table.c
@@ -3772,21 +3772,21 @@ int mem_sharing_gref_to_gfn(struct grant_table *gt, grant_ref_t ref,
 }
 #endif
 
-int gnttab_map_frame(struct domain *d, unsigned long idx, gfn_t gfn,
-                     mfn_t *mfn)
+/* Caller must hold write lock as version may change and table may grow */
+static int gnttab_get_frame(struct domain *d, bool is_status,
+                            unsigned long idx, mfn_t *mfn)
 {
-    int rc = 0;
     struct grant_table *gt = d->grant_table;
-
-    grant_write_lock(gt);
+    int rc = 0;
 
     if ( gt->gt_version == 0 )
         gt->gt_version = 1;
 
-    if ( gt->gt_version == 2 &&
-         (idx & XENMAPIDX_grant_table_status) )
+    if ( is_status )
     {
-        idx &= ~XENMAPIDX_grant_table_status;
+        if ( gt->gt_version != 2 )
+            return -EINVAL;
+
         if ( idx < nr_status_frames(gt) )
             *mfn = _mfn(virt_to_mfn(gt->status[idx]));
         else
@@ -3803,6 +3803,25 @@ int gnttab_map_frame(struct domain *d, unsigned long idx, gfn_t gfn,
             rc = -EINVAL;
     }
 
+    return rc;
+}
+
+int gnttab_map_frame(struct domain *d, unsigned long idx, gfn_t gfn,
+                     mfn_t *mfn)
+{
+    struct grant_table *gt = d->grant_table;
+    bool is_status = false;
+    int rc;
+
+    grant_write_lock(gt);
+
+    if ( idx & XENMAPIDX_grant_table_status )
+    {
+        is_status = true;
+        idx &= ~XENMAPIDX_grant_table_status;
+    }
+
+    rc = gnttab_get_frame(d, is_status, idx, mfn);
     if ( !rc )
         gnttab_set_frame_gfn(gt, idx, gfn);
 
@@ -3811,6 +3830,34 @@ int gnttab_map_frame(struct domain *d, unsigned long idx, gfn_t gfn,
     return rc;
 }
 
+int gnttab_get_grant_frame(struct domain *d, unsigned long idx,
+                           mfn_t *mfn)
+{
+    struct grant_table *gt = d->grant_table;
+    int rc;
+
+    /* write lock required as version may change and/or table may grow */
+    grant_write_lock(gt);
+    rc = gnttab_get_frame(d, false, idx, mfn);
+    grant_write_unlock(gt);
+
+    return rc;
+}
+
+int gnttab_get_status_frame(struct domain *d, unsigned long idx,
+                            mfn_t *mfn)
+{
+    struct grant_table *gt = d->grant_table;
+    int rc;
+
+    /* write lock required as version may change and/or table may grow */
+    grant_write_lock(gt);
+    rc = gnttab_get_frame(d, true, idx, mfn);
+    grant_write_unlock(gt);
+
+    return rc;
+}
+
 static void gnttab_usage_print(struct domain *rd)
 {
     int first = 1;
diff --git a/xen/common/memory.c b/xen/common/memory.c
index 0167d9788b..40d4264d5f 100644
--- a/xen/common/memory.c
+++ b/xen/common/memory.c
@@ -23,6 +23,7 @@
 #include <xen/numa.h>
 #include <xen/mem_access.h>
 #include <xen/trace.h>
+#include <xen/grant_table.h>
 #include <asm/current.h>
 #include <asm/hardirq.h>
 #include <asm/p2m.h>
@@ -970,6 +971,43 @@ static long xatp_permission_check(struct domain *d, unsigned int space)
     return xsm_add_to_physmap(XSM_TARGET, current->domain, d);
 }
 
+static int acquire_grant_table(struct domain *d, unsigned int id,
+                               unsigned long frame,
+                               unsigned int nr_frames,
+                               xen_pfn_t mfn_list[])
+{
+    unsigned int i = nr_frames;
+
+    /* Iterate backwards in case table needs to grow */
+    while ( i-- != 0 )
+    {
+        mfn_t mfn = INVALID_MFN;
+        int rc;
+
+        switch ( id )
+        {
+        case XENMEM_resource_grant_table_id_grant:
+            rc = gnttab_get_grant_frame(d, frame + i, &mfn);
+            break;
+
+        case XENMEM_resource_grant_table_id_status:
+            rc = gnttab_get_status_frame(d, frame + i, &mfn);
+            break;
+
+        default:
+            rc = -EINVAL;
+            break;
+        }
+
+        if ( rc )
+            return rc;
+
+        mfn_list[i] = mfn_x(mfn);
+    }
+
+    return 0;
+}
+
 static int acquire_resource(
     XEN_GUEST_HANDLE_PARAM(xen_mem_acquire_resource_t) arg)
 {
@@ -980,7 +1018,7 @@ static int acquire_resource(
      * moment since they are small, but if they need to grow in future
      * use-cases then per-CPU arrays or heap allocations may be required.
      */
-    xen_pfn_t mfn_list[2];
+    xen_pfn_t mfn_list[32];
     int rc;
 
     if ( copy_from_guest(&xmar, arg, 1) )
@@ -1015,6 +1053,11 @@ static int acquire_resource(
 
     switch ( xmar.type )
     {
+    case XENMEM_resource_grant_table:
+        rc = acquire_grant_table(d, xmar.id, xmar.frame, xmar.nr_frames,
+                                 mfn_list);
+        break;
+
     default:
         rc = arch_acquire_resource(d, xmar.type, xmar.id, xmar.frame,
                                    xmar.nr_frames, mfn_list);
diff --git a/xen/include/public/memory.h b/xen/include/public/memory.h
index 838f248a59..d4ed8ba889 100644
--- a/xen/include/public/memory.h
+++ b/xen/include/public/memory.h
@@ -611,14 +611,20 @@ struct xen_mem_acquire_resource {
     uint16_t type;
 
 #define XENMEM_resource_ioreq_server 0
+#define XENMEM_resource_grant_table 1
 
     /*
      * IN - a type-specific resource identifier, which must be zero
      *      unless stated otherwise.
      *
      * type == XENMEM_resource_ioreq_server -> id == ioreq server id
+     * type == XENMEM_resource_grant_table -> id defined below
      */
     uint32_t id;
+
+#define XENMEM_resource_grant_table_id_grant 0
+#define XENMEM_resource_grant_table_id_status 1
+
     /* IN/OUT - As an IN parameter number of frames of the resource
      *          to be mapped. However, if the specified value is 0 and
      *          frame_list is NULL then this field will be set to the
diff --git a/xen/include/xen/grant_table.h b/xen/include/xen/grant_table.h
index b3a95fda58..e9125e43e7 100644
--- a/xen/include/xen/grant_table.h
+++ b/xen/include/xen/grant_table.h
@@ -55,6 +55,10 @@ int mem_sharing_gref_to_gfn(struct grant_table *gt, grant_ref_t ref,
 
 int gnttab_map_frame(struct domain *d, unsigned long idx, gfn_t gfn,
                      mfn_t *mfn);
+int gnttab_get_grant_frame(struct domain *d, unsigned long idx,
+                           mfn_t *mfn);
+int gnttab_get_status_frame(struct domain *d, unsigned long idx,
+                            mfn_t *mfn);
 
 unsigned int gnttab_dom0_frames(void);
 
-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* [PATCH v14 11/11] tools/libxenctrl: use new xenforeignmemory API to seed grant table
  2017-11-28 15:08 [PATCH v14 00/11] x86: guest resource mapping Paul Durrant
                   ` (9 preceding siblings ...)
  2017-11-28 15:08 ` [PATCH v14 10/11] common: add a new mappable resource type: XENMEM_resource_grant_table Paul Durrant
@ 2017-11-28 15:08 ` Paul Durrant
  10 siblings, 0 replies; 30+ messages in thread
From: Paul Durrant @ 2017-11-28 15:08 UTC (permalink / raw)
  To: xen-devel; +Cc: Paul Durrant, Ian Jackson

A previous patch added support for priv-mapping guest resources directly
(rather than having to foreign-map, which requires P2M modification for
HVM guests).

This patch makes use of the new API to seed the guest grant table unless
the underlying infrastructure (i.e. privcmd) doesn't support it, in which
case the old scheme is used.

NOTE: The call to xc_dom_gnttab_hvm_seed() in hvm_build_set_params() was
      actually unnecessary, as the grant table has already been seeded
      by a prior call to xc_dom_gnttab_init() made by libxl__build_dom().

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
Acked-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
Acked-by: Wei Liu <wei.liu2@citrix.com>
---
Cc: Ian Jackson <ian.jackson@eu.citrix.com>

v13:
 - Re-base.

v10:
 - Use new id constant for grant table.

v4:
 - Minor cosmetic fix suggested by Roger.

v3:
 - Introduced xc_dom_set_gnttab_entry() to avoid duplicated code.
---
 tools/libxc/include/xc_dom.h        |   8 +--
 tools/libxc/xc_dom_boot.c           | 114 +++++++++++++++++++++++++-----------
 tools/libxc/xc_sr_restore_x86_hvm.c |  10 ++--
 tools/libxc/xc_sr_restore_x86_pv.c  |   2 +-
 tools/libxl/libxl_dom.c             |   1 -
 tools/python/xen/lowlevel/xc/xc.c   |   6 +-
 6 files changed, 92 insertions(+), 49 deletions(-)

diff --git a/tools/libxc/include/xc_dom.h b/tools/libxc/include/xc_dom.h
index cdcdd07d2b..45c9d676c7 100644
--- a/tools/libxc/include/xc_dom.h
+++ b/tools/libxc/include/xc_dom.h
@@ -325,12 +325,8 @@ void *xc_dom_boot_domU_map(struct xc_dom_image *dom, xen_pfn_t pfn,
 int xc_dom_boot_image(struct xc_dom_image *dom);
 int xc_dom_compat_check(struct xc_dom_image *dom);
 int xc_dom_gnttab_init(struct xc_dom_image *dom);
-int xc_dom_gnttab_hvm_seed(xc_interface *xch, uint32_t domid,
-                           xen_pfn_t console_gmfn,
-                           xen_pfn_t xenstore_gmfn,
-                           uint32_t console_domid,
-                           uint32_t xenstore_domid);
-int xc_dom_gnttab_seed(xc_interface *xch, uint32_t domid,
+int xc_dom_gnttab_seed(xc_interface *xch, uint32_t guest_domid,
+                       bool is_hvm,
                        xen_pfn_t console_gmfn,
                        xen_pfn_t xenstore_gmfn,
                        uint32_t console_domid,
diff --git a/tools/libxc/xc_dom_boot.c b/tools/libxc/xc_dom_boot.c
index 2e5681dc5d..a779422ac3 100644
--- a/tools/libxc/xc_dom_boot.c
+++ b/tools/libxc/xc_dom_boot.c
@@ -256,11 +256,29 @@ static xen_pfn_t xc_dom_gnttab_setup(xc_interface *xch, uint32_t domid)
     return gmfn;
 }
 
-int xc_dom_gnttab_seed(xc_interface *xch, uint32_t domid,
-                       xen_pfn_t console_gmfn,
-                       xen_pfn_t xenstore_gmfn,
-                       uint32_t console_domid,
-                       uint32_t xenstore_domid)
+static void xc_dom_set_gnttab_entry(xc_interface *xch,
+                                    grant_entry_v1_t *gnttab,
+                                    unsigned int idx,
+                                    uint32_t guest_domid,
+                                    uint32_t backend_domid,
+                                    xen_pfn_t backend_gmfn)
+{
+    if ( guest_domid == backend_domid || backend_gmfn == -1)
+        return;
+
+    xc_dom_printf(xch, "%s: [%u] -> 0x%"PRI_xen_pfn,
+                  __FUNCTION__, idx, backend_gmfn);
+
+    gnttab[idx].flags = GTF_permit_access;
+    gnttab[idx].domid = backend_domid;
+    gnttab[idx].frame = backend_gmfn;
+}
+
+static int compat_gnttab_seed(xc_interface *xch, uint32_t domid,
+                              xen_pfn_t console_gmfn,
+                              xen_pfn_t xenstore_gmfn,
+                              uint32_t console_domid,
+                              uint32_t xenstore_domid)
 {
 
     xen_pfn_t gnttab_gmfn;
@@ -284,18 +302,10 @@ int xc_dom_gnttab_seed(xc_interface *xch, uint32_t domid,
         return -1;
     }
 
-    if ( domid != console_domid  && console_gmfn != -1)
-    {
-        gnttab[GNTTAB_RESERVED_CONSOLE].flags = GTF_permit_access;
-        gnttab[GNTTAB_RESERVED_CONSOLE].domid = console_domid;
-        gnttab[GNTTAB_RESERVED_CONSOLE].frame = console_gmfn;
-    }
-    if ( domid != xenstore_domid && xenstore_gmfn != -1)
-    {
-        gnttab[GNTTAB_RESERVED_XENSTORE].flags = GTF_permit_access;
-        gnttab[GNTTAB_RESERVED_XENSTORE].domid = xenstore_domid;
-        gnttab[GNTTAB_RESERVED_XENSTORE].frame = xenstore_gmfn;
-    }
+    xc_dom_set_gnttab_entry(xch, gnttab, GNTTAB_RESERVED_CONSOLE,
+                            domid, console_domid, console_gmfn);
+    xc_dom_set_gnttab_entry(xch, gnttab, GNTTAB_RESERVED_XENSTORE,
+                            domid, xenstore_domid, xenstore_gmfn);
 
     if ( munmap(gnttab, PAGE_SIZE) == -1 )
     {
@@ -313,11 +323,11 @@ int xc_dom_gnttab_seed(xc_interface *xch, uint32_t domid,
     return 0;
 }
 
-int xc_dom_gnttab_hvm_seed(xc_interface *xch, uint32_t domid,
-                           xen_pfn_t console_gpfn,
-                           xen_pfn_t xenstore_gpfn,
-                           uint32_t console_domid,
-                           uint32_t xenstore_domid)
+static int compat_gnttab_hvm_seed(xc_interface *xch, uint32_t domid,
+                                  xen_pfn_t console_gpfn,
+                                  xen_pfn_t xenstore_gpfn,
+                                  uint32_t console_domid,
+                                  uint32_t xenstore_domid)
 {
     int rc;
     xen_pfn_t scratch_gpfn;
@@ -356,7 +366,7 @@ int xc_dom_gnttab_hvm_seed(xc_interface *xch, uint32_t domid,
         return -1;
     }
 
-    rc = xc_dom_gnttab_seed(xch, domid,
+    rc = compat_gnttab_seed(xch, domid,
                             console_gpfn, xenstore_gpfn,
                             console_domid, xenstore_domid);
     if (rc != 0)
@@ -381,18 +391,56 @@ int xc_dom_gnttab_hvm_seed(xc_interface *xch, uint32_t domid,
     return 0;
 }
 
-int xc_dom_gnttab_init(struct xc_dom_image *dom)
+int xc_dom_gnttab_seed(xc_interface *xch, uint32_t guest_domid,
+                       bool is_hvm, xen_pfn_t console_gmfn,
+                       xen_pfn_t xenstore_gmfn, uint32_t console_domid,
+                       uint32_t xenstore_domid)
 {
-    if ( xc_dom_translated(dom) ) {
-        return xc_dom_gnttab_hvm_seed(dom->xch, dom->guest_domid,
-                                      dom->console_pfn, dom->xenstore_pfn,
-                                      dom->console_domid, dom->xenstore_domid);
-    } else {
-        return xc_dom_gnttab_seed(dom->xch, dom->guest_domid,
-                                  xc_dom_p2m(dom, dom->console_pfn),
-                                  xc_dom_p2m(dom, dom->xenstore_pfn),
-                                  dom->console_domid, dom->xenstore_domid);
+    xenforeignmemory_handle* fmem = xch->fmem;
+    xenforeignmemory_resource_handle *fres;
+    void *addr = NULL;
+
+    fres = xenforeignmemory_map_resource(
+        fmem, guest_domid, XENMEM_resource_grant_table,
+        XENMEM_resource_grant_table_id_grant, 0, 1, &addr,
+        PROT_READ | PROT_WRITE, 0);
+    if ( !fres )
+    {
+        if ( errno == EOPNOTSUPP )
+            return is_hvm ?
+                compat_gnttab_hvm_seed(xch, guest_domid,
+                                       console_gmfn, xenstore_gmfn,
+                                       console_domid, xenstore_domid) :
+                compat_gnttab_seed(xch, guest_domid,
+                                   console_gmfn, xenstore_gmfn,
+                                   console_domid, xenstore_domid);
+
+        xc_dom_panic(xch, XC_INTERNAL_ERROR,
+                     "%s: failed to acquire grant table "
+                     "[errno=%d]\n",
+                     __FUNCTION__, errno);
+        return -1;
     }
+
+    xc_dom_set_gnttab_entry(xch, addr, GNTTAB_RESERVED_CONSOLE,
+                            guest_domid, console_domid, console_gmfn);
+    xc_dom_set_gnttab_entry(xch, addr, GNTTAB_RESERVED_XENSTORE,
+                            guest_domid, xenstore_domid, xenstore_gmfn);
+
+    xenforeignmemory_unmap_resource(fmem, fres);
+
+    return 0;
+}
+
+int xc_dom_gnttab_init(struct xc_dom_image *dom)
+{
+    bool is_hvm = xc_dom_translated(dom);
+    xen_pfn_t console_gmfn = xc_dom_p2m(dom, dom->console_pfn);
+    xen_pfn_t xenstore_gmfn = xc_dom_p2m(dom, dom->xenstore_pfn);
+
+    return xc_dom_gnttab_seed(dom->xch, dom->guest_domid, is_hvm,
+                              console_gmfn, xenstore_gmfn,
+                              dom->console_domid, dom->xenstore_domid);
 }
 
 /*
diff --git a/tools/libxc/xc_sr_restore_x86_hvm.c b/tools/libxc/xc_sr_restore_x86_hvm.c
index 227c48553e..4765a52f33 100644
--- a/tools/libxc/xc_sr_restore_x86_hvm.c
+++ b/tools/libxc/xc_sr_restore_x86_hvm.c
@@ -216,11 +216,11 @@ static int x86_hvm_stream_complete(struct xc_sr_context *ctx)
         return rc;
     }
 
-    rc = xc_dom_gnttab_hvm_seed(xch, ctx->domid,
-                                ctx->restore.console_gfn,
-                                ctx->restore.xenstore_gfn,
-                                ctx->restore.console_domid,
-                                ctx->restore.xenstore_domid);
+    rc = xc_dom_gnttab_seed(xch, ctx->domid, true,
+                            ctx->restore.console_gfn,
+                            ctx->restore.xenstore_gfn,
+                            ctx->restore.console_domid,
+                            ctx->restore.xenstore_domid);
     if ( rc )
     {
         PERROR("Failed to seed grant table");
diff --git a/tools/libxc/xc_sr_restore_x86_pv.c b/tools/libxc/xc_sr_restore_x86_pv.c
index ed0fd0ead9..49e135006c 100644
--- a/tools/libxc/xc_sr_restore_x86_pv.c
+++ b/tools/libxc/xc_sr_restore_x86_pv.c
@@ -1104,7 +1104,7 @@ static int x86_pv_stream_complete(struct xc_sr_context *ctx)
     if ( rc )
         return rc;
 
-    rc = xc_dom_gnttab_seed(xch, ctx->domid,
+    rc = xc_dom_gnttab_seed(xch, ctx->domid, false,
                             ctx->restore.console_gfn,
                             ctx->restore.xenstore_gfn,
                             ctx->restore.console_domid,
diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c
index ef834e652d..86f562549e 100644
--- a/tools/libxl/libxl_dom.c
+++ b/tools/libxl/libxl_dom.c
@@ -903,7 +903,6 @@ static int hvm_build_set_params(xc_interface *handle, uint32_t domid,
     *store_mfn = str_mfn;
     *console_mfn = cons_mfn;
 
-    xc_dom_gnttab_hvm_seed(handle, domid, *console_mfn, *store_mfn, console_domid, store_domid);
     return 0;
 }
 
diff --git a/tools/python/xen/lowlevel/xc/xc.c b/tools/python/xen/lowlevel/xc/xc.c
index f501764100..51dc2afb1e 100644
--- a/tools/python/xen/lowlevel/xc/xc.c
+++ b/tools/python/xen/lowlevel/xc/xc.c
@@ -800,9 +800,9 @@ static PyObject *pyxc_gnttab_hvm_seed(XcObject *self,
 				      &console_domid, &xenstore_domid) )
         return NULL;
 
-    if ( xc_dom_gnttab_hvm_seed(self->xc_handle, dom,
-				console_gmfn, xenstore_gmfn,
-				console_domid, xenstore_domid) != 0 )
+    if ( xc_dom_gnttab_seed(self->xc_handle, dom, true,
+                            console_gmfn, xenstore_gmfn,
+                            console_domid, xenstore_domid) != 0 )
         return pyxc_error_to_exception(self->xc_handle);
 
     return Py_None;
-- 
2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v14 05/11] x86/mm: add HYPERVISOR_memory_op to acquire guest resources
  2017-11-28 15:08 ` [PATCH v14 05/11] x86/mm: add HYPERVISOR_memory_op to acquire guest resources Paul Durrant
@ 2017-11-28 18:50   ` Daniel De Graaf
  0 siblings, 0 replies; 30+ messages in thread
From: Daniel De Graaf @ 2017-11-28 18:50 UTC (permalink / raw)
  To: Paul Durrant, xen-devel
  Cc: Stefano Stabellini, Wei Liu, George Dunlap, Andrew Cooper,
	Tim Deegan, Julien Grall, Ian Jackson

On 11/28/2017 10:08 AM, Paul Durrant wrote:
> Certain memory resources associated with a guest are not necessarily
> present in the guest P2M.
> 
> This patch adds the boilerplate for new memory op to allow such a resource
> to be priv-mapped directly, by either a PV or HVM tools domain.
> 
> NOTE: Whilst the new op is not intrinsicly specific to the x86 architecture,
>        I have no means to test it on an ARM platform and so cannot verify
>        that it functions correctly.
> 
> Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
> Reviewed-by: Jan Beulich <jbeulich@suse.com>

Acked-by: Daniel De Graaf <dgdegra@tycho.nsa.gov>

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v14 04/11] x86/hvm/ioreq: defer mapping gfns until they are actually requsted
  2017-11-28 15:08 ` [PATCH v14 04/11] x86/hvm/ioreq: defer mapping gfns until they are actually requsted Paul Durrant
@ 2017-12-06 21:49   ` Chao Gao
  2017-12-07  8:38     ` Paul Durrant
  0 siblings, 1 reply; 30+ messages in thread
From: Chao Gao @ 2017-12-06 21:49 UTC (permalink / raw)
  To: Paul Durrant
  Cc: Stefano Stabellini, George Dunlap, Ian Jackson, Tim Deegan,
	Andrew Cooper, xen-devel

On Tue, Nov 28, 2017 at 03:08:46PM +0000, Paul Durrant wrote:
>A subsequent patch will introduce a new scheme to allow an emulator to
>map ioreq server pages directly from Xen rather than the guest P2M.
>
>This patch lays the groundwork for that change by deferring mapping of
>gfns until their values are requested by an emulator. To that end, the
>pad field of the xen_dm_op_get_ioreq_server_info structure is re-purposed
>to a flags field and new flag, XEN_DMOP_no_gfns, defined which modifies the
>behaviour of XEN_DMOP_get_ioreq_server_info to allow the caller to avoid
>requesting the gfn values.
>
>Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
>Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
>Acked-by: Wei Liu <wei.liu2@citrix.com>
>Reviewed-by: Jan Beulich <jbeulich@suse.com>
>---
>Cc: Ian Jackson <ian.jackson@eu.citrix.com>
>Cc: Andrew Cooper <andrew.cooper3@citrix.com>
>Cc: George Dunlap <George.Dunlap@eu.citrix.com>
>Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
>Cc: Stefano Stabellini <sstabellini@kernel.org>
>Cc: Tim Deegan <tim@xen.org>
>
>v8:
> - For safety make all of the pointers passed to
>   hvm_get_ioreq_server_info() optional.
> - Shrink bufioreq_handling down to a uint8_t.
>
>v3:
> - Updated in response to review comments from Wei and Roger.
> - Added a HANDLE_BUFIOREQ macro to make the code neater.
> - This patch no longer introduces a security vulnerability since there
>   is now an explicit limit on the number of ioreq servers that may be
>   created for any one domain.
>---
> tools/libs/devicemodel/core.c                   |  8 +++++
> tools/libs/devicemodel/include/xendevicemodel.h |  6 ++--
> xen/arch/x86/hvm/dm.c                           |  9 +++--
> xen/arch/x86/hvm/ioreq.c                        | 47 ++++++++++++++-----------
> xen/include/asm-x86/hvm/domain.h                |  2 +-
> xen/include/public/hvm/dm_op.h                  | 32 ++++++++++-------
> 6 files changed, 63 insertions(+), 41 deletions(-)
>
>diff --git a/tools/libs/devicemodel/core.c b/tools/libs/devicemodel/core.c
>index b66d4f9294..e684e657b6 100644
>--- a/tools/libs/devicemodel/core.c
>+++ b/tools/libs/devicemodel/core.c
>@@ -204,6 +204,14 @@ int xendevicemodel_get_ioreq_server_info(
> 
>     data->id = id;
> 
>+    /*
>+     * If the caller is not requesting gfn values then instruct the
>+     * hypercall not to retrieve them as this may cause them to be
>+     * mapped.
>+     */
>+    if (!ioreq_gfn && !bufioreq_gfn)
>+        data->flags |= XEN_DMOP_no_gfns;
>+
>     rc = xendevicemodel_op(dmod, domid, 1, &op, sizeof(op));
>     if (rc)
>         return rc;
>diff --git a/tools/libs/devicemodel/include/xendevicemodel.h b/tools/libs/devicemodel/include/xendevicemodel.h
>index dda0bc7695..fffee3a4a0 100644
>--- a/tools/libs/devicemodel/include/xendevicemodel.h
>+++ b/tools/libs/devicemodel/include/xendevicemodel.h
>@@ -61,11 +61,11 @@ int xendevicemodel_create_ioreq_server(
>  * @parm domid the domain id to be serviced
>  * @parm id the IOREQ Server id.
>  * @parm ioreq_gfn pointer to a xen_pfn_t to receive the synchronous ioreq
>- *                  gfn
>+ *                  gfn. (May be NULL if not required)
>  * @parm bufioreq_gfn pointer to a xen_pfn_t to receive the buffered ioreq
>- *                    gfn
>+ *                    gfn. (May be NULL if not required)
>  * @parm bufioreq_port pointer to a evtchn_port_t to receive the buffered
>- *                     ioreq event channel
>+ *                     ioreq event channel. (May be NULL if not required)
>  * @return 0 on success, -1 on failure.
>  */
> int xendevicemodel_get_ioreq_server_info(
>diff --git a/xen/arch/x86/hvm/dm.c b/xen/arch/x86/hvm/dm.c
>index a787f43737..3c617bd754 100644
>--- a/xen/arch/x86/hvm/dm.c
>+++ b/xen/arch/x86/hvm/dm.c
>@@ -416,16 +416,19 @@ static int dm_op(const struct dmop_args *op_args)
>     {
>         struct xen_dm_op_get_ioreq_server_info *data =
>             &op.u.get_ioreq_server_info;
>+        const uint16_t valid_flags = XEN_DMOP_no_gfns;
> 
>         const_op = false;
> 
>         rc = -EINVAL;
>-        if ( data->pad )
>+        if ( data->flags & ~valid_flags )
>             break;
> 
>         rc = hvm_get_ioreq_server_info(d, data->id,
>-                                       &data->ioreq_gfn,
>-                                       &data->bufioreq_gfn,
>+                                       (data->flags & XEN_DMOP_no_gfns) ?
>+                                       NULL : &data->ioreq_gfn,
>+                                       (data->flags & XEN_DMOP_no_gfns) ?
>+                                       NULL : &data->bufioreq_gfn,
>                                        &data->bufioreq_port);
>         break;
>     }
>diff --git a/xen/arch/x86/hvm/ioreq.c b/xen/arch/x86/hvm/ioreq.c
>index eec4e4771e..39de659ddf 100644
>--- a/xen/arch/x86/hvm/ioreq.c
>+++ b/xen/arch/x86/hvm/ioreq.c
>@@ -350,6 +350,9 @@ static void hvm_update_ioreq_evtchn(struct hvm_ioreq_server *s,
>     }
> }
> 
>+#define HANDLE_BUFIOREQ(s) \
>+    ((s)->bufioreq_handling != HVM_IOREQSRV_BUFIOREQ_OFF)
>+
> static int hvm_ioreq_server_add_vcpu(struct hvm_ioreq_server *s,
>                                      struct vcpu *v)
> {
>@@ -371,7 +374,7 @@ static int hvm_ioreq_server_add_vcpu(struct hvm_ioreq_server *s,
> 
>     sv->ioreq_evtchn = rc;
> 
>-    if ( v->vcpu_id == 0 && s->bufioreq.va != NULL )
>+    if ( v->vcpu_id == 0 && HANDLE_BUFIOREQ(s) )
>     {
>         struct domain *d = s->domain;
> 
>@@ -422,7 +425,7 @@ static void hvm_ioreq_server_remove_vcpu(struct hvm_ioreq_server *s,
> 
>         list_del(&sv->list_entry);
> 
>-        if ( v->vcpu_id == 0 && s->bufioreq.va != NULL )
>+        if ( v->vcpu_id == 0 && HANDLE_BUFIOREQ(s) )
>             free_xen_event_channel(v->domain, s->bufioreq_evtchn);
> 
>         free_xen_event_channel(v->domain, sv->ioreq_evtchn);
>@@ -449,7 +452,7 @@ static void hvm_ioreq_server_remove_all_vcpus(struct hvm_ioreq_server *s)
> 
>         list_del(&sv->list_entry);
> 
>-        if ( v->vcpu_id == 0 && s->bufioreq.va != NULL )
>+        if ( v->vcpu_id == 0 && HANDLE_BUFIOREQ(s) )
>             free_xen_event_channel(v->domain, s->bufioreq_evtchn);
> 
>         free_xen_event_channel(v->domain, sv->ioreq_evtchn);
>@@ -460,14 +463,13 @@ static void hvm_ioreq_server_remove_all_vcpus(struct hvm_ioreq_server *s)
>     spin_unlock(&s->lock);
> }
> 
>-static int hvm_ioreq_server_map_pages(struct hvm_ioreq_server *s,
>-                                      bool handle_bufioreq)
>+static int hvm_ioreq_server_map_pages(struct hvm_ioreq_server *s)
> {
>     int rc;
> 
>     rc = hvm_map_ioreq_gfn(s, false);
> 
>-    if ( !rc && handle_bufioreq )
>+    if ( !rc && HANDLE_BUFIOREQ(s) )
>         rc = hvm_map_ioreq_gfn(s, true);
> 
>     if ( rc )
>@@ -597,13 +599,7 @@ static int hvm_ioreq_server_init(struct hvm_ioreq_server *s,
>     if ( rc )
>         return rc;
> 
>-    if ( bufioreq_handling == HVM_IOREQSRV_BUFIOREQ_ATOMIC )
>-        s->bufioreq_atomic = true;
>-
>-    rc = hvm_ioreq_server_map_pages(
>-             s, bufioreq_handling != HVM_IOREQSRV_BUFIOREQ_OFF);

It seems that for default IO server, mapping gfns here is required. Old
qemu won't call hvm_get_ioreq_server_info() (and cannot because of the
assertion 'ASSERT(!IS_DEFAULT(s))') to set up the mapping.

Thanks
Chao

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v14 04/11] x86/hvm/ioreq: defer mapping gfns until they are actually requsted
  2017-12-06 21:49   ` Chao Gao
@ 2017-12-07  8:38     ` Paul Durrant
  0 siblings, 0 replies; 30+ messages in thread
From: Paul Durrant @ 2017-12-07  8:38 UTC (permalink / raw)
  To: 'Chao Gao'
  Cc: Stefano Stabellini, Andrew Cooper, Tim (Xen.org),
	George Dunlap, Ian Jackson, xen-devel

> -----Original Message-----
> From: Chao Gao [mailto:chao.gao@intel.com]
> Sent: 06 December 2017 21:50
> To: Paul Durrant <Paul.Durrant@citrix.com>
> Cc: xen-devel@lists.xenproject.org; Stefano Stabellini
> <sstabellini@kernel.org>; George Dunlap <George.Dunlap@citrix.com>;
> Andrew Cooper <Andrew.Cooper3@citrix.com>; Ian Jackson
> <Ian.Jackson@citrix.com>; Tim (Xen.org) <tim@xen.org>
> Subject: Re: [Xen-devel] [PATCH v14 04/11] x86/hvm/ioreq: defer mapping
> gfns until they are actually requsted
> 
> On Tue, Nov 28, 2017 at 03:08:46PM +0000, Paul Durrant wrote:
> >A subsequent patch will introduce a new scheme to allow an emulator to
> >map ioreq server pages directly from Xen rather than the guest P2M.
> >
> >This patch lays the groundwork for that change by deferring mapping of
> >gfns until their values are requested by an emulator. To that end, the
> >pad field of the xen_dm_op_get_ioreq_server_info structure is re-
> purposed
> >to a flags field and new flag, XEN_DMOP_no_gfns, defined which modifies
> the
> >behaviour of XEN_DMOP_get_ioreq_server_info to allow the caller to
> avoid
> >requesting the gfn values.
> >
> >Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
> >Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
> >Acked-by: Wei Liu <wei.liu2@citrix.com>
> >Reviewed-by: Jan Beulich <jbeulich@suse.com>
> >---
> >Cc: Ian Jackson <ian.jackson@eu.citrix.com>
> >Cc: Andrew Cooper <andrew.cooper3@citrix.com>
> >Cc: George Dunlap <George.Dunlap@eu.citrix.com>
> >Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> >Cc: Stefano Stabellini <sstabellini@kernel.org>
> >Cc: Tim Deegan <tim@xen.org>
> >
> >v8:
> > - For safety make all of the pointers passed to
> >   hvm_get_ioreq_server_info() optional.
> > - Shrink bufioreq_handling down to a uint8_t.
> >
> >v3:
> > - Updated in response to review comments from Wei and Roger.
> > - Added a HANDLE_BUFIOREQ macro to make the code neater.
> > - This patch no longer introduces a security vulnerability since there
> >   is now an explicit limit on the number of ioreq servers that may be
> >   created for any one domain.
> >---
> > tools/libs/devicemodel/core.c                   |  8 +++++
> > tools/libs/devicemodel/include/xendevicemodel.h |  6 ++--
> > xen/arch/x86/hvm/dm.c                           |  9 +++--
> > xen/arch/x86/hvm/ioreq.c                        | 47 ++++++++++++++-----------
> > xen/include/asm-x86/hvm/domain.h                |  2 +-
> > xen/include/public/hvm/dm_op.h                  | 32 ++++++++++-------
> > 6 files changed, 63 insertions(+), 41 deletions(-)
> >
> >diff --git a/tools/libs/devicemodel/core.c b/tools/libs/devicemodel/core.c
> >index b66d4f9294..e684e657b6 100644
> >--- a/tools/libs/devicemodel/core.c
> >+++ b/tools/libs/devicemodel/core.c
> >@@ -204,6 +204,14 @@ int xendevicemodel_get_ioreq_server_info(
> >
> >     data->id = id;
> >
> >+    /*
> >+     * If the caller is not requesting gfn values then instruct the
> >+     * hypercall not to retrieve them as this may cause them to be
> >+     * mapped.
> >+     */
> >+    if (!ioreq_gfn && !bufioreq_gfn)
> >+        data->flags |= XEN_DMOP_no_gfns;
> >+
> >     rc = xendevicemodel_op(dmod, domid, 1, &op, sizeof(op));
> >     if (rc)
> >         return rc;
> >diff --git a/tools/libs/devicemodel/include/xendevicemodel.h
> b/tools/libs/devicemodel/include/xendevicemodel.h
> >index dda0bc7695..fffee3a4a0 100644
> >--- a/tools/libs/devicemodel/include/xendevicemodel.h
> >+++ b/tools/libs/devicemodel/include/xendevicemodel.h
> >@@ -61,11 +61,11 @@ int xendevicemodel_create_ioreq_server(
> >  * @parm domid the domain id to be serviced
> >  * @parm id the IOREQ Server id.
> >  * @parm ioreq_gfn pointer to a xen_pfn_t to receive the synchronous
> ioreq
> >- *                  gfn
> >+ *                  gfn. (May be NULL if not required)
> >  * @parm bufioreq_gfn pointer to a xen_pfn_t to receive the buffered
> ioreq
> >- *                    gfn
> >+ *                    gfn. (May be NULL if not required)
> >  * @parm bufioreq_port pointer to a evtchn_port_t to receive the
> buffered
> >- *                     ioreq event channel
> >+ *                     ioreq event channel. (May be NULL if not required)
> >  * @return 0 on success, -1 on failure.
> >  */
> > int xendevicemodel_get_ioreq_server_info(
> >diff --git a/xen/arch/x86/hvm/dm.c b/xen/arch/x86/hvm/dm.c
> >index a787f43737..3c617bd754 100644
> >--- a/xen/arch/x86/hvm/dm.c
> >+++ b/xen/arch/x86/hvm/dm.c
> >@@ -416,16 +416,19 @@ static int dm_op(const struct dmop_args
> *op_args)
> >     {
> >         struct xen_dm_op_get_ioreq_server_info *data =
> >             &op.u.get_ioreq_server_info;
> >+        const uint16_t valid_flags = XEN_DMOP_no_gfns;
> >
> >         const_op = false;
> >
> >         rc = -EINVAL;
> >-        if ( data->pad )
> >+        if ( data->flags & ~valid_flags )
> >             break;
> >
> >         rc = hvm_get_ioreq_server_info(d, data->id,
> >-                                       &data->ioreq_gfn,
> >-                                       &data->bufioreq_gfn,
> >+                                       (data->flags & XEN_DMOP_no_gfns) ?
> >+                                       NULL : &data->ioreq_gfn,
> >+                                       (data->flags & XEN_DMOP_no_gfns) ?
> >+                                       NULL : &data->bufioreq_gfn,
> >                                        &data->bufioreq_port);
> >         break;
> >     }
> >diff --git a/xen/arch/x86/hvm/ioreq.c b/xen/arch/x86/hvm/ioreq.c
> >index eec4e4771e..39de659ddf 100644
> >--- a/xen/arch/x86/hvm/ioreq.c
> >+++ b/xen/arch/x86/hvm/ioreq.c
> >@@ -350,6 +350,9 @@ static void hvm_update_ioreq_evtchn(struct
> hvm_ioreq_server *s,
> >     }
> > }
> >
> >+#define HANDLE_BUFIOREQ(s) \
> >+    ((s)->bufioreq_handling != HVM_IOREQSRV_BUFIOREQ_OFF)
> >+
> > static int hvm_ioreq_server_add_vcpu(struct hvm_ioreq_server *s,
> >                                      struct vcpu *v)
> > {
> >@@ -371,7 +374,7 @@ static int hvm_ioreq_server_add_vcpu(struct
> hvm_ioreq_server *s,
> >
> >     sv->ioreq_evtchn = rc;
> >
> >-    if ( v->vcpu_id == 0 && s->bufioreq.va != NULL )
> >+    if ( v->vcpu_id == 0 && HANDLE_BUFIOREQ(s) )
> >     {
> >         struct domain *d = s->domain;
> >
> >@@ -422,7 +425,7 @@ static void hvm_ioreq_server_remove_vcpu(struct
> hvm_ioreq_server *s,
> >
> >         list_del(&sv->list_entry);
> >
> >-        if ( v->vcpu_id == 0 && s->bufioreq.va != NULL )
> >+        if ( v->vcpu_id == 0 && HANDLE_BUFIOREQ(s) )
> >             free_xen_event_channel(v->domain, s->bufioreq_evtchn);
> >
> >         free_xen_event_channel(v->domain, sv->ioreq_evtchn);
> >@@ -449,7 +452,7 @@ static void
> hvm_ioreq_server_remove_all_vcpus(struct hvm_ioreq_server *s)
> >
> >         list_del(&sv->list_entry);
> >
> >-        if ( v->vcpu_id == 0 && s->bufioreq.va != NULL )
> >+        if ( v->vcpu_id == 0 && HANDLE_BUFIOREQ(s) )
> >             free_xen_event_channel(v->domain, s->bufioreq_evtchn);
> >
> >         free_xen_event_channel(v->domain, sv->ioreq_evtchn);
> >@@ -460,14 +463,13 @@ static void
> hvm_ioreq_server_remove_all_vcpus(struct hvm_ioreq_server *s)
> >     spin_unlock(&s->lock);
> > }
> >
> >-static int hvm_ioreq_server_map_pages(struct hvm_ioreq_server *s,
> >-                                      bool handle_bufioreq)
> >+static int hvm_ioreq_server_map_pages(struct hvm_ioreq_server *s)
> > {
> >     int rc;
> >
> >     rc = hvm_map_ioreq_gfn(s, false);
> >
> >-    if ( !rc && handle_bufioreq )
> >+    if ( !rc && HANDLE_BUFIOREQ(s) )
> >         rc = hvm_map_ioreq_gfn(s, true);
> >
> >     if ( rc )
> >@@ -597,13 +599,7 @@ static int hvm_ioreq_server_init(struct
> hvm_ioreq_server *s,
> >     if ( rc )
> >         return rc;
> >
> >-    if ( bufioreq_handling == HVM_IOREQSRV_BUFIOREQ_ATOMIC )
> >-        s->bufioreq_atomic = true;
> >-
> >-    rc = hvm_ioreq_server_map_pages(
> >-             s, bufioreq_handling != HVM_IOREQSRV_BUFIOREQ_OFF);
> 
> It seems that for default IO server, mapping gfns here is required. Old
> qemu won't call hvm_get_ioreq_server_info() (and cannot because of the
> assertion 'ASSERT(!IS_DEFAULT(s))') to set up the mapping.

Yes. Old qemu has no knowledge of the ioreq server API so the 'default' ioreq server is there to accommodate it. Again this is all legacy code so no need to extend it.

  Paul

> 
> Thanks
> Chao

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v14 07/11] x86/mm: add an extra command to HYPERVISOR_mmu_update...
  2017-11-28 15:08 ` [PATCH v14 07/11] x86/mm: add an extra command to HYPERVISOR_mmu_update Paul Durrant
@ 2017-12-12 13:25   ` Jan Beulich
  2017-12-12 13:52     ` Andrew Cooper
  2017-12-12 14:54     ` Paul Durrant
  0 siblings, 2 replies; 30+ messages in thread
From: Jan Beulich @ 2017-12-12 13:25 UTC (permalink / raw)
  To: Paul Durrant
  Cc: Stefano Stabellini, Wei Liu, George Dunlap, Andrew Cooper,
	Ian Jackson, Tim Deegan, xen-devel

>>> On 28.11.17 at 16:08, <paul.durrant@citrix.com> wrote:
> @@ -1905,7 +1906,8 @@ static int mod_l1_entry(l1_pgentry_t *pl1e, l1_pgentry_t nl1e,
>          }
>  
>          /* Translate foreign guest address. */
> -        if ( paging_mode_translate(pg_dom) )
> +        if ( cmd != MMU_PT_UPDATE_NO_TRANSLATE &&
> +             paging_mode_translate(pg_dom) )
>          {
>              p2m_type_t p2mt;
>              p2m_query_t q = l1e_get_flags(nl1e) & _PAGE_RW ?

Now that they're public - it was this change which led to the
recognition of the issue XSA-248 describes (which in turn led to the
other three). Without the fix for XSA-248 you'd have introduced a
worse issue here, allowing writable mappings of page table pages
rather than just r/o ones (leading to hypervisor crashes).

Especially with the bypass of acquiring a writable page ref in
get_page_from_l1e() for domains controlling shadow-external
domains we need to be extremely careful with assigning page
ownership. Before this series goes in I'd therefor like to ask you and
others (especially people on the Cc list) to double check that the
bypass introduced above doesn't allow for other (security) badness.
I think I've sufficiently convinced myself that it doesn't, but this
clearly wants double checking.

Jan


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v14 07/11] x86/mm: add an extra command to HYPERVISOR_mmu_update...
  2017-12-12 13:25   ` Jan Beulich
@ 2017-12-12 13:52     ` Andrew Cooper
  2017-12-12 14:38       ` Jan Beulich
  2017-12-12 14:54     ` Paul Durrant
  1 sibling, 1 reply; 30+ messages in thread
From: Andrew Cooper @ 2017-12-12 13:52 UTC (permalink / raw)
  To: Jan Beulich, Paul Durrant
  Cc: Stefano Stabellini, Wei Liu, George Dunlap, Tim Deegan,
	Ian Jackson, xen-devel

On 12/12/17 13:25, Jan Beulich wrote:
>>>> On 28.11.17 at 16:08, <paul.durrant@citrix.com> wrote:
>> @@ -1905,7 +1906,8 @@ static int mod_l1_entry(l1_pgentry_t *pl1e, l1_pgentry_t nl1e,
>>          }
>>  
>>          /* Translate foreign guest address. */
>> -        if ( paging_mode_translate(pg_dom) )
>> +        if ( cmd != MMU_PT_UPDATE_NO_TRANSLATE &&
>> +             paging_mode_translate(pg_dom) )
>>          {
>>              p2m_type_t p2mt;
>>              p2m_query_t q = l1e_get_flags(nl1e) & _PAGE_RW ?
> Now that they're public - it was this change which led to the
> recognition of the issue XSA-248 describes (which in turn led to the
> other three). Without the fix for XSA-248 you'd have introduced a
> worse issue here, allowing writable mappings of page table pages
> rather than just r/o ones (leading to hypervisor crashes).
>
> Especially with the bypass of acquiring a writable page ref in
> get_page_from_l1e() for domains controlling shadow-external
> domains we need to be extremely careful with assigning page
> ownership. Before this series goes in I'd therefor like to ask you and
> others (especially people on the Cc list) to double check that the
> bypass introduced above doesn't allow for other (security) badness.
> I think I've sufficiently convinced myself that it doesn't, but this
> clearly wants double checking.

Perhaps it is worth stepping back and considering the usecase from first
principles.

We are deliberately trying to introducing a mechanism whereby a
toolstack/device-mode/other semi-privileged entity can map resources
belonging to a guest which are not part of the guests physmap.  This is
because we deliberately want to move things like emulator rings out of
the guest physmap for attack surface reduction purposes.

On top of that, it would be far more simple if the mechanism by which
this is achieved was compatible with the existing mapping interfaces. 
One way or another, a PV guest needs to be able to construct a PTE for
these frames, and HVM guests need to be able to add these frames to its
physmap, and this looks very similar to foreign mapping.

Other thoughts/suggestions welcome.

~Andrew

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v14 07/11] x86/mm: add an extra command to HYPERVISOR_mmu_update...
  2017-12-12 13:52     ` Andrew Cooper
@ 2017-12-12 14:38       ` Jan Beulich
  2017-12-13 12:06         ` Paul Durrant
  0 siblings, 1 reply; 30+ messages in thread
From: Jan Beulich @ 2017-12-12 14:38 UTC (permalink / raw)
  To: Andrew Cooper
  Cc: Stefano Stabellini, Wei Liu, George Dunlap, Tim Deegan,
	Ian Jackson, Paul Durrant, xen-devel

>>> On 12.12.17 at 14:52, <andrew.cooper3@citrix.com> wrote:
> On 12/12/17 13:25, Jan Beulich wrote:
>>>>> On 28.11.17 at 16:08, <paul.durrant@citrix.com> wrote:
>>> @@ -1905,7 +1906,8 @@ static int mod_l1_entry(l1_pgentry_t *pl1e, 
> l1_pgentry_t nl1e,
>>>          }
>>>  
>>>          /* Translate foreign guest address. */
>>> -        if ( paging_mode_translate(pg_dom) )
>>> +        if ( cmd != MMU_PT_UPDATE_NO_TRANSLATE &&
>>> +             paging_mode_translate(pg_dom) )
>>>          {
>>>              p2m_type_t p2mt;
>>>              p2m_query_t q = l1e_get_flags(nl1e) & _PAGE_RW ?
>> Now that they're public - it was this change which led to the
>> recognition of the issue XSA-248 describes (which in turn led to the
>> other three). Without the fix for XSA-248 you'd have introduced a
>> worse issue here, allowing writable mappings of page table pages
>> rather than just r/o ones (leading to hypervisor crashes).
>>
>> Especially with the bypass of acquiring a writable page ref in
>> get_page_from_l1e() for domains controlling shadow-external
>> domains we need to be extremely careful with assigning page
>> ownership. Before this series goes in I'd therefor like to ask you and
>> others (especially people on the Cc list) to double check that the
>> bypass introduced above doesn't allow for other (security) badness.
>> I think I've sufficiently convinced myself that it doesn't, but this
>> clearly wants double checking.
> 
> Perhaps it is worth stepping back and considering the usecase from first
> principles.

First of all, from your reply as a whole I can't judge whether you
mean to say "all is fine, let's not think about it anymore" or "this
needs to be redone from scratch" or anything in between.

> We are deliberately trying to introducing a mechanism whereby a
> toolstack/device-mode/other semi-privileged entity can map resources
> belonging to a guest which are not part of the guests physmap.  This is
> because we deliberately want to move things like emulator rings out of
> the guest physmap for attack surface reduction purposes.

Correct. What I was trying to point out with my reply is that the
bypass here removes a check which previously we've been
relying on: By finding the page in the guest's physmap, we can
at least be certain that access to the page from outside of Xen is
expected. With it removed, the only other check is the
ownership one; the bypass in get_page_from_l1e() then blindly
allows writable mappings to pages owned by the guest, even if
they were shared r/o.

So while the relaxation here is deliberate _for the purposes the
series intends_, we still need to make sure we don't open a path
for device models to gain access to memory which they aren't
supposed to be able to write (or just read).

As you certainly realize, this would have happened if, long after
having reviewed the patch, it hadn't occurred to me that there's
problem here. Hence I think it is quite reasonable to take a step
back and think through another time whether there isn't any
further issue being introduced here.

Jan

> On top of that, it would be far more simple if the mechanism by which
> this is achieved was compatible with the existing mapping interfaces. 
> One way or another, a PV guest needs to be able to construct a PTE for
> these frames, and HVM guests need to be able to add these frames to its
> physmap, and this looks very similar to foreign mapping.
> 
> Other thoughts/suggestions welcome.
> 
> ~Andrew




_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v14 07/11] x86/mm: add an extra command to HYPERVISOR_mmu_update...
  2017-12-12 13:25   ` Jan Beulich
  2017-12-12 13:52     ` Andrew Cooper
@ 2017-12-12 14:54     ` Paul Durrant
  1 sibling, 0 replies; 30+ messages in thread
From: Paul Durrant @ 2017-12-12 14:54 UTC (permalink / raw)
  To: 'Jan Beulich'
  Cc: Stefano Stabellini, Wei Liu, Andrew Cooper, Tim (Xen.org),
	George Dunlap, Ian Jackson, xen-devel

> -----Original Message-----
> From: Jan Beulich [mailto:JBeulich@suse.com]
> Sent: 12 December 2017 13:25
> To: Paul Durrant <Paul.Durrant@citrix.com>
> Cc: Andrew Cooper <Andrew.Cooper3@citrix.com>; Wei Liu
> <wei.liu2@citrix.com>; George Dunlap <George.Dunlap@citrix.com>; Ian
> Jackson <Ian.Jackson@citrix.com>; Stefano Stabellini
> <sstabellini@kernel.org>; xen-devel@lists.xenproject.org; Tim (Xen.org)
> <tim@xen.org>
> Subject: Re: [PATCH v14 07/11] x86/mm: add an extra command to
> HYPERVISOR_mmu_update...
> 
> >>> On 28.11.17 at 16:08, <paul.durrant@citrix.com> wrote:
> > @@ -1905,7 +1906,8 @@ static int mod_l1_entry(l1_pgentry_t *pl1e,
> l1_pgentry_t nl1e,
> >          }
> >
> >          /* Translate foreign guest address. */
> > -        if ( paging_mode_translate(pg_dom) )
> > +        if ( cmd != MMU_PT_UPDATE_NO_TRANSLATE &&
> > +             paging_mode_translate(pg_dom) )
> >          {
> >              p2m_type_t p2mt;
> >              p2m_query_t q = l1e_get_flags(nl1e) & _PAGE_RW ?
> 
> Now that they're public - it was this change which led to the
> recognition of the issue XSA-248 describes (which in turn led to the
> other three). Without the fix for XSA-248 you'd have introduced a
> worse issue here, allowing writable mappings of page table pages
> rather than just r/o ones (leading to hypervisor crashes).
> 
> Especially with the bypass of acquiring a writable page ref in
> get_page_from_l1e() for domains controlling shadow-external
> domains we need to be extremely careful with assigning page
> ownership. Before this series goes in I'd therefor like to ask you and
> others (especially people on the Cc list) to double check that the
> bypass introduced above doesn't allow for other (security) badness.
> I think I've sufficiently convinced myself that it doesn't, but this
> clearly wants double checking.
> 

Ok. I'll have another look.

  Paul

> Jan


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v14 07/11] x86/mm: add an extra command to HYPERVISOR_mmu_update...
  2017-12-12 14:38       ` Jan Beulich
@ 2017-12-13 12:06         ` Paul Durrant
  2017-12-13 14:35           ` Jan Beulich
  0 siblings, 1 reply; 30+ messages in thread
From: Paul Durrant @ 2017-12-13 12:06 UTC (permalink / raw)
  To: 'Jan Beulich', Andrew Cooper
  Cc: Stefano Stabellini, Wei Liu, Tim (Xen.org),
	George Dunlap, xen-devel, Ian Jackson

 -----Original Message-----
> From: Jan Beulich [mailto:JBeulich@suse.com]
> Sent: 12 December 2017 14:39
> To: Andrew Cooper <Andrew.Cooper3@citrix.com>
> Cc: Paul Durrant <Paul.Durrant@citrix.com>; Wei Liu <wei.liu2@citrix.com>;
> George Dunlap <George.Dunlap@citrix.com>; Ian Jackson
> <Ian.Jackson@citrix.com>; Stefano Stabellini <sstabellini@kernel.org>; xen-
> devel@lists.xenproject.org; Tim (Xen.org) <tim@xen.org>
> Subject: Re: [PATCH v14 07/11] x86/mm: add an extra command to
> HYPERVISOR_mmu_update...
> 
> >>> On 12.12.17 at 14:52, <andrew.cooper3@citrix.com> wrote:
> > On 12/12/17 13:25, Jan Beulich wrote:
> >>>>> On 28.11.17 at 16:08, <paul.durrant@citrix.com> wrote:
> >>> @@ -1905,7 +1906,8 @@ static int mod_l1_entry(l1_pgentry_t *pl1e,
> > l1_pgentry_t nl1e,
> >>>          }
> >>>
> >>>          /* Translate foreign guest address. */
> >>> -        if ( paging_mode_translate(pg_dom) )
> >>> +        if ( cmd != MMU_PT_UPDATE_NO_TRANSLATE &&
> >>> +             paging_mode_translate(pg_dom) )
> >>>          {
> >>>              p2m_type_t p2mt;
> >>>              p2m_query_t q = l1e_get_flags(nl1e) & _PAGE_RW ?
> >> Now that they're public - it was this change which led to the
> >> recognition of the issue XSA-248 describes (which in turn led to the
> >> other three). Without the fix for XSA-248 you'd have introduced a
> >> worse issue here, allowing writable mappings of page table pages
> >> rather than just r/o ones (leading to hypervisor crashes).
> >>
> >> Especially with the bypass of acquiring a writable page ref in
> >> get_page_from_l1e() for domains controlling shadow-external
> >> domains we need to be extremely careful with assigning page
> >> ownership. Before this series goes in I'd therefor like to ask you and
> >> others (especially people on the Cc list) to double check that the
> >> bypass introduced above doesn't allow for other (security) badness.
> >> I think I've sufficiently convinced myself that it doesn't, but this
> >> clearly wants double checking.
> >
> > Perhaps it is worth stepping back and considering the usecase from first
> > principles.
> 
> First of all, from your reply as a whole I can't judge whether you
> mean to say "all is fine, let's not think about it anymore" or "this
> needs to be redone from scratch" or anything in between.
> 
> > We are deliberately trying to introducing a mechanism whereby a
> > toolstack/device-mode/other semi-privileged entity can map resources
> > belonging to a guest which are not part of the guests physmap.  This is
> > because we deliberately want to move things like emulator rings out of
> > the guest physmap for attack surface reduction purposes.
> 
> Correct. What I was trying to point out with my reply is that the
> bypass here removes a check which previously we've been
> relying on: By finding the page in the guest's physmap, we can
> at least be certain that access to the page from outside of Xen is
> expected. With it removed, the only other check is the
> ownership one; the bypass in get_page_from_l1e() then blindly
> allows writable mappings to pages owned by the guest, even if
> they were shared r/o.
> 
> So while the relaxation here is deliberate _for the purposes the
> series intends_, we still need to make sure we don't open a path
> for device models to gain access to memory which they aren't
> supposed to be able to write (or just read).
> 

So, a suggestion would be to use some form of flag on the page (probably a PGC_ flag?) to tag it as a mappable resource. We can then white-list grant frames and ioreq frames with the new flag and then make sure use of MMU_PT_UPDATE_NO_TRANSLATE checks that the mfn is either in the guest P2M anyway, or tagged as a mappable resource?

Does that sound reasonable?

  Paul

> As you certainly realize, this would have happened if, long after
> having reviewed the patch, it hadn't occurred to me that there's
> problem here. Hence I think it is quite reasonable to take a step
> back and think through another time whether there isn't any
> further issue being introduced here.
> 
> Jan
> 
> > On top of that, it would be far more simple if the mechanism by which
> > this is achieved was compatible with the existing mapping interfaces.
> > One way or another, a PV guest needs to be able to construct a PTE for
> > these frames, and HVM guests need to be able to add these frames to its
> > physmap, and this looks very similar to foreign mapping.
> >
> > Other thoughts/suggestions welcome.
> >
> > ~Andrew
> 
> 


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v14 07/11] x86/mm: add an extra command to HYPERVISOR_mmu_update...
  2017-12-13 12:06         ` Paul Durrant
@ 2017-12-13 14:35           ` Jan Beulich
  2017-12-13 14:49             ` Paul Durrant
  0 siblings, 1 reply; 30+ messages in thread
From: Jan Beulich @ 2017-12-13 14:35 UTC (permalink / raw)
  To: Paul Durrant
  Cc: Stefano Stabellini, Wei Liu, Andrew Cooper, Tim (Xen.org),
	George Dunlap, Ian Jackson, xen-devel

 >>> On 13.12.17 at 13:06, <Paul.Durrant@citrix.com> wrote:
>> From: Jan Beulich [mailto:JBeulich@suse.com]
>> Sent: 12 December 2017 14:39
>> >>> On 12.12.17 at 14:52, <andrew.cooper3@citrix.com> wrote:
>> > We are deliberately trying to introducing a mechanism whereby a
>> > toolstack/device-mode/other semi-privileged entity can map resources
>> > belonging to a guest which are not part of the guests physmap.  This is
>> > because we deliberately want to move things like emulator rings out of
>> > the guest physmap for attack surface reduction purposes.
>> 
>> Correct. What I was trying to point out with my reply is that the
>> bypass here removes a check which previously we've been
>> relying on: By finding the page in the guest's physmap, we can
>> at least be certain that access to the page from outside of Xen is
>> expected. With it removed, the only other check is the
>> ownership one; the bypass in get_page_from_l1e() then blindly
>> allows writable mappings to pages owned by the guest, even if
>> they were shared r/o.
>> 
>> So while the relaxation here is deliberate _for the purposes the
>> series intends_, we still need to make sure we don't open a path
>> for device models to gain access to memory which they aren't
>> supposed to be able to write (or just read).
> 
> So, a suggestion would be to use some form of flag on the page (probably a 
> PGC_ flag?) to tag it as a mappable resource. We can then white-list grant 
> frames and ioreq frames with the new flag and then make sure use of 
> MMU_PT_UPDATE_NO_TRANSLATE checks that the mfn is either in the guest P2M 
> anyway, or tagged as a mappable resource?

This doesn't look to be race free: What about a page having the
new flag removed while the page is still mapped, or in the process
of being mapped (but already past the check of the flag)?

Jan


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v14 07/11] x86/mm: add an extra command to HYPERVISOR_mmu_update...
  2017-12-13 14:35           ` Jan Beulich
@ 2017-12-13 14:49             ` Paul Durrant
  2017-12-13 15:24               ` Jan Beulich
  0 siblings, 1 reply; 30+ messages in thread
From: Paul Durrant @ 2017-12-13 14:49 UTC (permalink / raw)
  To: 'Jan Beulich'
  Cc: Stefano Stabellini, Wei Liu, Andrew Cooper, Tim (Xen.org),
	George Dunlap, Ian Jackson, xen-devel

> -----Original Message-----
> From: Jan Beulich [mailto:JBeulich@suse.com]
> Sent: 13 December 2017 14:36
> To: Paul Durrant <Paul.Durrant@citrix.com>
> Cc: Andrew Cooper <Andrew.Cooper3@citrix.com>; George Dunlap
> <George.Dunlap@citrix.com>; Ian Jackson <Ian.Jackson@citrix.com>; Wei Liu
> <wei.liu2@citrix.com>; Stefano Stabellini <sstabellini@kernel.org>; xen-
> devel@lists.xenproject.org; Tim (Xen.org) <tim@xen.org>
> Subject: RE: [PATCH v14 07/11] x86/mm: add an extra command to
> HYPERVISOR_mmu_update...
> 
>  >>> On 13.12.17 at 13:06, <Paul.Durrant@citrix.com> wrote:
> >> From: Jan Beulich [mailto:JBeulich@suse.com]
> >> Sent: 12 December 2017 14:39
> >> >>> On 12.12.17 at 14:52, <andrew.cooper3@citrix.com> wrote:
> >> > We are deliberately trying to introducing a mechanism whereby a
> >> > toolstack/device-mode/other semi-privileged entity can map resources
> >> > belonging to a guest which are not part of the guests physmap.  This is
> >> > because we deliberately want to move things like emulator rings out of
> >> > the guest physmap for attack surface reduction purposes.
> >>
> >> Correct. What I was trying to point out with my reply is that the
> >> bypass here removes a check which previously we've been
> >> relying on: By finding the page in the guest's physmap, we can
> >> at least be certain that access to the page from outside of Xen is
> >> expected. With it removed, the only other check is the
> >> ownership one; the bypass in get_page_from_l1e() then blindly
> >> allows writable mappings to pages owned by the guest, even if
> >> they were shared r/o.
> >>
> >> So while the relaxation here is deliberate _for the purposes the
> >> series intends_, we still need to make sure we don't open a path
> >> for device models to gain access to memory which they aren't
> >> supposed to be able to write (or just read).
> >
> > So, a suggestion would be to use some form of flag on the page (probably a
> > PGC_ flag?) to tag it as a mappable resource. We can then white-list grant
> > frames and ioreq frames with the new flag and then make sure use of
> > MMU_PT_UPDATE_NO_TRANSLATE checks that the mfn is either in the
> guest P2M
> > anyway, or tagged as a mappable resource?
> 
> This doesn't look to be race free: What about a page having the
> new flag removed while the page is still mapped, or in the process
> of being mapped (but already past the check of the flag)?
> 

Maybe that wouldn't work then. I don't really have any further suggestions. The big question seems to be what does page ownership actually mean?

  Paul

> Jan


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v14 07/11] x86/mm: add an extra command to HYPERVISOR_mmu_update...
  2017-12-13 14:49             ` Paul Durrant
@ 2017-12-13 15:24               ` Jan Beulich
  2017-12-13 17:03                 ` Paul Durrant
  0 siblings, 1 reply; 30+ messages in thread
From: Jan Beulich @ 2017-12-13 15:24 UTC (permalink / raw)
  To: Paul Durrant
  Cc: Stefano Stabellini, Wei Liu, Andrew Cooper, Tim(Xen.org),
	George Dunlap, Ian Jackson, xen-devel

>>> On 13.12.17 at 15:49, <Paul.Durrant@citrix.com> wrote:
>> From: Jan Beulich [mailto:JBeulich@suse.com]
>> Sent: 13 December 2017 14:36
>>  >>> On 13.12.17 at 13:06, <Paul.Durrant@citrix.com> wrote:
>> >> From: Jan Beulich [mailto:JBeulich@suse.com]
>> >> Sent: 12 December 2017 14:39
>> >> >>> On 12.12.17 at 14:52, <andrew.cooper3@citrix.com> wrote:
>> >> > We are deliberately trying to introducing a mechanism whereby a
>> >> > toolstack/device-mode/other semi-privileged entity can map resources
>> >> > belonging to a guest which are not part of the guests physmap.  This is
>> >> > because we deliberately want to move things like emulator rings out of
>> >> > the guest physmap for attack surface reduction purposes.
>> >>
>> >> Correct. What I was trying to point out with my reply is that the
>> >> bypass here removes a check which previously we've been
>> >> relying on: By finding the page in the guest's physmap, we can
>> >> at least be certain that access to the page from outside of Xen is
>> >> expected. With it removed, the only other check is the
>> >> ownership one; the bypass in get_page_from_l1e() then blindly
>> >> allows writable mappings to pages owned by the guest, even if
>> >> they were shared r/o.
>> >>
>> >> So while the relaxation here is deliberate _for the purposes the
>> >> series intends_, we still need to make sure we don't open a path
>> >> for device models to gain access to memory which they aren't
>> >> supposed to be able to write (or just read).
>> >
>> > So, a suggestion would be to use some form of flag on the page (probably a
>> > PGC_ flag?) to tag it as a mappable resource. We can then white-list grant
>> > frames and ioreq frames with the new flag and then make sure use of
>> > MMU_PT_UPDATE_NO_TRANSLATE checks that the mfn is either in the
>> guest P2M
>> > anyway, or tagged as a mappable resource?
>> 
>> This doesn't look to be race free: What about a page having the
>> new flag removed while the page is still mapped, or in the process
>> of being mapped (but already past the check of the flag)?
>> 
> 
> Maybe that wouldn't work then. I don't really have any further suggestions. 
> The big question seems to be what does page ownership actually mean?

Maybe there was a misunderstanding in the first place: Unless you
found an issue with the current version of the patch, I wasn't
actually asking to add any further checking logic. Instead I was
asking to double check that with the remaining (after XSA-248)
ownership assignments we don't have any pages left which could
have a mapping established, _despite_ the new bypass.

Jan


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v14 07/11] x86/mm: add an extra command to HYPERVISOR_mmu_update...
  2017-12-13 15:24               ` Jan Beulich
@ 2017-12-13 17:03                 ` Paul Durrant
  2017-12-14 13:50                   ` Jan Beulich
  0 siblings, 1 reply; 30+ messages in thread
From: Paul Durrant @ 2017-12-13 17:03 UTC (permalink / raw)
  To: 'Jan Beulich'
  Cc: Stefano Stabellini, Wei Liu, Andrew Cooper, Tim (Xen.org),
	George Dunlap, Ian Jackson, xen-devel

> -----Original Message-----
> From: Jan Beulich [mailto:JBeulich@suse.com]
> Sent: 13 December 2017 15:25
> To: Paul Durrant <Paul.Durrant@citrix.com>
> Cc: Andrew Cooper <Andrew.Cooper3@citrix.com>; George Dunlap
> <George.Dunlap@citrix.com>; Ian Jackson <Ian.Jackson@citrix.com>; Wei Liu
> <wei.liu2@citrix.com>; Stefano Stabellini <sstabellini@kernel.org>; xen-
> devel@lists.xenproject.org; Tim (Xen.org) <tim@xen.org>
> Subject: RE: [PATCH v14 07/11] x86/mm: add an extra command to
> HYPERVISOR_mmu_update...
> 
> >>> On 13.12.17 at 15:49, <Paul.Durrant@citrix.com> wrote:
> >> From: Jan Beulich [mailto:JBeulich@suse.com]
> >> Sent: 13 December 2017 14:36
> >>  >>> On 13.12.17 at 13:06, <Paul.Durrant@citrix.com> wrote:
> >> >> From: Jan Beulich [mailto:JBeulich@suse.com]
> >> >> Sent: 12 December 2017 14:39
> >> >> >>> On 12.12.17 at 14:52, <andrew.cooper3@citrix.com> wrote:
> >> >> > We are deliberately trying to introducing a mechanism whereby a
> >> >> > toolstack/device-mode/other semi-privileged entity can map
> resources
> >> >> > belonging to a guest which are not part of the guests physmap.  This
> is
> >> >> > because we deliberately want to move things like emulator rings out
> of
> >> >> > the guest physmap for attack surface reduction purposes.
> >> >>
> >> >> Correct. What I was trying to point out with my reply is that the
> >> >> bypass here removes a check which previously we've been
> >> >> relying on: By finding the page in the guest's physmap, we can
> >> >> at least be certain that access to the page from outside of Xen is
> >> >> expected. With it removed, the only other check is the
> >> >> ownership one; the bypass in get_page_from_l1e() then blindly
> >> >> allows writable mappings to pages owned by the guest, even if
> >> >> they were shared r/o.
> >> >>
> >> >> So while the relaxation here is deliberate _for the purposes the
> >> >> series intends_, we still need to make sure we don't open a path
> >> >> for device models to gain access to memory which they aren't
> >> >> supposed to be able to write (or just read).
> >> >
> >> > So, a suggestion would be to use some form of flag on the page
> (probably a
> >> > PGC_ flag?) to tag it as a mappable resource. We can then white-list
> grant
> >> > frames and ioreq frames with the new flag and then make sure use of
> >> > MMU_PT_UPDATE_NO_TRANSLATE checks that the mfn is either in the
> >> guest P2M
> >> > anyway, or tagged as a mappable resource?
> >>
> >> This doesn't look to be race free: What about a page having the
> >> new flag removed while the page is still mapped, or in the process
> >> of being mapped (but already past the check of the flag)?
> >>
> >
> > Maybe that wouldn't work then. I don't really have any further
> suggestions.
> > The big question seems to be what does page ownership actually mean?
> 
> Maybe there was a misunderstanding in the first place: Unless you
> found an issue with the current version of the patch, I wasn't
> actually asking to add any further checking logic. Instead I was
> asking to double check that with the remaining (after XSA-248)
> ownership assignments we don't have any pages left which could
> have a mapping established, _despite_ the new bypass.
> 

Looking through the code, the only one thing that bothers me is the page_set_owner() done in shadow_enable() for the page used for HVM guest vcpus that have paging disabled. AFAICT that page would become mappable by an emulating domain with MMU_PT_UPDATE_NO_TRANSLATE, if it figured out or guessed the correct MFN, but I'm not sure whether damage could be done to Xen using that.

  Paul

> Jan


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v14 06/11] x86/hvm/ioreq: add a new mappable resource type...
  2017-11-28 15:08 ` [PATCH v14 06/11] x86/hvm/ioreq: add a new mappable resource type Paul Durrant
@ 2017-12-14  9:51   ` Paul Durrant
  2017-12-14  9:52     ` Paul Durrant
                       ` (2 more replies)
  0 siblings, 3 replies; 30+ messages in thread
From: Paul Durrant @ 2017-12-14  9:51 UTC (permalink / raw)
  To: Paul Durrant, xen-devel
  Cc: Stefano Stabellini, Wei Liu, Andrew Cooper, Tim (Xen.org),
	George Dunlap, Julien Grall, Ian Jackson

> -----Original Message-----
> From: Paul Durrant [mailto:paul.durrant@citrix.com]
> Sent: 28 November 2017 15:09
> To: xen-devel@lists.xenproject.org
> Cc: Paul Durrant <Paul.Durrant@citrix.com>; George Dunlap
> <George.Dunlap@citrix.com>; Wei Liu <wei.liu2@citrix.com>; Andrew
> Cooper <Andrew.Cooper3@citrix.com>; Ian Jackson
> <Ian.Jackson@citrix.com>; Konrad Rzeszutek Wilk
> <konrad.wilk@oracle.com>; Stefano Stabellini <sstabellini@kernel.org>; Tim
> (Xen.org) <tim@xen.org>; Julien Grall <julien.grall@arm.com>
> Subject: [PATCH v14 06/11] x86/hvm/ioreq: add a new mappable resource
> type...
> 
> ... XENMEM_resource_ioreq_server
> 
> This patch adds support for a new resource type that can be mapped using
> the XENMEM_acquire_resource memory op.
> 
> If an emulator makes use of this resource type then, instead of mapping
> gfns, the IOREQ server will allocate pages from the heap. These pages
> will never be present in the P2M of the guest at any point and so are
> not vulnerable to any direct attack by the guest. They are only ever
> accessible by Xen and any domain that has mapping privilege over the
> guest (which may or may not be limited to the domain running the
> emulator).
> 
> NOTE: Use of the new resource type is not compatible with use of
>       XEN_DMOP_get_ioreq_server_info unless the XEN_DMOP_no_gfns flag
> is
>       set.
> 
> Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
> Reviewed-by: Jan Beulich <jbeulich@suse.com>
> ---
> Cc: George Dunlap <George.Dunlap@eu.citrix.com>
> Cc: Wei Liu <wei.liu2@citrix.com>
> Cc: Andrew Cooper <andrew.cooper3@citrix.com>
> Cc: Ian Jackson <ian.jackson@eu.citrix.com>
> Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> Cc: Stefano Stabellini <sstabellini@kernel.org>
> Cc: Tim Deegan <tim@xen.org>
> Cc: Julien Grall <julien.grall@arm.com>
> 
> v14:
>  - Addressed more comments from Jan.
> 
> v13:
>  - Introduce an arch_acquire_resource() as suggested by Julien (and have
>    the ARM varient simply return -EOPNOTSUPP).
>  - Check for ioreq server id truncation as requested by Jan.
>  - Not added Jan's R-b due to substantive change from v12.
> 
> v12:
>  - Addressed more comments from Jan.
>  - Dropped George's A-b and Wei's R-b because of material change.
> 
> v11:
>  - Addressed more comments from Jan.
> 
> v10:
>  - Addressed comments from Jan.
> 
> v8:
>  - Re-base on new boilerplate.
>  - Adjust function signature of hvm_get_ioreq_server_frame(), and test
>    whether the bufioreq page is present.
> 
> v5:
>  - Use get_ioreq_server() function rather than indexing array directly.
>  - Add more explanation into comments to state than mapping guest frames
>    and allocation of pages for ioreq servers are not simultaneously
>    permitted.
>  - Add a comment into asm/ioreq.h stating the meaning of the index
>    value passed to hvm_get_ioreq_server_frame().
> ---
>  xen/arch/x86/hvm/ioreq.c        | 156
> ++++++++++++++++++++++++++++++++++++++++
>  xen/arch/x86/mm.c               |  41 +++++++++++
>  xen/common/memory.c             |   3 +-
>  xen/include/asm-arm/mm.h        |   7 ++
>  xen/include/asm-x86/hvm/ioreq.h |   2 +
>  xen/include/asm-x86/mm.h        |   5 ++
>  xen/include/public/hvm/dm_op.h  |   4 ++
>  xen/include/public/memory.h     |   9 +++
>  8 files changed, 226 insertions(+), 1 deletion(-)
> 
> diff --git a/xen/arch/x86/hvm/ioreq.c b/xen/arch/x86/hvm/ioreq.c
> index 39de659ddf..d991ac9cdc 100644
> --- a/xen/arch/x86/hvm/ioreq.c
> +++ b/xen/arch/x86/hvm/ioreq.c
> @@ -259,6 +259,19 @@ static int hvm_map_ioreq_gfn(struct
> hvm_ioreq_server *s, bool buf)
>      struct hvm_ioreq_page *iorp = buf ? &s->bufioreq : &s->ioreq;
>      int rc;
> 
> +    if ( iorp->page )
> +    {
> +        /*
> +         * If a page has already been allocated (which will happen on
> +         * demand if hvm_get_ioreq_server_frame() is called), then
> +         * mapping a guest frame is not permitted.
> +         */
> +        if ( gfn_eq(iorp->gfn, INVALID_GFN) )
> +            return -EPERM;
> +
> +        return 0;
> +    }
> +
>      if ( d->is_dying )
>          return -EINVAL;
> 
> @@ -281,6 +294,70 @@ static int hvm_map_ioreq_gfn(struct
> hvm_ioreq_server *s, bool buf)
>      return rc;
>  }
> 
> +static int hvm_alloc_ioreq_mfn(struct hvm_ioreq_server *s, bool buf)
> +{
> +    struct domain *currd = current->domain;
> +    struct hvm_ioreq_page *iorp = buf ? &s->bufioreq : &s->ioreq;
> +
> +    if ( iorp->page )
> +    {
> +        /*
> +         * If a guest frame has already been mapped (which may happen
> +         * on demand if hvm_get_ioreq_server_info() is called), then
> +         * allocating a page is not permitted.
> +         */
> +        if ( !gfn_eq(iorp->gfn, INVALID_GFN) )
> +            return -EPERM;
> +
> +        return 0;
> +    }
> +
> +    /*
> +     * Allocated IOREQ server pages are assigned to the emulating
> +     * domain, not the target domain. This is because the emulator is
> +     * likely to be destroyed after the target domain has been torn
> +     * down, and we must use MEMF_no_refcount otherwise page allocation
> +     * could fail if the emulating domain has already reached its
> +     * maximum allocation.
> +     */
> +    iorp->page = alloc_domheap_page(currd, MEMF_no_refcount);

This is no longer going to work as it is predicated on my original modification to HYPERVISOR_mmu_update (which allowed a PV domain to map a foreign MFN from a domain over which it had privilege as if the MFN was local). Because that mechanism was decided against, this code needs to change to use the target domain of the ioreq server rather than the calling domain. I will verfy this modification and submit v15 of the series.

Jan, are you ok for me to keep your R-b?

  Paul

> +    if ( !iorp->page )
> +        return -ENOMEM;
> +
> +    if ( !get_page_type(iorp->page, PGT_writable_page) )
> +    {
> +        ASSERT_UNREACHABLE();
> +        put_page(iorp->page);
> +        iorp->page = NULL;
> +        return -ENOMEM;
> +    }
> +
> +    iorp->va = __map_domain_page_global(iorp->page);
> +    if ( !iorp->va )
> +    {
> +        put_page_and_type(iorp->page);
> +        iorp->page = NULL;
> +        return -ENOMEM;
> +    }
> +
> +    clear_page(iorp->va);
> +    return 0;
> +}
> +
> +static void hvm_free_ioreq_mfn(struct hvm_ioreq_server *s, bool buf)
> +{
> +    struct hvm_ioreq_page *iorp = buf ? &s->bufioreq : &s->ioreq;
> +
> +    if ( !iorp->page )
> +        return;
> +
> +    unmap_domain_page_global(iorp->va);
> +    iorp->va = NULL;
> +
> +    put_page_and_type(iorp->page);
> +    iorp->page = NULL;
> +}
> +
>  bool is_ioreq_server_page(struct domain *d, const struct page_info *page)
>  {
>      const struct hvm_ioreq_server *s;
> @@ -484,6 +561,27 @@ static void hvm_ioreq_server_unmap_pages(struct
> hvm_ioreq_server *s)
>      hvm_unmap_ioreq_gfn(s, false);
>  }
> 
> +static int hvm_ioreq_server_alloc_pages(struct hvm_ioreq_server *s)
> +{
> +    int rc;
> +
> +    rc = hvm_alloc_ioreq_mfn(s, false);
> +
> +    if ( !rc && (s->bufioreq_handling != HVM_IOREQSRV_BUFIOREQ_OFF) )
> +        rc = hvm_alloc_ioreq_mfn(s, true);
> +
> +    if ( rc )
> +        hvm_free_ioreq_mfn(s, false);
> +
> +    return rc;
> +}
> +
> +static void hvm_ioreq_server_free_pages(struct hvm_ioreq_server *s)
> +{
> +    hvm_free_ioreq_mfn(s, true);
> +    hvm_free_ioreq_mfn(s, false);
> +}
> +
>  static void hvm_ioreq_server_free_rangesets(struct hvm_ioreq_server *s)
>  {
>      unsigned int i;
> @@ -612,7 +710,18 @@ static int hvm_ioreq_server_init(struct
> hvm_ioreq_server *s,
> 
>   fail_add:
>      hvm_ioreq_server_remove_all_vcpus(s);
> +
> +    /*
> +     * NOTE: It is safe to call both hvm_ioreq_server_unmap_pages() and
> +     *       hvm_ioreq_server_free_pages() in that order.
> +     *       This is because the former will do nothing if the pages
> +     *       are not mapped, leaving the page to be freed by the latter.
> +     *       However if the pages are mapped then the former will set
> +     *       the page_info pointer to NULL, meaning the latter will do
> +     *       nothing.
> +     */
>      hvm_ioreq_server_unmap_pages(s);
> +    hvm_ioreq_server_free_pages(s);
> 
>      return rc;
>  }
> @@ -622,6 +731,7 @@ static void hvm_ioreq_server_deinit(struct
> hvm_ioreq_server *s)
>      ASSERT(!s->enabled);
>      hvm_ioreq_server_remove_all_vcpus(s);
>      hvm_ioreq_server_unmap_pages(s);
> +    hvm_ioreq_server_free_pages(s);
>      hvm_ioreq_server_free_rangesets(s);
>  }
> 
> @@ -777,6 +887,52 @@ int hvm_get_ioreq_server_info(struct domain *d,
> ioservid_t id,
>      return rc;
>  }
> 
> +int hvm_get_ioreq_server_frame(struct domain *d, ioservid_t id,
> +                               unsigned long idx, mfn_t *mfn)
> +{
> +    struct hvm_ioreq_server *s;
> +    int rc;
> +
> +    spin_lock_recursive(&d->arch.hvm_domain.ioreq_server.lock);
> +
> +    if ( id == DEFAULT_IOSERVID )
> +        return -EOPNOTSUPP;
> +
> +    s = get_ioreq_server(d, id);
> +
> +    ASSERT(!IS_DEFAULT(s));
> +
> +    rc = hvm_ioreq_server_alloc_pages(s);
> +    if ( rc )
> +        goto out;
> +
> +    switch ( idx )
> +    {
> +    case XENMEM_resource_ioreq_server_frame_bufioreq:
> +        rc = -ENOENT;
> +        if ( !HANDLE_BUFIOREQ(s) )
> +            goto out;
> +
> +        *mfn = _mfn(page_to_mfn(s->bufioreq.page));
> +        rc = 0;
> +        break;
> +
> +    case XENMEM_resource_ioreq_server_frame_ioreq(0):
> +        *mfn = _mfn(page_to_mfn(s->ioreq.page));
> +        rc = 0;
> +        break;
> +
> +    default:
> +        rc = -EINVAL;
> +        break;
> +    }
> +
> + out:
> +    spin_unlock_recursive(&d->arch.hvm_domain.ioreq_server.lock);
> +
> +    return rc;
> +}
> +
>  int hvm_map_io_range_to_ioreq_server(struct domain *d, ioservid_t id,
>                                       uint32_t type, uint64_t start,
>                                       uint64_t end)
> diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
> index 6ec6e68afe..2656eb181a 100644
> --- a/xen/arch/x86/mm.c
> +++ b/xen/arch/x86/mm.c
> @@ -122,6 +122,7 @@
>  #include <asm/fixmap.h>
>  #include <asm/io_apic.h>
>  #include <asm/pci.h>
> +#include <asm/hvm/ioreq.h>
> 
>  #include <asm/hvm/grant_table.h>
>  #include <asm/pv/grant_table.h>
> @@ -4170,6 +4171,46 @@ int xenmem_add_to_physmap_one(
>      return rc;
>  }
> 
> +int arch_acquire_resource(struct domain *d, unsigned int type,
> +                          unsigned int id, unsigned long frame,
> +                          unsigned int nr_frames, xen_pfn_t mfn_list[])
> +{
> +    int rc;
> +
> +    switch ( type )
> +    {
> +    case XENMEM_resource_ioreq_server:
> +    {
> +        ioservid_t ioservid = id;
> +        unsigned int i;
> +
> +        rc = -EINVAL;
> +        if ( id != (unsigned int)ioservid )
> +            break;
> +
> +        rc = 0;
> +        for ( i = 0; i < nr_frames; i++ )
> +        {
> +            mfn_t mfn;
> +
> +            rc = hvm_get_ioreq_server_frame(d, id, frame + i, &mfn);
> +            if ( rc )
> +                break;
> +
> +            mfn_list[i] = mfn_x(mfn);
> +        }
> +
> +        break;
> +    }
> +
> +    default:
> +        rc = -EOPNOTSUPP;
> +        break;
> +    }
> +
> +    return rc;
> +}
> +
>  long arch_memory_op(unsigned long cmd,
> XEN_GUEST_HANDLE_PARAM(void) arg)
>  {
>      int rc;
> diff --git a/xen/common/memory.c b/xen/common/memory.c
> index 6c385a2328..0167d9788b 100644
> --- a/xen/common/memory.c
> +++ b/xen/common/memory.c
> @@ -1016,7 +1016,8 @@ static int acquire_resource(
>      switch ( xmar.type )
>      {
>      default:
> -        rc = -EOPNOTSUPP;
> +        rc = arch_acquire_resource(d, xmar.type, xmar.id, xmar.frame,
> +                                   xmar.nr_frames, mfn_list);
>          break;
>      }
> 
> diff --git a/xen/include/asm-arm/mm.h b/xen/include/asm-arm/mm.h
> index ad2f2a43dc..bd146dee3c 100644
> --- a/xen/include/asm-arm/mm.h
> +++ b/xen/include/asm-arm/mm.h
> @@ -381,6 +381,13 @@ static inline void put_page_and_type(struct
> page_info *page)
> 
>  void clear_and_clean_page(struct page_info *page);
> 
> +static inline int arch_acquire_resource(
> +    struct domain *d, unsigned int type, unsigned int id,
> +    unsigned long frame,unsigned int nr_frames, xen_pfn_t mfn_list[])
> +{
> +    return -EOPNOTSUPP;
> +}
> +
>  #endif /*  __ARCH_ARM_MM__ */
>  /*
>   * Local variables:
> diff --git a/xen/include/asm-x86/hvm/ioreq.h b/xen/include/asm-
> x86/hvm/ioreq.h
> index 1829fcf43e..9e37c97a37 100644
> --- a/xen/include/asm-x86/hvm/ioreq.h
> +++ b/xen/include/asm-x86/hvm/ioreq.h
> @@ -31,6 +31,8 @@ int hvm_get_ioreq_server_info(struct domain *d,
> ioservid_t id,
>                                unsigned long *ioreq_gfn,
>                                unsigned long *bufioreq_gfn,
>                                evtchn_port_t *bufioreq_port);
> +int hvm_get_ioreq_server_frame(struct domain *d, ioservid_t id,
> +                               unsigned long idx, mfn_t *mfn);
>  int hvm_map_io_range_to_ioreq_server(struct domain *d, ioservid_t id,
>                                       uint32_t type, uint64_t start,
>                                       uint64_t end);
> diff --git a/xen/include/asm-x86/mm.h b/xen/include/asm-x86/mm.h
> index 83626085e0..10e5b6cd14 100644
> --- a/xen/include/asm-x86/mm.h
> +++ b/xen/include/asm-x86/mm.h
> @@ -629,4 +629,9 @@ static inline bool arch_mfn_in_directmap(unsigned
> long mfn)
>      return mfn <= (virt_to_mfn(eva - 1) + 1);
>  }
> 
> +int arch_acquire_resource(struct domain *d, unsigned int type,
> +                          unsigned int id, unsigned long frame,
> +                          unsigned int nr_frames,
> +                          xen_pfn_t mfn_list[]);
> +
>  #endif /* __ASM_X86_MM_H__ */
> diff --git a/xen/include/public/hvm/dm_op.h
> b/xen/include/public/hvm/dm_op.h
> index 13b3737c2f..add68ea192 100644
> --- a/xen/include/public/hvm/dm_op.h
> +++ b/xen/include/public/hvm/dm_op.h
> @@ -90,6 +90,10 @@ struct xen_dm_op_create_ioreq_server {
>   * the frame numbers passed back in gfns <ioreq_gfn> and <bufioreq_gfn>
>   * respectively. (If the IOREQ Server is not handling buffered emulation
>   * only <ioreq_gfn> will be valid).
> + *
> + * NOTE: To access the synchronous ioreq structures and buffered ioreq
> + *       ring, it is preferable to use the XENMEM_acquire_resource memory
> + *       op specifying resource type XENMEM_resource_ioreq_server.
>   */
>  #define XEN_DMOP_get_ioreq_server_info 2
> 
> diff --git a/xen/include/public/memory.h b/xen/include/public/memory.h
> index 83e60b6603..838f248a59 100644
> --- a/xen/include/public/memory.h
> +++ b/xen/include/public/memory.h
> @@ -609,9 +609,14 @@ struct xen_mem_acquire_resource {
>      domid_t domid;
>      /* IN - the type of resource */
>      uint16_t type;
> +
> +#define XENMEM_resource_ioreq_server 0
> +
>      /*
>       * IN - a type-specific resource identifier, which must be zero
>       *      unless stated otherwise.
> +     *
> +     * type == XENMEM_resource_ioreq_server -> id == ioreq server id
>       */
>      uint32_t id;
>      /* IN/OUT - As an IN parameter number of frames of the resource
> @@ -625,6 +630,10 @@ struct xen_mem_acquire_resource {
>       *      is ignored if nr_frames is 0.
>       */
>      uint64_aligned_t frame;
> +
> +#define XENMEM_resource_ioreq_server_frame_bufioreq 0
> +#define XENMEM_resource_ioreq_server_frame_ioreq(n) (1 + (n))
> +
>      /* IN/OUT - If the tools domain is PV then, upon return, frame_list
>       *          will be populated with the MFNs of the resource.
>       *          If the tools domain is HVM then it is expected that, on
> --
> 2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v14 06/11] x86/hvm/ioreq: add a new mappable resource type...
  2017-12-14  9:51   ` Paul Durrant
@ 2017-12-14  9:52     ` Paul Durrant
  2017-12-14 10:31     ` Paul Durrant
  2017-12-14 13:46     ` Jan Beulich
  2 siblings, 0 replies; 30+ messages in thread
From: Paul Durrant @ 2017-12-14  9:52 UTC (permalink / raw)
  To: xen-devel, Jan Beulich (JBeulich@suse.com)
  Cc: Stefano Stabellini, Wei Liu, Andrew Cooper, Tim (Xen.org),
	George Dunlap, Julien Grall, Ian Jackson

Actually adding Jan to the To: line this time...

> -----Original Message-----
> From: Paul Durrant
> Sent: 14 December 2017 09:52
> To: Paul Durrant <Paul.Durrant@citrix.com>; xen-devel@lists.xenproject.org
> Cc: George Dunlap <George.Dunlap@citrix.com>; Wei Liu
> <wei.liu2@citrix.com>; Andrew Cooper <Andrew.Cooper3@citrix.com>; Ian
> Jackson <Ian.Jackson@citrix.com>; Konrad Rzeszutek Wilk
> <konrad.wilk@oracle.com>; Stefano Stabellini <sstabellini@kernel.org>; Tim
> (Xen.org) <tim@xen.org>; Julien Grall <julien.grall@arm.com>
> Subject: RE: [PATCH v14 06/11] x86/hvm/ioreq: add a new mappable
> resource type...
> 
> > -----Original Message-----
> > From: Paul Durrant [mailto:paul.durrant@citrix.com]
> > Sent: 28 November 2017 15:09
> > To: xen-devel@lists.xenproject.org
> > Cc: Paul Durrant <Paul.Durrant@citrix.com>; George Dunlap
> > <George.Dunlap@citrix.com>; Wei Liu <wei.liu2@citrix.com>; Andrew
> > Cooper <Andrew.Cooper3@citrix.com>; Ian Jackson
> > <Ian.Jackson@citrix.com>; Konrad Rzeszutek Wilk
> > <konrad.wilk@oracle.com>; Stefano Stabellini <sstabellini@kernel.org>;
> Tim
> > (Xen.org) <tim@xen.org>; Julien Grall <julien.grall@arm.com>
> > Subject: [PATCH v14 06/11] x86/hvm/ioreq: add a new mappable resource
> > type...
> >
> > ... XENMEM_resource_ioreq_server
> >
> > This patch adds support for a new resource type that can be mapped using
> > the XENMEM_acquire_resource memory op.
> >
> > If an emulator makes use of this resource type then, instead of mapping
> > gfns, the IOREQ server will allocate pages from the heap. These pages
> > will never be present in the P2M of the guest at any point and so are
> > not vulnerable to any direct attack by the guest. They are only ever
> > accessible by Xen and any domain that has mapping privilege over the
> > guest (which may or may not be limited to the domain running the
> > emulator).
> >
> > NOTE: Use of the new resource type is not compatible with use of
> >       XEN_DMOP_get_ioreq_server_info unless the XEN_DMOP_no_gfns
> flag
> > is
> >       set.
> >
> > Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
> > Reviewed-by: Jan Beulich <jbeulich@suse.com>
> > ---
> > Cc: George Dunlap <George.Dunlap@eu.citrix.com>
> > Cc: Wei Liu <wei.liu2@citrix.com>
> > Cc: Andrew Cooper <andrew.cooper3@citrix.com>
> > Cc: Ian Jackson <ian.jackson@eu.citrix.com>
> > Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> > Cc: Stefano Stabellini <sstabellini@kernel.org>
> > Cc: Tim Deegan <tim@xen.org>
> > Cc: Julien Grall <julien.grall@arm.com>
> >
> > v14:
> >  - Addressed more comments from Jan.
> >
> > v13:
> >  - Introduce an arch_acquire_resource() as suggested by Julien (and have
> >    the ARM varient simply return -EOPNOTSUPP).
> >  - Check for ioreq server id truncation as requested by Jan.
> >  - Not added Jan's R-b due to substantive change from v12.
> >
> > v12:
> >  - Addressed more comments from Jan.
> >  - Dropped George's A-b and Wei's R-b because of material change.
> >
> > v11:
> >  - Addressed more comments from Jan.
> >
> > v10:
> >  - Addressed comments from Jan.
> >
> > v8:
> >  - Re-base on new boilerplate.
> >  - Adjust function signature of hvm_get_ioreq_server_frame(), and test
> >    whether the bufioreq page is present.
> >
> > v5:
> >  - Use get_ioreq_server() function rather than indexing array directly.
> >  - Add more explanation into comments to state than mapping guest
> frames
> >    and allocation of pages for ioreq servers are not simultaneously
> >    permitted.
> >  - Add a comment into asm/ioreq.h stating the meaning of the index
> >    value passed to hvm_get_ioreq_server_frame().
> > ---
> >  xen/arch/x86/hvm/ioreq.c        | 156
> > ++++++++++++++++++++++++++++++++++++++++
> >  xen/arch/x86/mm.c               |  41 +++++++++++
> >  xen/common/memory.c             |   3 +-
> >  xen/include/asm-arm/mm.h        |   7 ++
> >  xen/include/asm-x86/hvm/ioreq.h |   2 +
> >  xen/include/asm-x86/mm.h        |   5 ++
> >  xen/include/public/hvm/dm_op.h  |   4 ++
> >  xen/include/public/memory.h     |   9 +++
> >  8 files changed, 226 insertions(+), 1 deletion(-)
> >
> > diff --git a/xen/arch/x86/hvm/ioreq.c b/xen/arch/x86/hvm/ioreq.c
> > index 39de659ddf..d991ac9cdc 100644
> > --- a/xen/arch/x86/hvm/ioreq.c
> > +++ b/xen/arch/x86/hvm/ioreq.c
> > @@ -259,6 +259,19 @@ static int hvm_map_ioreq_gfn(struct
> > hvm_ioreq_server *s, bool buf)
> >      struct hvm_ioreq_page *iorp = buf ? &s->bufioreq : &s->ioreq;
> >      int rc;
> >
> > +    if ( iorp->page )
> > +    {
> > +        /*
> > +         * If a page has already been allocated (which will happen on
> > +         * demand if hvm_get_ioreq_server_frame() is called), then
> > +         * mapping a guest frame is not permitted.
> > +         */
> > +        if ( gfn_eq(iorp->gfn, INVALID_GFN) )
> > +            return -EPERM;
> > +
> > +        return 0;
> > +    }
> > +
> >      if ( d->is_dying )
> >          return -EINVAL;
> >
> > @@ -281,6 +294,70 @@ static int hvm_map_ioreq_gfn(struct
> > hvm_ioreq_server *s, bool buf)
> >      return rc;
> >  }
> >
> > +static int hvm_alloc_ioreq_mfn(struct hvm_ioreq_server *s, bool buf)
> > +{
> > +    struct domain *currd = current->domain;
> > +    struct hvm_ioreq_page *iorp = buf ? &s->bufioreq : &s->ioreq;
> > +
> > +    if ( iorp->page )
> > +    {
> > +        /*
> > +         * If a guest frame has already been mapped (which may happen
> > +         * on demand if hvm_get_ioreq_server_info() is called), then
> > +         * allocating a page is not permitted.
> > +         */
> > +        if ( !gfn_eq(iorp->gfn, INVALID_GFN) )
> > +            return -EPERM;
> > +
> > +        return 0;
> > +    }
> > +
> > +    /*
> > +     * Allocated IOREQ server pages are assigned to the emulating
> > +     * domain, not the target domain. This is because the emulator is
> > +     * likely to be destroyed after the target domain has been torn
> > +     * down, and we must use MEMF_no_refcount otherwise page
> allocation
> > +     * could fail if the emulating domain has already reached its
> > +     * maximum allocation.
> > +     */
> > +    iorp->page = alloc_domheap_page(currd, MEMF_no_refcount);
> 
> This is no longer going to work as it is predicated on my original modification
> to HYPERVISOR_mmu_update (which allowed a PV domain to map a foreign
> MFN from a domain over which it had privilege as if the MFN was local).
> Because that mechanism was decided against, this code needs to change to
> use the target domain of the ioreq server rather than the calling domain. I
> will verfy this modification and submit v15 of the series.
> 
> Jan, are you ok for me to keep your R-b?
> 
>   Paul
> 
> > +    if ( !iorp->page )
> > +        return -ENOMEM;
> > +
> > +    if ( !get_page_type(iorp->page, PGT_writable_page) )
> > +    {
> > +        ASSERT_UNREACHABLE();
> > +        put_page(iorp->page);
> > +        iorp->page = NULL;
> > +        return -ENOMEM;
> > +    }
> > +
> > +    iorp->va = __map_domain_page_global(iorp->page);
> > +    if ( !iorp->va )
> > +    {
> > +        put_page_and_type(iorp->page);
> > +        iorp->page = NULL;
> > +        return -ENOMEM;
> > +    }
> > +
> > +    clear_page(iorp->va);
> > +    return 0;
> > +}
> > +
> > +static void hvm_free_ioreq_mfn(struct hvm_ioreq_server *s, bool buf)
> > +{
> > +    struct hvm_ioreq_page *iorp = buf ? &s->bufioreq : &s->ioreq;
> > +
> > +    if ( !iorp->page )
> > +        return;
> > +
> > +    unmap_domain_page_global(iorp->va);
> > +    iorp->va = NULL;
> > +
> > +    put_page_and_type(iorp->page);
> > +    iorp->page = NULL;
> > +}
> > +
> >  bool is_ioreq_server_page(struct domain *d, const struct page_info
> *page)
> >  {
> >      const struct hvm_ioreq_server *s;
> > @@ -484,6 +561,27 @@ static void
> hvm_ioreq_server_unmap_pages(struct
> > hvm_ioreq_server *s)
> >      hvm_unmap_ioreq_gfn(s, false);
> >  }
> >
> > +static int hvm_ioreq_server_alloc_pages(struct hvm_ioreq_server *s)
> > +{
> > +    int rc;
> > +
> > +    rc = hvm_alloc_ioreq_mfn(s, false);
> > +
> > +    if ( !rc && (s->bufioreq_handling != HVM_IOREQSRV_BUFIOREQ_OFF) )
> > +        rc = hvm_alloc_ioreq_mfn(s, true);
> > +
> > +    if ( rc )
> > +        hvm_free_ioreq_mfn(s, false);
> > +
> > +    return rc;
> > +}
> > +
> > +static void hvm_ioreq_server_free_pages(struct hvm_ioreq_server *s)
> > +{
> > +    hvm_free_ioreq_mfn(s, true);
> > +    hvm_free_ioreq_mfn(s, false);
> > +}
> > +
> >  static void hvm_ioreq_server_free_rangesets(struct hvm_ioreq_server
> *s)
> >  {
> >      unsigned int i;
> > @@ -612,7 +710,18 @@ static int hvm_ioreq_server_init(struct
> > hvm_ioreq_server *s,
> >
> >   fail_add:
> >      hvm_ioreq_server_remove_all_vcpus(s);
> > +
> > +    /*
> > +     * NOTE: It is safe to call both hvm_ioreq_server_unmap_pages() and
> > +     *       hvm_ioreq_server_free_pages() in that order.
> > +     *       This is because the former will do nothing if the pages
> > +     *       are not mapped, leaving the page to be freed by the latter.
> > +     *       However if the pages are mapped then the former will set
> > +     *       the page_info pointer to NULL, meaning the latter will do
> > +     *       nothing.
> > +     */
> >      hvm_ioreq_server_unmap_pages(s);
> > +    hvm_ioreq_server_free_pages(s);
> >
> >      return rc;
> >  }
> > @@ -622,6 +731,7 @@ static void hvm_ioreq_server_deinit(struct
> > hvm_ioreq_server *s)
> >      ASSERT(!s->enabled);
> >      hvm_ioreq_server_remove_all_vcpus(s);
> >      hvm_ioreq_server_unmap_pages(s);
> > +    hvm_ioreq_server_free_pages(s);
> >      hvm_ioreq_server_free_rangesets(s);
> >  }
> >
> > @@ -777,6 +887,52 @@ int hvm_get_ioreq_server_info(struct domain *d,
> > ioservid_t id,
> >      return rc;
> >  }
> >
> > +int hvm_get_ioreq_server_frame(struct domain *d, ioservid_t id,
> > +                               unsigned long idx, mfn_t *mfn)
> > +{
> > +    struct hvm_ioreq_server *s;
> > +    int rc;
> > +
> > +    spin_lock_recursive(&d->arch.hvm_domain.ioreq_server.lock);
> > +
> > +    if ( id == DEFAULT_IOSERVID )
> > +        return -EOPNOTSUPP;
> > +
> > +    s = get_ioreq_server(d, id);
> > +
> > +    ASSERT(!IS_DEFAULT(s));
> > +
> > +    rc = hvm_ioreq_server_alloc_pages(s);
> > +    if ( rc )
> > +        goto out;
> > +
> > +    switch ( idx )
> > +    {
> > +    case XENMEM_resource_ioreq_server_frame_bufioreq:
> > +        rc = -ENOENT;
> > +        if ( !HANDLE_BUFIOREQ(s) )
> > +            goto out;
> > +
> > +        *mfn = _mfn(page_to_mfn(s->bufioreq.page));
> > +        rc = 0;
> > +        break;
> > +
> > +    case XENMEM_resource_ioreq_server_frame_ioreq(0):
> > +        *mfn = _mfn(page_to_mfn(s->ioreq.page));
> > +        rc = 0;
> > +        break;
> > +
> > +    default:
> > +        rc = -EINVAL;
> > +        break;
> > +    }
> > +
> > + out:
> > +    spin_unlock_recursive(&d->arch.hvm_domain.ioreq_server.lock);
> > +
> > +    return rc;
> > +}
> > +
> >  int hvm_map_io_range_to_ioreq_server(struct domain *d, ioservid_t id,
> >                                       uint32_t type, uint64_t start,
> >                                       uint64_t end)
> > diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
> > index 6ec6e68afe..2656eb181a 100644
> > --- a/xen/arch/x86/mm.c
> > +++ b/xen/arch/x86/mm.c
> > @@ -122,6 +122,7 @@
> >  #include <asm/fixmap.h>
> >  #include <asm/io_apic.h>
> >  #include <asm/pci.h>
> > +#include <asm/hvm/ioreq.h>
> >
> >  #include <asm/hvm/grant_table.h>
> >  #include <asm/pv/grant_table.h>
> > @@ -4170,6 +4171,46 @@ int xenmem_add_to_physmap_one(
> >      return rc;
> >  }
> >
> > +int arch_acquire_resource(struct domain *d, unsigned int type,
> > +                          unsigned int id, unsigned long frame,
> > +                          unsigned int nr_frames, xen_pfn_t mfn_list[])
> > +{
> > +    int rc;
> > +
> > +    switch ( type )
> > +    {
> > +    case XENMEM_resource_ioreq_server:
> > +    {
> > +        ioservid_t ioservid = id;
> > +        unsigned int i;
> > +
> > +        rc = -EINVAL;
> > +        if ( id != (unsigned int)ioservid )
> > +            break;
> > +
> > +        rc = 0;
> > +        for ( i = 0; i < nr_frames; i++ )
> > +        {
> > +            mfn_t mfn;
> > +
> > +            rc = hvm_get_ioreq_server_frame(d, id, frame + i, &mfn);
> > +            if ( rc )
> > +                break;
> > +
> > +            mfn_list[i] = mfn_x(mfn);
> > +        }
> > +
> > +        break;
> > +    }
> > +
> > +    default:
> > +        rc = -EOPNOTSUPP;
> > +        break;
> > +    }
> > +
> > +    return rc;
> > +}
> > +
> >  long arch_memory_op(unsigned long cmd,
> > XEN_GUEST_HANDLE_PARAM(void) arg)
> >  {
> >      int rc;
> > diff --git a/xen/common/memory.c b/xen/common/memory.c
> > index 6c385a2328..0167d9788b 100644
> > --- a/xen/common/memory.c
> > +++ b/xen/common/memory.c
> > @@ -1016,7 +1016,8 @@ static int acquire_resource(
> >      switch ( xmar.type )
> >      {
> >      default:
> > -        rc = -EOPNOTSUPP;
> > +        rc = arch_acquire_resource(d, xmar.type, xmar.id, xmar.frame,
> > +                                   xmar.nr_frames, mfn_list);
> >          break;
> >      }
> >
> > diff --git a/xen/include/asm-arm/mm.h b/xen/include/asm-arm/mm.h
> > index ad2f2a43dc..bd146dee3c 100644
> > --- a/xen/include/asm-arm/mm.h
> > +++ b/xen/include/asm-arm/mm.h
> > @@ -381,6 +381,13 @@ static inline void put_page_and_type(struct
> > page_info *page)
> >
> >  void clear_and_clean_page(struct page_info *page);
> >
> > +static inline int arch_acquire_resource(
> > +    struct domain *d, unsigned int type, unsigned int id,
> > +    unsigned long frame,unsigned int nr_frames, xen_pfn_t mfn_list[])
> > +{
> > +    return -EOPNOTSUPP;
> > +}
> > +
> >  #endif /*  __ARCH_ARM_MM__ */
> >  /*
> >   * Local variables:
> > diff --git a/xen/include/asm-x86/hvm/ioreq.h b/xen/include/asm-
> > x86/hvm/ioreq.h
> > index 1829fcf43e..9e37c97a37 100644
> > --- a/xen/include/asm-x86/hvm/ioreq.h
> > +++ b/xen/include/asm-x86/hvm/ioreq.h
> > @@ -31,6 +31,8 @@ int hvm_get_ioreq_server_info(struct domain *d,
> > ioservid_t id,
> >                                unsigned long *ioreq_gfn,
> >                                unsigned long *bufioreq_gfn,
> >                                evtchn_port_t *bufioreq_port);
> > +int hvm_get_ioreq_server_frame(struct domain *d, ioservid_t id,
> > +                               unsigned long idx, mfn_t *mfn);
> >  int hvm_map_io_range_to_ioreq_server(struct domain *d, ioservid_t id,
> >                                       uint32_t type, uint64_t start,
> >                                       uint64_t end);
> > diff --git a/xen/include/asm-x86/mm.h b/xen/include/asm-x86/mm.h
> > index 83626085e0..10e5b6cd14 100644
> > --- a/xen/include/asm-x86/mm.h
> > +++ b/xen/include/asm-x86/mm.h
> > @@ -629,4 +629,9 @@ static inline bool arch_mfn_in_directmap(unsigned
> > long mfn)
> >      return mfn <= (virt_to_mfn(eva - 1) + 1);
> >  }
> >
> > +int arch_acquire_resource(struct domain *d, unsigned int type,
> > +                          unsigned int id, unsigned long frame,
> > +                          unsigned int nr_frames,
> > +                          xen_pfn_t mfn_list[]);
> > +
> >  #endif /* __ASM_X86_MM_H__ */
> > diff --git a/xen/include/public/hvm/dm_op.h
> > b/xen/include/public/hvm/dm_op.h
> > index 13b3737c2f..add68ea192 100644
> > --- a/xen/include/public/hvm/dm_op.h
> > +++ b/xen/include/public/hvm/dm_op.h
> > @@ -90,6 +90,10 @@ struct xen_dm_op_create_ioreq_server {
> >   * the frame numbers passed back in gfns <ioreq_gfn> and
> <bufioreq_gfn>
> >   * respectively. (If the IOREQ Server is not handling buffered emulation
> >   * only <ioreq_gfn> will be valid).
> > + *
> > + * NOTE: To access the synchronous ioreq structures and buffered ioreq
> > + *       ring, it is preferable to use the XENMEM_acquire_resource memory
> > + *       op specifying resource type XENMEM_resource_ioreq_server.
> >   */
> >  #define XEN_DMOP_get_ioreq_server_info 2
> >
> > diff --git a/xen/include/public/memory.h b/xen/include/public/memory.h
> > index 83e60b6603..838f248a59 100644
> > --- a/xen/include/public/memory.h
> > +++ b/xen/include/public/memory.h
> > @@ -609,9 +609,14 @@ struct xen_mem_acquire_resource {
> >      domid_t domid;
> >      /* IN - the type of resource */
> >      uint16_t type;
> > +
> > +#define XENMEM_resource_ioreq_server 0
> > +
> >      /*
> >       * IN - a type-specific resource identifier, which must be zero
> >       *      unless stated otherwise.
> > +     *
> > +     * type == XENMEM_resource_ioreq_server -> id == ioreq server id
> >       */
> >      uint32_t id;
> >      /* IN/OUT - As an IN parameter number of frames of the resource
> > @@ -625,6 +630,10 @@ struct xen_mem_acquire_resource {
> >       *      is ignored if nr_frames is 0.
> >       */
> >      uint64_aligned_t frame;
> > +
> > +#define XENMEM_resource_ioreq_server_frame_bufioreq 0
> > +#define XENMEM_resource_ioreq_server_frame_ioreq(n) (1 + (n))
> > +
> >      /* IN/OUT - If the tools domain is PV then, upon return, frame_list
> >       *          will be populated with the MFNs of the resource.
> >       *          If the tools domain is HVM then it is expected that, on
> > --
> > 2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v14 06/11] x86/hvm/ioreq: add a new mappable resource type...
  2017-12-14  9:51   ` Paul Durrant
  2017-12-14  9:52     ` Paul Durrant
@ 2017-12-14 10:31     ` Paul Durrant
  2017-12-14 13:46     ` Jan Beulich
  2 siblings, 0 replies; 30+ messages in thread
From: Paul Durrant @ 2017-12-14 10:31 UTC (permalink / raw)
  To: xen-devel
  Cc: Stefano Stabellini, Wei Liu, Andrew Cooper, Tim (Xen.org),
	George Dunlap, Julien Grall, Ian Jackson

> -----Original Message-----
> From: Paul Durrant
> Sent: 14 December 2017 09:52
> To: Paul Durrant <Paul.Durrant@citrix.com>; xen-devel@lists.xenproject.org
> Cc: George Dunlap <George.Dunlap@citrix.com>; Wei Liu
> <wei.liu2@citrix.com>; Andrew Cooper <Andrew.Cooper3@citrix.com>; Ian
> Jackson <Ian.Jackson@citrix.com>; Konrad Rzeszutek Wilk
> <konrad.wilk@oracle.com>; Stefano Stabellini <sstabellini@kernel.org>; Tim
> (Xen.org) <tim@xen.org>; Julien Grall <julien.grall@arm.com>
> Subject: RE: [PATCH v14 06/11] x86/hvm/ioreq: add a new mappable
> resource type...
> 
> > -----Original Message-----
> > From: Paul Durrant [mailto:paul.durrant@citrix.com]
> > Sent: 28 November 2017 15:09
> > To: xen-devel@lists.xenproject.org
> > Cc: Paul Durrant <Paul.Durrant@citrix.com>; George Dunlap
> > <George.Dunlap@citrix.com>; Wei Liu <wei.liu2@citrix.com>; Andrew
> > Cooper <Andrew.Cooper3@citrix.com>; Ian Jackson
> > <Ian.Jackson@citrix.com>; Konrad Rzeszutek Wilk
> > <konrad.wilk@oracle.com>; Stefano Stabellini <sstabellini@kernel.org>;
> Tim
> > (Xen.org) <tim@xen.org>; Julien Grall <julien.grall@arm.com>
> > Subject: [PATCH v14 06/11] x86/hvm/ioreq: add a new mappable resource
> > type...
> >
> > ... XENMEM_resource_ioreq_server
> >
> > This patch adds support for a new resource type that can be mapped using
> > the XENMEM_acquire_resource memory op.
> >
> > If an emulator makes use of this resource type then, instead of mapping
> > gfns, the IOREQ server will allocate pages from the heap. These pages
> > will never be present in the P2M of the guest at any point and so are
> > not vulnerable to any direct attack by the guest. They are only ever
> > accessible by Xen and any domain that has mapping privilege over the
> > guest (which may or may not be limited to the domain running the
> > emulator).
> >
> > NOTE: Use of the new resource type is not compatible with use of
> >       XEN_DMOP_get_ioreq_server_info unless the XEN_DMOP_no_gfns
> flag
> > is
> >       set.
> >
> > Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
> > Reviewed-by: Jan Beulich <jbeulich@suse.com>
> > ---
> > Cc: George Dunlap <George.Dunlap@eu.citrix.com>
> > Cc: Wei Liu <wei.liu2@citrix.com>
> > Cc: Andrew Cooper <andrew.cooper3@citrix.com>
> > Cc: Ian Jackson <ian.jackson@eu.citrix.com>
> > Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> > Cc: Stefano Stabellini <sstabellini@kernel.org>
> > Cc: Tim Deegan <tim@xen.org>
> > Cc: Julien Grall <julien.grall@arm.com>
> >
> > v14:
> >  - Addressed more comments from Jan.
> >
> > v13:
> >  - Introduce an arch_acquire_resource() as suggested by Julien (and have
> >    the ARM varient simply return -EOPNOTSUPP).
> >  - Check for ioreq server id truncation as requested by Jan.
> >  - Not added Jan's R-b due to substantive change from v12.
> >
> > v12:
> >  - Addressed more comments from Jan.
> >  - Dropped George's A-b and Wei's R-b because of material change.
> >
> > v11:
> >  - Addressed more comments from Jan.
> >
> > v10:
> >  - Addressed comments from Jan.
> >
> > v8:
> >  - Re-base on new boilerplate.
> >  - Adjust function signature of hvm_get_ioreq_server_frame(), and test
> >    whether the bufioreq page is present.
> >
> > v5:
> >  - Use get_ioreq_server() function rather than indexing array directly.
> >  - Add more explanation into comments to state than mapping guest
> frames
> >    and allocation of pages for ioreq servers are not simultaneously
> >    permitted.
> >  - Add a comment into asm/ioreq.h stating the meaning of the index
> >    value passed to hvm_get_ioreq_server_frame().
> > ---
> >  xen/arch/x86/hvm/ioreq.c        | 156
> > ++++++++++++++++++++++++++++++++++++++++
> >  xen/arch/x86/mm.c               |  41 +++++++++++
> >  xen/common/memory.c             |   3 +-
> >  xen/include/asm-arm/mm.h        |   7 ++
> >  xen/include/asm-x86/hvm/ioreq.h |   2 +
> >  xen/include/asm-x86/mm.h        |   5 ++
> >  xen/include/public/hvm/dm_op.h  |   4 ++
> >  xen/include/public/memory.h     |   9 +++
> >  8 files changed, 226 insertions(+), 1 deletion(-)
> >
> > diff --git a/xen/arch/x86/hvm/ioreq.c b/xen/arch/x86/hvm/ioreq.c
> > index 39de659ddf..d991ac9cdc 100644
> > --- a/xen/arch/x86/hvm/ioreq.c
> > +++ b/xen/arch/x86/hvm/ioreq.c
> > @@ -259,6 +259,19 @@ static int hvm_map_ioreq_gfn(struct
> > hvm_ioreq_server *s, bool buf)
> >      struct hvm_ioreq_page *iorp = buf ? &s->bufioreq : &s->ioreq;
> >      int rc;
> >
> > +    if ( iorp->page )
> > +    {
> > +        /*
> > +         * If a page has already been allocated (which will happen on
> > +         * demand if hvm_get_ioreq_server_frame() is called), then
> > +         * mapping a guest frame is not permitted.
> > +         */
> > +        if ( gfn_eq(iorp->gfn, INVALID_GFN) )
> > +            return -EPERM;
> > +
> > +        return 0;
> > +    }
> > +
> >      if ( d->is_dying )
> >          return -EINVAL;
> >
> > @@ -281,6 +294,70 @@ static int hvm_map_ioreq_gfn(struct
> > hvm_ioreq_server *s, bool buf)
> >      return rc;
> >  }
> >
> > +static int hvm_alloc_ioreq_mfn(struct hvm_ioreq_server *s, bool buf)
> > +{
> > +    struct domain *currd = current->domain;
> > +    struct hvm_ioreq_page *iorp = buf ? &s->bufioreq : &s->ioreq;
> > +
> > +    if ( iorp->page )
> > +    {
> > +        /*
> > +         * If a guest frame has already been mapped (which may happen
> > +         * on demand if hvm_get_ioreq_server_info() is called), then
> > +         * allocating a page is not permitted.
> > +         */
> > +        if ( !gfn_eq(iorp->gfn, INVALID_GFN) )
> > +            return -EPERM;
> > +
> > +        return 0;
> > +    }
> > +
> > +    /*
> > +     * Allocated IOREQ server pages are assigned to the emulating
> > +     * domain, not the target domain. This is because the emulator is
> > +     * likely to be destroyed after the target domain has been torn
> > +     * down, and we must use MEMF_no_refcount otherwise page
> allocation
> > +     * could fail if the emulating domain has already reached its
> > +     * maximum allocation.
> > +     */
> > +    iorp->page = alloc_domheap_page(currd, MEMF_no_refcount);
> 
> This is no longer going to work as it is predicated on my original modification
> to HYPERVISOR_mmu_update (which allowed a PV domain to map a foreign
> MFN from a domain over which it had privilege as if the MFN was local).
> Because that mechanism was decided against, this code needs to change to
> use the target domain of the ioreq server rather than the calling domain. I
> will verfy this modification and submit v15 of the series.

Actually, I should read my own comments more closely...

I can't use the target domain otherwise the page gets yanked from underneath the ioreq server (because the page ends up in the target domain's page list) so the best option I see is to leave this as it is and call page_set_owner(..., s->domain) on the page directly.

  Paul

> 
> Jan, are you ok for me to keep your R-b?
> 
>   Paul
> 
> > +    if ( !iorp->page )
> > +        return -ENOMEM;
> > +
> > +    if ( !get_page_type(iorp->page, PGT_writable_page) )
> > +    {
> > +        ASSERT_UNREACHABLE();
> > +        put_page(iorp->page);
> > +        iorp->page = NULL;
> > +        return -ENOMEM;
> > +    }
> > +
> > +    iorp->va = __map_domain_page_global(iorp->page);
> > +    if ( !iorp->va )
> > +    {
> > +        put_page_and_type(iorp->page);
> > +        iorp->page = NULL;
> > +        return -ENOMEM;
> > +    }
> > +
> > +    clear_page(iorp->va);
> > +    return 0;
> > +}
> > +
> > +static void hvm_free_ioreq_mfn(struct hvm_ioreq_server *s, bool buf)
> > +{
> > +    struct hvm_ioreq_page *iorp = buf ? &s->bufioreq : &s->ioreq;
> > +
> > +    if ( !iorp->page )
> > +        return;
> > +
> > +    unmap_domain_page_global(iorp->va);
> > +    iorp->va = NULL;
> > +
> > +    put_page_and_type(iorp->page);
> > +    iorp->page = NULL;
> > +}
> > +
> >  bool is_ioreq_server_page(struct domain *d, const struct page_info
> *page)
> >  {
> >      const struct hvm_ioreq_server *s;
> > @@ -484,6 +561,27 @@ static void
> hvm_ioreq_server_unmap_pages(struct
> > hvm_ioreq_server *s)
> >      hvm_unmap_ioreq_gfn(s, false);
> >  }
> >
> > +static int hvm_ioreq_server_alloc_pages(struct hvm_ioreq_server *s)
> > +{
> > +    int rc;
> > +
> > +    rc = hvm_alloc_ioreq_mfn(s, false);
> > +
> > +    if ( !rc && (s->bufioreq_handling != HVM_IOREQSRV_BUFIOREQ_OFF) )
> > +        rc = hvm_alloc_ioreq_mfn(s, true);
> > +
> > +    if ( rc )
> > +        hvm_free_ioreq_mfn(s, false);
> > +
> > +    return rc;
> > +}
> > +
> > +static void hvm_ioreq_server_free_pages(struct hvm_ioreq_server *s)
> > +{
> > +    hvm_free_ioreq_mfn(s, true);
> > +    hvm_free_ioreq_mfn(s, false);
> > +}
> > +
> >  static void hvm_ioreq_server_free_rangesets(struct hvm_ioreq_server
> *s)
> >  {
> >      unsigned int i;
> > @@ -612,7 +710,18 @@ static int hvm_ioreq_server_init(struct
> > hvm_ioreq_server *s,
> >
> >   fail_add:
> >      hvm_ioreq_server_remove_all_vcpus(s);
> > +
> > +    /*
> > +     * NOTE: It is safe to call both hvm_ioreq_server_unmap_pages() and
> > +     *       hvm_ioreq_server_free_pages() in that order.
> > +     *       This is because the former will do nothing if the pages
> > +     *       are not mapped, leaving the page to be freed by the latter.
> > +     *       However if the pages are mapped then the former will set
> > +     *       the page_info pointer to NULL, meaning the latter will do
> > +     *       nothing.
> > +     */
> >      hvm_ioreq_server_unmap_pages(s);
> > +    hvm_ioreq_server_free_pages(s);
> >
> >      return rc;
> >  }
> > @@ -622,6 +731,7 @@ static void hvm_ioreq_server_deinit(struct
> > hvm_ioreq_server *s)
> >      ASSERT(!s->enabled);
> >      hvm_ioreq_server_remove_all_vcpus(s);
> >      hvm_ioreq_server_unmap_pages(s);
> > +    hvm_ioreq_server_free_pages(s);
> >      hvm_ioreq_server_free_rangesets(s);
> >  }
> >
> > @@ -777,6 +887,52 @@ int hvm_get_ioreq_server_info(struct domain *d,
> > ioservid_t id,
> >      return rc;
> >  }
> >
> > +int hvm_get_ioreq_server_frame(struct domain *d, ioservid_t id,
> > +                               unsigned long idx, mfn_t *mfn)
> > +{
> > +    struct hvm_ioreq_server *s;
> > +    int rc;
> > +
> > +    spin_lock_recursive(&d->arch.hvm_domain.ioreq_server.lock);
> > +
> > +    if ( id == DEFAULT_IOSERVID )
> > +        return -EOPNOTSUPP;
> > +
> > +    s = get_ioreq_server(d, id);
> > +
> > +    ASSERT(!IS_DEFAULT(s));
> > +
> > +    rc = hvm_ioreq_server_alloc_pages(s);
> > +    if ( rc )
> > +        goto out;
> > +
> > +    switch ( idx )
> > +    {
> > +    case XENMEM_resource_ioreq_server_frame_bufioreq:
> > +        rc = -ENOENT;
> > +        if ( !HANDLE_BUFIOREQ(s) )
> > +            goto out;
> > +
> > +        *mfn = _mfn(page_to_mfn(s->bufioreq.page));
> > +        rc = 0;
> > +        break;
> > +
> > +    case XENMEM_resource_ioreq_server_frame_ioreq(0):
> > +        *mfn = _mfn(page_to_mfn(s->ioreq.page));
> > +        rc = 0;
> > +        break;
> > +
> > +    default:
> > +        rc = -EINVAL;
> > +        break;
> > +    }
> > +
> > + out:
> > +    spin_unlock_recursive(&d->arch.hvm_domain.ioreq_server.lock);
> > +
> > +    return rc;
> > +}
> > +
> >  int hvm_map_io_range_to_ioreq_server(struct domain *d, ioservid_t id,
> >                                       uint32_t type, uint64_t start,
> >                                       uint64_t end)
> > diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
> > index 6ec6e68afe..2656eb181a 100644
> > --- a/xen/arch/x86/mm.c
> > +++ b/xen/arch/x86/mm.c
> > @@ -122,6 +122,7 @@
> >  #include <asm/fixmap.h>
> >  #include <asm/io_apic.h>
> >  #include <asm/pci.h>
> > +#include <asm/hvm/ioreq.h>
> >
> >  #include <asm/hvm/grant_table.h>
> >  #include <asm/pv/grant_table.h>
> > @@ -4170,6 +4171,46 @@ int xenmem_add_to_physmap_one(
> >      return rc;
> >  }
> >
> > +int arch_acquire_resource(struct domain *d, unsigned int type,
> > +                          unsigned int id, unsigned long frame,
> > +                          unsigned int nr_frames, xen_pfn_t mfn_list[])
> > +{
> > +    int rc;
> > +
> > +    switch ( type )
> > +    {
> > +    case XENMEM_resource_ioreq_server:
> > +    {
> > +        ioservid_t ioservid = id;
> > +        unsigned int i;
> > +
> > +        rc = -EINVAL;
> > +        if ( id != (unsigned int)ioservid )
> > +            break;
> > +
> > +        rc = 0;
> > +        for ( i = 0; i < nr_frames; i++ )
> > +        {
> > +            mfn_t mfn;
> > +
> > +            rc = hvm_get_ioreq_server_frame(d, id, frame + i, &mfn);
> > +            if ( rc )
> > +                break;
> > +
> > +            mfn_list[i] = mfn_x(mfn);
> > +        }
> > +
> > +        break;
> > +    }
> > +
> > +    default:
> > +        rc = -EOPNOTSUPP;
> > +        break;
> > +    }
> > +
> > +    return rc;
> > +}
> > +
> >  long arch_memory_op(unsigned long cmd,
> > XEN_GUEST_HANDLE_PARAM(void) arg)
> >  {
> >      int rc;
> > diff --git a/xen/common/memory.c b/xen/common/memory.c
> > index 6c385a2328..0167d9788b 100644
> > --- a/xen/common/memory.c
> > +++ b/xen/common/memory.c
> > @@ -1016,7 +1016,8 @@ static int acquire_resource(
> >      switch ( xmar.type )
> >      {
> >      default:
> > -        rc = -EOPNOTSUPP;
> > +        rc = arch_acquire_resource(d, xmar.type, xmar.id, xmar.frame,
> > +                                   xmar.nr_frames, mfn_list);
> >          break;
> >      }
> >
> > diff --git a/xen/include/asm-arm/mm.h b/xen/include/asm-arm/mm.h
> > index ad2f2a43dc..bd146dee3c 100644
> > --- a/xen/include/asm-arm/mm.h
> > +++ b/xen/include/asm-arm/mm.h
> > @@ -381,6 +381,13 @@ static inline void put_page_and_type(struct
> > page_info *page)
> >
> >  void clear_and_clean_page(struct page_info *page);
> >
> > +static inline int arch_acquire_resource(
> > +    struct domain *d, unsigned int type, unsigned int id,
> > +    unsigned long frame,unsigned int nr_frames, xen_pfn_t mfn_list[])
> > +{
> > +    return -EOPNOTSUPP;
> > +}
> > +
> >  #endif /*  __ARCH_ARM_MM__ */
> >  /*
> >   * Local variables:
> > diff --git a/xen/include/asm-x86/hvm/ioreq.h b/xen/include/asm-
> > x86/hvm/ioreq.h
> > index 1829fcf43e..9e37c97a37 100644
> > --- a/xen/include/asm-x86/hvm/ioreq.h
> > +++ b/xen/include/asm-x86/hvm/ioreq.h
> > @@ -31,6 +31,8 @@ int hvm_get_ioreq_server_info(struct domain *d,
> > ioservid_t id,
> >                                unsigned long *ioreq_gfn,
> >                                unsigned long *bufioreq_gfn,
> >                                evtchn_port_t *bufioreq_port);
> > +int hvm_get_ioreq_server_frame(struct domain *d, ioservid_t id,
> > +                               unsigned long idx, mfn_t *mfn);
> >  int hvm_map_io_range_to_ioreq_server(struct domain *d, ioservid_t id,
> >                                       uint32_t type, uint64_t start,
> >                                       uint64_t end);
> > diff --git a/xen/include/asm-x86/mm.h b/xen/include/asm-x86/mm.h
> > index 83626085e0..10e5b6cd14 100644
> > --- a/xen/include/asm-x86/mm.h
> > +++ b/xen/include/asm-x86/mm.h
> > @@ -629,4 +629,9 @@ static inline bool arch_mfn_in_directmap(unsigned
> > long mfn)
> >      return mfn <= (virt_to_mfn(eva - 1) + 1);
> >  }
> >
> > +int arch_acquire_resource(struct domain *d, unsigned int type,
> > +                          unsigned int id, unsigned long frame,
> > +                          unsigned int nr_frames,
> > +                          xen_pfn_t mfn_list[]);
> > +
> >  #endif /* __ASM_X86_MM_H__ */
> > diff --git a/xen/include/public/hvm/dm_op.h
> > b/xen/include/public/hvm/dm_op.h
> > index 13b3737c2f..add68ea192 100644
> > --- a/xen/include/public/hvm/dm_op.h
> > +++ b/xen/include/public/hvm/dm_op.h
> > @@ -90,6 +90,10 @@ struct xen_dm_op_create_ioreq_server {
> >   * the frame numbers passed back in gfns <ioreq_gfn> and
> <bufioreq_gfn>
> >   * respectively. (If the IOREQ Server is not handling buffered emulation
> >   * only <ioreq_gfn> will be valid).
> > + *
> > + * NOTE: To access the synchronous ioreq structures and buffered ioreq
> > + *       ring, it is preferable to use the XENMEM_acquire_resource memory
> > + *       op specifying resource type XENMEM_resource_ioreq_server.
> >   */
> >  #define XEN_DMOP_get_ioreq_server_info 2
> >
> > diff --git a/xen/include/public/memory.h b/xen/include/public/memory.h
> > index 83e60b6603..838f248a59 100644
> > --- a/xen/include/public/memory.h
> > +++ b/xen/include/public/memory.h
> > @@ -609,9 +609,14 @@ struct xen_mem_acquire_resource {
> >      domid_t domid;
> >      /* IN - the type of resource */
> >      uint16_t type;
> > +
> > +#define XENMEM_resource_ioreq_server 0
> > +
> >      /*
> >       * IN - a type-specific resource identifier, which must be zero
> >       *      unless stated otherwise.
> > +     *
> > +     * type == XENMEM_resource_ioreq_server -> id == ioreq server id
> >       */
> >      uint32_t id;
> >      /* IN/OUT - As an IN parameter number of frames of the resource
> > @@ -625,6 +630,10 @@ struct xen_mem_acquire_resource {
> >       *      is ignored if nr_frames is 0.
> >       */
> >      uint64_aligned_t frame;
> > +
> > +#define XENMEM_resource_ioreq_server_frame_bufioreq 0
> > +#define XENMEM_resource_ioreq_server_frame_ioreq(n) (1 + (n))
> > +
> >      /* IN/OUT - If the tools domain is PV then, upon return, frame_list
> >       *          will be populated with the MFNs of the resource.
> >       *          If the tools domain is HVM then it is expected that, on
> > --
> > 2.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v14 06/11] x86/hvm/ioreq: add a new mappable resource type...
  2017-12-14  9:51   ` Paul Durrant
  2017-12-14  9:52     ` Paul Durrant
  2017-12-14 10:31     ` Paul Durrant
@ 2017-12-14 13:46     ` Jan Beulich
  2017-12-14 13:46       ` Paul Durrant
  2 siblings, 1 reply; 30+ messages in thread
From: Jan Beulich @ 2017-12-14 13:46 UTC (permalink / raw)
  To: Paul Durrant
  Cc: Stefano Stabellini, Wei Liu, Andrew Cooper, Tim (Xen.org),
	George Dunlap, Julien Grall, xen-devel, Ian Jackson

>>> On 14.12.17 at 10:51, <Paul.Durrant@citrix.com> wrote:
>> From: Paul Durrant [mailto:paul.durrant@citrix.com]
>> Sent: 28 November 2017 15:09
>> +static int hvm_alloc_ioreq_mfn(struct hvm_ioreq_server *s, bool buf)
>> +{
>> +    struct domain *currd = current->domain;
>> +    struct hvm_ioreq_page *iorp = buf ? &s->bufioreq : &s->ioreq;
>> +
>> +    if ( iorp->page )
>> +    {
>> +        /*
>> +         * If a guest frame has already been mapped (which may happen
>> +         * on demand if hvm_get_ioreq_server_info() is called), then
>> +         * allocating a page is not permitted.
>> +         */
>> +        if ( !gfn_eq(iorp->gfn, INVALID_GFN) )
>> +            return -EPERM;
>> +
>> +        return 0;
>> +    }
>> +
>> +    /*
>> +     * Allocated IOREQ server pages are assigned to the emulating
>> +     * domain, not the target domain. This is because the emulator is
>> +     * likely to be destroyed after the target domain has been torn
>> +     * down, and we must use MEMF_no_refcount otherwise page allocation
>> +     * could fail if the emulating domain has already reached its
>> +     * maximum allocation.
>> +     */
>> +    iorp->page = alloc_domheap_page(currd, MEMF_no_refcount);
> 
> This is no longer going to work as it is predicated on my original 
> modification to HYPERVISOR_mmu_update (which allowed a PV domain to map a 
> foreign MFN from a domain over which it had privilege as if the MFN was 
> local). Because that mechanism was decided against, this code needs to change 
> to use the target domain of the ioreq server rather than the calling domain. 
> I will verfy this modification and submit v15 of the series.
> 
> Jan, are you ok for me to keep your R-b?

This is all pretty fragile - better drop it and I'll then take a look
once you've sent the new version.

Jan


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v14 06/11] x86/hvm/ioreq: add a new mappable resource type...
  2017-12-14 13:46     ` Jan Beulich
@ 2017-12-14 13:46       ` Paul Durrant
  0 siblings, 0 replies; 30+ messages in thread
From: Paul Durrant @ 2017-12-14 13:46 UTC (permalink / raw)
  To: 'Jan Beulich'
  Cc: Stefano Stabellini, Wei Liu, Andrew Cooper, Tim (Xen.org),
	George Dunlap, Julien Grall, xen-devel, Ian Jackson

> -----Original Message-----
> From: Jan Beulich [mailto:JBeulich@suse.com]
> Sent: 14 December 2017 13:46
> To: Paul Durrant <Paul.Durrant@citrix.com>
> Cc: Julien Grall <julien.grall@arm.com>; Andrew Cooper
> <Andrew.Cooper3@citrix.com>; George Dunlap
> <George.Dunlap@citrix.com>; Ian Jackson <Ian.Jackson@citrix.com>; Wei Liu
> <wei.liu2@citrix.com>; Stefano Stabellini <sstabellini@kernel.org>; xen-
> devel@lists.xenproject.org; Tim (Xen.org) <tim@xen.org>
> Subject: Re: [PATCH v14 06/11] x86/hvm/ioreq: add a new mappable
> resource type...
> 
> >>> On 14.12.17 at 10:51, <Paul.Durrant@citrix.com> wrote:
> >> From: Paul Durrant [mailto:paul.durrant@citrix.com]
> >> Sent: 28 November 2017 15:09
> >> +static int hvm_alloc_ioreq_mfn(struct hvm_ioreq_server *s, bool buf)
> >> +{
> >> +    struct domain *currd = current->domain;
> >> +    struct hvm_ioreq_page *iorp = buf ? &s->bufioreq : &s->ioreq;
> >> +
> >> +    if ( iorp->page )
> >> +    {
> >> +        /*
> >> +         * If a guest frame has already been mapped (which may happen
> >> +         * on demand if hvm_get_ioreq_server_info() is called), then
> >> +         * allocating a page is not permitted.
> >> +         */
> >> +        if ( !gfn_eq(iorp->gfn, INVALID_GFN) )
> >> +            return -EPERM;
> >> +
> >> +        return 0;
> >> +    }
> >> +
> >> +    /*
> >> +     * Allocated IOREQ server pages are assigned to the emulating
> >> +     * domain, not the target domain. This is because the emulator is
> >> +     * likely to be destroyed after the target domain has been torn
> >> +     * down, and we must use MEMF_no_refcount otherwise page
> allocation
> >> +     * could fail if the emulating domain has already reached its
> >> +     * maximum allocation.
> >> +     */
> >> +    iorp->page = alloc_domheap_page(currd, MEMF_no_refcount);
> >
> > This is no longer going to work as it is predicated on my original
> > modification to HYPERVISOR_mmu_update (which allowed a PV domain to
> map a
> > foreign MFN from a domain over which it had privilege as if the MFN was
> > local). Because that mechanism was decided against, this code needs to
> change
> > to use the target domain of the ioreq server rather than the calling domain.
> > I will verfy this modification and submit v15 of the series.
> >
> > Jan, are you ok for me to keep your R-b?
> 
> This is all pretty fragile - better drop it and I'll then take a look
> once you've sent the new version.

Ok. Will do.

  Paul

> 
> Jan


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH v14 07/11] x86/mm: add an extra command to HYPERVISOR_mmu_update...
  2017-12-13 17:03                 ` Paul Durrant
@ 2017-12-14 13:50                   ` Jan Beulich
  0 siblings, 0 replies; 30+ messages in thread
From: Jan Beulich @ 2017-12-14 13:50 UTC (permalink / raw)
  To: Paul Durrant
  Cc: Stefano Stabellini, Wei Liu, Andrew Cooper, Tim(Xen.org),
	George Dunlap, Ian Jackson, xen-devel

>>> On 13.12.17 at 18:03, <Paul.Durrant@citrix.com> wrote:
> Looking through the code, the only one thing that bothers me is the 
> page_set_owner() done in shadow_enable() for the page used for HVM guest 
> vcpus that have paging disabled. AFAICT that page would become mappable by an 
> emulating domain with MMU_PT_UPDATE_NO_TRANSLATE, if it figured out or 
> guessed the correct MFN, but I'm not sure whether damage could be done to Xen 
> using that.

I was afraid of a problem here too, but Tim did convince me that
there's no problem as this is a page table being shadowed, not a
page table the guest actually runs on. Corrupting the page's
contents would only affect the guest (just like is the case for any
other guest page tables).

Jan


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

end of thread, other threads:[~2017-12-14 13:50 UTC | newest]

Thread overview: 30+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-11-28 15:08 [PATCH v14 00/11] x86: guest resource mapping Paul Durrant
2017-11-28 15:08 ` [PATCH v14 01/11] x86/hvm/ioreq: maintain an array of ioreq servers rather than a list Paul Durrant
2017-11-28 15:08 ` [PATCH v14 02/11] x86/hvm/ioreq: simplify code and use consistent naming Paul Durrant
2017-11-28 15:08 ` [PATCH v14 03/11] x86/hvm/ioreq: use gfn_t in struct hvm_ioreq_page Paul Durrant
2017-11-28 15:08 ` [PATCH v14 04/11] x86/hvm/ioreq: defer mapping gfns until they are actually requsted Paul Durrant
2017-12-06 21:49   ` Chao Gao
2017-12-07  8:38     ` Paul Durrant
2017-11-28 15:08 ` [PATCH v14 05/11] x86/mm: add HYPERVISOR_memory_op to acquire guest resources Paul Durrant
2017-11-28 18:50   ` Daniel De Graaf
2017-11-28 15:08 ` [PATCH v14 06/11] x86/hvm/ioreq: add a new mappable resource type Paul Durrant
2017-12-14  9:51   ` Paul Durrant
2017-12-14  9:52     ` Paul Durrant
2017-12-14 10:31     ` Paul Durrant
2017-12-14 13:46     ` Jan Beulich
2017-12-14 13:46       ` Paul Durrant
2017-11-28 15:08 ` [PATCH v14 07/11] x86/mm: add an extra command to HYPERVISOR_mmu_update Paul Durrant
2017-12-12 13:25   ` Jan Beulich
2017-12-12 13:52     ` Andrew Cooper
2017-12-12 14:38       ` Jan Beulich
2017-12-13 12:06         ` Paul Durrant
2017-12-13 14:35           ` Jan Beulich
2017-12-13 14:49             ` Paul Durrant
2017-12-13 15:24               ` Jan Beulich
2017-12-13 17:03                 ` Paul Durrant
2017-12-14 13:50                   ` Jan Beulich
2017-12-12 14:54     ` Paul Durrant
2017-11-28 15:08 ` [PATCH v14 08/11] tools/libxenforeignmemory: add support for resource mapping Paul Durrant
2017-11-28 15:08 ` [PATCH v14 09/11] tools/libxenforeignmemory: reduce xenforeignmemory_restrict code footprint Paul Durrant
2017-11-28 15:08 ` [PATCH v14 10/11] common: add a new mappable resource type: XENMEM_resource_grant_table Paul Durrant
2017-11-28 15:08 ` [PATCH v14 11/11] tools/libxenctrl: use new xenforeignmemory API to seed grant table Paul Durrant

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.