# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1211465294 -3600
# Node ID 2195290728d4774eb86bbd73a6bee07f93d9e44a
# Parent b259eebb0223e58eb9caf88f80b5aae1f12fc394
shadow: check for gfn_to_mfn returning INVALID_MFN
Signed-off-by: Samuel Thibault <samuel.thibault@xxxxxxxxxxxxx>
---
xen/arch/x86/mm/shadow/common.c | 119 ++++++++++++++++++++++------------------
1 files changed, 67 insertions(+), 52 deletions(-)
diff -r b259eebb0223 -r 2195290728d4 xen/arch/x86/mm/shadow/common.c
--- a/xen/arch/x86/mm/shadow/common.c Thu May 22 11:04:02 2008 +0100
+++ b/xen/arch/x86/mm/shadow/common.c Thu May 22 15:08:14 2008 +0100
@@ -2799,8 +2799,11 @@ int shadow_track_dirty_vram(struct domai
if ( !d->dirty_vram )
{
/* Just recount from start. */
- for ( i = begin_pfn; i < end_pfn; i++ )
- flush_tlb |= sh_remove_all_mappings(d->vcpu[0], gfn_to_mfn(d, i,
&t));
+ for ( i = begin_pfn; i < end_pfn; i++ ) {
+ mfn_t mfn = gfn_to_mfn(d, i, &t);
+ if (mfn_x(mfn) != INVALID_MFN)
+ flush_tlb |= sh_remove_all_mappings(d->vcpu[0], mfn);
+ }
gdprintk(XENLOG_INFO, "tracking VRAM %lx - %lx\n", begin_pfn, end_pfn);
@@ -2840,61 +2843,70 @@ int shadow_track_dirty_vram(struct domai
/* Iterate over VRAM to track dirty bits. */
for ( i = 0; i < nr; i++ ) {
mfn_t mfn = gfn_to_mfn(d, begin_pfn + i, &t);
- struct page_info *page = mfn_to_page(mfn);
- u32 count_info = page->u.inuse.type_info & PGT_count_mask;
+ struct page_info *page;
+ u32 count_info;
int dirty = 0;
paddr_t sl1ma = d->dirty_vram->sl1ma[i];
- switch (count_info)
+ if (mfn_x(mfn) == INVALID_MFN)
{
- case 0:
- /* No guest reference, nothing to track. */
- break;
- case 1:
- /* One guest reference. */
- if ( sl1ma == INVALID_PADDR )
+ dirty = 1;
+ }
+ else
+ {
+ page = mfn_to_page(mfn);
+ count_info = page->u.inuse.type_info & PGT_count_mask;
+ switch (count_info)
{
- /* We don't know which sl1e points to this, too bad. */
+ case 0:
+ /* No guest reference, nothing to track. */
+ break;
+ case 1:
+ /* One guest reference. */
+ if ( sl1ma == INVALID_PADDR )
+ {
+ /* We don't know which sl1e points to this, too bad. */
+ dirty = 1;
+ /* TODO: Heuristics for finding the single mapping of
+ * this gmfn */
+ flush_tlb |= sh_remove_all_mappings(d->vcpu[0], mfn);
+ }
+ else
+ {
+ /* Hopefully the most common case: only one mapping,
+ * whose dirty bit we can use. */
+ l1_pgentry_t *sl1e;
+#ifdef __i386__
+ void *sl1p = map_sl1p;
+ unsigned long sl1mfn = paddr_to_pfn(sl1ma);
+
+ if ( sl1mfn != map_mfn ) {
+ if ( map_sl1p )
+ sh_unmap_domain_page(map_sl1p);
+ map_sl1p = sl1p = sh_map_domain_page(_mfn(sl1mfn));
+ map_mfn = sl1mfn;
+ }
+ sl1e = sl1p + (sl1ma & ~PAGE_MASK);
+#else
+ sl1e = maddr_to_virt(sl1ma);
+#endif
+
+ if ( l1e_get_flags(*sl1e) & _PAGE_DIRTY )
+ {
+ dirty = 1;
+ /* Note: this is atomic, so we may clear a
+ * _PAGE_ACCESSED set by another processor. */
+ l1e_remove_flags(*sl1e, _PAGE_DIRTY);
+ flush_tlb = 1;
+ }
+ }
+ break;
+ default:
+ /* More than one guest reference,
+ * we don't afford tracking that. */
dirty = 1;
- /* TODO: Heuristics for finding the single mapping of
- * this gmfn */
- flush_tlb |= sh_remove_all_mappings(d->vcpu[0],
gfn_to_mfn(d, begin_pfn + i, &t));
+ break;
}
- else
- {
- /* Hopefully the most common case: only one mapping,
- * whose dirty bit we can use. */
- l1_pgentry_t *sl1e;
-#ifdef __i386__
- void *sl1p = map_sl1p;
- unsigned long sl1mfn = paddr_to_pfn(sl1ma);
-
- if ( sl1mfn != map_mfn ) {
- if ( map_sl1p )
- sh_unmap_domain_page(map_sl1p);
- map_sl1p = sl1p = sh_map_domain_page(_mfn(sl1mfn));
- map_mfn = sl1mfn;
- }
- sl1e = sl1p + (sl1ma & ~PAGE_MASK);
-#else
- sl1e = maddr_to_virt(sl1ma);
-#endif
-
- if ( l1e_get_flags(*sl1e) & _PAGE_DIRTY )
- {
- dirty = 1;
- /* Note: this is atomic, so we may clear a
- * _PAGE_ACCESSED set by another processor. */
- l1e_remove_flags(*sl1e, _PAGE_DIRTY);
- flush_tlb = 1;
- }
- }
- break;
- default:
- /* More than one guest reference,
- * we don't afford tracking that. */
- dirty = 1;
- break;
}
if ( dirty )
@@ -2916,8 +2928,11 @@ int shadow_track_dirty_vram(struct domai
{
/* was clean for more than two seconds, try to disable guest
* write access */
- for ( i = begin_pfn; i < end_pfn; i++ )
- flush_tlb |= sh_remove_write_access(d->vcpu[0],
gfn_to_mfn(d, i, &t), 1, 0);
+ for ( i = begin_pfn; i < end_pfn; i++ ) {
+ mfn_t mfn = gfn_to_mfn(d, i, &t);
+ if (mfn_x(mfn) != INVALID_MFN)
+ flush_tlb |= sh_remove_write_access(d->vcpu[0], mfn,
1, 0);
+ }
d->dirty_vram->last_dirty = -1;
}
rc = 0;
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|