[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH] x86/PAE partially linear page table support



>>> Keir Fraser <keir@xxxxxxxxxxxxx> 15.02.07 14:24 >>>
>On 15/2/07 13:08, "Jan Beulich" <jbeulich@xxxxxxxxxx> wrote:
>> But even for the general case - wouldn't it be possible to call
>> relinquish_memory() CONFIG_PAGING_LEVELS-1 times, each time lowering
>> the level of page tables that can be forced invalid by one?
>
>Yeah, this would work. Seems acceptable.

Okay, so here's a second try:

While full linear page table support makes little sense (and would be more
complicated to implement), partial linear page table support is almost identical
to that in non-PAE, and is used (at least) by NetWare.

Of course, the question here is whether this shouldn't be generalized - all
validated page tables (except for top level PAE) could be allowed to be 
installed
at lower levels using the same scheme.

Signed-off-by: Jan Beulich <jbeulich@xxxxxxxxxx>

Index: 2007-02-07/xen/arch/x86/domain.c
===================================================================
--- 2007-02-07.orig/xen/arch/x86/domain.c       2007-02-07 16:27:53.000000000 
+0100
+++ 2007-02-07/xen/arch/x86/domain.c    2007-02-15 15:23:47.000000000 +0100
@@ -1333,7 +1333,8 @@ int hypercall_xlat_continuation(unsigned
 }
 #endif
 
-static void relinquish_memory(struct domain *d, struct list_head *list)
+static void relinquish_memory(struct domain *d, struct list_head *list,
+                              unsigned long type)
 {
     struct list_head *ent;
     struct page_info  *page;
@@ -1362,23 +1363,24 @@ static void relinquish_memory(struct dom
             put_page(page);
 
         /*
-         * Forcibly invalidate base page tables at this point to break circular
-         * 'linear page table' references. This is okay because MMU structures
-         * are not shared across domains and this domain is now dead. Thus base
-         * tables are not in use so a non-zero count means circular reference.
+         * Forcibly invalidate top-most, still valid page tables at this point
+         * to break circular 'linear page table' references. This is okay
+         * because MMU structures are not shared across domains and this domain
+         * is now dead. Thus top-most valid tables are not in use so a non-zero
+         * count means circular reference.
          */
         y = page->u.inuse.type_info;
         for ( ; ; )
         {
             x = y;
             if ( likely((x & (PGT_type_mask|PGT_validated)) !=
-                        (PGT_base_page_table|PGT_validated)) )
+                        (type|PGT_validated)) )
                 break;
 
             y = cmpxchg(&page->u.inuse.type_info, x, x & ~PGT_validated);
             if ( likely(y == x) )
             {
-                free_page_type(page, PGT_base_page_table);
+                free_page_type(page, type);
                 break;
             }
         }
@@ -1476,8 +1478,16 @@ void domain_relinquish_resources(struct 
         destroy_gdt(v);
 
     /* Relinquish every page of memory. */
-    relinquish_memory(d, &d->xenpage_list);
-    relinquish_memory(d, &d->page_list);
+#if CONFIG_PAGING_LEVELS >= 4
+    relinquish_memory(d, &d->xenpage_list, PGT_l4_page_table);
+    relinquish_memory(d, &d->page_list, PGT_l4_page_table);
+#endif
+#if CONFIG_PAGING_LEVELS >= 3
+    relinquish_memory(d, &d->xenpage_list, PGT_l3_page_table);
+    relinquish_memory(d, &d->page_list, PGT_l3_page_table);
+#endif
+    relinquish_memory(d, &d->xenpage_list, PGT_l2_page_table);
+    relinquish_memory(d, &d->page_list, PGT_l2_page_table);
 
     /* Free page used by xen oprofile buffer */
     free_xenoprof_pages(d);
Index: 2007-02-07/xen/arch/x86/mm.c
===================================================================
--- 2007-02-07.orig/xen/arch/x86/mm.c   2007-02-07 16:08:05.000000000 +0100
+++ 2007-02-07/xen/arch/x86/mm.c        2007-02-07 16:31:33.000000000 +0100
@@ -547,7 +547,7 @@ get_linear_pagetable(
             return 0;
 
         /*
-         * Make sure that the mapped frame is an already-validated L2 table. 
+         * Make sure that the mapped frame is an already-validated root table.
          * If so, atomically increment the count (checking for overflow).
          */
         page = mfn_to_page(pfn);
@@ -569,6 +569,51 @@ get_linear_pagetable(
 }
 #endif /* !CONFIG_X86_PAE */
 
+#if defined(CONFIG_X86_PAE) || defined(CONFIG_X86_64)
+static int
+get_l2_linear_pagetable(
+    l2_pgentry_t l2e, unsigned long l2e_pfn, struct domain *d)
+{
+    unsigned long pfn;
+
+    if ( (l2e_get_flags(l2e) & _PAGE_RW) )
+    {
+        MEM_LOG("Attempt to create linear p.t. with write perms");
+        return 0;
+    }
+
+    if ( (pfn = l2e_get_pfn(l2e)) != l2e_pfn )
+    {
+        unsigned long x, y;
+        struct page_info *page;
+
+        /* Make sure the mapped frame belongs to the correct domain. */
+        if ( unlikely(!get_page_from_pagenr(pfn, d)) )
+            return 0;
+
+        /*
+         * Make sure that the mapped frame is an already-validated L2 table.
+         * If so, atomically increment the count (checking for overflow).
+         */
+        page = mfn_to_page(pfn);
+        y = page->u.inuse.type_info;
+        do {
+            x = y;
+            if ( unlikely((x & PGT_count_mask) == PGT_count_mask) ||
+                 unlikely((x & (PGT_type_mask|PGT_validated)) !=
+                          (PGT_l2_page_table|PGT_validated)) )
+            {
+                put_page(page);
+                return 0;
+            }
+        }
+        while ( (y = cmpxchg(&page->u.inuse.type_info, x, x + 1)) != x );
+    }
+
+    return 1;
+}
+#endif /* !CONFIG_X86_PAE */
+
 int
 get_page_from_l1e(
     l1_pgentry_t l1e, struct domain *d)
@@ -645,10 +690,16 @@ get_page_from_l2e(
     }
 
     rc = get_page_and_type_from_pagenr(l2e_get_pfn(l2e), PGT_l1_page_table, d);
-#if CONFIG_PAGING_LEVELS == 2
     if ( unlikely(!rc) )
+    {
+#if CONFIG_PAGING_LEVELS == 2
         rc = get_linear_pagetable(l2e, pfn, d);
+#else
+        if ( (CONFIG_PAGING_LEVELS == 3 || IS_COMPAT(d)) )
+            rc = get_l2_linear_pagetable(l2e, pfn, d);
 #endif
+    }
+
     return rc;
 }
 


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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.