From mboxrd@z Thu Jan 1 00:00:00 1970 From: "Jan Beulich" Subject: [PATCH v2] x86: generic MSRs save/restore Date: Fri, 13 Dec 2013 14:01:57 +0000 Message-ID: <52AB2165020000780010D068@nat28.tlf.novell.com> References: <529F47D2020000780010A0E4@nat28.tlf.novell.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=__PartC7F43345.3__=" Return-path: In-Reply-To: List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org To: Jinsong Liu Cc: Andrew Cooper , "xen-devel@lists.xen.org" , "keir@xen.org" , "Ian.Campbell@citrix.com" , "haoxudong.hao@gmail.com" List-Id: xen-devel@lists.xenproject.org This is a MIME message. If you are reading this text, you may want to consider changing to a mail reader or gateway that understands how to properly handle MIME multipart messages. --=__PartC7F43345.3__= Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: quoted-printable Content-Disposition: inline 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 --- 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; } =20 -/* 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 =3D (struct hvm_msr *)&h->data[h->cur]; + ctxt->count =3D 0; + + if ( hvm_funcs.save_msr ) + hvm_funcs.save_msr(v, ctxt); + + for ( i =3D 0; i < ctxt->count; ++i ) + ctxt->msr[i]._rsvd =3D 0; + + if ( ctxt->count ) + h->cur +=3D HVM_CPU_MSR_SIZE(ctxt->count); + else + h->cur -=3D sizeof(struct hvm_save_descriptor); + } + + return 0; +} + +static int hvm_load_cpu_msrs(struct domain *d, hvm_domain_context_t *h) +{ + unsigned int i, vcpuid =3D hvm_load_instance(h); + struct vcpu *v; + const struct hvm_save_descriptor *desc; + struct hvm_msr *ctxt; + int err =3D 0; + + if ( vcpuid >=3D d->max_vcpus || (v =3D d->vcpu[vcpuid]) =3D=3D 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 =3D (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 +=3D sizeof(*desc); + ctxt =3D (struct hvm_msr *)&h->data[h->cur]; + h->cur +=3D desc->length; + + if ( desc->length !=3D HVM_CPU_MSR_SIZE(ctxt->count) ) + { + printk(XENLOG_G_WARNING + "HVM%d.%d restore mismatch: MSR length %u !=3D %zu\n", + d->domain_id, vcpuid, desc->length, + HVM_CPU_MSR_SIZE(ctxt->count)); + return -EOPNOTSUPP; + } + + for ( i =3D 0; i < ctxt->count; ++i ) + if ( ctxt->msr[i]._rsvd ) + return -EOPNOTSUPP; + /* Checking finished */ + + if ( hvm_funcs.load_msr ) + err =3D hvm_funcs.load_msr(v, ctxt); + + for ( i =3D 0; !err && i < ctxt->count; ++i ) + { + switch ( ctxt->msr[i].index ) + { + default: + if ( !ctxt->msr[i]._rsvd ) + err =3D -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 +=3D hvm_funcs.init_msr(); + + 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); =20 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); =20 + unsigned int (*init_msr)(void); + 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 { =20 DECLARE_HVM_SAVE_TYPE(TSC_ADJUST, 19, struct hvm_tsc_adjust); =20 + +struct hvm_msr { + uint32_t count; + struct hvm_one_msr { + uint32_t index; + uint32_t _rsvd; + uint64_t val; + } msr[1 /* variable size */]; +}; + +#define CPU_MSR_CODE 20 + /*=20 * Largest type-code in use */ -#define HVM_SAVE_CODE_MAX 19 +#define HVM_SAVE_CODE_MAX 20 =20 #endif /* __XEN_PUBLIC_HVM_SAVE_X86_H__ */ --=__PartC7F43345.3__= Content-Type: text/plain; name="x86-MSR-sr.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="x86-MSR-sr.patch" x86: generic MSRs save/restore=0A=0AThis patch introduces a generic MSRs = save/restore mechanism, so that=0Ain the future new MSRs save/restore = could be added w/ smaller change=0Athan the full blown addition of a new = save/restore type.=0A=0ASigned-off-by: Jan Beulich =0A= =0A--- a/xen/arch/x86/hvm/hvm.c=0A+++ b/xen/arch/x86/hvm/hvm.c=0A@@ = -1127,10 +1127,117 @@ static int hvm_load_cpu_xsave_states(str=0A = return 0;=0A }=0A =0A-/* We need variable length data chunk for xsave = area, hence customized=0A- * declaration other than HVM_REGISTER_SAVE_RESTO= RE.=0A+#define HVM_CPU_MSR_SIZE(cnt) offsetof(struct hvm_msr, msr[cnt])=0A+= static unsigned int __read_mostly msr_count_max;=0A+=0A+static int = hvm_save_cpu_msrs(struct domain *d, hvm_domain_context_t *h)=0A+{=0A+ = struct vcpu *v;=0A+=0A+ for_each_vcpu ( d, v )=0A+ {=0A+ = struct hvm_msr *ctxt;=0A+ unsigned int i;=0A+=0A+ if ( = _hvm_init_entry(h, CPU_MSR_CODE, v->vcpu_id,=0A+ = HVM_CPU_MSR_SIZE(msr_count_max)) )=0A+ return 1;=0A+ = ctxt =3D (struct hvm_msr *)&h->data[h->cur];=0A+ ctxt->count =3D = 0;=0A+=0A+ if ( hvm_funcs.save_msr )=0A+ hvm_funcs.save_m= sr(v, ctxt);=0A+=0A+ for ( i =3D 0; i < ctxt->count; ++i )=0A+ = ctxt->msr[i]._rsvd =3D 0;=0A+=0A+ if ( ctxt->count )=0A+ = h->cur +=3D HVM_CPU_MSR_SIZE(ctxt->count);=0A+ else=0A+ = h->cur -=3D sizeof(struct hvm_save_descriptor);=0A+ }=0A+=0A+ = return 0;=0A+}=0A+=0A+static int hvm_load_cpu_msrs(struct domain *d, = hvm_domain_context_t *h)=0A+{=0A+ unsigned int i, vcpuid =3D hvm_load_in= stance(h);=0A+ struct vcpu *v;=0A+ const struct hvm_save_descriptor = *desc;=0A+ struct hvm_msr *ctxt;=0A+ int err =3D 0;=0A+=0A+ if ( = vcpuid >=3D d->max_vcpus || (v =3D d->vcpu[vcpuid]) =3D=3D NULL )=0A+ = {=0A+ dprintk(XENLOG_G_ERR, "HVM restore: dom%d has no vcpu%u\n",=0A= + d->domain_id, vcpuid);=0A+ return -EINVAL;=0A+ = }=0A+=0A+ /* Customized checking for entry since our entry is of = variable length */=0A+ desc =3D (struct hvm_save_descriptor *)&h->data[h= ->cur];=0A+ if ( sizeof (*desc) > h->size - h->cur)=0A+ {=0A+ = printk(XENLOG_G_WARNING=0A+ "HVM%d.%d restore: not enough = data left to read MSR descriptor\n",=0A+ d->domain_id, = vcpuid);=0A+ return -ENODATA;=0A+ }=0A+ if ( desc->length + = sizeof (*desc) > h->size - h->cur)=0A+ {=0A+ printk(XENLOG_G_WARN= ING=0A+ "HVM%d.%d restore: not enough data left to read %u = MSR bytes\n",=0A+ d->domain_id, vcpuid, desc->length);=0A+ = return -ENODATA;=0A+ }=0A+ if ( desc->length < HVM_CPU_MSR_SIZE(= 1) )=0A+ {=0A+ printk(XENLOG_G_WARNING=0A+ = "HVM%d.%d restore mismatch: MSR length %u < %zu\n",=0A+ = d->domain_id, vcpuid, desc->length, HVM_CPU_MSR_SIZE(1));=0A+ = return -EINVAL;=0A+ }=0A+=0A+ h->cur +=3D sizeof(*desc);=0A+ ctxt = =3D (struct hvm_msr *)&h->data[h->cur];=0A+ h->cur +=3D desc->length;=0A= +=0A+ if ( desc->length !=3D HVM_CPU_MSR_SIZE(ctxt->count) )=0A+ = {=0A+ printk(XENLOG_G_WARNING=0A+ "HVM%d.%d restore = mismatch: MSR length %u !=3D %zu\n",=0A+ d->domain_id, = vcpuid, desc->length,=0A+ HVM_CPU_MSR_SIZE(ctxt->count));=0A+= return -EOPNOTSUPP;=0A+ }=0A+=0A+ for ( i =3D 0; i < = ctxt->count; ++i )=0A+ if ( ctxt->msr[i]._rsvd )=0A+ = return -EOPNOTSUPP;=0A+ /* Checking finished */=0A+=0A+ if ( = hvm_funcs.load_msr )=0A+ err =3D hvm_funcs.load_msr(v, ctxt);=0A+=0A= + for ( i =3D 0; !err && i < ctxt->count; ++i )=0A+ {=0A+ = switch ( ctxt->msr[i].index )=0A+ {=0A+ default:=0A+ = if ( !ctxt->msr[i]._rsvd )=0A+ err =3D -ENXIO;=0A+ = break;=0A+ }=0A+ }=0A+=0A+ return err;=0A+}=0A+=0A+/* We = need variable length data chunks for XSAVE area and MSRs, hence=0A+ * a = custom declaration rather than HVM_REGISTER_SAVE_RESTORE.=0A */=0A-static = int __init __hvm_register_CPU_XSAVE_save_and_restore(void)=0A+static int = __init hvm_register_CPU_save_and_restore(void)=0A {=0A hvm_register_sav= evm(CPU_XSAVE_CODE,=0A "CPU_XSAVE",=0A@@ -1139,9 = +1246,22 @@ static int __init __hvm_register_CPU_XSA=0A = HVM_CPU_XSAVE_SIZE(xfeature_mask) +=0A = sizeof(struct hvm_save_descriptor),=0A HVMSR_PER_VC= PU);=0A+=0A+ if ( hvm_funcs.init_msr )=0A+ msr_count_max +=3D = hvm_funcs.init_msr();=0A+=0A+ if ( msr_count_max )=0A+ hvm_regist= er_savevm(CPU_MSR_CODE,=0A+ "CPU_MSR",=0A+ = hvm_save_cpu_msrs,=0A+ = hvm_load_cpu_msrs,=0A+ HVM_CPU_MSR_SIZE(msr_coun= t_max) +=0A+ sizeof(struct hvm_save_descript= or),=0A+ HVMSR_PER_VCPU);=0A+=0A return = 0;=0A }=0A-__initcall(__hvm_register_CPU_XSAVE_save_and_restore);=0A+__init= call(hvm_register_CPU_save_and_restore);=0A =0A int hvm_vcpu_initialise(str= uct vcpu *v)=0A {=0A--- a/xen/include/asm-x86/hvm/hvm.h=0A+++ b/xen/include= /asm-x86/hvm/hvm.h=0A@@ -109,6 +109,10 @@ struct hvm_function_table {=0A = void (*save_cpu_ctxt)(struct vcpu *v, struct hvm_hw_cpu *ctxt);=0A = int (*load_cpu_ctxt)(struct vcpu *v, struct hvm_hw_cpu *ctxt);=0A =0A+ = unsigned int (*init_msr)(void);=0A+ void (*save_msr)(struct vcpu *, = struct hvm_msr *);=0A+ int (*load_msr)(struct vcpu *, struct hvm_msr = *);=0A+=0A /* Examine specifics of the guest state. */=0A unsigned = int (*get_interrupt_shadow)(struct vcpu *v);=0A void (*set_interrupt_sh= adow)(struct vcpu *v, unsigned int intr_shadow);=0A--- a/xen/include/public= /arch-x86/hvm/save.h=0A+++ b/xen/include/public/arch-x86/hvm/save.h=0A@@ = -592,9 +592,21 @@ struct hvm_tsc_adjust {=0A =0A DECLARE_HVM_SAVE_TYPE(TSC_= ADJUST, 19, struct hvm_tsc_adjust);=0A =0A+=0A+struct hvm_msr {=0A+ = uint32_t count;=0A+ struct hvm_one_msr {=0A+ uint32_t index;=0A+ = uint32_t _rsvd;=0A+ uint64_t val;=0A+ } msr[1 /* variable = size */];=0A+};=0A+=0A+#define CPU_MSR_CODE 20=0A+=0A /* =0A * Largest = type-code in use=0A */=0A-#define HVM_SAVE_CODE_MAX 19=0A+#define = HVM_SAVE_CODE_MAX 20=0A =0A #endif /* __XEN_PUBLIC_HVM_SAVE_X86_H__ */=0A --=__PartC7F43345.3__= Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ Xen-devel mailing list Xen-devel@lists.xen.org http://lists.xen.org/xen-devel --=__PartC7F43345.3__=--