[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] nEPT: Try to enable EPT paging for L2 guest
# HG changeset patch # User Zhang Xiantao <xiantao.zhang@xxxxxxxxx> # Date 1358245126 -3600 # Node ID 0d20a4939690437e2a2b2b29b30c7518000dd961 # Parent 4056e5a3d8150303bf8d89bd64b789e3a72321a3 nEPT: Try to enable EPT paging for L2 guest Once found EPT is enabled by L1 VMM, enabled nested EPT support for L2 guest. 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 4056e5a3d815 -r 0d20a4939690 xen/arch/x86/hvm/vmx/vmx.c --- a/xen/arch/x86/hvm/vmx/vmx.c Tue Jan 15 11:17:01 2013 +0100 +++ b/xen/arch/x86/hvm/vmx/vmx.c Tue Jan 15 11:18:46 2013 +0100 @@ -1461,6 +1461,7 @@ static struct hvm_function_table __read_ .nhvm_vcpu_guestcr3 = nvmx_vcpu_guestcr3, .nhvm_vcpu_p2m_base = nvmx_vcpu_eptp_base, .nhvm_vcpu_asid = nvmx_vcpu_asid, + .nhvm_vmcx_hap_enabled = nvmx_ept_enabled, .nhvm_vmcx_guest_intercepts_trap = nvmx_intercepts_exception, .nhvm_vcpu_vmexit_trap = nvmx_vmexit_trap, .nhvm_intr_blocked = nvmx_intr_blocked, @@ -2003,6 +2004,7 @@ static void ept_handle_violation(unsigne unsigned long gla, gfn = gpa >> PAGE_SHIFT; mfn_t mfn; p2m_type_t p2mt; + int ret; struct domain *d = current->domain; if ( tb_init_done ) @@ -2017,18 +2019,33 @@ static void ept_handle_violation(unsigne _d.gpa = gpa; _d.qualification = qualification; _d.mfn = mfn_x(get_gfn_query_unlocked(d, gfn, &_d.p2mt)); - + __trace_var(TRC_HVM_NPF, 0, sizeof(_d), &_d); } - if ( hvm_hap_nested_page_fault(gpa, + ret = hvm_hap_nested_page_fault(gpa, qualification & EPT_GLA_VALID ? 1 : 0, qualification & EPT_GLA_VALID ? __vmread(GUEST_LINEAR_ADDRESS) : ~0ull, qualification & EPT_READ_VIOLATION ? 1 : 0, qualification & EPT_WRITE_VIOLATION ? 1 : 0, - qualification & EPT_EXEC_VIOLATION ? 1 : 0) ) + qualification & EPT_EXEC_VIOLATION ? 1 : 0); + switch ( ret ) + { + case 0: // Unhandled L1 EPT violation + break; + case 1: // This violation is handled completly + /*Current nested EPT maybe flushed by other vcpus, so need + * to re-set its shadow EPTP pointer. + */ + if ( nestedhvm_vcpu_in_guestmode(current) && + nestedhvm_paging_mode_hap(current ) ) + __vmwrite(EPT_POINTER, get_shadow_eptp(current)); return; + case -1: // This vioaltion should be injected to L1 VMM + vcpu_nestedhvm(current).nv_vmexit_pending = 1; + return; + } /* Everything else is an error. */ mfn = get_gfn_query_unlocked(d, gfn, &p2mt); diff -r 4056e5a3d815 -r 0d20a4939690 xen/arch/x86/hvm/vmx/vvmx.c --- a/xen/arch/x86/hvm/vmx/vvmx.c Tue Jan 15 11:17:01 2013 +0100 +++ b/xen/arch/x86/hvm/vmx/vvmx.c Tue Jan 15 11:18:46 2013 +0100 @@ -41,6 +41,7 @@ int nvmx_vcpu_initialise(struct vcpu *v) gdprintk(XENLOG_ERR, "nest: allocation for shadow vmcs failed\n"); goto out; } + nvmx->ept.enabled = 0; nvmx->vmxon_region_pa = 0; nvcpu->nv_vvmcx = NULL; nvcpu->nv_vvmcxaddr = VMCX_EADDR; @@ -96,9 +97,11 @@ uint64_t nvmx_vcpu_guestcr3(struct vcpu uint64_t nvmx_vcpu_eptp_base(struct vcpu *v) { - /* TODO */ - ASSERT(0); - return 0; + uint64_t eptp_base; + struct nestedvcpu *nvcpu = &vcpu_nestedhvm(v); + + eptp_base = __get_vvmcs(nvcpu->nv_vvmcx, EPT_POINTER); + return eptp_base & PAGE_MASK; } uint32_t nvmx_vcpu_asid(struct vcpu *v) @@ -108,6 +111,13 @@ uint32_t nvmx_vcpu_asid(struct vcpu *v) return 0; } +bool_t nvmx_ept_enabled(struct vcpu *v) +{ + struct nestedvmx *nvmx = &vcpu_2_nvmx(v); + + return !!(nvmx->ept.enabled); +} + static const enum x86_segment sreg_to_index[] = { [VMX_SREG_ES] = x86_seg_es, [VMX_SREG_CS] = x86_seg_cs, @@ -502,14 +512,16 @@ void nvmx_update_exec_control(struct vcp } void nvmx_update_secondary_exec_control(struct vcpu *v, - unsigned long value) + unsigned long host_cntrl) { u32 shadow_cntrl; struct nestedvcpu *nvcpu = &vcpu_nestedhvm(v); + struct nestedvmx *nvmx = &vcpu_2_nvmx(v); shadow_cntrl = __get_vvmcs(nvcpu->nv_vvmcx, SECONDARY_VM_EXEC_CONTROL); - shadow_cntrl |= value; - set_shadow_control(v, SECONDARY_VM_EXEC_CONTROL, shadow_cntrl); + nvmx->ept.enabled = !!(shadow_cntrl & SECONDARY_EXEC_ENABLE_EPT); + shadow_cntrl |= host_cntrl; + __vmwrite(SECONDARY_VM_EXEC_CONTROL, shadow_cntrl); } static void nvmx_update_pin_control(struct vcpu *v, unsigned long host_cntrl) @@ -874,6 +886,16 @@ static void load_shadow_guest_state(stru /* TODO: CR3 target control */ } +uint64_t get_shadow_eptp(struct vcpu *v) +{ + uint64_t np2m_base = nvmx_vcpu_eptp_base(v); + struct p2m_domain *p2m = p2m_get_nestedp2m(v, np2m_base); + struct ept_data *ept = &p2m->ept; + + ept->asr = pagetable_get_pfn(p2m_get_pagetable(p2m)); + return ept_get_eptp(ept); +} + static void virtual_vmentry(struct cpu_user_regs *regs) { struct vcpu *v = current; @@ -918,7 +940,10 @@ static void virtual_vmentry(struct cpu_u /* updating host cr0 to sync TS bit */ __vmwrite(HOST_CR0, v->arch.hvm_vmx.host_cr0); - /* TODO: EPT_POINTER */ + /* Setup virtual ETP for L2 guest*/ + if ( nestedhvm_paging_mode_hap(v) ) + __vmwrite(EPT_POINTER, get_shadow_eptp(v)); + } static void sync_vvmcs_guest_state(struct vcpu *v, struct cpu_user_regs *regs) @@ -952,8 +977,8 @@ static void sync_vvmcs_ro(struct vcpu *v /* 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); + __set_vvmcs(vvmcs, EXIT_QUALIFICATION, nvmx->ept.exit_qual); + __set_vvmcs(vvmcs, VM_EXIT_REASON, nvmx->ept.exit_reason); } } @@ -1520,8 +1545,8 @@ nvmx_hap_walk_L1_p2m(struct vcpu *v, pad 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; + nvmx->ept.exit_reason = exit_reason; + nvmx->ept.exit_qual = exit_qual; break; case EPT_TRANSLATE_RETRY: rc = NESTEDHVM_PAGEFAULT_RETRY; diff -r 4056e5a3d815 -r 0d20a4939690 xen/include/asm-x86/hvm/vmx/vvmx.h --- a/xen/include/asm-x86/hvm/vmx/vvmx.h Tue Jan 15 11:17:01 2013 +0100 +++ b/xen/include/asm-x86/hvm/vmx/vvmx.h Tue Jan 15 11:18:46 2013 +0100 @@ -33,9 +33,10 @@ struct nestedvmx { u32 error_code; } intr; struct { + bool_t enabled; uint32_t exit_reason; uint32_t exit_qual; - } ept_exit; + } ept; }; #define vcpu_2_nvmx(v) (vcpu_nestedhvm(v).u.nvmx) @@ -110,6 +111,8 @@ int nvmx_intercepts_exception(struct vcp unsigned int trap, int error_code); void nvmx_domain_relinquish_resources(struct domain *d); +bool_t nvmx_ept_enabled(struct vcpu *v); + int nvmx_handle_vmxon(struct cpu_user_regs *regs); int nvmx_handle_vmxoff(struct cpu_user_regs *regs); @@ -178,6 +181,8 @@ enum vvmcs_encoding_type { u64 __get_vvmcs(void *vvmcs, u32 vmcs_encoding); void __set_vvmcs(void *vvmcs, u32 vmcs_encoding, u64 val); +uint64_t get_shadow_eptp(struct vcpu *v); + void nvmx_destroy_vmcs(struct vcpu *v); int nvmx_handle_vmptrld(struct cpu_user_regs *regs); int nvmx_handle_vmptrst(struct cpu_user_regs *regs); _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |