]> xenbits.xensource.com Git - people/dariof/xen.git/commitdiff
Sharable/shared pages need to be unshared in responce to a write attempt. This
authorKeir Fraser <keir.fraser@citrix.com>
Thu, 17 Dec 2009 06:27:56 +0000 (06:27 +0000)
committerKeir Fraser <keir.fraser@citrix.com>
Thu, 17 Dec 2009 06:27:56 +0000 (06:27 +0000)
is handled through custom gfn_to_mfn transation functions called from generic
host page table page fault handler. This should handle both SVM and VTX alike.

Signed-off-by: Grzegorz Milos <Grzegorz.Milos@citrix.com>
xen/arch/x86/hvm/hvm.c
xen/include/asm-x86/p2m.h

index 1477099fe1b1f000357009371e24561729762187..4fc1b934883defd01eaf1a216791af65b9dbe7cf 100644 (file)
@@ -1325,12 +1325,14 @@ static void *hvm_map_entry(unsigned long va)
     gfn = paging_gva_to_gfn(current, va, &pfec);
     if ( pfec == PFEC_page_paged )
         return NULL;
-    mfn = mfn_x(gfn_to_mfn_current(gfn, &p2mt));
+    mfn = mfn_x(gfn_to_mfn_unshare(current->domain, gfn, &p2mt, 0));
     if ( p2m_is_paging(p2mt) )
     {
         p2m_mem_paging_populate(current->domain, gfn);
         return NULL;
     }
+    if ( p2m_is_shared(p2mt) )
+        return NULL;
     if ( !p2m_is_ram(p2mt) )
     {
         gdprintk(XENLOG_ERR, "Failed to look up descriptor table entry\n");
@@ -2986,6 +2988,10 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg)
                 rc = -EINVAL;
                 goto param_fail3;
             }
+            if( p2m_is_shared(t) )
+                gdprintk(XENLOG_WARNING,
+                         "shared pfn 0x%lx modified?\n", pfn);
+            
             if ( mfn_x(mfn) != INVALID_MFN )
             {
                 paging_mark_dirty(d, mfn_x(mfn));
@@ -3038,7 +3044,7 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg)
             p2m_type_t t;
             p2m_type_t nt;
             mfn_t mfn;
-            mfn = gfn_to_mfn(d, pfn, &t);
+            mfn = gfn_to_mfn_unshare(d, pfn, &t, 0);
             if ( p2m_is_paging(t) )
             {
                 p2m_mem_paging_populate(d, pfn);
@@ -3046,6 +3052,11 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg)
                 rc = -EINVAL;
                 goto param_fail4;
             }
+            if ( p2m_is_shared(t) )
+            {
+                rc = -EINVAL;
+                goto param_fail4;
+            } 
             if ( p2m_is_grant(t) )
             {
                 gdprintk(XENLOG_WARNING,
index 75afec893a78bc9224bc6c65b5236613086fd6f4..0fb485661f2deb952f49eed329071b84c33f3ed3 100644 (file)
@@ -308,6 +308,31 @@ static inline mfn_t _gfn_to_mfn_type(struct domain *d,
 #define gfn_to_mfn_current(g, t) gfn_to_mfn_type_current((g), (t), p2m_alloc)
 #define gfn_to_mfn_foreign(d, g, t) gfn_to_mfn_type_foreign((d), (g), (t), p2m_alloc)
 
+static inline mfn_t gfn_to_mfn_unshare(struct domain *d,
+                                       unsigned long gfn,
+                                       p2m_type_t *p2mt,
+                                       int must_succeed)
+{
+    mfn_t mfn;
+    int ret;
+
+    mfn = gfn_to_mfn(d, gfn, p2mt);
+    if(p2m_is_shared(*p2mt))
+    {
+        ret = mem_sharing_unshare_page(d, gfn,
+                must_succeed ? MEM_SHARING_MUST_SUCCEED : 0);
+        if(ret < 0)
+        {
+            BUG_ON(must_succeed);
+            return mfn;
+        }
+        mfn = gfn_to_mfn(d, gfn, p2mt);
+    }
+
+    return mfn;
+}
+
+
 /* Compatibility function exporting the old untyped interface */
 static inline unsigned long gmfn_to_mfn(struct domain *d, unsigned long gpfn)
 {