ia64/xen-unstable

changeset 10925:47a5dfd1bcd6

[IA64] fix memory leak when domVTI is created

privregs clean up.
memory leak occures when VT-i domain is created.
When domain is created, xend sets max vcpu before domain setup.
So alloc_vcpu_struct() think the domain is normal domU, not domVTI.
And next xend set the domain as domVTI. so the memory is allocated for
domU won't be freed.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
author awilliam@xenbuild.aw
date Thu Aug 03 11:05:59 2006 -0600 (2006-08-03)
parents 4151d83d0db9
children 147144f9ec51
files xen/arch/ia64/asm-offsets.c xen/arch/ia64/xen/dom0_ops.c xen/arch/ia64/xen/domain.c xen/include/asm-ia64/domain.h
line diff
     1.1 --- a/xen/arch/ia64/asm-offsets.c	Thu Aug 03 10:44:23 2006 -0600
     1.2 +++ b/xen/arch/ia64/asm-offsets.c	Thu Aug 03 11:05:59 2006 -0600
     1.3 @@ -32,6 +32,7 @@ void foo(void)
     1.4  	DEFINE(IA64_CPU_SIZE, sizeof (struct cpuinfo_ia64));
     1.5  	DEFINE(UNW_FRAME_INFO_SIZE, sizeof (struct unw_frame_info));
     1.6  	DEFINE(SHARED_INFO_SIZE, sizeof (struct shared_info));
     1.7 +	DEFINE(MAPPED_REGS_T_SIZE, sizeof (mapped_regs_t));
     1.8  
     1.9  	BLANK();
    1.10  	DEFINE(IA64_MCA_CPU_INIT_STACK_OFFSET, offsetof (struct ia64_mca_cpu, init_stack));
     2.1 --- a/xen/arch/ia64/xen/dom0_ops.c	Thu Aug 03 10:44:23 2006 -0600
     2.2 +++ b/xen/arch/ia64/xen/dom0_ops.c	Thu Aug 03 11:05:59 2006 -0600
     2.3 @@ -122,6 +122,15 @@ long arch_do_dom0_op(dom0_op_t *op, XEN_
     2.4                      ret = -EINVAL;
     2.5                      break;
     2.6                  }
     2.7 +                if (!d->arch.is_vti) {
     2.8 +                    struct vcpu *v;
     2.9 +                    for_each_vcpu(d, v) {
    2.10 +                        BUG_ON(v->arch.privregs == NULL);
    2.11 +                        free_domheap_pages(virt_to_page(v->arch.privregs),
    2.12 +                                      get_order_from_shift(XMAPPEDREGS_SHIFT));
    2.13 +                        relinquish_vcpu_resources(v);
    2.14 +                    }
    2.15 +                }
    2.16                  d->arch.is_vti = 1;
    2.17                  vmx_setup_platform(d);
    2.18              }
     3.1 --- a/xen/arch/ia64/xen/domain.c	Thu Aug 03 10:44:23 2006 -0600
     3.2 +++ b/xen/arch/ia64/xen/domain.c	Thu Aug 03 11:05:59 2006 -0600
     3.3 @@ -236,6 +236,14 @@ void startup_cpu_idle_loop(void)
     3.4  	continue_cpu_idle_loop();
     3.5  }
     3.6  
     3.7 +/* compile time test for get_order(sizeof(mapped_regs_t)) !=
     3.8 + * get_order_from_shift(XMAPPEDREGS_SHIFT))
     3.9 + */
    3.10 +#if !(((1 << (XMAPPEDREGS_SHIFT - 1)) < MAPPED_REGS_T_SIZE) && \
    3.11 +      (MAPPED_REGS_T_SIZE < (1 << (XMAPPEDREGS_SHIFT + 1))))
    3.12 +# error "XMAPPEDREGS_SHIFT doesn't match sizeof(mapped_regs_t)."
    3.13 +#endif
    3.14 +
    3.15  struct vcpu *alloc_vcpu_struct(struct domain *d, unsigned int vcpu_id)
    3.16  {
    3.17  	struct vcpu *v;
    3.18 @@ -261,13 +269,17 @@ struct vcpu *alloc_vcpu_struct(struct do
    3.19  
    3.20  	if (!is_idle_domain(d)) {
    3.21  	    if (!d->arch.is_vti) {
    3.22 -		/* Create privregs page only if not VTi.  */
    3.23 -		v->arch.privregs = 
    3.24 -		    alloc_xenheap_pages(get_order(sizeof(mapped_regs_t)));
    3.25 +		int order;
    3.26 +		int i;
    3.27 +
    3.28 +		/* Create privregs page only if not VTi. */
    3.29 +		order = get_order_from_shift(XMAPPEDREGS_SHIFT);
    3.30 +		v->arch.privregs = alloc_xenheap_pages(order);
    3.31  		BUG_ON(v->arch.privregs == NULL);
    3.32 -		memset(v->arch.privregs, 0, PAGE_SIZE);
    3.33 -		share_xen_page_with_guest(virt_to_page(v->arch.privregs),
    3.34 -		                          d, XENSHARE_writable);
    3.35 +		memset(v->arch.privregs, 0, 1 << XMAPPEDREGS_SHIFT);
    3.36 +		for (i = 0; i < (1 << order); i++)
    3.37 +		    share_xen_page_with_guest(virt_to_page(v->arch.privregs) +
    3.38 +		                              i, d, XENSHARE_writable);
    3.39  	    }
    3.40  
    3.41  	    v->arch.metaphysical_rr0 = d->arch.metaphysical_rr0;
    3.42 @@ -295,15 +307,21 @@ struct vcpu *alloc_vcpu_struct(struct do
    3.43  	return v;
    3.44  }
    3.45  
    3.46 +void relinquish_vcpu_resources(struct vcpu *v)
    3.47 +{
    3.48 +    if (v->arch.privregs != NULL) {
    3.49 +        free_xenheap_pages(v->arch.privregs,
    3.50 +                           get_order_from_shift(XMAPPEDREGS_SHIFT));
    3.51 +        v->arch.privregs = NULL;
    3.52 +    }
    3.53 +}
    3.54 +
    3.55  void free_vcpu_struct(struct vcpu *v)
    3.56  {
    3.57  	if (VMX_DOMAIN(v))
    3.58  		vmx_relinquish_vcpu_resources(v);
    3.59 -	else {
    3.60 -		if (v->arch.privregs != NULL)
    3.61 -			free_xenheap_pages(v->arch.privregs,
    3.62 -			              get_order_from_shift(XMAPPEDREGS_SHIFT));
    3.63 -	}
    3.64 +	else
    3.65 +		relinquish_vcpu_resources(v);
    3.66  
    3.67  	free_xenheap_pages(v, KERNEL_STACK_SIZE_ORDER);
    3.68  }
     4.1 --- a/xen/include/asm-ia64/domain.h	Thu Aug 03 10:44:23 2006 -0600
     4.2 +++ b/xen/include/asm-ia64/domain.h	Thu Aug 03 11:05:59 2006 -0600
     4.3 @@ -37,6 +37,8 @@ p2m_entry_retry(struct p2m_entry* entry)
     4.4  }
     4.5  
     4.6  extern void domain_relinquish_resources(struct domain *);
     4.7 +struct vcpu;
     4.8 +extern void relinquish_vcpu_resources(struct vcpu *v);
     4.9  
    4.10  /* given a current domain metaphysical address, return the physical address */
    4.11  extern unsigned long translate_domain_mpaddr(unsigned long mpaddr,