xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: Andrii Anisov <andrii.anisov@gmail.com>
Cc: Stefano Stabellini <sstabellini@kernel.org>,
	Andrii Anisov <andrii_anisov@epam.com>,
	Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>,
	George Dunlap <George.Dunlap@eu.citrix.com>,
	Andrew Cooper <andrew.cooper3@citrix.com>,
	Ian Jackson <ian.jackson@eu.citrix.com>, Tim Deegan <tim@xen.org>,
	Julien Grall <julien.grall@arm.com>,
	Jan Beulich <jbeulich@suse.com>,
	xen-devel@lists.xenproject.org, Wei Liu <wei.liu2@citrix.com>
Subject: [Xen-devel] [PATCH RFC 2] [DO NOT APPLY] introduce VCPUOP_register_runstate_phys_memory_area hypercall
Date: Fri, 24 May 2019 21:12:54 +0300	[thread overview]
Message-ID: <1558721577-13958-1-git-send-email-andrii.anisov@gmail.com> (raw)
Message-ID: <20190524181254.VPl8JBIM1874IEPRRijv3aAUQ24wn_iozxbx_IXcbwU@z> (raw)

From: Andrii Anisov <andrii_anisov@epam.com>

An RFC version of the runstate registration with phys address.
Runstate area access is implemented with mapping on each update once for
all accesses.

Signed-off-by: Andrii Anisov <andrii_anisov@epam.com>
---
 xen/arch/arm/domain.c     |  63 ++++++++++++++++++++++++++---
 xen/common/domain.c       | 101 ++++++++++++++++++++++++++++++++++++++++++++--
 xen/include/public/vcpu.h |  15 +++++++
 xen/include/xen/sched.h   |  28 +++++++++----
 4 files changed, 190 insertions(+), 17 deletions(-)

diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
index a9f7ff5..04c4cff 100644
--- a/xen/arch/arm/domain.c
+++ b/xen/arch/arm/domain.c
@@ -274,17 +274,15 @@ static void ctxt_switch_to(struct vcpu *n)
     virt_timer_restore(n);
 }
 
-/* Update per-VCPU guest runstate shared memory area (if registered). */
-static void update_runstate_area(struct vcpu *v)
+static void update_runstate_by_gvaddr(struct vcpu *v)
 {
     void __user *guest_handle = NULL;
 
-    if ( guest_handle_is_null(runstate_guest(v)) )
-        return;
+    ASSERT(!guest_handle_is_null(runstate_guest_virt(v)));
 
     if ( VM_ASSIST(v->domain, runstate_update_flag) )
     {
-        guest_handle = &v->runstate_guest.p->state_entry_time + 1;
+        guest_handle = &v->runstate_guest.virt.p->state_entry_time + 1;
         guest_handle--;
         v->runstate.state_entry_time |= XEN_RUNSTATE_UPDATE;
         __raw_copy_to_guest(guest_handle,
@@ -292,7 +290,7 @@ static void update_runstate_area(struct vcpu *v)
         smp_wmb();
     }
 
-    __copy_to_guest(runstate_guest(v), &v->runstate, 1);
+    __copy_to_guest(runstate_guest_virt(v), &v->runstate, 1);
 
     if ( guest_handle )
     {
@@ -303,6 +301,58 @@ static void update_runstate_area(struct vcpu *v)
     }
 }
 
+extern int map_runstate_area(struct vcpu *v, struct vcpu_runstate_info **area);
+extern void unmap_runstate_area(struct vcpu_runstate_info *area);
+
+static void update_runstate_by_gpaddr(struct vcpu *v)
+{
+    struct vcpu_runstate_info *runstate;
+
+    if ( map_runstate_area(v, &runstate) )
+        return;
+
+    if ( VM_ASSIST(v->domain, runstate_update_flag) )
+    {
+        runstate->state_entry_time |= XEN_RUNSTATE_UPDATE;
+        smp_wmb();
+        v->runstate.state_entry_time |= XEN_RUNSTATE_UPDATE;
+    }
+
+    memcpy(runstate, &v->runstate, sizeof(v->runstate));
+
+    if ( VM_ASSIST(v->domain, runstate_update_flag) )
+    {
+        runstate->state_entry_time &= ~XEN_RUNSTATE_UPDATE;
+        smp_wmb();
+        v->runstate.state_entry_time &= ~XEN_RUNSTATE_UPDATE;
+    }
+
+    unmap_runstate_area(runstate);
+}
+
+/* Update per-VCPU guest runstate shared memory area (if registered). */
+static void update_runstate_area(struct vcpu *v)
+{
+    if ( xchg(&v->runstate_in_use, 1) )
+        return;
+
+    switch ( v->runstate_guest_type )
+    {
+    case RUNSTATE_NONE:
+       break;
+
+    case RUNSTATE_VADDR:
+       update_runstate_by_gvaddr(v);
+       break;
+
+    case RUNSTATE_PADDR:
+       update_runstate_by_gpaddr(v);
+       break;
+    }
+
+    xchg(&v->runstate_in_use, 0);
+}
+
 static void schedule_tail(struct vcpu *prev)
 {
     ctxt_switch_from(prev);
@@ -998,6 +1048,7 @@ long do_arm_vcpu_op(int cmd, unsigned int vcpuid, XEN_GUEST_HANDLE_PARAM(void) a
     {
         case VCPUOP_register_vcpu_info:
         case VCPUOP_register_runstate_memory_area:
+        case VCPUOP_register_runstate_phys_memory_area:
             return do_vcpu_op(cmd, vcpuid, arg);
         default:
             return -EINVAL;
diff --git a/xen/common/domain.c b/xen/common/domain.c
index 32bca8d..f167a68 100644
--- a/xen/common/domain.c
+++ b/xen/common/domain.c
@@ -700,6 +700,68 @@ int rcu_lock_live_remote_domain_by_id(domid_t dom, struct domain **d)
     return 0;
 }
 
+void unmap_runstate_area(struct vcpu_runstate_info *area)
+{
+    mfn_t mfn;
+
+    ASSERT(area != NULL);
+
+    mfn = _mfn(domain_page_map_to_mfn(area));
+
+    unmap_domain_page_global((void *)
+                             ((unsigned long)area &
+                              PAGE_MASK));
+
+    put_page_and_type(mfn_to_page(mfn));
+}
+
+int map_runstate_area(struct vcpu *v, struct vcpu_runstate_info **area)
+{
+    unsigned long offset = v->runstate_guest.phys & ~PAGE_MASK;
+    gfn_t gfn = gaddr_to_gfn(v->runstate_guest.phys);
+    struct domain *d = v->domain;
+    void *mapping;
+    struct page_info *page;
+    size_t size = sizeof(struct vcpu_runstate_info);
+
+    if ( offset > (PAGE_SIZE - size) )
+        return -EINVAL;
+
+    page = get_page_from_gfn(d, gfn_x(gfn), NULL, P2M_ALLOC);
+    if ( !page )
+        return -EINVAL;
+
+    if ( !get_page_type(page, PGT_writable_page) )
+    {
+        put_page(page);
+        return -EINVAL;
+    }
+
+    mapping = __map_domain_page_global(page);
+
+    if ( mapping == NULL )
+    {
+        put_page_and_type(page);
+        return -ENOMEM;
+    }
+
+    *area = mapping + offset;
+
+    return 0;
+}
+
+static void discard_runstate_area(struct vcpu *v)
+{
+    v->runstate_guest_type = RUNSTATE_NONE;
+}
+
+static void discard_runstate_area_locked(struct vcpu *v)
+{
+    while ( xchg(&v->runstate_in_use, 1) );
+    discard_runstate_area(v);
+    xchg(&v->runstate_in_use, 0);
+}
+
 int domain_kill(struct domain *d)
 {
     int rc = 0;
@@ -738,7 +800,10 @@ int domain_kill(struct domain *d)
         if ( cpupool_move_domain(d, cpupool0) )
             return -ERESTART;
         for_each_vcpu ( d, v )
+        {
+            discard_runstate_area_locked(v);
             unmap_vcpu_info(v);
+        }
         d->is_dying = DOMDYING_dead;
         /* Mem event cleanup has to go here because the rings 
          * have to be put before we call put_domain. */
@@ -1192,7 +1257,7 @@ int domain_soft_reset(struct domain *d)
 
     for_each_vcpu ( d, v )
     {
-        set_xen_guest_handle(runstate_guest(v), NULL);
+        discard_runstate_area_locked(v);
         unmap_vcpu_info(v);
     }
 
@@ -1520,18 +1585,46 @@ long do_vcpu_op(int cmd, unsigned int vcpuid, XEN_GUEST_HANDLE_PARAM(void) arg)
             break;
 
         rc = 0;
-        runstate_guest(v) = area.addr.h;
+
+        while( xchg(&v->runstate_in_use, 1) == 0);
+
+        discard_runstate_area(v);
+
+        runstate_guest_virt(v) = area.addr.h;
+        v->runstate_guest_type = RUNSTATE_VADDR;
 
         if ( v == current )
         {
-            __copy_to_guest(runstate_guest(v), &v->runstate, 1);
+            __copy_to_guest(runstate_guest_virt(v), &v->runstate, 1);
         }
         else
         {
             vcpu_runstate_get(v, &runstate);
-            __copy_to_guest(runstate_guest(v), &runstate, 1);
+            __copy_to_guest(runstate_guest_virt(v), &runstate, 1);
         }
 
+        xchg(&v->runstate_in_use, 0);
+
+        break;
+    }
+
+    case VCPUOP_register_runstate_phys_memory_area:
+    {
+        struct vcpu_register_runstate_memory_area area;
+
+        rc = -EFAULT;
+        if ( copy_from_guest(&area, arg, 1) )
+             break;
+
+        while( xchg(&v->runstate_in_use, 1) == 0);
+
+        discard_runstate_area(v);
+        v->runstate_guest.phys = area.addr.p;
+        v->runstate_guest_type = RUNSTATE_PADDR;
+
+        xchg(&v->runstate_in_use, 0);
+        rc = 0;
+
         break;
     }
 
diff --git a/xen/include/public/vcpu.h b/xen/include/public/vcpu.h
index 3623af9..d7da4a3 100644
--- a/xen/include/public/vcpu.h
+++ b/xen/include/public/vcpu.h
@@ -235,6 +235,21 @@ struct vcpu_register_time_memory_area {
 typedef struct vcpu_register_time_memory_area vcpu_register_time_memory_area_t;
 DEFINE_XEN_GUEST_HANDLE(vcpu_register_time_memory_area_t);
 
+/*
+ * Register a shared memory area from which the guest may obtain its own
+ * runstate information without needing to execute a hypercall.
+ * Notes:
+ *  1. The registered address must be guest's physical address.
+ *  2. The registered runstate area should not cross page boundary.
+ *  3. Only one shared area may be registered per VCPU. The shared area is
+ *     updated by the hypervisor each time the VCPU is scheduled. Thus
+ *     runstate.state will always be RUNSTATE_running and
+ *     runstate.state_entry_time will indicate the system time at which the
+ *     VCPU was last scheduled to run.
+ * @extra_arg == pointer to vcpu_register_runstate_memory_area structure.
+ */
+#define VCPUOP_register_runstate_phys_memory_area 14
+
 #endif /* __XEN_PUBLIC_VCPU_H__ */
 
 /*
diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h
index edee52d..8ac597b 100644
--- a/xen/include/xen/sched.h
+++ b/xen/include/xen/sched.h
@@ -163,17 +163,31 @@ struct vcpu
     void            *sched_priv;    /* scheduler-specific data */
 
     struct vcpu_runstate_info runstate;
+
+    enum {
+        RUNSTATE_NONE = 0,
+        RUNSTATE_PADDR = 1,
+        RUNSTATE_VADDR = 2,
+    } runstate_guest_type;
+
+    unsigned long runstate_in_use;
+
+    union
+    {
 #ifndef CONFIG_COMPAT
-# define runstate_guest(v) ((v)->runstate_guest)
-    XEN_GUEST_HANDLE(vcpu_runstate_info_t) runstate_guest; /* guest address */
+# define runstate_guest_virt(v) ((v)->runstate_guest.virt)
+           XEN_GUEST_HANDLE(vcpu_runstate_info_t) virt; /* guest address */
 #else
-# define runstate_guest(v) ((v)->runstate_guest.native)
-    union {
-        XEN_GUEST_HANDLE(vcpu_runstate_info_t) native;
-        XEN_GUEST_HANDLE(vcpu_runstate_info_compat_t) compat;
-    } runstate_guest; /* guest address */
+# define runstate_guest_virt(v) ((v)->runstate_guest.virt.native)
+           union {
+               XEN_GUEST_HANDLE(vcpu_runstate_info_t) native;
+               XEN_GUEST_HANDLE(vcpu_runstate_info_compat_t) compat;
+           } virt; /* guest address */
 #endif
 
+        paddr_t phys;
+    } runstate_guest;
+
     /* last time when vCPU is scheduled out */
     uint64_t last_run_time;
 
-- 
2.7.4


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

             reply	other threads:[~2019-05-24 18:13 UTC|newest]

Thread overview: 51+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-05-24 18:12 Andrii Anisov [this message]
2019-05-24 18:12 ` [Xen-devel] [PATCH RFC 2] [DO NOT APPLY] introduce VCPUOP_register_runstate_phys_memory_area hypercall Andrii Anisov
2019-05-24 18:12 ` [PATCH v3] Introduce runstate area registration with phys address Andrii Anisov
2019-05-24 18:12   ` [Xen-devel] " Andrii Anisov
2019-05-24 18:12 ` [PATCH v3] xen: introduce VCPUOP_register_runstate_phys_memory_area hypercall Andrii Anisov
2019-05-24 18:12   ` [Xen-devel] " Andrii Anisov
2019-06-07 14:23   ` Jan Beulich
2019-06-10 11:44     ` Julien Grall
2019-06-11  9:10       ` Jan Beulich
2019-06-11 10:22         ` Andrii Anisov
2019-06-11 12:12           ` Julien Grall
2019-06-11 12:26             ` Andrii Anisov
2019-06-11 12:32               ` Julien Grall
2019-06-11 12:40                 ` Andrii Anisov
2019-06-13 12:21           ` Andrii Anisov
2019-06-13 12:39             ` Jan Beulich
2019-06-13 12:32         ` Andrii Anisov
2019-06-13 12:41           ` Jan Beulich
2019-06-13 12:48             ` Julien Grall
2019-06-13 12:58               ` Jan Beulich
2019-06-13 13:14                 ` Julien Grall
2019-06-13 13:40                   ` Jan Beulich
2019-06-13 14:41                     ` Julien Grall
2019-06-14 14:36                       ` Andrii Anisov
2019-06-14 14:39                         ` Julien Grall
2019-06-14 15:11                           ` Andrii Anisov
2019-06-14 15:24                             ` Julien Grall
2019-06-14 16:11                               ` Andrii Anisov
2019-06-14 16:20                                 ` Julien Grall
2019-06-14 16:25                                   ` Andrii Anisov
2019-06-17  6:27                                     ` Jan Beulich
2019-06-14 15:42                             ` Jan Beulich
2019-06-14 16:23                               ` Andrii Anisov
2019-06-17  6:28                                 ` Jan Beulich
2019-06-18 15:32                                   ` Andrii Anisov
2019-06-18 15:44                                     ` Jan Beulich
2019-06-11 16:09     ` Andrii Anisov
2019-06-12  7:27       ` Jan Beulich
2019-06-13 12:17         ` Andrii Anisov
2019-06-13 12:36           ` Jan Beulich
2019-06-11 16:13     ` Andrii Anisov
2019-05-24 18:12 ` [PATCH RFC 1] [DO NOT APPLY] " Andrii Anisov
2019-05-24 18:12   ` [Xen-devel] " Andrii Anisov
2019-05-28  8:59 ` [PATCH RFC 2] " Julien Grall
2019-05-28  8:59   ` [Xen-devel] " Julien Grall
2019-05-28  9:17   ` Andrii Anisov
2019-05-28  9:17     ` [Xen-devel] " Andrii Anisov
2019-05-28  9:23     ` Julien Grall
2019-05-28  9:23       ` [Xen-devel] " Julien Grall
2019-05-28  9:36       ` Andrii Anisov
2019-05-28  9:36         ` [Xen-devel] " Andrii Anisov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1558721577-13958-1-git-send-email-andrii.anisov@gmail.com \
    --to=andrii.anisov@gmail.com \
    --cc=George.Dunlap@eu.citrix.com \
    --cc=andrew.cooper3@citrix.com \
    --cc=andrii_anisov@epam.com \
    --cc=ian.jackson@eu.citrix.com \
    --cc=jbeulich@suse.com \
    --cc=julien.grall@arm.com \
    --cc=konrad.wilk@oracle.com \
    --cc=sstabellini@kernel.org \
    --cc=tim@xen.org \
    --cc=wei.liu2@citrix.com \
    --cc=xen-devel@lists.xenproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).