direct-io.hg

changeset 13482:7d8670a30445

[IA64] Change vCPU initialization to avoid domVTi privregs memory leak

1) This patch moved some processing from vcpu_initialise() and
added a new function vcpu_late_initialise().
It executes the following initializations for VCPU of
dom0/domU.
- Allocate the VHPT
- Allocate the privregs area and assign these pages into
guest pseudo physical address space.
- Set the tlbflush_timestamp.

It is executed in the following sequence.

dom0:
start_kernel()
->domain_create()
->alloc_vcpu(VCPU0)
->alloc_vcpu_struct(VCPU0)
->vcpu_initialise(VCPU0)
->vcpu_late_initialise(VCPU0)

->construct_dom0
->alloc_vcpu(othe VCPUs)
->alloc_vcpu_struct(other VCPUs)
->vcpu_initialise(other VCPUs)

ia64_hypercall(FW_HYPERCALL_IPI)
->fw_hypercall_ipi(XEN_SAL_BOOT_RENDEZ_VEC)
->arch_set_info_guest(other VCPUs)
->vcpu_late_initialise(other VCPUs)

domU:
do_domctl(XEN_DOMCTL_createdomain)
->domain_create()

do_domctl(XEN_DOMCTL_max_vcpus)
->alloc_vcpu(all VCPUs)
->alloc_vcpu_struct(all VCPUs)
->vcpu_initialise(all VCPUs)

do_domctl(XEN_DOMCTL_setvcpucontext)
->set_info_guest(VCPU0)
->arch_set_info_guest(VCPU0)
->vcpu_late_initialise(VCPU0)

ia64_hypercall(FW_HYPERCALL_IPI)
->fw_hypercall_ipi(XEN_SAL_BOOT_RENDEZ_VEC)
->arch_set_info_guest(other VCPUs)
->vcpu_late_initialise(other VCPUs)


2) This patch modified the domain_set_shared_info_va().
Currently, initialization of arch.privregs->interrupt_mask_addr
of all VCPUs is executed in domain_set_shared_info_va().
However, allocation of privregs area is late by modified of 1).
Therefore, this patch modified initialization of
arch.privregs->interrupt_mask_addr to the following sequence.

dom0 and domU:
ia64_hypercall(FW_HYPERCALL_SET_SHARED_INFO_VA)
->domain_set_shared_info_va()
Initialize interrupt_mask_addr of VCPU0

ia64_hypercall(FW_HYPERCALL_IPI)
->fw_hypercall_ipi(XEN_SAL_BOOT_RENDEZ_VEC)
->arch_set_info_guest(other VCPUs)
->vcpu_late_initialise(other VCPUs)
Initialize interrupt_mask_addr of other VCPUs


Signed-off-by: Masaki Kanno <kanno.masaki@jp.fujitsu.com>
author awilliam@xenbuild2.aw
date Tue Jan 16 10:40:37 2007 -0700 (2007-01-16)
parents a2b2b2a011f1
children 24ce556e3049
files xen/arch/ia64/xen/dom0_ops.c xen/arch/ia64/xen/domain.c xen/arch/ia64/xen/xensetup.c xen/include/asm-ia64/domain.h
line diff
     1.1 --- a/xen/arch/ia64/xen/dom0_ops.c	Mon Jan 15 15:15:26 2007 -0700
     1.2 +++ b/xen/arch/ia64/xen/dom0_ops.c	Tue Jan 16 10:40:37 2007 -0700
     1.3 @@ -103,16 +103,6 @@ long arch_do_domctl(xen_domctl_t *op, XE
     1.4                      ret = -EINVAL;
     1.5                      break;
     1.6                  }
     1.7 -                if (!d->arch.is_vti) {
     1.8 -                    struct vcpu *v;
     1.9 -                    for_each_vcpu(d, v) {
    1.10 -                        BUG_ON(v->arch.privregs == NULL);
    1.11 -                        free_domheap_pages(virt_to_page(v->arch.privregs),
    1.12 -                                      get_order_from_shift(XMAPPEDREGS_SHIFT));
    1.13 -                        v->arch.privregs = NULL;
    1.14 -                        relinquish_vcpu_resources(v);
    1.15 -                    }
    1.16 -                }
    1.17                  d->arch.is_vti = 1;
    1.18                  vmx_setup_platform(d);
    1.19              }
     2.1 --- a/xen/arch/ia64/xen/domain.c	Mon Jan 15 15:15:26 2007 -0700
     2.2 +++ b/xen/arch/ia64/xen/domain.c	Tue Jan 16 10:40:37 2007 -0700
     2.3 @@ -305,24 +305,14 @@ void hlt_timer_fn(void *data)
     2.4  
     2.5  void relinquish_vcpu_resources(struct vcpu *v)
     2.6  {
     2.7 -    if (HAS_PERVCPU_VHPT(v->domain))
     2.8 -        pervcpu_vhpt_free(v);
     2.9 -    if (v->arch.privregs != NULL) {
    2.10 -        // this might be called by arch_do_domctl() with XEN_DOMCTL_arch_setup()
    2.11 -        // for domVTi.
    2.12 -        if (!(atomic_read(&v->domain->refcnt) & DOMAIN_DESTROYED)) {
    2.13 -            unsigned long i;
    2.14 -            for (i = 0; i < XMAPPEDREGS_SIZE; i += PAGE_SIZE)
    2.15 -                guest_physmap_remove_page(v->domain,
    2.16 -                    IA64_XMAPPEDREGS_PADDR(v->vcpu_id) + i,
    2.17 -                    virt_to_maddr(v->arch.privregs + i));
    2.18 -        }
    2.19 -
    2.20 -        free_xenheap_pages(v->arch.privregs,
    2.21 -                           get_order_from_shift(XMAPPEDREGS_SHIFT));
    2.22 -        v->arch.privregs = NULL;
    2.23 -    }
    2.24 -    kill_timer(&v->arch.hlt_timer);
    2.25 +	if (HAS_PERVCPU_VHPT(v->domain))
    2.26 +		pervcpu_vhpt_free(v);
    2.27 +	if (v->arch.privregs != NULL) {
    2.28 +		free_xenheap_pages(v->arch.privregs,
    2.29 +		                   get_order_from_shift(XMAPPEDREGS_SHIFT));
    2.30 +		v->arch.privregs = NULL;
    2.31 +	}
    2.32 +	kill_timer(&v->arch.hlt_timer);
    2.33  }
    2.34  
    2.35  struct vcpu *alloc_vcpu_struct(void)
    2.36 @@ -361,36 +351,8 @@ void free_vcpu_struct(struct vcpu *v)
    2.37  int vcpu_initialise(struct vcpu *v)
    2.38  {
    2.39  	struct domain *d = v->domain;
    2.40 -	int rc, order, i;
    2.41  
    2.42  	if (!is_idle_domain(d)) {
    2.43 -	    if (!d->arch.is_vti) {
    2.44 -		if (HAS_PERVCPU_VHPT(d))
    2.45 -			if ((rc = pervcpu_vhpt_alloc(v)) != 0)
    2.46 -				return rc;
    2.47 -
    2.48 -		/* Create privregs page only if not VTi. */
    2.49 -		order = get_order_from_shift(XMAPPEDREGS_SHIFT);
    2.50 -		v->arch.privregs = alloc_xenheap_pages(order);
    2.51 -		BUG_ON(v->arch.privregs == NULL);
    2.52 -		memset(v->arch.privregs, 0, 1 << XMAPPEDREGS_SHIFT);
    2.53 -		for (i = 0; i < (1 << order); i++)
    2.54 -		    share_xen_page_with_guest(virt_to_page(v->arch.privregs) +
    2.55 -		                              i, d, XENSHARE_writable);
    2.56 -		/*
    2.57 -		 * XXX IA64_XMAPPEDREGS_PADDR
    2.58 -		 * assign these pages into guest pseudo physical address
    2.59 -		 * space for dom0 to map this page by gmfn.
    2.60 -		 * this is necessary for domain save, restore and dump-core.
    2.61 -		 */
    2.62 -		for (i = 0; i < XMAPPEDREGS_SIZE; i += PAGE_SIZE)
    2.63 -		    assign_domain_page(d, IA64_XMAPPEDREGS_PADDR(v->vcpu_id) + i,
    2.64 -                                      virt_to_maddr(v->arch.privregs + i));
    2.65 -
    2.66 -		tlbflush_update_time(&v->arch.tlbflush_timestamp,
    2.67 -		                     tlbflush_current_time());
    2.68 -	    }
    2.69 -
    2.70  	    v->arch.metaphysical_rr0 = d->arch.metaphysical_rr0;
    2.71  	    v->arch.metaphysical_rr4 = d->arch.metaphysical_rr4;
    2.72  	    v->arch.metaphysical_saved_rr0 = d->arch.metaphysical_rr0;
    2.73 @@ -420,6 +382,41 @@ int vcpu_initialise(struct vcpu *v)
    2.74  	return 0;
    2.75  }
    2.76  
    2.77 +int vcpu_late_initialise(struct vcpu *v)
    2.78 +{
    2.79 +	struct domain *d = v->domain;
    2.80 +	int rc, order, i;
    2.81 +
    2.82 +	if (HAS_PERVCPU_VHPT(d)) {
    2.83 +		rc = pervcpu_vhpt_alloc(v);
    2.84 +		if (rc != 0)
    2.85 +			return rc;
    2.86 +	}
    2.87 +
    2.88 +	/* Create privregs page. */
    2.89 +	order = get_order_from_shift(XMAPPEDREGS_SHIFT);
    2.90 +	v->arch.privregs = alloc_xenheap_pages(order);
    2.91 +	BUG_ON(v->arch.privregs == NULL);
    2.92 +	memset(v->arch.privregs, 0, 1 << XMAPPEDREGS_SHIFT);
    2.93 +	for (i = 0; i < (1 << order); i++)
    2.94 +		share_xen_page_with_guest(virt_to_page(v->arch.privregs) + i,
    2.95 +		                          d, XENSHARE_writable);
    2.96 +	/*
    2.97 +	 * XXX IA64_XMAPPEDREGS_PADDR
    2.98 +	 * assign these pages into guest pseudo physical address
    2.99 +	 * space for dom0 to map this page by gmfn.
   2.100 +	 * this is necessary for domain save, restore and dump-core.
   2.101 +	 */
   2.102 +	for (i = 0; i < XMAPPEDREGS_SIZE; i += PAGE_SIZE)
   2.103 +		assign_domain_page(d, IA64_XMAPPEDREGS_PADDR(v->vcpu_id) + i,
   2.104 +		                   virt_to_maddr(v->arch.privregs + i));
   2.105 +
   2.106 +	tlbflush_update_time(&v->arch.tlbflush_timestamp,
   2.107 +	                     tlbflush_current_time());
   2.108 +
   2.109 +	return 0;
   2.110 +}
   2.111 +
   2.112  void vcpu_destroy(struct vcpu *v)
   2.113  {
   2.114  	if (v->domain->arch.is_vti)
   2.115 @@ -553,6 +550,7 @@ int arch_set_info_guest(struct vcpu *v, 
   2.116  {
   2.117  	struct pt_regs *regs = vcpu_regs (v);
   2.118  	struct domain *d = v->domain;
   2.119 +	int rc;
   2.120  	
   2.121  	*regs = c.nat->user_regs;
   2.122   	
   2.123 @@ -582,16 +580,25 @@ int arch_set_info_guest(struct vcpu *v, 
   2.124  		v->arch.event_callback_ip = er->event_callback_ip;
   2.125  		v->arch.dcr = er->dcr;
   2.126  		v->arch.iva = er->iva;
   2.127 -  	}
   2.128 -	
   2.129 -  	if ( test_bit(_VCPUF_initialised, &v->vcpu_flags) )
   2.130 - 		return 0;
   2.131 - 	if (d->arch.is_vti)
   2.132 - 		vmx_final_setup_guest(v);
   2.133 -	
   2.134 - 	/* This overrides some registers.  */
   2.135 -  	vcpu_init_regs(v);
   2.136 -  
   2.137 +	}
   2.138 +
   2.139 +	if (test_bit(_VCPUF_initialised, &v->vcpu_flags))
   2.140 +		return 0;
   2.141 +
   2.142 +	if (d->arch.is_vti)
   2.143 +		vmx_final_setup_guest(v);
   2.144 +	else {
   2.145 +		rc = vcpu_late_initialise(v);
   2.146 +		if (rc != 0)
   2.147 +			return rc;
   2.148 +		VCPU(v, interrupt_mask_addr) = 
   2.149 +			(unsigned char *) d->arch.shared_info_va +
   2.150 +			INT_ENABLE_OFFSET(v);
   2.151 +	}
   2.152 +
   2.153 +	/* This overrides some registers. */
   2.154 +	vcpu_init_regs(v);
   2.155 +
   2.156  	/* Don't redo final setup */
   2.157  	set_bit(_VCPUF_initialised, &v->vcpu_flags);
   2.158  	return 0;
   2.159 @@ -683,7 +690,6 @@ domain_set_shared_info_va (unsigned long
   2.160  {
   2.161  	struct vcpu *v = current;
   2.162  	struct domain *d = v->domain;
   2.163 -	struct vcpu *v1;
   2.164  
   2.165  	/* Check virtual address:
   2.166  	   must belong to region 7,
   2.167 @@ -699,10 +705,8 @@ domain_set_shared_info_va (unsigned long
   2.168  	printk ("Domain set shared_info_va to 0x%016lx\n", va);
   2.169  	d->arch.shared_info_va = va;
   2.170  
   2.171 -	for_each_vcpu (d, v1) {
   2.172 -		VCPU(v1, interrupt_mask_addr) = 
   2.173 -			(unsigned char *)va + INT_ENABLE_OFFSET(v1);
   2.174 -	}
   2.175 +	VCPU(v, interrupt_mask_addr) = (unsigned char *)va +
   2.176 +	                               INT_ENABLE_OFFSET(v);
   2.177  
   2.178  	__ia64_per_cpu_var(current_psr_ic_addr) = (int *)(va + XSI_PSR_IC_OFS);
   2.179  
   2.180 @@ -1106,7 +1110,7 @@ int construct_dom0(struct domain *d,
   2.181  	printk ("Dom0 max_vcpus=%d\n", dom0_max_vcpus);
   2.182  	for ( i = 1; i < dom0_max_vcpus; i++ )
   2.183  	    if (alloc_vcpu(d, i, i) == NULL)
   2.184 -		printk ("Cannot allocate dom0 vcpu %d\n", i);
   2.185 +		panic("Cannot allocate dom0 vcpu %d\n", i);
   2.186  
   2.187  	/* Copy the OS image. */
   2.188  	loaddomainelfimage(d,image_start);
     3.1 --- a/xen/arch/ia64/xen/xensetup.c	Mon Jan 15 15:15:26 2007 -0700
     3.2 +++ b/xen/arch/ia64/xen/xensetup.c	Tue Jan 16 10:40:37 2007 -0700
     3.3 @@ -249,6 +249,7 @@ void start_kernel(void)
     3.4      unsigned long dom0_initrd_start, dom0_initrd_size;
     3.5      unsigned long md_end, relo_start, relo_end, relo_size = 0;
     3.6      struct domain *idle_domain;
     3.7 +    struct vcpu *dom0_vcpu0;
     3.8      efi_memory_desc_t *kern_md, *last_md, *md;
     3.9  #ifdef CONFIG_SMP
    3.10      int i;
    3.11 @@ -503,8 +504,11 @@ printk("num_online_cpus=%d, max_cpus=%d\
    3.12  
    3.13      /* Create initial domain 0. */
    3.14      dom0 = domain_create(0, 0);
    3.15 -    if ( (dom0 == NULL) || (alloc_vcpu(dom0, 0, 0) == NULL) )
    3.16 +    if (dom0 == NULL)
    3.17          panic("Error creating domain 0\n");
    3.18 +    dom0_vcpu0 = alloc_vcpu(dom0, 0, 0);
    3.19 +    if (dom0_vcpu0 == NULL || vcpu_late_initialise(dom0_vcpu0) != 0)
    3.20 +        panic("Cannot allocate dom0 vcpu 0\n");
    3.21  
    3.22      dom0->is_privileged = 1;
    3.23  
     4.1 --- a/xen/include/asm-ia64/domain.h	Mon Jan 15 15:15:26 2007 -0700
     4.2 +++ b/xen/include/asm-ia64/domain.h	Tue Jan 16 10:40:37 2007 -0700
     4.3 @@ -21,6 +21,7 @@ struct tlb_track;
     4.4  extern void domain_relinquish_resources(struct domain *);
     4.5  struct vcpu;
     4.6  extern void relinquish_vcpu_resources(struct vcpu *v);
     4.7 +extern int vcpu_late_initialise(struct vcpu *v);
     4.8  
     4.9  /* given a current domain metaphysical address, return the physical address */
    4.10  extern unsigned long translate_domain_mpaddr(unsigned long mpaddr,