From mboxrd@z Thu Jan 1 00:00:00 1970 From: "Jan Beulich" Subject: [PATCH 5/6] x86: introduce alloc_vcpu_guest_context() Date: Tue, 05 Apr 2011 09:22:26 +0100 Message-ID: <4D9AED620200007800039F3A@vpn.id2.novell.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=__Part3C10E652.0__=" Return-path: List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xensource.com Errors-To: xen-devel-bounces@lists.xensource.com To: "xen-devel@lists.xensource.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. --=__Part3C10E652.0__= Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: quoted-printable Content-Disposition: inline This is necessary because on x86-64 struct vcpu_guest_context is larger than PAGE_SIZE, and hence not suitable for a general purpose runtime allocation. On x86-32, FIX_PAE_HIGHMEM_* fixmap entries are being re-used, whiule on x86-64 new per-CPU fixmap entries get introduced. The implication of using per-CPU fixmaps is that these allocations have to happen from non-preemptable hypercall context (which they all do). Signed-off-by: Jan Beulich --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -221,6 +222,53 @@ void free_vcpu_struct(struct vcpu *v) free_xenheap_page(v); } =20 +static DEFINE_PER_CPU(struct page_info *[ + PFN_UP(sizeof(struct vcpu_guest_context))], vgc_pages); + +struct vcpu_guest_context *alloc_vcpu_guest_context(void) +{ + unsigned int i, cpu =3D smp_processor_id(); + enum fixed_addresses idx =3D FIX_VGC_BEGIN - + cpu * PFN_UP(sizeof(struct vcpu_guest_context)); + +#ifdef __i386__ + BUILD_BUG_ON(sizeof(struct vcpu_guest_context) > PAGE_SIZE); +#endif + BUG_ON(per_cpu(vgc_pages[0], cpu) !=3D NULL); + + for ( i =3D 0; i < PFN_UP(sizeof(struct vcpu_guest_context)); ++i ) + { + struct page_info *pg =3D alloc_domheap_page(NULL, 0); + + if ( unlikely(pg =3D=3D NULL) ) + { + free_vcpu_guest_context(NULL); + return NULL; + } + __set_fixmap(idx - i, page_to_mfn(pg), __PAGE_HYPERVISOR); + per_cpu(vgc_pages[i], cpu) =3D pg; + } + return (void *)fix_to_virt(idx); +} + +void free_vcpu_guest_context(struct vcpu_guest_context *vgc) +{ + unsigned int i, cpu =3D smp_processor_id(); + enum fixed_addresses idx =3D FIX_VGC_BEGIN - + cpu * PFN_UP(sizeof(struct vcpu_guest_context)); + + BUG_ON(vgc && vgc !=3D (void *)fix_to_virt(idx)); + + for ( i =3D 0; i < PFN_UP(sizeof(struct vcpu_guest_context)); ++i ) + { + if ( !per_cpu(vgc_pages[i], cpu) ) + continue; + __set_fixmap(idx - i, 0, 0); + free_domheap_page(per_cpu(vgc_pages[i], cpu)); + per_cpu(vgc_pages[i], cpu) =3D NULL; + } +} + #ifdef __x86_64__ =20 static int setup_compat_l4(struct vcpu *v) --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -832,12 +832,12 @@ long do_vcpu_op(int cmd, int vcpuid, XEN if ( v->vcpu_info =3D=3D &dummy_vcpu_info ) return -EINVAL; =20 - if ( (ctxt =3D xmalloc(struct vcpu_guest_context)) =3D=3D NULL ) + if ( (ctxt =3D alloc_vcpu_guest_context()) =3D=3D NULL ) return -ENOMEM; =20 if ( copy_from_guest(ctxt, arg, 1) ) { - xfree(ctxt); + free_vcpu_guest_context(ctxt); return -EFAULT; } =20 @@ -847,7 +847,7 @@ long do_vcpu_op(int cmd, int vcpuid, XEN rc =3D boot_vcpu(d, vcpuid, ctxt); domain_unlock(d); =20 - xfree(ctxt); + free_vcpu_guest_context(ctxt); break; =20 case VCPUOP_up: --- a/xen/common/domctl.c +++ b/xen/common/domctl.c @@ -295,7 +295,7 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domc < sizeof(struct compat_vcpu_guest_context)); #endif ret =3D -ENOMEM; - if ( (c.nat =3D xmalloc(struct vcpu_guest_context)) =3D=3D NULL ) + if ( (c.nat =3D alloc_vcpu_guest_context()) =3D=3D NULL ) goto svc_out; =20 #ifdef CONFIG_COMPAT @@ -318,7 +318,7 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domc } =20 svc_out: - xfree(c.nat); + free_vcpu_guest_context(c.nat); rcu_unlock_domain(d); } break; --- a/xen/include/asm-ia64/domain.h +++ b/xen/include/asm-ia64/domain.h @@ -25,6 +25,9 @@ struct vcpu; extern void relinquish_vcpu_resources(struct vcpu *v); extern int vcpu_late_initialise(struct vcpu *v); =20 +#define alloc_vcpu_guest_context() xmalloc(struct vcpu_guest_context) +#define free_vcpu_guest_context(vgc) xfree(vgc) + /* given a current domain metaphysical address, return the physical = address */ extern unsigned long translate_domain_mpaddr(unsigned long mpaddr, struct p2m_entry* entry); --- a/xen/include/asm-x86/fixmap.h +++ b/xen/include/asm-x86/fixmap.h @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -34,6 +35,12 @@ enum fixed_addresses { #ifdef __i386__ FIX_PAE_HIGHMEM_0, FIX_PAE_HIGHMEM_END =3D FIX_PAE_HIGHMEM_0 + NR_CPUS-1, +#define FIX_VGC_END FIX_PAE_HIGHMEM_0 +#define FIX_VGC_BEGIN FIX_PAE_HIGHMEM_END +#else + FIX_VGC_END, + FIX_VGC_BEGIN =3D FIX_VGC_END + + PFN_UP(sizeof(struct vcpu_guest_context)) * NR_CPUS - 1, #endif FIX_APIC_BASE, FIX_IO_APIC_BASE_0, --- a/xen/include/xen/domain.h +++ b/xen/include/xen/domain.h @@ -32,6 +32,12 @@ void free_domain_struct(struct domain *d struct vcpu *alloc_vcpu_struct(void); void free_vcpu_struct(struct vcpu *v); =20 +/* Allocate/free a vcpu_guest_context structure. */ +#ifndef alloc_vcpu_guest_context +struct vcpu_guest_context *alloc_vcpu_guest_context(void); +void free_vcpu_guest_context(struct vcpu_guest_context *); +#endif + /* * Initialise/destroy arch-specific details of a VCPU. * - vcpu_initialise() is called after the basic generic fields of the --=__Part3C10E652.0__= Content-Type: text/plain; name="x86-alloc-vcpu-guest-context.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="x86-alloc-vcpu-guest-context.patch" This is necessary because on x86-64 struct vcpu_guest_context is larger=0At= han PAGE_SIZE, and hence not suitable for a general purpose runtime=0Aalloc= ation. On x86-32, FIX_PAE_HIGHMEM_* fixmap entries are being=0Are-used, = whiule on x86-64 new per-CPU fixmap entries get introduced.=0AThe = implication of using per-CPU fixmaps is that these allocations have=0Ato = happen from non-preemptable hypercall context (which they all do).=0A=0ASig= ned-off-by: Jan Beulich =0A=0A--- a/xen/arch/x86/domai= n.c=0A+++ b/xen/arch/x86/domain.c=0A@@ -45,6 +45,7 @@=0A #include = =0A #include =0A #include =0A+#in= clude =0A #include =0A #include =0A #include =0A@@ -221,6 +222,53 @@ void free_vcpu_st= ruct(struct vcpu *v)=0A free_xenheap_page(v);=0A }=0A =0A+static = DEFINE_PER_CPU(struct page_info *[=0A+ PFN_UP(sizeof(struct vcpu_guest_c= ontext))], vgc_pages);=0A+=0A+struct vcpu_guest_context *alloc_vcpu_guest_c= ontext(void)=0A+{=0A+ unsigned int i, cpu =3D smp_processor_id();=0A+ = enum fixed_addresses idx =3D FIX_VGC_BEGIN -=0A+ cpu * PFN_UP(sizeo= f(struct vcpu_guest_context));=0A+=0A+#ifdef __i386__=0A+ BUILD_BUG_ON(s= izeof(struct vcpu_guest_context) > PAGE_SIZE);=0A+#endif=0A+ BUG_ON(per_= cpu(vgc_pages[0], cpu) !=3D NULL);=0A+=0A+ for ( i =3D 0; i < PFN_UP(siz= eof(struct vcpu_guest_context)); ++i )=0A+ {=0A+ struct = page_info *pg =3D alloc_domheap_page(NULL, 0);=0A+=0A+ if ( = unlikely(pg =3D=3D NULL) )=0A+ {=0A+ free_vcpu_guest_cont= ext(NULL);=0A+ return NULL;=0A+ }=0A+ __set_fixmap= (idx - i, page_to_mfn(pg), __PAGE_HYPERVISOR);=0A+ per_cpu(vgc_pages= [i], cpu) =3D pg;=0A+ }=0A+ return (void *)fix_to_virt(idx);=0A+}=0A+= =0A+void free_vcpu_guest_context(struct vcpu_guest_context *vgc)=0A+{=0A+ = unsigned int i, cpu =3D smp_processor_id();=0A+ enum fixed_addresses = idx =3D FIX_VGC_BEGIN -=0A+ cpu * PFN_UP(sizeof(struct vcpu_guest_co= ntext));=0A+=0A+ BUG_ON(vgc && vgc !=3D (void *)fix_to_virt(idx));=0A+= =0A+ for ( i =3D 0; i < PFN_UP(sizeof(struct vcpu_guest_context)); ++i = )=0A+ {=0A+ if ( !per_cpu(vgc_pages[i], cpu) )=0A+ = continue;=0A+ __set_fixmap(idx - i, 0, 0);=0A+ free_domheap_p= age(per_cpu(vgc_pages[i], cpu));=0A+ per_cpu(vgc_pages[i], cpu) =3D = NULL;=0A+ }=0A+}=0A+=0A #ifdef __x86_64__=0A =0A static int setup_compat= _l4(struct vcpu *v)=0A--- a/xen/common/domain.c=0A+++ b/xen/common/domain.c= =0A@@ -832,12 +832,12 @@ long do_vcpu_op(int cmd, int vcpuid, XEN=0A = if ( v->vcpu_info =3D=3D &dummy_vcpu_info )=0A return = -EINVAL;=0A =0A- if ( (ctxt =3D xmalloc(struct vcpu_guest_context)) = =3D=3D NULL )=0A+ if ( (ctxt =3D alloc_vcpu_guest_context()) =3D=3D = NULL )=0A return -ENOMEM;=0A =0A if ( copy_from_guest(c= txt, arg, 1) )=0A {=0A- xfree(ctxt);=0A+ = free_vcpu_guest_context(ctxt);=0A return -EFAULT;=0A = }=0A =0A@@ -847,7 +847,7 @@ long do_vcpu_op(int cmd, int vcpuid, XEN=0A = rc =3D boot_vcpu(d, vcpuid, ctxt);=0A domain_unlock(d);=0A= =0A- xfree(ctxt);=0A+ free_vcpu_guest_context(ctxt);=0A = break;=0A =0A case VCPUOP_up:=0A--- a/xen/common/domctl.c=0A+++ = b/xen/common/domctl.c=0A@@ -295,7 +295,7 @@ long do_domctl(XEN_GUEST_HANDLE= (xen_domc=0A < sizeof(struct compat_vcpu_guest_context= ));=0A #endif=0A ret =3D -ENOMEM;=0A- if ( (c.nat =3D = xmalloc(struct vcpu_guest_context)) =3D=3D NULL )=0A+ if ( (c.nat = =3D alloc_vcpu_guest_context()) =3D=3D NULL )=0A goto = svc_out;=0A =0A #ifdef CONFIG_COMPAT=0A@@ -318,7 +318,7 @@ long do_domctl(X= EN_GUEST_HANDLE(xen_domc=0A }=0A =0A svc_out:=0A- = xfree(c.nat);=0A+ free_vcpu_guest_context(c.nat);=0A = rcu_unlock_domain(d);=0A }=0A break;=0A--- a/xen/include/asm-ia64/d= omain.h=0A+++ b/xen/include/asm-ia64/domain.h=0A@@ -25,6 +25,9 @@ struct = vcpu;=0A extern void relinquish_vcpu_resources(struct vcpu *v);=0A extern = int vcpu_late_initialise(struct vcpu *v);=0A =0A+#define alloc_vcpu_guest_c= ontext() xmalloc(struct vcpu_guest_context)=0A+#define free_vcpu_guest_cont= ext(vgc) xfree(vgc)=0A+=0A /* given a current domain metaphysical address, = return the physical address */=0A extern unsigned long translate_domain_mpa= ddr(unsigned long mpaddr,=0A = struct p2m_entry* entry);=0A--- a/xen/include/asm-x86/fixmap.h=0A+++ = b/xen/include/asm-x86/fixmap.h=0A@@ -16,6 +16,7 @@=0A #include =0A #include =0A #include =0A+#include = =0A #include =0A #include =0A = #include =0A@@ -34,6 +35,12 @@ enum fixed_addresses {=0A = #ifdef __i386__=0A FIX_PAE_HIGHMEM_0,=0A FIX_PAE_HIGHMEM_END =3D = FIX_PAE_HIGHMEM_0 + NR_CPUS-1,=0A+#define FIX_VGC_END FIX_PAE_HIGHMEM_0=0A+= #define FIX_VGC_BEGIN FIX_PAE_HIGHMEM_END=0A+#else=0A+ FIX_VGC_END,=0A+ = FIX_VGC_BEGIN =3D FIX_VGC_END=0A+ + PFN_UP(sizeof(struct vcpu_guest= _context)) * NR_CPUS - 1,=0A #endif=0A FIX_APIC_BASE,=0A FIX_IO_API= C_BASE_0,=0A--- a/xen/include/xen/domain.h=0A+++ b/xen/include/xen/domain.h= =0A@@ -32,6 +32,12 @@ void free_domain_struct(struct domain *d=0A struct = vcpu *alloc_vcpu_struct(void);=0A void free_vcpu_struct(struct vcpu = *v);=0A =0A+/* Allocate/free a vcpu_guest_context structure. */=0A+#ifndef = alloc_vcpu_guest_context=0A+struct vcpu_guest_context *alloc_vcpu_guest_con= text(void);=0A+void free_vcpu_guest_context(struct vcpu_guest_context = *);=0A+#endif=0A+=0A /*=0A * Initialise/destroy arch-specific details of = a VCPU.=0A * - vcpu_initialise() is called after the basic generic = fields of the=0A --=__Part3C10E652.0__= 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.xensource.com http://lists.xensource.com/xen-devel --=__Part3C10E652.0__=--