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