mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
Add a new domctl to get a single record from the HVM save context
Signed-off-by: Tim Deegan <Tim.Deegan@citrix.com>
This commit is contained in:
1 parent
38651997ed
commit
1bb7e0437b
5 files changed
+91
No files matched your search
@@ -417,6 +417,34 @@ long arch_do_domctl(
|
||||
}
|
||||
break;
|
||||
|
||||
case XEN_DOMCTL_gethvmcontext_partial:
|
||||
{
|
||||
struct domain *d;
|
||||
|
||||
ret = -ESRCH;
|
||||
if ( (d = rcu_lock_domain_by_id(domctl->domain)) == NULL )
|
||||
break;
|
||||
|
||||
ret = xsm_hvmcontext(d, domctl->cmd);
|
||||
if ( ret )
|
||||
goto gethvmcontext_partial_out;
|
||||
|
||||
ret = -EINVAL;
|
||||
if ( !is_hvm_domain(d) )
|
||||
goto gethvmcontext_partial_out;
|
||||
|
||||
domain_pause(d);
|
||||
ret = hvm_save_one(d, domctl->u.hvmcontext_partial.type,
|
||||
domctl->u.hvmcontext_partial.instance,
|
||||
domctl->u.hvmcontext_partial.buffer);
|
||||
domain_unpause(d);
|
||||
|
||||
gethvmcontext_partial_out:
|
||||
rcu_unlock_domain(d);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case XEN_DOMCTL_set_address_size:
|
||||
{
|
||||
struct domain *d;
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <xen/version.h>
|
||||
#include <public/version.h>
|
||||
#include <xen/sched.h>
|
||||
#include <xen/guest_access.h>
|
||||
|
||||
#include <asm/hvm/support.h>
|
||||
|
||||
@@ -75,6 +76,53 @@ size_t hvm_save_size(struct domain *d)
|
||||
return sz;
|
||||
}
|
||||
|
||||
/* Extract a single instance of a save record, by marshalling all
|
||||
* records of that type and copying out the one we need. */
|
||||
int hvm_save_one(struct domain *d, uint16_t typecode, uint16_t instance,
|
||||
XEN_GUEST_HANDLE_64(uint8) handle)
|
||||
{
|
||||
int rv = 0;
|
||||
size_t sz = 0;
|
||||
struct vcpu *v;
|
||||
hvm_domain_context_t ctxt = { 0, };
|
||||
|
||||
if ( d->is_dying
|
||||
|| typecode > HVM_SAVE_CODE_MAX
|
||||
|| hvm_sr_handlers[typecode].size < sizeof(struct hvm_save_descriptor)
|
||||
|| hvm_sr_handlers[typecode].save == NULL )
|
||||
return -EINVAL;
|
||||
|
||||
if ( hvm_sr_handlers[typecode].kind == HVMSR_PER_VCPU )
|
||||
for_each_vcpu(d, v)
|
||||
sz += hvm_sr_handlers[typecode].size;
|
||||
else
|
||||
sz = hvm_sr_handlers[typecode].size;
|
||||
|
||||
if ( (instance + 1) * hvm_sr_handlers[typecode].size > sz )
|
||||
return -EINVAL;
|
||||
|
||||
ctxt.size = sz;
|
||||
ctxt.data = xmalloc_bytes(sz);
|
||||
if ( !ctxt.data )
|
||||
return -ENOMEM;
|
||||
|
||||
if ( hvm_sr_handlers[typecode].save(d, &ctxt) != 0 )
|
||||
{
|
||||
gdprintk(XENLOG_ERR,
|
||||
"HVM save: failed to save type %"PRIu16"\n", typecode);
|
||||
rv = -EFAULT;
|
||||
}
|
||||
else if ( copy_to_guest(handle,
|
||||
ctxt.data
|
||||
+ (instance * hvm_sr_handlers[typecode].size)
|
||||
+ sizeof (struct hvm_save_descriptor),
|
||||
hvm_sr_handlers[typecode].size
|
||||
- sizeof (struct hvm_save_descriptor)) )
|
||||
rv = -EFAULT;
|
||||
|
||||
xfree(ctxt.data);
|
||||
return rv;
|
||||
}
|
||||
|
||||
int hvm_save(struct domain *d, hvm_domain_context_t *h)
|
||||
{
|
||||
|
||||
@@ -630,6 +630,17 @@ struct xen_domctl_debug_op {
|
||||
typedef struct xen_domctl_debug_op xen_domctl_debug_op_t;
|
||||
DEFINE_XEN_GUEST_HANDLE(xen_domctl_debug_op_t);
|
||||
|
||||
/*
|
||||
* Request a particular record from the HVM context
|
||||
*/
|
||||
#define XEN_DOMCTL_gethvmcontext_partial 55
|
||||
typedef struct xen_domctl_hvmcontext_partial {
|
||||
uint32_t type; /* IN: Type of record required */
|
||||
uint32_t instance; /* IN: Instance of that type */
|
||||
XEN_GUEST_HANDLE_64(uint8) buffer; /* OUT: buffer to write record into */
|
||||
} xen_domctl_hvmcontext_partial_t;
|
||||
DEFINE_XEN_GUEST_HANDLE(xen_domctl_hvmcontext_partial_t);
|
||||
|
||||
|
||||
struct xen_domctl {
|
||||
uint32_t cmd;
|
||||
@@ -658,6 +669,7 @@ struct xen_domctl {
|
||||
struct xen_domctl_settimeoffset settimeoffset;
|
||||
struct xen_domctl_real_mode_area real_mode_area;
|
||||
struct xen_domctl_hvmcontext hvmcontext;
|
||||
struct xen_domctl_hvmcontext_partial hvmcontext_partial;
|
||||
struct xen_domctl_address_size address_size;
|
||||
struct xen_domctl_sendtrigger sendtrigger;
|
||||
struct xen_domctl_get_device_group get_device_group;
|
||||
|
||||
@@ -152,6 +152,8 @@ __initcall(__hvm_register_##_x##_save_and_restore);
|
||||
/* Entry points for saving and restoring HVM domain state */
|
||||
size_t hvm_save_size(struct domain *d);
|
||||
int hvm_save(struct domain *d, hvm_domain_context_t *h);
|
||||
int hvm_save_one(struct domain *d, uint16_t typecode, uint16_t instance,
|
||||
XEN_GUEST_HANDLE_64(uint8) handle);
|
||||
int hvm_load(struct domain *d, hvm_domain_context_t *h);
|
||||
|
||||
/* Arch-specific definitions. */
|
||||
|
||||
@@ -820,6 +820,7 @@ static int flask_hvmcontext(struct domain *d, uint32_t cmd)
|
||||
perm = HVM__SETHVMC;
|
||||
break;
|
||||
case XEN_DOMCTL_gethvmcontext:
|
||||
case XEN_DOMCTL_gethvmcontext_partial:
|
||||
perm = HVM__GETHVMC;
|
||||
break;
|
||||
default:
|
||||
|
||||