# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1233247248 0
# Node ID e1352667df950a597b82171b506ca5b5cce891fe
# Parent aa89d1afb287a5c712c6b888966c4c759021939f
PoD: Check refcount, not type count when reclaiming zero pages
Check the page refcount rather than the type count when deciding if a
page is still mapped.
This catches pages which are mapped by qemu; it also removes the need
for gnttab_is_granted().
Signed-off-by: George Dunlap <george.dunlap@xxxxxxxxxxxxx>
---
xen/arch/x86/mm/p2m.c | 61 ++++++++++++++++++++++++------------------
xen/common/grant_table.c | 27 ------------------
xen/include/xen/grant_table.h | 3 --
3 files changed, 35 insertions(+), 56 deletions(-)
diff -r aa89d1afb287 -r e1352667df95 xen/arch/x86/mm/p2m.c
--- a/xen/arch/x86/mm/p2m.c Thu Jan 29 16:39:56 2009 +0000
+++ b/xen/arch/x86/mm/p2m.c Thu Jan 29 16:40:48 2009 +0000
@@ -723,9 +723,14 @@ p2m_pod_zero_check_superpage(struct doma
unsigned long * map = NULL;
int ret=0, reset = 0;
int i, j;
+ int max_ref = 1;
if ( !superpage_aligned(gfn) )
goto out;
+
+ /* Allow an extra refcount for one shadow pt mapping in shadowed domains */
+ if ( paging_mode_shadow(d) )
+ max_ref++;
/* Look up the mfns, checking to make sure they're the same mfn
* and aligned, and mapping them. */
@@ -743,13 +748,19 @@ p2m_pod_zero_check_superpage(struct doma
/* Conditions that must be met for superpage-superpage:
* + All gfns are ram types
* + All gfns have the same type
+ * + All of the mfns are allocated to a domain
* + None of the mfns are used as pagetables
* + The first mfn is 2-meg aligned
* + All the other mfns are in sequence
+ * Adding for good measure:
+ * + None of the mfns are likely to be mapped elsewhere (refcount
+ * 2 or less for shadow, 1 for hap)
*/
if ( !p2m_is_ram(type)
|| type != type0
+ || ( (mfn_to_page(mfn)->count_info & PGC_allocated) == 0 )
|| ( (mfn_to_page(mfn)->count_info & PGC_page_table) != 0 )
+ || ( (mfn_to_page(mfn)->count_info & PGC_count_mask) > max_ref )
|| !( ( i == 0 && superpage_aligned(mfn_x(mfn0)) )
|| ( i != 0 && mfn_x(mfn) == (mfn_x(mfn0) + i) ) ) )
goto out;
@@ -777,26 +788,16 @@ p2m_pod_zero_check_superpage(struct doma
_mfn(POPULATE_ON_DEMAND_MFN), 9,
p2m_populate_on_demand);
- if ( (mfn_to_page(mfn0)->u.inuse.type_info & PGT_count_mask) != 0 )
- {
- reset = 1;
- goto out_reset;
- }
-
- /* Timing here is important. We need to make sure not to reclaim
- * a page which has been grant-mapped to another domain. But we
- * can't grab the grant table lock, because we may be invoked from
- * the grant table code! So we first remove the page from the
- * p2m, then check to see if the gpfn has been granted. Once this
- * gpfn is marked PoD, any future gfn_to_mfn() call will block
- * waiting for the p2m lock. If we find that it has been granted, we
- * simply restore the old value.
- */
- if ( gnttab_is_granted(d, gfn, 9) )
- {
- printk("gfn contains grant table %lx\n", gfn);
- reset = 1;
- goto out_reset;
+ /* Make none of the MFNs are used elsewhere... for example, mapped
+ * via the grant table interface, or by qemu. Allow one refcount for
+ * being allocated to the domain. */
+ for ( i=0; i < (1<<9); i++ )
+ {
+ if ( (mfn_to_page(mfn0+i)->count_info & PGC_count_mask) > 1 )
+ {
+ reset = 1;
+ goto out_reset;
+ }
}
/* Finally, do a full zero-check */
@@ -838,15 +839,22 @@ p2m_pod_zero_check(struct domain *d, uns
unsigned long * map[count];
int i, j;
+ int max_ref = 1;
+
+ /* Allow an extra refcount for one shadow pt mapping in shadowed domains */
+ if ( paging_mode_shadow(d) )
+ max_ref++;
/* First, get the gfn list, translate to mfns, and map the pages. */
for ( i=0; i<count; i++ )
{
mfns[i] = gfn_to_mfn_query(d, gfns[i], types + i);
- /* If this is ram, and not a pagetable, map it; otherwise,
- * skip. */
+ /* If this is ram, and not a pagetable, and probably not mapped
+ elsewhere, map it; otherwise, skip. */
if ( p2m_is_ram(types[i])
- && ( (mfn_to_page(mfns[i])->count_info & PGC_page_table) == 0 ) )
+ && ( (mfn_to_page(mfns[i])->count_info & PGC_allocated) != 0 )
+ && ( (mfn_to_page(mfns[i])->count_info & PGC_page_table) == 0 )
+ && ( (mfn_to_page(mfns[i])->count_info & PGC_count_mask) <=
max_ref ) )
map[i] = map_domain_page(mfn_x(mfns[i]));
else
map[i] = NULL;
@@ -876,7 +884,9 @@ p2m_pod_zero_check(struct domain *d, uns
_mfn(POPULATE_ON_DEMAND_MFN), 0,
p2m_populate_on_demand);
- if ( (mfn_to_page(mfns[i])->u.inuse.type_info & PGT_count_mask) != 0 )
+ /* See if the page was successfully unmapped. (Allow one refcount
+ * for being allocated to a domain.) */
+ if ( (mfn_to_page(mfns[i])->count_info & PGC_count_mask) > 1 )
{
unmap_domain_page(map[i]);
map[i] = NULL;
@@ -899,8 +909,7 @@ p2m_pod_zero_check(struct domain *d, uns
/* See comment in p2m_pod_zero_check_superpage() re gnttab
* check timing. */
- if ( j < PAGE_SIZE/sizeof(*map[i])
- || gnttab_is_granted(d, gfns[i], 0) )
+ if ( j < PAGE_SIZE/sizeof(*map[i]) )
{
set_p2m_entry(d, gfns[i], mfns[i], 0, types[i]);
continue;
diff -r aa89d1afb287 -r e1352667df95 xen/common/grant_table.c
--- a/xen/common/grant_table.c Thu Jan 29 16:39:56 2009 +0000
+++ b/xen/common/grant_table.c Thu Jan 29 16:40:48 2009 +0000
@@ -111,33 +111,6 @@ static unsigned inline int max_nr_maptra
#define active_entry(t, e) \
((t)->active[(e)/ACGNT_PER_PAGE][(e)%ACGNT_PER_PAGE])
-/* The p2m emergency sweep code should not reclaim a frame that is currenlty
- * grant mapped by another domain. That would involve checking all other
- * domains grant maps, which is impractical. Instead, we check the active
- * grant table for this domain to see if it's been granted. Since this
- * may be called as a result of a grant table op, we can't grab the lock. */
-int
-gnttab_is_granted(struct domain *d, xen_pfn_t gfn, int order)
-{
- int i, found=0;
- struct active_grant_entry *act;
-
- /* We need to compare with active grant entries to make sure that
- * pinned (== currently mapped) entries don't disappear under our
- * feet. */
- for ( i=0; i<nr_grant_entries(d->grant_table); i++ )
- {
- act = &active_entry(d->grant_table, i);
- if ( act->gfn >> order == gfn >> order )
- {
- found = 1;
- break;
- }
- }
-
- return found;
-}
-
static inline int
__get_maptrack_handle(
struct grant_table *t)
diff -r aa89d1afb287 -r e1352667df95 xen/include/xen/grant_table.h
--- a/xen/include/xen/grant_table.h Thu Jan 29 16:39:56 2009 +0000
+++ b/xen/include/xen/grant_table.h Thu Jan 29 16:40:48 2009 +0000
@@ -147,7 +147,4 @@ nr_active_grant_frames(struct grant_tabl
return num_act_frames_from_sha_frames(nr_grant_frames(gt));
}
-int
-gnttab_is_granted(struct domain *d, xen_pfn_t gfn, int order);
-
#endif /* __XEN_GRANT_TABLE_H__ */
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|