]> xenbits.xensource.com Git - people/royger/xen.git/commitdiff
tools/libxc: Exposed XEN_DOMCTL_getvcpuextstate
authorRazvan Cojocaru <rcojocaru@bitdefender.com>
Tue, 14 Mar 2017 13:30:18 +0000 (15:30 +0200)
committerWei Liu <wei.liu2@citrix.com>
Tue, 14 Mar 2017 14:29:52 +0000 (14:29 +0000)
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>
tools/libxc/include/xenctrl.h
tools/libxc/xc_domain.c

index a48981abeaf58da2fcf67b460e87e00e40bca9ec..b80d150cc54b1a1508595c92a8d4d0cf77d5397d 100644 (file)
@@ -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,
index d862e537d98441da20e42959291480bc2fb7eed3..71e5d939c4480481aa79b3406174f43ddeeafeea 100644 (file)
@@ -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)