PoD (populate-on-demand) memory 1/9: Add a p2m query type.
authorKeir Fraser <keir.fraser@citrix.com>
Mon, 5 Jan 2009 10:41:48 +0000 (10:41 +0000)
committerKeir Fraser <keir.fraser@citrix.com>
Mon, 5 Jan 2009 10:41:48 +0000 (10:41 +0000)
Signed-off-by: George Dunlap <george.dunlap@eu.citrix.com>
xen/arch/x86/mm/hap/p2m-ept.c
xen/arch/x86/mm/p2m.c
xen/include/asm-x86/guest_pt.h
xen/include/asm-x86/p2m.h

index 689f152261c0b0484ac96c291e40e2a6e67622f5..ba7239e4fadac56e424bf3257d420788cb5d7407 100644 (file)
@@ -274,7 +274,8 @@ out:
 }
 
 /* Read ept p2m entries */
-static mfn_t ept_get_entry(struct domain *d, unsigned long gfn, p2m_type_t *t)
+static mfn_t ept_get_entry(struct domain *d, unsigned long gfn, p2m_type_t *t,
+    p2m_query_t q)
 {
     ept_entry_t *table =
         map_domain_page(mfn_x(pagetable_get_mfn(d->arch.phys_table)));
@@ -359,9 +360,10 @@ static uint64_t ept_get_entry_content(struct domain *d, unsigned long gfn)
     return content;
 }
 
-static mfn_t ept_get_entry_current(unsigned long gfn, p2m_type_t *t)
+static mfn_t ept_get_entry_current(unsigned long gfn, p2m_type_t *t,
+                                   p2m_query_t q)
 {
-    return ept_get_entry(current->domain, gfn, t);
+    return ept_get_entry(current->domain, gfn, t, q);
 }
 
 void ept_change_entry_emt_with_range(struct domain *d, unsigned long start_gfn,
index 72f470dcf18c17b07454cf2ec8d588c7bbb050df..25819adf12c7022e24e8f7451a86d4275996dac2 100644 (file)
@@ -345,7 +345,8 @@ p2m_set_entry(struct domain *d, unsigned long gfn, mfn_t mfn,
 }
 
 static mfn_t
-p2m_gfn_to_mfn(struct domain *d, unsigned long gfn, p2m_type_t *t)
+p2m_gfn_to_mfn(struct domain *d, unsigned long gfn, p2m_type_t *t,
+               p2m_query_t q)
 {
     mfn_t mfn;
     paddr_t addr = ((paddr_t)gfn) << PAGE_SHIFT;
@@ -436,7 +437,8 @@ p2m_gfn_to_mfn(struct domain *d, unsigned long gfn, p2m_type_t *t)
 }
 
 /* Read the current domain's p2m table (through the linear mapping). */
-static mfn_t p2m_gfn_to_mfn_current(unsigned long gfn, p2m_type_t *t)
+static mfn_t p2m_gfn_to_mfn_current(unsigned long gfn, p2m_type_t *t,
+                                    p2m_query_t q)
 {
     mfn_t mfn = _mfn(INVALID_MFN);
     p2m_type_t p2mt = p2m_mmio_dm;
index d44e622ddc3bf4f9526849661a63c56f84cd6d77..16a8b759bfd503ccf2bbcfa391a1913027be2cba 100644 (file)
@@ -49,7 +49,7 @@ gfn_to_paddr(gfn_t gfn)
 
 /* Override gfn_to_mfn to work with gfn_t */
 #undef gfn_to_mfn
-#define gfn_to_mfn(d, g, t) _gfn_to_mfn((d), gfn_x(g), (t))
+#define gfn_to_mfn(d, g, t) _gfn_to_mfn_type((d), gfn_x(g), (t), p2m_alloc)
 
 
 /* Types of the guest's page tables and access functions for them */
index 4909c065910596160b4a014ebaeb2f9350282503..6bdd603853e62e38904a54a282fe6b95689d435c 100644 (file)
@@ -66,6 +66,12 @@ typedef enum {
     p2m_mmio_direct = 5,        /* Read/write mapping of genuine MMIO area */
 } p2m_type_t;
 
+typedef enum {
+    p2m_query = 0,              /* Do not populate a PoD entries      */
+    p2m_alloc = 1,              /* Automatically populate PoD entries */
+    p2m_guest = 2,              /* Guest demand-fault; implies alloc  */
+} p2m_query_t;
+
 /* We use bitmaps and maks to handle groups of types */
 #define p2m_to_mask(_t) (1UL << (_t))
 
@@ -105,9 +111,11 @@ struct p2m_domain {
                                        mfn_t mfn, unsigned int page_order,
                                        p2m_type_t p2mt);
     mfn_t              (*get_entry   )(struct domain *d, unsigned long gfn,
-                                       p2m_type_t *p2mt);
+                                       p2m_type_t *p2mt,
+                                       p2m_query_t q);
     mfn_t              (*get_entry_current)(unsigned long gfn,
-                                            p2m_type_t *p2mt);
+                                            p2m_type_t *p2mt,
+                                            p2m_query_t q);
     void               (*change_entry_type_global)(struct domain *d,
                                                    p2m_type_t ot,
                                                    p2m_type_t nt);
@@ -123,23 +131,26 @@ static inline p2m_type_t p2m_flags_to_type(unsigned long flags)
     return (flags >> 9) & 0x7;
 }
 
-/* Read the current domain's p2m table. */
-static inline mfn_t gfn_to_mfn_current(unsigned long gfn, p2m_type_t *t)
+/* Read the current domain's p2m table.  Do not populate PoD pages. */
+static inline mfn_t gfn_to_mfn_type_current(unsigned long gfn, p2m_type_t *t,
+                                            p2m_query_t q)
 {
-    return current->domain->arch.p2m->get_entry_current(gfn, t);
+    return current->domain->arch.p2m->get_entry_current(gfn, t, q);
 }
 
-/* Read another domain's P2M table, mapping pages as we go */
+/* Read another domain's P2M table, mapping pages as we go.
+ * Do not populate PoD pages. */
 static inline
-mfn_t gfn_to_mfn_foreign(struct domain *d, unsigned long gfn, p2m_type_t *t)
+mfn_t gfn_to_mfn_type_foreign(struct domain *d, unsigned long gfn, p2m_type_t *t,
+                              p2m_query_t q)
 {
-    return d->arch.p2m->get_entry(d, gfn, t);
+    return d->arch.p2m->get_entry(d, gfn, t, q);
 }
 
 /* General conversion function from gfn to mfn */
-#define gfn_to_mfn(d, g, t) _gfn_to_mfn((d), (g), (t))
-static inline mfn_t _gfn_to_mfn(struct domain *d,
-                                unsigned long gfn, p2m_type_t *t)
+static inline mfn_t _gfn_to_mfn_type(struct domain *d,
+                                     unsigned long gfn, p2m_type_t *t,
+                                     p2m_query_t q)
 {
     if ( !paging_mode_translate(d) )
     {
@@ -149,11 +160,18 @@ static inline mfn_t _gfn_to_mfn(struct domain *d,
         return _mfn(gfn);
     }
     if ( likely(current->domain == d) )
-        return gfn_to_mfn_current(gfn, t);
+        return gfn_to_mfn_type_current(gfn, t, q);
     else
-        return gfn_to_mfn_foreign(d, gfn, t);
+        return gfn_to_mfn_type_foreign(d, gfn, t, q);
 }
 
+#define gfn_to_mfn(d, g, t) _gfn_to_mfn_type((d), (g), (t), p2m_alloc)
+#define gfn_to_mfn_query(d, g, t) _gfn_to_mfn_type((d), (g), (t), p2m_query)
+#define gfn_to_mfn_guest(d, g, t) _gfn_to_mfn_type((d), (g), (t), p2m_guest)
+
+#define gfn_to_mfn_current(g, t) gfn_to_mfn_type_current((g), (t), p2m_alloc)
+#define gfn_to_mfn_foreign(d, g, t) gfn_to_mfn_type_foreign((d), (g), (t), p2m_alloc)
+
 /* Compatibility function exporting the old untyped interface */
 static inline unsigned long gmfn_to_mfn(struct domain *d, unsigned long gpfn)
 {