All of lore.kernel.org
 help / color / mirror / Atom feed
* RE: [PATCH] patch to support super page (2M) with EPT
@ 2008-05-12 12:14 Huang2, Wei
  0 siblings, 0 replies; 14+ messages in thread
From: Huang2, Wei @ 2008-05-12 12:14 UTC (permalink / raw)
  To: Keir Fraser, Xin, Xiaohui, xen-devel

I will re-submit another one today.

-----Original Message-----
From: Keir Fraser <keir.fraser@eu.citrix.com>
Sent: Monday, May 12, 2008 2:03 AM
To: Xin, Xiaohui <xiaohui.xin@intel.com>; Huang2, Wei <Wei.Huang2@amd.com>; xen-devel@lists.xensource.com <xen-devel@lists.xensource.com>
Subject: Re: [Xen-devel][PATCH] patch to support super page (2M) with EPT

Yes, absolutely no need for 4M page support. We do not support the 32-bit non-PAE build target any more.

 -- Keir

On 12/5/08 06:04, "Xin, Xiaohui" <xiaohui.xin@intel.com> wrote:



	Some comments here:
	1) Basically 4M pages allocations is not hardware naturally for EPT, we only use 2M super pages now. 
	I remembered that Keir said that 2M pages allocation is sufficient, and he removed all the pure 32bit support already.
	2)  If we don’t allocate the last 2M area with 4kb pages, the EPT will meet some problem. Xen will set one of the 4k page
	     there to be invalid, logically that means we should invalid the all the 2M page if we allocate it with 2M, and then the 
	     special pages Xen used in the high end of the guest memory can not be used then. May we know how you cope with that?
	 
	Thanks
	Xiaohui
	 
	

	________________________________

	From: xen-devel-bounces@lists.xensource.com [mailto:xen-devel-bounces@lists.xensource.com] On Behalf Of Huang2, Wei
	Sent: Monday, May 12, 2008 12:36 PM
	To: Xin, Xiaohui; xen-devel@lists.xensource.com
	Subject: RE: [Xen-devel][PATCH] patch to support super page (2M) with EPT
	
	This is the latest one I created. Please review it and I will re-submit.
	 
	1.      It includes the patch for p2m-ept.c, directly from your previous patch. 
	
	2.      Xc_hvm_create.c is based on my original approach. It includes support for both 2MB and 4MB pages. Also it considers the case of odd page size (such as 255MB). But I did not allocate the last 2MB area using 4KB  pages. Let me know if it is a big issue.
	
	3.      The rest are pretty similar.
	
	
	Thanks,
	 
	-Wei
	 
	
	From: xen-devel-bounces@lists.xensource.com [mailto:xen-devel-bounces@lists.xensource.com] On Behalf Of Huang2, Wei
	Sent: Sunday, May 11, 2008 3:34 PM
	To: Xin, Xiaohui; xen-devel@lists.xensource.com
	Subject: RE: [Xen-devel][PATCH] patch to support super page (2M) with EPT
	
	Could we work together for a common solution? As far as I can see, it largely overlaps with my super page patch. The major difference is between p2m.c and p2m-ept.c.
	 
	-Wei
	 
	
	From: xen-devel-bounces@lists.xensource.com [mailto:xen-devel-bounces@lists.xensource.com] On Behalf Of Xin, Xiaohui
	Sent: Friday, May 09, 2008 4:11 AM
	To: xen-devel@lists.xensource.com
	Subject: [Xen-devel][PATCH] patch to support super page (2M) with EPT
	
	Attached are the patches to support super page with EPT. We only support 2M size. And shadow may still work fine with 4K pages.
	The patches can be split into 3 parts. Apply order is as attached.
	 
	tool.diff 
	To allocate 2M physical contiguous memory in guest except the first 2M and the last 2M.
	The first 2M covers special memory, and Xen use the last few pages in guest memory to do special things.
	We let them to be 4K pages as normal.
	super_page_common.patch 
	To modify the p2m interfaces by adding an order parameter, such as guest_physmap_add_page(), p2m_set_entry(), etc.
	p2m-ept-file.patch
	           To handle the EPT tables to support super page.            
	 
	 
	Signed-off-by: Xin Xiaohui <xiaohui.xin@intel.com>
	Signed-off-by: Li Xin, B <xin.b.li@intel.com>
	 
	
	 
	
	
________________________________

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

^ permalink raw reply	[flat|nested] 14+ messages in thread
* [PATCH] patch to support super page (2M) with EPT
@ 2008-05-09  9:10 Xin, Xiaohui
  2008-05-11 20:33 ` Huang2, Wei
  0 siblings, 1 reply; 14+ messages in thread
From: Xin, Xiaohui @ 2008-05-09  9:10 UTC (permalink / raw)
  To: xen-devel


[-- Attachment #1.1: Type: text/plain, Size: 835 bytes --]

Attached are the patches to support super page with EPT. We only support
2M size. And shadow may still work fine with 4K pages.

The patches can be split into 3 parts. Apply order is as attached.

 

tool.diff 

To allocate 2M physical contiguous memory in guest except the first 2M
and the last 2M.

The first 2M covers special memory, and Xen use the last few pages in
guest memory to do special things.

We let them to be 4K pages as normal.

super_page_common.patch 

To modify the p2m interfaces by adding an order parameter, such as
guest_physmap_add_page(), p2m_set_entry(), etc.

p2m-ept-file.patch

            To handle the EPT tables to support super page.            

 

 

Signed-off-by: Xin Xiaohui <xiaohui.xin@intel.com>

Signed-off-by: Li Xin, B <xin.b.li@intel.com>

 

 

 


[-- Attachment #1.2: Type: text/html, Size: 5406 bytes --]

[-- Attachment #2: tool.diff --]
[-- Type: application/octet-stream, Size: 2945 bytes --]

diff -r ccbbe6fe5827 tools/libxc/xc_hvm_build.c
--- a/tools/libxc/xc_hvm_build.c	Mon May 05 10:16:58 2008 +0100
+++ b/tools/libxc/xc_hvm_build.c	Fri May 09 01:07:36 2008 +0800
@@ -165,7 +165,7 @@ static int setup_guest(int xc_handle,
     uint32_t *ident_pt;
     struct elf_binary elf;
     uint64_t v_start, v_end;
-    int rc;
+    int rc, left;
     xen_capabilities_info_t caps;
 
     /* An HVM guest must be initialised with at least 2MB memory. */
@@ -213,19 +213,64 @@ static int setup_guest(int xc_handle,
      * Allocate memory for HVM guest, skipping VGA hole 0xA0000-0xC0000.
      * We allocate pages in batches of no more than 2048 to ensure that
      * we can be preempted and hence dom0 remains responsive.
-     */
+     * 1) Allocate 4K pages for the first 2M guest memory;
+     * 2) try to allocate 2M continous pages for the left guest memory
+     *    or use 4K pages;
+     * 3) Since the last page of the guest memory will be dereserved at last,
+     *    we try just allocate 4K pages for the last 2M guest memory.
+     */
+
     rc = xc_domain_memory_populate_physmap(
         xc_handle, dom, 0xa0, 0, 0, &page_array[0x00]);
     cur_pages = 0xc0;
-    while ( (rc == 0) && (nr_pages > cur_pages) )
+
+    if ( rc == 0 )
+        rc = xc_domain_memory_populate_physmap(
+            xc_handle, dom, 0x200-0xc0, 0, 0, &page_array[0xc0]);
+
+    cur_pages = 0x200;
+
+    left = nr_pages - ((nr_pages >> 9 ) << 9 );
+
+    while ( (rc == 0) && ( (left ? nr_pages : (nr_pages - 0x200))  > cur_pages) )
     {
         unsigned long count = nr_pages - cur_pages;
         if ( count > 2048 )
+        {
             count = 2048;
+            rc = xc_domain_memory_populate_physmap(
+                xc_handle, dom, 4, 9, 0, &page_array[cur_pages]);
+            if ( rc != 0 )
+            {
+                PERROR("Cannot allocate more 2M pages for HVM guest.\n");
+                rc = xc_domain_memory_populate_physmap(
+                    xc_handle, dom, count, 0, 0, &page_array[cur_pages]);
+                if ( rc != 0 )
+                {
+                    PERROR("Could not allocate memory for HVM guest.\n");
+                    goto error_out;
+                }
+            }
+        }
+        else
+        {
+            rc = xc_domain_memory_populate_physmap(
+                xc_handle, dom, count, 0, 0, &page_array[cur_pages]);
+
+            if ( rc != 0 )
+            {
+                PERROR("Could not allocate memory for HVM guest.\n");
+                goto error_out;
+            }
+        }
+
+        cur_pages += count;
+    }
+
+    if ( !left )
         rc = xc_domain_memory_populate_physmap(
-            xc_handle, dom, count, 0, 0, &page_array[cur_pages]);
-        cur_pages += count;
-    }
+            xc_handle, dom, nr_pages - cur_pages, 0, 0, &page_array[cur_pages]);
+
     if ( rc != 0 )
     {
         PERROR("Could not allocate memory for HVM guest.\n");

[-- Attachment #3: super_page_common.patch --]
[-- Type: application/octet-stream, Size: 15687 bytes --]

diff -r 26b88953b0c8 xen/arch/ia64/xen/mm.c
--- a/xen/arch/ia64/xen/mm.c	Wed May 07 23:13:22 2008 +0800
+++ b/xen/arch/ia64/xen/mm.c	Thu May 08 00:35:05 2008 +0800
@@ -2415,7 +2415,7 @@ steal_page(struct domain *d, struct page
 
 int
 guest_physmap_add_page(struct domain *d, unsigned long gpfn,
-                       unsigned long mfn)
+                       unsigned long mfn, int order)
 {
     BUG_ON(!mfn_valid(mfn));
     BUG_ON(mfn_to_page(mfn)->count_info != (PGC_allocated | 1));
@@ -2432,7 +2432,7 @@ guest_physmap_add_page(struct domain *d,
 
 void
 guest_physmap_remove_page(struct domain *d, unsigned long gpfn,
-                          unsigned long mfn)
+                          unsigned long mfn, int order)
 {
     BUG_ON(mfn == 0);//XXX
     zap_domain_page_one(d, gpfn << PAGE_SHIFT, 0, mfn);
@@ -2838,7 +2838,7 @@ arch_memory_op(int op, XEN_GUEST_HANDLE(
         if (prev_mfn && mfn_valid(prev_mfn)) {
             if (is_xen_heap_mfn(prev_mfn))
                 /* Xen heap frames are simply unhooked from this phys slot. */
-                guest_physmap_remove_page(d, xatp.gpfn, prev_mfn);
+                guest_physmap_remove_page(d, xatp.gpfn, prev_mfn, 0);
             else
                 /* Normal domain memory is freed, to avoid leaking memory. */
                 guest_remove_page(d, xatp.gpfn);
@@ -2847,10 +2847,10 @@ arch_memory_op(int op, XEN_GUEST_HANDLE(
         /* Unmap from old location, if any. */
         gpfn = get_gpfn_from_mfn(mfn);
         if (gpfn != INVALID_M2P_ENTRY)
-            guest_physmap_remove_page(d, gpfn, mfn);
+            guest_physmap_remove_page(d, gpfn, mfn, 0);
 
         /* Map at new location. */
-        guest_physmap_add_page(d, xatp.gpfn, mfn);
+        guest_physmap_add_page(d, xatp.gpfn, mfn, 0);
 
     out:
         domain_unlock(d);
diff -r 26b88953b0c8 xen/arch/powerpc/mm.c
--- a/xen/arch/powerpc/mm.c	Wed May 07 23:13:22 2008 +0800
+++ b/xen/arch/powerpc/mm.c	Thu May 08 00:35:05 2008 +0800
@@ -591,7 +591,7 @@ void guest_physmap_add_page(
 }
 
 void guest_physmap_remove_page(
-    struct domain *d, unsigned long gpfn, unsigned long mfn)
+    struct domain *d, unsigned long gpfn, unsigned long mfn, int order)
 {
     if (page_get_owner(mfn_to_page(mfn)) != d) {
         printk("Won't unmap foreign MFN 0x%lx for DOM%d\n", mfn, d->domain_id);
diff -r 26b88953b0c8 xen/arch/x86/mm.c
--- a/xen/arch/x86/mm.c	Wed May 07 23:13:22 2008 +0800
+++ b/xen/arch/x86/mm.c	Thu May 08 00:35:05 2008 +0800
@@ -3310,7 +3310,7 @@ long arch_memory_op(int op, XEN_GUEST_HA
         {
             if ( is_xen_heap_mfn(prev_mfn) )
                 /* Xen heap frames are simply unhooked from this phys slot. */
-                guest_physmap_remove_page(d, xatp.gpfn, prev_mfn);
+                guest_physmap_remove_page(d, xatp.gpfn, prev_mfn, 0);
             else
                 /* Normal domain memory is freed, to avoid leaking memory. */
                 guest_remove_page(d, xatp.gpfn);
@@ -3319,10 +3319,10 @@ long arch_memory_op(int op, XEN_GUEST_HA
         /* Unmap from old location, if any. */
         gpfn = get_gpfn_from_mfn(mfn);
         if ( gpfn != INVALID_M2P_ENTRY )
-            guest_physmap_remove_page(d, gpfn, mfn);
+            guest_physmap_remove_page(d, gpfn, mfn, 0);
 
         /* Map at new location. */
-        guest_physmap_add_page(d, xatp.gpfn, mfn);
+        guest_physmap_add_page(d, xatp.gpfn, mfn, 0);
 
         domain_unlock(d);
 
diff -r 26b88953b0c8 xen/arch/x86/mm/p2m.c
--- a/xen/arch/x86/mm/p2m.c	Wed May 07 23:13:22 2008 +0800
+++ b/xen/arch/x86/mm/p2m.c	Thu May 08 01:17:02 2008 +0800
@@ -204,7 +204,7 @@ p2m_next_level(struct domain *d, mfn_t *
 
 // Returns 0 on error (out of memory)
 static int
-p2m_set_entry(struct domain *d, unsigned long gfn, mfn_t mfn, p2m_type_t p2mt)
+p2m_set_entry(struct domain *d, unsigned long gfn, mfn_t mfn, int order, p2m_type_t p2mt)
 {
     // XXX -- this might be able to be faster iff current->domain == d
     mfn_t table_mfn = pagetable_get_mfn(d->arch.phys_table);
@@ -433,9 +433,9 @@ void p2m_change_entry_type_global(struct
 }
 
 static inline
-int set_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn, p2m_type_t p2mt)
-{
-    return d->arch.p2m->set_entry(d, gfn, mfn, p2mt);
+int set_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn, int order, p2m_type_t p2mt)
+{
+    return d->arch.p2m->set_entry(d, gfn, mfn, order, p2mt);
 }
 
 // Allocate a new p2m table for a domain.
@@ -498,7 +498,7 @@ int p2m_alloc_table(struct domain *d,
     P2M_PRINTK("populating p2m table\n");
 
     /* Initialise physmap tables for slot zero. Other code assumes this. */
-    if ( !set_p2m_entry(d, 0, _mfn(INVALID_MFN), p2m_invalid) )
+    if ( !set_p2m_entry(d, 0, _mfn(INVALID_MFN), 0, p2m_invalid) )
         goto error;
 
     /* Copy all existing mappings from the page list and m2p */
@@ -517,7 +517,7 @@ int p2m_alloc_table(struct domain *d,
             (gfn != 0x55555555L)
 #endif
              && gfn != INVALID_M2P_ENTRY
-            && !set_p2m_entry(d, gfn, mfn, p2m_ram_rw) )
+            && !set_p2m_entry(d, gfn, mfn, 0, p2m_ram_rw) )
             goto error;
     }
 
@@ -750,30 +750,32 @@ static void audit_p2m(struct domain *d)
 
 
 static void
-p2m_remove_page(struct domain *d, unsigned long gfn, unsigned long mfn)
+p2m_remove_page(struct domain *d, unsigned long gfn, unsigned long mfn,
+                    int order )
 {
     if ( !paging_mode_translate(d) )
         return;
     P2M_DEBUG("removing gfn=%#lx mfn=%#lx\n", gfn, mfn);
 
-    set_p2m_entry(d, gfn, _mfn(INVALID_MFN), p2m_invalid);
+    set_p2m_entry(d, gfn, _mfn(INVALID_MFN), order, p2m_invalid);
     set_gpfn_from_mfn(mfn, INVALID_M2P_ENTRY);
 }
 
 void
 guest_physmap_remove_page(struct domain *d, unsigned long gfn,
-                          unsigned long mfn)
+                          unsigned long mfn, int order )
 {
     p2m_lock(d->arch.p2m);
     audit_p2m(d);
-    p2m_remove_page(d, gfn, mfn);
+    for ( int i = 0; i < ( 1<< order); i++ )
+        p2m_remove_page(d, gfn+i, mfn+i, order);
     audit_p2m(d);
     p2m_unlock(d->arch.p2m);
 }
 
 int
 guest_physmap_add_entry(struct domain *d, unsigned long gfn,
-                        unsigned long mfn, p2m_type_t t)
+                        unsigned long mfn, int order, p2m_type_t t)
 {
     unsigned long ogfn;
     p2m_type_t ot;
@@ -831,13 +833,13 @@ guest_physmap_add_entry(struct domain *d
             P2M_DEBUG("old gfn=%#lx -> mfn %#lx\n",
                       ogfn , mfn_x(omfn));
             if ( mfn_x(omfn) == mfn )
-                p2m_remove_page(d, ogfn, mfn);
+                p2m_remove_page(d, ogfn, mfn, order);
         }
     }
 
     if ( mfn_valid(_mfn(mfn)) ) 
     {
-        if ( !set_p2m_entry(d, gfn, _mfn(mfn), t) )
+        if ( !set_p2m_entry(d, gfn, _mfn(mfn), order, t) )
             rc = -EINVAL;
         set_gpfn_from_mfn(mfn, gfn);
     }
@@ -845,7 +847,7 @@ guest_physmap_add_entry(struct domain *d
     {
         gdprintk(XENLOG_WARNING, "Adding bad mfn to p2m map (%#lx -> %#lx)\n",
                  gfn, mfn);
-        if ( !set_p2m_entry(d, gfn, _mfn(INVALID_MFN), p2m_invalid) )
+        if ( !set_p2m_entry(d, gfn, _mfn(INVALID_MFN), order, p2m_invalid) )
             rc = -EINVAL;
     }
 
@@ -967,7 +969,7 @@ p2m_type_t p2m_change_type(struct domain
 
     mfn = gfn_to_mfn(d, gfn, &pt);
     if ( pt == ot )
-        set_p2m_entry(d, gfn, mfn, nt);
+        set_p2m_entry(d, gfn, mfn, 0, nt);
 
     p2m_unlock(d->arch.p2m);
 
@@ -991,7 +993,7 @@ set_mmio_p2m_entry(struct domain *d, uns
         set_gpfn_from_mfn(mfn_x(omfn), INVALID_M2P_ENTRY);
     }
 
-    rc = set_p2m_entry(d, gfn, mfn, p2m_mmio_direct);
+    rc = set_p2m_entry(d, gfn, mfn, 0, p2m_mmio_direct);
     if ( 0 == rc )
         gdprintk(XENLOG_ERR,
             "set_mmio_p2m_entry: set_p2m_entry failed! mfn=%08lx\n",
@@ -1015,7 +1017,7 @@ clear_mmio_p2m_entry(struct domain *d, u
             "clear_mmio_p2m_entry: gfn_to_mfn failed! gfn=%08lx\n", gfn);
         return 0;
     }
-    rc = set_p2m_entry(d, gfn, _mfn(INVALID_MFN), 0);
+    rc = set_p2m_entry(d, gfn, _mfn(INVALID_MFN), 0, 0);
 
     return rc;
 }
diff -r 26b88953b0c8 xen/common/grant_table.c
--- a/xen/common/grant_table.c	Wed May 07 23:13:22 2008 +0800
+++ b/xen/common/grant_table.c	Thu May 08 00:35:05 2008 +0800
@@ -1159,7 +1159,7 @@ gnttab_transfer(
         spin_lock(&e->grant_table->lock);
 
         sha = &shared_entry(e->grant_table, gop.ref);
-        guest_physmap_add_page(e, sha->frame, mfn);
+        guest_physmap_add_page(e, sha->frame, mfn, 0);
         sha->frame = mfn;
         wmb();
         sha->flags |= GTF_transfer_completed;
diff -r 26b88953b0c8 xen/common/memory.c
--- a/xen/common/memory.c	Wed May 07 23:13:22 2008 +0800
+++ b/xen/common/memory.c	Thu May 08 00:35:05 2008 +0800
@@ -109,8 +109,11 @@ static void populate_physmap(struct memo
             goto out;
         }
 
-        if ( unlikely(__copy_from_guest_offset(&gpfn, a->extent_list, i, 1)) )
-            goto out;
+        if ( unlikely(__copy_from_guest_offset(&gpfn, a->extent_list, i << a->extent_order, 1)) )
+        {
+            printk("copy_from_guest failed.\n");
+            goto out;
+        }
 
         page = alloc_domheap_pages(
             d, a->extent_order, a->memflags | MEMF_node(node));
@@ -126,11 +129,7 @@ static void populate_physmap(struct memo
         mfn = page_to_mfn(page);
 
         if ( unlikely(paging_mode_translate(d)) )
-        {
-            for ( j = 0; j < (1 << a->extent_order); j++ )
-                if ( guest_physmap_add_page(d, gpfn + j, mfn + j) )
-                    goto out;
-        }
+            guest_physmap_add_page(d, gpfn, mfn, a->extent_order);
         else
         {
             for ( j = 0; j < (1 << a->extent_order); j++ )
@@ -172,7 +171,7 @@ int guest_remove_page(struct domain *d, 
     if ( test_and_clear_bit(_PGC_allocated, &page->count_info) )
         put_page(page);
 
-    guest_physmap_remove_page(d, gmfn, mfn);
+    guest_physmap_remove_page(d, gmfn, mfn, 0);
 
     put_page(page);
 
@@ -419,7 +418,7 @@ static long memory_exchange(XEN_GUEST_HA
             if ( !test_and_clear_bit(_PGC_allocated, &page->count_info) )
                 BUG();
             mfn = page_to_mfn(page);
-            guest_physmap_remove_page(d, mfn_to_gmfn(d, mfn), mfn);
+            guest_physmap_remove_page(d, mfn_to_gmfn(d, mfn), mfn, 0);
             put_page(page);
         }
 
@@ -441,8 +440,7 @@ static long memory_exchange(XEN_GUEST_HA
             if ( unlikely(paging_mode_translate(d)) )
             {
                 /* Ignore failure here. There's nothing we can do. */
-                for ( k = 0; k < (1UL << exch.out.extent_order); k++ )
-                    (void)guest_physmap_add_page(d, gpfn + k, mfn + k);
+                (void)guest_physmap_add_page(d, gpfn, mfn, exch.out.extent_order);
             }
             else
             {
diff -r 26b88953b0c8 xen/include/asm-ia64/grant_table.h
--- a/xen/include/asm-ia64/grant_table.h	Wed May 07 23:13:22 2008 +0800
+++ b/xen/include/asm-ia64/grant_table.h	Thu May 08 00:35:05 2008 +0800
@@ -13,7 +13,7 @@ int replace_grant_host_mapping(unsigned 
 int replace_grant_host_mapping(unsigned long gpaddr, unsigned long mfn, unsigned long new_gpaddr, unsigned int flags);
 
 // for grant transfer
-int guest_physmap_add_page(struct domain *d, unsigned long gpfn, unsigned long mfn);
+int guest_physmap_add_page(struct domain *d, unsigned long gpfn, unsigned long mfn, int order);
 
 /* XXX
  * somewhere appropriate
diff -r 26b88953b0c8 xen/include/asm-ia64/shadow.h
--- a/xen/include/asm-ia64/shadow.h	Wed May 07 23:13:22 2008 +0800
+++ b/xen/include/asm-ia64/shadow.h	Thu May 08 00:35:05 2008 +0800
@@ -40,8 +40,10 @@
  * Utilities to change relationship of gpfn->mfn for designated domain,
  * which is required by gnttab transfer, balloon, device model and etc.
  */
-int guest_physmap_add_page(struct domain *d, unsigned long gpfn, unsigned long mfn);
-void guest_physmap_remove_page(struct domain *d, unsigned long gpfn, unsigned long mfn);
+int guest_physmap_add_page(struct domain *d, unsigned long gpfn, 
+                        unsigned long mfn, int order);
+void guest_physmap_remove_page(struct domain *d, unsigned long gpfn, 
+                        unsigned long mfn, int order);
 
 static inline int
 shadow_mode_enabled(struct domain *d)
diff -r 26b88953b0c8 xen/include/asm-powerpc/mm.h
--- a/xen/include/asm-powerpc/mm.h	Wed May 07 23:13:22 2008 +0800
+++ b/xen/include/asm-powerpc/mm.h	Thu May 08 00:35:05 2008 +0800
@@ -278,9 +278,9 @@ extern int guest_physmap_max_mem_pages(s
 extern int guest_physmap_max_mem_pages(struct domain *d, unsigned long new_max);
 
 extern void guest_physmap_add_page(
-    struct domain *d, unsigned long gpfn, unsigned long mfn);
+    struct domain *d, unsigned long gpfn, unsigned long mfn, int order);
 
 extern void guest_physmap_remove_page(
-    struct domain *d, unsigned long gpfn, unsigned long mfn);
+    struct domain *d, unsigned long gpfn, unsigned long mfn, int order);
 
 #endif
diff -r 26b88953b0c8 xen/include/asm-x86/p2m.h
--- a/xen/include/asm-x86/p2m.h	Wed May 07 23:13:22 2008 +0800
+++ b/xen/include/asm-x86/p2m.h	Thu May 08 19:52:57 2008 +0800
@@ -102,7 +102,7 @@ struct p2m_domain {
     void               (*free_page   )(struct domain *d,
                                        struct page_info *pg);
     int                (*set_entry   )(struct domain *d, unsigned long gfn,
-                                       mfn_t mfn, p2m_type_t p2mt);
+                                       mfn_t mfn, int order, p2m_type_t p2mt);
     mfn_t              (*get_entry   )(struct domain *d, unsigned long gfn,
                                        p2m_type_t *p2mt);
     mfn_t              (*get_entry_current)(unsigned long gfn,
@@ -203,21 +203,32 @@ void p2m_final_teardown(struct domain *d
 
 /* Add a page to a domain's p2m table */
 int guest_physmap_add_entry(struct domain *d, unsigned long gfn,
-                             unsigned long mfn, p2m_type_t t);
+                             unsigned long mfn, int order, p2m_type_t t);
 
 /* Untyped version for RAM only, for compatibility 
  *
  * Return 0 for success
  */
 static inline int guest_physmap_add_page(struct domain *d, unsigned long gfn,
-                                         unsigned long mfn)
-{
-    return guest_physmap_add_entry(d, gfn, mfn, p2m_ram_rw);
+                                         unsigned long mfn, int order)
+{
+    int ret;
+
+    for ( int i = 0; i < (1 << order); i++ )
+    {
+        ret = guest_physmap_add_entry(d, gfn+i, mfn+i, order, p2m_ram_rw);
+        if ( ret != 0 )
+            break;
+    }
+
+    /* TODO: fix exit path when failure */
+
+    return ret;
 }
 
 /* Remove a page from a domain's p2m table */
 void guest_physmap_remove_page(struct domain *d, unsigned long gfn,
-                               unsigned long mfn);
+                               unsigned long mfn, int order);
 
 /* Change types across all p2m entries in a domain */
 void p2m_change_type_global(struct domain *d, p2m_type_t ot, p2m_type_t nt);
diff -r 26b88953b0c8 xen/include/xen/paging.h
--- a/xen/include/xen/paging.h	Wed May 07 23:13:22 2008 +0800
+++ b/xen/include/xen/paging.h	Thu May 08 00:35:05 2008 +0800
@@ -18,8 +18,8 @@
 #else
 
 #define paging_mode_translate(d)              (0)
-#define guest_physmap_add_page(d, p, m)       (0)
-#define guest_physmap_remove_page(d, p, m)    ((void)0)
+#define guest_physmap_add_page(d, p, m, order)       (0)
+#define guest_physmap_remove_page(d, p, m, order)    ((void)0)
 
 #endif
 

[-- Attachment #4: p2m-ept-file.patch --]
[-- Type: application/octet-stream, Size: 9705 bytes --]

diff -r bc9cf015d722 xen/arch/x86/mm/hap/p2m-ept.c
--- a/xen/arch/x86/mm/hap/p2m-ept.c	Fri May 09 01:46:33 2008 +0800
+++ b/xen/arch/x86/mm/hap/p2m-ept.c	Sat May 10 01:16:31 2008 +0800
@@ -20,6 +20,7 @@
 #include <xen/domain_page.h>
 #include <xen/sched.h>
 #include <asm/current.h>
+#include <asm/paging.h>
 #include <asm/types.h>
 #include <asm/domain.h>
 #include <asm/p2m.h>
@@ -46,6 +47,9 @@ static void ept_p2m_type_to_flags(ept_en
     }
 }
 
+#define GUEST_TABLE_NORMAL_PAGE 1
+#define GUEST_TABLE_SUPER_PAGE  2
+
 static int ept_next_level(struct domain *d, bool_t read_only,
                           ept_entry_t **table, unsigned long *gfn_remainder,
                           u32 shift)
@@ -54,7 +58,6 @@ static int ept_next_level(struct domain 
     u32 index;
 
     index = *gfn_remainder >> shift;
-    *gfn_remainder &= (1UL << shift) - 1;
 
     ept_entry = (*table) + index;
 
@@ -83,31 +86,53 @@ static int ept_next_level(struct domain 
         ept_entry->r = ept_entry->w = ept_entry->x = 1;
     }
 
-    next = map_domain_page(ept_entry->mfn);
-    unmap_domain_page(*table);
-    *table = next;
-
-    return 1;
+    if ( !ept_entry->sp_avail )
+    {
+        *gfn_remainder &= (1UL << shift) - 1;
+        next = map_domain_page(ept_entry->mfn);
+        unmap_domain_page(*table);
+        *table = next;
+        return GUEST_TABLE_NORMAL_PAGE;
+    }
+    else
+        return GUEST_TABLE_SUPER_PAGE;
 }
 
 static int
-ept_set_entry(struct domain *d, unsigned long gfn, mfn_t mfn, p2m_type_t p2mt)
-{
-    ept_entry_t *table =
-        map_domain_page(mfn_x(pagetable_get_mfn(d->arch.phys_table)));
-    unsigned long gfn_remainder = gfn;
+ept_set_entry(struct domain *d, unsigned long gfn, mfn_t mfn, int order,
+                p2m_type_t p2mt)
+{
+    ept_entry_t *table = NULL;
+    unsigned long gfn_remainder = gfn, offset = 0;
     ept_entry_t *ept_entry = NULL;
     u32 index;
-    int i, rv = 0;
+    int i, rv = 0, ret = 0;
+    int walk_level = order / EPT_TABLE_ORDER;
 
     /* Should check if gfn obeys GAW here */
 
-    for ( i = EPT_DEFAULT_GAW; i > 0; i-- )
-        if ( !ept_next_level(d, 0, &table, &gfn_remainder,
-                             i * EPT_TABLE_ORDER) )
+    if (  order != 0 )
+        if ( (gfn & ((1UL << order) - 1)) )
+            return 1;
+
+    table = map_domain_page(mfn_x(pagetable_get_mfn(d->arch.phys_table)));
+
+    ASSERT(table != NULL);
+
+    for ( i = EPT_DEFAULT_GAW; i > walk_level; i-- )
+    {
+        ret = ept_next_level(d, 0, &table, &gfn_remainder,
+          i * EPT_TABLE_ORDER);
+        if ( !ret )
             goto out;
-
-    index = gfn_remainder;
+        else if ( ret == GUEST_TABLE_SUPER_PAGE )
+            break;
+    }
+
+    index = gfn_remainder >> ( i ?  (i * EPT_TABLE_ORDER): order);
+    walk_level = ( i ? ( i * EPT_TABLE_ORDER) : order) / EPT_TABLE_ORDER;
+    offset = (gfn_remainder & ( ((1 << (i*EPT_TABLE_ORDER)) - 1)));
+
     ept_entry = table + index;
 
     if ( mfn_valid(mfn_x(mfn)) || (p2mt == p2m_mmio_direct) )
@@ -117,9 +142,20 @@ ept_set_entry(struct domain *d, unsigned
             d->arch.p2m->max_mapped_pfn = gfn;
 
         ept_entry->emt = EPT_DEFAULT_MT;
-        ept_entry->sp_avail = 0;
+        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->mfn = mfn_x(mfn);
         ept_entry->rsvd = 0;
         ept_entry->avail2 = 0;
         /* last step */
@@ -132,14 +168,42 @@ ept_set_entry(struct domain *d, unsigned
     /* Success */
     rv = 1;
 
- out:
+out:
     unmap_domain_page(table);
 
     ept_sync_domain(d);
 
+    /* Now the p2m table is not shared with vt-d page table */
+
+    if ( iommu_enabled && is_hvm_domain(d) )
+    {
+        if ( p2mt == p2m_ram_rw )
+        {
+            if ( ret == GUEST_TABLE_SUPER_PAGE )
+            {
+                for ( i = 0; i < 512; i++ )
+                    iommu_map_page(d, gfn-offset+i, mfn_x(mfn)-offset+i);
+            }
+            else if ( ret )
+                iommu_map_page(d, gfn, mfn_x(mfn));
+        }
+        else
+        {
+            if ( ret == GUEST_TABLE_SUPER_PAGE )
+            {
+                for ( i = 0; i < 512; i++ )
+                    iommu_unmap_page(d, gfn-offset+i);
+            }
+            else if ( ret )
+                iommu_unmap_page(d, gfn);
+        }
+    }
+
+#ifdef P2M_SHARE_WITH_VTD_PAGE_TABLE
     /* If p2m table is shared with vtd page-table. */
     if ( iommu_enabled && is_hvm_domain(d) && (p2mt == p2m_mmio_direct) )
         iommu_flush(d, gfn, (u64*)ept_entry);
+#endif
 
     return rv;
 }
@@ -152,7 +216,7 @@ static mfn_t ept_get_entry(struct domain
     unsigned long gfn_remainder = gfn;
     ept_entry_t *ept_entry;
     u32 index;
-    int i;
+    int i, ret=0;
     mfn_t mfn = _mfn(INVALID_MFN);
 
     *t = p2m_mmio_dm;
@@ -164,17 +228,31 @@ static mfn_t ept_get_entry(struct domain
     /* Should check if gfn obeys GAW here. */
 
     for ( i = EPT_DEFAULT_GAW; i > 0; i-- )
-        if ( !ept_next_level(d, 1, &table, &gfn_remainder,
-                             i * EPT_TABLE_ORDER) )
+    {
+        ret = ept_next_level(d, 1, &table, &gfn_remainder,
+                             i * EPT_TABLE_ORDER);
+        if ( !ret )
             goto out;
-
-    index = gfn_remainder;
+        else if ( ret == GUEST_TABLE_SUPER_PAGE )
+            break;
+    }
+
+    index = gfn_remainder >> ( i * EPT_TABLE_ORDER);
     ept_entry = table + index;
 
     if ( ept_entry->avail1 != p2m_invalid )
     {
         *t = ept_entry->avail1;
         mfn = _mfn(ept_entry->mfn);
+        if ( i )
+        {
+            /* we may meet super pages, and to split into 4k pages
+             * to emulate p2m table
+             */
+            unsigned long split_mfn = 
+              mfn_x(mfn) + (gfn_remainder & ( ((1 << (i*EPT_TABLE_ORDER)) - 1 )));
+            mfn = _mfn(split_mfn);
+        }
     }
 
  out:
@@ -205,33 +283,63 @@ static void ept_change_entry_type_global
     l4e = map_domain_page(mfn_x(pagetable_get_mfn(d->arch.phys_table)));
     for (i4 = 0; i4 < EPT_PAGETABLE_ENTRIES; i4++ )
     {
-        if ( !l4e[i4].epte || l4e[i4].sp_avail )
+        if ( !l4e[i4].epte )
             continue;
-        l3e = map_domain_page(l4e[i4].mfn);
-        for ( i3 = 0; i3 < EPT_PAGETABLE_ENTRIES; i3++ )
-        {
-            if ( !l3e[i3].epte || l3e[i3].sp_avail )
+        if ( !l4e[i4].sp_avail )
+        {
+            l3e = map_domain_page(l4e[i4].mfn);
+            for ( i3 = 0; i3 < EPT_PAGETABLE_ENTRIES; i3++ )
+            {
+                if ( !l3e[i3].epte )
+                    continue;
+                if ( !l3e[i3].sp_avail )
+                {
+                    l2e = map_domain_page(l3e[i3].mfn);
+                    for ( i2 = 0; i2 < EPT_PAGETABLE_ENTRIES; i2++ )
+                    {
+                        if ( !l2e[i2].epte )
+                            continue;
+                        if ( !l2e[i2].sp_avail )
+                        {
+                            l1e = map_domain_page(l2e[i2].mfn);
+                            for ( i1  = 0; i1 < EPT_PAGETABLE_ENTRIES; i1++ )
+                            {
+                                if ( !l1e[i1].epte )
+                                    continue;
+                                if ( l1e[i1].avail1 != ot )
+                                    continue;
+                                l1e[i1].avail1 = nt;
+                                ept_p2m_type_to_flags(l1e+i1, nt);
+                            }
+                            unmap_domain_page(l1e);
+                        }
+                        else
+                        {
+                            if ( l2e[i2].avail1 != ot )
+                                continue;
+                            l2e[i2].avail1 = nt;
+                            ept_p2m_type_to_flags(l2e+i2, nt);
+                        }
+                    }
+                    unmap_domain_page(l2e);
+                }
+                else
+                {
+                    if ( l3e[i3].avail1 != ot )
+                        continue;
+                    l3e[i3].avail1 = nt;
+                    ept_p2m_type_to_flags(l3e+i3, nt);
+                }
+            }
+            unmap_domain_page(l3e);
+        }
+        else
+        {
+            if ( l4e[i4].avail1 != ot )
                 continue;
-            l2e = map_domain_page(l3e[i3].mfn);
-            for ( i2 = 0; i2 < EPT_PAGETABLE_ENTRIES; i2++ )
-            {
-                if ( !l2e[i2].epte || l2e[i2].sp_avail )
-                    continue;
-                l1e = map_domain_page(l2e[i2].mfn);
-                for ( i1  = 0; i1 < EPT_PAGETABLE_ENTRIES; i1++ )
-                {
-                    if ( !l1e[i1].epte )
-                        continue;
-                    if ( l1e[i1].avail1 != ot )
-                        continue;
-                    l1e[i1].avail1 = nt;
-                    ept_p2m_type_to_flags(l1e+i1, nt);
-                }
-                unmap_domain_page(l1e);
-            }
-            unmap_domain_page(l2e);
-        }
-        unmap_domain_page(l3e);
+            l4e[i4].avail1 = nt;
+            ept_p2m_type_to_flags(l4e+i4, nt);
+        }
     }
     unmap_domain_page(l4e);
 

[-- Attachment #5: Type: text/plain, Size: 138 bytes --]

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

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2008-05-14 21:22 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-05-12 12:14 [PATCH] patch to support super page (2M) with EPT Huang2, Wei
  -- strict thread matches above, loose matches on Subject: below --
2008-05-09  9:10 Xin, Xiaohui
2008-05-11 20:33 ` Huang2, Wei
2008-05-12  4:36   ` Huang2, Wei
2008-05-12  5:04     ` Xin, Xiaohui
2008-05-12  7:03       ` Keir Fraser
2008-05-12 17:28         ` Huang2, Wei
2008-05-13  8:46           ` Keir Fraser
2008-05-13 13:36             ` Huang2, Wei
2008-05-13 13:39               ` Li, Xin B
2008-05-13 13:51                 ` Keir Fraser
2008-05-13 15:49                   ` Huang2, Wei
2008-05-14  8:40                     ` Keir Fraser
2008-05-14 21:22                       ` Huang2, Wei

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.