[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] nested_ept: Implement guest ept's walker
# HG changeset patch # User Zhang Xiantao <xiantao.zhang@xxxxxxxxx> # Date 1358244929 -3600 # Node ID 289f47c01867013f4f6d0f9b65f7cb532bb60938 # Parent eaeef464f3920c7ebd68a4d30813eee2763df70c nested_ept: Implement guest ept's walker 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> Acked-by: Tim Deegan <tim@xxxxxxx> Acked-by: Jun Nakajima <jun.nakajima@xxxxxxxxx> Acked-by: Eddie Dong <eddie.dong@xxxxxxxxx> Committed-by: Jan Beulich <jbeulich@xxxxxxxx> --- diff -r eaeef464f392 -r 289f47c01867 xen/arch/x86/hvm/hvm.c --- a/xen/arch/x86/hvm/hvm.c Tue Jan 15 11:11:37 2013 +0100 +++ b/xen/arch/x86/hvm/hvm.c Tue Jan 15 11:15:29 2013 +0100 @@ -1326,6 +1326,7 @@ int hvm_hap_nested_page_fault(paddr_t gp 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 -r eaeef464f392 -r 289f47c01867 xen/arch/x86/hvm/vmx/vvmx.c --- a/xen/arch/x86/hvm/vmx/vvmx.c Tue Jan 15 11:11:37 2013 +0100 +++ b/xen/arch/x86/hvm/vmx/vvmx.c Tue Jan 15 11:15:29 2013 +0100 @@ -943,9 +943,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) @@ -1493,8 +1502,37 @@ nvmx_hap_walk_L1_p2m(struct vcpu *v, pad unsigned int *page_order, bool_t access_r, bool_t access_w, bool_t access_x) { - /*TODO:*/ - return 0; + int rc; + unsigned long gfn; + uint64_t exit_qual = __vmread(EXIT_QUALIFICATION); + uint32_t exit_reason = EXIT_REASON_EPT_VIOLATION; + 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; + default: + gdprintk(XENLOG_ERR, "GUEST EPT translation error!:%d\n", rc); + BUG(); + break; + } + + return rc; } void nvmx_idtv_handling(void) diff -r eaeef464f392 -r 289f47c01867 xen/arch/x86/mm/guest_walk.c --- a/xen/arch/x86/mm/guest_walk.c Tue Jan 15 11:11:37 2013 +0100 +++ b/xen/arch/x86/mm/guest_walk.c Tue Jan 15 11:15:29 2013 +0100 @@ -88,18 +88,15 @@ static uint32_t set_ad_bits(void *guest_ /* 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, - mfn_t *mfn, - p2m_type_t *p2mt, - uint32_t *rc) +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) { 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)); @@ -149,6 +146,7 @@ guest_walk_tables(struct vcpu *v, struct 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 +186,8 @@ guest_walk_tables(struct vcpu *v, struct l3p = map_domain_gfn(p2m, guest_l4e_get_gfn(gw->l4e), &gw->l3mfn, - &p2mt, + &p2mt, + qt, &rc); if(l3p == NULL) goto out; @@ -249,6 +248,7 @@ guest_walk_tables(struct vcpu *v, struct guest_l3e_get_gfn(gw->l3e), &gw->l2mfn, &p2mt, + qt, &rc); if(l2p == NULL) goto out; @@ -322,6 +322,7 @@ guest_walk_tables(struct vcpu *v, struct guest_l2e_get_gfn(gw->l2e), &gw->l1mfn, &p2mt, + qt, &rc); if(l1p == NULL) goto out; diff -r eaeef464f392 -r 289f47c01867 xen/arch/x86/mm/hap/Makefile --- a/xen/arch/x86/mm/hap/Makefile Tue Jan 15 11:11:37 2013 +0100 +++ b/xen/arch/x86/mm/hap/Makefile Tue Jan 15 11:15:29 2013 +0100 @@ -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 -r eaeef464f392 -r 289f47c01867 xen/arch/x86/mm/hap/nested_ept.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xen/arch/x86/mm/hap/nested_ept.c Tue Jan 15 11:15:29 2013 +0100 @@ -0,0 +1,287 @@ +/* + * 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: + gdprintk(XENLOG_ERR,"Unsupported EPT paging level: %d\n", level); + BUG(); + break; + } + 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_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) +{ + uint64_t caps = NEPT_VPID_CAP_BITS; + + if ( !cpu_has_vmx_ept_exec_only_supported ) + caps &= ~VMX_EPT_EXEC_ONLY_SUPPORTED; + return caps; +} + +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_get_ept_vpid_cap() & 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 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; + goto out; + } + /* fall through to misconfig error */ +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_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); + BUG(); + break; + } + return rc; +} diff -r eaeef464f392 -r 289f47c01867 xen/arch/x86/mm/hap/nested_hap.c --- a/xen/arch/x86/mm/hap/nested_hap.c Tue Jan 15 11:11:37 2013 +0100 +++ b/xen/arch/x86/mm/hap/nested_hap.c Tue Jan 15 11:15:29 2013 +0100 @@ -218,7 +218,7 @@ nestedhvm_hap_nested_page_fault(struct v /* 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 -r eaeef464f392 -r 289f47c01867 xen/include/asm-x86/guest_pt.h --- a/xen/include/asm-x86/guest_pt.h Tue Jan 15 11:11:37 2013 +0100 +++ b/xen/include/asm-x86/guest_pt.h Tue Jan 15 11:15:29 2013 +0100 @@ -315,6 +315,10 @@ 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) + +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 -r eaeef464f392 -r 289f47c01867 xen/include/asm-x86/hvm/nestedhvm.h --- a/xen/include/asm-x86/hvm/nestedhvm.h Tue Jan 15 11:11:37 2013 +0100 +++ b/xen/include/asm-x86/hvm/nestedhvm.h Tue Jan 15 11:15:29 2013 +0100 @@ -52,6 +52,7 @@ bool_t nestedhvm_vcpu_in_guestmode(struc #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 -r eaeef464f392 -r 289f47c01867 xen/include/asm-x86/hvm/vmx/vmcs.h --- a/xen/include/asm-x86/hvm/vmx/vmcs.h Tue Jan 15 11:11:37 2013 +0100 +++ b/xen/include/asm-x86/hvm/vmx/vmcs.h Tue Jan 15 11:15:29 2013 +0100 @@ -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 -r eaeef464f392 -r 289f47c01867 xen/include/asm-x86/hvm/vmx/vmx.h --- a/xen/include/asm-x86/hvm/vmx/vmx.h Tue Jan 15 11:11:37 2013 +0100 +++ b/xen/include/asm-x86/hvm/vmx/vmx.h Tue Jan 15 11:15:29 2013 +0100 @@ -51,6 +51,22 @@ typedef union { u64 epte; } ept_entry_t; +typedef struct { + /*use lxe[0] to save result */ + ept_entry_t lxe[5]; +} ept_walk_t; + +typedef enum { + ept_access_n = 0, /* No access permissions allowed */ + ept_access_r = 1, /* Read only */ + ept_access_w = 2, /* Write only */ + ept_access_rw = 3, /* Read & Write */ + ept_access_x = 4, /* Exec Only */ + ept_access_rx = 5, /* Read & Exec */ + ept_access_wx = 6, /* Write & Exec*/ + ept_access_all = 7, /* Full permissions */ +} ept_access_t; + #define EPT_TABLE_ORDER 9 #define EPTE_SUPER_PAGE_MASK 0x80 #define EPTE_MFN_MASK 0xffffffffff000ULL @@ -60,6 +76,17 @@ 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 void vmx_asm_vmexit_handler(struct cpu_user_regs); void vmx_asm_do_vmentry(void); @@ -191,6 +218,9 @@ void vmx_update_secondary_exec_control(s extern u64 vmx_ept_vpid_cap; +#define cpu_has_vmx_ept_exec_only_supported \ + (vmx_ept_vpid_cap & VMX_EPT_EXEC_ONLY_SUPPORTED) + #define cpu_has_vmx_ept_wl4_supported \ (vmx_ept_vpid_cap & VMX_EPT_WALK_LENGTH_4_SUPPORTED) #define cpu_has_vmx_ept_mt_uc \ @@ -419,6 +449,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 -r eaeef464f392 -r 289f47c01867 xen/include/asm-x86/hvm/vmx/vvmx.h --- a/xen/include/asm-x86/hvm/vmx/vvmx.h Tue Jan 15 11:11:37 2013 +0100 +++ b/xen/include/asm-x86/hvm/vmx/vvmx.h Tue Jan 15 11:15:29 2013 +0100 @@ -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,11 @@ void nvmx_domain_relinquish_resources(st 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_MISCONFIG 2 +#define EPT_TRANSLATE_RETRY 3 + int nvmx_hap_walk_L1_p2m(struct vcpu *v, paddr_t L2_gpa, paddr_t *L1_gpa, unsigned int *page_order, @@ -192,5 +201,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__ */ _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |