[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH v5 1/6] xen/arm: Implement hvm save and restore



Either my email client is playing tricks on me or this patch series has
been sent in HTML format. If that is the case, please avoid HTML emails
in the future, especially to send patches.

On Wed, 6 Nov 2013, Jaeyong Yoo wrote:
> 
> Implement save/restore of hvm context hypercall.
> 
> In hvm context save/restore, we save gic, timer and vfp registers.
> 
> Â
> 
> Changes from v4: Save vcpu registers within hvm context, and purge
> 
> the save-vcpu-register patch.
> 
> Â
> 
> Singed-off-by: Evgeny Fedotov <e.fedotov@xxxxxxxxxxx>
> 
> ---
> 
> xen/arch/arm/MakefileÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ |ÂÂ 1 +
> 
> xen/arch/arm/domctl.cÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ |Â 89 ++++++-
> 
> xen/arch/arm/hvm.cÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ | 464 ++++++++++++++++++++++++++++++++-
> 
> xen/arch/arm/save.cÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ |Â 66 +++++
> 
> xen/common/MakefileÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ |ÂÂ 2 +
> 
> xen/include/asm-arm/hvm/support.hÂÂÂÂÂ |Â 29 +++
> 
> xen/include/public/arch-arm/hvm/save.h | 130 +++++++++
> 
> 7 files changed, 779 insertions(+), 2 deletions(-)
> 
> create mode 100644 xen/arch/arm/save.c
> 
> create mode 100644 xen/include/asm-arm/hvm/support.h
> 
> Â
> 
> diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
> 
> index 003ac84..8910a6c 100644
> 
> --- a/xen/arch/arm/Makefile
> 
> +++ b/xen/arch/arm/Makefile
> 
> @@ -31,6 +31,7 @@ obj-y += vuart.o
> 
> obj-y += hvm.o
> 
> obj-y += device.o
> 
> obj-y += decode.o
> 
> +obj-y += save.o
> 
> Â
> 
> #obj-bin-y += ....o
> 
> Â
> 
> diff --git a/xen/arch/arm/domctl.c b/xen/arch/arm/domctl.c
> 
> index 851ee40..cb38e59 100644
> 
> --- a/xen/arch/arm/domctl.c
> 
> +++ b/xen/arch/arm/domctl.c
> 
> @@ -9,12 +9,99 @@
> 
> #include <xen/lib.h>
> 
> #include <xen/errno.h>
> 
> #include <xen/sched.h>
> 
> +#include <xen/hvm/save.h>
> 
> +#include <xen/guest_access.h>
> 
> #include <public/domctl.h>
> 
> Â
> 
> long arch_do_domctl(struct xen_domctl *domctl, struct domain *d,
> 
> ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
> 
> {
> 
> -ÂÂÂ return -ENOSYS;
> 
> +ÂÂÂ long ret = 0;
> 
> +ÂÂÂ bool_t copyback = 0;
> 
> +
> 
> +ÂÂÂ switch ( domctl->cmd )
> 
> +ÂÂÂ {
> 
> +ÂÂÂ case XEN_DOMCTL_sethvmcontext:
> 
> +ÂÂÂ {
> 
> +ÂÂÂÂÂÂÂ struct hvm_domain_context c = { .size = domctl->u.hvmcontext.size };
> 
> +
> 
> +ÂÂÂÂÂÂÂ ret = -ENOMEM;
> 
> +ÂÂÂÂÂÂÂ if ( (c.data = xmalloc_bytes(c.size)) == NULL )
> 
> +ÂÂÂÂÂÂÂÂÂÂÂ goto sethvmcontext_out;
> 
> +
> 
> +ÂÂÂÂÂÂÂ ret = -EFAULT;
> 
> +ÂÂÂÂÂÂÂ if ( copy_from_guest(c.data, domctl->u.hvmcontext.buffer, c.size) != 
> 0 )
> 
> +ÂÂÂÂÂÂÂÂÂÂÂ goto sethvmcontext_out;
> 
> +
> 
> +ÂÂÂÂÂÂÂ domain_pause(d);
> 
> +ÂÂÂÂÂÂÂ ret = hvm_load(d, &c);
> 
> +ÂÂÂÂÂÂÂ domain_unpause(d);
> 
> +
> 
> +ÂÂÂ sethvmcontext_out:
> 
> +ÂÂÂÂÂÂÂ if ( c.data != NULL )
> 
> +ÂÂÂÂÂÂÂÂÂÂÂ xfree(c.data);
> 
> +ÂÂÂ }
> 
> +ÂÂÂ break;
> 
> +ÂÂÂ case XEN_DOMCTL_gethvmcontext:
> 
> +ÂÂÂ {
> 
> +ÂÂÂÂÂÂÂ struct hvm_domain_context c = { 0 };
> 
> +
> 
> +ÂÂÂÂÂÂÂ ret = -EINVAL;
> 
> +
> 
> +ÂÂÂÂÂÂÂ c.size = hvm_save_size(d);
> 
> +
> 
> +ÂÂÂÂÂÂÂ if ( guest_handle_is_null(domctl->u.hvmcontext.buffer) )
> 
> +ÂÂÂÂÂÂÂ {
> 
> +ÂÂÂÂÂÂÂÂÂÂÂ /* Client is querying for the correct buffer size */
> 
> +ÂÂÂÂÂÂÂÂÂÂÂ domctl->u.hvmcontext.size = c.size;
> 
> +ÂÂÂÂÂÂÂÂÂÂÂ ret = 0;
> 
> +ÂÂÂÂÂÂÂÂÂÂÂ goto gethvmcontext_out;
> 
> +ÂÂÂ ÂÂÂÂ}
> 
> +
> 
> +ÂÂÂÂÂÂÂ /* Check that the client has a big enough buffer */
> 
> +ÂÂÂÂÂÂÂ ret = -ENOSPC;
> 
> +ÂÂÂÂÂÂÂ if ( domctl->u.hvmcontext.size < c.size )
> 
> +ÂÂÂÂÂÂÂ {
> 
> +ÂÂÂÂÂÂÂÂÂÂÂ printk("(gethvmcontext) size error: %d and %d\n",
> 
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ domctl->u.hvmcontext.size, c.size );
> 
> +ÂÂÂÂÂÂÂÂÂÂÂ goto gethvmcontext_out;
> 
> +ÂÂÂÂÂÂÂ }
> 
> +
> 
> +ÂÂÂÂÂÂÂ /* Allocate our own marshalling buffer */
> 
> +ÂÂÂÂÂÂÂ ret = -ENOMEM;
> 
> +ÂÂÂÂÂÂÂ if ( (c.data = xmalloc_bytes(c.size)) == NULL )
> 
> +ÂÂÂÂÂÂÂ {
> 
> +ÂÂÂÂÂÂÂÂÂÂÂ printk("(gethvmcontext) xmalloc_bytes failed: %d\n", c.size );
> 
> +ÂÂÂÂÂÂÂÂÂÂÂ goto gethvmcontext_out;
> 
> +ÂÂÂÂÂÂÂ }
> 
> +
> 
> +ÂÂÂÂÂÂÂ domain_pause(d);
> 
> +ÂÂÂÂÂÂÂ ret = hvm_save(d, &c);
> 
> +ÂÂÂÂÂÂÂ domain_unpause(d);
> 
> +
> 
> +ÂÂÂÂÂÂÂ domctl->u.hvmcontext.size = c.cur;
> 
> +ÂÂÂÂÂÂÂ if ( copy_to_guest(domctl->u.hvmcontext.buffer, c.data, c.size) != 0 
> )
> 
> +ÂÂÂÂÂÂÂ {
> 
> +ÂÂÂÂÂÂÂÂÂÂÂ printk("(gethvmcontext) copy to guest failed\n");
> 
> +ÂÂÂÂÂÂÂÂÂÂÂ ret = -EFAULT;
> 
> +ÂÂÂÂÂÂÂ }
> 
> +
> 
> +ÂÂÂ gethvmcontext_out:
> 
> +ÂÂÂÂÂÂÂ copyback = 1;
> 
> +
> 
> +ÂÂÂÂÂÂÂ if ( c.data != NULL )
> 
> +ÂÂÂÂÂÂÂÂÂÂÂ xfree(c.data);
> 
> +ÂÂÂ }
> 
> +ÂÂÂ break;
> 
> +
> 
> +ÂÂÂ default:
> 
> +ÂÂÂÂÂÂÂ return -EINVAL;
> 
> +ÂÂÂ }
> 
> +
> 
> +ÂÂÂ if ( copyback && __copy_to_guest(u_domctl, domctl, 1) )
> 
> +ÂÂÂÂÂÂÂ ret = -EFAULT;
> 
> +
> 
> +ÂÂÂ return ret;
> 
> }
> 
> Â
> 
> void arch_get_info_guest(struct vcpu *v, vcpu_guest_context_u c)
> 
> diff --git a/xen/arch/arm/hvm.c b/xen/arch/arm/hvm.c
> 
> index 471c4cd..01ce2e7 100644
> 
> --- a/xen/arch/arm/hvm.c
> 
> +++ b/xen/arch/arm/hvm.c
> 
> @@ -7,14 +7,15 @@
> 
> Â
> 
> #include <xsm/xsm.h>
> 
> Â
> 
> +#include <xen/hvm/save.h>
> 
> #include <public/xen.h>
> 
> #include <public/hvm/params.h>
> 
> #include <public/hvm/hvm_op.h>
> 
> Â
> 
> #include <asm/hypercall.h>
> 
> +#include <asm/gic.h>
> 
> Â
> 
> long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE_PARAM(void) arg)
> 
> -
> 
> {
> 
> ÂÂÂÂ long rc = 0;
> 
> Â
> 
> @@ -65,3 +66,464 @@ long do_hvm_op(unsigned long op, 
> XEN_GUEST_HANDLE_PARAM(void) arg)
> 
> Â
> 
> ÂÂÂÂ return rc;
> 
> }
> 
> +
> 
> +static int vgic_irq_rank_save(struct vgic_rank *ext,
> 
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ struct vgic_irq_rank *rank)
> 
> +{
> 
> +ÂÂÂ spin_lock(&rank->lock);
> 
> +ÂÂÂ /* Some of VGIC registers are not used yet, it is for a future usage */
> 
> + /* IENABLE, IACTIVE, IPEND, PENDSGI registers */
> 
> +ÂÂÂ ext->ienable = rank->ienable;
> 
> +ÂÂÂ ext->iactive = rank->iactive;
> 
> +ÂÂÂ ext->ipend = rank->ipend;
> 
> +ÂÂÂ ext->pendsgi = rank->pendsgi;
> 
> +ÂÂÂ /* ICFG */
> 
> +ÂÂÂ ext->icfg[0] = rank->icfg[0];
> 
> +ÂÂÂ ext->icfg[1] = rank->icfg[1];
> 
> +ÂÂÂ /* IPRIORITY */
> 
> +ÂÂÂ if ( sizeof(rank->ipriority) != sizeof (ext->ipriority) )
> 
> +ÂÂÂ {
> 
> +ÂÂÂÂÂÂÂ dprintk(XENLOG_G_ERR, "hvm_hw_gic: check ipriority dumping space\n");
> 
> +ÂÂÂÂÂÂÂ return -EINVAL;
> 
> +ÂÂÂ }
> 
> +ÂÂÂ memcpy(ext->ipriority, rank->ipriority, sizeof(rank->ipriority));
> 
> +ÂÂÂ /* ITARGETS */
> 
> +ÂÂÂ if ( sizeof(rank->itargets) != sizeof (ext->itargets) )
> 
> +ÂÂÂ {
> 
> +ÂÂÂÂÂÂÂ dprintk(XENLOG_G_ERR, "hvm_hw_gic: check itargets dumping space\n");
> 
> +ÂÂÂÂÂÂÂ return -EINVAL;
> 
> +ÂÂÂ }
> 
> +ÂÂÂ memcpy(ext->itargets, rank->itargets, sizeof(rank->itargets));
> 
> +ÂÂÂ spin_unlock(&rank->lock);
> 
> +ÂÂÂ return 0;
> 
> +}
> 
> +
> 
> +static int vgic_irq_rank_restore(struct vgic_irq_rank *rank,
> 
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ struct vgic_rank *ext)
> 
> +{
> 
> +ÂÂÂ spin_lock(&rank->lock);
> 
> + /* IENABLE, IACTIVE, IPEND, PENDSGI registers */
> 
> +ÂÂÂ rank->ienable = ext->ienable;
> 
> +ÂÂÂ rank->iactive = ext->iactive;
> 
> +ÂÂÂ rank->ipend = ext->ipend;
> 
> +ÂÂÂ rank->pendsgi = ext->pendsgi;
> 
> +ÂÂÂ /* ICFG */
> 
> +ÂÂÂ rank->icfg[0] = ext->icfg[0];
> 
> +ÂÂÂ rank->icfg[1] = ext->icfg[1];
> 
> +ÂÂÂ /* IPRIORITY */
> 
> +ÂÂÂ if ( sizeof(rank->ipriority) != sizeof (ext->ipriority) )
> 
> +ÂÂÂ {
> 
> +ÂÂÂÂÂÂÂ dprintk(XENLOG_G_ERR, "hvm_hw_gic: check ipriority dumping space\n");
> 
> +ÂÂÂÂÂÂÂ return -EINVAL;
> 
> +ÂÂÂ }
> 
> +ÂÂÂ memcpy(rank->ipriority, ext->ipriority, sizeof(rank->ipriority));
> 
> +ÂÂÂ /* ITARGETS */
> 
> +ÂÂÂ if ( sizeof(rank->itargets) != sizeof (ext->itargets) )
> 
> +ÂÂÂ {
> 
> +ÂÂÂÂÂÂÂ dprintk(XENLOG_G_ERR, "hvm_hw_gic: check itargets dumping space\n");
> 
> +ÂÂÂÂÂÂÂ return -EINVAL;
> 
> +ÂÂÂ }
> 
> +ÂÂÂ memcpy(rank->itargets, ext->itargets, sizeof(rank->itargets));
> 
> +ÂÂÂ spin_unlock(&rank->lock);
> 
> +ÂÂÂ return 0;
> 
> +}
> 
> +
> 
> +
> 
> +static int gic_save(struct domain *d, hvm_domain_context_t *h)
> 
> +{
> 
> +ÂÂÂ struct hvm_hw_gic ctxt;
> 
> +ÂÂÂ struct vcpu *v;
> 
> +
> 
> +ÂÂÂ /* Save the state of GICs */
> 
> +ÂÂÂ for_each_vcpu( d, v )
> 
> +ÂÂÂ {
> 
> +ÂÂÂÂÂÂÂ ctxt.gic_hcr = v->arch.gic_hcr;
> 
> +ÂÂÂÂÂÂÂ ctxt.gic_vmcr = v->arch.gic_vmcr;
> 
> +ÂÂÂÂÂÂÂ ctxt.gic_apr = v->arch.gic_apr;
> 
> +
> 
> +ÂÂÂÂ ÂÂÂ/* Save list registers and masks */
> 
> +ÂÂÂÂÂÂÂ /* (it is not necessary to save/restore them, but LR state can have
> 
> +ÂÂÂÂÂÂÂÂ * influence on downtime after Live Migration (to be tested)
> 
> +ÂÂÂÂÂÂÂÂ */
> 
> +ÂÂÂÂÂÂÂ if ( sizeof(v->arch.gic_lr) > sizeof (ctxt.gic_lr) )
> 
> +ÂÂÂÂÂÂÂ {
> 
> +ÂÂÂÂÂÂÂÂÂÂÂÂ dprintk(XENLOG_G_ERR, "hvm_hw_gic: increase LR dumping 
> space\n");
> 
> +ÂÂÂÂÂÂÂÂÂÂÂÂ return -EINVAL;
> 
> +ÂÂÂÂÂÂÂ }
> 
> +ÂÂÂÂÂÂÂ memcpy(ctxt.gic_lr, v->arch.gic_lr, sizeof(v->arch.gic_lr));
> 
> +ÂÂÂÂÂÂÂ ctxt.lr_mask = v->arch.lr_mask;
> 
> +ÂÂÂÂÂÂÂ ctxt.event_mask = v->arch.event_mask;
> 
> +
> 
> +ÂÂÂÂÂÂÂ /* Save PPI states (per-CPU) */
> 
> +ÂÂÂÂÂÂÂ /* It is necessary if SMP enabled */
> 
> + if ( vgic_irq_rank_save(&ctxt.ppi_state, 
> &v->arch.vgic.private_irqs) )
> 
> +ÂÂÂÂÂÂÂÂÂÂÂ return 1;
> 
> +
> 
> +ÂÂÂÂÂÂÂ if ( hvm_save_entry(GIC, v->vcpu_id, h, &ctxt) != 0 )
> 
> +ÂÂÂÂÂÂÂÂÂÂÂ return 1;
> 
> +ÂÂÂ }
> 
> +ÂÂÂ return 0;
> 
> +}
> 
> +
> 
> +static int gic_load(struct domain *d, hvm_domain_context_t *h)
> 
> +{
> 
> +ÂÂÂ int vcpuid;
> 
> +ÂÂÂ struct hvm_hw_gic ctxt;
> 
> +ÂÂÂ struct vcpu *v;
> 
> +
> 
> +ÂÂÂ /* Which vcpu is this? */
> 
> +ÂÂÂ vcpuid = hvm_load_instance(h);
> 
> +ÂÂÂ if ( vcpuid >= d->max_vcpus || (v = d->vcpu[vcpuid]) == NULL )
> 
> +ÂÂÂ {
> 
> +ÂÂÂÂÂÂÂ dprintk(XENLOG_G_ERR, "HVM restore: dom%u has no vcpu%u\n",
> 
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ d->domain_id, vcpuid);
> 
> +ÂÂÂÂÂÂÂ return -EINVAL;
> 
> +ÂÂÂ }
> 
> +
> 
> +ÂÂÂ if ( hvm_load_entry(GIC, h, &ctxt) != 0 )
> 
> +ÂÂÂÂÂÂÂ return -EINVAL;
> 
> +
> 
> +ÂÂÂ v->arch.gic_hcr = ctxt.gic_hcr;
> 
> +ÂÂÂ v->arch.gic_vmcr = ctxt.gic_vmcr;
> 
> +ÂÂÂ v->arch.gic_apr = ctxt.gic_apr;
> 
> +
> 
> +ÂÂÂ /* Restore list registers and masks */
> 
> +ÂÂÂ if ( sizeof(v->arch.gic_lr) > sizeof (ctxt.gic_lr) )
> 
> +ÂÂÂ {
> 
> +ÂÂÂÂÂÂÂÂ dprintk(XENLOG_G_ERR, "hvm_hw_gic: increase LR dumping space\n");
> 
> +ÂÂÂÂÂÂÂÂ return -EINVAL;
> 
> +ÂÂÂ }
> 
> +ÂÂÂ memcpy(v->arch.gic_lr, ctxt.gic_lr, sizeof(v->arch.gic_lr));
> 
> +ÂÂÂ v->arch.lr_mask = ctxt.lr_mask;
> 
> +ÂÂÂ v->arch.event_mask = ctxt.event_mask;
> 
> +
> 
> +ÂÂÂ /* Restore PPI states */
> 
> +ÂÂÂ if ( vgic_irq_rank_restore(&v->arch.vgic.private_irqs, &ctxt.ppi_state) )
> 
> +ÂÂÂÂÂÂÂ return 1;
> 
> +
> 
> +ÂÂÂ return 0;
> 
> +}
> 
> +
> 
> +HVM_REGISTER_SAVE_RESTORE(GIC, gic_save, gic_load, 1, HVMSR_PER_VCPU);
> 
> +
> 
> +static int timer_save(struct domain *d, hvm_domain_context_t *h)
> 
> +{
> 
> +ÂÂÂ struct hvm_hw_timer ctxt;
> 
> +ÂÂÂ struct vcpu *v;
> 
> +ÂÂÂ struct vtimer *t;
> 
> +ÂÂÂ int i;
> 
> +
> 
> +ÂÂÂ /* Save the state of vtimer and ptimer */
> 
> +ÂÂÂ for_each_vcpu( d, v )
> 
> +ÂÂÂ {
> 
> +ÂÂÂÂÂÂÂ t = &v->arch.virt_timer;
> 
> +ÂÂÂÂÂÂÂ for ( i = 0; i < 2; i++ )
> 
> +ÂÂÂÂÂÂÂ {
> 
> +ÂÂÂÂÂÂÂÂÂÂÂ ctxt.cval = t->cval;
> 
> +ÂÂÂÂÂÂÂÂÂÂÂ ctxt.ctl = t->ctl;
> 
> +ÂÂÂÂÂÂÂÂÂÂÂ ctxt.vtb_offset = i ? d->arch.phys_timer_base.offset :
> 
> +ÂÂÂÂÂÂ ÂÂÂÂÂÂÂÂÂd->arch.virt_timer_base.offset;
> 
> +ÂÂÂÂÂÂÂÂÂÂÂ ctxt.type = i ? TIMER_TYPE_PHYS : TIMER_TYPE_VIRT;
> 
> +ÂÂÂÂÂÂÂÂÂÂÂ if ( hvm_save_entry(A15_TIMER, v->vcpu_id, h, &ctxt) != 0 )
> 
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ return 1;
> 
> +ÂÂÂÂÂÂÂÂÂÂÂ t = &v->arch.phys_timer;
> 
> +ÂÂÂÂÂÂÂ }
> 
> + ÂÂÂ}
> 
> +
> 
> +ÂÂÂ return 0;
> 
> +}
> 
> +
> 
> +static int timer_load(struct domain *d, hvm_domain_context_t *h)
> 
> +{
> 
> +ÂÂÂ int vcpuid;
> 
> +ÂÂÂ struct hvm_hw_timer ctxt;
> 
> +ÂÂÂ struct vcpu *v;
> 
> +ÂÂÂ struct vtimer *t = NULL;
> 
> +
> 
> +ÂÂÂ /* Which vcpu is this? */
> 
> +ÂÂÂ vcpuid = hvm_load_instance(h);
> 
> +
> 
> +ÂÂÂ if ( vcpuid >= d->max_vcpus || (v = d->vcpu[vcpuid]) == NULL )
> 
> +ÂÂÂ {
> 
> +ÂÂÂÂÂÂÂ dprintk(XENLOG_G_ERR, "HVM restore: dom%u has no vcpu%u\n",
> 
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ d->domain_id, vcpuid);
> 
> +ÂÂÂÂÂÂÂ return -EINVAL;
> 
> +ÂÂÂ }
> 
> +
> 
> +ÂÂÂ if ( hvm_load_entry(A15_TIMER, h, &ctxt) != 0 )
> 
> +ÂÂÂÂÂÂÂ return -EINVAL;
> 
> +
> 
> +
> 
> +ÂÂÂ if ( ctxt.type == TIMER_TYPE_VIRT )
> 
> +ÂÂÂ {
> 
> +ÂÂÂÂÂÂÂ t = &v->arch.virt_timer;
> 
> +ÂÂÂÂÂÂÂ d->arch.virt_timer_base.offset = ctxt.vtb_offset;
> 
> +
> 
> +ÂÂÂ }
> 
> +ÂÂÂ else
> 
> +ÂÂÂ {
> 
> +ÂÂÂÂÂ ÂÂt = &v->arch.phys_timer;
> 
> +ÂÂÂÂÂÂÂ d->arch.phys_timer_base.offset = ctxt.vtb_offset;
> 
> +ÂÂÂ }
> 
> +
> 
> +ÂÂÂ t->cval = ctxt.cval;
> 
> +ÂÂÂ t->ctl = ctxt.ctl;
> 
> +ÂÂÂ t->v = v;
> 
> +
> 
> +ÂÂÂ return 0;
> 
> +}
> 
> +
> 
> +HVM_REGISTER_SAVE_RESTORE(A15_TIMER, timer_save, timer_load, 2, 
> HVMSR_PER_VCPU);
> 
> +
> 
> +static int cpu_save(struct domain *d, hvm_domain_context_t *h)
> 
> +{
> 
> +ÂÂÂ struct hvm_hw_cpu ctxt;
> 
> +ÂÂÂ struct vcpu_guest_core_regs c;
> 
> +ÂÂÂ struct vcpu *v;
> 
> +
> 
> +ÂÂÂ /* Save the state of CPU */
> 
> +ÂÂÂ for_each_vcpu( d, v )
> 
> +ÂÂÂ {
> 
> +ÂÂÂÂÂÂÂ memset(&ctxt, 0, sizeof(ctxt));
> 
> +
> 
> +ÂÂÂÂÂÂÂ ctxt.sctlr = v->arch.sctlr;
> 
> +ÂÂÂÂÂÂÂ ctxt.ttbr0 = v->arch.ttbr0;
> 
> +ÂÂÂÂÂÂÂ ctxt.ttbr1 = v->arch.ttbr1;
> 
> +ÂÂÂÂÂÂÂ ctxt.ttbcr = v->arch.ttbcr;
> 
> +
> 
> +ÂÂÂÂÂÂÂ ctxt.dacr = v->arch.dacr;
> 
> +ÂÂÂÂÂÂÂ ctxt.ifar = v->arch.ifar;
> 
> +ÂÂÂÂÂÂÂ ctxt.ifsr = v->arch.ifsr;
> 
> +ÂÂÂÂÂÂÂ ctxt.dfar = v->arch.dfar;
> 
> +ÂÂÂÂÂÂÂ ctxt.dfsr = v->arch.dfsr;
> 
> +
> 
> +#ifdef CONFIG_ARM_32
> 
> +ÂÂÂÂÂÂÂ ctxt.mair0 = v->arch.mair0;
> 
> +ÂÂÂÂÂÂÂ ctxt.mair1 = v->arch.mair1;
> 
> +#else
> 
> +ÂÂÂÂÂÂÂ ctxt.mair0 = v->arch.mair;
> 
> +#endif
> 
> +ÂÂÂÂÂÂÂ /* Control Registers */
> 
> +ÂÂÂÂÂÂÂ ctxt.actlr = v->arch.actlr;
> 
> +ÂÂÂÂÂÂÂ ctxt.sctlr = v->arch.sctlr;
> 
> +ÂÂÂÂÂÂÂ ctxt.cpacr = v->arch.cpacr;
> 
> +
> 
> +ÂÂÂÂÂÂÂ ctxt.contextidr = v->arch.contextidr;
> 
> +ÂÂÂÂÂÂÂ ctxt.tpidr_el0 = v->arch.tpidr_el0;
> 
> +ÂÂÂÂÂÂÂ ctxt.tpidr_el1 = v->arch.tpidr_el1;
> 
> +ÂÂÂÂÂÂÂ ctxt.tpidrro_el0 = v->arch.tpidrro_el0;
> 
> +
> 
> +ÂÂÂÂÂÂÂ /* CP 15 */
> 
> +ÂÂÂÂÂÂÂ ctxt.csselr = v->arch.csselr;
> 
> +
> 
> +ÂÂÂÂÂÂÂ ctxt.afsr0 = v->arch.afsr0;
> 
> +ÂÂÂÂÂÂÂ ctxt.afsr1 = v->arch.afsr1;
> 
> +ÂÂÂÂÂÂÂ ctxt.vbar = v->arch.vbar;
> 
> +ÂÂÂÂÂÂÂ ctxt.par = v->arch.par;
> 
> +ÂÂÂÂÂÂÂ ctxt.teecr = v->arch.teecr;
> 
> +ÂÂÂÂÂÂÂ ctxt.teehbr = v->arch.teehbr;
> 
> +ÂÂÂÂÂÂÂ ctxt.joscr = v->arch.joscr;
> 
> +ÂÂÂÂÂÂÂ ctxt.jmcr = v->arch.jmcr;
> 
> +
> 
> +ÂÂÂÂÂÂÂ memset(&c, 0, sizeof(c));
> 
> +
> 
> +ÂÂÂÂÂÂÂ /* get guest core registers */
> 
> +ÂÂÂÂÂÂÂ vcpu_regs_hyp_to_user(v, &c);
> 
> +
> 
> +ÂÂÂÂÂÂÂ ctxt.x0 = c.x0;
> 
> +ÂÂÂÂÂÂÂ ctxt.x1 = c.x1;
> 
> +ÂÂÂÂÂÂÂ ctxt.x2 = c.x2;
> 
> +ÂÂÂÂÂÂÂ ctxt.x3 = c.x3;
> 
> +ÂÂÂÂÂÂÂ ctxt.x4 = c.x4;
> 
> +ÂÂÂÂÂÂÂ ctxt.x5 = c.x5;
> 
> +ÂÂÂÂÂÂÂ ctxt.x6 = c.x6;
> 
> +ÂÂÂÂÂÂÂ ctxt.x7 = c.x7;
> 
> +ÂÂÂÂÂÂÂ ctxt.x8 = c.x8;
> 
> +ÂÂÂÂÂÂÂ ctxt.x9 = c.x9;
> 
> +ÂÂÂÂÂÂÂ ctxt.x10 = c.x10;
> 
> +ÂÂÂÂÂÂÂ ctxt.x11 = c.x11;
> 
> +ÂÂÂÂÂÂÂ ctxt.x12 = c.x12;
> 
> +ÂÂÂÂÂÂÂ ctxt.x13 = c.x13;
> 
> +ÂÂÂÂÂÂÂ ctxt.x14 = c.x14;
> 
> +ÂÂÂÂÂÂÂ ctxt.x15 = c.x15;
> 
> +ÂÂÂÂÂÂÂ ctxt.x16 = c.x16;
> 
> +ÂÂÂÂÂÂÂ ctxt.x17 = c.x17;
> 
> +ÂÂÂÂÂÂÂ ctxt.x18 = c.x18;
> 
> +ÂÂÂÂÂÂÂ ctxt.x19 = c.x19;
> 
> +ÂÂÂÂÂÂÂ ctxt.x20 = c.x20;
> 
> +ÂÂÂÂÂÂÂ ctxt.x21 = c.x21;
> 
> +ÂÂÂÂÂÂÂ ctxt.x22 = c.x22;
> 
> +ÂÂÂÂÂÂÂ ctxt.x23 = c.x23;
> 
> +ÂÂÂÂÂÂÂ ctxt.x24 = c.x24;
> 
> +ÂÂÂÂÂÂÂ ctxt.x25 = c.x25;
> 
> +ÂÂÂÂÂÂÂ ctxt.x26 = c.x26;
> 
> +ÂÂÂÂÂÂÂ ctxt.x27 = c.x27;
> 
> +ÂÂÂÂÂÂÂ ctxt.x28 = c.x28;
> 
> +ÂÂÂÂÂÂÂ ctxt.x29 = c.x29;
> 
> +ÂÂÂÂÂÂÂ ctxt.x30 = c.x30;
> 
> +ÂÂÂÂÂÂÂ ctxt.pc64 = c.pc64;
> 
> +ÂÂÂÂÂÂÂ ctxt.cpsr = c.cpsr;
> 
> +ÂÂÂÂÂÂÂ ctxt.spsr_el1 = c.spsr_el1; /* spsr_svc */
> 
> +
> 
> +ÂÂÂÂÂÂÂ #ifdef CONFIG_ARM_32
> 
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ ctxt.spsr_fiq = c.spsr_fiq;
> 
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ ctxt.spsr_irq = c.spsr_irq;
> 
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ ctxt.spsr_und = c.spsr_und;
> 
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ ctxt.spsr_abt = c.spsr_abt;
> 
> +ÂÂÂÂÂÂÂ #endif
> 
> +ÂÂÂÂÂÂÂ #ifdef CONFIG_ARM_64
> 
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ ctxt.sp_el0 = c.sp_el0;
> 
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ ctxt.sp_el1 = c.sp_el1;
> 
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ ctxt.elr_el1 = c.elr_el1;
> 
> +ÂÂÂÂÂÂÂ #endif
> 
> +
> 
> +ÂÂÂÂÂÂÂ /* check VFP state size before dumping */
> 
> +ÂÂÂÂÂÂÂ if ( sizeof(v->arch.vfp) > sizeof (ctxt.vfp) )
> 
> +ÂÂÂÂÂÂÂ {
> 
> +ÂÂÂÂÂÂÂÂÂÂÂ dprintk(XENLOG_G_ERR, "hvm_hw_cpu: increase VFP dumping 
> space\n");
> 
> +ÂÂÂÂÂÂÂÂÂÂÂ return -EINVAL;
> 
> +ÂÂÂÂÂÂÂ }
> 
> +ÂÂÂÂÂÂÂ memcpy((void*) &ctxt.vfp, (void*) &v->arch.vfp, sizeof(v->arch.vfp));
> 
> +
> 
> +ÂÂÂÂÂÂÂ ctxt.pause_flags = v->pause_flags;
> 
> +
> 
> +ÂÂÂÂÂÂÂ if ( hvm_save_entry(VCPU, v->vcpu_id, h, &ctxt) != 0 )
> 
> +ÂÂÂÂÂÂÂÂÂÂÂ return 1;
> 
> +ÂÂÂ }
> 
> +ÂÂÂ return 0;
> 
> +}
> 
> +
> 
> +static int cpu_load(struct domain *d, hvm_domain_context_t *h)
> 
> +{
> 
> +ÂÂÂ int vcpuid;
> 
> +ÂÂÂ struct hvm_hw_cpu ctxt;
> 
> +ÂÂÂ struct vcpu *v;
> 
> +ÂÂÂ struct vcpu_guest_core_regs c;
> 
> +
> 
> +ÂÂÂ /* Which vcpu is this? */
> 
> +ÂÂÂ vcpuid = hvm_load_instance(h);
> 
> +ÂÂÂ if ( vcpuid >= d->max_vcpus || (v = d->vcpu[vcpuid]) == NULL )
> 
> +ÂÂÂ {
> 
> +ÂÂÂÂÂÂÂ dprintk(XENLOG_G_ERR, "HVM restore: dom%u has no vcpu%u\n",
> 
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂÂ d->domain_id, vcpuid);
> 
> +ÂÂÂÂÂÂÂ return -EINVAL;
> 
> +ÂÂÂ }
> 
> +
> 
> +ÂÂÂ if ( hvm_load_entry(VCPU, h, &ctxt) != 0 )
> 
> +ÂÂÂÂÂÂÂ return -EINVAL;
> 
> +
> 
> +ÂÂÂ v->arch.sctlr = ctxt.sctlr;
> 
> +ÂÂÂ v->arch.ttbr0 = ctxt.ttbr0;
> 
> +ÂÂÂ v->arch.ttbr1 = ctxt.ttbr1;
> 
> +ÂÂÂ v->arch.ttbcr = ctxt.ttbcr;
> 
> +
> 
> +ÂÂÂ v->arch.dacr = ctxt.dacr;
> 
> +ÂÂÂ v->arch.ifar = ctxt.ifar;
> 
> +ÂÂÂ v->arch.ifsr = ctxt.ifsr;
> 
> +ÂÂÂ v->arch.dfar = ctxt.dfar;
> 
> +ÂÂÂ v->arch.dfsr = ctxt.dfsr;
> 
> +
> 
> +#ifdef CONFIG_ARM_32
> 
> +ÂÂÂ v->arch.mair0 = ctxt.mair0;
> 
> +ÂÂÂ v->arch.mair1 = ctxt.mair1;
> 
> +#else
> 
> +ÂÂÂ v->arch.mair = ctxt.mair0;
> 
> +#endif
> 
> +
> 
> +ÂÂÂ /* Control Registers */
> 
> +ÂÂÂ v->arch.actlr = ctxt.actlr;
> 
> +ÂÂÂ v->arch.cpacr = ctxt.cpacr;
> 
> +ÂÂÂ v->arch.contextidr = ctxt.contextidr;
> 
> +ÂÂÂ v->arch.tpidr_el0 = ctxt.tpidr_el0;
> 
> +ÂÂÂ v->arch.tpidr_el1 = ctxt.tpidr_el1;
> 
> +ÂÂÂ v->arch.tpidrro_el0 = ctxt.tpidrro_el0;
> 
> +
> 
> +ÂÂÂ /* CP 15 */
> 
> +ÂÂÂ v->arch.csselr = ctxt.csselr;
> 
> +
> 
> +ÂÂÂ v->arch.afsr0 = ctxt.afsr0;
> 
> +ÂÂÂ v->arch.afsr1 = ctxt.afsr1;
> 
> +ÂÂÂ v->arch.vbar = ctxt.vbar;
> 
> +ÂÂÂ v->arch.par = ctxt.par;
> 
> +ÂÂÂ v->arch.teecr = ctxt.teecr;
> 
> +ÂÂÂ v->arch.teehbr = ctxt.teehbr;
> 
> +ÂÂÂ v->arch.joscr = ctxt.joscr;
> 
> +ÂÂÂ v->arch.jmcr = ctxt.jmcr;
> 
> +
> 
> +ÂÂÂ /* fill guest core registers */
> 
> +ÂÂÂ memset(&c, 0, sizeof(c));
> 
> +ÂÂÂ c.x0 = ctxt.x0;
> 
> +ÂÂÂ c.x1 = ctxt.x1;
> 
> +ÂÂÂ c.x2 = ctxt.x2;
> 
> +ÂÂÂ c.x3 = ctxt.x3;
> 
> +ÂÂÂ c.x4 = ctxt.x4;
> 
> +ÂÂÂ c.x5 = ctxt.x5;
> 
> +ÂÂÂ c.x6 = ctxt.x6;
> 
> +ÂÂÂ c.x7 = ctxt.x7;
> 
> +ÂÂÂ c.x8 = ctxt.x8;
> 
> +ÂÂÂ c.x9 = ctxt.x9;
> 
> +ÂÂÂ c.x10 = ctxt.x10;
> 
> +ÂÂÂ c.x11 = ctxt.x11;
> 
> +ÂÂÂ c.x12 = ctxt.x12;
> 
> +ÂÂÂ c.x13 = ctxt.x13;
> 
> +ÂÂÂ c.x14 = ctxt.x14;
> 
> +ÂÂÂ c.x15 = ctxt.x15;
> 
> +ÂÂÂ c.x16 = ctxt.x16;
> 
> +ÂÂÂ c.x17 = ctxt.x17;
> 
> +ÂÂÂ c.x18 = ctxt.x18;
> 
> +ÂÂÂ c.x19 = ctxt.x19;
> 
> +ÂÂÂ c.x20 = ctxt.x20;
> 
> +ÂÂÂ c.x21 = ctxt.x21;
> 
> +ÂÂÂ c.x22 = ctxt.x22;
> 
> +ÂÂÂ c.x23 = ctxt.x23;
> 
> +ÂÂÂ c.x24 = ctxt.x24;
> 
> +ÂÂÂ c.x25 = ctxt.x25;
> 
> +ÂÂÂ c.x26 = ctxt.x26;
> 
> +ÂÂÂ c.x27 = ctxt.x27;
> 
> +ÂÂÂ c.x28 = ctxt.x28;
> 
> +ÂÂÂ c.x29 = ctxt.x29;
> 
> +ÂÂÂ c.x30 = ctxt.x30;
> 
> +ÂÂÂ c.pc64 = ctxt.pc64;
> 
> +ÂÂÂ c.cpsr = ctxt.cpsr;
> 
> +ÂÂÂ c.spsr_el1 = ctxt.spsr_el1; /* spsr_svc */
> 
> +
> 
> +ÂÂ #ifdef CONFIG_ARM_32
> 
> +ÂÂÂ c.spsr_fiq = ctxt.spsr_fiq;
> 
> +ÂÂÂ c.spsr_irq = ctxt.spsr_irq;
> 
> +ÂÂÂ c.spsr_und = ctxt.spsr_und;
> 
> +ÂÂÂ c.spsr_abt = ctxt.spsr_abt;
> 
> +ÂÂ #endif
> 
> +ÂÂ #ifdef CONFIG_ARM_64
> 
> +ÂÂÂ c.sp_el0 = ctxt.sp_el0;
> 
> +ÂÂÂ c.sp_el1 = ctxt.sp_el1;
> 
> +ÂÂÂ c.elr_el1 = ctxt.elr_el1;
> 
> +ÂÂ #endif
> 
> +
> 
> +ÂÂÂ /* set guest core registers */
> 
> +ÂÂÂ vcpu_regs_user_to_hyp(v, &c);
> 
> +
> 
> +ÂÂÂ if ( sizeof(v->arch.vfp) > sizeof (ctxt.vfp) )
> 
> +ÂÂÂ {
> 
> +ÂÂÂÂÂÂÂ dprintk(XENLOG_G_ERR, "hvm_hw_cpu: increase VFP dumping space\n");
> 
> +ÂÂÂÂÂÂÂ return -EINVAL;
> 
> +ÂÂÂ }
> 
> +
> 
> + memcpy(&v->arch.vfp, &ctxt, sizeof(v->arch.vfp));
> 
> +
> 
> +ÂÂÂ v->is_initialised = 1;
> 
> +ÂÂÂ v->pause_flags = ctxt.pause_flags;
> 
> +
> 
> +ÂÂÂ return 0;
> 
> +}
> 
> +
> 
> +HVM_REGISTER_SAVE_RESTORE(VCPU, cpu_save, cpu_load, 1, HVMSR_PER_VCPU);
> 
> +
> 
> +/*
> 
> + * Local variables:
> 
> + * mode: C
> 
> + * c-file-style: "BSD"
> 
> + * c-basic-offset: 4
> 
> + * tab-width: 4
> 
> + * indent-tabs-mode: nil
> 
> + * End:
> 
> + */
> 
> diff --git a/xen/arch/arm/save.c b/xen/arch/arm/save.c
> 
> new file mode 100644
> 
> index 0000000..c923910
> 
> --- /dev/null
> 
> +++ b/xen/arch/arm/save.c
> 
> @@ -0,0 +1,66 @@
> 
> +/*
> 
> + * hvm/save.c: Save and restore HVM guest's emulated hardware state for ARM.
> 
> + *
> 
> + * Copyright (c) 2013, Samsung Electronics.
> 
> + *
> 
> + * This program is free software; you can redistribute it and/or modify it
> 
> + * under the terms and conditions of the GNU General Public License,
> 
> + * version 2, as published by the Free Software Foundation.
> 
> + *
> 
> + * This program is distributed in the hope it will be useful, but WITHOUT
> 
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> 
> + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
> 
> + * more details.
> 
> + *
> 
> + * You should have received a copy of the GNU General Public License along 
> with
> 
> + * this program; if not, write to the Free Software Foundation, Inc., 59 
> Temple
> 
> + * Place - Suite 330, Boston, MA 02111-1307 USA.
> 
> + */
> 
> +
> 
> +#include <asm/hvm/support.h>
> 
> +#include <public/hvm/save.h>
> 
> +
> 
> +void arch_hvm_save(struct domain *d, struct hvm_save_header *hdr)
> 
> +{
> 
> +ÂÂÂ hdr->cpuid = READ_SYSREG32(MIDR_EL1);
> 
> +}
> 
> +
> 
> +int arch_hvm_load(struct domain *d, struct hvm_save_header *hdr)
> 
> +{
> 
> +ÂÂÂ uint32_t cpuid;
> 
> +
> 
> +ÂÂÂ if ( hdr->magic != HVM_FILE_MAGIC )
> 
> +ÂÂÂ {
> 
> +ÂÂÂÂÂÂÂ printk(XENLOG_G_ERR "HVM%d restore: bad magic number %#"PRIx32"\n",
> 
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂ d->domain_id, hdr->magic);
> 
> +ÂÂÂÂÂÂÂ return -1;
> 
> +ÂÂÂ }
> 
> +
> 
> +ÂÂÂ if ( hdr->version != HVM_FILE_VERSION )
> 
> +ÂÂÂ {
> 
> +ÂÂÂÂÂÂÂ printk(XENLOG_G_ERR "HVM%d restore: unsupported version %u\n",
> 
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂ d->domain_id, hdr->version);
> 
> +ÂÂÂÂÂÂÂ return -1;
> 
> +ÂÂÂ }
> 
> +
> 
> +ÂÂÂ cpuid = READ_SYSREG32(MIDR_EL1);
> 
> +ÂÂÂ if ( hdr->cpuid != cpuid )
> 
> +ÂÂÂ {
> 
> +ÂÂÂÂÂÂÂ printk(XENLOG_G_INFO "HVM%d restore: VM saved on one CPU "
> 
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂ "(%#"PRIx32") and restored on another (%#"PRIx32").\n",
> 
> +ÂÂÂÂÂÂÂÂÂÂÂÂÂÂ d->domain_id, hdr->cpuid, cpuid);
> 
> +ÂÂÂÂÂÂÂ return -1;
> 
> +ÂÂÂ }
> 
> +
> 
> +ÂÂÂ return 0;
> 
> +}
> 
> +
> 
> +/*
> 
> + * Local variables:
> 
> + * mode: C
> 
> + * c-file-style: "BSD"
> 
> + * c-basic-offset: 4
> 
> + * tab-width: 4
> 
> + * indent-tabs-mode: nil
> 
> + * End:
> 
> + */
> 
> diff --git a/xen/common/Makefile b/xen/common/Makefile
> 
> index 686f7a1..f943302 100644
> 
> --- a/xen/common/Makefile
> 
> +++ b/xen/common/Makefile
> 
> @@ -63,6 +63,8 @@ subdir-$(CONFIG_COMPAT) += compat
> 
> Â
> 
> subdir-$(x86_64) += hvm
> 
> Â
> 
> +subdir-$(CONFIG_ARM) += hvm
> 
> +
> 
> subdir-$(coverage) += gcov
> 
> Â
> 
> subdir-y += libelf
> 
> diff --git a/xen/include/asm-arm/hvm/support.h 
> b/xen/include/asm-arm/hvm/support.h
> 
> new file mode 100644
> 
> index 0000000..8311f2f
> 
> --- /dev/null
> 
> +++ b/xen/include/asm-arm/hvm/support.h
> 
> @@ -0,0 +1,29 @@
> 
> +/*
> 
> + * support.h: HVM support routines used by ARMv7 VE.
> 
> + *
> 
> + * Copyright (c) 2012, Citrix Systems
> 
> + *
> 
> + * This program is free software; you can redistribute it and/or modify it
> 
> + * under the terms and conditions of the GNU General Public License,
> 
> + * version 2, as published by the Free Software Foundation.
> 
> + *
> 
> + * This program is distributed in the hope it will be useful, but WITHOUT
> 
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> 
> + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
> 
> + * more details.
> 
> + *
> 
> + * You should have received a copy of the GNU General Public License along 
> with
> 
> + * this program; if not, write to the Free Software Foundation, Inc., 59 
> Temple
> 
> + * Place - Suite 330, Boston, MA 02111-1307 USA.
> 
> + */
> 
> +
> 
> +#ifndef __ASM_ARM_HVM_SUPPORT_H__
> 
> +#define __ASM_ARM_HVM_SUPPORT_H__
> 
> +
> 
> +#include <xen/types.h>
> 
> +#include <public/hvm/ioreq.h>
> 
> +#include <xen/sched.h>
> 
> +#include <xen/hvm/save.h>
> 
> +#include <asm/processor.h>
> 
> +
> 
> +#endif /* __ASM_ARM_HVM_SUPPORT_H__ */
> 
> diff --git a/xen/include/public/arch-arm/hvm/save.h 
> b/xen/include/public/arch-arm/hvm/save.h
> 
> index 75b8e65..1f71c41 100644
> 
> --- a/xen/include/public/arch-arm/hvm/save.h
> 
> +++ b/xen/include/public/arch-arm/hvm/save.h
> 
> @@ -26,6 +26,136 @@
> 
> #ifndef __XEN_PUBLIC_HVM_SAVE_ARM_H__
> 
> #define __XEN_PUBLIC_HVM_SAVE_ARM_H__
> 
> Â
> 
> +#define HVM_FILE_MAGICÂÂ 0x92385520
> 
> +#define HVM_FILE_VERSION 0x00000001
> 
> +
> 
> +
> 
> +struct hvm_save_header
> 
> +{
> 
> +ÂÂÂ uint32_t magic;ÂÂÂÂ ÂÂÂÂÂÂÂÂ/* Must be HVM_FILE_MAGIC */
> 
> +ÂÂÂ uint32_t version;ÂÂÂÂÂÂÂÂÂÂ /* File format version */
> 
> +ÂÂÂ uint64_t changeset;ÂÂÂÂÂÂÂÂ /* Version of Xen that saved this file */
> 
> +ÂÂÂ uint32_t cpuid;ÂÂÂÂÂÂÂÂÂÂÂÂ /* MIDR_EL1 on the saving machine */
> 
> +};
> 
> +
> 
> +DECLARE_HVM_SAVE_TYPE(HEADER, 1, struct hvm_save_header);
> 
> +
> 
> +struct vgic_rank
> 
> +{
> 
> +ÂÂÂ uint32_t ienable, iactive, ipend, pendsgi;
> 
> +ÂÂÂ uint32_t icfg[2];
> 
> +ÂÂÂ uint32_t ipriority[8];
> 
> +ÂÂÂ uint32_t itargets[8];
> 
> +};
> 
> +
> 
> +struct hvm_hw_gic
> 
> +{
> 
> +ÂÂÂ uint32_t gic_hcr;
> 
> +ÂÂÂ uint32_t gic_vmcr;
> 
> +ÂÂÂ uint32_t gic_apr;
> 
> +ÂÂÂ uint32_t gic_lr[64];
> 
> +ÂÂÂ uint64_t event_mask;
> 
> +ÂÂÂ uint64_t lr_mask;
> 
> +ÂÂÂ struct vgic_rank ppi_state;
> 
> +};
> 
> +
> 
> +DECLARE_HVM_SAVE_TYPE(GIC, 2, struct hvm_hw_gic);
> 
> +
> 
> +#define TIMER_TYPE_VIRT 0
> 
> +#define TIMER_TYPE_PHYS 1
> 
> +
> 
> +struct hvm_hw_timer
> 
> +{
> 
> +ÂÂÂ uint64_t vtb_offset;
> 
> +ÂÂÂ uint32_t ctl;
> 
> +ÂÂÂ uint64_t cval;
> 
> +ÂÂÂ uint32_t type;
> 
> +};
> 
> +
> 
> +DECLARE_HVM_SAVE_TYPE(A15_TIMER, 3, struct hvm_hw_timer);
> 
> +
> 
> +
> 
> +struct hvm_hw_cpu
> 
> +{
> 
> +ÂÂÂ uint64_t vfp[34]; /* Vector floating pointer */
> 
> +ÂÂÂ /* VFP v3 state is 34x64 bit, VFP v4 is not yet supported */
> 
> +
> 
> +ÂÂÂ /* Guest core registers */
> 
> +ÂÂÂ uint64_t x0;ÂÂÂÂ /* r0_usr */
> 
> +ÂÂÂ uint64_t x1;ÂÂÂÂ /* r1_usr */
> 
> +ÂÂÂ uint64_t x2;ÂÂÂÂ /* r2_usr */
> 
> +ÂÂÂ uint64_t x3;ÂÂÂÂ /* r3_usr */
> 
> +ÂÂÂ uint64_t x4;ÂÂÂÂ /* r4_usr */
> 
> +ÂÂÂ uint64_t x5;ÂÂÂÂ /* r5_usr */
> 
> +ÂÂÂ uint64_t x6;ÂÂÂÂ /* r6_usr */
> 
> +ÂÂÂ uint64_t x7;ÂÂÂÂ /* r7_usr */
> 
> +ÂÂÂ uint64_t x8;ÂÂÂÂ /* r8_usr */
> 
> +ÂÂÂ uint64_t x9;ÂÂÂÂ /* r9_usr */
> 
> +ÂÂÂ uint64_t x10;ÂÂÂ /* r10_usr */
> 
> +ÂÂÂ uint64_t x11;ÂÂÂ /* r11_usr */
> 
> +ÂÂÂ uint64_t x12;ÂÂÂ /* r12_usr */
> 
> +ÂÂÂ uint64_t x13;ÂÂÂ /* sp_usr */
> 
> +ÂÂÂ uint64_t x14;ÂÂÂ /* lr_usr; */
> 
> +ÂÂÂ uint64_t x15;ÂÂÂ /* __unused_sp_hyp */
> 
> +ÂÂÂ uint64_t x16;ÂÂÂ /* lr_irq */
> 
> +ÂÂÂ uint64_t x17;ÂÂÂ /* sp_irq */
> 
> +ÂÂÂ uint64_t x18;ÂÂÂ /* lr_svc */
> 
> +ÂÂÂ uint64_t x19;ÂÂÂ /* sp_svc */
> 
> +ÂÂÂ uint64_t x20;ÂÂÂ /* lr_abt */
> 
> +ÂÂÂ uint64_t x21;ÂÂÂ /* sp_abt */
> 
> +ÂÂÂ uint64_t x22;ÂÂÂ /* lr_und */
> 
> +ÂÂÂ uint64_t x23;ÂÂÂ /* sp_und */
> 
> +ÂÂÂ uint64_t x24;ÂÂÂ /* r8_fiq */
> 
> +ÂÂÂ uint64_t x25;ÂÂÂ /* r9_fiq */
> 
> +ÂÂÂ uint64_t x26;ÂÂÂ /* r10_fiq */
> 
> +ÂÂÂ uint64_t x27;ÂÂÂ /* r11_fiq */
> 
> +ÂÂÂ uint64_t x28;ÂÂÂ /* r12_fiq */
> 
> +ÂÂÂ uint64_t x29;ÂÂÂ /* fp,sp_fiq */
> 
> +ÂÂÂ uint64_t x30;ÂÂÂ /* lr_fiq */
> 
> +ÂÂÂ uint64_t pc64;ÂÂ /* ELR_EL2 */
> 
> +ÂÂÂ uint32_t cpsr;ÂÂ /* SPSR_EL2 */
> 
> +ÂÂÂ uint32_t spsr_el1;Â /*spsr_svc */
> 
> +ÂÂÂ /* AArch32 guests only */
> 
> +ÂÂÂ uint32_t spsr_fiq, spsr_irq, spsr_und, spsr_abt;
> 
> +ÂÂÂ /* AArch64 guests only */
> 
> +ÂÂÂ uint64_t sp_el0;
> 
> +ÂÂÂ uint64_t sp_el1, elr_el1;
> 
> +
> 
> +ÂÂÂ uint32_t sctlr, ttbcr;
> 
> +ÂÂÂ uint64_t ttbr0, ttbr1;
> 
> +
> 
> +ÂÂÂ uint32_t ifar, dfar;
> 
> +ÂÂÂ uint32_t ifsr, dfsr;
> 
> +ÂÂÂ uint32_t dacr;
> 
> +ÂÂÂ uint64_t par;
> 
> +
> 
> +ÂÂÂ uint64_t mair0, mair1;
> 
> +ÂÂÂ uint64_t tpidr_el0;
> 
> +ÂÂÂ uint64_t tpidr_el1;
> 
> +ÂÂÂ uint64_t tpidrro_el0;
> 
> +ÂÂÂ uint64_t vbar;
> 
> +
> 
> +ÂÂÂ /* Control Registers */
> 
> +ÂÂÂ uint32_t actlr;
> 
> +ÂÂÂ uint32_t cpacr;
> 
> +ÂÂÂ uint32_t afsr0, afsr1;
> 
> +ÂÂÂ uint32_t contextidr;
> 
> +ÂÂÂ uint32_t teecr, teehbr; /* ThumbEE, 32-bit guests only */
> 
> +ÂÂÂ uint32_t joscr, jmcr;
> 
> +ÂÂÂ /* CP 15 */
> 
> +ÂÂÂ uint32_t csselr;
> 
> +
> 
> +ÂÂÂ unsigned long pause_flags;
> 
> +
> 
> +};
> 
> +
> 
> +DECLARE_HVM_SAVE_TYPE(VCPU, 4, struct hvm_hw_cpu);
> 
> +
> 
> +/*
> 
> + * Largest type-code in use
> 
> + */
> 
> +#define HVM_SAVE_CODE_MAX 4
> 
> +
> 
> #endif
> 
> Â
> 
> /*
> 
> --
> 
> 1.8.1.2
> 
> 
> 
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.