WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] MTRR virtualization for Intel EPT

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] MTRR virtualization for Intel EPT
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Mon, 07 Jul 2008 10:40:08 -0700
Delivery-date: Mon, 07 Jul 2008 10:39:54 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1215423950 -3600
# Node ID 9b35ae586cb8587186f08be9acff2b76024ae65e
# Parent  abd84464c09c1a43f3c756bdc7934ea9e99f375a
MTRR virtualization for Intel EPT
Signed-off-by: Xiaohui Xin <xiaohui.xin@xxxxxxxxx>
---
 xen/arch/x86/hvm/hvm.c            |   19 ++++---
 xen/arch/x86/hvm/mtrr.c           |   27 ++++++++++
 xen/arch/x86/hvm/vmx/vmx.c        |   11 ++++
 xen/arch/x86/mm/hap/p2m-ept.c     |   95 ++++++++++++++++++++++++++++++++++----
 xen/include/asm-x86/hvm/hvm.h     |    1 
 xen/include/asm-x86/hvm/vmx/vmx.h |    4 +
 xen/include/asm-x86/mtrr.h        |    3 +
 7 files changed, 143 insertions(+), 17 deletions(-)

diff -r abd84464c09c -r 9b35ae586cb8 xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c    Mon Jul 07 10:29:56 2008 +0100
+++ b/xen/arch/x86/hvm/hvm.c    Mon Jul 07 10:45:50 2008 +0100
@@ -836,6 +836,14 @@ static void local_flush_cache(void *info
     wbinvd();
 }
 
+static void hvm_set_uc_mode(struct vcpu *v, bool_t is_in_uc_mode)
+{
+    v->domain->arch.hvm_domain.is_in_uc_mode = is_in_uc_mode;
+    shadow_blow_tables_per_domain(v->domain);
+    if ( hvm_funcs.set_uc_mode )
+        return hvm_funcs.set_uc_mode(v);
+}
+
 int hvm_set_cr0(unsigned long value)
 {
     struct vcpu *v = current;
@@ -923,9 +931,7 @@ int hvm_set_cr0(unsigned long value)
             {
                 /* Flush physical caches. */
                 on_each_cpu(local_flush_cache, NULL, 1, 1);
-                /* Shadow pagetables must recognise UC mode. */
-                v->domain->arch.hvm_domain.is_in_uc_mode = 1;
-                shadow_blow_tables_per_domain(v->domain);
+                hvm_set_uc_mode(v, 1);
             }
             spin_unlock(&v->domain->arch.hvm_domain.uc_lock);
         }
@@ -937,11 +943,8 @@ int hvm_set_cr0(unsigned long value)
             v->arch.hvm_vcpu.cache_mode = NORMAL_CACHE_MODE;
 
             if ( domain_exit_uc_mode(v) )
-            {
-                /* Shadow pagetables must recognise normal caching mode. */
-                v->domain->arch.hvm_domain.is_in_uc_mode = 0;
-                shadow_blow_tables_per_domain(v->domain);
-            }
+                hvm_set_uc_mode(v, 0);
+
             spin_unlock(&v->domain->arch.hvm_domain.uc_lock);
         }
     }
diff -r abd84464c09c -r 9b35ae586cb8 xen/arch/x86/hvm/mtrr.c
--- a/xen/arch/x86/hvm/mtrr.c   Mon Jul 07 10:29:56 2008 +0100
+++ b/xen/arch/x86/hvm/mtrr.c   Mon Jul 07 10:45:50 2008 +0100
@@ -696,3 +696,30 @@ static int hvm_load_mtrr_msr(struct doma
 
 HVM_REGISTER_SAVE_RESTORE(MTRR, hvm_save_mtrr_msr, hvm_load_mtrr_msr,
                           1, HVMSR_PER_VCPU);
+
+uint8_t epte_get_entry_emt(
+    struct domain *d, unsigned long gfn, unsigned long mfn)
+{
+    uint8_t gmtrr_mtype, hmtrr_mtype;
+    uint32_t type;
+    struct vcpu *v = current;
+
+    if ( (current->domain != d) && ((v = d->vcpu[0]) == NULL) )
+        return MTRR_TYPE_WRBACK;
+
+    if ( !v->domain->arch.hvm_domain.params[HVM_PARAM_IDENT_PT] )
+        return MTRR_TYPE_WRBACK;
+
+    if ( (v == current) && v->domain->arch.hvm_domain.is_in_uc_mode )
+        return MTRR_TYPE_UNCACHABLE;
+
+    if ( !mfn_valid(mfn) )
+        return MTRR_TYPE_UNCACHABLE;
+
+    if ( hvm_get_mem_pinned_cacheattr(d, gfn, &type) )
+        return type;
+
+    gmtrr_mtype = get_mtrr_type(&v->arch.hvm_vcpu.mtrr, (gfn << PAGE_SHIFT));
+    hmtrr_mtype = get_mtrr_type(&mtrr_state, (mfn << PAGE_SHIFT));
+    return ((gmtrr_mtype <= hmtrr_mtype) ? gmtrr_mtype : hmtrr_mtype);
+}
diff -r abd84464c09c -r 9b35ae586cb8 xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c        Mon Jul 07 10:29:56 2008 +0100
+++ b/xen/arch/x86/hvm/vmx/vmx.c        Mon Jul 07 10:45:50 2008 +0100
@@ -1173,6 +1173,14 @@ static int vmx_do_pmu_interrupt(struct c
     return vpmu_do_interrupt(regs);
 }
 
+static void vmx_set_uc_mode(struct vcpu *v)
+{
+    if ( paging_mode_hap(v->domain) )
+        ept_change_entry_emt_with_range(
+            v->domain, 0, v->domain->arch.p2m->max_mapped_pfn);
+    vpid_sync_all();
+}
+
 static struct hvm_function_table vmx_function_table = {
     .name                 = "VMX",
     .domain_initialise    = vmx_domain_initialise,
@@ -1202,7 +1210,8 @@ static struct hvm_function_table vmx_fun
     .fpu_dirty_intercept  = vmx_fpu_dirty_intercept,
     .msr_read_intercept   = vmx_msr_read_intercept,
     .msr_write_intercept  = vmx_msr_write_intercept,
-    .invlpg_intercept     = vmx_invlpg_intercept
+    .invlpg_intercept     = vmx_invlpg_intercept,
+    .set_uc_mode          = vmx_set_uc_mode
 };
 
 static unsigned long *vpid_bitmap;
diff -r abd84464c09c -r 9b35ae586cb8 xen/arch/x86/mm/hap/p2m-ept.c
--- a/xen/arch/x86/mm/hap/p2m-ept.c     Mon Jul 07 10:29:56 2008 +0100
+++ b/xen/arch/x86/mm/hap/p2m-ept.c     Mon Jul 07 10:45:50 2008 +0100
@@ -26,6 +26,8 @@
 #include <asm/p2m.h>
 #include <asm/hvm/vmx/vmx.h>
 #include <xen/iommu.h>
+#include <asm/mtrr.h>
+#include <asm/hvm/cacheattr.h>
 
 static void ept_p2m_type_to_flags(ept_entry_t *entry, p2m_type_t type)
 {
@@ -158,8 +160,7 @@ ept_set_entry(struct domain *d, unsigned
             /* Track the highest gfn for which we have ever had a valid 
mapping */
             if ( gfn > d->arch.p2m->max_mapped_pfn )
                 d->arch.p2m->max_mapped_pfn = gfn;
-
-            ept_entry->emt = EPT_DEFAULT_MT;
+            ept_entry->emt = epte_get_entry_emt(d, gfn, mfn_x(mfn));
             ept_entry->sp_avail = walk_level ? 1 : 0;
 
             if ( ret == GUEST_TABLE_SUPER_PAGE )
@@ -204,11 +205,13 @@ ept_set_entry(struct domain *d, unsigned
         /* split the super page before to 4k pages */
 
         split_table = map_domain_page(ept_entry->mfn);
+        offset = gfn & ((1 << EPT_TABLE_ORDER) - 1);
 
         for ( i = 0; i < 512; i++ )
         {
             split_ept_entry = split_table + i;
-            split_ept_entry->emt = EPT_DEFAULT_MT;
+            split_ept_entry->emt = epte_get_entry_emt(d,
+                                        gfn-offset+i, split_mfn+i);
             split_ept_entry->sp_avail =  0;
 
             split_ept_entry->mfn = split_mfn+i;
@@ -222,15 +225,13 @@ ept_set_entry(struct domain *d, unsigned
         }
 
         /* Set the destinated 4k page as normal */
-
-        offset = gfn & ((1 << EPT_TABLE_ORDER) - 1);
         split_ept_entry = split_table + offset;
+        split_ept_entry->emt = epte_get_entry_emt(d, gfn, mfn_x(mfn));
         split_ept_entry->mfn = mfn_x(mfn);
         split_ept_entry->avail1 = p2mt;
         ept_p2m_type_to_flags(split_ept_entry, p2mt);
 
         unmap_domain_page(split_table);
-
     }
 
     /* Success */
@@ -249,7 +250,7 @@ out:
         {
             if ( order == EPT_TABLE_ORDER )
             {
-                for ( i = 0; i < 512; i++ )
+                for ( i = 0; i < ( 1 << order ); i++ )
                     iommu_map_page(d, gfn-offset+i, mfn_x(mfn)-offset+i);
             }
             else if ( !order )
@@ -259,7 +260,7 @@ out:
         {
             if ( order == EPT_TABLE_ORDER )
             {
-                for ( i = 0; i < 512; i++ )
+                for ( i = 0; i < ( 1 << order ); i++ )
                     iommu_unmap_page(d, gfn-offset+i);
             }
             else if ( !order )
@@ -322,9 +323,87 @@ static mfn_t ept_get_entry(struct domain
     return mfn;
 }
 
+static uint64_t ept_get_entry_content(struct domain *d, unsigned long gfn)
+{
+    ept_entry_t *table =
+        map_domain_page(mfn_x(pagetable_get_mfn(d->arch.phys_table)));
+    unsigned long gfn_remainder = gfn;
+    ept_entry_t *ept_entry;
+    uint64_t content = 0;
+
+    u32 index;
+    int i, ret=0;
+
+    /* This pfn is higher than the highest the p2m map currently holds */
+    if ( gfn > d->arch.p2m->max_mapped_pfn )
+        goto out;
+
+    for ( i = EPT_DEFAULT_GAW; i > 0; i-- )
+    {
+        ret = ept_next_level(d, 1, &table, &gfn_remainder,
+                             i * EPT_TABLE_ORDER, 0);
+        if ( !ret )
+            goto out;
+        else if ( ret == GUEST_TABLE_SUPER_PAGE )
+            break;
+    }
+
+    index = gfn_remainder >> ( i * EPT_TABLE_ORDER);
+    ept_entry = table + index;
+    content = ept_entry->epte;
+
+ out:
+    unmap_domain_page(table);
+    return content;
+}
+
 static mfn_t ept_get_entry_current(unsigned long gfn, p2m_type_t *t)
 {
     return ept_get_entry(current->domain, gfn, t);
+}
+
+void ept_change_entry_emt_with_range(struct domain *d, unsigned long start_gfn,
+                 unsigned long end_gfn)
+{
+    unsigned long gfn;
+    p2m_type_t p2mt;
+    uint64_t epte;
+    int order = 0;
+    unsigned long mfn;
+
+    for ( gfn = start_gfn; gfn <= end_gfn; gfn++ )
+    {
+        epte = ept_get_entry_content(d, gfn);
+        if ( epte == 0 )
+            continue;
+        mfn = (epte & EPTE_MFN_MASK) >> PAGE_SHIFT;
+        if ( !mfn_valid(mfn) )
+            continue;
+        p2mt = (epte & EPTE_AVAIL1_MASK) >> 8;
+        order = 0;
+
+        if ( epte & EPTE_SUPER_PAGE_MASK )
+        {
+            if ( !(gfn & ( (1 << EPT_TABLE_ORDER) - 1)) &&
+              ((gfn + 0x1FF) <= end_gfn) )
+            {
+                /* gfn assigned with 2M, and the end covers more than 2m areas.
+                 * Set emt for super page.
+                 */
+                order = EPT_TABLE_ORDER;
+                ept_set_entry(d, gfn, _mfn(mfn), order, p2mt);
+                gfn += 0x1FF;
+            }
+            else
+            {
+                /* change emt for partial entries of the 2m area */
+                ept_set_entry(d, gfn, _mfn(mfn), order, p2mt);
+                gfn = ((gfn >> EPT_TABLE_ORDER) << EPT_TABLE_ORDER) + 0x1FF;
+            }
+        }
+        else /* gfn assigned with 4k */
+            ept_set_entry(d, gfn, _mfn(mfn), order, p2mt);
+    }
 }
 
 /* Walk the whole p2m table, changing any entries of the old type
diff -r abd84464c09c -r 9b35ae586cb8 xen/include/asm-x86/hvm/hvm.h
--- a/xen/include/asm-x86/hvm/hvm.h     Mon Jul 07 10:29:56 2008 +0100
+++ b/xen/include/asm-x86/hvm/hvm.h     Mon Jul 07 10:45:50 2008 +0100
@@ -127,6 +127,7 @@ struct hvm_function_table {
     int (*msr_read_intercept)(struct cpu_user_regs *regs);
     int (*msr_write_intercept)(struct cpu_user_regs *regs);
     void (*invlpg_intercept)(unsigned long vaddr);
+    void (*set_uc_mode)(struct vcpu *v);
 };
 
 extern struct hvm_function_table hvm_funcs;
diff -r abd84464c09c -r 9b35ae586cb8 xen/include/asm-x86/hvm/vmx/vmx.h
--- a/xen/include/asm-x86/hvm/vmx/vmx.h Mon Jul 07 10:29:56 2008 +0100
+++ b/xen/include/asm-x86/hvm/vmx/vmx.h Mon Jul 07 10:45:50 2008 +0100
@@ -44,6 +44,10 @@ typedef union {
 } ept_entry_t;
 
 #define EPT_TABLE_ORDER     9
+#define EPTE_SUPER_PAGE_MASK    0x80
+#define EPTE_MFN_MASK           0x1fffffffffff000
+#define EPTE_AVAIL1_MASK        0xF00
+#define EPTE_EMT_MASK           0x78
 
 void vmx_asm_vmexit_handler(struct cpu_user_regs);
 void vmx_asm_do_vmentry(void);
diff -r abd84464c09c -r 9b35ae586cb8 xen/include/asm-x86/mtrr.h
--- a/xen/include/asm-x86/mtrr.h        Mon Jul 07 10:29:56 2008 +0100
+++ b/xen/include/asm-x86/mtrr.h        Mon Jul 07 10:45:50 2008 +0100
@@ -64,6 +64,9 @@ extern void mtrr_centaur_report_mcr(int 
 extern void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi);
 extern u32 get_pat_flags(struct vcpu *v, u32 gl1e_flags, paddr_t gpaddr,
                   paddr_t spaddr);
+extern uint8_t epte_get_entry_emt(struct domain *d, unsigned long gfn, 
unsigned long mfn);
+extern void ept_change_entry_emt_with_range(struct domain *d, unsigned long 
start_gfn,
+                 unsigned long end_gfn);
 extern unsigned char pat_type_2_pte_flags(unsigned char pat_type);
 
 #endif /* __ASM_X86_MTRR_H__ */

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] MTRR virtualization for Intel EPT, Xen patchbot-unstable <=