# HG changeset patch # User Tim Deegan # Date 1233764708 0 # Node ID 7265fb34414b00e413bd40e2804eb3df0cdca243 # Parent de853e901b5c6cfe3687404623c750b0f2c66058 Add a new domctl to get a single record from the HVM save context Signed-off-by: Tim Deegan diff -r de853e901b5c -r 7265fb34414b xen/arch/x86/domctl.c --- a/xen/arch/x86/domctl.c Wed Feb 04 15:29:51 2009 +0000 +++ b/xen/arch/x86/domctl.c Wed Feb 04 16:25:08 2009 +0000 @@ -416,6 +416,34 @@ rcu_unlock_domain(d); } 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: { diff -r de853e901b5c -r 7265fb34414b xen/common/hvm/save.c --- a/xen/common/hvm/save.c Wed Feb 04 15:29:51 2009 +0000 +++ b/xen/common/hvm/save.c Wed Feb 04 16:25:08 2009 +0000 @@ -26,6 +26,7 @@ #include #include #include +#include #include @@ -75,6 +76,53 @@ 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) { diff -r de853e901b5c -r 7265fb34414b xen/include/public/domctl.h --- a/xen/include/public/domctl.h Wed Feb 04 15:29:51 2009 +0000 +++ b/xen/include/public/domctl.h Wed Feb 04 16:25:08 2009 +0000 @@ -630,6 +630,17 @@ 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_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; diff -r de853e901b5c -r 7265fb34414b xen/include/xen/hvm/save.h --- a/xen/include/xen/hvm/save.h Wed Feb 04 15:29:51 2009 +0000 +++ b/xen/include/xen/hvm/save.h Wed Feb 04 16:25:08 2009 +0000 @@ -152,6 +152,8 @@ /* 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. */ diff -r de853e901b5c -r 7265fb34414b xen/xsm/flask/hooks.c --- a/xen/xsm/flask/hooks.c Wed Feb 04 15:29:51 2009 +0000 +++ b/xen/xsm/flask/hooks.c Wed Feb 04 16:25:08 2009 +0000 @@ -820,6 +820,7 @@ perm = HVM__SETHVMC; break; case XEN_DOMCTL_gethvmcontext: + case XEN_DOMCTL_gethvmcontext_partial: perm = HVM__GETHVMC; break; default: