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