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

[Xen-changelog] [IA64] domU destroy



# HG changeset patch
# User awilliam@xxxxxxxxxxx
# Node ID 551f7935f79a842341ec5baf5fccb9c56bd5473b
# Parent  c644eb4049abedac4bbe83c0497b592b1f4bb531
[IA64] domU destroy

Signed-off-by: Akio Takebe <takebe_akio@xxxxxxxxxxxxxx>
Signed-off-by: Masaki Kanno <kanno.masaki@xxxxxxxxxxxxxx>

diff -r c644eb4049ab -r 551f7935f79a xen/arch/ia64/xen/domain.c
--- a/xen/arch/ia64/xen/domain.c        Fri Mar 10 15:23:39 2006
+++ b/xen/arch/ia64/xen/domain.c        Fri Mar 10 15:25:54 2006
@@ -49,6 +49,8 @@
 #include <asm/pal.h>
 #include <asm/vhpt.h>
 #include <public/hvm/ioreq.h>
+#include <asm/tlbflush.h>
+#include <asm/regionreg.h>
 
 #define CONFIG_DOMAIN0_CONTIGUOUS
 unsigned long dom0_start = -1L;
@@ -69,10 +71,7 @@
 /* FIXME: where these declarations should be there ? */
 extern void domain_pend_keyboard_interrupt(int);
 extern long platform_is_hp_ski(void);
-extern unsigned long allocate_metaphysical_rr(void);
-extern int allocate_rid_range(struct domain *, unsigned long);
 extern void sync_split_caches(void);
-extern void init_all_rr(struct vcpu *);
 extern void serial_input_init(void);
 
 static void init_switch_stack(struct vcpu *v);
@@ -80,9 +79,33 @@
 /* this belongs in include/asm, but there doesn't seem to be a suitable place 
*/
 void arch_domain_destroy(struct domain *d)
 {
-       printf("arch_domain_destroy: not implemented\n");
-       //free_page((unsigned long)d->mm.perdomain_pt);
-       free_xenheap_page(d->shared_info);
+       struct page *page;
+       struct list_head *ent, *prev;
+
+       if (d->arch.mm->pgd != NULL)
+       {
+               list_for_each ( ent, &d->arch.mm->pt_list )
+               {
+                       page = list_entry(ent, struct page, list);
+                       prev = ent->prev;
+                       list_del(ent);
+                       free_xenheap_page(page_to_virt(page));
+                       ent = prev;
+               }
+               pgd_free(d->arch.mm->pgd);
+       }
+       if (d->arch.mm != NULL)
+               xfree(d->arch.mm);
+       if (d->shared_info != NULL)
+               free_xenheap_page(d->shared_info);
+
+       deallocate_rid_range(d);
+
+       /* It is really good in this? */
+       flush_tlb_all();
+
+       /* It is really good in this? */
+       vhpt_flush();
 }
 
 static void default_idle(void)
@@ -187,6 +210,8 @@
 
 void free_vcpu_struct(struct vcpu *v)
 {
+       if (v->arch.privregs != NULL)
+               free_xenheap_pages(v->arch.privregs, 
get_order(sizeof(mapped_regs_t)));
        free_xenheap_pages(v, KERNEL_STACK_SIZE_ORDER);
 }
 
@@ -239,6 +264,7 @@
        if ((d->arch.mm = xmalloc(struct mm_struct)) == NULL)
            goto fail_nomem;
        memset(d->arch.mm, 0, sizeof(*d->arch.mm));
+       INIT_LIST_HEAD(&d->arch.mm->pt_list);
 
        if ((d->arch.mm->pgd = pgd_alloc(d->arch.mm)) == NULL)
            goto fail_nomem;
@@ -310,10 +336,74 @@
        return 0;
 }
 
+static void relinquish_memory(struct domain *d, struct list_head *list)
+{
+    struct list_head *ent;
+    struct page      *page;
+#ifndef __ia64__
+    unsigned long     x, y;
+#endif
+
+    /* Use a recursive lock, as we may enter 'free_domheap_page'. */
+    spin_lock_recursive(&d->page_alloc_lock);
+    ent = list->next;
+    while ( ent != list )
+    {
+        page = list_entry(ent, struct page, list);
+        /* Grab a reference to the page so it won't disappear from under us. */
+        if ( unlikely(!get_page(page, d)) )
+        {
+            /* Couldn't get a reference -- someone is freeing this page. */
+            ent = ent->next;
+            continue;
+        }
+
+        if ( test_and_clear_bit(_PGT_pinned, &page->u.inuse.type_info) )
+            put_page_and_type(page);
+
+        if ( test_and_clear_bit(_PGC_allocated, &page->count_info) )
+            put_page(page);
+
+#ifndef __ia64__
+        /*
+         * Forcibly invalidate base page tables at this point to break circular
+         * 'linear page table' references. This is okay because MMU structures
+         * are not shared across domains and this domain is now dead. Thus base
+         * tables are not in use so a non-zero count means circular reference.
+         */
+        y = page->u.inuse.type_info;
+        for ( ; ; )
+        {
+            x = y;
+            if ( likely((x & (PGT_type_mask|PGT_validated)) !=
+                        (PGT_base_page_table|PGT_validated)) )
+                break;
+
+            y = cmpxchg(&page->u.inuse.type_info, x, x & ~PGT_validated);
+            if ( likely(y == x) )
+            {
+                free_page_type(page, PGT_base_page_table);
+                break;
+            }
+        }
+#endif
+
+        /* Follow the list chain and /then/ potentially free the page. */
+        ent = ent->next;
+        put_page(page);
+    }
+
+    spin_unlock_recursive(&d->page_alloc_lock);
+}
+
 void domain_relinquish_resources(struct domain *d)
 {
-       /* FIXME */
-       printf("domain_relinquish_resources: not implemented\n");
+    /* Relinquish every page of memory. */
+
+    /* xenheap_list is not used in ia64. */
+    BUG_ON(!list_empty(&d->xenpage_list));
+
+    relinquish_memory(d, &d->page_list);
 }
 
 // heavily leveraged from linux/arch/ia64/kernel/process.c:copy_thread()
@@ -389,7 +479,7 @@
 struct page * assign_new_domain_page(struct domain *d, unsigned long mpaddr)
 {
        struct mm_struct *mm = d->arch.mm;
-       struct page *p = (struct page *)0;
+       struct page *pt, *p = (struct page *)0;
        pgd_t *pgd;
        pud_t *pud;
        pmd_t *pmd;
@@ -401,16 +491,28 @@
        }
        pgd = pgd_offset(mm,mpaddr);
        if (pgd_none(*pgd))
+       {
                pgd_populate(mm, pgd, pud_alloc_one(mm,mpaddr));
+               pt = maddr_to_page(pgd_val(*pgd));
+               list_add_tail(&pt->list, &d->arch.mm->pt_list);
+       }
 
        pud = pud_offset(pgd, mpaddr);
        if (pud_none(*pud))
+       {
                pud_populate(mm, pud, pmd_alloc_one(mm,mpaddr));
+               pt = maddr_to_page(pud_val(*pud));
+               list_add_tail(&pt->list, &d->arch.mm->pt_list);
+       }
 
        pmd = pmd_offset(pud, mpaddr);
        if (pmd_none(*pmd))
+       {
                pmd_populate_kernel(mm, pmd, pte_alloc_one_kernel(mm,mpaddr));
 //             pmd_populate(mm, pmd, pte_alloc_one(mm,mpaddr));
+               pt = maddr_to_page(pmd_val(*pmd));
+               list_add_tail(&pt->list, &d->arch.mm->pt_list);
+       }
 
        pte = pte_offset_map(pmd, mpaddr);
        if (pte_none(*pte)) {
@@ -443,6 +545,7 @@
 void assign_domain_page(struct domain *d, unsigned long mpaddr, unsigned long 
physaddr)
 {
        struct mm_struct *mm = d->arch.mm;
+       struct page *pt;
        pgd_t *pgd;
        pud_t *pud;
        pmd_t *pmd;
@@ -454,16 +557,28 @@
        }
        pgd = pgd_offset(mm,mpaddr);
        if (pgd_none(*pgd))
+       {
                pgd_populate(mm, pgd, pud_alloc_one(mm,mpaddr));
+               pt = maddr_to_page(pgd_val(*pgd));
+               list_add_tail(&pt->list, &d->arch.mm->pt_list);
+       }
 
        pud = pud_offset(pgd, mpaddr);
        if (pud_none(*pud))
+       {
                pud_populate(mm, pud, pmd_alloc_one(mm,mpaddr));
+               pt = maddr_to_page(pud_val(*pud));
+               list_add_tail(&pt->list, &d->arch.mm->pt_list);
+       }
 
        pmd = pmd_offset(pud, mpaddr);
        if (pmd_none(*pmd))
+       {
                pmd_populate_kernel(mm, pmd, pte_alloc_one_kernel(mm,mpaddr));
 //             pmd_populate(mm, pmd, pte_alloc_one(mm,mpaddr));
+               pt = maddr_to_page(pmd_val(*pmd));
+               list_add_tail(&pt->list, &d->arch.mm->pt_list);
+       }
 
        pte = pte_offset_map(pmd, mpaddr);
        if (pte_none(*pte)) {
diff -r c644eb4049ab -r 551f7935f79a xen/arch/ia64/xen/regionreg.c
--- a/xen/arch/ia64/xen/regionreg.c     Fri Mar 10 15:23:39 2006
+++ b/xen/arch/ia64/xen/regionreg.c     Fri Mar 10 15:25:54 2006
@@ -157,7 +157,6 @@
        int rid_block_end = d->arch.ending_rid >> IA64_MIN_IMPL_RID_BITS;
        int rid_block_start = d->arch.starting_rid >> IA64_MIN_IMPL_RID_BITS;
 
-       return 1;  // KLUDGE ALERT
        //
        // not all domains will have allocated RIDs (physical mode loaders for 
instance)
        //
diff -r c644eb4049ab -r 551f7935f79a xen/include/asm-ia64/domain.h
--- a/xen/include/asm-ia64/domain.h     Fri Mar 10 15:23:39 2006
+++ b/xen/include/asm-ia64/domain.h     Fri Mar 10 15:25:54 2006
@@ -102,6 +102,8 @@
 #endif
        spinlock_t page_table_lock;             /* Protects task page tables 
and mm->rss */
 
+       struct list_head pt_list;               /* List of pagetable */
+
        struct list_head mmlist;                /* List of all active mm's.  
These are globally strung
                                                 * together off init_mm.mmlist, 
and are protected
                                                 * by mmlist_lock
diff -r c644eb4049ab -r 551f7935f79a xen/include/asm-ia64/regionreg.h
--- a/xen/include/asm-ia64/regionreg.h  Fri Mar 10 15:23:39 2006
+++ b/xen/include/asm-ia64/regionreg.h  Fri Mar 10 15:25:54 2006
@@ -64,4 +64,13 @@
 // since vmMangleRID is symmetric, use it for unmangling also
 #define vmUnmangleRID(x)       vmMangleRID(x)
 
+extern unsigned long allocate_metaphysical_rr(void);
+
+struct domain;
+extern int allocate_rid_range(struct domain *d, unsigned long ridbits);
+extern int deallocate_rid_range(struct domain *d);
+
+struct vcpu;
+extern void init_all_rr(struct vcpu *v);
+
 #endif         /* !_REGIONREG_H_ */

_______________________________________________
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®.