aboutsummaryrefslogtreecommitdiffstats
path: root/xen
diff options
context:
space:
mode:
authoriap10@labyrinth.cl.cam.ac.uk <iap10@labyrinth.cl.cam.ac.uk>2004-05-24 18:13:06 +0000
committeriap10@labyrinth.cl.cam.ac.uk <iap10@labyrinth.cl.cam.ac.uk>2004-05-24 18:13:06 +0000
commit84b3199c7847e50cb3d777127327674b21540801 (patch)
treea31f8c33c41b7ba3f66c16fa65b7f9895540c5a6 /xen
parentfdb0b778782b5a8606b37689bbfbe004fdac2722 (diff)
downloadxen-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.c14
-rw-r--r--xen/common/shadow.c41
-rw-r--r--xen/include/asm-i386/processor.h16
-rw-r--r--xen/include/hypervisor-ifs/dom0_ops.h13
-rw-r--r--xen/include/xen/shadow.h8
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
{