84 lines
2.5 KiB
Diff
84 lines
2.5 KiB
Diff
|
Index: 2007-01-31/xen/arch/x86/mm.c
|
||
|
===================================================================
|
||
|
--- 2007-01-31.orig/xen/arch/x86/mm.c 2007-01-31 09:43:38.000000000 +0100
|
||
|
+++ 2007-01-31/xen/arch/x86/mm.c 2007-02-02 16:34:03.000000000 +0100
|
||
|
@@ -509,7 +509,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);
|
||
|
@@ -531,6 +531,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)
|
||
|
@@ -607,10 +652,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;
|
||
|
}
|
||
|
|