From mboxrd@z Thu Jan 1 00:00:00 1970 From: "Jan Beulich" Subject: [PATCH 2/2] x86: package up context switch hook pointers Date: Tue, 14 Feb 2017 03:29:50 -0700 Message-ID: <58A2EA2E0200007800139961@prv-mh.provo.novell.com> References: <58A2E8B70200007800139946@prv-mh.provo.novell.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=__Part4079B70E.3__=" Return-path: Received: from mail6.bemta5.messagelabs.com ([195.245.231.135]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1cdaMw-0004yy-0O for xen-devel@lists.xenproject.org; Tue, 14 Feb 2017 10:29:58 +0000 In-Reply-To: <58A2E8B70200007800139946@prv-mh.provo.novell.com> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xen.org Sender: "Xen-devel" To: xen-devel Cc: Boris Ostrovsky , Andrew Cooper , Kevin Tian , Jun Nakajima , Suravee Suthikulpanit 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. --=__Part4079B70E.3__= Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: quoted-printable Content-Disposition: inline They're all solely dependent on guest type, so we don't need to repeat all the same four pointers in every vCPU control structure. Instead use static const structures, and store pointers to them in the domain control structure. Since touching it anyway, take the opportunity and move schedule_tail() into the only C file needing it. Signed-off-by: Jan Beulich --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -426,16 +426,8 @@ int vcpu_initialise(struct vcpu *v) /* PV guests by default have a 100Hz ticker. */ v->periodic_period =3D MILLISECS(10); } - - v->arch.schedule_tail =3D continue_nonidle_domain; - v->arch.ctxt_switch_from =3D paravirt_ctxt_switch_from; - v->arch.ctxt_switch_to =3D paravirt_ctxt_switch_to; - - if ( is_idle_domain(d) ) - { - v->arch.schedule_tail =3D continue_idle_domain; - v->arch.cr3 =3D __pa(idle_pg_table); - } + else + v->arch.cr3 =3D __pa(idle_pg_table); =20 v->arch.pv_vcpu.ctrlreg[4] =3D real_cr4_to_pv_guest_cr4(mmu_cr4_featur= es); =20 @@ -642,8 +634,23 @@ int arch_domain_create(struct domain *d, goto fail; } else + { + static const struct arch_csw pv_csw =3D { + .from =3D paravirt_ctxt_switch_from, + .to =3D paravirt_ctxt_switch_to, + .tail =3D continue_nonidle_domain, + }; + static const struct arch_csw idle_csw =3D { + .from =3D paravirt_ctxt_switch_from, + .to =3D paravirt_ctxt_switch_to, + .tail =3D continue_idle_domain, + }; + + d->arch.ctxt_switch =3D is_idle_domain(d) ? &idle_csw : &pv_csw; + /* 64-bit PV guest by default. */ d->arch.is_32bit_pv =3D d->arch.has_32bit_shinfo =3D 0; + } =20 /* initialize default tsc behavior in case tools don't */ tsc_set_info(d, TSC_MODE_DEFAULT, 0UL, 0, 0); @@ -1997,7 +2004,7 @@ static void __context_switch(void) { memcpy(&p->arch.user_regs, stack_regs, CTXT_SWITCH_STACK_BYTES); vcpu_save_fpu(p); - p->arch.ctxt_switch_from(p); + pd->arch.ctxt_switch->from(p); } =20 /* @@ -2023,7 +2030,7 @@ static void __context_switch(void) set_msr_xss(n->arch.hvm_vcpu.msr_xss); } vcpu_restore_fpu_eager(n); - n->arch.ctxt_switch_to(n); + nd->arch.ctxt_switch->to(n); } =20 psr_ctxt_switch_to(nd); @@ -2066,6 +2073,15 @@ static void __context_switch(void) per_cpu(curr_vcpu, cpu) =3D n; } =20 +/* + * Schedule tail *should* be a terminal function pointer, but leave a = bugframe + * around just incase it returns, to save going back into the context + * switching code and leaving a far more subtle crash to diagnose. + */ +#define schedule_tail(vcpu) do { \ + (((vcpu)->domain->arch.ctxt_switch->tail)(vcpu)); \ + BUG(); \ + } while (0) =20 void context_switch(struct vcpu *prev, struct vcpu *next) { @@ -2100,8 +2116,8 @@ void context_switch(struct vcpu *prev, s =20 if ( (per_cpu(curr_vcpu, cpu) =3D=3D next) ) { - if ( next->arch.ctxt_switch_same ) - next->arch.ctxt_switch_same(next); + if ( nextd->arch.ctxt_switch->same ) + nextd->arch.ctxt_switch->same(next); local_irq_enable(); } else if ( is_idle_domain(nextd) && cpu_online(cpu) ) --- a/xen/arch/x86/hvm/svm/svm.c +++ b/xen/arch/x86/hvm/svm/svm.c @@ -1144,6 +1144,14 @@ void svm_host_osvw_init() =20 static int svm_domain_initialise(struct domain *d) { + static const struct arch_csw csw =3D { + .from =3D svm_ctxt_switch_from, + .to =3D svm_ctxt_switch_to, + .tail =3D svm_do_resume, + }; + + d->arch.ctxt_switch =3D &csw; + return 0; } =20 @@ -1155,10 +1163,6 @@ static int svm_vcpu_initialise(struct vc { int rc; =20 - v->arch.schedule_tail =3D svm_do_resume; - v->arch.ctxt_switch_from =3D svm_ctxt_switch_from; - v->arch.ctxt_switch_to =3D svm_ctxt_switch_to; - v->arch.hvm_svm.launch_core =3D -1; =20 if ( (rc =3D svm_create_vmcb(v)) !=3D 0 ) --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -268,8 +268,16 @@ void vmx_pi_hooks_deassign(struct domain =20 static int vmx_domain_initialise(struct domain *d) { + static const struct arch_csw csw =3D { + .from =3D vmx_ctxt_switch_from, + .to =3D vmx_ctxt_switch_to, + .same =3D vmx_vmcs_reload, + .tail =3D vmx_do_resume, + }; int rc; =20 + d->arch.ctxt_switch =3D &csw; + if ( !has_vlapic(d) ) return 0; =20 @@ -295,11 +303,6 @@ static int vmx_vcpu_initialise(struct vc =20 INIT_LIST_HEAD(&v->arch.hvm_vmx.pi_blocking.list); =20 - v->arch.schedule_tail =3D vmx_do_resume; - v->arch.ctxt_switch_from =3D vmx_ctxt_switch_from; - v->arch.ctxt_switch_to =3D vmx_ctxt_switch_to; - v->arch.ctxt_switch_same =3D vmx_vmcs_reload; - if ( (rc =3D vmx_create_vmcs(v)) !=3D 0 ) { dprintk(XENLOG_WARNING, --- a/xen/include/asm-x86/current.h +++ b/xen/include/asm-x86/current.h @@ -103,16 +103,6 @@ unsigned long get_stack_dump_bottom (uns }) =20 /* - * Schedule tail *should* be a terminal function pointer, but leave a = bugframe - * around just incase it returns, to save going back into the context - * switching code and leaving a far more subtle crash to diagnose. - */ -#define schedule_tail(vcpu) do { \ - (((vcpu)->arch.schedule_tail)(vcpu)); \ - BUG(); \ - } while (0) - -/* * Which VCPU's state is currently running on each CPU? * This is not necesasrily the same as 'current' as a CPU may be * executing a lazy state switch. --- a/xen/include/asm-x86/domain.h +++ b/xen/include/asm-x86/domain.h @@ -314,6 +314,13 @@ struct arch_domain } relmem; struct page_list_head relmem_list; =20 + const struct arch_csw { + void (*from)(struct vcpu *); + void (*to)(struct vcpu *); + void (*same)(struct vcpu *); + void (*tail)(struct vcpu *); + } *ctxt_switch; + /* nestedhvm: translate l2 guest physical to host physical */ struct p2m_domain *nested_p2m[MAX_NESTEDP2M]; mm_lock_t nested_p2m_lock; @@ -510,12 +517,6 @@ struct arch_vcpu =20 unsigned long flags; /* TF_ */ =20 - void (*schedule_tail) (struct vcpu *); - - void (*ctxt_switch_from) (struct vcpu *); - void (*ctxt_switch_to) (struct vcpu *); - void (*ctxt_switch_same) (struct vcpu *); - struct vpmu_struct vpmu; =20 /* Virtual Machine Extensions */ --=__Part4079B70E.3__= Content-Type: text/plain; name="x86-csw-func-package.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="x86-csw-func-package.patch" x86: package up context switch hook pointers=0A=0AThey're all solely = dependent on guest type, so we don't need to repeat=0Aall the same four = pointers in every vCPU control structure. Instead use=0Astatic const = structures, and store pointers to them in the domain=0Acontrol structure.= =0A=0ASince touching it anyway, take the opportunity and move schedule_tail= ()=0Ainto the only C file needing it.=0A=0ASigned-off-by: Jan Beulich = =0A=0A--- a/xen/arch/x86/domain.c=0A+++ b/xen/arch/x86/d= omain.c=0A@@ -426,16 +426,8 @@ int vcpu_initialise(struct vcpu *v)=0A = /* PV guests by default have a 100Hz ticker. */=0A v->periodic_p= eriod =3D MILLISECS(10);=0A }=0A-=0A- v->arch.schedule_tail =3D = continue_nonidle_domain;=0A- v->arch.ctxt_switch_from =3D paravirt_ctxt_= switch_from;=0A- v->arch.ctxt_switch_to =3D paravirt_ctxt_switch_to;= =0A-=0A- if ( is_idle_domain(d) )=0A- {=0A- v->arch.schedule_t= ail =3D continue_idle_domain;=0A- v->arch.cr3 =3D = __pa(idle_pg_table);=0A- }=0A+ else=0A+ v->arch.cr3 =3D = __pa(idle_pg_table);=0A =0A v->arch.pv_vcpu.ctrlreg[4] =3D real_cr4_to_= pv_guest_cr4(mmu_cr4_features);=0A =0A@@ -642,8 +634,23 @@ int arch_domain_= create(struct domain *d,=0A goto fail;=0A }=0A = else=0A+ {=0A+ static const struct arch_csw pv_csw =3D {=0A+ = .from =3D paravirt_ctxt_switch_from,=0A+ .to =3D = paravirt_ctxt_switch_to,=0A+ .tail =3D continue_nonidle_domain,= =0A+ };=0A+ static const struct arch_csw idle_csw =3D {=0A+ = .from =3D paravirt_ctxt_switch_from,=0A+ .to =3D = paravirt_ctxt_switch_to,=0A+ .tail =3D continue_idle_domain,=0A+= };=0A+=0A+ d->arch.ctxt_switch =3D is_idle_domain(d) ? = &idle_csw : &pv_csw;=0A+=0A /* 64-bit PV guest by default. */=0A = d->arch.is_32bit_pv =3D d->arch.has_32bit_shinfo =3D 0;=0A+ }=0A = =0A /* initialize default tsc behavior in case tools don't */=0A = tsc_set_info(d, TSC_MODE_DEFAULT, 0UL, 0, 0);=0A@@ -1997,7 +2004,7 @@ = static void __context_switch(void)=0A {=0A memcpy(&p->arch.user= _regs, stack_regs, CTXT_SWITCH_STACK_BYTES);=0A vcpu_save_fpu(p);= =0A- p->arch.ctxt_switch_from(p);=0A+ pd->arch.ctxt_switch->f= rom(p);=0A }=0A =0A /*=0A@@ -2023,7 +2030,7 @@ static void = __context_switch(void)=0A set_msr_xss(n->arch.hvm_vcpu.msr_= xss);=0A }=0A vcpu_restore_fpu_eager(n);=0A- = n->arch.ctxt_switch_to(n);=0A+ nd->arch.ctxt_switch->to(n);=0A = }=0A =0A psr_ctxt_switch_to(nd);=0A@@ -2066,6 +2073,15 @@ static void = __context_switch(void)=0A per_cpu(curr_vcpu, cpu) =3D n;=0A }=0A = =0A+/*=0A+ * Schedule tail *should* be a terminal function pointer, but = leave a bugframe=0A+ * around just incase it returns, to save going back = into the context=0A+ * switching code and leaving a far more subtle crash = to diagnose.=0A+ */=0A+#define schedule_tail(vcpu) do { = \=0A+ (((vcpu)->domain->arch.ctxt_switch->tail)(vcpu)); \=0A+ = BUG(); \=0A+ } while = (0)=0A =0A void context_switch(struct vcpu *prev, struct vcpu *next)=0A = {=0A@@ -2100,8 +2116,8 @@ void context_switch(struct vcpu *prev, s=0A =0A = if ( (per_cpu(curr_vcpu, cpu) =3D=3D next) )=0A {=0A- if ( = next->arch.ctxt_switch_same )=0A- next->arch.ctxt_switch_same(ne= xt);=0A+ if ( nextd->arch.ctxt_switch->same )=0A+ = nextd->arch.ctxt_switch->same(next);=0A local_irq_enable();=0A = }=0A else if ( is_idle_domain(nextd) && cpu_online(cpu) )=0A--- = a/xen/arch/x86/hvm/svm/svm.c=0A+++ b/xen/arch/x86/hvm/svm/svm.c=0A@@ = -1144,6 +1144,14 @@ void svm_host_osvw_init()=0A =0A static int svm_domain_= initialise(struct domain *d)=0A {=0A+ static const struct arch_csw csw = =3D {=0A+ .from =3D svm_ctxt_switch_from,=0A+ .to =3D = svm_ctxt_switch_to,=0A+ .tail =3D svm_do_resume,=0A+ };=0A+=0A+ = d->arch.ctxt_switch =3D &csw;=0A+=0A return 0;=0A }=0A =0A@@ = -1155,10 +1163,6 @@ static int svm_vcpu_initialise(struct vc=0A {=0A = int rc;=0A =0A- v->arch.schedule_tail =3D svm_do_resume;=0A- = v->arch.ctxt_switch_from =3D svm_ctxt_switch_from;=0A- v->arch.ctxt_swit= ch_to =3D svm_ctxt_switch_to;=0A-=0A v->arch.hvm_svm.launch_core =3D = -1;=0A =0A if ( (rc =3D svm_create_vmcb(v)) !=3D 0 )=0A--- a/xen/arch/x= 86/hvm/vmx/vmx.c=0A+++ b/xen/arch/x86/hvm/vmx/vmx.c=0A@@ -268,8 +268,16 @@ = void vmx_pi_hooks_deassign(struct domain=0A =0A static int vmx_domain_initi= alise(struct domain *d)=0A {=0A+ static const struct arch_csw csw =3D = {=0A+ .from =3D vmx_ctxt_switch_from,=0A+ .to =3D = vmx_ctxt_switch_to,=0A+ .same =3D vmx_vmcs_reload,=0A+ .tail = =3D vmx_do_resume,=0A+ };=0A int rc;=0A =0A+ d->arch.ctxt_switch = =3D &csw;=0A+=0A if ( !has_vlapic(d) )=0A return 0;=0A =0A@@ = -295,11 +303,6 @@ static int vmx_vcpu_initialise(struct vc=0A =0A = INIT_LIST_HEAD(&v->arch.hvm_vmx.pi_blocking.list);=0A =0A- v->arch.sched= ule_tail =3D vmx_do_resume;=0A- v->arch.ctxt_switch_from =3D = vmx_ctxt_switch_from;=0A- v->arch.ctxt_switch_to =3D vmx_ctxt_switch_t= o;=0A- v->arch.ctxt_switch_same =3D vmx_vmcs_reload;=0A-=0A if ( = (rc =3D vmx_create_vmcs(v)) !=3D 0 )=0A {=0A dprintk(XENLOG_WAR= NING,=0A--- a/xen/include/asm-x86/current.h=0A+++ b/xen/include/asm-x86/cur= rent.h=0A@@ -103,16 +103,6 @@ unsigned long get_stack_dump_bottom (uns=0A = })=0A =0A /*=0A- * Schedule tail *should* be a terminal function = pointer, but leave a bugframe=0A- * around just incase it returns, to save = going back into the context=0A- * switching code and leaving a far more = subtle crash to diagnose.=0A- */=0A-#define schedule_tail(vcpu) do { = \=0A- (((vcpu)->arch.schedule_tail)(vcpu)); \=0A- = BUG(); \=0A- } while (0)=0A-=0A-/*=0A = * Which VCPU's state is currently running on each CPU?=0A * This is not = necesasrily the same as 'current' as a CPU may be=0A * executing a lazy = state switch.=0A--- a/xen/include/asm-x86/domain.h=0A+++ b/xen/include/asm-= x86/domain.h=0A@@ -314,6 +314,13 @@ struct arch_domain=0A } relmem;=0A = struct page_list_head relmem_list;=0A =0A+ const struct arch_csw = {=0A+ void (*from)(struct vcpu *);=0A+ void (*to)(struct = vcpu *);=0A+ void (*same)(struct vcpu *);=0A+ void (*tail)(st= ruct vcpu *);=0A+ } *ctxt_switch;=0A+=0A /* nestedhvm: translate l2 = guest physical to host physical */=0A struct p2m_domain *nested_p2m[MAX= _NESTEDP2M];=0A mm_lock_t nested_p2m_lock;=0A@@ -510,12 +517,6 @@ = struct arch_vcpu=0A =0A unsigned long flags; /* TF_ */=0A =0A- = void (*schedule_tail) (struct vcpu *);=0A-=0A- void (*ctxt_switch_from) = (struct vcpu *);=0A- void (*ctxt_switch_to) (struct vcpu *);=0A- = void (*ctxt_switch_same) (struct vcpu *);=0A-=0A struct vpmu_struct = vpmu;=0A =0A /* Virtual Machine Extensions */=0A --=__Part4079B70E.3__= Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: base64 Content-Disposition: inline X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KWGVuLWRldmVs IG1haWxpbmcgbGlzdApYZW4tZGV2ZWxAbGlzdHMueGVuLm9yZwpodHRwczovL2xpc3RzLnhlbi5v cmcveGVuLWRldmVsCg== --=__Part4079B70E.3__=--