WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] Intel EPT: Add page shattering logic for

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] Intel EPT: Add page shattering logic for EPT when a super-page gets partially freed.
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Wed, 21 May 2008 08:20:12 -0700
Delivery-date: Wed, 21 May 2008 08:20:20 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1211364171 -3600
# Node ID ff23c9a11085dce8c5b2e3b692cde86cd87698a7
# Parent  ef019d230080cc1c85a3a9a79c170f898db6be53
Intel EPT: Add page shattering logic for EPT when a super-page gets partially 
freed.

Signed-off-by: Xin Xiaohui <xiaohui.xin@xxxxxxxxx>
---
 xen/arch/x86/mm/hap/p2m-ept.c |  172 +++++++++++++++++++++++++++++-------------
 1 files changed, 120 insertions(+), 52 deletions(-)

diff -r ef019d230080 -r ff23c9a11085 xen/arch/x86/mm/hap/p2m-ept.c
--- a/xen/arch/x86/mm/hap/p2m-ept.c     Wed May 21 10:59:49 2008 +0100
+++ b/xen/arch/x86/mm/hap/p2m-ept.c     Wed May 21 11:02:51 2008 +0100
@@ -49,10 +49,35 @@ static void ept_p2m_type_to_flags(ept_en
 
 #define GUEST_TABLE_NORMAL_PAGE 1
 #define GUEST_TABLE_SUPER_PAGE  2
+#define GUEST_TABLE_SPLIT_PAGE  3
+
+static int ept_set_middle_entry(struct domain *d, ept_entry_t *ept_entry)
+{
+    struct page_info *pg;
+
+    pg = d->arch.p2m->alloc_page(d);
+    if ( pg == NULL )
+        return 0;
+
+    pg->count_info = 1;
+    pg->u.inuse.type_info = 1 | PGT_validated;
+    list_add_tail(&pg->list, &d->arch.p2m->pages);
+
+    ept_entry->emt = 0;
+    ept_entry->sp_avail = 0;
+    ept_entry->avail1 = 0;
+    ept_entry->mfn = page_to_mfn(pg);
+    ept_entry->rsvd = 0;
+    ept_entry->avail2 = 0;
+    /* last step */
+    ept_entry->r = ept_entry->w = ept_entry->x = 1;
+
+    return 1;
+}
 
 static int ept_next_level(struct domain *d, bool_t read_only,
                           ept_entry_t **table, unsigned long *gfn_remainder,
-                          u32 shift)
+                          u32 shift, int order)
 {
     ept_entry_t *ept_entry, *next;
     u32 index;
@@ -63,27 +88,11 @@ static int ept_next_level(struct domain 
 
     if ( !(ept_entry->epte & 0x7) )
     {
-        struct page_info *pg;
-
         if ( read_only )
             return 0;
 
-        pg = d->arch.p2m->alloc_page(d);
-        if ( pg == NULL )
+        if ( !ept_set_middle_entry(d, ept_entry) )
             return 0;
-
-        pg->count_info = 1;
-        pg->u.inuse.type_info = 1 | PGT_validated;
-        list_add_tail(&pg->list, &d->arch.p2m->pages);
-
-        ept_entry->emt = 0;
-        ept_entry->sp_avail = 0;
-        ept_entry->avail1 = 0;
-        ept_entry->mfn = page_to_mfn(pg);
-        ept_entry->rsvd = 0;
-        ept_entry->avail2 = 0;
-        /* last step */
-        ept_entry->r = ept_entry->w = ept_entry->x = 1;
     }
 
     if ( !ept_entry->sp_avail )
@@ -95,7 +104,12 @@ static int ept_next_level(struct domain 
         return GUEST_TABLE_NORMAL_PAGE;
     }
     else
-        return GUEST_TABLE_SUPER_PAGE;
+    {
+        if ( order == shift || read_only )
+            return GUEST_TABLE_SUPER_PAGE;
+        else
+            return GUEST_TABLE_SPLIT_PAGE;
+    }
 }
 
 static int
@@ -109,7 +123,9 @@ ept_set_entry(struct domain *d, unsigned
     int i, rv = 0, ret = 0;
     int walk_level = order / EPT_TABLE_ORDER;
 
-    /* Should check if gfn obeys GAW here */
+    /* we only support 4k and 2m pages now */
+
+    BUG_ON(order && order != EPT_TABLE_ORDER);
 
     if (  order != 0 )
         if ( (gfn & ((1UL << order) - 1)) )
@@ -122,10 +138,10 @@ ept_set_entry(struct domain *d, unsigned
     for ( i = EPT_DEFAULT_GAW; i > walk_level; i-- )
     {
         ret = ept_next_level(d, 0, &table, &gfn_remainder,
-          i * EPT_TABLE_ORDER);
+          i * EPT_TABLE_ORDER, order);
         if ( !ret )
             goto out;
-        else if ( ret == GUEST_TABLE_SUPER_PAGE )
+        else if ( ret != GUEST_TABLE_NORMAL_PAGE )
             break;
     }
 
@@ -135,35 +151,87 @@ ept_set_entry(struct domain *d, unsigned
 
     ept_entry = table + index;
 
-    if ( mfn_valid(mfn_x(mfn)) || (p2mt == p2m_mmio_direct) )
-    {
-        /* Track the highest gfn for which we have ever had a valid mapping */
-        if ( gfn > d->arch.p2m->max_mapped_pfn )
-            d->arch.p2m->max_mapped_pfn = gfn;
-
-        ept_entry->emt = EPT_DEFAULT_MT;
-        ept_entry->sp_avail = walk_level ? 1 : 0;
-
-        if ( ret == GUEST_TABLE_SUPER_PAGE )
-        {
-            ept_entry->mfn = mfn_x(mfn) - offset;
-            if ( ept_entry->avail1 == p2m_ram_logdirty &&
-              p2mt == p2m_ram_rw )
-                for ( i = 0; i < 512; i++ )
-                    paging_mark_dirty(d, mfn_x(mfn)-offset+i);
+    if ( ret != GUEST_TABLE_SPLIT_PAGE )
+    {
+        if ( mfn_valid(mfn_x(mfn)) || (p2mt == p2m_mmio_direct) )
+        {
+            /* Track the highest gfn for which we have ever had a valid 
mapping */
+            if ( gfn > d->arch.p2m->max_mapped_pfn )
+                d->arch.p2m->max_mapped_pfn = gfn;
+
+            ept_entry->emt = EPT_DEFAULT_MT;
+            ept_entry->sp_avail = walk_level ? 1 : 0;
+
+            if ( ret == GUEST_TABLE_SUPER_PAGE )
+            {
+                ept_entry->mfn = mfn_x(mfn) - offset;
+                if ( ept_entry->avail1 == p2m_ram_logdirty &&
+                  p2mt == p2m_ram_rw )
+                    for ( i = 0; i < 512; i++ )
+                        paging_mark_dirty(d, mfn_x(mfn)-offset+i);
+            }
+            else
+                ept_entry->mfn = mfn_x(mfn);
+
+            ept_entry->avail1 = p2mt;
+            ept_entry->rsvd = 0;
+            ept_entry->avail2 = 0;
+            /* last step */
+            ept_entry->r = ept_entry->w = ept_entry->x = 1;
+            ept_p2m_type_to_flags(ept_entry, p2mt);
         }
         else
-            ept_entry->mfn = mfn_x(mfn);
-
-        ept_entry->avail1 = p2mt;
-        ept_entry->rsvd = 0;
-        ept_entry->avail2 = 0;
-        /* last step */
-        ept_entry->r = ept_entry->w = ept_entry->x = 1;
-        ept_p2m_type_to_flags(ept_entry, p2mt);
+            ept_entry->epte = 0;
     }
     else
-        ept_entry->epte = 0;
+    {
+        /* It's super page before, now set one of the 4k pages, so
+         * we should split the 2m page to 4k pages now.
+         */
+
+        ept_entry_t *split_table = NULL;
+        ept_entry_t *split_ept_entry = NULL;
+        unsigned long split_mfn = ept_entry->mfn;
+        p2m_type_t split_p2mt = ept_entry->avail1;
+
+        /* alloc new page for new ept middle level entry which is
+         * before a leaf super entry
+         */
+
+        if ( !ept_set_middle_entry(d, ept_entry) )
+            goto out;
+
+        /* split the super page before to 4k pages */
+
+        split_table = map_domain_page(ept_entry->mfn);
+
+        for ( i = 0; i < 512; i++ )
+        {
+            split_ept_entry = split_table + i;
+            split_ept_entry->emt = EPT_DEFAULT_MT;
+            split_ept_entry->sp_avail =  0;
+
+            split_ept_entry->mfn = split_mfn+i;
+
+            split_ept_entry->avail1 = split_p2mt;
+            split_ept_entry->rsvd = 0;
+            split_ept_entry->avail2 = 0;
+            /* last step */
+            split_ept_entry->r = split_ept_entry->w = split_ept_entry->x = 1;
+            ept_p2m_type_to_flags(split_ept_entry, split_p2mt);
+        }
+
+        /* Set the destinated 4k page as normal */
+
+        offset = gfn & ((1 << EPT_TABLE_ORDER) - 1);
+        split_ept_entry = split_table + offset;
+        split_ept_entry->mfn = mfn_x(mfn);
+        split_ept_entry->avail1 = p2mt;
+        ept_p2m_type_to_flags(split_ept_entry, p2mt);
+
+        unmap_domain_page(split_table);
+
+    }
 
     /* Success */
     rv = 1;
@@ -179,22 +247,22 @@ out:
     {
         if ( p2mt == p2m_ram_rw )
         {
-            if ( ret == GUEST_TABLE_SUPER_PAGE )
+            if ( order == EPT_TABLE_ORDER )
             {
                 for ( i = 0; i < 512; i++ )
                     iommu_map_page(d, gfn-offset+i, mfn_x(mfn)-offset+i);
             }
-            else if ( ret )
+            else if ( !order )
                 iommu_map_page(d, gfn, mfn_x(mfn));
         }
         else
         {
-            if ( ret == GUEST_TABLE_SUPER_PAGE )
+            if ( order == EPT_TABLE_ORDER )
             {
                 for ( i = 0; i < 512; i++ )
                     iommu_unmap_page(d, gfn-offset+i);
             }
-            else if ( ret )
+            else if ( !order )
                 iommu_unmap_page(d, gfn);
         }
     }
@@ -230,7 +298,7 @@ static mfn_t ept_get_entry(struct domain
     for ( i = EPT_DEFAULT_GAW; i > 0; i-- )
     {
         ret = ept_next_level(d, 1, &table, &gfn_remainder,
-                             i * EPT_TABLE_ORDER);
+                             i * EPT_TABLE_ORDER, 0);
         if ( !ret )
             goto out;
         else if ( ret == GUEST_TABLE_SUPER_PAGE )

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] Intel EPT: Add page shattering logic for EPT when a super-page gets partially freed., Xen patchbot-unstable <=