diff mbox

tools/libxc: Exposed XEN_DOMCTL_getvcpuextstate

Message ID 1489498218-11452-1-git-send-email-rcojocaru@bitdefender.com (mailing list archive)
State New, archived
Headers show

Commit Message

Razvan Cojocaru March 14, 2017, 1:30 p.m. UTC
It's useful for an introspection tool to be able to inspect
XSAVE states. Xen already has a DOMCTL that can be used for this
purpose, but it had no public libxc wrapper. This patch adds
xc_vcpu_get_extstate().

Signed-off-by: Razvan Cojocaru <rcojocaru@bitdefender.com>
---
 tools/libxc/include/xenctrl.h | 23 +++++++++++++++++
 tools/libxc/xc_domain.c       | 59 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 82 insertions(+)

Comments

Wei Liu March 14, 2017, 2:44 p.m. UTC | #1
On Tue, Mar 14, 2017 at 03:30:18PM +0200, Razvan Cojocaru wrote:
> It's useful for an introspection tool to be able to inspect
> XSAVE states. Xen already has a DOMCTL that can be used for this
> purpose, but it had no public libxc wrapper. This patch adds
> xc_vcpu_get_extstate().
> 
> Signed-off-by: Razvan Cojocaru <rcojocaru@bitdefender.com>

Acked-by: Wei Liu <wei.liu2@citrix.com>
diff mbox

Patch

diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h
index a48981a..b80d150 100644
--- a/tools/libxc/include/xenctrl.h
+++ b/tools/libxc/include/xenctrl.h
@@ -487,6 +487,11 @@  typedef union
 } start_info_any_t;
 #endif
 
+typedef struct xc_vcpu_extstate {
+    uint64_t xfeature_mask;
+    uint64_t size;
+    void *buffer;
+} xc_vcpu_extstate_t;
 
 typedef struct xen_arch_domainconfig xc_domain_configuration_t;
 int xc_domain_create(xc_interface *xch, uint32_t ssidref,
@@ -880,6 +885,24 @@  int xc_vcpu_getcontext(xc_interface *xch,
                        uint32_t vcpu,
                        vcpu_guest_context_any_t *ctxt);
 
+/**
+ * This function returns information about the XSAVE state of a particular
+ * vcpu of a domain. If extstate->size and extstate->xfeature_mask are 0,
+ * the call is considered a query to retrieve them and the buffer is not
+ * filled.
+ *
+ * @parm xch a handle to an open hypervisor interface
+ * @parm domid the domain to get information from
+ * @parm vcpu the vcpu number
+ * @parm extstate a pointer to a structure to store the XSAVE state of the
+ *                domain
+ * @return 0 on success, negative error code on failure
+ */
+int xc_vcpu_get_extstate(xc_interface *xch,
+                         uint32_t domid,
+                         uint32_t vcpu,
+                         xc_vcpu_extstate_t *extstate);
+
 typedef xen_domctl_getvcpuinfo_t xc_vcpuinfo_t;
 int xc_vcpu_getinfo(xc_interface *xch,
                     uint32_t domid,
diff --git a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c
index d862e53..71e5d93 100644
--- a/tools/libxc/xc_domain.c
+++ b/tools/libxc/xc_domain.c
@@ -555,6 +555,65 @@  int xc_vcpu_getcontext(xc_interface *xch,
     return rc;
 }
 
+int xc_vcpu_get_extstate(xc_interface *xch,
+                         uint32_t domid,
+                         uint32_t vcpu,
+                         xc_vcpu_extstate_t *extstate)
+{
+    int rc;
+    DECLARE_DOMCTL;
+    DECLARE_HYPERCALL_BUFFER(void, buffer);
+    bool get_state;
+
+    if ( !extstate )
+        return -EINVAL;
+
+    domctl.cmd = XEN_DOMCTL_getvcpuextstate;
+    domctl.domain = (domid_t)domid;
+    domctl.u.vcpuextstate.vcpu = (uint16_t)vcpu;
+    domctl.u.vcpuextstate.xfeature_mask = extstate->xfeature_mask;
+    domctl.u.vcpuextstate.size = extstate->size;
+
+    get_state = (extstate->size != 0);
+
+    if ( get_state )
+    {
+        buffer = xc_hypercall_buffer_alloc(xch, buffer, extstate->size);
+
+        if ( !buffer )
+        {
+            PERROR("Unable to allocate memory for vcpu%u's xsave context",
+                   vcpu);
+            rc = -ENOMEM;
+            goto out;
+        }
+
+        set_xen_guest_handle(domctl.u.vcpuextstate.buffer, buffer);
+    }
+
+    rc = do_domctl(xch, &domctl);
+
+    if ( rc )
+        goto out;
+
+    /* A query for the size of buffer to use. */
+    if ( !extstate->size && !extstate->xfeature_mask )
+    {
+        extstate->xfeature_mask = domctl.u.vcpuextstate.xfeature_mask;
+        extstate->size = domctl.u.vcpuextstate.size;
+        goto out;
+    }
+
+    if ( get_state )
+        memcpy(extstate->buffer, buffer, extstate->size);
+
+out:
+    if ( get_state )
+        xc_hypercall_buffer_free(xch, buffer);
+
+    return rc;
+}
+
 int xc_watchdog(xc_interface *xch,
                 uint32_t id,
                 uint32_t timeout)