diff options
author | iap10@labyrinth.cl.cam.ac.uk <iap10@labyrinth.cl.cam.ac.uk> | 2004-05-24 18:13:06 +0000 |
---|---|---|
committer | iap10@labyrinth.cl.cam.ac.uk <iap10@labyrinth.cl.cam.ac.uk> | 2004-05-24 18:13:06 +0000 |
commit | 84b3199c7847e50cb3d777127327674b21540801 (patch) | |
tree | a31f8c33c41b7ba3f66c16fa65b7f9895540c5a6 /xen | |
parent | fdb0b778782b5a8606b37689bbfbe004fdac2722 (diff) | |
download | xen-84b3199c7847e50cb3d777127327674b21540801.tar.gz xen-84b3199c7847e50cb3d777127327674b21540801.tar.bz2 xen-84b3199c7847e50cb3d777127327674b21540801.zip |
bitkeeper revision 1.921 (40b23b32vMbvKCdgtCukVpQP62ZvYA)
Add more stats to migration code, scan pages in psuedo random permutation,
misc cleanups.
Diffstat (limited to 'xen')
-rw-r--r-- | xen/common/dom0_ops.c | 14 | ||||
-rw-r--r-- | xen/common/shadow.c | 41 | ||||
-rw-r--r-- | xen/include/asm-i386/processor.h | 16 | ||||
-rw-r--r-- | xen/include/hypervisor-ifs/dom0_ops.h | 13 | ||||
-rw-r--r-- | xen/include/xen/shadow.h | 8 |
5 files changed, 75 insertions, 17 deletions
diff --git a/xen/common/dom0_ops.c b/xen/common/dom0_ops.c index 586a3a1270..b4baf6c141 100644 --- a/xen/common/dom0_ops.c +++ b/xen/common/dom0_ops.c @@ -397,7 +397,7 @@ long do_dom0_op(dom0_op_t *u_dom0_op) { ret = 0; - op->u.getpageframeinfo.type = NONE; + op->u.getpageframeinfo.type = NOTAB; if ( (page->type_and_flags & PGT_count_mask) != 0 ) { @@ -645,11 +645,17 @@ long do_dom0_op(dom0_op_t *u_dom0_op) switch( page->type_and_flags & PGT_type_mask ) { case PGT_l1_page_table: + type = L1TAB; + break; case PGT_l2_page_table: + type = L2TAB; + break; case PGT_l3_page_table: + type = L3TAB; + break; case PGT_l4_page_table: - type = page->type_and_flags & PGT_type_mask; - + type = L4TAB; + break; } l_arr[j] |= type; put_page(page); @@ -657,7 +663,7 @@ long do_dom0_op(dom0_op_t *u_dom0_op) else { e2_err: - l_arr[j] |= PGT_type_mask; /* error */ + l_arr[j] |= XTAB; } } diff --git a/xen/common/shadow.c b/xen/common/shadow.c index f222419b25..d9e4d9aef8 100644 --- a/xen/common/shadow.c +++ b/xen/common/shadow.c @@ -33,12 +33,34 @@ hypercall lock anyhow (at least initially). FIXME: -1. Flush needs to avoid blowing away the L2 page that another CPU may be using! - -fix using cpu_raise_softirq - -have a flag to count in, (after switching to init's PTs) -spinlock, reload cr3_shadow, unlock +The shadow table flush command is dangerous on SMP systems as the +guest may be using the L2 on one CPU while the other is trying to +blow the table away. + +The current save restore code works around this by not calling FLUSH, +but by calling CLEAN2 which leaves all L2s in tact (this is probably +quicker anyhow). + +Even so, we have to be very careful. The flush code may need to cause +a TLB flush on another CPU. It needs to do this while holding the +shadow table lock. The trouble is, the guest may be in the shadow page +fault handler spinning waiting to grab the shadow lock. It may have +intterupts disabled, hence we can't use the normal flush_tlb_cpu +mechanism. + +For the moment, we have a grim hace whereby the spinlock in the shadow +fault handler is actually a try lock, in a loop with a helper for the +tlb flush code. + +A better soloution would be to take a new flush lock, then raise a +per-domain soft irq on the other CPU. The softirq will switch to +init's PTs, then do an atomic inc of a variable to count himself in, +then spin on a lock. Having noticed that the other guy has counted +in, flush the shadow table, then release him by dropping the lock. He +will then reload cr3 from mm.page_table on the way out of the softirq. + +In domian-softirq context we know that the guy holds no locks and has +interrupts enabled. Nothing can go wrong ;-) **/ @@ -364,6 +386,11 @@ static int shadow_mode_table_op( struct task_struct *p, rc = -EINVAL; goto out; } + + sc->fault_count = p->mm.shadow_fault_count; + sc->dirty_count = p->mm.shadow_dirty_count; + p->mm.shadow_fault_count = 0; + p->mm.shadow_dirty_count = 0; sc->pages = p->tot_pages; @@ -746,6 +773,8 @@ int shadow_fault( unsigned long va, long error_code ) perfc_incrc(shadow_fixup_count); + m->shadow_fault_count++; + check_pagetable( current, current->mm.pagetable, "post-sf" ); spin_unlock(&m->shadow_lock); diff --git a/xen/include/asm-i386/processor.h b/xen/include/asm-i386/processor.h index c2e36d6191..b1eab99d56 100644 --- a/xen/include/asm-i386/processor.h +++ b/xen/include/asm-i386/processor.h @@ -445,17 +445,27 @@ struct mm_struct { l1_pgentry_t *perdomain_pt; pagetable_t pagetable; + /* shadow mode status and controls */ unsigned int shadow_mode; /* flags to control shadow table operation */ pagetable_t shadow_table; spinlock_t shadow_lock; + unsigned int shadow_max_page_count; // currently unused + + /* shadow hashtable */ struct shadow_status *shadow_ht; struct shadow_status *shadow_ht_free; struct shadow_status *shadow_ht_extras; /* extra allocation units */ + unsigned int shadow_extras_count; + + /* shadow dirty bitmap */ unsigned long *shadow_dirty_bitmap; unsigned int shadow_dirty_bitmap_size; /* in pages, bit per page */ - unsigned int shadow_page_count; - unsigned int shadow_max_page_count; - unsigned int shadow_extras_count; + + /* shadow mode stats */ + unsigned int shadow_page_count; + unsigned int shadow_fault_count; + unsigned int shadow_dirty_count; + /* Current LDT details. */ unsigned long ldt_base, ldt_ents, shadow_ldt_mapcnt; diff --git a/xen/include/hypervisor-ifs/dom0_ops.h b/xen/include/hypervisor-ifs/dom0_ops.h index 2a17605bf2..6273878d16 100644 --- a/xen/include/hypervisor-ifs/dom0_ops.h +++ b/xen/include/hypervisor-ifs/dom0_ops.h @@ -150,6 +150,13 @@ typedef struct dom0_settime_st } dom0_settime_t; #define DOM0_GETPAGEFRAMEINFO 18 +#define NOTAB 0 /* normal page */ +#define L1TAB (1<<28) +#define L2TAB (2<<28) +#define L3TAB (3<<28) +#define L4TAB (4<<28) +#define XTAB (0xf<<28) /* invalid page */ +#define LTAB_MASK XTAB typedef struct dom0_getpageframeinfo_st { /* IN variables. */ @@ -157,8 +164,7 @@ typedef struct dom0_getpageframeinfo_st domid_t domain; /* To which domain does the frame belong? */ /* OUT variables. */ /* Is the page PINNED to a type? */ - enum { NONE, L1TAB=(1<<29), L2TAB=(2<<29), L3TAB=(3<<29), L4TAB=(4<<29) } type; -#define PGT_type_mask (7<<29) + unsigned long type; /* see above type defs */ } dom0_getpageframeinfo_t; @@ -251,6 +257,9 @@ typedef struct dom0_shadow_control_st unsigned long *dirty_bitmap; // pointe to mlocked buffer /* IN/OUT variables */ unsigned long pages; // size of buffer, updated with actual size + /* OUT varaibles */ + unsigned long fault_count; + unsigned long dirty_count; } dom0_shadow_control_t; #define DOM0_SETDOMAINNAME 26 diff --git a/xen/include/xen/shadow.h b/xen/include/xen/shadow.h index f1ce8b6689..1597e1feb2 100644 --- a/xen/include/xen/shadow.h +++ b/xen/include/xen/shadow.h @@ -95,8 +95,12 @@ printk("DOM%lld: (file=shadow.c, line=%d) " _f "\n", \ ASSERT(m->shadow_dirty_bitmap); if( likely(pfn<m->shadow_dirty_bitmap_size) ) { - /* These updates occur with mm.shadow_lock held */ - __set_bit( pfn, m->shadow_dirty_bitmap ); + /* These updates occur with mm.shadow_lock held, so use + (__) version of test_and_set */ + if( ! __test_and_set_bit( pfn, m->shadow_dirty_bitmap ) ) + { + m->shadow_dirty_count++; + } } else { |