ia64/xen-unstable

changeset 15828:3b50a7e52ff2

Implement x86 continuable domain destroy.
This patch addresses the following bug report.
http://bugzilla.xensource.com/bugzilla/show_bug.cgi?id=1037
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
author kfraser@localhost.localdomain
date Fri Aug 31 17:00:11 2007 +0100 (2007-08-31)
parents 230000d3ef32
children 1b11356af548
files xen/arch/x86/domain.c xen/arch/x86/domctl.c xen/common/domain.c xen/include/asm-x86/domain.h
line diff
     1.1 --- a/xen/arch/x86/domain.c	Fri Aug 31 16:50:26 2007 +0100
     1.2 +++ b/xen/arch/x86/domain.c	Fri Aug 31 17:00:11 2007 +0100
     1.3 @@ -437,6 +437,9 @@ int arch_domain_create(struct domain *d)
     1.4      int vcpuid, pdpt_order, paging_initialised = 0;
     1.5      int rc = -ENOMEM;
     1.6  
     1.7 +    d->arch.relmem = RELMEM_not_started;
     1.8 +    INIT_LIST_HEAD(&d->arch.relmem_list);
     1.9 +
    1.10      pdpt_order = get_order_from_bytes(PDPT_L1_ENTRIES * sizeof(l1_pgentry_t));
    1.11      d->arch.mm_perdomain_pt = alloc_xenheap_pages(pdpt_order);
    1.12      if ( d->arch.mm_perdomain_pt == NULL )
    1.13 @@ -1599,12 +1602,13 @@ int hypercall_xlat_continuation(unsigned
    1.14  }
    1.15  #endif
    1.16  
    1.17 -static void relinquish_memory(struct domain *d, struct list_head *list,
    1.18 -                              unsigned long type)
    1.19 +static int relinquish_memory(
    1.20 +    struct domain *d, struct list_head *list, unsigned long type)
    1.21  {
    1.22      struct list_head *ent;
    1.23      struct page_info  *page;
    1.24      unsigned long     x, y;
    1.25 +    int               ret = 0;
    1.26  
    1.27      /* Use a recursive lock, as we may enter 'free_domheap_page'. */
    1.28      spin_lock_recursive(&d->page_alloc_lock);
    1.29 @@ -1619,6 +1623,7 @@ static void relinquish_memory(struct dom
    1.30          {
    1.31              /* Couldn't get a reference -- someone is freeing this page. */
    1.32              ent = ent->next;
    1.33 +            list_move_tail(&page->list, &d->arch.relmem_list);
    1.34              continue;
    1.35          }
    1.36  
    1.37 @@ -1653,10 +1658,21 @@ static void relinquish_memory(struct dom
    1.38  
    1.39          /* Follow the list chain and /then/ potentially free the page. */
    1.40          ent = ent->next;
    1.41 +        list_move_tail(&page->list, &d->arch.relmem_list);
    1.42          put_page(page);
    1.43 +
    1.44 +        if ( hypercall_preempt_check() )
    1.45 +        {
    1.46 +            ret = -EAGAIN;
    1.47 +            goto out;
    1.48 +        }
    1.49      }
    1.50  
    1.51 +    list_splice_init(&d->arch.relmem_list, list);
    1.52 +
    1.53 + out:
    1.54      spin_unlock_recursive(&d->page_alloc_lock);
    1.55 +    return ret;
    1.56  }
    1.57  
    1.58  static void vcpu_destroy_pagetables(struct vcpu *v)
    1.59 @@ -1719,35 +1735,81 @@ static void vcpu_destroy_pagetables(stru
    1.60  
    1.61  int domain_relinquish_resources(struct domain *d)
    1.62  {
    1.63 +    int ret;
    1.64      struct vcpu *v;
    1.65  
    1.66      BUG_ON(!cpus_empty(d->domain_dirty_cpumask));
    1.67  
    1.68 -    /* Tear down paging-assistance stuff. */
    1.69 -    paging_teardown(d);
    1.70 -
    1.71 -    /* Drop the in-use references to page-table bases. */
    1.72 -    for_each_vcpu ( d, v )
    1.73 -        vcpu_destroy_pagetables(v);
    1.74 +    switch ( d->arch.relmem )
    1.75 +    {
    1.76 +    case RELMEM_not_started:
    1.77 +        /* Tear down paging-assistance stuff. */
    1.78 +        paging_teardown(d);
    1.79  
    1.80 -    /*
    1.81 -     * Relinquish GDT mappings. No need for explicit unmapping of the LDT as
    1.82 -     * it automatically gets squashed when the guest's mappings go away.
    1.83 -     */
    1.84 -    for_each_vcpu(d, v)
    1.85 -        destroy_gdt(v);
    1.86 +        /* Drop the in-use references to page-table bases. */
    1.87 +        for_each_vcpu ( d, v )
    1.88 +            vcpu_destroy_pagetables(v);
    1.89  
    1.90 -    /* Relinquish every page of memory. */
    1.91 +        /*
    1.92 +         * Relinquish GDT mappings. No need for explicit unmapping of the LDT
    1.93 +         * as it automatically gets squashed when the guest's mappings go away.
    1.94 +         */
    1.95 +        for_each_vcpu(d, v)
    1.96 +            destroy_gdt(v);
    1.97 +
    1.98 +        d->arch.relmem = RELMEM_xen_l4;
    1.99 +        /* fallthrough */
   1.100 +
   1.101 +        /* Relinquish every page of memory. */
   1.102  #if CONFIG_PAGING_LEVELS >= 4
   1.103 -    relinquish_memory(d, &d->xenpage_list, PGT_l4_page_table);
   1.104 -    relinquish_memory(d, &d->page_list, PGT_l4_page_table);
   1.105 +    case RELMEM_xen_l4:
   1.106 +        ret = relinquish_memory(d, &d->xenpage_list, PGT_l4_page_table);
   1.107 +        if ( ret )
   1.108 +            return ret;
   1.109 +        d->arch.relmem = RELMEM_dom_l4;
   1.110 +        /* fallthrough */
   1.111 +	case RELMEM_dom_l4:
   1.112 +        ret = relinquish_memory(d, &d->page_list, PGT_l4_page_table);
   1.113 +        if ( ret )
   1.114 +            return ret;
   1.115 +        d->arch.relmem = RELMEM_xen_l3;
   1.116 +        /* fallthrough */
   1.117  #endif
   1.118 +
   1.119  #if CONFIG_PAGING_LEVELS >= 3
   1.120 -    relinquish_memory(d, &d->xenpage_list, PGT_l3_page_table);
   1.121 -    relinquish_memory(d, &d->page_list, PGT_l3_page_table);
   1.122 +	case RELMEM_xen_l3:
   1.123 +        ret = relinquish_memory(d, &d->xenpage_list, PGT_l3_page_table);
   1.124 +        if ( ret )
   1.125 +            return ret;
   1.126 +        d->arch.relmem = RELMEM_dom_l3;
   1.127 +        /* fallthrough */
   1.128 +	case RELMEM_dom_l3:
   1.129 +        ret = relinquish_memory(d, &d->page_list, PGT_l3_page_table);
   1.130 +        if ( ret )
   1.131 +            return ret;
   1.132 +        d->arch.relmem = RELMEM_xen_l2;
   1.133 +        /* fallthrough */
   1.134  #endif
   1.135 -    relinquish_memory(d, &d->xenpage_list, PGT_l2_page_table);
   1.136 -    relinquish_memory(d, &d->page_list, PGT_l2_page_table);
   1.137 +
   1.138 +	case RELMEM_xen_l2:
   1.139 +        ret = relinquish_memory(d, &d->xenpage_list, PGT_l2_page_table);
   1.140 +        if ( ret )
   1.141 +            return ret;
   1.142 +        d->arch.relmem = RELMEM_dom_l2;
   1.143 +        /* fallthrough */
   1.144 +	case RELMEM_dom_l2:
   1.145 +        ret = relinquish_memory(d, &d->page_list, PGT_l2_page_table);
   1.146 +        if ( ret )
   1.147 +            return ret;
   1.148 +        d->arch.relmem = RELMEM_done;
   1.149 +        /* fallthrough */
   1.150 +
   1.151 +	case RELMEM_done:
   1.152 +        break;
   1.153 +
   1.154 +    default:
   1.155 +        BUG();
   1.156 +    }
   1.157  
   1.158      /* Free page used by xen oprofile buffer. */
   1.159      free_xenoprof_pages(d);
     2.1 --- a/xen/arch/x86/domctl.c	Fri Aug 31 16:50:26 2007 +0100
     2.2 +++ b/xen/arch/x86/domctl.c	Fri Aug 31 17:00:11 2007 +0100
     2.3 @@ -257,10 +257,14 @@ long arch_do_domctl(
     2.4                  break;
     2.5              }
     2.6  
     2.7 -            ret = 0;
     2.8 -
     2.9              spin_lock(&d->page_alloc_lock);
    2.10  
    2.11 +            if ( unlikely(d->is_dying) ) {
    2.12 +                spin_unlock(&d->page_alloc_lock);
    2.13 +                goto getmemlist_out;
    2.14 +            }
    2.15 +
    2.16 +            ret = 0;
    2.17              list_ent = d->page_list.next;
    2.18              for ( i = 0; (i < max_pfns) && (list_ent != &d->page_list); i++ )
    2.19              {
    2.20 @@ -279,7 +283,7 @@ long arch_do_domctl(
    2.21  
    2.22              domctl->u.getmemlist.num_pfns = i;
    2.23              copy_to_guest(u_domctl, domctl, 1);
    2.24 -
    2.25 +        getmemlist_out:
    2.26              rcu_unlock_domain(d);
    2.27          }
    2.28      }
     3.1 --- a/xen/common/domain.c	Fri Aug 31 16:50:26 2007 +0100
     3.2 +++ b/xen/common/domain.c	Fri Aug 31 17:00:11 2007 +0100
     3.3 @@ -318,6 +318,7 @@ int domain_kill(struct domain *d)
     3.4          d->is_dying = DOMDYING_dying;
     3.5          evtchn_destroy(d);
     3.6          gnttab_release_mappings(d);
     3.7 +        /* fallthrough */
     3.8      case DOMDYING_dying:
     3.9          rc = domain_relinquish_resources(d);
    3.10          page_scrub_kick();
    3.11 @@ -329,6 +330,7 @@ int domain_kill(struct domain *d)
    3.12          d->is_dying = DOMDYING_dead;
    3.13          put_domain(d);
    3.14          send_guest_global_virq(dom0, VIRQ_DOM_EXC);
    3.15 +        /* fallthrough */
    3.16      case DOMDYING_dead:
    3.17          break;
    3.18      }
     4.1 --- a/xen/include/asm-x86/domain.h	Fri Aug 31 16:50:26 2007 +0100
     4.2 +++ b/xen/include/asm-x86/domain.h	Fri Aug 31 17:00:11 2007 +0100
     4.3 @@ -234,6 +234,19 @@ struct arch_domain
     4.4      bool_t is_32bit_pv;
     4.5      /* Is shared-info page in 32-bit format? */
     4.6      bool_t has_32bit_shinfo;
     4.7 +
     4.8 +    /* Continuable domain_relinquish_resources(). */
     4.9 +    enum {
    4.10 +        RELMEM_not_started,
    4.11 +        RELMEM_xen_l4,
    4.12 +        RELMEM_dom_l4,
    4.13 +        RELMEM_xen_l3,
    4.14 +        RELMEM_dom_l3,
    4.15 +        RELMEM_xen_l2,
    4.16 +        RELMEM_dom_l2,
    4.17 +        RELMEM_done,
    4.18 +    } relmem;
    4.19 +    struct list_head relmem_list;
    4.20  } __cacheline_aligned;
    4.21  
    4.22  #ifdef CONFIG_X86_PAE