All of lore.kernel.org
 help / color / mirror / Atom feed
From: Andrew Cooper <andrew.cooper3@citrix.com>
To: Jan Beulich <JBeulich@suse.com>, Jinsong Liu <jinsong.liu@intel.com>
Cc: "xen-devel@lists.xen.org" <xen-devel@lists.xen.org>,
	"keir@xen.org" <keir@xen.org>,
	"Ian.Campbell@citrix.com" <Ian.Campbell@citrix.com>,
	"haoxudong.hao@gmail.com" <haoxudong.hao@gmail.com>
Subject: Re: [PATCH v2] x86: generic MSRs save/restore
Date: Fri, 13 Dec 2013 17:44:29 +0000	[thread overview]
Message-ID: <52AB477D.3060206@citrix.com> (raw)
In-Reply-To: <52AB2165020000780010D068@nat28.tlf.novell.com>

On 13/12/2013 14:01, Jan Beulich wrote:
> This patch introduces a generic MSRs save/restore mechanism, so that
> in the future new MSRs save/restore could be added w/ smaller change
> than the full blown addition of a new save/restore type.
>
> Signed-off-by: Jan Beulich <jbeulich@suse.com>
>
> --- a/xen/arch/x86/hvm/hvm.c
> +++ b/xen/arch/x86/hvm/hvm.c
> @@ -1127,10 +1127,117 @@ static int hvm_load_cpu_xsave_states(str
>      return 0;
>  }
>  
> -/* We need variable length data chunk for xsave area, hence customized
> - * declaration other than HVM_REGISTER_SAVE_RESTORE.
> +#define HVM_CPU_MSR_SIZE(cnt) offsetof(struct hvm_msr, msr[cnt])
> +static unsigned int __read_mostly msr_count_max;
> +
> +static int hvm_save_cpu_msrs(struct domain *d, hvm_domain_context_t *h)
> +{
> +    struct vcpu *v;
> +
> +    for_each_vcpu ( d, v )
> +    {
> +        struct hvm_msr *ctxt;
> +        unsigned int i;
> +
> +        if ( _hvm_init_entry(h, CPU_MSR_CODE, v->vcpu_id,
> +                             HVM_CPU_MSR_SIZE(msr_count_max)) )
> +            return 1;
> +        ctxt = (struct hvm_msr *)&h->data[h->cur];
> +        ctxt->count = 0;
> +
> +        if ( hvm_funcs.save_msr )
> +            hvm_funcs.save_msr(v, ctxt);
> +
> +        for ( i = 0; i < ctxt->count; ++i )
> +            ctxt->msr[i]._rsvd = 0;
> +
> +        if ( ctxt->count )
> +            h->cur += HVM_CPU_MSR_SIZE(ctxt->count);
> +        else
> +            h->cur -= sizeof(struct hvm_save_descriptor);

On the last iteration of the loop, this will leave a stale CPU_MSR_CODE
header in the area between the end of the hvm record and the maximum
possible size of the record, which then gets copied into the toolstack-
provided buffer.

Luckily, it does appear that xc_domain_save() does deal with this
correctly and only send the valid subset of the entire record.  I
presume we dont care about breaking any other toolstacks which might get
this wrong?

> +    }
> +
> +    return 0;
> +}
> +
> +static int hvm_load_cpu_msrs(struct domain *d, hvm_domain_context_t *h)
> +{
> +    unsigned int i, vcpuid = hvm_load_instance(h);
> +    struct vcpu *v;
> +    const struct hvm_save_descriptor *desc;
> +    struct hvm_msr *ctxt;
> +    int err = 0;
> +
> +    if ( vcpuid >= d->max_vcpus || (v = d->vcpu[vcpuid]) == NULL )
> +    {
> +        dprintk(XENLOG_G_ERR, "HVM restore: dom%d has no vcpu%u\n",
> +                d->domain_id, vcpuid);
> +        return -EINVAL;
> +    }
> +
> +    /* Customized checking for entry since our entry is of variable length */
> +    desc = (struct hvm_save_descriptor *)&h->data[h->cur];
> +    if ( sizeof (*desc) > h->size - h->cur)
> +    {
> +        printk(XENLOG_G_WARNING
> +               "HVM%d.%d restore: not enough data left to read MSR descriptor\n",
> +               d->domain_id, vcpuid);
> +        return -ENODATA;
> +    }
> +    if ( desc->length + sizeof (*desc) > h->size - h->cur)
> +    {
> +        printk(XENLOG_G_WARNING
> +               "HVM%d.%d restore: not enough data left to read %u MSR bytes\n",
> +               d->domain_id, vcpuid, desc->length);
> +        return -ENODATA;
> +    }
> +    if ( desc->length < HVM_CPU_MSR_SIZE(1) )
> +    {
> +        printk(XENLOG_G_WARNING
> +               "HVM%d.%d restore mismatch: MSR length %u < %zu\n",
> +               d->domain_id, vcpuid, desc->length, HVM_CPU_MSR_SIZE(1));
> +        return -EINVAL;
> +    }
> +
> +    h->cur += sizeof(*desc);
> +    ctxt = (struct hvm_msr *)&h->data[h->cur];
> +    h->cur += desc->length;
> +
> +    if ( desc->length != HVM_CPU_MSR_SIZE(ctxt->count) )
> +    {
> +        printk(XENLOG_G_WARNING
> +               "HVM%d.%d restore mismatch: MSR length %u != %zu\n",
> +               d->domain_id, vcpuid, desc->length,
> +               HVM_CPU_MSR_SIZE(ctxt->count));
> +        return -EOPNOTSUPP;
> +    }
> +
> +    for ( i = 0; i < ctxt->count; ++i )
> +        if ( ctxt->msr[i]._rsvd )
> +            return -EOPNOTSUPP;
> +    /* Checking finished */
> +
> +    if ( hvm_funcs.load_msr )
> +        err = hvm_funcs.load_msr(v, ctxt);
> +
> +    for ( i = 0; !err && i < ctxt->count; ++i )
> +    {
> +        switch ( ctxt->msr[i].index )
> +        {
> +        default:
> +            if ( !ctxt->msr[i]._rsvd )
> +                err = -ENXIO;
> +            break;
> +        }
> +    }
> +
> +    return err;
> +}
> +
> +/* We need variable length data chunks for XSAVE area and MSRs, hence
> + * a custom declaration rather than HVM_REGISTER_SAVE_RESTORE.
>   */
> -static int __init __hvm_register_CPU_XSAVE_save_and_restore(void)
> +static int __init hvm_register_CPU_save_and_restore(void)
>  {
>      hvm_register_savevm(CPU_XSAVE_CODE,
>                          "CPU_XSAVE",
> @@ -1139,9 +1246,22 @@ static int __init __hvm_register_CPU_XSA
>                          HVM_CPU_XSAVE_SIZE(xfeature_mask) +
>                              sizeof(struct hvm_save_descriptor),
>                          HVMSR_PER_VCPU);
> +
> +    if ( hvm_funcs.init_msr )
> +        msr_count_max += hvm_funcs.init_msr();

Why += as opposed to direct assignment?  Changing this value anywhere
other than here looks as if it will lead to problems.

> +
> +    if ( msr_count_max )
> +        hvm_register_savevm(CPU_MSR_CODE,
> +                            "CPU_MSR",
> +                            hvm_save_cpu_msrs,
> +                            hvm_load_cpu_msrs,
> +                            HVM_CPU_MSR_SIZE(msr_count_max) +
> +                                sizeof(struct hvm_save_descriptor),
> +                            HVMSR_PER_VCPU);
> +
>      return 0;
>  }
> -__initcall(__hvm_register_CPU_XSAVE_save_and_restore);
> +__initcall(hvm_register_CPU_save_and_restore);
>  
>  int hvm_vcpu_initialise(struct vcpu *v)
>  {
> --- a/xen/include/asm-x86/hvm/hvm.h
> +++ b/xen/include/asm-x86/hvm/hvm.h
> @@ -109,6 +109,10 @@ struct hvm_function_table {
>      void (*save_cpu_ctxt)(struct vcpu *v, struct hvm_hw_cpu *ctxt);
>      int (*load_cpu_ctxt)(struct vcpu *v, struct hvm_hw_cpu *ctxt);
>  
> +    unsigned int (*init_msr)(void);

Possibly a comment to explain that this must return the number of MSRs
we expect to insert into an hvm msr record?

> +    void (*save_msr)(struct vcpu *, struct hvm_msr *);
> +    int (*load_msr)(struct vcpu *, struct hvm_msr *);
> +
>      /* Examine specifics of the guest state. */
>      unsigned int (*get_interrupt_shadow)(struct vcpu *v);
>      void (*set_interrupt_shadow)(struct vcpu *v, unsigned int intr_shadow);
> --- a/xen/include/public/arch-x86/hvm/save.h
> +++ b/xen/include/public/arch-x86/hvm/save.h
> @@ -592,9 +592,21 @@ struct hvm_tsc_adjust {
>  
>  DECLARE_HVM_SAVE_TYPE(TSC_ADJUST, 19, struct hvm_tsc_adjust);
>  
> +
> +struct hvm_msr {
> +    uint32_t count;
> +    struct hvm_one_msr {
> +        uint32_t index;
> +        uint32_t _rsvd;
> +        uint64_t val;
> +    } msr[1 /* variable size */];

Coverity is going to complain about using this with more than 1 record,
but I can't think of a better way of doing this without introducing a
VLA to the public header files.

As far as I can tell, the underlying implementation is safe to index off
the end of msr[].

~Andrew

> +};
> +
> +#define CPU_MSR_CODE  20
> +
>  /* 
>   * Largest type-code in use
>   */
> -#define HVM_SAVE_CODE_MAX 19
> +#define HVM_SAVE_CODE_MAX 20
>  
>  #endif /* __XEN_PUBLIC_HVM_SAVE_X86_H__ */
>
>

  reply	other threads:[~2013-12-13 17:44 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-12-03 14:50 [PATCH v5 4/7] X86: generic MSRs save/restore Liu, Jinsong
2013-12-04 14:18 ` Jan Beulich
2013-12-13  7:50   ` Liu, Jinsong
2013-12-13  9:44     ` Jan Beulich
2013-12-13  7:57   ` Liu, Jinsong
2013-12-13  9:47     ` Jan Beulich
2013-12-13 12:04       ` Andrew Cooper
2013-12-13 12:26         ` Jan Beulich
2013-12-13 14:01     ` [PATCH v2] x86: " Jan Beulich
2013-12-13 17:44       ` Andrew Cooper [this message]
2013-12-16  3:12         ` Liu, Jinsong
2013-12-16  8:03         ` Jan Beulich
2013-12-16  3:01       ` Liu, Jinsong
2013-12-16  8:04         ` Jan Beulich
2013-12-16  8:39           ` Liu, Jinsong
2013-12-16  8:52             ` Jan Beulich
2013-12-16  9:13               ` Liu, Jinsong
2013-12-16  9:41                 ` Jan Beulich
2013-12-16  9:53                   ` Liu, Jinsong
2013-12-16 10:01                     ` Jan Beulich
2013-12-16 10:05                       ` Liu, Jinsong
2013-12-16 11:11                         ` Jan Beulich
2013-12-16 13:23                           ` Liu, Jinsong
2013-12-16 13:34                             ` Jan Beulich
2013-12-16 13:57                               ` Liu, Jinsong
2013-12-16 14:01                                 ` Liu, Jinsong
2013-12-18 12:20       ` Liu, Jinsong
2013-12-13 14:02     ` [PATCH v2] x86: MSR_IA32_BNDCFGS save/restore Jan Beulich
2013-12-13 17:57       ` Andrew Cooper
2013-12-16  3:22         ` Liu, Jinsong
2013-12-16  8:06         ` Jan Beulich
2013-12-16  3:23       ` Liu, Jinsong

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=52AB477D.3060206@citrix.com \
    --to=andrew.cooper3@citrix.com \
    --cc=Ian.Campbell@citrix.com \
    --cc=JBeulich@suse.com \
    --cc=haoxudong.hao@gmail.com \
    --cc=jinsong.liu@intel.com \
    --cc=keir@xen.org \
    --cc=xen-devel@lists.xen.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.