diff options
author | Keir Fraser <keir.fraser@citrix.com> | 2008-07-29 10:05:32 +0100 |
---|---|---|
committer | Keir Fraser <keir.fraser@citrix.com> | 2008-07-29 10:05:32 +0100 |
commit | 06efa7c66478852d5b3d135a2b2cbf1e2c4020c9 (patch) | |
tree | 0087c1c2c0c89d2fcfd61e3a136b6c85fa048cfb | |
parent | 043521fecd43f5891ebed26609b6a4dd05f0626e (diff) | |
download | xen-06efa7c66478852d5b3d135a2b2cbf1e2c4020c9.tar.gz xen-06efa7c66478852d5b3d135a2b2cbf1e2c4020c9.tar.bz2 xen-06efa7c66478852d5b3d135a2b2cbf1e2c4020c9.zip |
x86: fix a few page table handling issues
- adjust_guest_l?e() shouldn't be called on non-guest entries
- unadjust_guest_l3e() should be called in the back-out loop of
alloc_l3_table()
- create_pae_xen_mappings() and pae_flush_pgd() shouldn't be called in
the failure case of mod_l3_entry()
Signed-off-by: Jan Beulich <jbeulich@novell.com>
-rw-r--r-- | xen/arch/x86/mm.c | 36 |
1 files changed, 24 insertions, 12 deletions
diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index afe4d965d6..9aa18a9c3c 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -1138,8 +1138,10 @@ static int alloc_l2_table(struct page_info *page, unsigned long type) for ( i = 0; i < L2_PAGETABLE_ENTRIES; i++ ) { - if ( is_guest_l2_slot(d, type, i) && - unlikely(!get_page_from_l2e(pl2e[i], pfn, d)) ) + if ( !is_guest_l2_slot(d, type, i) ) + continue; + + if ( unlikely(!get_page_from_l2e(pl2e[i], pfn, d)) ) goto fail; adjust_guest_l2e(pl2e[i], d); @@ -1206,8 +1208,9 @@ static int alloc_l3_table(struct page_info *page) d) ) goto fail; } - else if ( is_guest_l3_slot(i) && - unlikely(!get_page_from_l3e(pl3e[i], pfn, d)) ) + else if ( !is_guest_l3_slot(i) ) + continue; + else if ( unlikely(!get_page_from_l3e(pl3e[i], pfn, d)) ) goto fail; adjust_guest_l3e(pl3e[i], d); @@ -1222,8 +1225,12 @@ static int alloc_l3_table(struct page_info *page) fail: MEM_LOG("Failure in alloc_l3_table: entry %d", i); while ( i-- > 0 ) - if ( is_guest_l3_slot(i) ) - put_page_from_l3e(pl3e[i], pfn); + { + if ( !is_guest_l3_slot(i) ) + continue; + unadjust_guest_l3e(pl3e[i], d); + put_page_from_l3e(pl3e[i], pfn); + } unmap_domain_page(pl3e); return 0; @@ -1242,8 +1249,10 @@ static int alloc_l4_table(struct page_info *page) for ( i = 0; i < L4_PAGETABLE_ENTRIES; i++ ) { - if ( is_guest_l4_slot(d, i) && - unlikely(!get_page_from_l4e(pl4e[i], pfn, d)) ) + if ( !is_guest_l4_slot(d, i) ) + continue; + + if ( unlikely(!get_page_from_l4e(pl4e[i], pfn, d)) ) goto fail; adjust_guest_l4e(pl4e[i], d); @@ -1585,7 +1594,7 @@ static int mod_l3_entry(l3_pgentry_t *pl3e, struct vcpu *curr = current; struct domain *d = curr->domain; struct page_info *l3pg = mfn_to_page(pfn); - int okay, rc = 1; + int rc = 1; if ( unlikely(!is_guest_l3_slot(pgentry_ptr_to_slot(pl3e))) ) { @@ -1642,10 +1651,13 @@ static int mod_l3_entry(l3_pgentry_t *pl3e, return 0; } - okay = create_pae_xen_mappings(d, pl3e); - BUG_ON(!okay); + if ( likely(rc) ) + { + if ( !create_pae_xen_mappings(d, pl3e) ) + BUG(); - pae_flush_pgd(pfn, pgentry_ptr_to_slot(pl3e), nl3e); + pae_flush_pgd(pfn, pgentry_ptr_to_slot(pl3e), nl3e); + } page_unlock(l3pg); put_page_from_l3e(ol3e, pfn); |