[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>
This commit is contained in:
awilliam@xenbuild2.aw committed 2007-01-16 10:40:37 -07:00
1 parent b5a65552a9
commit 5a1ef100be
4 files changed
+72 -73

No files matched your search

-10
View File
@@ -103,16 +103,6 @@ long arch_do_domctl(xen_domctl_t *op, XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
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);
}
+66 -62
View File
@@ -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 @@ void free_vcpu_struct(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;
@@ -420,6 +382,41 @@ int vcpu_initialise(struct vcpu *v)
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;
}
void vcpu_destroy(struct vcpu *v)
{
if (v->domain->arch.is_vti)
@@ -553,6 +550,7 @@ int arch_set_info_guest(struct vcpu *v, vcpu_guest_context_u c)
{
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, vcpu_guest_context_u c)
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 va)
{
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 va)
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);
+5 -1
View File
@@ -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\n",num_online_cpus(),max_cpus);
/* 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;
+1
View File
@@ -21,6 +21,7 @@ struct tlb_track;
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,
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.