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

[PATCH 7/8] x86/mm: make code robust to future PAT changes



It may be desirable to change Xen's PAT for various reasons.  This
requires changes to several _PAGE_* macros as well.  Add static
assertions to check that XEN_MSR_PAT is consistent with the _PAGE_*
macros.

Additionally, Xen has two unused entries in the PAT.  Currently these
are UC, but this will change if the hardware ever supports additional
memory types.  To avoid future problems, this adds a check in debug
builds that injects #GP into a guest that tries to use one of these
entries, along with returning -EINVAL from the hypercall.  Future
versions of Xen will refuse to use these entries even in release builds.

Signed-off-by: Demi Marie Obenour <demi@xxxxxxxxxxxxxxxxxxxxxx>
---
 xen/arch/x86/mm.c | 58 +++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 54 insertions(+), 4 deletions(-)

diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
index 
5d05399c3a841bf03991a3bed63df9a815c1e891..517fccee699b2a673ba537e47933aefc80017aa5
 100644
--- a/xen/arch/x86/mm.c
+++ b/xen/arch/x86/mm.c
@@ -849,6 +849,45 @@ static int cf_check print_mmio_emul_range(
 }
 #endif
 
+static void __init __maybe_unused build_assertions(void)
+{
+    /* A bunch of static assertions to check that the XEN_MSR_PAT is valid
+     * and consistent with the _PAGE_* macros */
+#define PAT_VALUE(v) (0xFF & (XEN_MSR_PAT >> (8 * (v))))
+#define BAD_VALUE(v) ((v) < 0 || (v) > 7 ||                                    
\
+                      (v) == MSR_PAT_RESERVED_1 || (v) == MSR_PAT_RESERVED_2)
+#define BAD_PAT_VALUE(v) BUILD_BUG_ON(BAD_VALUE(PAT_VALUE(v)))
+    BAD_PAT_VALUE(0);
+    BAD_PAT_VALUE(1);
+    BAD_PAT_VALUE(2);
+    BAD_PAT_VALUE(3);
+    BAD_PAT_VALUE(4);
+    BAD_PAT_VALUE(5);
+    BAD_PAT_VALUE(6);
+    BAD_PAT_VALUE(7);
+#undef BAD_PAT_VALUE
+#undef BAD_VALUE
+#define PAT_SHIFT(page_value) (((page_value) & _PAGE_PAT) >> 5 |               
\
+                               ((page_value) & (_PAGE_PCD | _PAGE_PWT)) >> 3)
+#define CHECK_PAGE_VALUE(page_value) do {                                      
\
+    /* Check that the _PAGE_* macros only use bits from PAGE_CACHE_ATTRS */    
\
+    BUILD_BUG_ON(((_PAGE_##page_value) & PAGE_CACHE_ATTRS) !=                  
\
+                  (_PAGE_##page_value));                                       
\
+    /* Check that the _PAGE_* are consistent with XEN_MSR_PAT */               
\
+    BUILD_BUG_ON(PAT_VALUE(PAT_SHIFT(_PAGE_##page_value)) !=                   
\
+                 (MSR_PAT_##page_value));                                      
\
+} while (0)
+    CHECK_PAGE_VALUE(WT);
+    CHECK_PAGE_VALUE(WB);
+    CHECK_PAGE_VALUE(WC);
+    CHECK_PAGE_VALUE(UC);
+    CHECK_PAGE_VALUE(UCM);
+    CHECK_PAGE_VALUE(WP);
+#undef CHECK_PAGE_VALUE
+#undef PAT_SHIFT
+#undef PAT_VALUE
+}
+
 /*
  * get_page_from_l1e returns:
  *   0  => success (page not present also counts as such)
@@ -961,13 +1000,24 @@ get_page_from_l1e(
 
         switch ( l1f & PAGE_CACHE_ATTRS )
         {
-        case _PAGE_WB:
+        default:
+#ifndef NDEBUG
+            printk(XENLOG_G_WARNING
+                   "d%d: Guest tried to use bad cachability attribute %u for 
MFN %lx\n",
+                   l1e_owner->domain_id, l1f & PAGE_CACHE_ATTRS, mfn);
+            pv_inject_hw_exception(TRAP_gp_fault, 0);
+            return -EINVAL;
+#endif
         case _PAGE_WT:
         case _PAGE_WP:
-            flip |= (l1f & PAGE_CACHE_ATTRS) ^ _PAGE_UC;
+        case _PAGE_WB:
+            /* Force this to be uncachable */
+            return flip | ( (l1f & PAGE_CACHE_ATTRS) ^ _PAGE_UC );
+        case _PAGE_WC:
+        case _PAGE_UC:
+        case _PAGE_UCM:
+            return flip;
         }
-
-        return flip;
     }
 
     if ( unlikely((real_pg_owner != pg_owner) &&
-- 
Sincerely,
Demi Marie Obenour (she/her/hers)
Invisible Things Lab




 


Rackspace

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