ia64/xen-unstable

changeset 3567:3fef449b1078

bitkeeper revision 1.1159.231.10 (41f97d1c7VgcW6eh60Nx2MTEdlYhkQ)

Free pages for VMX domain at domain termination.

Signed-off-by: Jun Nakajima <jun.nakajima@intel.com>
Signed-off-by: ian.pratt@cl.cam.ac.uk
author iap10@labyrinth.cl.cam.ac.uk
date Thu Jan 27 23:45:32 2005 +0000 (2005-01-27)
parents a396b30da79d
children 002034af24e6
files xen/arch/x86/domain.c
line diff
     1.1 --- a/xen/arch/x86/domain.c	Thu Jan 27 23:42:08 2005 +0000
     1.2 +++ b/xen/arch/x86/domain.c	Thu Jan 27 23:45:32 2005 +0000
     1.3 @@ -308,15 +308,21 @@ void arch_do_createdomain(struct exec_do
     1.4  }
     1.5  
     1.6  #ifdef CONFIG_VMX
     1.7 -void arch_vmx_do_resume(struct exec_domain *d) 
     1.8 +void arch_vmx_do_resume(struct exec_domain *ed) 
     1.9  {
    1.10 -    vmx_do_resume(d);
    1.11 +    u64 vmcs_phys_ptr = (u64) virt_to_phys(ed->thread.arch_vmx.vmcs);
    1.12 +
    1.13 +    load_vmcs(&ed->thread.arch_vmx, vmcs_phys_ptr);
    1.14 +    vmx_do_resume(ed);
    1.15      reset_stack_and_jump(vmx_asm_do_resume);
    1.16  }
    1.17  
    1.18 -void arch_vmx_do_launch(struct exec_domain *d) 
    1.19 +void arch_vmx_do_launch(struct exec_domain *ed) 
    1.20  {
    1.21 -    vmx_do_launch(d);
    1.22 +    u64 vmcs_phys_ptr = (u64) virt_to_phys(ed->thread.arch_vmx.vmcs);
    1.23 +
    1.24 +    load_vmcs(&ed->thread.arch_vmx, vmcs_phys_ptr);
    1.25 +    vmx_do_launch(ed);
    1.26      reset_stack_and_jump(vmx_asm_do_launch);
    1.27  }
    1.28  
    1.29 @@ -332,14 +338,14 @@ static void monitor_mk_pagetable(struct 
    1.30      ASSERT( mpfn_info ); 
    1.31  
    1.32      mpfn = (unsigned long) (mpfn_info - frame_table);
    1.33 -    mpl2e = (l2_pgentry_t *) map_domain_mem(mpfn << PAGE_SHIFT);
    1.34 +    mpl2e = (l2_pgentry_t *) map_domain_mem(mpfn << L1_PAGETABLE_SHIFT);
    1.35      memset(mpl2e, 0, PAGE_SIZE);
    1.36  
    1.37      memcpy(&mpl2e[DOMAIN_ENTRIES_PER_L2_PAGETABLE], 
    1.38             &idle_pg_table[DOMAIN_ENTRIES_PER_L2_PAGETABLE],
    1.39             HYPERVISOR_ENTRIES_PER_L2_PAGETABLE * sizeof(l2_pgentry_t));
    1.40  
    1.41 -    m->monitor_table = mk_pagetable(mpfn << PAGE_SHIFT);
    1.42 +    m->monitor_table = mk_pagetable(mpfn << L1_PAGETABLE_SHIFT);
    1.43      m->shadow_mode = SHM_full_32;
    1.44  
    1.45      mpl2e[PERDOMAIN_VIRT_START >> L2_PAGETABLE_SHIFT] =
    1.46 @@ -349,13 +355,42 @@ static void monitor_mk_pagetable(struct 
    1.47      unmap_domain_mem(mpl2e);
    1.48  }
    1.49  
    1.50 -static int vmx_final_setup_guestos(struct exec_domain *d,
    1.51 +/*
    1.52 + * Free the pages for monitor_table and guest_pl2e_cache
    1.53 + */
    1.54 +static void monitor_rm_pagetable(struct exec_domain *ed)
    1.55 +{
    1.56 +    struct mm_struct *m = &ed->mm;
    1.57 +    l2_pgentry_t *mpl2e;
    1.58 +    unsigned long mpfn;
    1.59 +
    1.60 +    ASSERT( m->monitor_table );
    1.61 +    
    1.62 +    mpl2e = (l2_pgentry_t *) map_domain_mem(pagetable_val(m->monitor_table));
    1.63 +    /*
    1.64 +     * First get the pfn for guest_pl2e_cache by looking at monitor_table
    1.65 +     */
    1.66 +    mpfn = l2_pgentry_val(mpl2e[LINEAR_PT_VIRT_START >> L2_PAGETABLE_SHIFT])
    1.67 +        >> PAGE_SHIFT;
    1.68 +
    1.69 +    free_domheap_page(&frame_table[mpfn]);
    1.70 +    unmap_domain_mem(mpl2e);
    1.71 +
    1.72 +    /*
    1.73 +     * Then free monitor_table.
    1.74 +     */
    1.75 +    mpfn = (pagetable_val(m->monitor_table)) >> PAGE_SHIFT;
    1.76 +    free_domheap_page(&frame_table[mpfn]);
    1.77 +
    1.78 +    m->monitor_table = mk_pagetable(0);
    1.79 +}
    1.80 +
    1.81 +static int vmx_final_setup_guestos(struct exec_domain *ed,
    1.82                                     full_execution_context_t *full_context)
    1.83  {
    1.84      int error;
    1.85      execution_context_t *context;
    1.86      struct vmcs_struct *vmcs;
    1.87 -    unsigned long guest_pa;
    1.88  
    1.89      context = &full_context->cpu_ctxt;
    1.90  
    1.91 @@ -367,33 +402,38 @@ static int vmx_final_setup_guestos(struc
    1.92          return -ENOMEM;
    1.93      }
    1.94  
    1.95 -    memset(&d->thread.arch_vmx, 0, sizeof (struct arch_vmx_struct));
    1.96 +    memset(&ed->thread.arch_vmx, 0, sizeof (struct arch_vmx_struct));
    1.97  
    1.98 -    d->thread.arch_vmx.vmcs = vmcs;
    1.99 -    error = construct_vmcs(&d->thread.arch_vmx, context, full_context, VMCS_USE_HOST_ENV);
   1.100 +    ed->thread.arch_vmx.vmcs = vmcs;
   1.101 +    error = construct_vmcs(&ed->thread.arch_vmx, context, full_context, VMCS_USE_HOST_ENV);
   1.102      if (error < 0) {
   1.103          printk("Failed to construct a new VMCS\n");
   1.104          goto out;
   1.105      }
   1.106  
   1.107 -    monitor_mk_pagetable(d);
   1.108 -    guest_pa = pagetable_val(d->mm.pagetable);
   1.109 -    clear_bit(VMX_CPU_STATE_PG_ENABLED, &d->thread.arch_vmx.cpu_state);
   1.110 +    monitor_mk_pagetable(ed);
   1.111 +    ed->thread.schedule_tail = arch_vmx_do_launch;
   1.112 +    clear_bit(VMX_CPU_STATE_PG_ENABLED, &ed->thread.arch_vmx.cpu_state);
   1.113  
   1.114 -    d->thread.arch_vmx.vmx_platform.real_mode_data = 
   1.115 +#if defined (__i386)
   1.116 +    ed->thread.arch_vmx.vmx_platform.real_mode_data = 
   1.117          (unsigned long *) context->esi;
   1.118 +#endif
   1.119  
   1.120 -    memset(&d->domain->shared_info->evtchn_mask[0], 0xff, 
   1.121 -           sizeof(d->domain->shared_info->evtchn_mask));
   1.122 -    clear_bit(IOPACKET_PORT, &d->domain->shared_info->evtchn_mask[0]);
   1.123 -
   1.124 -    d->thread.schedule_tail = arch_vmx_do_launch;
   1.125 +    if (ed == ed->domain->exec_domain[0]) {
   1.126 +        /* 
   1.127 +         * Required to do this once per domain
   1.128 +         */
   1.129 +        memset(&ed->domain->shared_info->evtchn_mask[0], 0xff, 
   1.130 +               sizeof(ed->domain->shared_info->evtchn_mask));
   1.131 +        clear_bit(IOPACKET_PORT, &ed->domain->shared_info->evtchn_mask[0]);
   1.132 +    }
   1.133  
   1.134      return 0;
   1.135  
   1.136  out:
   1.137      free_vmcs(vmcs);
   1.138 -    d->thread.arch_vmx.vmcs = 0;
   1.139 +    ed->thread.arch_vmx.vmcs = 0;
   1.140      return error;
   1.141  }
   1.142  #endif
   1.143 @@ -707,6 +747,35 @@ static void relinquish_list(struct domai
   1.144      spin_unlock_recursive(&d->page_alloc_lock);
   1.145  }
   1.146  
   1.147 +static void vmx_domain_relinquish_memory(struct exec_domain *ed)
   1.148 +{
   1.149 +    struct domain *d = ed->domain;
   1.150 +
   1.151 +    /*
   1.152 +     * Free VMCS
   1.153 +     */
   1.154 +    ASSERT(ed->thread.arch_vmx.vmcs);
   1.155 +    free_vmcs(ed->thread.arch_vmx.vmcs);
   1.156 +    ed->thread.arch_vmx.vmcs = 0;
   1.157 +    
   1.158 +    monitor_rm_pagetable(ed);
   1.159 +
   1.160 +    if (ed == d->exec_domain[0]) {
   1.161 +        int i;
   1.162 +        unsigned long pfn;
   1.163 +
   1.164 +        for (i = 0; i < ENTRIES_PER_L1_PAGETABLE; i++) {
   1.165 +            unsigned long l1e;
   1.166 +            
   1.167 +            l1e = l1_pgentry_val(d->mm_perdomain_pt[i]);
   1.168 +            if (l1e & _PAGE_PRESENT) {
   1.169 +                pfn = l1e >> PAGE_SHIFT;
   1.170 +                free_domheap_page(&frame_table[pfn]);
   1.171 +            }
   1.172 +        }
   1.173 +    }
   1.174 +
   1.175 +}
   1.176  
   1.177  void domain_relinquish_memory(struct domain *d)
   1.178  {
   1.179 @@ -725,6 +794,10 @@ void domain_relinquish_memory(struct dom
   1.180                                             PAGE_SHIFT]);
   1.181      }
   1.182  
   1.183 +    if (VMX_DOMAIN(d->exec_domain[0]))
   1.184 +        for_each_exec_domain(d, ed)
   1.185 +            vmx_domain_relinquish_memory(ed);
   1.186 +
   1.187      /*
   1.188       * Relinquish GDT mappings. No need for explicit unmapping of the LDT as 
   1.189       * it automatically gets squashed when the guest's mappings go away.