[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-3.4-testing] x86: Fix mfn/page handling in do_mmuext_op().
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1262179235 0 # Node ID 20158bbae22c36a339d04d2fd70a1074044d31d4 # Parent fff896fccb4ee418986933643d8025cdeb454a4b x86: Fix mfn/page handling in do_mmuext_op(). Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx> xen-unstable changeset: 20723:98c4b2498415 xen-unstable date: Thu Dec 24 15:59:44 2009 +0000 x86: In mmuext_op(), MMUEXT_[UN]PIN_* must respect 'foreigndom'... ... and *only* those subcommands respect 'foreigndom', according to documentation in public header xen.h. Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx> xen-unstable changeset: 20744:bb34d8e578d2 xen-unstable date: Wed Dec 30 13:10:03 2009 +0000 --- xen/arch/x86/mm.c | 100 ++++++++++++++++++++++++++++++------------------------ 1 files changed, 57 insertions(+), 43 deletions(-) diff -r fff896fccb4e -r 20158bbae22c xen/arch/x86/mm.c --- a/xen/arch/x86/mm.c Wed Dec 30 12:53:26 2009 +0000 +++ b/xen/arch/x86/mm.c Wed Dec 30 13:20:35 2009 +0000 @@ -2615,9 +2615,8 @@ int do_mmuext_op( { struct mmuext_op op; int rc = 0, i = 0, okay; - unsigned long mfn = 0, gmfn = 0, type; + unsigned long type; unsigned int done = 0; - struct page_info *page; struct vcpu *curr = current; struct domain *d = curr->domain; @@ -2658,9 +2657,6 @@ int do_mmuext_op( } okay = 1; - gmfn = op.arg1.mfn; - mfn = gmfn_to_mfn(FOREIGNDOM, gmfn); - page = mfn_to_page(mfn); switch ( op.cmd ) { @@ -2681,10 +2677,9 @@ int do_mmuext_op( break; type = PGT_l4_page_table; - pin_page: - rc = xsm_memory_pin_page(d, page); - if ( rc ) - break; + pin_page: { + unsigned long mfn; + struct page_info *page; /* Ignore pinning of invalid paging levels. */ if ( (op.cmd - MMUEXT_PIN_L1_TABLE) > (CONFIG_PAGING_LEVELS - 1) ) @@ -2693,6 +2688,7 @@ int do_mmuext_op( if ( paging_mode_refcounts(FOREIGNDOM) ) break; + mfn = gmfn_to_mfn(FOREIGNDOM, op.arg1.mfn); rc = get_page_and_type_from_pagenr(mfn, type, FOREIGNDOM, 0, 1); okay = !rc; if ( unlikely(!okay) ) @@ -2704,6 +2700,15 @@ int do_mmuext_op( break; } + page = mfn_to_page(mfn); + + if ( (rc = xsm_memory_pin_page(d, page)) != 0 ) + { + put_page_and_type(page); + okay = 0; + break; + } + if ( unlikely(test_and_set_bit(_PGT_pinned, &page->u.inuse.type_info)) ) { @@ -2714,7 +2719,7 @@ int do_mmuext_op( } /* A page is dirtied when its pin status is set. */ - paging_mark_dirty(d, mfn); + paging_mark_dirty(FOREIGNDOM, mfn); /* We can race domain destruction (domain_relinquish_resources). */ if ( unlikely(this_cpu(percpu_mm_info).foreign != NULL) ) @@ -2730,44 +2735,51 @@ int do_mmuext_op( } break; - - case MMUEXT_UNPIN_TABLE: - if ( paging_mode_refcounts(d) ) + } + + case MMUEXT_UNPIN_TABLE: { + unsigned long mfn; + struct page_info *page; + + if ( paging_mode_refcounts(FOREIGNDOM) ) break; - if ( unlikely(!(okay = get_page_from_pagenr(mfn, d))) ) + mfn = gmfn_to_mfn(FOREIGNDOM, op.arg1.mfn); + if ( unlikely(!(okay = get_page_from_pagenr(mfn, FOREIGNDOM))) ) { - MEM_LOG("Mfn %lx bad domain (dom=%p)", - mfn, page_get_owner(page)); + MEM_LOG("Mfn %lx bad domain", mfn); + break; } - else if ( likely(test_and_clear_bit(_PGT_pinned, - &page->u.inuse.type_info)) ) - { - put_page_and_type(page); - put_page(page); - if ( !rc ) - { - /* A page is dirtied when its pin status is cleared. */ - paging_mark_dirty(d, mfn); - } - } - else + + page = mfn_to_page(mfn); + + if ( !test_and_clear_bit(_PGT_pinned, &page->u.inuse.type_info) ) { okay = 0; put_page(page); MEM_LOG("Mfn %lx not pinned", mfn); + break; } + + put_page_and_type(page); + put_page(page); + + /* A page is dirtied when its pin status is cleared. */ + paging_mark_dirty(FOREIGNDOM, mfn); + break; + } case MMUEXT_NEW_BASEPTR: - okay = new_guest_cr3(mfn); + okay = new_guest_cr3(gmfn_to_mfn(d, op.arg1.mfn)); this_cpu(percpu_mm_info).deferred_ops &= ~DOP_FLUSH_TLB; break; #ifdef __x86_64__ case MMUEXT_NEW_USER_BASEPTR: { - unsigned long old_mfn; - + unsigned long old_mfn, mfn; + + mfn = gmfn_to_mfn(d, op.arg1.mfn); if ( mfn != 0 ) { if ( paging_mode_refcounts(d) ) @@ -2877,12 +2889,13 @@ int do_mmuext_op( break; } - case MMUEXT_CLEAR_PAGE: - { + case MMUEXT_CLEAR_PAGE: { + unsigned long mfn; unsigned char *ptr; - okay = !get_page_and_type_from_pagenr(mfn, PGT_writable_page, - FOREIGNDOM, 0, 0); + mfn = gmfn_to_mfn(d, op.arg1.mfn); + okay = !get_page_and_type_from_pagenr( + mfn, PGT_writable_page, d, 0, 0); if ( unlikely(!okay) ) { MEM_LOG("Error while clearing mfn %lx", mfn); @@ -2896,7 +2909,7 @@ int do_mmuext_op( clear_page(ptr); fixunmap_domain_page(ptr); - put_page_and_type(page); + put_page_and_type(mfn_to_page(mfn)); break; } @@ -2904,18 +2917,19 @@ int do_mmuext_op( { const unsigned char *src; unsigned char *dst; - unsigned long src_mfn; - - src_mfn = gmfn_to_mfn(FOREIGNDOM, op.arg2.src_mfn); - okay = get_page_from_pagenr(src_mfn, FOREIGNDOM); + unsigned long src_mfn, mfn; + + src_mfn = gmfn_to_mfn(d, op.arg2.src_mfn); + okay = get_page_from_pagenr(src_mfn, d); if ( unlikely(!okay) ) { MEM_LOG("Error while copying from mfn %lx", src_mfn); break; } - okay = !get_page_and_type_from_pagenr(mfn, PGT_writable_page, - FOREIGNDOM, 0, 0); + mfn = gmfn_to_mfn(d, op.arg1.mfn); + okay = !get_page_and_type_from_pagenr( + mfn, PGT_writable_page, d, 0, 0); if ( unlikely(!okay) ) { put_page(mfn_to_page(src_mfn)); @@ -2932,7 +2946,7 @@ int do_mmuext_op( fixunmap_domain_page(dst); unmap_domain_page(src); - put_page_and_type(page); + put_page_and_type(mfn_to_page(mfn)); put_page(mfn_to_page(src_mfn)); break; } _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |