# 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
|