[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] [IA64] Change vCPU initialization to avoid domVTi privregs memory leak



# HG changeset patch
# User awilliam@xxxxxxxxxxxx
# Date 1168969237 25200
# Node ID 7d8670a30445e50fad19a0885113376245727f65
# Parent  a2b2b2a011f1d406d49caba478020f3b2b173cb8
[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@xxxxxxxxxxxxxx>
---
 xen/arch/ia64/xen/dom0_ops.c  |   10 ---
 xen/arch/ia64/xen/domain.c    |  128 +++++++++++++++++++++---------------------
 xen/arch/ia64/xen/xensetup.c  |    6 +
 xen/include/asm-ia64/domain.h |    1 
 4 files changed, 72 insertions(+), 73 deletions(-)

diff -r a2b2b2a011f1 -r 7d8670a30445 xen/arch/ia64/xen/dom0_ops.c
--- a/xen/arch/ia64/xen/dom0_ops.c      Mon Jan 15 15:15:26 2007 -0700
+++ b/xen/arch/ia64/xen/dom0_ops.c      Tue Jan 16 10:40:37 2007 -0700
@@ -103,16 +103,6 @@ long arch_do_domctl(xen_domctl_t *op, XE
                     ret = -EINVAL;
                     break;
                 }
-                if (!d->arch.is_vti) {
-                    struct vcpu *v;
-                    for_each_vcpu(d, v) {
-                        BUG_ON(v->arch.privregs == NULL);
-                        free_domheap_pages(virt_to_page(v->arch.privregs),
-                                      get_order_from_shift(XMAPPEDREGS_SHIFT));
-                        v->arch.privregs = NULL;
-                        relinquish_vcpu_resources(v);
-                    }
-                }
                 d->arch.is_vti = 1;
                 vmx_setup_platform(d);
             }
diff -r a2b2b2a011f1 -r 7d8670a30445 xen/arch/ia64/xen/domain.c
--- a/xen/arch/ia64/xen/domain.c        Mon Jan 15 15:15:26 2007 -0700
+++ b/xen/arch/ia64/xen/domain.c        Tue Jan 16 10:40:37 2007 -0700
@@ -305,24 +305,14 @@ void hlt_timer_fn(void *data)
 
 void relinquish_vcpu_resources(struct vcpu *v)
 {
-    if (HAS_PERVCPU_VHPT(v->domain))
-        pervcpu_vhpt_free(v);
-    if (v->arch.privregs != NULL) {
-        // this might be called by arch_do_domctl() with 
XEN_DOMCTL_arch_setup()
-        // for domVTi.
-        if (!(atomic_read(&v->domain->refcnt) & DOMAIN_DESTROYED)) {
-            unsigned long i;
-            for (i = 0; i < XMAPPEDREGS_SIZE; i += PAGE_SIZE)
-                guest_physmap_remove_page(v->domain,
-                    IA64_XMAPPEDREGS_PADDR(v->vcpu_id) + i,
-                    virt_to_maddr(v->arch.privregs + i));
-        }
-
-        free_xenheap_pages(v->arch.privregs,
-                           get_order_from_shift(XMAPPEDREGS_SHIFT));
-        v->arch.privregs = NULL;
-    }
-    kill_timer(&v->arch.hlt_timer);
+       if (HAS_PERVCPU_VHPT(v->domain))
+               pervcpu_vhpt_free(v);
+       if (v->arch.privregs != NULL) {
+               free_xenheap_pages(v->arch.privregs,
+                                  get_order_from_shift(XMAPPEDREGS_SHIFT));
+               v->arch.privregs = NULL;
+       }
+       kill_timer(&v->arch.hlt_timer);
 }
 
 struct vcpu *alloc_vcpu_struct(void)
@@ -361,36 +351,8 @@ int vcpu_initialise(struct vcpu *v)
 int vcpu_initialise(struct vcpu *v)
 {
        struct domain *d = v->domain;
-       int rc, order, i;
 
        if (!is_idle_domain(d)) {
-           if (!d->arch.is_vti) {
-               if (HAS_PERVCPU_VHPT(d))
-                       if ((rc = pervcpu_vhpt_alloc(v)) != 0)
-                               return rc;
-
-               /* Create privregs page only if not VTi. */
-               order = get_order_from_shift(XMAPPEDREGS_SHIFT);
-               v->arch.privregs = alloc_xenheap_pages(order);
-               BUG_ON(v->arch.privregs == NULL);
-               memset(v->arch.privregs, 0, 1 << XMAPPEDREGS_SHIFT);
-               for (i = 0; i < (1 << order); i++)
-                   share_xen_page_with_guest(virt_to_page(v->arch.privregs) +
-                                             i, d, XENSHARE_writable);
-               /*
-                * XXX IA64_XMAPPEDREGS_PADDR
-                * assign these pages into guest pseudo physical address
-                * space for dom0 to map this page by gmfn.
-                * this is necessary for domain save, restore and dump-core.
-                */
-               for (i = 0; i < XMAPPEDREGS_SIZE; i += PAGE_SIZE)
-                   assign_domain_page(d, IA64_XMAPPEDREGS_PADDR(v->vcpu_id) + 
i,
-                                      virt_to_maddr(v->arch.privregs + i));
-
-               tlbflush_update_time(&v->arch.tlbflush_timestamp,
-                                    tlbflush_current_time());
-           }
-
            v->arch.metaphysical_rr0 = d->arch.metaphysical_rr0;
            v->arch.metaphysical_rr4 = d->arch.metaphysical_rr4;
            v->arch.metaphysical_saved_rr0 = d->arch.metaphysical_rr0;
@@ -416,6 +378,41 @@ int vcpu_initialise(struct vcpu *v)
        if (!VMX_DOMAIN(v))
                init_timer(&v->arch.hlt_timer, hlt_timer_fn, v,
                           first_cpu(cpu_online_map));
+
+       return 0;
+}
+
+int vcpu_late_initialise(struct vcpu *v)
+{
+       struct domain *d = v->domain;
+       int rc, order, i;
+
+       if (HAS_PERVCPU_VHPT(d)) {
+               rc = pervcpu_vhpt_alloc(v);
+               if (rc != 0)
+                       return rc;
+       }
+
+       /* Create privregs page. */
+       order = get_order_from_shift(XMAPPEDREGS_SHIFT);
+       v->arch.privregs = alloc_xenheap_pages(order);
+       BUG_ON(v->arch.privregs == NULL);
+       memset(v->arch.privregs, 0, 1 << XMAPPEDREGS_SHIFT);
+       for (i = 0; i < (1 << order); i++)
+               share_xen_page_with_guest(virt_to_page(v->arch.privregs) + i,
+                                         d, XENSHARE_writable);
+       /*
+        * XXX IA64_XMAPPEDREGS_PADDR
+        * assign these pages into guest pseudo physical address
+        * space for dom0 to map this page by gmfn.
+        * this is necessary for domain save, restore and dump-core.
+        */
+       for (i = 0; i < XMAPPEDREGS_SIZE; i += PAGE_SIZE)
+               assign_domain_page(d, IA64_XMAPPEDREGS_PADDR(v->vcpu_id) + i,
+                                  virt_to_maddr(v->arch.privregs + i));
+
+       tlbflush_update_time(&v->arch.tlbflush_timestamp,
+                            tlbflush_current_time());
 
        return 0;
 }
@@ -553,6 +550,7 @@ int arch_set_info_guest(struct vcpu *v, 
 {
        struct pt_regs *regs = vcpu_regs (v);
        struct domain *d = v->domain;
+       int rc;
        
        *regs = c.nat->user_regs;
        
@@ -582,16 +580,25 @@ int arch_set_info_guest(struct vcpu *v, 
                v->arch.event_callback_ip = er->event_callback_ip;
                v->arch.dcr = er->dcr;
                v->arch.iva = er->iva;
-       }
-       
-       if ( test_bit(_VCPUF_initialised, &v->vcpu_flags) )
-               return 0;
-       if (d->arch.is_vti)
-               vmx_final_setup_guest(v);
-       
-       /* This overrides some registers.  */
-       vcpu_init_regs(v);
-  
+       }
+
+       if (test_bit(_VCPUF_initialised, &v->vcpu_flags))
+               return 0;
+
+       if (d->arch.is_vti)
+               vmx_final_setup_guest(v);
+       else {
+               rc = vcpu_late_initialise(v);
+               if (rc != 0)
+                       return rc;
+               VCPU(v, interrupt_mask_addr) = 
+                       (unsigned char *) d->arch.shared_info_va +
+                       INT_ENABLE_OFFSET(v);
+       }
+
+       /* This overrides some registers. */
+       vcpu_init_regs(v);
+
        /* Don't redo final setup */
        set_bit(_VCPUF_initialised, &v->vcpu_flags);
        return 0;
@@ -683,7 +690,6 @@ domain_set_shared_info_va (unsigned long
 {
        struct vcpu *v = current;
        struct domain *d = v->domain;
-       struct vcpu *v1;
 
        /* Check virtual address:
           must belong to region 7,
@@ -699,10 +705,8 @@ domain_set_shared_info_va (unsigned long
        printk ("Domain set shared_info_va to 0x%016lx\n", va);
        d->arch.shared_info_va = va;
 
-       for_each_vcpu (d, v1) {
-               VCPU(v1, interrupt_mask_addr) = 
-                       (unsigned char *)va + INT_ENABLE_OFFSET(v1);
-       }
+       VCPU(v, interrupt_mask_addr) = (unsigned char *)va +
+                                      INT_ENABLE_OFFSET(v);
 
        __ia64_per_cpu_var(current_psr_ic_addr) = (int *)(va + XSI_PSR_IC_OFS);
 
@@ -1106,7 +1110,7 @@ int construct_dom0(struct domain *d,
        printk ("Dom0 max_vcpus=%d\n", dom0_max_vcpus);
        for ( i = 1; i < dom0_max_vcpus; i++ )
            if (alloc_vcpu(d, i, i) == NULL)
-               printk ("Cannot allocate dom0 vcpu %d\n", i);
+               panic("Cannot allocate dom0 vcpu %d\n", i);
 
        /* Copy the OS image. */
        loaddomainelfimage(d,image_start);
diff -r a2b2b2a011f1 -r 7d8670a30445 xen/arch/ia64/xen/xensetup.c
--- a/xen/arch/ia64/xen/xensetup.c      Mon Jan 15 15:15:26 2007 -0700
+++ b/xen/arch/ia64/xen/xensetup.c      Tue Jan 16 10:40:37 2007 -0700
@@ -249,6 +249,7 @@ void start_kernel(void)
     unsigned long dom0_initrd_start, dom0_initrd_size;
     unsigned long md_end, relo_start, relo_end, relo_size = 0;
     struct domain *idle_domain;
+    struct vcpu *dom0_vcpu0;
     efi_memory_desc_t *kern_md, *last_md, *md;
 #ifdef CONFIG_SMP
     int i;
@@ -503,8 +504,11 @@ printk("num_online_cpus=%d, max_cpus=%d\
 
     /* Create initial domain 0. */
     dom0 = domain_create(0, 0);
-    if ( (dom0 == NULL) || (alloc_vcpu(dom0, 0, 0) == NULL) )
+    if (dom0 == NULL)
         panic("Error creating domain 0\n");
+    dom0_vcpu0 = alloc_vcpu(dom0, 0, 0);
+    if (dom0_vcpu0 == NULL || vcpu_late_initialise(dom0_vcpu0) != 0)
+        panic("Cannot allocate dom0 vcpu 0\n");
 
     dom0->is_privileged = 1;
 
diff -r a2b2b2a011f1 -r 7d8670a30445 xen/include/asm-ia64/domain.h
--- a/xen/include/asm-ia64/domain.h     Mon Jan 15 15:15:26 2007 -0700
+++ b/xen/include/asm-ia64/domain.h     Tue Jan 16 10:40:37 2007 -0700
@@ -21,6 +21,7 @@ extern void domain_relinquish_resources(
 extern void domain_relinquish_resources(struct domain *);
 struct vcpu;
 extern void relinquish_vcpu_resources(struct vcpu *v);
+extern int vcpu_late_initialise(struct vcpu *v);
 
 /* given a current domain metaphysical address, return the physical address */
 extern unsigned long translate_domain_mpaddr(unsigned long mpaddr,

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.