All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] xen: enable EPT A/D bit feature
@ 2012-06-19  6:28 Xudong Hao
  2012-06-19  6:28 ` [PATCH 1/4] xen: Add EPT A/D bits definitions Xudong Hao
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Xudong Hao @ 2012-06-19  6:28 UTC (permalink / raw)
  To: xen-devel; +Cc: keir, xiantao.zhang, JBeulich

Extended Page Tables introduce two bit: access bit and dirty bit, A/D bits
enable VMMs to efficiently implement memory management and page classification
algorithms to optimize VM memory operations.

This series of patches enable EPT dirty bit feature for guest live migration.

PATCH 1/4: Add EPT A/D bits definitions.

PATCH 2/4: Add xen parameter to control A/D bits support, it on by default.

PATCH 3/4: Introduce a log_dirty new function update_dirty_bitmap, which will 
only update the log dirty bitmap, but won't clear the EPT page dirty bit. 
The function is used by live migration peek round with EPT D bit supported.

PATCH 4/4: enable EPT dirty bit for guest live migration.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/4] xen: Add EPT A/D bits definitions
  2012-06-19  6:28 [PATCH 0/4] xen: enable EPT A/D bit feature Xudong Hao
@ 2012-06-19  6:28 ` Xudong Hao
  2012-06-19  6:28 ` [PATCH 2/4] xen: add xen parameter to control A/D bits support Xudong Hao
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 7+ messages in thread
From: Xudong Hao @ 2012-06-19  6:28 UTC (permalink / raw)
  To: xen-devel; +Cc: Haitao Shan, Xudong Hao, keir, xiantao.zhang, JBeulich

Add EPT A/D bits definitions.

Signed-off-by: Haitao Shan<haitao.shan@intel.com>
Signed-off-by: Xudong Hao <xudong.hao@intel.com>
---
 xen/include/asm-x86/hvm/vmx/vmcs.h |    4 +++-
 xen/include/asm-x86/hvm/vmx/vmx.h  |    3 ++-
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/xen/include/asm-x86/hvm/vmx/vmcs.h b/xen/include/asm-x86/hvm/vmx/vmcs.h
index 6100619..c0b9a44 100644
--- a/xen/include/asm-x86/hvm/vmx/vmcs.h
+++ b/xen/include/asm-x86/hvm/vmx/vmcs.h
@@ -62,7 +62,8 @@ struct vmx_domain {
         struct {
             u64 ept_mt :3,
                 ept_wl :3,
-                rsvd   :6,
+                ept_ad :1,
+                rsvd   :5,
                 asr    :52;
         };
         u64 eptp;
@@ -194,6 +195,7 @@ extern bool_t cpu_has_vmx_ins_outs_instr_info;
 #define VMX_EPT_SUPERPAGE_2MB                   0x00010000
 #define VMX_EPT_SUPERPAGE_1GB                   0x00020000
 #define VMX_EPT_INVEPT_INSTRUCTION              0x00100000
+#define VMX_EPT_AD_BITS_SUPPORT                 0x00200000
 #define VMX_EPT_INVEPT_SINGLE_CONTEXT           0x02000000
 #define VMX_EPT_INVEPT_ALL_CONTEXT              0x04000000
 
diff --git a/xen/include/asm-x86/hvm/vmx/vmx.h b/xen/include/asm-x86/hvm/vmx/vmx.h
index accfa3f..416504f 100644
--- a/xen/include/asm-x86/hvm/vmx/vmx.h
+++ b/xen/include/asm-x86/hvm/vmx/vmx.h
@@ -37,7 +37,8 @@ typedef union {
         emt         :   3,  /* bits 5:3 - EPT Memory type */
         ipat        :   1,  /* bit 6 - Ignore PAT memory type */
         sp          :   1,  /* bit 7 - Is this a superpage? */
-        rsvd1       :   2,  /* bits 9:8 - Reserved for future use */
+        a           :   1,  /* bit 8 - Access bit */
+        d           :   1,  /* bit 9 - Dirty bit */
         avail1      :   1,  /* bit 10 - Software available 1 */
         rsvd2_snp   :   1,  /* bit 11 - Used for VT-d snoop control
                                in shared EPT/VT-d usage */
-- 
1.5.5

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/4] xen: add xen parameter to control A/D bits support
  2012-06-19  6:28 [PATCH 0/4] xen: enable EPT A/D bit feature Xudong Hao
  2012-06-19  6:28 ` [PATCH 1/4] xen: Add EPT A/D bits definitions Xudong Hao
@ 2012-06-19  6:28 ` Xudong Hao
  2012-06-19  9:56   ` Jan Beulich
  2012-06-19  6:28 ` [PATCH 3/4] xen: introduce new function update_dirty_bitmap Xudong Hao
  2012-06-19  6:28 ` [PATCH 4/4] xen: enable EPT dirty bit for guest live migration Xudong Hao
  3 siblings, 1 reply; 7+ messages in thread
From: Xudong Hao @ 2012-06-19  6:28 UTC (permalink / raw)
  To: xen-devel; +Cc: Haitao Shan, Xudong Hao, keir, xiantao.zhang, JBeulich

Add xen parameter to control A/D bits support, it on by default.

Signed-off-by: Haitao Shan<haitao.shan@intel.com>
Signed-off-by: Xudong Hao <xudong.hao@intel.com>
---
 xen/arch/x86/hvm/vmx/vmcs.c       |    1 +
 xen/arch/x86/hvm/vmx/vmx.c        |    8 ++++++++
 xen/arch/x86/mm/p2m.c             |    3 +++
 xen/include/asm-x86/hap.h         |    3 +++
 xen/include/asm-x86/hvm/vmx/vmx.h |    3 +++
 5 files changed, 18 insertions(+), 0 deletions(-)

diff --git a/xen/arch/x86/hvm/vmx/vmcs.c b/xen/arch/x86/hvm/vmx/vmcs.c
index 38b5d03..5a6be4c 100644
--- a/xen/arch/x86/hvm/vmx/vmcs.c
+++ b/xen/arch/x86/hvm/vmx/vmcs.c
@@ -85,6 +85,7 @@ static void __init vmx_display_features(void)
     P(cpu_has_vmx_virtualize_apic_accesses, "APIC MMIO access virtualisation");
     P(cpu_has_vmx_tpr_shadow, "APIC TPR shadow");
     P(cpu_has_vmx_ept, "Extended Page Tables (EPT)");
+    P(cpu_has_vmx_ept_ad_bits, "EPT A/D Bits");
     P(cpu_has_vmx_vpid, "Virtual-Processor Identifiers (VPID)");
     P(cpu_has_vmx_vnmi, "Virtual NMI");
     P(cpu_has_vmx_msr_bitmap, "MSR direct-access bitmap");
diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c
index ffb86c1..cb94226 100644
--- a/xen/arch/x86/hvm/vmx/vmx.c
+++ b/xen/arch/x86/hvm/vmx/vmx.c
@@ -37,6 +37,7 @@
 #include <asm/spinlock.h>
 #include <asm/paging.h>
 #include <asm/p2m.h>
+#include <asm/hap.h>
 #include <asm/mem_sharing.h>
 #include <asm/hvm/emulate.h>
 #include <asm/hvm/hvm.h>
@@ -89,6 +90,10 @@ static int vmx_domain_initialise(struct domain *d)
     d->arch.hvm_domain.vmx.ept_control.asr  =
         pagetable_get_pfn(p2m_get_pagetable(p2m_get_hostp2m(d)));
 
+    /* set EPT access and dirty bits support */
+    d->arch.hvm_domain.vmx.ept_control.ept_ad =
+        cpu_has_vmx_ept_ad_bits? 1 : 0;
+
     if ( !zalloc_cpumask_var(&d->arch.hvm_domain.vmx.ept_synced) )
         return -ENOMEM;
 
@@ -1574,6 +1579,9 @@ struct hvm_function_table * __init start_vmx(void)
         if ( cpu_has_vmx_ept_1gb )
             vmx_function_table.hap_capabilities |= HVM_HAP_SUPERPAGE_1GB;
 
+        if ( cpu_has_vmx_ept_ad_bits )
+            hap_has_access_bit = hap_has_dirty_bit = 1;
+
         setup_ept_dump();
     }
 
diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c
index 3cdc417..0a796f3 100644
--- a/xen/arch/x86/mm/p2m.c
+++ b/xen/arch/x86/mm/p2m.c
@@ -46,6 +46,9 @@ boolean_param("hap_1gb", opt_hap_1gb);
 bool_t __read_mostly opt_hap_2mb = 1;
 boolean_param("hap_2mb", opt_hap_2mb);
 
+bool_t __read_mostly opt_hap_ad_bits = 1;
+boolean_param("hap_ad_bits", opt_hap_ad_bits);
+
 /* Printouts */
 #define P2M_PRINTK(_f, _a...)                                \
     debugtrace_printk("p2m: %s(): " _f, __func__, ##_a)
diff --git a/xen/include/asm-x86/hap.h b/xen/include/asm-x86/hap.h
index a2532a4..00d0296 100644
--- a/xen/include/asm-x86/hap.h
+++ b/xen/include/asm-x86/hap.h
@@ -64,6 +64,9 @@ int   hap_track_dirty_vram(struct domain *d,
 
 extern const struct paging_mode *hap_paging_get_mode(struct vcpu *);
 
+extern int hap_has_dirty_bit __read_mostly;
+extern int hap_has_access_bit __read_mostly;
+
 #endif /* XEN_HAP_H */
 
 /*
diff --git a/xen/include/asm-x86/hvm/vmx/vmx.h b/xen/include/asm-x86/hvm/vmx/vmx.h
index 416504f..f552d08 100644
--- a/xen/include/asm-x86/hvm/vmx/vmx.h
+++ b/xen/include/asm-x86/hvm/vmx/vmx.h
@@ -201,6 +201,9 @@ extern u64 vmx_ept_vpid_cap;
     (vmx_ept_vpid_cap & VMX_EPT_SUPERPAGE_2MB)
 #define cpu_has_vmx_ept_invept_single_context   \
     (vmx_ept_vpid_cap & VMX_EPT_INVEPT_SINGLE_CONTEXT)
+extern bool_t opt_hap_ad_bits;
+#define cpu_has_vmx_ept_ad_bits                 \
+    ( opt_hap_ad_bits ? (vmx_ept_vpid_cap & VMX_EPT_AD_BITS_SUPPORT) : 0 )
 
 #define EPT_2MB_SHIFT     16
 #define EPT_1GB_SHIFT     17
-- 
1.5.5

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 3/4] xen: introduce new function update_dirty_bitmap
  2012-06-19  6:28 [PATCH 0/4] xen: enable EPT A/D bit feature Xudong Hao
  2012-06-19  6:28 ` [PATCH 1/4] xen: Add EPT A/D bits definitions Xudong Hao
  2012-06-19  6:28 ` [PATCH 2/4] xen: add xen parameter to control A/D bits support Xudong Hao
@ 2012-06-19  6:28 ` Xudong Hao
  2012-06-19  6:28 ` [PATCH 4/4] xen: enable EPT dirty bit for guest live migration Xudong Hao
  3 siblings, 0 replies; 7+ messages in thread
From: Xudong Hao @ 2012-06-19  6:28 UTC (permalink / raw)
  To: xen-devel; +Cc: Haitao Shan, Xudong Hao, keir, xiantao.zhang, JBeulich

Introduce log_dirty new function update_dirty_bitmap, which will only update the
log dirty bitmap, but won't clear the EPT page dirty bit. The function is used
by live migration peek round with EPT D bit supported.

Set correct p2m type when EPT dirty bit supported.

Signed-off-by: Xudong Hao <xudong.hao@intel.com>
Signed-off-by: Haitao Shan<haitao.shan@intel.com>
---
 xen/arch/x86/mm/hap/hap.c       |   36 +++++++++++++++++++++++++++++++-----
 xen/arch/x86/mm/p2m-pt.c        |    1 +
 xen/arch/x86/mm/p2m.c           |    8 ++++++++
 xen/arch/x86/mm/paging.c        |   32 +++++++++++++++++++-------------
 xen/arch/x86/mm/shadow/common.c |    2 +-
 xen/include/asm-x86/domain.h    |    1 +
 xen/include/asm-x86/hap.h       |    3 +++
 xen/include/asm-x86/p2m.h       |    5 ++++-
 xen/include/asm-x86/paging.h    |    3 ++-
 9 files changed, 70 insertions(+), 21 deletions(-)

diff --git a/xen/arch/x86/mm/hap/hap.c b/xen/arch/x86/mm/hap/hap.c
index 13b4be2..3839273 100644
--- a/xen/arch/x86/mm/hap/hap.c
+++ b/xen/arch/x86/mm/hap/hap.c
@@ -52,6 +52,10 @@
 #undef page_to_mfn
 #define page_to_mfn(_pg) _mfn(__page_to_mfn(_pg))
 
+/* Define whether HW has access and dirty bits seperately */
+int hap_has_dirty_bit __read_mostly = 0;
+int hap_has_access_bit __read_mostly = 0;
+
 /************************************************/
 /*          HAP VRAM TRACKING SUPPORT           */
 /************************************************/
@@ -72,6 +76,7 @@ static int hap_enable_vram_tracking(struct domain *d)
     p2m_change_type_range(d, dirty_vram->begin_pfn, dirty_vram->end_pfn, 
                           p2m_ram_rw, p2m_ram_logdirty);
 
+    /* A TLB flush is needed no matter whether hap dirty bit is supported */
     flush_tlb_mask(d->domain_dirty_cpumask);
     return 0;
 }
@@ -79,19 +84,31 @@ static int hap_enable_vram_tracking(struct domain *d)
 static int hap_disable_vram_tracking(struct domain *d)
 {
     struct sh_dirty_vram *dirty_vram = d->arch.hvm_domain.dirty_vram;
+    p2m_type_t p2mt = p2m_ram_rw;
 
     if ( !dirty_vram )
         return -EINVAL;
 
+    /* With hap dirty bit, p2m type cannot be changed from p2m_ram_logdirty
+     * to p2m_ram_rw when first fault is met. Actually, there is no such
+     * fault occurred.
+     */
+    if ( hap_has_dirty_bit )
+        p2mt = p2m_ram_logdirty;
+
     paging_lock(d);
     d->arch.paging.mode &= ~PG_log_dirty;
     paging_unlock(d);
 
     /* set l1e entries of P2M table with normal mode */
     p2m_change_type_range(d, dirty_vram->begin_pfn, dirty_vram->end_pfn, 
-                          p2m_ram_logdirty, p2m_ram_rw);
+                          p2mt, p2m_ram_rw);
 
-    flush_tlb_mask(d->domain_dirty_cpumask);
+    /* With hap dirty bit, we actually did not change HW sensitive bits
+     * of the P2M tables.
+     */
+    if ( !hap_has_dirty_bit )
+        flush_tlb_mask(d->domain_dirty_cpumask);
     return 0;
 }
 
@@ -113,7 +130,7 @@ static void hap_vram_tracking_init(struct domain *d)
 {
     paging_log_dirty_init(d, hap_enable_vram_tracking,
                           hap_disable_vram_tracking,
-                          hap_clean_vram_tracking);
+                          hap_clean_vram_tracking, NULL);
 }
 
 int hap_track_dirty_vram(struct domain *d,
@@ -216,8 +233,16 @@ static int hap_disable_log_dirty(struct domain *d)
 
 static void hap_clean_dirty_bitmap(struct domain *d)
 {
+    p2m_type_t p2mt = (hap_has_dirty_bit)? p2m_ram_logdirty : p2m_ram_rw;
     /* set l1e entries of P2M table to be read-only. */
-    p2m_change_entry_type_global(d, p2m_ram_rw, p2m_ram_logdirty);
+    p2m_change_entry_type_global(d, p2mt, p2m_ram_logdirty);
+    flush_tlb_mask(d->domain_dirty_cpumask);
+}
+
+static void hap_update_dirty_bitmap(struct domain *d)
+{
+    /* find out dirty page by walking EPT table and update dirty bitmap. */
+    p2m_query_entry_global(d, WALK_EPT_D);
     flush_tlb_mask(d->domain_dirty_cpumask);
 }
 
@@ -234,7 +259,8 @@ void hap_logdirty_init(struct domain *d)
     /* Reinitialize logdirty mechanism */
     paging_log_dirty_init(d, hap_enable_log_dirty,
                           hap_disable_log_dirty,
-                          hap_clean_dirty_bitmap);
+                          hap_clean_dirty_bitmap,
+                          hap_update_dirty_bitmap);
 }
 
 /************************************************/
diff --git a/xen/arch/x86/mm/p2m-pt.c b/xen/arch/x86/mm/p2m-pt.c
index c97cac4..7334167 100644
--- a/xen/arch/x86/mm/p2m-pt.c
+++ b/xen/arch/x86/mm/p2m-pt.c
@@ -1141,6 +1141,7 @@ void p2m_pt_init(struct p2m_domain *p2m)
     p2m->set_entry = p2m_set_entry;
     p2m->get_entry = p2m_gfn_to_mfn;
     p2m->change_entry_type_global = p2m_change_type_global;
+    p2m->query_entry_global = NULL;
     p2m->write_p2m_entry = paging_write_p2m_entry;
 #if P2M_AUDIT
     p2m->audit_p2m = p2m_pt_audit_p2m;
diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c
index 0a796f3..299f6b1 100644
--- a/xen/arch/x86/mm/p2m.c
+++ b/xen/arch/x86/mm/p2m.c
@@ -148,6 +148,15 @@ void p2m_change_entry_type_global(struct domain *d,
     p2m_unlock(p2m);
 }
 
+void p2m_query_entry_global(struct domain *d, int mask)
+{
+    struct p2m_domain *p2m = p2m_get_hostp2m(d);
+    ASSERT(p2m);
+    p2m_lock(p2m);
+    p2m->query_entry_global(p2m, mask);
+    p2m_unlock(p2m);
+}
+
 mfn_t __get_gfn_type_access(struct p2m_domain *p2m, unsigned long gfn,
                     p2m_type_t *t, p2m_access_t *a, p2m_query_t q,
                     unsigned int *page_order, bool_t locked)
diff --git a/xen/arch/x86/mm/paging.c b/xen/arch/x86/mm/paging.c
index ca879f9..12ee552 100644
--- a/xen/arch/x86/mm/paging.c
+++ b/xen/arch/x86/mm/paging.c
@@ -335,9 +335,24 @@ int paging_log_dirty_op(struct domain *d, struct xen_domctl_shadow_op *sc)
     int i4, i3, i2;
 
     domain_pause(d);
-    paging_lock(d);
 
     clean = (sc->op == XEN_DOMCTL_SHADOW_OP_CLEAN);
+    if ( clean )
+    {
+        /* We need to further call clean_dirty_bitmap() functions of specific
+         * paging modes (shadow or hap).  Safe because the domain is paused.
+         * And this call must be made before actually transferring the dirty
+         * bitmap since with HW hap dirty bit support, dirty bitmap is
+         * produced by hooking on this call. */
+        d->arch.paging.log_dirty.clean_dirty_bitmap(d);
+    }
+
+    if ( peek && d->arch.paging.log_dirty.update_dirty_bitmap)
+    {
+        d->arch.paging.log_dirty.update_dirty_bitmap(d);
+    }
+
+    paging_lock(d);
 
     PAGING_DEBUG(LOGDIRTY, "log-dirty %s: dom %u faults=%u dirty=%u\n",
                  (clean) ? "clean" : "peek",
@@ -420,17 +435,6 @@ int paging_log_dirty_op(struct domain *d, struct xen_domctl_shadow_op *sc)
     if ( pages < sc->pages )
         sc->pages = pages;
 
-    paging_unlock(d);
-
-    if ( clean )
-    {
-        /* We need to further call clean_dirty_bitmap() functions of specific
-         * paging modes (shadow or hap).  Safe because the domain is paused. */
-        d->arch.paging.log_dirty.clean_dirty_bitmap(d);
-    }
-    domain_unpause(d);
-    return rv;
-
  out:
     paging_unlock(d);
     domain_unpause(d);
@@ -600,11 +604,13 @@ int paging_log_dirty_range(struct domain *d,
 void paging_log_dirty_init(struct domain *d,
                            int    (*enable_log_dirty)(struct domain *d),
                            int    (*disable_log_dirty)(struct domain *d),
-                           void   (*clean_dirty_bitmap)(struct domain *d))
+                           void   (*clean_dirty_bitmap)(struct domain *d),
+                           void   (*update_dirty_bitmap)(struct domain *d))
 {
     d->arch.paging.log_dirty.enable_log_dirty = enable_log_dirty;
     d->arch.paging.log_dirty.disable_log_dirty = disable_log_dirty;
     d->arch.paging.log_dirty.clean_dirty_bitmap = clean_dirty_bitmap;
+    d->arch.paging.log_dirty.update_dirty_bitmap = update_dirty_bitmap;
 }
 
 /* This function fress log dirty bitmap resources. */
diff --git a/xen/arch/x86/mm/shadow/common.c b/xen/arch/x86/mm/shadow/common.c
index dc245be..f4e7566 100644
--- a/xen/arch/x86/mm/shadow/common.c
+++ b/xen/arch/x86/mm/shadow/common.c
@@ -50,7 +50,7 @@ void shadow_domain_init(struct domain *d, unsigned int domcr_flags)
 
     /* Use shadow pagetables for log-dirty support */
     paging_log_dirty_init(d, shadow_enable_log_dirty, 
-                          shadow_disable_log_dirty, shadow_clean_dirty_bitmap);
+                          shadow_disable_log_dirty, shadow_clean_dirty_bitmap, NULL);
 
 #if (SHADOW_OPTIMIZATIONS & SHOPT_OUT_OF_SYNC)
     d->arch.paging.shadow.oos_active = 0;
diff --git a/xen/include/asm-x86/domain.h b/xen/include/asm-x86/domain.h
index aecee68..22cd0f9 100644
--- a/xen/include/asm-x86/domain.h
+++ b/xen/include/asm-x86/domain.h
@@ -179,6 +179,7 @@ struct log_dirty_domain {
     int            (*enable_log_dirty   )(struct domain *d);
     int            (*disable_log_dirty  )(struct domain *d);
     void           (*clean_dirty_bitmap )(struct domain *d);
+    void           (*update_dirty_bitmap )(struct domain *d);
 };
 
 struct paging_domain {
diff --git a/xen/include/asm-x86/hap.h b/xen/include/asm-x86/hap.h
index 00d0296..efd73cc 100644
--- a/xen/include/asm-x86/hap.h
+++ b/xen/include/asm-x86/hap.h
@@ -31,6 +31,9 @@
 #define HAP_ERROR(_f, _a...)                                          \
     printk("hap error: %s(): " _f, __func__, ##_a)
 
+#define WALK_EPT_UNUSED    0
+#define WALK_EPT_D         2
+
 /************************************************/
 /*          hap domain page mapping             */
 /************************************************/
diff --git a/xen/include/asm-x86/p2m.h b/xen/include/asm-x86/p2m.h
index 63bc7cf..21ed9a5 100644
--- a/xen/include/asm-x86/p2m.h
+++ b/xen/include/asm-x86/p2m.h
@@ -249,7 +249,7 @@ struct p2m_domain {
     void               (*change_entry_type_global)(struct p2m_domain *p2m,
                                                    p2m_type_t ot,
                                                    p2m_type_t nt);
-    
+    void               (*query_entry_global)(struct p2m_domain *p2m, int mask);
     void               (*write_p2m_entry)(struct p2m_domain *p2m,
                                           unsigned long gfn, l1_pgentry_t *p,
                                           mfn_t table_mfn, l1_pgentry_t new,
@@ -506,6 +506,9 @@ int guest_physmap_mark_populate_on_demand(struct domain *d, unsigned long gfn,
 void p2m_change_entry_type_global(struct domain *d, 
                                   p2m_type_t ot, p2m_type_t nt);
 
+/* Query across all p2m entries in a domain */
+void p2m_query_entry_global(struct domain *d, int mask);
+
 /* Change types across a range of p2m entries (start ... end-1) */
 void p2m_change_type_range(struct domain *d, 
                            unsigned long start, unsigned long end,
diff --git a/xen/include/asm-x86/paging.h b/xen/include/asm-x86/paging.h
index c432a97..9d95e51 100644
--- a/xen/include/asm-x86/paging.h
+++ b/xen/include/asm-x86/paging.h
@@ -160,7 +160,8 @@ int paging_log_dirty_disable(struct domain *d);
 void paging_log_dirty_init(struct domain *d,
                            int  (*enable_log_dirty)(struct domain *d),
                            int  (*disable_log_dirty)(struct domain *d),
-                           void (*clean_dirty_bitmap)(struct domain *d));
+                           void (*clean_dirty_bitmap)(struct domain *d),
+                           void (*update_dirty_bitmap)(struct domain *d));
 
 /* mark a page as dirty */
 void paging_mark_dirty(struct domain *d, unsigned long guest_mfn);
-- 
1.5.5

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 4/4] xen: enable EPT dirty bit for guest live migration
  2012-06-19  6:28 [PATCH 0/4] xen: enable EPT A/D bit feature Xudong Hao
                   ` (2 preceding siblings ...)
  2012-06-19  6:28 ` [PATCH 3/4] xen: introduce new function update_dirty_bitmap Xudong Hao
@ 2012-06-19  6:28 ` Xudong Hao
  3 siblings, 0 replies; 7+ messages in thread
From: Xudong Hao @ 2012-06-19  6:28 UTC (permalink / raw)
  To: xen-devel; +Cc: Haitao Shan, Xudong Hao, keir, xiantao.zhang, JBeulich

When p2m type is p2m_ram_logdirty, page should be read/write/execute(d) with EPT
dirty bit support.

When guest live migration with EPT dirty bit support, it does not trigger EPT
violation any longer, we flush dirty bitmap in ept_change_entry_type_page()
function, by walking the EPT page table.

Signed-off-by: Haitao Shan<haitao.shan@intel.com>
Signed-off-by: Xudong Hao <xudong.hao@intel.com>
---
 xen/arch/x86/mm/p2m-ept.c |   50 ++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 47 insertions(+), 3 deletions(-)

diff --git a/xen/arch/x86/mm/p2m-ept.c b/xen/arch/x86/mm/p2m-ept.c
index f373905..e07004d 100644
--- a/xen/arch/x86/mm/p2m-ept.c
+++ b/xen/arch/x86/mm/p2m-ept.c
@@ -24,6 +24,7 @@
 #include <asm/types.h>
 #include <asm/domain.h>
 #include <asm/p2m.h>
+#include <asm/hap.h>
 #include <asm/hvm/vmx/vmx.h>
 #include <asm/hvm/vmx/vmcs.h>
 #include <xen/iommu.h>
@@ -69,6 +70,11 @@ static void ept_p2m_type_to_flags(ept_entry_t *entry, p2m_type_t type, p2m_acces
                                                     entry->mfn);
             break;
         case p2m_ram_logdirty:
+            entry->w = hap_has_dirty_bit;
+            entry->r = entry->x = 1;
+            /* Not necessarily need to clear A bit, but it is safe anyway */
+            entry->a = entry->d = 0;
+            break;
         case p2m_ram_ro:
         case p2m_ram_shared:
             entry->r = entry->x = 1;
@@ -373,6 +379,9 @@ ept_set_entry(struct p2m_domain *p2m, unsigned long gfn, mfn_t mfn,
                 need_modify_vtd_table = 0;
 
             ept_p2m_type_to_flags(&new_entry, p2mt, p2ma);
+
+            if ( old_entry.d && (old_entry.sa_p2mt == p2m_ram_logdirty) )
+                paging_mark_dirty(d, mfn_x(mfn));
         }
 
         atomic_write_ept_entry(ept_entry, new_entry);
@@ -749,7 +758,8 @@ void ept_change_entry_emt_with_range(struct domain *d,
  * quickly enable or diable log-dirty tracking
  */
 static void ept_change_entry_type_page(mfn_t ept_page_mfn, int ept_page_level,
-                                       p2m_type_t ot, p2m_type_t nt)
+                                       p2m_type_t ot, p2m_type_t nt,
+                                       struct domain *d, int mask)
 {
     ept_entry_t e, *epte = map_domain_page(mfn_x(ept_page_mfn));
 
@@ -760,15 +770,33 @@ static void ept_change_entry_type_page(mfn_t ept_page_mfn, int ept_page_level,
 
         if ( (ept_page_level > 0) && !is_epte_superpage(epte + i) )
             ept_change_entry_type_page(_mfn(epte[i].mfn),
-                                       ept_page_level - 1, ot, nt);
+                                       ept_page_level - 1, ot, nt, d, mask);
         else
         {
             e = atomic_read_ept_entry(&epte[i]);
             if ( e.sa_p2mt != ot )
                 continue;
 
+            if ( e.d && (e.sa_p2mt == p2m_ram_logdirty) )
+            {
+                int j, nr_pages;
+                struct p2m_domain *p2m = p2m_get_hostp2m(d);
+                for ( j = 0, nr_pages = 1; j < ept_page_level;
+                      j++, nr_pages *= 512 ) {}
+                for ( j = 0; j < nr_pages; j++ )
+                    paging_mark_dirty(d, e.mfn + j);
+
+                /* split super page to 4k page, so that dirty bitmap can 
+                 * map the dirty page
+                 */
+                if ( !ept_split_super_page(p2m, &e, ept_page_level, 0) )
+                    continue;
+                atomic_write_ept_entry(&epte[i], e);
+            }
             e.sa_p2mt = nt;
             ept_p2m_type_to_flags(&e, nt, e.access);
+            if (!mask)
+                e.a = e.d = 0;
             atomic_write_ept_entry(&epte[i], e);
         }
     }
@@ -786,7 +814,22 @@ static void ept_change_entry_type_global(struct p2m_domain *p2m,
     BUG_ON(p2m_is_grant(ot) || p2m_is_grant(nt));
     BUG_ON(ot != nt && (ot == p2m_mmio_direct || nt == p2m_mmio_direct));
 
-    ept_change_entry_type_page(_mfn(ept_get_asr(d)), ept_get_wl(d), ot, nt);
+    ept_change_entry_type_page(_mfn(ept_get_asr(d)), ept_get_wl(d),
+                               ot, nt, p2m->domain, WALK_EPT_UNUSED);
+
+    ept_sync_domain(d);
+}
+
+static void ept_query_entry_global(struct p2m_domain *p2m, int mask)
+{
+    struct domain *d = p2m->domain;
+    p2m_type_t ot = p2m_ram_logdirty;
+    p2m_type_t nt = p2m_ram_logdirty;
+    if ( ept_get_asr(d) == 0 )
+        return;
+
+    ept_change_entry_type_page(_mfn(ept_get_asr(d)), ept_get_wl(d),
+                               ot, nt, p2m->domain, mask);
 
     ept_sync_domain(d);
 }
@@ -796,6 +839,7 @@ void ept_p2m_init(struct p2m_domain *p2m)
     p2m->set_entry = ept_set_entry;
     p2m->get_entry = ept_get_entry;
     p2m->change_entry_type_global = ept_change_entry_type_global;
+    p2m->query_entry_global = ept_query_entry_global;
     p2m->audit_p2m = NULL;
 }
 
-- 
1.5.5

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/4] xen: add xen parameter to control A/D bits support
  2012-06-19  6:28 ` [PATCH 2/4] xen: add xen parameter to control A/D bits support Xudong Hao
@ 2012-06-19  9:56   ` Jan Beulich
  2012-06-20  1:24     ` Hao, Xudong
  0 siblings, 1 reply; 7+ messages in thread
From: Jan Beulich @ 2012-06-19  9:56 UTC (permalink / raw)
  To: Xudong Hao; +Cc: keir, Haitao Shan, xiantao.zhang, xen-devel

>>> On 19.06.12 at 08:28, Xudong Hao <xudong.hao@intel.com> wrote:
> @@ -1574,6 +1579,9 @@ struct hvm_function_table * __init start_vmx(void)
>          if ( cpu_has_vmx_ept_1gb )
>              vmx_function_table.hap_capabilities |= HVM_HAP_SUPERPAGE_1GB;
>  
> +        if ( cpu_has_vmx_ept_ad_bits )
> +            hap_has_access_bit = hap_has_dirty_bit = 1;

So you're using these flags here, ...

> +
>          setup_ept_dump();
>      }
>  
> --- a/xen/include/asm-x86/hap.h
> +++ b/xen/include/asm-x86/hap.h
> @@ -64,6 +64,9 @@ int   hap_track_dirty_vram(struct domain *d,
>  
>  extern const struct paging_mode *hap_paging_get_mode(struct vcpu *);
>  
> +extern int hap_has_dirty_bit __read_mostly;
> +extern int hap_has_access_bit __read_mostly;

... and you're declaring them here, but I fail to find their definition.
How does the result of applying up to this patch build?

Also, they should clearly be bool_t.

Jan

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/4] xen: add xen parameter to control A/D bits support
  2012-06-19  9:56   ` Jan Beulich
@ 2012-06-20  1:24     ` Hao, Xudong
  0 siblings, 0 replies; 7+ messages in thread
From: Hao, Xudong @ 2012-06-20  1:24 UTC (permalink / raw)
  To: Jan Beulich; +Cc: keir, Shan, Haitao, Zhang, Xiantao, xen-devel

> -----Original Message-----
> From: Jan Beulich [mailto:JBeulich@suse.com]
> Sent: Tuesday, June 19, 2012 5:57 PM
> To: Hao, Xudong
> Cc: Shan, Haitao; Zhang, Xiantao; xen-devel@lists.xen.org; keir@xen.org
> Subject: Re: [PATCH 2/4] xen: add xen parameter to control A/D bits support
> 
> >>> On 19.06.12 at 08:28, Xudong Hao <xudong.hao@intel.com> wrote:
> > @@ -1574,6 +1579,9 @@ struct hvm_function_table * __init
> start_vmx(void)
> >          if ( cpu_has_vmx_ept_1gb )
> >              vmx_function_table.hap_capabilities |=
> HVM_HAP_SUPERPAGE_1GB;
> >
> > +        if ( cpu_has_vmx_ept_ad_bits )
> > +            hap_has_access_bit = hap_has_dirty_bit = 1;
> 
> So you're using these flags here, ...
> 
> > +
> >          setup_ept_dump();
> >      }
> >
> > --- a/xen/include/asm-x86/hap.h
> > +++ b/xen/include/asm-x86/hap.h
> > @@ -64,6 +64,9 @@ int   hap_track_dirty_vram(struct domain *d,
> >
> >  extern const struct paging_mode *hap_paging_get_mode(struct vcpu *);
> >
> > +extern int hap_has_dirty_bit __read_mostly;
> > +extern int hap_has_access_bit __read_mostly;
> 
> ... and you're declaring them here, but I fail to find their definition.
> How does the result of applying up to this patch build?
> 

The definition is in patch 3, I'll move them in this patch.

> Also, they should clearly be bool_t.
> 

Thanks, I'll use type bool_t instead of int.

> Jan

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2012-06-20  1:24 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-06-19  6:28 [PATCH 0/4] xen: enable EPT A/D bit feature Xudong Hao
2012-06-19  6:28 ` [PATCH 1/4] xen: Add EPT A/D bits definitions Xudong Hao
2012-06-19  6:28 ` [PATCH 2/4] xen: add xen parameter to control A/D bits support Xudong Hao
2012-06-19  9:56   ` Jan Beulich
2012-06-20  1:24     ` Hao, Xudong
2012-06-19  6:28 ` [PATCH 3/4] xen: introduce new function update_dirty_bitmap Xudong Hao
2012-06-19  6:28 ` [PATCH 4/4] xen: enable EPT dirty bit for guest live migration Xudong Hao

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.