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

[Xen-devel] [PATCH v2 03/10] nested_ept: Implement guest ept's walker



From: Zhang Xiantao <xiantao.zhang@xxxxxxxxx>

Implment guest EPT PT walker, some logic is based on shadow's
ia32e PT walker. During the PT walking, if the target pages are
not in memory, use RETRY mechanism and get a chance to let the
target page back.

Signed-off-by: Zhang Xiantao <xiantao.zhang@xxxxxxxxx>
---
 xen/arch/x86/hvm/hvm.c              |    1 +
 xen/arch/x86/hvm/vmx/vvmx.c         |   42 +++++-
 xen/arch/x86/mm/guest_walk.c        |   16 ++-
 xen/arch/x86/mm/hap/Makefile        |    1 +
 xen/arch/x86/mm/hap/nested_ept.c    |  276 +++++++++++++++++++++++++++++++++++
 xen/arch/x86/mm/hap/nested_hap.c    |    2 +-
 xen/arch/x86/mm/shadow/multi.c      |    2 +-
 xen/include/asm-x86/guest_pt.h      |    8 +
 xen/include/asm-x86/hvm/nestedhvm.h |    1 +
 xen/include/asm-x86/hvm/vmx/vmcs.h  |    1 +
 xen/include/asm-x86/hvm/vmx/vmx.h   |   28 ++++
 xen/include/asm-x86/hvm/vmx/vvmx.h  |   14 ++
 12 files changed, 382 insertions(+), 10 deletions(-)
 create mode 100644 xen/arch/x86/mm/hap/nested_ept.c

diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index 1cae8a8..3cd0075 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -1324,6 +1324,7 @@ int hvm_hap_nested_page_fault(paddr_t gpa,
                                              access_r, access_w, access_x);
         switch (rv) {
         case NESTEDHVM_PAGEFAULT_DONE:
+        case NESTEDHVM_PAGEFAULT_RETRY:
             return 1;
         case NESTEDHVM_PAGEFAULT_L1_ERROR:
             /* An error occured while translating gpa from
diff --git a/xen/arch/x86/hvm/vmx/vvmx.c b/xen/arch/x86/hvm/vmx/vvmx.c
index 4495dd6..76cf757 100644
--- a/xen/arch/x86/hvm/vmx/vvmx.c
+++ b/xen/arch/x86/hvm/vmx/vvmx.c
@@ -906,9 +906,18 @@ static void sync_vvmcs_ro(struct vcpu *v)
 {
     int i;
     struct nestedvcpu *nvcpu = &vcpu_nestedhvm(v);
+    struct nestedvmx *nvmx = &vcpu_2_nvmx(v);
+    void *vvmcs = nvcpu->nv_vvmcx;
 
     for ( i = 0; i < ARRAY_SIZE(vmcs_ro_field); i++ )
         shadow_to_vvmcs(nvcpu->nv_vvmcx, vmcs_ro_field[i]);
+
+    /* Adjust exit_reason/exit_qualifciation for violation case */
+    if ( __get_vvmcs(vvmcs, VM_EXIT_REASON) ==
+                EXIT_REASON_EPT_VIOLATION ) {
+        __set_vvmcs(vvmcs, EXIT_QUALIFICATION, nvmx->ept_exit.exit_qual);
+        __set_vvmcs(vvmcs, VM_EXIT_REASON, nvmx->ept_exit.exit_reason);
+    }
 }
 
 static void load_vvmcs_host_state(struct vcpu *v)
@@ -1454,8 +1463,37 @@ nvmx_hap_walk_L1_p2m(struct vcpu *v, paddr_t L2_gpa, 
paddr_t *L1_gpa,
                       unsigned int *page_order,
                       bool_t access_r, bool_t access_w, bool_t access_x)
 {
-    /*TODO:*/
-    return 0;
+    uint64_t exit_qual = __vmread(EXIT_QUALIFICATION);
+    uint32_t exit_reason = EXIT_REASON_EPT_VIOLATION;
+    int rc;
+    unsigned long gfn;
+    uint32_t rwx_rights = (access_x << 2) | (access_w << 1) | access_r;
+    struct nestedvmx *nvmx = &vcpu_2_nvmx(v);
+
+    rc = nept_translate_l2ga(v, L2_gpa, page_order, rwx_rights, &gfn,
+                                &exit_qual, &exit_reason);
+    switch ( rc ) {
+        case EPT_TRANSLATE_SUCCEED:
+            *L1_gpa = (gfn << PAGE_SHIFT) + (L2_gpa & ~PAGE_MASK);
+            rc = NESTEDHVM_PAGEFAULT_DONE;
+            break;
+        case EPT_TRANSLATE_VIOLATION:
+        case EPT_TRANSLATE_MISCONFIG:
+            rc = NESTEDHVM_PAGEFAULT_INJECT;
+            nvmx->ept_exit.exit_reason = exit_reason;
+            nvmx->ept_exit.exit_qual = exit_qual;
+            break;
+        case EPT_TRANSLATE_RETRY:
+            rc = NESTEDHVM_PAGEFAULT_RETRY;
+            break;
+        case EPT_TRANSLATE_ERR_PAGE:
+            rc = NESTEDHVM_PAGEFAULT_L1_ERROR;
+            break;
+        default:
+            gdprintk(XENLOG_ERR, "GUEST EPT translation error!\n");
+    }
+
+    return rc;
 }
 
 void nvmx_idtv_handling(void)
diff --git a/xen/arch/x86/mm/guest_walk.c b/xen/arch/x86/mm/guest_walk.c
index 0f08fb0..1c165c6 100644
--- a/xen/arch/x86/mm/guest_walk.c
+++ b/xen/arch/x86/mm/guest_walk.c
@@ -88,18 +88,19 @@ static uint32_t set_ad_bits(void *guest_p, void *walk_p, 
int set_dirty)
 
 /* If the map is non-NULL, we leave this function having 
  * acquired an extra ref on mfn_to_page(*mfn) */
-static inline void *map_domain_gfn(struct p2m_domain *p2m,
-                                   gfn_t gfn, 
+void *map_domain_gfn(struct p2m_domain *p2m,
+                                   gfn_t gfn,
                                    mfn_t *mfn,
                                    p2m_type_t *p2mt,
-                                   uint32_t *rc) 
+                                   p2m_query_t q,
+                                   uint32_t *rc)
 {
     struct page_info *page;
     void *map;
 
     /* Translate the gfn, unsharing if shared */
     page = get_page_from_gfn_p2m(p2m->domain, p2m, gfn_x(gfn), p2mt, NULL,
-                                  P2M_ALLOC | P2M_UNSHARE);
+                                  q);
     if ( p2m_is_paging(*p2mt) )
     {
         ASSERT(!p2m_is_nestedp2m(p2m));
@@ -128,7 +129,6 @@ static inline void *map_domain_gfn(struct p2m_domain *p2m,
     return map;
 }
 
-
 /* Walk the guest pagetables, after the manner of a hardware walker. */
 /* Because the walk is essentially random, it can cause a deadlock 
  * warning in the p2m locking code. Highly unlikely this is an actual
@@ -149,6 +149,7 @@ guest_walk_tables(struct vcpu *v, struct p2m_domain *p2m,
     uint32_t gflags, mflags, iflags, rc = 0;
     int smep;
     bool_t pse1G = 0, pse2M = 0;
+    p2m_query_t qt = P2M_ALLOC | P2M_UNSHARE;
 
     perfc_incr(guest_walk);
     memset(gw, 0, sizeof(*gw));
@@ -188,7 +189,8 @@ guest_walk_tables(struct vcpu *v, struct p2m_domain *p2m,
     l3p = map_domain_gfn(p2m, 
                          guest_l4e_get_gfn(gw->l4e), 
                          &gw->l3mfn,
-                         &p2mt, 
+                         &p2mt,
+                         qt, 
                          &rc); 
     if(l3p == NULL)
         goto out;
@@ -249,6 +251,7 @@ guest_walk_tables(struct vcpu *v, struct p2m_domain *p2m,
                          guest_l3e_get_gfn(gw->l3e), 
                          &gw->l2mfn,
                          &p2mt, 
+                         qt,
                          &rc); 
     if(l2p == NULL)
         goto out;
@@ -322,6 +325,7 @@ guest_walk_tables(struct vcpu *v, struct p2m_domain *p2m,
                              guest_l2e_get_gfn(gw->l2e), 
                              &gw->l1mfn,
                              &p2mt,
+                             qt,
                              &rc);
         if(l1p == NULL)
             goto out;
diff --git a/xen/arch/x86/mm/hap/Makefile b/xen/arch/x86/mm/hap/Makefile
index 80a6bec..68f2bb5 100644
--- a/xen/arch/x86/mm/hap/Makefile
+++ b/xen/arch/x86/mm/hap/Makefile
@@ -3,6 +3,7 @@ obj-y += guest_walk_2level.o
 obj-y += guest_walk_3level.o
 obj-$(x86_64) += guest_walk_4level.o
 obj-y += nested_hap.o
+obj-y += nested_ept.o
 
 guest_walk_%level.o: guest_walk.c Makefile
        $(CC) $(CFLAGS) -DGUEST_PAGING_LEVELS=$* -c $< -o $@
diff --git a/xen/arch/x86/mm/hap/nested_ept.c b/xen/arch/x86/mm/hap/nested_ept.c
new file mode 100644
index 0000000..5f80d82
--- /dev/null
+++ b/xen/arch/x86/mm/hap/nested_ept.c
@@ -0,0 +1,276 @@
+/*
+ * nested_ept.c: Handling virtulized EPT for guest in nested case.
+ *
+ * Copyright (c) 2012, Intel Corporation
+ *  Xiantao Zhang <xiantao.zhang@xxxxxxxxx>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ */
+#include <asm/domain.h>
+#include <asm/page.h>
+#include <asm/paging.h>
+#include <asm/p2m.h>
+#include <asm/mem_event.h>
+#include <public/mem_event.h>
+#include <asm/mem_sharing.h>
+#include <xen/event.h>
+#include <asm/hap.h>
+#include <asm/hvm/support.h>
+
+#include <asm/hvm/nestedhvm.h>
+
+#include "private.h"
+
+#include <asm/hvm/vmx/vmx.h>
+#include <asm/hvm/vmx/vvmx.h>
+
+/* EPT always use 4-level paging structure */
+#define GUEST_PAGING_LEVELS 4
+#include <asm/guest_pt.h>
+
+/* Must reserved bits in all level entries  */
+#define EPT_MUST_RSV_BITS (((1ull << PADDR_BITS) -1) & \
+                     ~((1ull << paddr_bits) - 1))
+
+/*
+ *TODO: Just leave it as 0 here for compile pass, will
+ * define real capabilities in the subsequent patches.
+ */
+#define NEPT_VPID_CAP_BITS 0
+
+
+#define NEPT_1G_ENTRY_FLAG (1 << 11)
+#define NEPT_2M_ENTRY_FLAG (1 << 10)
+#define NEPT_4K_ENTRY_FLAG (1 << 9)
+
+bool_t nept_sp_entry(ept_entry_t e)
+{
+    return !!(e.sp);
+}
+
+static bool_t nept_rsv_bits_check(ept_entry_t e, uint32_t level)
+{
+    uint64_t rsv_bits = EPT_MUST_RSV_BITS;
+
+    switch ( level ) {
+    case 1:
+        break;
+    case 2 ... 3:
+        if (nept_sp_entry(e))
+            rsv_bits |=  ((1ull << (9 * (level -1 ))) -1) << PAGE_SHIFT;
+        else
+            rsv_bits |= EPTE_EMT_MASK | EPTE_IGMT_MASK;
+        break;
+    case 4:
+        rsv_bits |= EPTE_EMT_MASK | EPTE_IGMT_MASK | EPTE_SUPER_PAGE_MASK;
+    break;
+    default:
+        printk("Unsupported EPT paging level: %d\n", level);
+    }
+    return !!(e.epte & rsv_bits);
+}
+
+/* EMT checking*/
+static bool_t nept_emt_bits_check(ept_entry_t e, uint32_t level)
+{
+    if ( e.sp || level == 1 ) {
+        if ( e.emt == EPT_EMT_RSV0 || e.emt == EPT_EMT_RSV1 ||
+                e.emt == EPT_EMT_RSV2 )
+            return 1;
+    }
+    return 0;
+}
+
+static bool_t nept_rwx_bits_check(ept_entry_t e) {
+    /*write only or write/execute only*/
+    uint8_t rwx_bits = e.epte & EPTE_RWX_MASK;
+
+    if ( rwx_bits == ept_access_w || rwx_bits == ept_access_wx )
+        return 1;
+
+    if ( rwx_bits == ept_access_x && !(NEPT_VPID_CAP_BITS &
+                        VMX_EPT_EXEC_ONLY_SUPPORTED))
+        return 1;
+
+    return 0;
+}
+
+/* nept's misconfiguration check */
+static bool_t nept_misconfiguration_check(ept_entry_t e, uint32_t level)
+{
+    return (nept_rsv_bits_check(e, level) ||
+                nept_emt_bits_check(e, level) ||
+                nept_rwx_bits_check(e));
+}
+
+static bool_t nept_permission_check(uint32_t rwx_acc, uint32_t rwx_bits)
+{
+    return !(EPTE_RWX_MASK & rwx_acc & ~rwx_bits);
+}
+
+/* nept's non-present check */
+static bool_t nept_non_present_check(ept_entry_t e)
+{
+    if (e.epte & EPTE_RWX_MASK)
+        return 0;
+    return 1;
+}
+
+uint64_t nept_get_ept_vpid_cap(void)
+{
+    return NEPT_VPID_CAP_BITS;
+}
+
+static int ept_lvl_table_offset(unsigned long gpa, int lvl)
+{
+    return (gpa >>(EPT_L4_PAGETABLE_SHIFT -(4 - lvl) * 9)) &
+                (EPT_PAGETABLE_ENTRIES -1 );
+}
+
+static uint32_t
+nept_walk_tables(struct vcpu *v, unsigned long l2ga, ept_walk_t *gw)
+{
+    int lvl;
+    p2m_type_t p2mt;
+    uint32_t rc = 0, ret = 0, gflags;
+    struct domain *d = v->domain;
+    struct p2m_domain *p2m = d->arch.p2m;
+    gfn_t base_gfn = _gfn(nhvm_vcpu_p2m_base(v) >> PAGE_SHIFT);
+    mfn_t lxmfn;
+    ept_entry_t *lxp = NULL;
+
+    memset(gw, 0, sizeof(*gw));
+
+    for (lvl = 4; lvl > 0; lvl--)
+    {
+        lxp = map_domain_gfn(p2m, base_gfn, &lxmfn, &p2mt, P2M_ALLOC, &rc);
+        if ( !lxp )
+            goto map_err;
+        gw->lxe[lvl] = lxp[ept_lvl_table_offset(l2ga, lvl)];
+        unmap_domain_page(lxp);
+        put_page(mfn_to_page(mfn_x(lxmfn)));
+
+        if (nept_non_present_check(gw->lxe[lvl]))
+            goto non_present;
+
+        if (nept_misconfiguration_check(gw->lxe[lvl], lvl))
+            goto misconfig_err;
+
+        if ( (lvl == 2 || lvl == 3) && nept_sp_entry(gw->lxe[lvl]) )
+        {
+            /* Generate a fake l1 table entry so callers don't all
+             * have to understand superpages. */
+            unsigned long gfn_lvl_mask =  (1ull << ((lvl - 1) * 9)) - 1;
+            gfn_t start = _gfn(gw->lxe[lvl].mfn);
+            /* Increment the pfn by the right number of 4k pages. */
+            start = _gfn((gfn_x(start) & ~gfn_lvl_mask) +
+                     ((l2ga >> PAGE_SHIFT) & gfn_lvl_mask));
+            gflags = (gw->lxe[lvl].epte & EPTE_FLAG_MASK) |
+                    (lvl == 3 ? NEPT_1G_ENTRY_FLAG: NEPT_2M_ENTRY_FLAG);
+            gw->lxe[0].epte = (gfn_x(start) << PAGE_SHIFT) | gflags;
+            goto done;
+        }
+        if ( lvl > 1 )
+            base_gfn = _gfn(gw->lxe[lvl].mfn);
+    }
+
+    /* If this is not a super entry, we can reach here. */
+    gflags = (gw->lxe[1].epte & EPTE_FLAG_MASK) | NEPT_4K_ENTRY_FLAG;
+    gw->lxe[0].epte = (gw->lxe[1].epte & PAGE_MASK) | gflags;
+
+done:
+    ret = EPT_TRANSLATE_SUCCEED;
+    goto out;
+
+map_err:
+    if ( rc == _PAGE_PAGED )
+        ret = EPT_TRANSLATE_RETRY;
+    else
+        ret = EPT_TRANSLATE_ERR_PAGE;
+    goto out;
+
+misconfig_err:
+    ret =  EPT_TRANSLATE_MISCONFIG;
+    goto out;
+
+non_present:
+    ret = EPT_TRANSLATE_VIOLATION;
+    /* fall through. */
+out:
+    return ret;
+}
+
+/* Translate a L2 guest address to L1 gpa via L1 EPT paging structure */
+
+int nept_translate_l2ga(struct vcpu *v, paddr_t l2ga,
+                        unsigned int *page_order, uint32_t rwx_acc,
+                        unsigned long *l1gfn, uint64_t *exit_qual,
+                        uint32_t *exit_reason)
+{
+    uint32_t rc, rwx_bits = 0;
+    ept_walk_t gw;
+    rwx_acc &= EPTE_RWX_MASK;
+
+    *l1gfn = INVALID_GFN;
+
+    rc = nept_walk_tables(v, l2ga, &gw);
+    switch ( rc ) {
+    case EPT_TRANSLATE_SUCCEED:
+        if ( likely(gw.lxe[0].epte & NEPT_2M_ENTRY_FLAG) )
+        {
+            rwx_bits = gw.lxe[4].epte & gw.lxe[3].epte & gw.lxe[2].epte &
+                            EPTE_RWX_MASK;
+            *page_order = 9;
+        }
+        else if ( gw.lxe[0].epte & NEPT_4K_ENTRY_FLAG ) {
+            rwx_bits = gw.lxe[4].epte & gw.lxe[3].epte & gw.lxe[2].epte &
+                    gw.lxe[1].epte & EPTE_RWX_MASK;
+            *page_order = 0;
+        }
+        else if ( gw.lxe[0].epte & NEPT_1G_ENTRY_FLAG  )
+        {
+            rwx_bits = gw.lxe[4].epte & gw.lxe[3].epte  & EPTE_RWX_MASK;
+            *page_order = 18;
+        }
+        else
+        {
+            gdprintk(XENLOG_ERR, "Uncorrect l1 entry!\n");
+            BUG();
+        }
+        if ( nept_permission_check(rwx_acc, rwx_bits) )
+        {
+            *l1gfn = gw.lxe[0].mfn;
+            break;
+        }
+        rc = EPT_TRANSLATE_VIOLATION;
+    /* Fall through to EPT violation if permission check fails. */
+    case EPT_TRANSLATE_VIOLATION:
+        *exit_qual = (*exit_qual & 0xffffffc0) | (rwx_bits << 3) | rwx_acc;
+        *exit_reason = EXIT_REASON_EPT_VIOLATION;
+        break;
+
+    case EPT_TRANSLATE_ERR_PAGE:
+        break;
+    case EPT_TRANSLATE_MISCONFIG:
+        rc = EPT_TRANSLATE_MISCONFIG;
+        *exit_qual = 0;
+        *exit_reason = EXIT_REASON_EPT_MISCONFIG;
+        break;
+    case EPT_TRANSLATE_RETRY:
+        break;
+    default:
+        gdprintk(XENLOG_ERR, "Unsupported ept translation type!:%d\n", rc);
+    }
+    return rc;
+}
diff --git a/xen/arch/x86/mm/hap/nested_hap.c b/xen/arch/x86/mm/hap/nested_hap.c
index 8787c91..6d1264b 100644
--- a/xen/arch/x86/mm/hap/nested_hap.c
+++ b/xen/arch/x86/mm/hap/nested_hap.c
@@ -217,7 +217,7 @@ nestedhvm_hap_nested_page_fault(struct vcpu *v, paddr_t 
*L2_gpa,
     /* let caller to handle these two cases */
     switch (rv) {
     case NESTEDHVM_PAGEFAULT_INJECT:
-        return rv;
+    case NESTEDHVM_PAGEFAULT_RETRY:
     case NESTEDHVM_PAGEFAULT_L1_ERROR:
         return rv;
     case NESTEDHVM_PAGEFAULT_DONE:
diff --git a/xen/arch/x86/mm/shadow/multi.c b/xen/arch/x86/mm/shadow/multi.c
index 4967da1..409198c 100644
--- a/xen/arch/x86/mm/shadow/multi.c
+++ b/xen/arch/x86/mm/shadow/multi.c
@@ -4582,7 +4582,7 @@ static mfn_t emulate_gva_to_mfn(struct vcpu *v,
     /* Translate the GFN to an MFN */
     ASSERT(!paging_locked_by_me(v->domain));
     mfn = get_gfn(v->domain, _gfn(gfn), &p2mt);
-        
+
     if ( p2m_is_readonly(p2mt) )
     {
         put_gfn(v->domain, gfn);
diff --git a/xen/include/asm-x86/guest_pt.h b/xen/include/asm-x86/guest_pt.h
index 4e1dda0..db8a0b6 100644
--- a/xen/include/asm-x86/guest_pt.h
+++ b/xen/include/asm-x86/guest_pt.h
@@ -315,6 +315,14 @@ guest_walk_to_page_order(walk_t *gw)
 #define GPT_RENAME2(_n, _l) _n ## _ ## _l ## _levels
 #define GPT_RENAME(_n, _l) GPT_RENAME2(_n, _l)
 #define guest_walk_tables GPT_RENAME(guest_walk_tables, GUEST_PAGING_LEVELS)
+#define map_domain_gfn GPT_RENAME(map_domain_gfn, GUEST_PAGING_LEVELS)
+
+extern void *map_domain_gfn(struct p2m_domain *p2m,
+                                   gfn_t gfn,
+                                   mfn_t *mfn,
+                                   p2m_type_t *p2mt,
+                                   p2m_query_t q,
+                                   uint32_t *rc);
 
 extern uint32_t 
 guest_walk_tables(struct vcpu *v, struct p2m_domain *p2m, unsigned long va,
diff --git a/xen/include/asm-x86/hvm/nestedhvm.h 
b/xen/include/asm-x86/hvm/nestedhvm.h
index 91fde0b..649c511 100644
--- a/xen/include/asm-x86/hvm/nestedhvm.h
+++ b/xen/include/asm-x86/hvm/nestedhvm.h
@@ -52,6 +52,7 @@ bool_t nestedhvm_vcpu_in_guestmode(struct vcpu *v);
 #define NESTEDHVM_PAGEFAULT_L1_ERROR   2
 #define NESTEDHVM_PAGEFAULT_L0_ERROR   3
 #define NESTEDHVM_PAGEFAULT_MMIO       4
+#define NESTEDHVM_PAGEFAULT_RETRY      5
 int nestedhvm_hap_nested_page_fault(struct vcpu *v, paddr_t *L2_gpa,
     bool_t access_r, bool_t access_w, bool_t access_x);
 
diff --git a/xen/include/asm-x86/hvm/vmx/vmcs.h 
b/xen/include/asm-x86/hvm/vmx/vmcs.h
index ef2c9c9..9a728b6 100644
--- a/xen/include/asm-x86/hvm/vmx/vmcs.h
+++ b/xen/include/asm-x86/hvm/vmx/vmcs.h
@@ -194,6 +194,7 @@ extern u32 vmx_secondary_exec_control;
 
 extern bool_t cpu_has_vmx_ins_outs_instr_info;
 
+#define VMX_EPT_EXEC_ONLY_SUPPORTED             0x00000001
 #define VMX_EPT_WALK_LENGTH_4_SUPPORTED         0x00000040
 #define VMX_EPT_MEMORY_TYPE_UC                  0x00000100
 #define VMX_EPT_MEMORY_TYPE_WB                  0x00004000
diff --git a/xen/include/asm-x86/hvm/vmx/vmx.h 
b/xen/include/asm-x86/hvm/vmx/vmx.h
index aa5b080..feaaa80 100644
--- a/xen/include/asm-x86/hvm/vmx/vmx.h
+++ b/xen/include/asm-x86/hvm/vmx/vmx.h
@@ -51,6 +51,11 @@ typedef union {
     u64 epte;
 } ept_entry_t;
 
+typedef struct {
+    /*use lxe[0] to save result */
+    ept_entry_t lxe[5];
+} ept_walk_t;
+
 #define EPT_TABLE_ORDER         9
 #define EPTE_SUPER_PAGE_MASK    0x80
 #define EPTE_MFN_MASK           0xffffffffff000ULL
@@ -60,6 +65,28 @@ typedef union {
 #define EPTE_AVAIL1_SHIFT       8
 #define EPTE_EMT_SHIFT          3
 #define EPTE_IGMT_SHIFT         6
+#define EPTE_RWX_MASK           0x7
+#define EPTE_FLAG_MASK          0x7f
+
+#define EPT_EMT_UC              0
+#define EPT_EMT_WC              1
+#define EPT_EMT_RSV0            2
+#define EPT_EMT_RSV1            3
+#define EPT_EMT_WT              4
+#define EPT_EMT_WP              5
+#define EPT_EMT_WB              6
+#define EPT_EMT_RSV2            7
+
+typedef enum {
+    ept_access_n     = 0, /* No access permissions allowed */
+    ept_access_r     = 1,
+    ept_access_w     = 2,
+    ept_access_rw    = 3,
+    ept_access_x     = 4,
+    ept_access_rx    = 5,
+    ept_access_wx    = 6,
+    ept_access_all   = 7,
+} ept_access_t;
 
 void vmx_asm_vmexit_handler(struct cpu_user_regs);
 void vmx_asm_do_vmentry(void);
@@ -419,6 +446,7 @@ void update_guest_eip(void);
 #define _EPT_GLA_FAULT              8
 #define EPT_GLA_FAULT               (1UL<<_EPT_GLA_FAULT)
 
+#define EPT_L4_PAGETABLE_SHIFT      39
 #define EPT_PAGETABLE_ENTRIES       512
 
 #endif /* __ASM_X86_HVM_VMX_VMX_H__ */
diff --git a/xen/include/asm-x86/hvm/vmx/vvmx.h 
b/xen/include/asm-x86/hvm/vmx/vvmx.h
index 422f006..8eb377b 100644
--- a/xen/include/asm-x86/hvm/vmx/vvmx.h
+++ b/xen/include/asm-x86/hvm/vmx/vvmx.h
@@ -32,6 +32,10 @@ struct nestedvmx {
         unsigned long intr_info;
         u32           error_code;
     } intr;
+    struct {
+        uint32_t exit_reason;
+        uint32_t exit_qual;
+    } ept_exit;
 };
 
 #define vcpu_2_nvmx(v) (vcpu_nestedhvm(v).u.nvmx)
@@ -109,6 +113,12 @@ void nvmx_domain_relinquish_resources(struct domain *d);
 int nvmx_handle_vmxon(struct cpu_user_regs *regs);
 int nvmx_handle_vmxoff(struct cpu_user_regs *regs);
 
+#define EPT_TRANSLATE_SUCCEED   0
+#define EPT_TRANSLATE_VIOLATION 1
+#define EPT_TRANSLATE_ERR_PAGE  2
+#define EPT_TRANSLATE_MISCONFIG 3
+#define EPT_TRANSLATE_RETRY     4
+
 int
 nvmx_hap_walk_L1_p2m(struct vcpu *v, paddr_t L2_gpa, paddr_t *L1_gpa,
                       unsigned int *page_order,
@@ -192,5 +202,9 @@ u64 nvmx_get_tsc_offset(struct vcpu *v);
 int nvmx_n2_vmexit_handler(struct cpu_user_regs *regs,
                           unsigned int exit_reason);
 
+int nept_translate_l2ga(struct vcpu *v, paddr_t l2ga, 
+                        unsigned int *page_order, uint32_t rwx_acc,
+                        unsigned long *l1gfn, uint64_t *exit_qual,
+                        uint32_t *exit_reason);
 #endif /* __ASM_X86_HVM_VVMX_H__ */
 
-- 
1.7.1


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

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