[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH v4 6/8] ioreq-server: remove p2m entries when server is enabled



For secondary servers, add a hvm op to enable/disable the server. The
server will not accept IO until it is enabled and the act of enabling
the server removes its pages from the guest p2m, thus preventing the guest
from directly mapping the pages and synthesizing ioreqs.

Signed-off-by: Paul Durrant <paul.durrant@xxxxxxxxxx>
Cc: Ian Jackson <ian.jackson@xxxxxxxxxxxxx>
Cc: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>
Cc: Ian Campbell <ian.campbell@xxxxxxxxxx>
Cc: Jan Beulich <jbeulich@xxxxxxxx>
---
 tools/libxc/xc_domain.c          |   24 ++++++++
 tools/libxc/xenctrl.h            |    5 ++
 xen/arch/x86/hvm/hvm.c           |  115 +++++++++++++++++++++++++++++++++++++-
 xen/include/asm-x86/hvm/domain.h |    1 +
 xen/include/public/hvm/hvm_op.h  |   33 +++++++----
 5 files changed, 164 insertions(+), 14 deletions(-)

diff --git a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c
index 8cec171..67829c5 100644
--- a/tools/libxc/xc_domain.c
+++ b/tools/libxc/xc_domain.c
@@ -1459,6 +1459,30 @@ int xc_hvm_destroy_ioreq_server(xc_interface *xch,
     return rc;
 }
 
+int xc_hvm_set_ioreq_server_state(xc_interface *xch,
+                                  domid_t domid,
+                                  ioservid_t id,
+                                  int enabled)
+{
+    DECLARE_HYPERCALL;
+    DECLARE_HYPERCALL_BUFFER(xen_hvm_set_ioreq_server_state_t, arg);
+    int rc;
+
+    arg = xc_hypercall_buffer_alloc(xch, arg, sizeof(*arg));
+    if ( arg == NULL )
+        return -1;
+
+    hypercall.op     = __HYPERVISOR_hvm_op;
+    hypercall.arg[0] = HVMOP_set_ioreq_server_state;
+    hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
+    arg->domid = domid;
+    arg->id = id;
+    arg->enabled = enabled;
+    rc = do_xen_hypercall(xch, &hypercall);
+    xc_hypercall_buffer_free(xch, arg);
+    return rc;
+}
+
 int xc_domain_setdebugging(xc_interface *xch,
                            uint32_t domid,
                            unsigned int enable)
diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h
index 3b0c678..1f8d490 100644
--- a/tools/libxc/xenctrl.h
+++ b/tools/libxc/xenctrl.h
@@ -1843,6 +1843,11 @@ int xc_hvm_destroy_ioreq_server(xc_interface *xch,
                                 domid_t domid,
                                 ioservid_t id);
 
+int xc_hvm_set_ioreq_server_state(xc_interface *xch,
+                                  domid_t domid,
+                                  ioservid_t id,
+                                  int enabled);
+
 /* HVM guest pass-through */
 int xc_assign_device(xc_interface *xch,
                      uint32_t domid,
diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index 5af01b0..ba9b304 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -545,6 +545,20 @@ static int hvm_map_ioreq_page(
     return 0;
 }
 
+static void hvm_remove_ioreq_gmfn(
+    struct domain *d, struct hvm_ioreq_page *iorp)
+{
+    guest_physmap_remove_page(d, iorp->gmfn, 
+                              page_to_mfn(iorp->page), 0);
+}
+
+static int hvm_add_ioreq_gmfn(
+    struct domain *d, struct hvm_ioreq_page *iorp)
+{
+    return guest_physmap_add_page(d, iorp->gmfn,
+                                  page_to_mfn(iorp->page), 0);
+}
+
 static int hvm_print_line(
     int dir, uint32_t port, uint32_t bytes, uint32_t *val)
 {
@@ -844,6 +858,26 @@ static void hvm_ioreq_server_unmap_pages(struct 
hvm_ioreq_server *s,
     }
 }
 
+static void hvm_ioreq_server_enable(struct hvm_ioreq_server *s)
+{
+    struct domain *d = s->domain;
+
+    hvm_remove_ioreq_gmfn(d, &s->ioreq);
+    hvm_remove_ioreq_gmfn(d, &s->bufioreq);
+
+    s->enabled = 1;
+}
+
+static void hvm_ioreq_server_disable(struct hvm_ioreq_server *s)
+{
+    struct domain *d = s->domain;
+
+    hvm_add_ioreq_gmfn(d, &s->bufioreq);
+    hvm_add_ioreq_gmfn(d, &s->ioreq);
+
+    s->enabled = 0;
+}
+
 static int hvm_ioreq_server_init(struct hvm_ioreq_server *s, struct domain *d,
                                  domid_t domid, bool_t is_default,
                                  ioservid_t id)
@@ -888,6 +922,9 @@ static void hvm_ioreq_server_deinit(struct hvm_ioreq_server 
*s,
 {
     struct list_head *entry;
 
+    if ( !is_default && s->enabled )
+        hvm_ioreq_server_disable(s);
+
     list_for_each ( entry,
                     &s->mmio_range_list )
     {
@@ -950,8 +987,10 @@ static int hvm_create_ioreq_server(struct domain *d, 
domid_t domid,
              &d->arch.hvm_domain.ioreq_server_list);
     d->arch.hvm_domain.ioreq_server_count++;
 
-    if ( is_default )
+    if ( is_default ) {
+        s->enabled = 1;
         d->arch.hvm_domain.default_ioreq_server = s;
+    }
 
     domain_unpause(d);
 
@@ -996,7 +1035,7 @@ static void hvm_destroy_ioreq_server(struct domain *d, 
ioservid_t id)
 
         --d->arch.hvm_domain.ioreq_server_count;
         list_del_init(&s->list_entry);
-        
+
         hvm_ioreq_server_deinit(s, is_default);
 
         domain_unpause(d);
@@ -1240,6 +1279,44 @@ static int hvm_unmap_pcidev_from_ioreq_server(struct 
domain *d, ioservid_t id,
     return rc;
 }
 
+static int hvm_set_ioreq_server_state(struct domain *d, ioservid_t id,
+                                      bool_t enabled)
+{
+    struct list_head *entry;
+    int rc;
+
+    spin_lock(&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);
+        if ( s->id != id )
+            continue;
+
+        rc = 0;
+        if ( s->enabled == enabled )
+            break;
+
+        domain_pause(d);
+
+        if ( enabled )
+            hvm_ioreq_server_enable(s);
+        else
+            hvm_ioreq_server_disable(s);
+
+        domain_unpause(d);
+        break;
+    }
+
+    spin_unlock(&d->arch.hvm_domain.ioreq_server_lock);
+
+    return rc;
+}
+
 static int hvm_all_ioreq_servers_add_vcpu(struct domain *d, struct vcpu *v)
 {
     struct list_head *entry;
@@ -2345,6 +2422,9 @@ static struct hvm_ioreq_server 
*hvm_select_ioreq_server(struct domain *d,
                           &d->arch.hvm_domain.ioreq_server_list,
                           list_entry )
     {
+        if ( !s->enabled )
+            continue;
+
         switch ( type )
         {
             case IOREQ_TYPE_COPY:
@@ -2389,6 +2469,7 @@ static struct hvm_ioreq_server 
*hvm_select_ioreq_server(struct domain *d,
  found:
     rcu_read_unlock(&ioreq_server_rcu_lock);
 
+    ASSERT(!s || s->enabled);
     return s;
 
 #undef BDF
@@ -5325,6 +5406,31 @@ static int hvmop_unmap_pcidev_from_ioreq_server(
     return rc;
 }
 
+static int hvmop_set_ioreq_server_state(
+    XEN_GUEST_HANDLE_PARAM(xen_hvm_set_ioreq_server_state_t) uop)
+{
+    xen_hvm_set_ioreq_server_state_t op;
+    struct domain *d;
+    int rc;
+
+    if ( copy_from_guest(&op, uop, 1) )
+        return -EFAULT;
+
+    rc = rcu_lock_remote_domain_by_id(op.domid, &d);
+    if ( rc != 0 )
+        return rc;
+
+    rc = -EINVAL;
+    if ( !is_hvm_domain(d) )
+        goto out;
+
+    rc = hvm_set_ioreq_server_state(d, op.id, op.enabled);
+
+ out:
+    rcu_unlock_domain(d);
+    return rc;
+}
+
 static int hvmop_destroy_ioreq_server(
     XEN_GUEST_HANDLE_PARAM(xen_hvm_destroy_ioreq_server_t) uop)
 {
@@ -5388,6 +5494,11 @@ long do_hvm_op(unsigned long op, 
XEN_GUEST_HANDLE_PARAM(void) arg)
         rc = hvmop_unmap_pcidev_from_ioreq_server(
             guest_handle_cast(arg, xen_hvm_unmap_pcidev_from_ioreq_server_t));
         break;
+
+    case HVMOP_set_ioreq_server_state:
+        rc = hvmop_set_ioreq_server_state(
+            guest_handle_cast(arg, xen_hvm_set_ioreq_server_state_t));
+        break;
     
     case HVMOP_destroy_ioreq_server:
         rc = hvmop_destroy_ioreq_server(
diff --git a/xen/include/asm-x86/hvm/domain.h b/xen/include/asm-x86/hvm/domain.h
index d7a73ce..36cb7ec 100644
--- a/xen/include/asm-x86/hvm/domain.h
+++ b/xen/include/asm-x86/hvm/domain.h
@@ -79,6 +79,7 @@ struct hvm_ioreq_server {
     struct list_head       mmio_range_list;
     struct list_head       portio_range_list;
     struct list_head       pcidev_list;
+    bool_t                 enabled;
 };
 
 struct hvm_domain {
diff --git a/xen/include/public/hvm/hvm_op.h b/xen/include/public/hvm/hvm_op.h
index c6ceea5..a39290e 100644
--- a/xen/include/public/hvm/hvm_op.h
+++ b/xen/include/public/hvm/hvm_op.h
@@ -296,10 +296,10 @@ DEFINE_XEN_GUEST_HANDLE(xen_hvm_get_ioreq_server_info_t);
 
 #define HVMOP_map_io_range_to_ioreq_server 19
 struct xen_hvm_map_io_range_to_ioreq_server {
-    domid_t domid;                  /* IN - domain to be serviced */
-    ioservid_t id;                  /* IN - handle from 
HVMOP_register_ioreq_server */
-    int is_mmio;                    /* IN - MMIO or port IO? */
-    uint64_aligned_t start, end;    /* IN - inclusive start and end of range */
+    domid_t domid;               /* IN - domain to be serviced */
+    ioservid_t id;               /* IN - handle from 
HVMOP_register_ioreq_server */
+    int is_mmio;                 /* IN - MMIO or port IO? */
+    uint64_aligned_t start, end; /* IN - inclusive start and end of range */
 };
 typedef struct xen_hvm_map_io_range_to_ioreq_server 
xen_hvm_map_io_range_to_ioreq_server_t;
 DEFINE_XEN_GUEST_HANDLE(xen_hvm_map_io_range_to_ioreq_server_t);
@@ -316,30 +316,39 @@ 
DEFINE_XEN_GUEST_HANDLE(xen_hvm_unmap_io_range_from_ioreq_server_t);
 
 #define HVMOP_map_pcidev_to_ioreq_server 21
 struct xen_hvm_map_pcidev_to_ioreq_server {
-    domid_t domid;      /* IN - domain to be serviced */
-    ioservid_t id;      /* IN - handle from HVMOP_register_ioreq_server */
-    uint16_t bdf;       /* IN - PCI bus/dev/func */
+    domid_t domid; /* IN - domain to be serviced */
+    ioservid_t id; /* IN - handle from HVMOP_register_ioreq_server */
+    uint16_t bdf;  /* IN - PCI bus/dev/func */
 };
 typedef struct xen_hvm_map_pcidev_to_ioreq_server 
xen_hvm_map_pcidev_to_ioreq_server_t;
 DEFINE_XEN_GUEST_HANDLE(xen_hvm_map_pcidev_to_ioreq_server_t);
 
 #define HVMOP_unmap_pcidev_from_ioreq_server 22
 struct xen_hvm_unmap_pcidev_from_ioreq_server {
-    domid_t domid;      /* IN - domain to be serviced */
-    ioservid_t id;      /* IN - handle from HVMOP_register_ioreq_server */
-    uint16_t bdf;       /* IN - PCI bus/dev/func */
+    domid_t domid; /* IN - domain to be serviced */
+    ioservid_t id; /* IN - handle from HVMOP_register_ioreq_server */
+    uint16_t bdf;  /* IN - PCI bus/dev/func */
 };
 typedef struct xen_hvm_unmap_pcidev_from_ioreq_server 
xen_hvm_unmap_pcidev_from_ioreq_server_t;
 DEFINE_XEN_GUEST_HANDLE(xen_hvm_unmap_pcidev_from_ioreq_server_t);
 
 #define HVMOP_destroy_ioreq_server 23
 struct xen_hvm_destroy_ioreq_server {
-    domid_t domid;          /* IN - domain to be serviced */
-    ioservid_t id;          /* IN - server id */
+    domid_t domid; /* IN - domain to be serviced */
+    ioservid_t id; /* IN - server id */
 };
 typedef struct xen_hvm_destroy_ioreq_server xen_hvm_destroy_ioreq_server_t;
 DEFINE_XEN_GUEST_HANDLE(xen_hvm_destroy_ioreq_server_t);
 
+#define HVMOP_set_ioreq_server_state 24
+struct xen_hvm_set_ioreq_server_state {
+    domid_t domid;   /* IN - domain to be serviced */
+    ioservid_t id;   /* IN - server id */
+    uint8_t enabled; /* IN - enabled? */    
+};
+typedef struct xen_hvm_set_ioreq_server_state xen_hvm_set_ioreq_server_state_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_ioreq_server_state_t);
+
 #endif /* defined(__XEN__) || defined(__XEN_TOOLS__) */
 
 #endif /* __XEN_PUBLIC_HVM_HVM_OP_H__ */
-- 
1.7.10.4


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.