# 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
|