# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxxxx
# Node ID 09d9d6e7b9851cfb2206395ced55b4769e164b4a
# Parent 25483d9b55d4307d125f4135b609a6387f247ba8
Fix MMU_NORMAL_PT_UPDATE when passed a page that is no longer of type
page-table.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
xen/arch/x86/mm.c | 101 ++++++++++++++++++++++++------------------------------
1 files changed, 45 insertions(+), 56 deletions(-)
diff -r 25483d9b55d4 -r 09d9d6e7b985 xen/arch/x86/mm.c
--- a/xen/arch/x86/mm.c Wed May 31 16:07:47 2006 -0600
+++ b/xen/arch/x86/mm.c Thu Jun 01 10:34:21 2006 +0100
@@ -2213,99 +2213,88 @@ int do_mmu_update(
switch ( (type_info = page->u.inuse.type_info) & PGT_type_mask )
{
- case PGT_l1_page_table:
- ASSERT( !shadow_mode_refcounts(d) );
- if ( likely(get_page_type(
+ case PGT_l1_page_table:
+ case PGT_l2_page_table:
+ case PGT_l3_page_table:
+ case PGT_l4_page_table:
+ {
+ ASSERT(!shadow_mode_refcounts(d));
+ if ( unlikely(!get_page_type(
page, type_info & (PGT_type_mask|PGT_va_mask))) )
+ goto not_a_pt;
+
+ switch ( type_info & PGT_type_mask )
{
- l1_pgentry_t l1e;
-
- /* FIXME: doesn't work with PAE */
- l1e = l1e_from_intpte(req.val);
+ case PGT_l1_page_table:
+ {
+ l1_pgentry_t l1e = l1e_from_intpte(req.val);
okay = mod_l1_entry(va, l1e);
if ( okay && unlikely(shadow_mode_enabled(d)) )
shadow_l1_normal_pt_update(
d, req.ptr, l1e, &sh_mapcache);
- put_page_type(page);
}
break;
- case PGT_l2_page_table:
- ASSERT( !shadow_mode_refcounts(d) );
- if ( likely(get_page_type(
- page, type_info & (PGT_type_mask|PGT_va_mask))) )
+ case PGT_l2_page_table:
{
- l2_pgentry_t l2e;
-
- /* FIXME: doesn't work with PAE */
- l2e = l2e_from_intpte(req.val);
+ l2_pgentry_t l2e = l2e_from_intpte(req.val);
okay = mod_l2_entry(
(l2_pgentry_t *)va, l2e, mfn, type_info);
if ( okay && unlikely(shadow_mode_enabled(d)) )
shadow_l2_normal_pt_update(
d, req.ptr, l2e, &sh_mapcache);
- put_page_type(page);
}
break;
#if CONFIG_PAGING_LEVELS >= 3
- case PGT_l3_page_table:
- ASSERT( !shadow_mode_refcounts(d) );
- if ( likely(get_page_type(
- page, type_info & (PGT_type_mask|PGT_va_mask))) )
+ case PGT_l3_page_table:
{
- l3_pgentry_t l3e;
-
- /* FIXME: doesn't work with PAE */
- l3e = l3e_from_intpte(req.val);
+ l3_pgentry_t l3e = l3e_from_intpte(req.val);
okay = mod_l3_entry(va, l3e, mfn, type_info);
if ( okay && unlikely(shadow_mode_enabled(d)) )
shadow_l3_normal_pt_update(
d, req.ptr, l3e, &sh_mapcache);
- put_page_type(page);
}
break;
#endif
#if CONFIG_PAGING_LEVELS >= 4
- case PGT_l4_page_table:
- ASSERT( !shadow_mode_refcounts(d) );
- if ( likely(get_page_type(
- page, type_info & (PGT_type_mask|PGT_va_mask))) )
+ case PGT_l4_page_table:
{
- l4_pgentry_t l4e;
-
- l4e = l4e_from_intpte(req.val);
+ l4_pgentry_t l4e = l4e_from_intpte(req.val);
okay = mod_l4_entry(va, l4e, mfn, type_info);
if ( okay && unlikely(shadow_mode_enabled(d)) )
shadow_l4_normal_pt_update(
d, req.ptr, l4e, &sh_mapcache);
- put_page_type(page);
}
break;
#endif
+ }
+
+ put_page_type(page);
+ }
+ break;
+
default:
- if ( likely(get_page_type(page, PGT_writable_page)) )
+ not_a_pt:
+ {
+ if ( unlikely(!get_page_type(page, PGT_writable_page)) )
+ break;
+
+ if ( shadow_mode_enabled(d) )
{
- if ( shadow_mode_enabled(d) )
- {
- shadow_lock(d);
-
- __mark_dirty(d, mfn);
-
- if ( page_is_page_table(page) &&
- !page_out_of_sync(page) )
- {
- shadow_mark_mfn_out_of_sync(v, gmfn, mfn);
- }
- }
-
- *(intpte_t *)va = req.val;
- okay = 1;
-
- if ( shadow_mode_enabled(d) )
- shadow_unlock(d);
-
- put_page_type(page);
+ shadow_lock(d);
+ __mark_dirty(d, mfn);
+ if ( page_is_page_table(page) && !page_out_of_sync(page) )
+ shadow_mark_mfn_out_of_sync(v, gmfn, mfn);
}
- break;
+
+ *(intpte_t *)va = req.val;
+ okay = 1;
+
+ if ( shadow_mode_enabled(d) )
+ shadow_unlock(d);
+
+ put_page_type(page);
+ }
+ break;
}
unmap_domain_page_with_cache(va, &mapcache);
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|