xen.org
2011-Jun-01 02:14 UTC
[Xen-devel] [xen-4.1-testing test] 7468: tolerable FAIL - PUSHED
flight 7468 xen-4.1-testing real [real] http://www.chiark.greenend.org.uk/~xensrcts/logs/7468/ Failures :-/ but no regressions. Tests which did not succeed, but are not blocking, including regressions (tests previously passed) regarded as allowable: test-amd64-amd64-win 16 leak-check/check fail never pass test-amd64-amd64-xl-win 13 guest-stop fail never pass test-amd64-i386-rhel6hvm-amd 8 guest-saverestore fail never pass test-amd64-i386-rhel6hvm-intel 8 guest-saverestore fail never pass test-amd64-i386-win-vcpus1 16 leak-check/check fail never pass test-amd64-i386-win 16 leak-check/check fail never pass test-amd64-i386-xl-win-vcpus1 13 guest-stop fail never pass test-amd64-xcpkern-i386-pair 16 guest-start fail like 7329 test-amd64-xcpkern-i386-rhel6hvm-amd 8 guest-saverestore fail never pass test-amd64-xcpkern-i386-rhel6hvm-intel 8 guest-saverestore fail never pass test-amd64-xcpkern-i386-win 16 leak-check/check fail never pass test-amd64-xcpkern-i386-xl-win 13 guest-stop fail never pass test-i386-i386-win 16 leak-check/check fail never pass test-i386-i386-xl-win 13 guest-stop fail never pass test-i386-xcpkern-i386-win 16 leak-check/check fail never pass version targeted for testing: xen dbe9e02a1f75 baseline version: xen 61336bbb0002 ------------------------------------------------------------ People who touched revisions under test: Ian Campbell <Ian.Campbell@citrix.com> Ian Jackson <ian.jackson@eu.citrix.com> Jim Fehlig <jfehlig@novell.com> Keir Fraser <keir@xen.org> Li, Xin <xin.li@intel.com> Tim Deegan <Tim.Deegan@citrix.com> Yang, Wei <wei.y.yang@intel.com> ------------------------------------------------------------ jobs: build-i386-xcpkern pass build-amd64 pass build-i386 pass build-amd64-oldkern pass build-i386-oldkern pass build-amd64-pvops pass build-i386-pvops pass test-amd64-amd64-xl pass test-amd64-i386-xl pass test-i386-i386-xl pass test-amd64-xcpkern-i386-xl pass test-i386-xcpkern-i386-xl pass test-amd64-i386-rhel6hvm-amd fail test-amd64-xcpkern-i386-rhel6hvm-amd fail test-amd64-i386-xl-credit2 pass test-amd64-xcpkern-i386-xl-credit2 pass test-amd64-i386-rhel6hvm-intel fail test-amd64-xcpkern-i386-rhel6hvm-intel fail test-amd64-i386-xl-multivcpu pass test-amd64-xcpkern-i386-xl-multivcpu pass test-amd64-amd64-pair pass test-amd64-i386-pair pass test-i386-i386-pair pass test-amd64-xcpkern-i386-pair fail test-i386-xcpkern-i386-pair pass test-amd64-amd64-pv pass test-amd64-i386-pv pass test-i386-i386-pv pass test-amd64-xcpkern-i386-pv pass test-i386-xcpkern-i386-pv pass test-amd64-i386-win-vcpus1 fail test-amd64-i386-xl-win-vcpus1 fail test-amd64-amd64-win fail test-amd64-i386-win fail test-i386-i386-win fail test-amd64-xcpkern-i386-win fail test-i386-xcpkern-i386-win fail test-amd64-amd64-xl-win fail test-i386-i386-xl-win fail test-amd64-xcpkern-i386-xl-win fail ------------------------------------------------------------ sg-report-flight on woking.cam.xci-test.com logs: /home/xc_osstest/logs images: /home/xc_osstest/images Logs, config files, etc. are available at http://www.chiark.greenend.org.uk/~xensrcts/logs Test harness code can be found at http://xenbits.xensource.com/gitweb?p=osstest.git;a=summary Pushing revision : + branch=xen-4.1-testing + revision=dbe9e02a1f75 + . cri-lock-repos ++ . cri-common +++ umask 002 +++ getconfig Repos +++ perl -e '' use Osstest; readconfigonly(); print $c{Repos} or die $!; '' ++ repos=/export/home/osstest/repos ++ repos_lock=/export/home/osstest/repos/lock ++ ''['' x ''!='' x/export/home/osstest/repos/lock '']'' ++ OSSTEST_REPOS_LOCK_LOCKED=/export/home/osstest/repos/lock ++ exec with-lock-ex -w /export/home/osstest/repos/lock ./ap-push xen-4.1-testing dbe9e02a1f75 + branch=xen-4.1-testing + revision=dbe9e02a1f75 + . cri-lock-repos ++ . cri-common +++ umask 002 +++ getconfig Repos +++ perl -e '' use Osstest; readconfigonly(); print $c{Repos} or die $!; '' ++ repos=/export/home/osstest/repos ++ repos_lock=/export/home/osstest/repos/lock ++ ''['' x/export/home/osstest/repos/lock ''!='' x/export/home/osstest/repos/lock '']'' + : xen@xenbits.xensource.com + : xen@xenbits.xensource.com:git/linux-pvops + : master + case "$branch" in + cd /export/home/osstest/repos/xen-4.1-testing.hg + hg push -r dbe9e02a1f75 ssh://xen@xenbits.xensource.com/HG/xen-4.1-testing.hg pushing to ssh://xen@xenbits.xensource.com/HG/xen-4.1-testing.hg searching for changes remote: adding changesets remote: adding manifests remote: adding file changes remote: added 5 changesets with 9 changes to 9 files _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Extend nhvm_vmcx_guest_intercepts_trap to include errcode to assist decision of TRAP_page_fault in VMX. Thanks, Eddie diff -r 0c446850d85e xen/arch/x86/hvm/hvm.c --- a/xen/arch/x86/hvm/hvm.c Wed May 11 12:58:04 2011 +0100 +++ b/xen/arch/x86/hvm/hvm.c Tue May 31 17:58:08 2011 +0800 @@ -1152,7 +1152,7 @@ return; } - if ( nhvm_vmcx_guest_intercepts_trap(v, trapnr) ) + if ( nhvm_vmcx_guest_intercepts_trap(v, trapnr, errcode) ) { enum nestedhvm_vmexits nsret; @@ -4175,10 +4175,10 @@ return -EOPNOTSUPP; } -int nhvm_vmcx_guest_intercepts_trap(struct vcpu *v, unsigned int trap) +int nhvm_vmcx_guest_intercepts_trap(struct vcpu *v, unsigned int trap, int errcode) { if (hvm_funcs.nhvm_vmcx_guest_intercepts_trap) - return hvm_funcs.nhvm_vmcx_guest_intercepts_trap(v, trap); + return hvm_funcs.nhvm_vmcx_guest_intercepts_trap(v, trap, errcode); return -EOPNOTSUPP; } diff -r 0c446850d85e xen/arch/x86/hvm/svm/nestedsvm.c --- a/xen/arch/x86/hvm/svm/nestedsvm.c Wed May 11 12:58:04 2011 +0100 +++ b/xen/arch/x86/hvm/svm/nestedsvm.c Tue May 31 17:58:08 2011 +0800 @@ -895,7 +895,7 @@ } int -nsvm_vmcb_guest_intercepts_trap(struct vcpu *v, unsigned int trapnr) +nsvm_vmcb_guest_intercepts_trap(struct vcpu *v, unsigned int trapnr, int errcode) { return nsvm_vmcb_guest_intercepts_exitcode(v, guest_cpu_user_regs(), VMEXIT_EXCEPTION_DE + trapnr); diff -r 0c446850d85e xen/include/asm-x86/hvm/hvm.h --- a/xen/include/asm-x86/hvm/hvm.h Wed May 11 12:58:04 2011 +0100 +++ b/xen/include/asm-x86/hvm/hvm.h Tue May 31 17:58:08 2011 +0800 @@ -164,7 +164,8 @@ uint64_t (*nhvm_vcpu_guestcr3)(struct vcpu *v); uint64_t (*nhvm_vcpu_hostcr3)(struct vcpu *v); uint32_t (*nhvm_vcpu_asid)(struct vcpu *v); - int (*nhvm_vmcx_guest_intercepts_trap)(struct vcpu *v, unsigned int trapnr); + int (*nhvm_vmcx_guest_intercepts_trap)(struct vcpu *v, + unsigned int trapnr, int errcode); bool_t (*nhvm_vmcx_hap_enabled)(struct vcpu *v); @@ -443,7 +444,8 @@ uint32_t nhvm_vcpu_asid(struct vcpu *v); /* returns true, when l1 guest intercepts the specified trap */ -int nhvm_vmcx_guest_intercepts_trap(struct vcpu *v, unsigned int trapnr); +int nhvm_vmcx_guest_intercepts_trap(struct vcpu *v, + unsigned int trapnr, int errcode); /* returns true when l1 guest wants to use hap to run l2 guest */ bool_t nhvm_vmcx_hap_enabled(struct vcpu *v); diff -r 0c446850d85e xen/include/asm-x86/hvm/svm/nestedsvm.h --- a/xen/include/asm-x86/hvm/svm/nestedsvm.h Wed May 11 12:58:04 2011 +0100 +++ b/xen/include/asm-x86/hvm/svm/nestedsvm.h Tue May 31 17:58:08 2011 +0800 @@ -114,7 +114,8 @@ uint32_t nsvm_vcpu_asid(struct vcpu *v); int nsvm_vmcb_guest_intercepts_exitcode(struct vcpu *v, struct cpu_user_regs *regs, uint64_t exitcode); -int nsvm_vmcb_guest_intercepts_trap(struct vcpu *v, unsigned int trapnr); +int nsvm_vmcb_guest_intercepts_trap(struct vcpu *v, unsigned int trapnr, + int errcode); bool_t nsvm_vmcb_hap_enabled(struct vcpu *v); enum hvm_intblk nsvm_intr_blocked(struct vcpu *v); _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Move IDT_VECTORING processing code out of intr_assist for simplicity. Thx, Eddie diff -r 9aa31694b91e xen/arch/x86/hvm/vmx/vmx.c --- a/xen/arch/x86/hvm/vmx/vmx.c Tue May 31 17:58:09 2011 +0800 +++ b/xen/arch/x86/hvm/vmx/vmx.c Wed Jun 01 08:44:03 2011 +0800 @@ -2098,6 +2098,33 @@ return 0; } +static void vmx_idtv_reinject(unsigned long idtv_info) +{ + + /* Event delivery caused this intercept? Queue for redelivery. */ + if ( unlikely(idtv_info & INTR_INFO_VALID_MASK) ) + { + if ( hvm_event_needs_reinjection((idtv_info>>8)&7, idtv_info&0xff) ) + { + /* See SDM 3B 25.7.1.1 and .2 for info about masking resvd bits. */ + __vmwrite(VM_ENTRY_INTR_INFO, + idtv_info & ~INTR_INFO_RESVD_BITS_MASK); + if ( idtv_info & INTR_INFO_DELIVER_CODE_MASK ) + __vmwrite(VM_ENTRY_EXCEPTION_ERROR_CODE, + __vmread(IDT_VECTORING_ERROR_CODE)); + } + + /* + * Clear NMI-blocking interruptibility info if an NMI delivery faulted. + * Re-delivery will re-set it (see SDM 3B 25.7.1.2). + */ + if ( (idtv_info & INTR_INFO_INTR_TYPE_MASK) == (X86_EVENTTYPE_NMI<<8) ) + __vmwrite(GUEST_INTERRUPTIBILITY_INFO, + __vmread(GUEST_INTERRUPTIBILITY_INFO) & + ~VMX_INTR_SHADOW_NMI); + } +} + asmlinkage void vmx_vmexit_handler(struct cpu_user_regs *regs) { unsigned int exit_reason, idtv_info, intr_info = 0, vector = 0; @@ -2187,30 +2214,9 @@ hvm_maybe_deassert_evtchn_irq(); - /* Event delivery caused this intercept? Queue for redelivery. */ idtv_info = __vmread(IDT_VECTORING_INFO); - if ( unlikely(idtv_info & INTR_INFO_VALID_MASK) && - (exit_reason != EXIT_REASON_TASK_SWITCH) ) - { - if ( hvm_event_needs_reinjection((idtv_info>>8)&7, idtv_info&0xff) ) - { - /* See SDM 3B 25.7.1.1 and .2 for info about masking resvd bits. */ - __vmwrite(VM_ENTRY_INTR_INFO, - idtv_info & ~INTR_INFO_RESVD_BITS_MASK); - if ( idtv_info & INTR_INFO_DELIVER_CODE_MASK ) - __vmwrite(VM_ENTRY_EXCEPTION_ERROR_CODE, - __vmread(IDT_VECTORING_ERROR_CODE)); - } - - /* - * Clear NMI-blocking interruptibility info if an NMI delivery faulted. - * Re-delivery will re-set it (see SDM 3B 25.7.1.2). - */ - if ( (idtv_info & INTR_INFO_INTR_TYPE_MASK) == (X86_EVENTTYPE_NMI<<8) ) - __vmwrite(GUEST_INTERRUPTIBILITY_INFO, - __vmread(GUEST_INTERRUPTIBILITY_INFO) & - ~VMX_INTR_SHADOW_NMI); - } + if ( exit_reason != EXIT_REASON_TASK_SWITCH ) + vmx_idtv_reinject(idtv_info); switch ( exit_reason ) { _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Dong, Eddie
2011-Jun-01 03:49 UTC
[Xen-devel] RFC: Nested VMX patch series 01: data structure
Thanks, Eddie Signed-off-by: Qing He <qing.he@intel.com> Signed-off-by: Eddie Dong <eddie.dong@intel.com> diff -r 9aa31694b91e xen/include/asm-x86/hvm/vcpu.h --- a/xen/include/asm-x86/hvm/vcpu.h Tue May 31 17:58:09 2011 +0800 +++ b/xen/include/asm-x86/hvm/vcpu.h Tue May 31 18:00:58 2011 +0800 @@ -24,6 +24,7 @@ #include <asm/hvm/io.h> #include <asm/hvm/vlapic.h> #include <asm/hvm/vmx/vmcs.h> +#include <asm/hvm/vmx/vvmx.h> #include <asm/hvm/svm/vmcb.h> #include <asm/hvm/svm/nestedsvm.h> #include <asm/mtrr.h> @@ -57,6 +58,7 @@ /* SVM/VMX arch specific */ union { struct nestedsvm nsvm; + struct nestedvmx nvmx; } u; bool_t nv_flushp2m; /* True, when p2m table must be flushed */ diff -r 9aa31694b91e xen/include/asm-x86/hvm/vmx/vvmx.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xen/include/asm-x86/hvm/vmx/vvmx.h Tue May 31 18:00:58 2011 +0800 @@ -0,0 +1,41 @@ + +/* + * vvmx.h: Support virtual VMX for nested virtualization. + * + * Copyright (c) 2010, Intel Corporation. + * Author: Qing He <qing.he@intel.com> + * Eddie Dong <eddie.dong@intel.com> + * + * 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. + * + */ +#ifndef __ASM_X86_HVM_VVMX_H__ +#define __ASM_X86_HVM_VVMX_H__ + +struct vmcs_struct; + +struct nestedvmx { + paddr_t vmxon_region_pa; + void *iobitmap[2]; /* map (va) of L1 guest I/O bitmap */ + /* deferred nested interrupt */ + struct { + unsigned long intr_info; + u32 error_code; + } intr; +}; + +#define nvcpu_2_nvmx(nv) ((*(nv)).u.nvmx) +#define vcpu_2_nvmx(v) (nvcpu_2_nvmx(&vcpu_nestedhvm(v))) +#endif /* __ASM_X86_HVM_VVMX_H__ */ + _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Wrap for common nested APIs. Thx, Eddie Signed-off-by: Qing He <qing.he@intel.com> Signed-off-by: Eddie Dong <eddie.dong@intel.com> diff -r 70ee714947fb xen/arch/x86/hvm/hvm.c --- a/xen/arch/x86/hvm/hvm.c Sat May 28 09:49:25 2011 +0800 +++ b/xen/arch/x86/hvm/hvm.c Mon May 30 17:15:52 2011 +0800 @@ -3502,7 +3502,7 @@ /* Remove the check below once we have * shadow-on-shadow. */ - if ( !paging_mode_hap(d) && a.value ) + if ( cpu_has_svm && !paging_mode_hap(d) && a.value ) rc = -EINVAL; /* Set up NHVM state for any vcpus that are already up */ if ( !d->arch.hvm_domain.params[HVM_PARAM_NESTEDHVM] ) diff -r 70ee714947fb xen/arch/x86/hvm/vmx/Makefile --- a/xen/arch/x86/hvm/vmx/Makefile Sat May 28 09:49:25 2011 +0800 +++ b/xen/arch/x86/hvm/vmx/Makefile Mon May 30 17:15:52 2011 +0800 @@ -4,3 +4,4 @@ obj-y += vmcs.o obj-y += vmx.o obj-y += vpmu_core2.o +obj-y += vvmx.o diff -r 70ee714947fb xen/arch/x86/hvm/vmx/intr.c --- a/xen/arch/x86/hvm/vmx/intr.c Sat May 28 09:49:25 2011 +0800 +++ b/xen/arch/x86/hvm/vmx/intr.c Mon May 30 17:15:52 2011 +0800 @@ -109,6 +109,11 @@ } } +enum hvm_intblk nvmx_intr_blocked(struct vcpu *v) +{ + return hvm_intblk_none; +} + asmlinkage void vmx_intr_assist(void) { struct hvm_intack intack; diff -r 70ee714947fb xen/arch/x86/hvm/vmx/vmx.c --- a/xen/arch/x86/hvm/vmx/vmx.c Sat May 28 09:49:25 2011 +0800 +++ b/xen/arch/x86/hvm/vmx/vmx.c Mon May 30 17:15:52 2011 +0800 @@ -1407,7 +1407,14 @@ .invlpg_intercept = vmx_invlpg_intercept, .set_uc_mode = vmx_set_uc_mode, .set_info_guest = vmx_set_info_guest, - .set_rdtsc_exiting = vmx_set_rdtsc_exiting + .set_rdtsc_exiting = vmx_set_rdtsc_exiting, + .nhvm_vcpu_initialise = nvmx_vcpu_initialise, + .nhvm_vcpu_destroy = nvmx_vcpu_destroy, + .nhvm_vcpu_reset = nvmx_vcpu_reset, + .nhvm_vcpu_guestcr3 = nvmx_vcpu_guestcr3, + .nhvm_vcpu_hostcr3 = nvmx_vcpu_hostcr3, + .nhvm_vcpu_asid = nvmx_vcpu_asid, + .nhvm_intr_blocked = nvmx_intr_blocked }; struct hvm_function_table * __init start_vmx(void) diff -r 70ee714947fb xen/arch/x86/hvm/vmx/vvmx.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xen/arch/x86/hvm/vmx/vvmx.c Mon May 30 17:15:52 2011 +0800 @@ -0,0 +1,93 @@ +/* + * vvmx.c: Support virtual VMX for nested virtualization. + * + * Copyright (c) 2010, Intel Corporation. + * Author: Qing He <qing.he@intel.com> + * Eddie Dong <eddie.dong@intel.com> + * + * 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 <xen/config.h> +#include <asm/types.h> +#include <asm/p2m.h> +#include <asm/hvm/vmx/vmx.h> +#include <asm/hvm/vmx/vvmx.h> + +int nvmx_vcpu_initialise(struct vcpu *v) +{ + struct nestedvmx *nvmx = &vcpu_2_nvmx(v); + struct nestedvcpu *nvcpu = &vcpu_nestedhvm(v); + + nvcpu->nv_n2vmcx = alloc_xenheap_page(); + if ( !nvcpu->nv_n2vmcx ) + { + gdprintk(XENLOG_ERR, "nest: allocation for shadow vmcs failed\n"); + goto out; + } + nvmx->vmxon_region_pa = 0; + nvcpu->nv_vvmcx = NULL; + nvcpu->nv_vvmcxaddr = VMCX_EADDR; + nvmx->intr.intr_info = 0; + nvmx->intr.error_code = 0; + nvmx->iobitmap[0] = NULL; + nvmx->iobitmap[1] = NULL; + return 0; +out: + return -ENOMEM; +} + +void nvmx_vcpu_destroy(struct vcpu *v) +{ + struct nestedvcpu *nvcpu = &vcpu_nestedhvm(v); + + if ( nvcpu->nv_n2vmcx ) { + __vmpclear(virt_to_maddr(nvcpu->nv_n2vmcx)); + free_xenheap_page(nvcpu->nv_n2vmcx); + nvcpu->nv_n2vmcx = NULL; + } + if ( nvcpu->nv_vvmcx ) { + unmap_domain_page_global(nvcpu->nv_vvmcx); + nvcpu->nv_vvmcx == NULL; + } + nvcpu->nv_vvmcxaddr = VMCX_EADDR; +} + +int nvmx_vcpu_reset(struct vcpu *v) +{ + return 0; +} + +uint64_t nvmx_vcpu_guestcr3(struct vcpu *v) +{ + /* TODO */ + ASSERT(0); + return 0; +} + +uint64_t nvmx_vcpu_hostcr3(struct vcpu *v) +{ + /* TODO */ + ASSERT(0); + return 0; +} + +uint32_t nvmx_vcpu_asid(struct vcpu *v) +{ + /* TODO */ + ASSERT(0); + return 0; +} + diff -r 70ee714947fb xen/include/asm-x86/hvm/vmx/vvmx.h --- a/xen/include/asm-x86/hvm/vmx/vvmx.h Sat May 28 09:49:25 2011 +0800 +++ b/xen/include/asm-x86/hvm/vmx/vvmx.h Mon May 30 17:15:52 2011 +0800 @@ -37,5 +37,14 @@ #define nvcpu_2_nvmx(nv) ((*(nv)).u.nvmx) #define vcpu_2_nvmx(v) (nvcpu_2_nvmx(&vcpu_nestedhvm(v))) + +int nvmx_vcpu_initialise(struct vcpu *v); +void nvmx_vcpu_destroy(struct vcpu *v); +int nvmx_vcpu_reset(struct vcpu *v); +uint64_t nvmx_vcpu_guestcr3(struct vcpu *v); +uint64_t nvmx_vcpu_hostcr3(struct vcpu *v); +uint32_t nvmx_vcpu_asid(struct vcpu *v); +enum hvm_intblk nvmx_intr_blocked(struct vcpu *v); + #endif /* __ASM_X86_HVM_VVMX_H__ */ _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
VMXON_OFF processing Thx, Eddie Signed-off-by: Qing He <qing.he@intel.com> Signed-off-by: Eddie Dong <eddie.dong@intel.com> diff -r 7a9c7fbdabc0 xen/arch/x86/hvm/vmx/Makefile --- a/xen/arch/x86/hvm/vmx/Makefile Wed Jun 01 08:48:22 2011 +0800 +++ b/xen/arch/x86/hvm/vmx/Makefile Wed Jun 01 09:39:53 2011 +0800 @@ -5,3 +5,4 @@ obj-y += vmx.o obj-y += vpmu_core2.o obj-y += vvmx.o +obj-y += vvmx.o diff -r 7a9c7fbdabc0 xen/arch/x86/hvm/vmx/vmx.c --- a/xen/arch/x86/hvm/vmx/vmx.c Wed Jun 01 08:48:22 2011 +0800 +++ b/xen/arch/x86/hvm/vmx/vmx.c Wed Jun 01 09:39:53 2011 +0800 @@ -2435,6 +2435,16 @@ break; } + case EXIT_REASON_VMXOFF: + if ( nvmx_handle_vmxoff(regs) == X86EMUL_OKAY ) + update_guest_eip(); + break; + + case EXIT_REASON_VMXON: + if ( nvmx_handle_vmxon(regs) == X86EMUL_OKAY ) + update_guest_eip(); + break; + case EXIT_REASON_MWAIT_INSTRUCTION: case EXIT_REASON_MONITOR_INSTRUCTION: case EXIT_REASON_VMCLEAR: @@ -2444,8 +2454,6 @@ case EXIT_REASON_VMREAD: case EXIT_REASON_VMRESUME: case EXIT_REASON_VMWRITE: - case EXIT_REASON_VMXOFF: - case EXIT_REASON_VMXON: case EXIT_REASON_GETSEC: case EXIT_REASON_INVEPT: case EXIT_REASON_INVVPID: diff -r 7a9c7fbdabc0 xen/arch/x86/hvm/vmx/vvmx.c --- a/xen/arch/x86/hvm/vmx/vvmx.c Wed Jun 01 08:48:22 2011 +0800 +++ b/xen/arch/x86/hvm/vmx/vvmx.c Wed Jun 01 09:39:53 2011 +0800 @@ -91,3 +91,281 @@ return 0; } +/* + * Encode of VMX instructions base on Table 24-11 & 24-12 of SDM 3B + */ + +enum vmx_regs_enc { + VMX_REG_RAX, + VMX_REG_RCX, + VMX_REG_RDX, + VMX_REG_RBX, + VMX_REG_RSP, + VMX_REG_RBP, + VMX_REG_RSI, + VMX_REG_RDI, +#ifdef CONFIG_X86_64 + VMX_REG_R8, + VMX_REG_R9, + VMX_REG_R10, + VMX_REG_R11, + VMX_REG_R12, + VMX_REG_R13, + VMX_REG_R14, + VMX_REG_R15, +#endif +}; + +enum vmx_sregs_enc { + VMX_SREG_ES, + VMX_SREG_CS, + VMX_SREG_SS, + VMX_SREG_DS, + VMX_SREG_FS, + VMX_SREG_GS, +}; + +union vmx_inst_info { + struct { + unsigned int scaling :2; /* bit 0-1 */ + unsigned int __rsvd0 :1; /* bit 2 */ + unsigned int reg1 :4; /* bit 3-6 */ + unsigned int addr_size :3; /* bit 7-9 */ + unsigned int memreg :1; /* bit 10 */ + unsigned int __rsvd1 :4; /* bit 11-14 */ + unsigned int segment :3; /* bit 15-17 */ + unsigned int index_reg :4; /* bit 18-21 */ + unsigned int index_reg_invalid :1; /* bit 22 */ + unsigned int base_reg :4; /* bit 23-26 */ + unsigned int base_reg_invalid :1; /* bit 27 */ + unsigned int reg2 :4; /* bit 28-31 */ + } fields; + u32 word; +}; + +enum x86_segment sreg_to_index[] = { + [VMX_SREG_ES] = x86_seg_es, + [VMX_SREG_CS] = x86_seg_cs, + [VMX_SREG_SS] = x86_seg_ss, + [VMX_SREG_DS] = x86_seg_ds, + [VMX_SREG_FS] = x86_seg_fs, + [VMX_SREG_GS] = x86_seg_gs, +}; + +struct vmx_inst_decoded { +#define VMX_INST_MEMREG_TYPE_MEMORY 0 +#define VMX_INST_MEMREG_TYPE_REG 1 + int type; + union { + struct { + unsigned long mem; + unsigned int len; + }; + enum vmx_regs_enc reg1; + }; + + enum vmx_regs_enc reg2; +}; + +enum vmx_ops_result { + VMSUCCEED, + VMFAIL_VALID, + VMFAIL_INVALID, +}; + +#define CASE_GET_REG(REG, reg) \ + case VMX_REG_ ## REG: value = regs->reg; break + +static unsigned long reg_read(struct cpu_user_regs *regs, + enum vmx_regs_enc index) +{ + unsigned long value = 0; + + switch ( index ) { + CASE_GET_REG(RAX, eax); + CASE_GET_REG(RCX, ecx); + CASE_GET_REG(RDX, edx); + CASE_GET_REG(RBX, ebx); + CASE_GET_REG(RBP, ebp); + CASE_GET_REG(RSI, esi); + CASE_GET_REG(RDI, edi); + CASE_GET_REG(RSP, esp); +#ifdef CONFIG_X86_64 + CASE_GET_REG(R8, r8); + CASE_GET_REG(R9, r9); + CASE_GET_REG(R10, r10); + CASE_GET_REG(R11, r11); + CASE_GET_REG(R12, r12); + CASE_GET_REG(R13, r13); + CASE_GET_REG(R14, r14); + CASE_GET_REG(R15, r15); +#endif + default: + break; + } + + return value; +} + +static int vmx_inst_check_privilege(struct cpu_user_regs *regs, int vmxop_check) +{ + struct vcpu *v = current; + struct segment_register cs; + + hvm_get_segment_register(v, x86_seg_cs, &cs); + + if ( vmxop_check ) + { + if ( !(v->arch.hvm_vcpu.guest_cr[0] & X86_CR0_PE) || + !(v->arch.hvm_vcpu.guest_cr[4] & X86_CR4_VMXE) ) + goto invalid_op; + } + else if ( !vcpu_2_nvmx(v).vmxon_region_pa ) + goto invalid_op; + + if ( (regs->eflags & X86_EFLAGS_VM) || + (hvm_long_mode_enabled(v) && cs.attr.fields.l == 0) ) + goto invalid_op; + /* TODO: check vmx operation mode */ + + if ( (cs.sel & 3) > 0 ) + goto gp_fault; + + return X86EMUL_OKAY; + +invalid_op: + gdprintk(XENLOG_ERR, "vmx_inst_check_privilege: invalid_op\n"); + hvm_inject_exception(TRAP_invalid_op, 0, 0); + return X86EMUL_EXCEPTION; + +gp_fault: + gdprintk(XENLOG_ERR, "vmx_inst_check_privilege: gp_fault\n"); + hvm_inject_exception(TRAP_gp_fault, 0, 0); + return X86EMUL_EXCEPTION; +} + +static int decode_vmx_inst(struct cpu_user_regs *regs, + struct vmx_inst_decoded *decode, + unsigned long *poperandS, int vmxon_check) +{ + struct vcpu *v = current; + union vmx_inst_info info; + struct segment_register seg; + unsigned long base, index, seg_base, disp, offset; + int scale, size; + + if ( vmx_inst_check_privilege(regs, vmxon_check) != X86EMUL_OKAY ) + return X86EMUL_EXCEPTION; + + info.word = __vmread(VMX_INSTRUCTION_INFO); + + if ( info.fields.memreg ) { + decode->type = VMX_INST_MEMREG_TYPE_REG; + decode->reg1 = info.fields.reg1; + if ( poperandS != NULL ) + *poperandS = reg_read(regs, decode->reg1); + } + else + { + decode->type = VMX_INST_MEMREG_TYPE_MEMORY; + hvm_get_segment_register(v, sreg_to_index[info.fields.segment], &seg); + /* TODO: segment type check */ + seg_base = seg.base; + + base = info.fields.base_reg_invalid ? 0 : + reg_read(regs, info.fields.base_reg); + + index = info.fields.index_reg_invalid ? 0 : + reg_read(regs, info.fields.index_reg); + + scale = 1 << info.fields.scaling; + + disp = __vmread(EXIT_QUALIFICATION); + + size = 1 << (info.fields.addr_size + 1); + + offset = base + index * scale + disp; + if ( (offset > seg.limit || offset + size > seg.limit) && + (!hvm_long_mode_enabled(v) || info.fields.segment == VMX_SREG_GS) ) + goto gp_fault; + + if ( poperandS != NULL && + hvm_copy_from_guest_virt(poperandS, seg_base + offset, size, 0) + != HVMCOPY_okay ) + return X86EMUL_EXCEPTION; + decode->mem = seg_base + offset; + decode->len = size; + } + + decode->reg2 = info.fields.reg2; + + return X86EMUL_OKAY; + +gp_fault: + hvm_inject_exception(TRAP_gp_fault, 0, 0); + return X86EMUL_EXCEPTION; +} + +static void vmreturn(struct cpu_user_regs *regs, enum vmx_ops_result ops_res) +{ + unsigned long eflags = regs->eflags; + unsigned long mask = X86_EFLAGS_CF | X86_EFLAGS_PF | X86_EFLAGS_AF | + X86_EFLAGS_ZF | X86_EFLAGS_SF | X86_EFLAGS_OF; + + eflags &= ~mask; + + switch ( ops_res ) { + case VMSUCCEED: + break; + case VMFAIL_VALID: + /* TODO: error number, useful for guest VMM debugging */ + eflags |= X86_EFLAGS_ZF; + break; + case VMFAIL_INVALID: + default: + eflags |= X86_EFLAGS_CF; + break; + } + + regs->eflags = eflags; +} + +/* + * VMX instructions handling + */ + +int nvmx_handle_vmxon(struct cpu_user_regs *regs) +{ + struct vcpu *v=current; + struct nestedvmx *nvmx = &vcpu_2_nvmx(v); + struct vmx_inst_decoded decode; + unsigned long gpa = 0; + int rc; + + rc = decode_vmx_inst(regs, &decode, &gpa, 1); + if ( rc != X86EMUL_OKAY ) + return rc; + + nvmx->vmxon_region_pa = gpa; + vmreturn(regs, VMSUCCEED); + + return X86EMUL_OKAY; + +} + +int nvmx_handle_vmxoff(struct cpu_user_regs *regs) +{ + struct vcpu *v=current; + struct nestedvmx *nvmx = &vcpu_2_nvmx(v); + int rc; + + rc = vmx_inst_check_privilege(regs, 0); + if ( rc != X86EMUL_OKAY ) + return rc; + + nvmx->vmxon_region_pa = 0; + + vmreturn(regs, VMSUCCEED); + return X86EMUL_OKAY; +} + diff -r 7a9c7fbdabc0 xen/include/asm-x86/hvm/vmx/vvmx.h --- a/xen/include/asm-x86/hvm/vmx/vvmx.h Wed Jun 01 08:48:22 2011 +0800 +++ b/xen/include/asm-x86/hvm/vmx/vvmx.h Wed Jun 01 09:39:53 2011 +0800 @@ -46,5 +46,7 @@ uint32_t nvmx_vcpu_asid(struct vcpu *v); enum hvm_intblk nvmx_intr_blocked(struct vcpu *v); +int nvmx_handle_vmxon(struct cpu_user_regs *regs); +int nvmx_handle_vmxoff(struct cpu_user_regs *regs); #endif /* __ASM_X86_HVM_VVMX_H__ */ _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Dong, Eddie
2011-Jun-01 03:55 UTC
[Xen-devel] RFC: Nested VMX patch series 04: virtual VMCS structure and APIs
Virtual VMCS structure and access wrapper APIs Thx, Eddie Signed-off-by: Qing He <qing.he@intel.com> Signed-off-by: Eddie Dong <eddie.dong@intel.com> diff -r f0647d3c60dc xen/arch/x86/hvm/vmx/vvmx.c --- a/xen/arch/x86/hvm/vmx/vvmx.c Sat May 28 23:20:01 2011 +0800 +++ b/xen/arch/x86/hvm/vmx/vvmx.c Mon May 30 15:07:17 2011 +0800 @@ -183,6 +183,84 @@ #define CASE_GET_REG(REG, reg) \ case VMX_REG_ ## REG: value = regs->reg; break +static int vvmcs_offset(u32 width, u32 type, u32 index) +{ + int offset; + + offset = (index & 0x1f) | type << 5 | width << 7; + + if ( offset == 0 ) /* vpid */ + offset = 0x3f; + + return offset; +} + +u64 __get_vvmcs(void *vvmcs, u32 vmcs_encoding) +{ + union vmcs_encoding enc; + u64 *content = (u64 *) vvmcs; + int offset; + u64 res; + + enc.word = vmcs_encoding; + offset = vvmcs_offset(enc.width, enc.type, enc.index); + res = content[offset]; + + switch ( enc.width ) { + case VVMCS_WIDTH_16: + res &= 0xffff; + break; + case VVMCS_WIDTH_64: + if ( enc.access_type ) + res >>= 32; + break; + case VVMCS_WIDTH_32: + res &= 0xffffffff; + break; + case VVMCS_WIDTH_NATURAL: + default: + break; + } + + return res; +} + +void __set_vvmcs(void *vvmcs, u32 vmcs_encoding, u64 val) +{ + union vmcs_encoding enc; + u64 *content = (u64 *) vvmcs; + int offset; + u64 res; + + enc.word = vmcs_encoding; + offset = vvmcs_offset(enc.width, enc.type, enc.index); + res = content[offset]; + + switch ( enc.width ) { + case VVMCS_WIDTH_16: + res = val & 0xffff; + break; + case VVMCS_WIDTH_64: + if ( enc.access_type ) + { + res &= 0xffffffff; + res |= val << 32; + } + else + res = val; + break; + case VVMCS_WIDTH_32: + res = val & 0xffffffff; + break; + case VVMCS_WIDTH_NATURAL: + default: + res = val; + break; + } + + content[offset] = res; +} + static unsigned long reg_read(struct cpu_user_regs *regs, enum vmx_regs_enc index) { diff -r f0647d3c60dc xen/include/asm-x86/hvm/vmx/vvmx.h --- a/xen/include/asm-x86/hvm/vmx/vvmx.h Sat May 28 23:20:01 2011 +0800 +++ b/xen/include/asm-x86/hvm/vmx/vvmx.h Mon May 30 15:07:17 2011 +0800 @@ -23,6 +23,9 @@ #ifndef __ASM_X86_HVM_VVMX_H__ #define __ASM_X86_HVM_VVMX_H__ +#include <xen/config.h> +#include <asm/types.h> + struct vmcs_struct; struct nestedvmx { @@ -48,5 +51,61 @@ int nvmx_handle_vmxon(struct cpu_user_regs *regs); int nvmx_handle_vmxoff(struct cpu_user_regs *regs); +/* + * Virtual VMCS layout + * + * Since physical VMCS layout is unknown, a custom layout is used + * for virtual VMCS seen by guest. It occupies a 4k page, and the + * field is offset by an 9-bit offset into u64[], The offset is as + * follow, which means every <width, type> pair has a max of 32 + * fields available. + * + * 9 7 5 0 + * -------------------------------- + * offset: | width | type | index | + * -------------------------------- + * + * Also, since the lower range <width=0, type={0,1}> has only one + * field: VPID, it is moved to a higher offset (63), and leaves the + * lower range to non-indexed field like VMCS revision. + * + */ + +#define VVMCS_REVISION 0x40000001u + +struct vvmcs_header { + u32 revision; + u32 abort; +}; + +union vmcs_encoding { + struct { + u32 access_type : 1; + u32 index : 9; + u32 type : 2; + u32 rsv1 : 1; + u32 width : 2; + u32 rsv2 : 17; + }; + u32 word; +}; + +enum vvmcs_encoding_width { + VVMCS_WIDTH_16 = 0, + VVMCS_WIDTH_64, + VVMCS_WIDTH_32, + VVMCS_WIDTH_NATURAL, +}; + +enum vvmcs_encoding_type { + VVMCS_TYPE_CONTROL = 0, + VVMCS_TYPE_RO, + VVMCS_TYPE_GSTATE, + VVMCS_TYPE_HSTATE, +}; + +u64 __get_vvmcs(void *vvmcs, u32 vmcs_encoding); +void __set_vvmcs(void *vvmcs, u32 vmcs_encoding, u64 val); + #endif /* __ASM_X86_HVM_VVMX_H__ */ _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Thx, Eddie Signed-off-by: Qing He <qing.he@intel.com> Signed-off-by: Eddie Dong <eddie.dong@intel.com> diff -r c7820e886afc xen/arch/x86/hvm/vmx/vmx.c --- a/xen/arch/x86/hvm/vmx/vmx.c Wed Jun 01 08:48:22 2011 +0800 +++ b/xen/arch/x86/hvm/vmx/vmx.c Wed Jun 01 09:18:29 2011 +0800 @@ -2445,11 +2445,15 @@ update_guest_eip(); break; + case EXIT_REASON_VMPTRLD: + if ( nvmx_handle_vmptrld(regs) == X86EMUL_OKAY ) + update_guest_eip(); + break; + case EXIT_REASON_MWAIT_INSTRUCTION: case EXIT_REASON_MONITOR_INSTRUCTION: case EXIT_REASON_VMCLEAR: case EXIT_REASON_VMLAUNCH: - case EXIT_REASON_VMPTRLD: case EXIT_REASON_VMPTRST: case EXIT_REASON_VMREAD: case EXIT_REASON_VMRESUME: diff -r c7820e886afc xen/arch/x86/hvm/vmx/vvmx.c --- a/xen/arch/x86/hvm/vmx/vvmx.c Wed Jun 01 08:48:22 2011 +0800 +++ b/xen/arch/x86/hvm/vmx/vvmx.c Wed Jun 01 09:18:29 2011 +0800 @@ -410,6 +410,42 @@ regs->eflags = eflags; } +static void __map_io_bitmap(struct vcpu *v, u64 vmcs_reg) +{ + struct nestedvmx *nvmx = &vcpu_2_nvmx(v); + struct nestedvcpu *nvcpu = &vcpu_nestedhvm(v); + unsigned long gpa; + unsigned long mfn; + p2m_type_t p2mt; + + if ( vmcs_reg == IO_BITMAP_A ) + { + if (nvmx->iobitmap[0]) { + unmap_domain_page_global(nvmx->iobitmap[0]); + } + gpa = __get_vvmcs(nvcpu->nv_vvmcx, IO_BITMAP_A); + mfn = mfn_x(gfn_to_mfn(p2m_get_hostp2m(v->domain), + gpa >> PAGE_SHIFT, &p2mt)); + nvmx->iobitmap[0] = map_domain_page_global(mfn); + } + else if ( vmcs_reg == IO_BITMAP_B ) + { + if (nvmx->iobitmap[1]) { + unmap_domain_page_global(nvmx->iobitmap[1]); + } + gpa = __get_vvmcs(nvcpu->nv_vvmcx, IO_BITMAP_B); + mfn = mfn_x(gfn_to_mfn(p2m_get_hostp2m(v->domain), + gpa >> PAGE_SHIFT, &p2mt)); + nvmx->iobitmap[1] = map_domain_page_global(mfn); + } +} + +static inline void map_io_bitmap_all(struct vcpu *v) +{ + __map_io_bitmap (v, IO_BITMAP_A); + __map_io_bitmap (v, IO_BITMAP_B); +} + /* * VMX instructions handling */ @@ -418,6 +454,7 @@ { struct vcpu *v=current; struct nestedvmx *nvmx = &vcpu_2_nvmx(v); + struct nestedvcpu *nvcpu = &vcpu_nestedhvm(v); struct vmx_inst_decoded decode; unsigned long gpa = 0; int rc; @@ -426,11 +463,25 @@ if ( rc != X86EMUL_OKAY ) return rc; + if ( nvmx->vmxon_region_pa ) + gdprintk(XENLOG_WARNING, + "vmxon again: orig %lx new %lx\n", + nvmx->vmxon_region_pa, gpa); + nvmx->vmxon_region_pa = gpa; + + /* + * `fork'' the host vmcs to shadow_vmcs + * vmcs_lock is not needed since we are on current + */ + nvcpu->nv_n1vmcx = v->arch.hvm_vmx.vmcs; + __vmpclear(virt_to_maddr(v->arch.hvm_vmx.vmcs)); + memcpy(nvcpu->nv_n2vmcx, v->arch.hvm_vmx.vmcs, PAGE_SIZE); + __vmptrld(virt_to_maddr(v->arch.hvm_vmx.vmcs)); + v->arch.hvm_vmx.launched = 0; vmreturn(regs, VMSUCCEED); return X86EMUL_OKAY; - } int nvmx_handle_vmxoff(struct cpu_user_regs *regs) @@ -449,3 +500,39 @@ return X86EMUL_OKAY; } +int nvmx_handle_vmptrld(struct cpu_user_regs *regs) +{ + struct vcpu *v = current; + struct vmx_inst_decoded decode; + struct nestedvmx *nvmx = &vcpu_2_nvmx(v); + struct nestedvcpu *nvcpu = &vcpu_nestedhvm(v); + unsigned long gpa = 0; + unsigned long mfn; + p2m_type_t p2mt; + int rc; + + rc = decode_vmx_inst(regs, &decode, &gpa, 0); + if ( rc != X86EMUL_OKAY ) + return rc; + + if ( gpa == nvmx->vmxon_region_pa || gpa & 0xfff ) + { + vmreturn(regs, VMFAIL_INVALID); + goto out; + } + + if ( nvcpu->nv_vvmcxaddr == VMCX_EADDR ) + { + mfn = mfn_x(gfn_to_mfn(p2m_get_hostp2m(v->domain), + gpa >> PAGE_SHIFT, &p2mt)); + nvcpu->nv_vvmcx = map_domain_page_global(mfn); + nvcpu->nv_vvmcxaddr = gpa; + map_io_bitmap_all (v); + } + + vmreturn(regs, VMSUCCEED); + +out: + return X86EMUL_OKAY; +} + diff -r c7820e886afc xen/include/asm-x86/hvm/vmx/vvmx.h --- a/xen/include/asm-x86/hvm/vmx/vvmx.h Wed Jun 01 08:48:22 2011 +0800 +++ b/xen/include/asm-x86/hvm/vmx/vvmx.h Wed Jun 01 09:18:29 2011 +0800 @@ -107,5 +107,8 @@ u64 __get_vvmcs(void *vvmcs, u32 vmcs_encoding); void __set_vvmcs(void *vvmcs, u32 vmcs_encoding, u64 val); +void nvmx_destroy_vmcs(struct vcpu *v); +int nvmx_handle_vmptrld(struct cpu_user_regs *regs); + #endif /* __ASM_X86_HVM_VVMX_H__ */ _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Dong, Eddie
2011-Jun-01 03:57 UTC
RE: [Xen-devel] RFC: Nested VMX patch series 05: vmptrst
Thx, Eddie Signed-off-by: Qing He <qing.he@intel.com> Signed-off-by: Eddie Dong <eddie.dong@intel.com> diff -r 474da95963e2 xen/arch/x86/hvm/vmx/vmx.c --- a/xen/arch/x86/hvm/vmx/vmx.c Wed Jun 01 09:18:30 2011 +0800 +++ b/xen/arch/x86/hvm/vmx/vmx.c Wed Jun 01 09:19:19 2011 +0800 @@ -2450,11 +2450,15 @@ update_guest_eip(); break; + case EXIT_REASON_VMPTRST: + if ( nvmx_handle_vmptrst(regs) == X86EMUL_OKAY ) + update_guest_eip(); + break; + case EXIT_REASON_MWAIT_INSTRUCTION: case EXIT_REASON_MONITOR_INSTRUCTION: case EXIT_REASON_VMCLEAR: case EXIT_REASON_VMLAUNCH: - case EXIT_REASON_VMPTRST: case EXIT_REASON_VMREAD: case EXIT_REASON_VMRESUME: case EXIT_REASON_VMWRITE: diff -r 474da95963e2 xen/arch/x86/hvm/vmx/vvmx.c --- a/xen/arch/x86/hvm/vmx/vvmx.c Wed Jun 01 09:18:30 2011 +0800 +++ b/xen/arch/x86/hvm/vmx/vvmx.c Wed Jun 01 09:19:19 2011 +0800 @@ -536,3 +536,25 @@ return X86EMUL_OKAY; } +int nvmx_handle_vmptrst(struct cpu_user_regs *regs) +{ + struct vcpu *v = current; + struct vmx_inst_decoded decode; + struct nestedvcpu *nvcpu = &vcpu_nestedhvm(v); + unsigned long gpa = 0; + int rc; + + rc = decode_vmx_inst(regs, &decode, &gpa, 0); + if ( rc != X86EMUL_OKAY ) + return rc; + + gpa = nvcpu->nv_vvmcxaddr; + + rc = hvm_copy_to_guest_virt(decode.mem, &gpa, decode.len, 0); + if ( rc != HVMCOPY_okay ) + return X86EMUL_EXCEPTION; + + vmreturn(regs, VMSUCCEED); + return X86EMUL_OKAY; +} + diff -r 474da95963e2 xen/include/asm-x86/hvm/vmx/vvmx.h --- a/xen/include/asm-x86/hvm/vmx/vvmx.h Wed Jun 01 09:18:30 2011 +0800 +++ b/xen/include/asm-x86/hvm/vmx/vvmx.h Wed Jun 01 09:19:19 2011 +0800 @@ -109,6 +109,7 @@ 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); #endif /* __ASM_X86_HVM_VVMX_H__ */ _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Thx, Eddie Signed-off-by: Qing He <qing.he@intel.com> Signed-off-by: Eddie Dong <eddie.dong@intel.com> diff -r 4c4c2256d301 xen/arch/x86/hvm/vmx/vmx.c --- a/xen/arch/x86/hvm/vmx/vmx.c Wed Jun 01 09:10:36 2011 +0800 +++ b/xen/arch/x86/hvm/vmx/vmx.c Wed Jun 01 09:13:45 2011 +0800 @@ -2445,6 +2445,11 @@ update_guest_eip(); break; + case EXIT_REASON_VMCLEAR: + if ( nvmx_handle_vmclear(regs) == X86EMUL_OKAY ) + update_guest_eip(); + break; + case EXIT_REASON_VMPTRLD: if ( nvmx_handle_vmptrld(regs) == X86EMUL_OKAY ) update_guest_eip(); @@ -2457,7 +2462,6 @@ case EXIT_REASON_MWAIT_INSTRUCTION: case EXIT_REASON_MONITOR_INSTRUCTION: - case EXIT_REASON_VMCLEAR: case EXIT_REASON_VMLAUNCH: case EXIT_REASON_VMREAD: case EXIT_REASON_VMRESUME: diff -r 4c4c2256d301 xen/arch/x86/hvm/vmx/vvmx.c --- a/xen/arch/x86/hvm/vmx/vvmx.c Wed Jun 01 09:10:36 2011 +0800 +++ b/xen/arch/x86/hvm/vmx/vvmx.c Wed Jun 01 09:13:45 2011 +0800 @@ -410,6 +410,14 @@ regs->eflags = eflags; } +static void __clear_current_vvmcs(struct vcpu *v) +{ + struct nestedvcpu *nvcpu = &vcpu_nestedhvm(v); + + if ( nvcpu->nv_n2vmcx ) + __vmpclear(virt_to_maddr(nvcpu->nv_n2vmcx)); +} + static void __map_io_bitmap(struct vcpu *v, u64 vmcs_reg) { struct nestedvmx *nvmx = &vcpu_2_nvmx(v); @@ -446,6 +454,26 @@ __map_io_bitmap (v, IO_BITMAP_B); } +static void nvmx_purge_vvmcs(struct vcpu *v) +{ + struct nestedvmx *nvmx = &vcpu_2_nvmx(v); + struct nestedvcpu *nvcpu = &vcpu_nestedhvm(v); + + __clear_current_vvmcs(v); + if ( nvcpu->nv_vvmcxaddr != VMCX_EADDR ) + unmap_domain_page_global(nvcpu->nv_vvmcx); + nvcpu->nv_vvmcx == NULL; + nvcpu->nv_vvmcxaddr = VMCX_EADDR; + if ( nvmx->iobitmap[0] ) { + unmap_domain_page_global(nvmx->iobitmap[0]); + nvmx->iobitmap[0] = NULL; + } + if ( nvmx->iobitmap[1] ) { + unmap_domain_page_global(nvmx->iobitmap[1]); + nvmx->iobitmap[1] = NULL; + } +} + /* * VMX instructions handling */ @@ -494,6 +522,7 @@ if ( rc != X86EMUL_OKAY ) return rc; + nvmx_purge_vvmcs(v); nvmx->vmxon_region_pa = 0; vmreturn(regs, VMSUCCEED); @@ -521,6 +550,9 @@ goto out; } + if ( nvcpu->nv_vvmcxaddr != gpa ) + nvmx_purge_vvmcs(v); + if ( nvcpu->nv_vvmcxaddr == VMCX_EADDR ) { mfn = mfn_x(gfn_to_mfn(p2m_get_hostp2m(v->domain), @@ -558,3 +590,37 @@ return X86EMUL_OKAY; } +int nvmx_handle_vmclear(struct cpu_user_regs *regs) +{ + struct vcpu *v = current; + struct vmx_inst_decoded decode; + struct nestedvcpu *nvcpu = &vcpu_nestedhvm(v); + unsigned long gpa = 0; + int rc; + + rc = decode_vmx_inst(regs, &decode, &gpa, 0); + if ( rc != X86EMUL_OKAY ) + return rc; + + if ( gpa & 0xfff ) + { + vmreturn(regs, VMFAIL_INVALID); + goto out; + } + + if ( gpa != nvcpu->nv_vvmcxaddr && nvcpu->nv_vvmcxaddr != VMCX_EADDR ) + { + gdprintk(XENLOG_WARNING, + "vmclear gpa %lx not the same with current vmcs %lx\n", + gpa, nvcpu->nv_vvmcxaddr); + vmreturn(regs, VMSUCCEED); + goto out; + } + nvmx_purge_vvmcs(v); + + vmreturn(regs, VMSUCCEED); + +out: + return X86EMUL_OKAY; +} + diff -r 4c4c2256d301 xen/include/asm-x86/hvm/vmx/vvmx.h --- a/xen/include/asm-x86/hvm/vmx/vvmx.h Wed Jun 01 09:10:36 2011 +0800 +++ b/xen/include/asm-x86/hvm/vmx/vvmx.h Wed Jun 01 09:13:45 2011 +0800 @@ -110,6 +110,7 @@ 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); +int nvmx_handle_vmclear(struct cpu_user_regs *regs); #endif /* __ASM_X86_HVM_VVMX_H__ */ _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Thx, Eddie Signed-off-by: Qing He <qing.he@intel.com> Signed-off-by: Eddie Dong <eddie.dong@intel.com> diff -r 135cec9c2aac xen/arch/x86/hvm/vmx/vmx.c --- a/xen/arch/x86/hvm/vmx/vmx.c Wed Jun 01 09:19:39 2011 +0800 +++ b/xen/arch/x86/hvm/vmx/vmx.c Wed Jun 01 09:23:22 2011 +0800 @@ -2460,12 +2460,16 @@ update_guest_eip(); break; + case EXIT_REASON_VMWRITE: + if ( nvmx_handle_vmwrite(regs) == X86EMUL_OKAY ) + update_guest_eip(); + break; + case EXIT_REASON_MWAIT_INSTRUCTION: case EXIT_REASON_MONITOR_INSTRUCTION: case EXIT_REASON_VMLAUNCH: case EXIT_REASON_VMREAD: case EXIT_REASON_VMRESUME: - case EXIT_REASON_VMWRITE: case EXIT_REASON_GETSEC: case EXIT_REASON_INVEPT: case EXIT_REASON_INVVPID: diff -r 135cec9c2aac xen/arch/x86/hvm/vmx/vvmx.c --- a/xen/arch/x86/hvm/vmx/vvmx.c Wed Jun 01 09:19:39 2011 +0800 +++ b/xen/arch/x86/hvm/vmx/vvmx.c Wed Jun 01 09:23:22 2011 +0800 @@ -624,3 +624,27 @@ return X86EMUL_OKAY; } +int nvmx_handle_vmwrite(struct cpu_user_regs *regs) +{ + struct vcpu *v = current; + struct vmx_inst_decoded decode; + struct nestedvcpu *nvcpu = &vcpu_nestedhvm(v); + u64 operandS, vmcs_encoding; + + if ( decode_vmx_inst(regs, &decode, &operandS, 0) + != X86EMUL_OKAY ) + return X86EMUL_EXCEPTION; + + vmcs_encoding = reg_read(regs, decode.reg2); + __set_vvmcs(nvcpu->nv_vvmcx, vmcs_encoding, operandS); + + if ( vmcs_encoding == IO_BITMAP_A || vmcs_encoding == IO_BITMAP_A_HIGH ) + __map_io_bitmap (v, IO_BITMAP_A); + else if ( vmcs_encoding == IO_BITMAP_B || + vmcs_encoding == IO_BITMAP_B_HIGH ) + __map_io_bitmap (v, IO_BITMAP_B); + + vmreturn(regs, VMSUCCEED); + return X86EMUL_OKAY; +} + diff -r 135cec9c2aac xen/include/asm-x86/hvm/vmx/vvmx.h --- a/xen/include/asm-x86/hvm/vmx/vvmx.h Wed Jun 01 09:19:39 2011 +0800 +++ b/xen/include/asm-x86/hvm/vmx/vvmx.h Wed Jun 01 09:23:22 2011 +0800 @@ -111,6 +111,7 @@ int nvmx_handle_vmptrld(struct cpu_user_regs *regs); int nvmx_handle_vmptrst(struct cpu_user_regs *regs); int nvmx_handle_vmclear(struct cpu_user_regs *regs); +int nvmx_handle_vmwrite(struct cpu_user_regs *regs); #endif /* __ASM_X86_HVM_VVMX_H__ */ _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Thx, Eddie Signed-off-by: Qing He <qing.he@intel.com> Signed-off-by: Eddie Dong <eddie.dong@intel.com> diff -r 4838d3cb1e85 xen/arch/x86/hvm/vmx/vmx.c --- a/xen/arch/x86/hvm/vmx/vmx.c Wed Jun 01 09:40:14 2011 +0800 +++ b/xen/arch/x86/hvm/vmx/vmx.c Wed Jun 01 09:40:43 2011 +0800 @@ -2460,6 +2460,11 @@ update_guest_eip(); break; + case EXIT_REASON_VMREAD: + if ( nvmx_handle_vmread(regs) == X86EMUL_OKAY ) + update_guest_eip(); + break; + case EXIT_REASON_VMWRITE: if ( nvmx_handle_vmwrite(regs) == X86EMUL_OKAY ) update_guest_eip(); @@ -2468,7 +2473,6 @@ case EXIT_REASON_MWAIT_INSTRUCTION: case EXIT_REASON_MONITOR_INSTRUCTION: case EXIT_REASON_VMLAUNCH: - case EXIT_REASON_VMREAD: case EXIT_REASON_VMRESUME: case EXIT_REASON_GETSEC: case EXIT_REASON_INVEPT: diff -r 4838d3cb1e85 xen/arch/x86/hvm/vmx/vvmx.c --- a/xen/arch/x86/hvm/vmx/vvmx.c Wed Jun 01 09:40:14 2011 +0800 +++ b/xen/arch/x86/hvm/vmx/vvmx.c Wed Jun 01 09:40:43 2011 +0800 @@ -173,6 +173,8 @@ VMFAIL_INVALID, }; +#define CASE_SET_REG(REG, reg) \ + case VMX_REG_ ## REG: regs->reg = value; break #define CASE_GET_REG(REG, reg) \ case VMX_REG_ ## REG: value = regs->reg; break @@ -285,6 +287,32 @@ return value; } +static void reg_write(struct cpu_user_regs *regs, + enum vmx_regs_enc index, + unsigned long value) +{ + switch ( index ) { + CASE_SET_REG(RAX, eax); + CASE_SET_REG(RCX, ecx); + CASE_SET_REG(RDX, edx); + CASE_SET_REG(RBX, ebx); + CASE_SET_REG(RBP, ebp); + CASE_SET_REG(RSI, esi); + CASE_SET_REG(RDI, edi); + CASE_SET_REG(RSP, esp); + CASE_SET_REG(R8, r8); + CASE_SET_REG(R9, r9); + CASE_SET_REG(R10, r10); + CASE_SET_REG(R11, r11); + CASE_SET_REG(R12, r12); + CASE_SET_REG(R13, r13); + CASE_SET_REG(R14, r14); + CASE_SET_REG(R15, r15); + default: + break; + } +} + static int vmx_inst_check_privilege(struct cpu_user_regs *regs, int vmxop_check) { struct vcpu *v = current; @@ -622,6 +650,35 @@ return X86EMUL_OKAY; } +int nvmx_handle_vmread(struct cpu_user_regs *regs) +{ + struct vcpu *v = current; + struct vmx_inst_decoded decode; + struct nestedvcpu *nvcpu = &vcpu_nestedhvm(v); + u64 value = 0; + int rc; + + rc = decode_vmx_inst(regs, &decode, NULL, 0); + if ( rc != X86EMUL_OKAY ) + return rc; + + value = __get_vvmcs(nvcpu->nv_vvmcx, reg_read(regs, decode.reg2)); + + switch ( decode.type ) { + case VMX_INST_MEMREG_TYPE_MEMORY: + rc = hvm_copy_to_guest_virt(decode.mem, &value, decode.len, 0); + if ( rc != HVMCOPY_okay ) + return X86EMUL_EXCEPTION; + break; + case VMX_INST_MEMREG_TYPE_REG: + reg_write(regs, decode.reg1, value); + break; + } + + vmreturn(regs, VMSUCCEED); + return X86EMUL_OKAY; +} + int nvmx_handle_vmwrite(struct cpu_user_regs *regs) { struct vcpu *v = current; diff -r 4838d3cb1e85 xen/include/asm-x86/hvm/vmx/vvmx.h --- a/xen/include/asm-x86/hvm/vmx/vvmx.h Wed Jun 01 09:40:14 2011 +0800 +++ b/xen/include/asm-x86/hvm/vmx/vvmx.h Wed Jun 01 09:40:43 2011 +0800 @@ -111,6 +111,7 @@ int nvmx_handle_vmptrld(struct cpu_user_regs *regs); int nvmx_handle_vmptrst(struct cpu_user_regs *regs); int nvmx_handle_vmclear(struct cpu_user_regs *regs); +int nvmx_handle_vmread(struct cpu_user_regs *regs); int nvmx_handle_vmwrite(struct cpu_user_regs *regs); #endif /* __ASM_X86_HVM_VVMX_H__ */ _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Dong, Eddie
2011-Jun-01 04:01 UTC
[Xen-devel] RFC: Nested VMX patch series 10: vmcs switching API
Thx, Eddie Signed-off-by: Qing He <qing.he@intel.com> Signed-off-by: Eddie Dong <eddie.dong@intel.com> diff -r e6ae904dc440 xen/arch/x86/hvm/vmx/vmcs.c --- a/xen/arch/x86/hvm/vmx/vmcs.c Tue May 31 18:01:17 2011 +0800 +++ b/xen/arch/x86/hvm/vmx/vmcs.c Wed Jun 01 08:34:24 2011 +0800 @@ -669,6 +669,38 @@ } } +/* + * Switch VMCS between layer 1 & 2 guest + */ +void vmx_vmcs_switch(struct vcpu *v, + struct vmcs_struct *from, + struct vmcs_struct *to) +{ + /* no foreign access */ + if ( unlikely(v != current) ) + return; + + if ( unlikely(current->arch.hvm_vmx.vmcs != from) ) + return; + + spin_lock(&v->arch.hvm_vmx.vmcs_lock); + + __vmpclear(virt_to_maddr(from)); + __vmptrld(virt_to_maddr(to)); + + v->arch.hvm_vmx.vmcs = to; + v->arch.hvm_vmx.launched = 0; + this_cpu(current_vmcs) = to; + + if ( v->arch.hvm_vmx.hostenv_migrated ) + { + v->arch.hvm_vmx.hostenv_migrated = 0; + vmx_set_host_env(v); + } + + spin_unlock(&v->arch.hvm_vmx.vmcs_lock); +} + static int construct_vmcs(struct vcpu *v) { struct domain *d = v->domain; @@ -1078,6 +1110,13 @@ hvm_migrate_timers(v); hvm_migrate_pirqs(v); vmx_set_host_env(v); + /* + * Both n1 VMCS and n2 VMCS need to update the host environment after + * VCPU migration. The environment of current VMCS is updated in place, + * but the action of another VMCS is deferred till it is switched in. + */ + v->arch.hvm_vmx.hostenv_migrated = 1; + hvm_asid_flush_vcpu(v); } diff -r e6ae904dc440 xen/include/asm-x86/hvm/vmx/vmcs.h --- a/xen/include/asm-x86/hvm/vmx/vmcs.h Tue May 31 18:01:17 2011 +0800 +++ b/xen/include/asm-x86/hvm/vmx/vmcs.h Wed Jun 01 08:34:24 2011 +0800 @@ -123,6 +123,7 @@ struct segment_register vm86_saved_seg[x86_seg_tr + 1]; /* Remember EFLAGS while in virtual 8086 mode */ uint32_t vm86_saved_eflags; + int hostenv_migrated; }; int vmx_create_vmcs(struct vcpu *v); @@ -390,6 +391,9 @@ int vmx_write_guest_msr(u32 msr, u64 val); int vmx_add_guest_msr(u32 msr); int vmx_add_host_load_msr(u32 msr); +void vmx_vmcs_switch(struct vcpu *v, + struct vmcs_struct *from, + struct vmcs_struct *to); #endif /* ASM_X86_HVM_VMX_VMCS_H__ */ _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Thx, Eddie Signed-off-by: Qing He <qing.he@intel.com> Signed-off-by: Eddie Dong <eddie.dong@intel.com> diff -r 599f4aacabeb xen/arch/x86/hvm/vmx/vmx.c --- a/xen/arch/x86/hvm/vmx/vmx.c Fri May 27 17:35:24 2011 +0800 +++ b/xen/arch/x86/hvm/vmx/vmx.c Fri May 27 17:46:40 2011 +0800 @@ -2142,6 +2142,11 @@ /* Now enable interrupts so it''s safe to take locks. */ local_irq_enable(); + /* XXX: This looks ugly, but we need a mechanism to ensure + * any pending vmresume has really happened + */ + vcpu_nestedhvm(v).nv_vmswitch_in_progress = 0; + if ( unlikely(exit_reason & VMX_EXIT_REASONS_FAILED_VMENTRY) ) return vmx_failed_vmentry(exit_reason, regs); @@ -2457,10 +2462,18 @@ update_guest_eip(); break; + case EXIT_REASON_VMLAUNCH: + if ( nvmx_handle_vmlaunch(regs) == X86EMUL_OKAY ) + update_guest_eip(); + break; + + case EXIT_REASON_VMRESUME: + if ( nvmx_handle_vmresume(regs) == X86EMUL_OKAY ) + update_guest_eip(); + break; + case EXIT_REASON_MWAIT_INSTRUCTION: case EXIT_REASON_MONITOR_INSTRUCTION: - case EXIT_REASON_VMLAUNCH: - case EXIT_REASON_VMRESUME: case EXIT_REASON_GETSEC: case EXIT_REASON_INVEPT: case EXIT_REASON_INVVPID: diff -r 599f4aacabeb xen/arch/x86/hvm/vmx/vvmx.c --- a/xen/arch/x86/hvm/vmx/vvmx.c Fri May 27 17:35:24 2011 +0800 +++ b/xen/arch/x86/hvm/vmx/vvmx.c Fri May 27 17:46:40 2011 +0800 @@ -283,6 +283,13 @@ } } +static inline u32 __n2_exec_control(struct vcpu *v) +{ + struct nestedvcpu *nvcpu = &vcpu_nestedhvm(v); + + return __get_vvmcs(nvcpu->nv_vvmcx, CPU_BASED_VM_EXEC_CONTROL); +} + static int vmx_inst_check_privilege(struct cpu_user_regs *regs, int vmxop_check) { struct vcpu *v = current; @@ -470,6 +477,34 @@ return X86EMUL_OKAY; } +int nvmx_handle_vmresume(struct cpu_user_regs *regs) +{ + struct vcpu *v = current; + struct nestedvmx *nvmx = &vcpu_2_nvmx(v); + struct nestedvcpu *nvcpu = &vcpu_nestedhvm(v); + int rc; + + rc = vmx_inst_check_privilege(regs, 0); + if ( rc != X86EMUL_OKAY ) + return rc; + + /* check VMCS is valid and IO BITMAP is set */ + if ( (nvcpu->nv_vvmcxaddr != VMCX_EADDR) && + ((nvmx->iobitmap[0] && nvmx->iobitmap[1]) || + !(__n2_exec_control(v) & CPU_BASED_ACTIVATE_IO_BITMAP) ) ) + nvcpu->nv_vmentry_pending = 1; + else + vmreturn(regs, VMFAIL_INVALID); + + return X86EMUL_OKAY; +} + +int nvmx_handle_vmlaunch(struct cpu_user_regs *regs) +{ + /* TODO: check for initial launch/resume */ + return nvmx_handle_vmresume(regs); +} + int nvmx_handle_vmptrld(struct cpu_user_regs *regs) { struct vcpu *v = current; diff -r 599f4aacabeb xen/include/asm-x86/hvm/vmx/vvmx.h --- a/xen/include/asm-x86/hvm/vmx/vvmx.h Fri May 27 17:35:24 2011 +0800 +++ b/xen/include/asm-x86/hvm/vmx/vvmx.h Fri May 27 17:46:40 2011 +0800 @@ -103,6 +103,8 @@ int nvmx_handle_vmread(struct cpu_user_regs *regs); int nvmx_handle_vmwrite(struct cpu_user_regs *regs); +int nvmx_handle_vmresume(struct cpu_user_regs *regs); +int nvmx_handle_vmlaunch(struct cpu_user_regs *regs); #endif /* __ASM_X86_HVM_VVMX_H__ */ _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Dong, Eddie
2011-Jun-01 04:03 UTC
[Xen-devel] RFC: Nested VMX patch series 12: shadow vmcs control
Thx, Eddie Signed-off-by: Qing He <qing.he@intel.com> Signed-off-by: Eddie Dong <eddie.dong@intel.com> diff -r 607ce7be0b5c xen/arch/x86/hvm/vmx/vmx.c --- a/xen/arch/x86/hvm/vmx/vmx.c Mon May 30 17:15:56 2011 +0800 +++ b/xen/arch/x86/hvm/vmx/vmx.c Mon May 30 17:38:21 2011 +0800 @@ -54,6 +54,7 @@ #include <asm/xenoprof.h> #include <asm/debugger.h> #include <asm/apic.h> +#include <asm/hvm/nestedhvm.h> enum handler_return { HNDL_done, HNDL_unhandled, HNDL_exception_raised }; @@ -361,18 +362,28 @@ void vmx_update_cpu_exec_control(struct vcpu *v) { - __vmwrite(CPU_BASED_VM_EXEC_CONTROL, v->arch.hvm_vmx.exec_control); + if ( nestedhvm_vcpu_in_guestmode(v) ) + nvmx_update_exec_control(v, v->arch.hvm_vmx.exec_control); + else + __vmwrite(CPU_BASED_VM_EXEC_CONTROL, v->arch.hvm_vmx.exec_control); } static void vmx_update_secondary_exec_control(struct vcpu *v) { - __vmwrite(SECONDARY_VM_EXEC_CONTROL, - v->arch.hvm_vmx.secondary_exec_control); + if ( nestedhvm_vcpu_in_guestmode(v) ) + nvmx_update_secondary_exec_control(v, + v->arch.hvm_vmx.secondary_exec_control); + else + __vmwrite(SECONDARY_VM_EXEC_CONTROL, + v->arch.hvm_vmx.secondary_exec_control); } void vmx_update_exception_bitmap(struct vcpu *v) { - __vmwrite(EXCEPTION_BITMAP, v->arch.hvm_vmx.exception_bitmap); + if ( nestedhvm_vcpu_in_guestmode(v) ) + nvmx_update_exception_bitmap(v, v->arch.hvm_vmx.exception_bitmap); + else + __vmwrite(EXCEPTION_BITMAP, v->arch.hvm_vmx.exception_bitmap); } static int vmx_guest_x86_mode(struct vcpu *v) diff -r 607ce7be0b5c xen/arch/x86/hvm/vmx/vvmx.c --- a/xen/arch/x86/hvm/vmx/vvmx.c Mon May 30 17:15:56 2011 +0800 +++ b/xen/arch/x86/hvm/vmx/vvmx.c Mon May 30 17:38:21 2011 +0800 @@ -25,6 +25,7 @@ #include <asm/p2m.h> #include <asm/hvm/vmx/vmx.h> #include <asm/hvm/vmx/vvmx.h> +#include <asm/hvm/nestedhvm.h> int nvmx_vcpu_initialise(struct vcpu *v) { @@ -443,6 +444,93 @@ regs->eflags = eflags; } +/* + * Nested VMX uses "strict" condition to exit from + * L2 guest if either L1 VMM or L0 VMM expect to exit. + */ +static inline u32 __shadow_control(struct vcpu *v, + unsigned int field, + u32 host_value) +{ + struct nestedvcpu *nvcpu = &vcpu_nestedhvm(v); + + return (u32) __get_vvmcs(nvcpu->nv_vvmcx, field) | host_value; +} + +static void set_shadow_control(struct vcpu *v, + unsigned int field, + u32 host_value) +{ + __vmwrite(field, __shadow_control(v, field, host_value)); +} + +unsigned long *_shadow_io_bitmap(struct vcpu *v) +{ + struct nestedvmx *nvmx = &vcpu_2_nvmx(v); + int port80, portED; + u8 *bitmap; + + bitmap = nvmx->iobitmap[0]; + port80 = bitmap[0x80 >> 3] & (1 << (0x80 & 0x7)) ? 1 : 0; + portED = bitmap[0xed >> 3] & (1 << (0xed & 0x7)) ? 1 : 0; + + return nestedhvm_vcpu_iomap_get(port80, portED); +} + +void nvmx_update_exec_control(struct vcpu *v, unsigned long host_cntrl) +{ +#define PIO_CNTRL_BITS ( CPU_BASED_ACTIVATE_IO_BITMAP \ + | CPU_BASED_UNCOND_IO_EXITING) + u32 pio_cntrl = PIO_CNTRL_BITS; + unsigned long *bitmap; + u32 shadow_cntrl; + + shadow_cntrl = __n2_exec_control(v); + pio_cntrl &= shadow_cntrl; + /* Enforce the removed features */ +#define REMOVED_EXEC_CONTROL_BITS (CPU_BASED_TPR_SHADOW \ + | CPU_BASED_ACTIVATE_MSR_BITMAP \ + | CPU_BASED_ACTIVATE_SECONDARY_CONTROLS \ + | CPU_BASED_ACTIVATE_IO_BITMAP \ + | CPU_BASED_UNCOND_IO_EXITING) + shadow_cntrl &= ~REMOVED_EXEC_CONTROL_BITS; + shadow_cntrl |= host_cntrl; + if ( pio_cntrl == CPU_BASED_UNCOND_IO_EXITING ) { + /* L1 VMM intercepts all I/O instructions */ + shadow_cntrl |= CPU_BASED_UNCOND_IO_EXITING; + shadow_cntrl &= ~CPU_BASED_ACTIVATE_IO_BITMAP; + } + else { + /* Use IO_BITMAP in shadow */ + if ( pio_cntrl == 0 ) { + /* + * L1 VMM doesn''t intercept IO instruction. + * Use host configuration and reset IO_BITMAP + */ + bitmap = hvm_io_bitmap; + } + else { + /* use IO bitmap */ + bitmap = _shadow_io_bitmap(v); + } + __vmwrite(IO_BITMAP_A, virt_to_maddr(bitmap)); + __vmwrite(IO_BITMAP_B, virt_to_maddr(bitmap) + PAGE_SIZE); + } + + __vmwrite(CPU_BASED_VM_EXEC_CONTROL, shadow_cntrl); +} + +void nvmx_update_secondary_exec_control(struct vcpu *v, + unsigned long value) +{ + set_shadow_control(v, SECONDARY_VM_EXEC_CONTROL, value); +} + +void nvmx_update_exception_bitmap(struct vcpu *v, unsigned long value) +{ + set_shadow_control(v, EXCEPTION_BITMAP, value); +} + static void __clear_current_vvmcs(struct vcpu *v) { struct nestedvcpu *nvcpu = &vcpu_nestedhvm(v); diff -r 607ce7be0b5c xen/include/asm-x86/hvm/vmx/vvmx.h --- a/xen/include/asm-x86/hvm/vmx/vvmx.h Mon May 30 17:15:56 2011 +0800 +++ b/xen/include/asm-x86/hvm/vmx/vvmx.h Mon May 30 17:38:21 2011 +0800 @@ -117,5 +117,10 @@ int nvmx_handle_vmresume(struct cpu_user_regs *regs); int nvmx_handle_vmlaunch(struct cpu_user_regs *regs); +void nvmx_update_exec_control(struct vcpu *v, unsigned long value); +void nvmx_update_secondary_exec_control(struct vcpu *v, + unsigned long value); +void nvmx_update_exception_bitmap(struct vcpu *v, unsigned long value); + #endif /* __ASM_X86_HVM_VVMX_H__ */ _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Dong, Eddie
2011-Jun-01 04:04 UTC
[Xen-devel] RFC: Nested VMX patch series 12: real VMCS switch
Thx, Eddie Signed-off-by: Qing He <qing.he@intel.com> Signed-off-by: Eddie Dong <eddie.dong@intel.com> diff -r 091f56f71a32 xen/arch/x86/hvm/vmx/entry.S --- a/xen/arch/x86/hvm/vmx/entry.S Mon May 30 17:38:21 2011 +0800 +++ b/xen/arch/x86/hvm/vmx/entry.S Mon May 30 17:40:15 2011 +0800 @@ -119,6 +119,7 @@ .globl vmx_asm_do_vmentry vmx_asm_do_vmentry: call vmx_intr_assist + call nvmx_switch_layed_guest get_current(bx) cli diff -r 091f56f71a32 xen/arch/x86/hvm/vmx/vvmx.c --- a/xen/arch/x86/hvm/vmx/vvmx.c Mon May 30 17:38:21 2011 +0800 +++ b/xen/arch/x86/hvm/vmx/vvmx.c Mon May 30 17:40:15 2011 +0800 @@ -526,6 +526,48 @@ set_shadow_control(v, SECONDARY_VM_EXEC_CONTROL, value); } +static void nvmx_update_pin_control(struct vcpu *v, + unsigned long host_cntrl) +{ + u32 shadow_cntrl; + struct nestedvcpu *nvcpu = &vcpu_nestedhvm(v); + +#define REMOVED_PIN_CONTROL_BITS (PIN_BASED_PREEMPT_TIMER) + shadow_cntrl = __get_vvmcs(nvcpu->nv_vvmcx, PIN_BASED_VM_EXEC_CONTROL); + shadow_cntrl &= ~REMOVED_PIN_CONTROL_BITS; + shadow_cntrl |= host_cntrl; + __vmwrite(PIN_BASED_VM_EXEC_CONTROL, shadow_cntrl); +} + +static void nvmx_update_exit_control(struct vcpu *v, + unsigned long host_cntrl) +{ + u32 shadow_cntrl; + struct nestedvcpu *nvcpu = &vcpu_nestedhvm(v); + +#define REMOVED_EXIT_CONTROL_BITS ((1<<2) | \ + (VM_EXIT_SAVE_GUEST_PAT) | \ + (VM_EXIT_SAVE_GUEST_EFER) | \ + (VM_EXIT_SAVE_PREEMPT_TIMER)) + shadow_cntrl = __get_vvmcs(nvcpu->nv_vvmcx, VM_EXIT_CONTROLS); + shadow_cntrl &= ~REMOVED_EXIT_CONTROL_BITS; + shadow_cntrl |= host_cntrl; + __vmwrite(VM_EXIT_CONTROLS, shadow_cntrl); +} + +static void nvmx_update_entry_control(struct vcpu *v) +{ + u32 shadow_cntrl; + struct nestedvcpu *nvcpu = &vcpu_nestedhvm(v); + + /* VM_ENTRY_CONTROLS: enforce removed features */ +#define REMOVED_ENTRY_CONTROL_BITS (VM_ENTRY_LOAD_GUEST_PAT \ + | VM_ENTRY_LOAD_GUEST_EFER) + shadow_cntrl = __get_vvmcs(nvcpu->nv_vvmcx, VM_ENTRY_CONTROLS); + shadow_cntrl &= ~REMOVED_ENTRY_CONTROL_BITS; + __vmwrite(VM_ENTRY_CONTROLS, shadow_cntrl); +} + void nvmx_update_exception_bitmap(struct vcpu *v, unsigned long value) { set_shadow_control(v, EXCEPTION_BITMAP, value); @@ -596,6 +638,361 @@ } /* + * Context synchronized between shadow and virtual VMCS. + */ +static unsigned long vmcs_gstate_field[] = { + /* 16 BITS */ + GUEST_ES_SELECTOR, + GUEST_CS_SELECTOR, + GUEST_SS_SELECTOR, + GUEST_DS_SELECTOR, + GUEST_FS_SELECTOR, + GUEST_GS_SELECTOR, + GUEST_LDTR_SELECTOR, + GUEST_TR_SELECTOR, + /* 64 BITS */ + VMCS_LINK_POINTER, + GUEST_IA32_DEBUGCTL, +#ifndef CONFIG_X86_64 + VMCS_LINK_POINTER_HIGH, + GUEST_IA32_DEBUGCTL_HIGH, +#endif + /* 32 BITS */ + GUEST_ES_LIMIT, + GUEST_CS_LIMIT, + GUEST_SS_LIMIT, + GUEST_DS_LIMIT, + GUEST_FS_LIMIT, + GUEST_GS_LIMIT, + GUEST_LDTR_LIMIT, + GUEST_TR_LIMIT, + GUEST_GDTR_LIMIT, + GUEST_IDTR_LIMIT, + GUEST_ES_AR_BYTES, + GUEST_CS_AR_BYTES, + GUEST_SS_AR_BYTES, + GUEST_DS_AR_BYTES, + GUEST_FS_AR_BYTES, + GUEST_GS_AR_BYTES, + GUEST_LDTR_AR_BYTES, + GUEST_TR_AR_BYTES, + GUEST_INTERRUPTIBILITY_INFO, + GUEST_ACTIVITY_STATE, + GUEST_SYSENTER_CS, + /* natural */ + GUEST_ES_BASE, + GUEST_CS_BASE, + GUEST_SS_BASE, + GUEST_DS_BASE, + GUEST_FS_BASE, + GUEST_GS_BASE, + GUEST_LDTR_BASE, + GUEST_TR_BASE, + GUEST_GDTR_BASE, + GUEST_IDTR_BASE, + GUEST_DR7, + /* + * Following guest states are in local cache (cpu_user_regs) + GUEST_RSP, + GUEST_RIP, + */ + GUEST_RFLAGS, + GUEST_PENDING_DBG_EXCEPTIONS, + GUEST_SYSENTER_ESP, + GUEST_SYSENTER_EIP, +}; + +/* + * Context: shadow -> virtual VMCS + */ +static unsigned long vmcs_ro_field[] = { + GUEST_PHYSICAL_ADDRESS, + VM_INSTRUCTION_ERROR, + VM_EXIT_REASON, + VM_EXIT_INTR_INFO, + VM_EXIT_INTR_ERROR_CODE, + IDT_VECTORING_INFO, + IDT_VECTORING_ERROR_CODE, + VM_EXIT_INSTRUCTION_LEN, + VMX_INSTRUCTION_INFO, + EXIT_QUALIFICATION, + GUEST_LINEAR_ADDRESS +}; + +static struct vmcs_host_to_guest { + unsigned long host_field; + unsigned long guest_field; +} vmcs_h2g_field[] = { + {HOST_ES_SELECTOR, GUEST_ES_SELECTOR}, + {HOST_CS_SELECTOR, GUEST_CS_SELECTOR}, + {HOST_SS_SELECTOR, GUEST_SS_SELECTOR}, + {HOST_DS_SELECTOR, GUEST_DS_SELECTOR}, + {HOST_FS_SELECTOR, GUEST_FS_SELECTOR}, + {HOST_GS_SELECTOR, GUEST_GS_SELECTOR}, + {HOST_TR_SELECTOR, GUEST_TR_SELECTOR}, + {HOST_SYSENTER_CS, GUEST_SYSENTER_CS}, + {HOST_FS_BASE, GUEST_FS_BASE}, + {HOST_GS_BASE, GUEST_GS_BASE}, + {HOST_TR_BASE, GUEST_TR_BASE}, + {HOST_GDTR_BASE, GUEST_GDTR_BASE}, + {HOST_IDTR_BASE, GUEST_IDTR_BASE}, + {HOST_SYSENTER_ESP, GUEST_SYSENTER_ESP}, + {HOST_SYSENTER_EIP, GUEST_SYSENTER_EIP}, +}; + +static void vvmcs_to_shadow(void *vvmcs, unsigned int field) +{ + u64 value; + + value = __get_vvmcs(vvmcs, field); + __vmwrite(field, value); +} + +static void shadow_to_vvmcs(void *vvmcs, unsigned int field) +{ + u64 value; + int rc; + + value = __vmread_safe(field, &rc); + if ( !rc ) + __set_vvmcs(vvmcs, field, value); +} + +static void load_shadow_control(struct vcpu *v) +{ + /* TODO: Make sure the shadow control doesn''t set the bits + * L0 VMM doesn''t handle. + */ + + /* + * Set shadow controls: PIN_BASED, CPU_BASED, EXIT, ENTRY + * and EXCEPTION + * Enforce the removed features + */ + nvmx_update_pin_control(v, vmx_pin_based_exec_control); + vmx_update_cpu_exec_control(v); + nvmx_update_exit_control(v, vmx_vmexit_control); + nvmx_update_entry_control(v); + vmx_update_exception_bitmap(v); +} + +static void load_shadow_guest_state(struct vcpu *v) +{ + struct nestedvcpu *nvcpu = &vcpu_nestedhvm(v); + void *vvmcs = nvcpu->nv_vvmcx; + int i; + + /* vvmcs.gstate to shadow vmcs.gstate */ + for ( i = 0; i < ARRAY_SIZE(vmcs_gstate_field); i++ ) + vvmcs_to_shadow(vvmcs, vmcs_gstate_field[i]); + + hvm_set_cr0(__get_vvmcs(vvmcs, GUEST_CR0)); + hvm_set_cr4(__get_vvmcs(vvmcs, GUEST_CR4)); + hvm_set_cr3(__get_vvmcs(vvmcs, GUEST_CR3)); + + vvmcs_to_shadow(vvmcs, VM_ENTRY_INTR_INFO); + vvmcs_to_shadow(vvmcs, VM_ENTRY_EXCEPTION_ERROR_CODE); + vvmcs_to_shadow(vvmcs, VM_ENTRY_INSTRUCTION_LEN); + + /* XXX: should refer to GUEST_HOST_MASK of both L0 and L1 */ + vvmcs_to_shadow(vvmcs, CR0_READ_SHADOW); + vvmcs_to_shadow(vvmcs, CR4_READ_SHADOW); + vvmcs_to_shadow(vvmcs, CR0_GUEST_HOST_MASK); + vvmcs_to_shadow(vvmcs, CR4_GUEST_HOST_MASK); + + /* TODO: PDPTRs for nested ept */ + /* TODO: CR3 target control */ +} + +static void virtual_vmentry(struct cpu_user_regs *regs) +{ + struct vcpu *v = current; + struct nestedvcpu *nvcpu = &vcpu_nestedhvm(v); + void *vvmcs = nvcpu->nv_vvmcx; +#ifdef __x86_64__ + unsigned long lm_l1, lm_l2; +#endif + + vmx_vmcs_switch(v, v->arch.hvm_vmx.vmcs, nvcpu->nv_n2vmcx); + + nestedhvm_vcpu_enter_guestmode(v); + nvcpu->nv_vmentry_pending = 0; + nvcpu->nv_vmswitch_in_progress = 1; + +#ifdef __x86_64__ + /* + * EFER handling: + * hvm_set_efer won''t work if CR0.PG = 1, so we change the value + * directly to make hvm_long_mode_enabled(v) work in L2. + * An additional update_paging_modes is also needed if + * there is 32/64 switch. v->arch.hvm_vcpu.guest_efer doesn''t + * need to be saved, since its value on vmexit is determined by + * L1 exit_controls + */ + lm_l1 = !!hvm_long_mode_enabled(v); + lm_l2 = !!(__get_vvmcs(vvmcs, VM_ENTRY_CONTROLS) & + VM_ENTRY_IA32E_MODE); + + if ( lm_l2 ) + v->arch.hvm_vcpu.guest_efer |= EFER_LMA | EFER_LME; + else + v->arch.hvm_vcpu.guest_efer &= ~(EFER_LMA | EFER_LME); +#endif + + load_shadow_control(v); + load_shadow_guest_state(v); + +#ifdef __x86_64__ + if ( lm_l1 != lm_l2 ) + { + paging_update_paging_modes(v); + } +#endif + + regs->rip = __get_vvmcs(vvmcs, GUEST_RIP); + regs->rsp = __get_vvmcs(vvmcs, GUEST_RSP); + regs->rflags = __get_vvmcs(vvmcs, GUEST_RFLAGS); + + /* TODO: EPT_POINTER */ +} + +static void sync_vvmcs_guest_state(struct vcpu *v, struct cpu_user_regs *regs) +{ + int i; + unsigned long mask; + unsigned long cr; + struct nestedvcpu *nvcpu = &vcpu_nestedhvm(v); + void *vvmcs = nvcpu->nv_vvmcx; + + /* copy shadow vmcs.gstate back to vvmcs.gstate */ + for ( i = 0; i < ARRAY_SIZE(vmcs_gstate_field); i++ ) + shadow_to_vvmcs(vvmcs, vmcs_gstate_field[i]); + /* RIP, RSP are in user regs */ + __set_vvmcs(vvmcs, GUEST_RIP, regs->rip); + __set_vvmcs(vvmcs, GUEST_RSP, regs->rsp); + + /* SDM 20.6.6: L2 guest execution may change GUEST CR0/CR4 */ + mask = __get_vvmcs(vvmcs, CR0_GUEST_HOST_MASK); + if ( ~mask ) + { + cr = __get_vvmcs(vvmcs, GUEST_CR0); + cr = (cr & mask) | (__vmread(GUEST_CR4) & ~mask); + __set_vvmcs(vvmcs, GUEST_CR0, cr); + } + + mask = __get_vvmcs(vvmcs, CR4_GUEST_HOST_MASK); + if ( ~mask ) + { + cr = __get_vvmcs(vvmcs, GUEST_CR4); + cr = (cr & mask) | (__vmread(GUEST_CR4) & ~mask); + __set_vvmcs(vvmcs, GUEST_CR4, cr); + } + + /* CR3 sync if exec doesn''t want cr3 load exiting: i.e. nested EPT */ + if ( !(__n2_exec_control(v) & CPU_BASED_CR3_LOAD_EXITING) ) + shadow_to_vvmcs(vvmcs, GUEST_CR3); +} + +static void sync_vvmcs_ro(struct vcpu *v) +{ + int i; + struct nestedvcpu *nvcpu = &vcpu_nestedhvm(v); + + for ( i = 0; i < ARRAY_SIZE(vmcs_ro_field); i++ ) + shadow_to_vvmcs(nvcpu->nv_vvmcx, vmcs_ro_field[i]); +} + +static void load_vvmcs_host_state(struct vcpu *v) +{ + int i; + u64 r; + void *vvmcs = vcpu_nestedhvm(v).nv_vvmcx; + + for ( i = 0; i < ARRAY_SIZE(vmcs_h2g_field); i++ ) + { + r = __get_vvmcs(vvmcs, vmcs_h2g_field[i].host_field); + __vmwrite(vmcs_h2g_field[i].guest_field, r); + } + + hvm_set_cr0(__get_vvmcs(vvmcs, HOST_CR0)); + hvm_set_cr4(__get_vvmcs(vvmcs, HOST_CR4)); + hvm_set_cr3(__get_vvmcs(vvmcs, HOST_CR3)); + + __set_vvmcs(vvmcs, VM_ENTRY_INTR_INFO, 0); +} + +static void virtual_vmexit(struct cpu_user_regs *regs) +{ + struct vcpu *v = current; + struct nestedvcpu *nvcpu = &vcpu_nestedhvm(v); +#ifdef __x86_64__ + unsigned long lm_l1, lm_l2; +#endif + + sync_vvmcs_ro(v); + sync_vvmcs_guest_state(v, regs); + + vmx_vmcs_switch(v, v->arch.hvm_vmx.vmcs, nvcpu->nv_n1vmcx); + + nestedhvm_vcpu_exit_guestmode(v); + nvcpu->nv_vmexit_pending = 0; + +#ifdef __x86_64__ + lm_l2 = !!hvm_long_mode_enabled(v); + lm_l1 = !!(__get_vvmcs(nvcpu->nv_vvmcx, VM_EXIT_CONTROLS) & + VM_EXIT_IA32E_MODE); + + if ( lm_l1 ) + v->arch.hvm_vcpu.guest_efer |= EFER_LMA | EFER_LME; + else + v->arch.hvm_vcpu.guest_efer &= ~(EFER_LMA | EFER_LME); +#endif + + vmx_update_cpu_exec_control(v); + vmx_update_exception_bitmap(v); + + load_vvmcs_host_state(v); + +#ifdef __x86_64__ + if ( lm_l1 != lm_l2 ) + paging_update_paging_modes(v); +#endif + + regs->rip = __get_vvmcs(nvcpu->nv_vvmcx, HOST_RIP); + regs->rsp = __get_vvmcs(nvcpu->nv_vvmcx, HOST_RSP); + regs->rflags = __vmread(GUEST_RFLAGS); + + vmreturn(regs, VMSUCCEED); +} + +asmlinkage void nvmx_switch_layed_guest(void) +{ + struct vcpu *v = current; + struct nestedvcpu *nvcpu = &vcpu_nestedhvm(v); + struct cpu_user_regs *regs = guest_cpu_user_regs(); + + /* + * a softirq may interrupt us between a virtual vmentry is + * just handled and the true vmentry. If during this window, + * a L1 virtual interrupt causes another virtual vmexit, we + * cannot let that happen or VM_ENTRY_INTR_INFO will be lost. + */ + if ( unlikely(nvcpu->nv_vmswitch_in_progress) ) + return; + + if ( nestedhvm_vcpu_in_guestmode(v) && nvcpu->nv_vmexit_pending ) + { + local_irq_enable(); + virtual_vmexit(regs); + } + else if ( !nestedhvm_vcpu_in_guestmode(v) && nvcpu->nv_vmentry_pending ) + { + local_irq_enable(); + virtual_vmentry(regs); + } +} + +/* * VMX instructions handling */ diff -r 091f56f71a32 xen/include/asm-x86/hvm/vmx/vvmx.h --- a/xen/include/asm-x86/hvm/vmx/vvmx.h Mon May 30 17:38:21 2011 +0800 +++ b/xen/include/asm-x86/hvm/vmx/vvmx.h Mon May 30 17:40:15 2011 +0800 @@ -121,6 +121,7 @@ void nvmx_update_secondary_exec_control(struct vcpu *v, unsigned long value); void nvmx_update_exception_bitmap(struct vcpu *v, unsigned long value); +asmlinkage void nvmx_switch_layed_guest(void); #endif /* __ASM_X86_HVM_VVMX_H__ */ _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Thx, Eddie Signed-off-by: Qing He <qing.he@intel.com> Signed-off-by: Eddie Dong <eddie.dong@intel.com> diff -r 3899dcd0005c xen/arch/x86/hvm/vmx/intr.c --- a/xen/arch/x86/hvm/vmx/intr.c Wed Jun 01 09:55:30 2011 +0800 +++ b/xen/arch/x86/hvm/vmx/intr.c Wed Jun 01 11:25:32 2011 +0800 @@ -35,6 +35,7 @@ #include <asm/hvm/vmx/vmcs.h> #include <asm/hvm/vpic.h> #include <asm/hvm/vlapic.h> +#include <asm/hvm/nestedhvm.h> #include <public/hvm/ioreq.h> #include <asm/hvm/trace.h> @@ -109,9 +110,100 @@ } } +/* + * Injecting interrupts for nested virtualization + * + * When injecting virtual interrupts (originated from L0), there are + * two major possibilities, within L1 context and within L2 context + * 1. L1 context (in_nesting == 0) + * Everything is the same as without nested, check RFLAGS.IF to + * see if the injection can be done, using VMCS to inject the + * interrupt + * + * 2. L2 context (in_nesting == 1) + * Causes a virtual VMExit, RFLAGS.IF is ignored, whether to ack + * irq according to intr_ack_on_exit, shouldn''t block normally, + * except for: + * a. context transition + * interrupt needs to be blocked at virtual VMEntry time + * b. L2 idtv reinjection + * if L2 idtv is handled within L0 (e.g. L0 shadow page fault), + * it needs to be reinjected without exiting to L1, interrupt + * injection should be blocked as well at this point. + * + * Unfortunately, interrupt blocking in L2 won''t work with simple + * intr_window_open (which depends on L2''s IF). To solve this, + * the following algorithm can be used: + * v->arch.hvm_vmx.exec_control.VIRTUAL_INTR_PENDING now denotes + * only L0 control, physical control may be different from it. + * - if in L1, it behaves normally, intr window is written + * to physical control as it is + * - if in L2, replace it to MTF (or NMI window) if possible + * - if MTF/NMI window is not used, intr window can still be + * used but may have negative impact on interrupt performance. + */ + enum hvm_intblk nvmx_intr_blocked(struct vcpu *v) { - return hvm_intblk_none; + int r = hvm_intblk_none; + struct nestedvcpu *nvcpu = &vcpu_nestedhvm(v); + + if ( nestedhvm_vcpu_in_guestmode(v) ) + { + if ( nvcpu->nv_vmexit_pending || + nvcpu->nv_vmswitch_in_progress || + (__vmread(VM_ENTRY_INTR_INFO) & INTR_INFO_VALID_MASK) ) + r = hvm_intblk_rflags_ie; + } + else if ( nvcpu->nv_vmentry_pending ) + r = hvm_intblk_rflags_ie; + + return r; +} + +static int nvmx_intr_intercept(struct vcpu *v, struct hvm_intack intack) +{ + u32 exit_ctrl; + + /* + * TODO: + * - if L1 intr-window exiting == 0 + * - vNMI + */ + + if ( nvmx_intr_blocked(v) != hvm_intblk_none ) + { + enable_intr_window(v, intack); + return 1; + } + + if ( nestedhvm_vcpu_in_guestmode(v) ) + { + if ( intack.source == hvm_intsrc_pic || + intack.source == hvm_intsrc_lapic ) + { + vmx_inject_extint(intack.vector); + + exit_ctrl = __get_vvmcs(vcpu_nestedhvm(v).nv_vvmcx, + VM_EXIT_CONTROLS); + if ( exit_ctrl & VM_EXIT_ACK_INTR_ON_EXIT ) + { + /* for now, duplicate the ack path in vmx_intr_assist */ + hvm_vcpu_ack_pending_irq(v, intack); + pt_intr_post(v, intack); + + intack = hvm_vcpu_has_pending_irq(v); + if ( unlikely(intack.source != hvm_intsrc_none) ) + enable_intr_window(v, intack); + } + else + enable_intr_window(v, intack); + + return 1; + } + } + + return 0; } asmlinkage void vmx_intr_assist(void) @@ -137,6 +229,9 @@ if ( likely(intack.source == hvm_intsrc_none) ) goto out; + if ( unlikely(nvmx_intr_intercept(v, intack)) ) + goto out; + intblk = hvm_interrupt_blocked(v, intack); if ( intblk == hvm_intblk_tpr ) { diff -r 3899dcd0005c xen/arch/x86/hvm/vmx/vmx.c --- a/xen/arch/x86/hvm/vmx/vmx.c Wed Jun 01 09:55:30 2011 +0800 +++ b/xen/arch/x86/hvm/vmx/vmx.c Wed Jun 01 11:25:32 2011 +0800 @@ -1243,6 +1243,31 @@ __ept_sync_domain, d, 1); } +void nvmx_enqueue_n2_exceptions(struct vcpu *v, + unsigned long intr_fields, int error_code) +{ + struct nestedvmx *nvmx = &vcpu_2_nvmx(v); + + if ( !(nvmx->intr.intr_info & INTR_INFO_VALID_MASK) ) { + /* enqueue the exception till the VMCS switch back to L1 */ + nvmx->intr.intr_info = intr_fields; + nvmx->intr.error_code = error_code; + vcpu_nestedhvm(v).nv_vmexit_pending = 1; + return; + } + else + gdprintk(XENLOG_ERR, "Double Fault on Nested Guest: exception %lx %x" + "on %lx %x\n", intr_fields, error_code, + nvmx->intr.intr_info, nvmx->intr.error_code); +} + +static int nvmx_vmexit_exceptions(struct vcpu *v, unsigned int trapnr, + int errcode, unsigned long cr2) +{ + nvmx_enqueue_n2_exceptions(v, trapnr, errcode); + return NESTEDHVM_VMEXIT_DONE; +} + static void __vmx_inject_exception(int trap, int type, int error_code) { unsigned long intr_fields; @@ -1272,11 +1297,16 @@ void vmx_inject_hw_exception(int trap, int error_code) { - unsigned long intr_info = __vmread(VM_ENTRY_INTR_INFO); + unsigned long intr_info; struct vcpu *curr = current; int type = X86_EVENTTYPE_HW_EXCEPTION; + if ( nestedhvm_vcpu_in_guestmode(curr) ) + intr_info = vcpu_2_nvmx(curr).intr.intr_info; + else + intr_info = __vmread(VM_ENTRY_INTR_INFO); + switch ( trap ) { case TRAP_debug: @@ -1308,7 +1338,16 @@ error_code = 0; } - __vmx_inject_exception(trap, type, error_code); + if ( nestedhvm_vcpu_in_guestmode(curr) && + nvmx_intercepts_exception(curr, trap, error_code) ) + { + nvmx_enqueue_n2_exceptions (curr, + INTR_INFO_VALID_MASK | (type<<8) | trap, + error_code); + return; + } + else + __vmx_inject_exception(trap, type, error_code); if ( trap == TRAP_page_fault ) HVMTRACE_LONG_2D(PF_INJECT, error_code, @@ -1319,12 +1358,38 @@ void vmx_inject_extint(int trap) { + struct vcpu *v = current; + u32 pin_based_cntrl; + + if ( nestedhvm_vcpu_in_guestmode(v) ) { + pin_based_cntrl = __get_vvmcs(vcpu_nestedhvm(v).nv_vvmcx, + PIN_BASED_VM_EXEC_CONTROL); + if ( pin_based_cntrl && PIN_BASED_EXT_INTR_MASK ) { + nvmx_enqueue_n2_exceptions (v, + INTR_INFO_VALID_MASK | (X86_EVENTTYPE_EXT_INTR<<8) | trap, + HVM_DELIVER_NO_ERROR_CODE); + return; + } + } __vmx_inject_exception(trap, X86_EVENTTYPE_EXT_INTR, HVM_DELIVER_NO_ERROR_CODE); } void vmx_inject_nmi(void) { + struct vcpu *v = current; + u32 pin_based_cntrl; + + if ( nestedhvm_vcpu_in_guestmode(v) ) { + pin_based_cntrl = __get_vvmcs(vcpu_nestedhvm(v).nv_vvmcx, + PIN_BASED_VM_EXEC_CONTROL); + if ( pin_based_cntrl && PIN_BASED_NMI_EXITING ) { + nvmx_enqueue_n2_exceptions (v, + INTR_INFO_VALID_MASK | (X86_EVENTTYPE_NMI<<8) | TRAP_nmi, + HVM_DELIVER_NO_ERROR_CODE); + return; + } + } __vmx_inject_exception(2, X86_EVENTTYPE_NMI, HVM_DELIVER_NO_ERROR_CODE); } @@ -1425,6 +1490,8 @@ .nhvm_vcpu_guestcr3 = nvmx_vcpu_guestcr3, .nhvm_vcpu_hostcr3 = nvmx_vcpu_hostcr3, .nhvm_vcpu_asid = nvmx_vcpu_asid, + .nhvm_vmcx_guest_intercepts_trap = nvmx_intercepts_exception, + .nhvm_vcpu_vmexit_trap = nvmx_vmexit_exceptions, .nhvm_intr_blocked = nvmx_intr_blocked }; @@ -2238,7 +2305,8 @@ hvm_maybe_deassert_evtchn_irq(); idtv_info = __vmread(IDT_VECTORING_INFO); - if ( exit_reason != EXIT_REASON_TASK_SWITCH ) + if ( !nestedhvm_vcpu_in_guestmode(v) && + exit_reason != EXIT_REASON_TASK_SWITCH ) vmx_idtv_reinject(idtv_info); switch ( exit_reason ) @@ -2586,6 +2654,9 @@ domain_crash(v->domain); break; } + + if ( nestedhvm_vcpu_in_guestmode(v) ) + nvmx_idtv_handling(); } asmlinkage void vmx_vmenter_helper(void) diff -r 3899dcd0005c xen/arch/x86/hvm/vmx/vvmx.c --- a/xen/arch/x86/hvm/vmx/vvmx.c Wed Jun 01 09:55:30 2011 +0800 +++ b/xen/arch/x86/hvm/vmx/vvmx.c Wed Jun 01 11:25:32 2011 +0800 @@ -92,6 +92,27 @@ return 0; } +int nvmx_intercepts_exception(struct vcpu *v, unsigned int trap, + int error_code) +{ + struct nestedvcpu *nvcpu = &vcpu_nestedhvm(v); + u32 exception_bitmap, pfec_match=0, pfec_mask=0; + int r; + + ASSERT ( trap < 32 ); + + exception_bitmap = __get_vvmcs(nvcpu->nv_vvmcx, EXCEPTION_BITMAP); + r = exception_bitmap & (1 << trap) ? 1: 0; + + if ( trap == TRAP_page_fault ) { + pfec_match = __get_vvmcs(nvcpu->nv_vvmcx, PAGE_FAULT_ERROR_CODE_MATCH); + pfec_mask = __get_vvmcs(nvcpu->nv_vvmcx, PAGE_FAULT_ERROR_CODE_MASK); + if ( (error_code & pfec_mask) != pfec_match ) + r = !r; + } + return r; +} + /* * Encode of VMX instructions base on Table 24-11 & 24-12 of SDM 3B */ @@ -517,6 +538,7 @@ __vmwrite(IO_BITMAP_B, virt_to_maddr(bitmap) + PAGE_SIZE); } + /* TODO: change L0 intr window to MTF or NMI window */ __vmwrite(CPU_BASED_VM_EXEC_CONTROL, shadow_cntrl); } @@ -921,6 +943,42 @@ __set_vvmcs(vvmcs, VM_ENTRY_INTR_INFO, 0); } +static void sync_exception_state(struct vcpu *v) +{ + struct nestedvcpu *nvcpu = &vcpu_nestedhvm(v); + struct nestedvmx *nvmx = &vcpu_2_nvmx(v); + + if ( !(nvmx->intr.intr_info & INTR_INFO_VALID_MASK) ) + return; + + switch ( nvmx->intr.intr_info & INTR_INFO_INTR_TYPE_MASK ) + { + case X86_EVENTTYPE_EXT_INTR: + /* rename exit_reason to EXTERNAL_INTERRUPT */ + __set_vvmcs(nvcpu->nv_vvmcx, VM_EXIT_REASON, + EXIT_REASON_EXTERNAL_INTERRUPT); + __set_vvmcs(nvcpu->nv_vvmcx, EXIT_QUALIFICATION, 0); + __set_vvmcs(nvcpu->nv_vvmcx, VM_EXIT_INTR_INFO, + nvmx->intr.intr_info); + break; + + case X86_EVENTTYPE_HW_EXCEPTION: + case X86_EVENTTYPE_SW_INTERRUPT: + case X86_EVENTTYPE_SW_EXCEPTION: + /* throw to L1 */ + __set_vvmcs(nvcpu->nv_vvmcx, VM_EXIT_INTR_INFO, + nvmx->intr.intr_info); + __set_vvmcs(nvcpu->nv_vvmcx, VM_EXIT_INTR_ERROR_CODE, + nvmx->intr.error_code); + break; + case X86_EVENTTYPE_NMI: + default: + gdprintk(XENLOG_ERR, "Exception state %lx not handled\n", + nvmx->intr.intr_info); + break; + } +} + static void virtual_vmexit(struct cpu_user_regs *regs) { struct vcpu *v = current; @@ -931,6 +989,7 @@ sync_vvmcs_ro(v); sync_vvmcs_guest_state(v, regs); + sync_exception_state(v); vmx_vmcs_switch(v, v->arch.hvm_vmx.vmcs, nvcpu->nv_n1vmcx); @@ -1223,3 +1282,40 @@ return X86EMUL_OKAY; } +void nvmx_idtv_handling(void) +{ + struct vcpu *v = current; + struct nestedvmx *nvmx = &vcpu_2_nvmx(v); + struct nestedvcpu *nvcpu = &vcpu_nestedhvm(v); + unsigned int idtv_info = __vmread(IDT_VECTORING_INFO); + + if ( likely(!(idtv_info & INTR_INFO_VALID_MASK)) ) + return; + + /* + * If L0 can solve the fault that causes idt vectoring, it should + * be reinjected, otherwise, pass to L1. + */ + if ( (__vmread(VM_EXIT_REASON) != EXIT_REASON_EPT_VIOLATION && + !(nvmx->intr.intr_info & INTR_INFO_VALID_MASK)) || + (__vmread(VM_EXIT_REASON) == EXIT_REASON_EPT_VIOLATION && + !nvcpu->nv_vmexit_pending) ) + { + __vmwrite(VM_ENTRY_INTR_INFO, idtv_info & ~INTR_INFO_RESVD_BITS_MASK); + if ( idtv_info & INTR_INFO_DELIVER_CODE_MASK ) + __vmwrite(VM_ENTRY_EXCEPTION_ERROR_CODE, + __vmread(IDT_VECTORING_ERROR_CODE)); + /* + * SDM 23.2.4, if L1 tries to inject a software interrupt + * and the delivery fails, VM_EXIT_INSTRUCTION_LEN receives + * the value of previous VM_ENTRY_INSTRUCTION_LEN. + * + * This means EXIT_INSTRUCTION_LEN is always valid here, for + * software interrupts both injected by L1, and generated in L2. + */ + __vmwrite(VM_ENTRY_INSTRUCTION_LEN, __vmread(VM_EXIT_INSTRUCTION_LEN)); + } + + /* TODO: NMI */ +} + diff -r 3899dcd0005c xen/include/asm-x86/hvm/vmx/vvmx.h --- a/xen/include/asm-x86/hvm/vmx/vvmx.h Wed Jun 01 09:55:30 2011 +0800 +++ b/xen/include/asm-x86/hvm/vmx/vvmx.h Wed Jun 01 11:25:32 2011 +0800 @@ -48,6 +48,8 @@ uint64_t nvmx_vcpu_hostcr3(struct vcpu *v); uint32_t nvmx_vcpu_asid(struct vcpu *v); enum hvm_intblk nvmx_intr_blocked(struct vcpu *v); +int nvmx_intercepts_exception(struct vcpu *v, + unsigned int trap, int error_code); int nvmx_handle_vmxon(struct cpu_user_regs *regs); int nvmx_handle_vmxoff(struct cpu_user_regs *regs); @@ -121,6 +123,7 @@ unsigned long value); void nvmx_update_exception_bitmap(struct vcpu *v, unsigned long value); asmlinkage void nvmx_switch_layed_guest(void); +void nvmx_idtv_handling(void); #endif /* __ASM_X86_HVM_VVMX_H__ */ _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Dong, Eddie
2011-Jun-01 04:06 UTC
[Xen-devel] RFC: Nested VMX patch series 15: exit from n2 guest
Thx, Eddie Signed-off-by: Qing He <qing.he@intel.com> Signed-off-by: Eddie Dong <eddie.dong@intel.com> diff -r 8a54c14b7bbd xen/arch/x86/hvm/vmx/vmx.c --- a/xen/arch/x86/hvm/vmx/vmx.c Sat May 28 19:02:20 2011 +0800 +++ b/xen/arch/x86/hvm/vmx/vmx.c Sat May 28 19:02:28 2011 +0800 @@ -943,6 +943,10 @@ static void vmx_set_tsc_offset(struct vcpu *v, u64 offset) { vmx_vmcs_enter(v); + + if ( nestedhvm_vcpu_in_guestmode(v) ) + offset += nvmx_get_tsc_offset(v); + __vmwrite(TSC_OFFSET, offset); #if defined (__i386__) __vmwrite(TSC_OFFSET_HIGH, offset >> 32); @@ -2203,6 +2207,11 @@ * any pending vmresume has really happened */ vcpu_nestedhvm(v).nv_vmswitch_in_progress = 0; + if ( nestedhvm_vcpu_in_guestmode(v) ) + { + if ( nvmx_n2_vmexit_handler(regs, exit_reason) ) + goto out; + } if ( unlikely(exit_reason & VMX_EXIT_REASONS_FAILED_VMENTRY) ) return vmx_failed_vmentry(exit_reason, regs); @@ -2605,6 +2614,7 @@ break; } +out: if ( nestedhvm_vcpu_in_guestmode(v) ) nvmx_idtv_handling(); } diff -r 8a54c14b7bbd xen/arch/x86/hvm/vmx/vvmx.c --- a/xen/arch/x86/hvm/vmx/vvmx.c Sat May 28 19:02:20 2011 +0800 +++ b/xen/arch/x86/hvm/vmx/vvmx.c Sat May 28 19:02:28 2011 +0800 @@ -348,13 +348,19 @@ if ( (regs->eflags & X86_EFLAGS_VM) || (hvm_long_mode_enabled(v) && cs.attr.fields.l == 0) ) goto invalid_op; - /* TODO: check vmx operation mode */ + else if ( nestedhvm_vcpu_in_guestmode(v) ) + goto vmexit; if ( (cs.sel & 3) > 0 ) goto gp_fault; return X86EMUL_OKAY; +vmexit: + gdprintk(XENLOG_ERR, "vmx_inst_check_privilege: vmexit\n"); + vcpu_nestedhvm(v).nv_vmexit_pending = 1; + return X86EMUL_EXCEPTION; + invalid_op: gdprintk(XENLOG_ERR, "vmx_inst_check_privilege: invalid_op\n"); hvm_inject_exception(TRAP_invalid_op, 0, 0); @@ -610,6 +616,18 @@ } } +u64 nvmx_get_tsc_offset(struct vcpu *v) +{ + u64 offset = 0; + struct nestedvcpu *nvcpu = &vcpu_nestedhvm(v); + + if ( __get_vvmcs(nvcpu->nv_vvmcx, CPU_BASED_VM_EXEC_CONTROL) & + CPU_BASED_USE_TSC_OFFSETING ) + offset = __get_vvmcs(nvcpu->nv_vvmcx, TSC_OFFSET); + + return offset; +} + /* * Context synchronized between shadow and virtual VMCS. */ @@ -763,6 +781,8 @@ hvm_set_cr4(__get_vvmcs(vvmcs, GUEST_CR4)); hvm_set_cr3(__get_vvmcs(vvmcs, GUEST_CR3)); + hvm_funcs.set_tsc_offset(v, v->arch.hvm_vcpu.cache_tsc_offset); + vvmcs_to_shadow(vvmcs, VM_ENTRY_INTR_INFO); vvmcs_to_shadow(vvmcs, VM_ENTRY_EXCEPTION_ERROR_CODE); vvmcs_to_shadow(vvmcs, VM_ENTRY_INSTRUCTION_LEN); @@ -891,6 +911,8 @@ hvm_set_cr4(__get_vvmcs(vvmcs, HOST_CR4)); hvm_set_cr3(__get_vvmcs(vvmcs, HOST_CR3)); + hvm_funcs.set_tsc_offset(v, v->arch.hvm_vcpu.cache_tsc_offset); + __set_vvmcs(vvmcs, VM_ENTRY_INTR_INFO, 0); } @@ -1289,3 +1311,252 @@ /* TODO: NMI */ } +/* + * L2 VMExit handling + * return 1: Done or skip the normal layer 0 hypervisor process. + * Typically it requires layer 1 hypervisor processing + * or it may be already processed here. + * 0: Require the normal layer 0 process. + */ +int nvmx_n2_vmexit_handler(struct cpu_user_regs *regs, + unsigned int exit_reason) +{ + struct vcpu *v = current; + struct nestedvcpu *nvcpu = &vcpu_nestedhvm(v); + struct nestedvmx *nvmx = &vcpu_2_nvmx(v); + u32 ctrl; + u16 port; + u8 *bitmap; + + nvcpu->nv_vmexit_pending = 0; + nvmx->intr.intr_info = 0; + nvmx->intr.error_code = 0; + + switch (exit_reason) { + case EXIT_REASON_EXCEPTION_NMI: + { + u32 intr_info = __vmread(VM_EXIT_INTR_INFO); + u32 valid_mask = (X86_EVENTTYPE_HW_EXCEPTION << 8) | + INTR_INFO_VALID_MASK; + u64 exec_bitmap; + int vector = intr_info & INTR_INFO_VECTOR_MASK; + + /* + * decided by L0 and L1 exception bitmap, if the vetor is set by + * both, L0 has priority on #PF, L1 has priority on others + */ + if ( vector == TRAP_page_fault ) + { + if ( paging_mode_hap(v->domain) ) + nvcpu->nv_vmexit_pending = 1; + } + else if ( (intr_info & valid_mask) == valid_mask ) + { + exec_bitmap =__get_vvmcs(nvcpu->nv_vvmcx, EXCEPTION_BITMAP); + + if ( exec_bitmap & (1 << vector) ) + nvcpu->nv_vmexit_pending = 1; + } + break; + } + + case EXIT_REASON_WBINVD: + case EXIT_REASON_EPT_VIOLATION: + case EXIT_REASON_EPT_MISCONFIG: + case EXIT_REASON_EXTERNAL_INTERRUPT: + /* pass to L0 handler */ + break; + + case VMX_EXIT_REASONS_FAILED_VMENTRY: + case EXIT_REASON_TRIPLE_FAULT: + case EXIT_REASON_TASK_SWITCH: + case EXIT_REASON_CPUID: + case EXIT_REASON_MSR_READ: + case EXIT_REASON_MSR_WRITE: + case EXIT_REASON_VMCALL: + case EXIT_REASON_VMCLEAR: + case EXIT_REASON_VMLAUNCH: + case EXIT_REASON_VMPTRLD: + case EXIT_REASON_VMPTRST: + case EXIT_REASON_VMREAD: + case EXIT_REASON_VMRESUME: + case EXIT_REASON_VMWRITE: + case EXIT_REASON_VMXOFF: + case EXIT_REASON_VMXON: + case EXIT_REASON_INVEPT: + /* inject to L1 */ + nvcpu->nv_vmexit_pending = 1; + break; + case EXIT_REASON_IO_INSTRUCTION: + ctrl = __n2_exec_control(v); + if ( ctrl & CPU_BASED_ACTIVATE_IO_BITMAP ) + { + port = __vmread(EXIT_QUALIFICATION) >> 16; + bitmap = nvmx->iobitmap[port >> 15]; + if ( bitmap[(port <<1) >> 4] & (1 << (port & 0x7)) ) + nvcpu->nv_vmexit_pending = 1; + } + else if ( ctrl & CPU_BASED_UNCOND_IO_EXITING ) + nvcpu->nv_vmexit_pending = 1; + break; + + case EXIT_REASON_PENDING_VIRT_INTR: + { + ctrl = v->arch.hvm_vmx.exec_control; + + /* + * if both open intr/nmi window, L0 has priority. + * + * Note that this is not strictly correct, in L2 context, + * L0''s intr/nmi window flag should be replaced to MTF, + * causing an imediate VMExit, but MTF may not be available + * on all hardware. + */ + if ( !(ctrl & CPU_BASED_VIRTUAL_INTR_PENDING) ) + nvcpu->nv_vmexit_pending = 1; + + break; + } + case EXIT_REASON_PENDING_VIRT_NMI: + { + ctrl = v->arch.hvm_vmx.exec_control; + + if ( !(ctrl & CPU_BASED_VIRTUAL_NMI_PENDING) ) + nvcpu->nv_vmexit_pending = 1; + + break; + } + + /* L1 has priority handling several other types of exits */ + case EXIT_REASON_HLT: + { + ctrl = __n2_exec_control(v); + + if ( ctrl & CPU_BASED_HLT_EXITING ) + nvcpu->nv_vmexit_pending = 1; + + break; + } + + case EXIT_REASON_RDTSC: + { + ctrl = __n2_exec_control(v); + + if ( ctrl & CPU_BASED_RDTSC_EXITING ) + nvcpu->nv_vmexit_pending = 1; + else + { + uint64_t tsc; + + /* + * special handler is needed if L1 doesn''t intercept rdtsc, + * avoiding changing guest_tsc and messing up timekeeping in L1 + */ + tsc = hvm_get_guest_tsc(v); + tsc += __get_vvmcs(nvcpu->nv_vvmcx, TSC_OFFSET); + regs->eax = (uint32_t)tsc; + regs->edx = (uint32_t)(tsc >> 32); + + return 1; + } + + break; + } + + case EXIT_REASON_RDPMC: + { + ctrl = __n2_exec_control(v); + + if ( ctrl & CPU_BASED_RDPMC_EXITING ) + nvcpu->nv_vmexit_pending = 1; + + break; + } + + case EXIT_REASON_MWAIT_INSTRUCTION: + { + ctrl = __n2_exec_control(v); + + if ( ctrl & CPU_BASED_MWAIT_EXITING ) + nvcpu->nv_vmexit_pending = 1; + + break; + } + + case EXIT_REASON_PAUSE_INSTRUCTION: + { + ctrl = __n2_exec_control(v); + + if ( ctrl & CPU_BASED_PAUSE_EXITING ) + nvcpu->nv_vmexit_pending = 1; + + break; + } + + case EXIT_REASON_MONITOR_INSTRUCTION: + { + ctrl = __n2_exec_control(v); + + if ( ctrl & CPU_BASED_MONITOR_EXITING ) + nvcpu->nv_vmexit_pending = 1; + + break; + } + + case EXIT_REASON_DR_ACCESS: + { + ctrl = __n2_exec_control(v); + + if ( ctrl & CPU_BASED_MOV_DR_EXITING ) + nvcpu->nv_vmexit_pending = 1; + + break; + } + + case EXIT_REASON_INVLPG: + { + ctrl = __n2_exec_control(v); + + if ( ctrl & CPU_BASED_INVLPG_EXITING ) + nvcpu->nv_vmexit_pending = 1; + + break; + } + + case EXIT_REASON_CR_ACCESS: + { + u64 exit_qualification = __vmread(EXIT_QUALIFICATION); + int cr = exit_qualification & 15; + int write = (exit_qualification >> 4) & 3; + u32 mask = 0; + + /* also according to guest exec_control */ + ctrl = __n2_exec_control(v); + + if ( cr == 3 ) + { + mask = write? CPU_BASED_CR3_STORE_EXITING: + CPU_BASED_CR3_LOAD_EXITING; + if ( ctrl & mask ) + nvcpu->nv_vmexit_pending = 1; + } + else if ( cr == 8 ) + { + mask = write? CPU_BASED_CR8_STORE_EXITING: + CPU_BASED_CR8_LOAD_EXITING; + if ( ctrl & mask ) + nvcpu->nv_vmexit_pending = 1; + } + else /* CR0, CR4, CLTS, LMSW */ + nvcpu->nv_vmexit_pending = 1; + + break; + } + default: + gdprintk(XENLOG_WARNING, "Unknown nested vmexit reason %x.\n", + exit_reason); + } + + return ( nvcpu->nv_vmexit_pending == 1 ); +} + diff -r 8a54c14b7bbd xen/include/asm-x86/hvm/vmx/vvmx.h --- a/xen/include/asm-x86/hvm/vmx/vvmx.h Sat May 28 19:02:20 2011 +0800 +++ b/xen/include/asm-x86/hvm/vmx/vvmx.h Sat May 28 19:02:28 2011 +0800 @@ -123,6 +123,9 @@ void nvmx_update_exception_bitmap(struct vcpu *v, unsigned long value); asmlinkage void nvmx_switch_layed_guest(void); void nvmx_idtv_handling(void); +u64 nvmx_get_tsc_offset(struct vcpu *v); +int nvmx_n2_vmexit_handler(struct cpu_user_regs *regs, + unsigned int exit_reason); #endif /* __ASM_X86_HVM_VVMX_H__ */ _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Thx, Eddie Signed-off-by: Qing He <qing.he@intel.com> Signed-off-by: Eddie Dong <eddie.dong@intel.com> diff -r 7c75c8a9da05 xen/arch/x86/hvm/vmx/vvmx.c --- a/xen/arch/x86/hvm/vmx/vvmx.c Fri May 13 13:28:35 2011 +0800 +++ b/xen/arch/x86/hvm/vmx/vvmx.c Fri May 13 13:31:33 2011 +0800 @@ -712,6 +712,9 @@ regs->rsp = __get_vvmcs(vvmcs, GUEST_RSP); regs->rflags = __get_vvmcs(vvmcs, GUEST_RFLAGS); + /* updating host cr0 to sync TS bit */ + __vmwrite(HOST_CR0, v->arch.hvm_vmx.host_cr0); + /* TODO: EPT_POINTER */ } @@ -851,6 +854,9 @@ regs->rsp = __get_vvmcs(nvcpu->nv_vvmcx, HOST_RSP); regs->rflags = __vmread(GUEST_RFLAGS); + /* updating host cr0 to sync TS bit */ + __vmwrite(HOST_CR0, v->arch.hvm_vmx.host_cr0); + vmreturn(regs, VMSUCCEED); } @@ -948,13 +954,18 @@ /* * decided by L0 and L1 exception bitmap, if the vetor is set by - * both, L0 has priority on #PF, L1 has priority on others + * both, L0 has priority on #PF and #NM, L1 has priority on others */ if ( vector == TRAP_page_fault ) { if ( paging_mode_hap(v->domain) ) nvcpu->nv_vmexit_pending = 1; } + else if ( vector == TRAP_no_device ) + { + if ( v->fpu_dirtied ) + nvcpu->nv_vmexit_pending = 1; + } else if ( (intr_info & valid_mask) == valid_mask ) { exec_bitmap =__get_vvmcs(nvcpu->nv_vvmcx, EXCEPTION_BITMAP); _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Thx, Eddie Signed-off-by: Qing He <qing.he@intel.com> Signed-off-by: Eddie Dong <eddie.dong@intel.com> diff -r 117cc0237936 xen/include/asm-x86/cpufeature.h --- a/xen/include/asm-x86/cpufeature.h Wed May 18 14:06:57 2011 +0800 +++ b/xen/include/asm-x86/cpufeature.h Wed May 18 14:43:29 2011 +0800 @@ -216,6 +216,8 @@ #define cpu_has_svm boot_cpu_has(X86_FEATURE_SVM) +#define cpu_has_vmx boot_cpu_has(X86_FEATURE_VMXE) + #endif /* __ASM_I386_CPUFEATURE_H */ /* diff -r 117cc0237936 xen/include/asm-x86/hvm/hvm.h --- a/xen/include/asm-x86/hvm/hvm.h Wed May 18 14:06:57 2011 +0800 +++ b/xen/include/asm-x86/hvm/hvm.h Wed May 18 14:43:29 2011 +0800 @@ -312,6 +312,8 @@ X86_CR4_DE | X86_CR4_PSE | X86_CR4_PAE | \ X86_CR4_MCE | X86_CR4_PGE | X86_CR4_PCE | \ X86_CR4_OSFXSR | X86_CR4_OSXMMEXCPT | \ + ((nestedhvm_enabled((_v)->domain) && \ + cpu_has_vmx) ? X86_CR4_VMXE : 0) | \ (xsave_enabled(_v) ? X86_CR4_OSXSAVE : 0)))) /* These exceptions must always be intercepted. */ _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Thx, Eddie Signed-off-by: Qing He <qing.he@intel.com> Signed-off-by: Eddie Dong <eddie.dong@intel.com> diff -r 6391fb6a41fb xen/arch/x86/hvm/vmx/vmx.c --- a/xen/arch/x86/hvm/vmx/vmx.c Fri May 27 12:06:01 2011 +0800 +++ b/xen/arch/x86/hvm/vmx/vmx.c Fri May 27 12:53:09 2011 +0800 @@ -1728,8 +1728,11 @@ *msr_content |= (u64)__vmread(GUEST_IA32_DEBUGCTL_HIGH) << 32; #endif break; - case MSR_IA32_VMX_BASIC...MSR_IA32_VMX_PROCBASED_CTLS2: - goto gp_fault; + case IA32_FEATURE_CONTROL_MSR: + case MSR_IA32_VMX_BASIC...MSR_IA32_VMX_TRUE_ENTRY_CTLS: + if ( !nvmx_msr_read_intercept(msr, msr_content) ) + goto gp_fault; + break; case MSR_IA32_MISC_ENABLE: rdmsrl(MSR_IA32_MISC_ENABLE, *msr_content); /* Debug Trace Store is not supported. */ @@ -1890,8 +1893,11 @@ break; } - case MSR_IA32_VMX_BASIC...MSR_IA32_VMX_PROCBASED_CTLS2: - goto gp_fault; + case IA32_FEATURE_CONTROL_MSR: + case MSR_IA32_VMX_BASIC...MSR_IA32_VMX_TRUE_ENTRY_CTLS: + if ( !nvmx_msr_write_intercept(msr, msr_content) ) + goto gp_fault; + break; default: if ( vpmu_do_wrmsr(msr, msr_content) ) return X86EMUL_OKAY; diff -r 6391fb6a41fb xen/arch/x86/hvm/vmx/vvmx.c --- a/xen/arch/x86/hvm/vmx/vvmx.c Fri May 27 12:06:01 2011 +0800 +++ b/xen/arch/x86/hvm/vmx/vvmx.c Fri May 27 12:53:09 2011 +0800 @@ -1186,6 +1186,94 @@ return X86EMUL_OKAY; } +/* + * Capability reporting + */ +int nvmx_msr_read_intercept(unsigned int msr, u64 *msr_content) +{ + u32 eax, edx; + u64 data = 0; + int r = 1; + u32 mask = 0; + + if ( !nestedhvm_enabled(current->domain) ) + return 0; + + switch (msr) { + case MSR_IA32_VMX_BASIC: + rdmsr(msr, eax, edx); + data = edx; + data = (data & ~0x1fff) | 0x1000; /* request 4KB for guest VMCS */ + data &= ~(1 << 23); /* disable TRUE_xxx_CTLS */ + data = (data << 32) | VVMCS_REVISION; /* VVMCS revision */ + break; + case MSR_IA32_VMX_PINBASED_CTLS: +#define REMOVED_PIN_CONTROL_CAP (PIN_BASED_PREEMPT_TIMER) + rdmsr(msr, eax, edx); + data = edx; + data = (data << 32) | eax; + break; + case MSR_IA32_VMX_PROCBASED_CTLS: + rdmsr(msr, eax, edx); +#define REMOVED_EXEC_CONTROL_CAP (CPU_BASED_TPR_SHADOW \ + | CPU_BASED_ACTIVATE_MSR_BITMAP \ + | CPU_BASED_ACTIVATE_SECONDARY_CONTROLS) + data = edx & ~REMOVED_EXEC_CONTROL_CAP; + data = (data << 32) | eax; + break; + case MSR_IA32_VMX_EXIT_CTLS: + rdmsr(msr, eax, edx); +#define REMOVED_EXIT_CONTROL_CAP (VM_EXIT_SAVE_GUEST_PAT \ + | VM_EXIT_LOAD_HOST_PAT \ + | VM_EXIT_SAVE_GUEST_EFER \ + | VM_EXIT_LOAD_HOST_EFER \ + | VM_EXIT_SAVE_PREEMPT_TIMER) + data = edx & ~REMOVED_EXIT_CONTROL_CAP; + data = (data << 32) | eax; + break; + case MSR_IA32_VMX_ENTRY_CTLS: + rdmsr(msr, eax, edx); +#define REMOVED_ENTRY_CONTROL_CAP (VM_ENTRY_LOAD_GUEST_PAT \ + | VM_ENTRY_LOAD_GUEST_EFER) + data = edx & ~REMOVED_ENTRY_CONTROL_CAP; + data = (data << 32) | eax; + break; + case MSR_IA32_VMX_PROCBASED_CTLS2: + mask = 0; + + rdmsr(msr, eax, edx); + data = edx & mask; + data = (data << 32) | eax; + break; + + /* pass through MSRs */ + case IA32_FEATURE_CONTROL_MSR: + case MSR_IA32_VMX_MISC: + case MSR_IA32_VMX_CR0_FIXED0: + case MSR_IA32_VMX_CR0_FIXED1: + case MSR_IA32_VMX_CR4_FIXED0: + case MSR_IA32_VMX_CR4_FIXED1: + case MSR_IA32_VMX_VMCS_ENUM: + rdmsr(msr, eax, edx); + data = edx; + data = (data << 32) | eax; + break; + + default: + r = 0; + break; + } + + *msr_content = data; + return r; +} + +int nvmx_msr_write_intercept(unsigned int msr, u64 msr_content) +{ + /* silently ignore for now */ + return 1; +} + void nvmx_idtv_handling(void) { struct vcpu *v = current; diff -r 6391fb6a41fb xen/include/asm-x86/hvm/vmx/vvmx.h --- a/xen/include/asm-x86/hvm/vmx/vvmx.h Fri May 27 12:06:01 2011 +0800 +++ b/xen/include/asm-x86/hvm/vmx/vvmx.h Fri May 27 12:53:09 2011 +0800 @@ -108,6 +108,10 @@ int nvmx_handle_vmwrite(struct cpu_user_regs *regs); int nvmx_handle_vmresume(struct cpu_user_regs *regs); int nvmx_handle_vmlaunch(struct cpu_user_regs *regs); +int nvmx_msr_read_intercept(unsigned int msr, + u64 *msr_content); +int nvmx_msr_write_intercept(unsigned int msr, + u64 msr_content); void nvmx_update_exec_control(struct vcpu *v, unsigned long value); void nvmx_update_secondary_exec_control(struct vcpu *v, _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Keir/Tim: Here is the nested VMX support series for comments. The current solution works with host shadow page table. The virtual EPT support will come soon. Thx, Eddie _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Please don''t start new threads by reply to an old, unrelated mail -- it confuses threading. On Wed, 2011-06-01 at 05:11 +0100, Dong, Eddie wrote:> Keir/Tim: > Here is the nested VMX support series for comments. The current > solution works with host shadow page table. The virtual EPT support > will come soon.I''m neither Tim nor Keir but the documentary aspects of this series seem rather insufficient IMHO, even for an RFC. You summary lines are mostly verbose boilerplate with very little actual information and the changelog entries do not generally describe the change either. Lastly you haven''t included a Signed-off-by on at least some of the patches (maybe that''s OK for an RFC but you did sign off some of them). Also there are two patch 5''s and two patch 12''s, a tool such as the hg email extension would help avoid that sort of thing. Ian. _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Christoph Egger
2011-Jun-01 09:13 UTC
Re: [Xen-devel] RFC: Nested VMX patch series 02: wrap APIs
On 06/01/11 05:51, Dong, Eddie wrote:> Wrap for common nested APIs. > Thx, Eddie > > Signed-off-by: Qing He<qing.he@intel.com> > Signed-off-by: Eddie Dong<eddie.dong@intel.com> > > diff -r 70ee714947fb xen/arch/x86/hvm/hvm.c > --- a/xen/arch/x86/hvm/hvm.c Sat May 28 09:49:25 2011 +0800 > +++ b/xen/arch/x86/hvm/hvm.c Mon May 30 17:15:52 2011 +0800 > @@ -3502,7 +3502,7 @@ > /* Remove the check below once we have > * shadow-on-shadow. > */ > - if ( !paging_mode_hap(d)&& a.value ) > + if ( cpu_has_svm&& !paging_mode_hap(d)&& a.value ) > rc = -EINVAL;Are you going to implement shadow-on-shadow ? Christoph> /* Set up NHVM state for any vcpus that are already up */ > if ( !d->arch.hvm_domain.params[HVM_PARAM_NESTEDHVM] ) > diff -r 70ee714947fb xen/arch/x86/hvm/vmx/Makefile > --- a/xen/arch/x86/hvm/vmx/Makefile Sat May 28 09:49:25 2011 +0800 > +++ b/xen/arch/x86/hvm/vmx/Makefile Mon May 30 17:15:52 2011 +0800 > @@ -4,3 +4,4 @@ > obj-y += vmcs.o > obj-y += vmx.o > obj-y += vpmu_core2.o > +obj-y += vvmx.o > diff -r 70ee714947fb xen/arch/x86/hvm/vmx/intr.c > --- a/xen/arch/x86/hvm/vmx/intr.c Sat May 28 09:49:25 2011 +0800 > +++ b/xen/arch/x86/hvm/vmx/intr.c Mon May 30 17:15:52 2011 +0800 > @@ -109,6 +109,11 @@ > } > } > > +enum hvm_intblk nvmx_intr_blocked(struct vcpu *v) > +{ > + return hvm_intblk_none; > +} > + > asmlinkage void vmx_intr_assist(void) > { > struct hvm_intack intack; > diff -r 70ee714947fb xen/arch/x86/hvm/vmx/vmx.c > --- a/xen/arch/x86/hvm/vmx/vmx.c Sat May 28 09:49:25 2011 +0800 > +++ b/xen/arch/x86/hvm/vmx/vmx.c Mon May 30 17:15:52 2011 +0800 > @@ -1407,7 +1407,14 @@ > .invlpg_intercept = vmx_invlpg_intercept, > .set_uc_mode = vmx_set_uc_mode, > .set_info_guest = vmx_set_info_guest, > - .set_rdtsc_exiting = vmx_set_rdtsc_exiting > + .set_rdtsc_exiting = vmx_set_rdtsc_exiting, > + .nhvm_vcpu_initialise = nvmx_vcpu_initialise, > + .nhvm_vcpu_destroy = nvmx_vcpu_destroy, > + .nhvm_vcpu_reset = nvmx_vcpu_reset, > + .nhvm_vcpu_guestcr3 = nvmx_vcpu_guestcr3, > + .nhvm_vcpu_hostcr3 = nvmx_vcpu_hostcr3, > + .nhvm_vcpu_asid = nvmx_vcpu_asid, > + .nhvm_intr_blocked = nvmx_intr_blocked > }; > > struct hvm_function_table * __init start_vmx(void) > diff -r 70ee714947fb xen/arch/x86/hvm/vmx/vvmx.c > --- /dev/null Thu Jan 01 00:00:00 1970 +0000 > +++ b/xen/arch/x86/hvm/vmx/vvmx.c Mon May 30 17:15:52 2011 +0800 > @@ -0,0 +1,93 @@ > +/* > + * vvmx.c: Support virtual VMX for nested virtualization. > + * > + * Copyright (c) 2010, Intel Corporation. > + * Author: Qing He<qing.he@intel.com> > + * Eddie Dong<eddie.dong@intel.com> > + * > + * 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<xen/config.h> > +#include<asm/types.h> > +#include<asm/p2m.h> > +#include<asm/hvm/vmx/vmx.h> > +#include<asm/hvm/vmx/vvmx.h> > + > +int nvmx_vcpu_initialise(struct vcpu *v) > +{ > + struct nestedvmx *nvmx =&vcpu_2_nvmx(v); > + struct nestedvcpu *nvcpu =&vcpu_nestedhvm(v); > + > + nvcpu->nv_n2vmcx = alloc_xenheap_page(); > + if ( !nvcpu->nv_n2vmcx ) > + { > + gdprintk(XENLOG_ERR, "nest: allocation for shadow vmcs failed\n"); > + goto out; > + } > + nvmx->vmxon_region_pa = 0; > + nvcpu->nv_vvmcx = NULL; > + nvcpu->nv_vvmcxaddr = VMCX_EADDR; > + nvmx->intr.intr_info = 0; > + nvmx->intr.error_code = 0; > + nvmx->iobitmap[0] = NULL; > + nvmx->iobitmap[1] = NULL; > + return 0; > +out: > + return -ENOMEM; > +} > + > +void nvmx_vcpu_destroy(struct vcpu *v) > +{ > + struct nestedvcpu *nvcpu =&vcpu_nestedhvm(v); > + > + if ( nvcpu->nv_n2vmcx ) { > + __vmpclear(virt_to_maddr(nvcpu->nv_n2vmcx)); > + free_xenheap_page(nvcpu->nv_n2vmcx); > + nvcpu->nv_n2vmcx = NULL; > + } > + if ( nvcpu->nv_vvmcx ) { > + unmap_domain_page_global(nvcpu->nv_vvmcx); > + nvcpu->nv_vvmcx == NULL; > + } > + nvcpu->nv_vvmcxaddr = VMCX_EADDR; > +} > + > +int nvmx_vcpu_reset(struct vcpu *v) > +{ > + return 0; > +} > + > +uint64_t nvmx_vcpu_guestcr3(struct vcpu *v) > +{ > + /* TODO */ > + ASSERT(0); > + return 0; > +} > + > +uint64_t nvmx_vcpu_hostcr3(struct vcpu *v) > +{ > + /* TODO */ > + ASSERT(0); > + return 0; > +} > + > +uint32_t nvmx_vcpu_asid(struct vcpu *v) > +{ > + /* TODO */ > + ASSERT(0); > + return 0; > +} > + > diff -r 70ee714947fb xen/include/asm-x86/hvm/vmx/vvmx.h > --- a/xen/include/asm-x86/hvm/vmx/vvmx.h Sat May 28 09:49:25 2011 +0800 > +++ b/xen/include/asm-x86/hvm/vmx/vvmx.h Mon May 30 17:15:52 2011 +0800 > @@ -37,5 +37,14 @@ > > #define nvcpu_2_nvmx(nv) ((*(nv)).u.nvmx) > #define vcpu_2_nvmx(v) (nvcpu_2_nvmx(&vcpu_nestedhvm(v))) > + > +int nvmx_vcpu_initialise(struct vcpu *v); > +void nvmx_vcpu_destroy(struct vcpu *v); > +int nvmx_vcpu_reset(struct vcpu *v); > +uint64_t nvmx_vcpu_guestcr3(struct vcpu *v); > +uint64_t nvmx_vcpu_hostcr3(struct vcpu *v); > +uint32_t nvmx_vcpu_asid(struct vcpu *v); > +enum hvm_intblk nvmx_intr_blocked(struct vcpu *v); > + > #endif /* __ASM_X86_HVM_VVMX_H__ */ > > > _______________________________________________ > Xen-devel mailing list > Xen-devel@lists.xensource.com > http://lists.xensource.com/xen-devel >-- ---to satisfy European Law for business letters: Advanced Micro Devices GmbH Einsteinring 24, 85689 Dornach b. Muenchen Geschaeftsfuehrer: Alberto Bozzo, Andrew Bowd Sitz: Dornach, Gemeinde Aschheim, Landkreis Muenchen Registergericht Muenchen, HRB Nr. 43632 _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
At 09:47 +0100 on 01 Jun (1306921654), Ian Campbell wrote:> Please don''t start new threads by reply to an old, unrelated mail -- it > confuses threading. > > On Wed, 2011-06-01 at 05:11 +0100, Dong, Eddie wrote: > > Keir/Tim: > > Here is the nested VMX support series for comments. The current > > solution works with host shadow page table. The virtual EPT support > > will come soon. > > I''m neither Tim nor Keir but the documentary aspects of this series seem > rather insufficient IMHO, even for an RFC. > > You summary lines are mostly verbose boilerplate with very little actual > information and the changelog entries do not generally describe the > change either. Lastly you haven''t included a Signed-off-by on at least > some of the patches (maybe that''s OK for an RFC but you did sign off > some of them). > > Also there are two patch 5''s and two patch 12''s, a tool such as the hg > email extension would help avoid that sort of thing.Yes, ''hg email'' does a good job of posting large patch series. Also, if you can add [diff] showfunc = True to your ~/.hgrc, it makes big patches much easier to review. Cheers, Tim. -- Tim Deegan <Tim.Deegan@citrix.com> Principal Software Engineer, Xen Platform Team Citrix Systems UK Ltd. (Company #02937203, SL9 0BG) _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
On 06/01/11 06:11, Dong, Eddie wrote:> Keir/Tim: > Here is the nested VMX support series for comments.> The current solution works with host shadow page table. The virtual EPT > support will come soon. I am surprised that shadow-on-shadow works w/o touching anything in xen/arch/x86/mm/* Christoph -- ---to satisfy European Law for business letters: Advanced Micro Devices GmbH Einsteinring 24, 85689 Dornach b. Muenchen Geschaeftsfuehrer: Alberto Bozzo, Andrew Bowd Sitz: Dornach, Gemeinde Aschheim, Landkreis Muenchen Registergericht Muenchen, HRB Nr. 43632 _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
At 11:56 +0200 on 01 Jun (1306929406), Christoph Egger wrote:> On 06/01/11 06:11, Dong, Eddie wrote: > >Keir/Tim: > > Here is the nested VMX support series for comments. > > The current solution works with host shadow page table. The virtual EPT > > support will come soon. > > I am surprised that shadow-on-shadow works w/o touching anything in > xen/arch/x86/mm/*What do you think should break? One major thing was that we didn''t properly report invalid PTE bits, but that''s been fixed. Tim. -- Tim Deegan <Tim.Deegan@citrix.com> Principal Software Engineer, Xen Platform Team Citrix Systems UK Ltd. (Company #02937203, SL9 0BG) _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
On 06/01/11 12:15, Tim Deegan wrote:> At 11:56 +0200 on 01 Jun (1306929406), Christoph Egger wrote: >> On 06/01/11 06:11, Dong, Eddie wrote: >>> Keir/Tim: >>> Here is the nested VMX support series for comments. >>> The current solution works with host shadow page table. The virtual EPT >>> support will come soon. >> >> I am surprised that shadow-on-shadow works w/o touching anything in >> xen/arch/x86/mm/* > > What do you think should break? One major thing was that we didn''t > properly report invalid PTE bits, but that''s been fixed.I thought some code to switch forth and back between two shadow page tables needs to be added at least (one to run l1 guest and one to run l2 guest). Christoph -- ---to satisfy European Law for business letters: Advanced Micro Devices GmbH Einsteinring 24, 85689 Dornach b. Muenchen Geschaeftsfuehrer: Alberto Bozzo, Andrew Bowd Sitz: Dornach, Gemeinde Aschheim, Landkreis Muenchen Registergericht Muenchen, HRB Nr. 43632 _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
At 12:34 +0200 on 01 Jun (1306931673), Christoph Egger wrote:> On 06/01/11 12:15, Tim Deegan wrote: > >At 11:56 +0200 on 01 Jun (1306929406), Christoph Egger wrote: > >>On 06/01/11 06:11, Dong, Eddie wrote: > >>>Keir/Tim: > >>> Here is the nested VMX support series for comments. > >>>The current solution works with host shadow page table. The virtual EPT > >>>support will come soon. > >> > >>I am surprised that shadow-on-shadow works w/o touching anything in > >>xen/arch/x86/mm/* > > > >What do you think should break? One major thing was that we didn''t > >properly report invalid PTE bits, but that''s been fixed. > > I thought some code to switch forth and back between two shadow page > tables needs to be added at least (one to run l1 guest and one to > run > l2 guest).No need - as long as the n1 guest provides valid pagetables (which may themselves be shadows of n2 pagetables), all n0 has to do is shadow them (again). Cheers, Tim. -- Tim Deegan <Tim.Deegan@citrix.com> Principal Software Engineer, Xen Platform Team Citrix Systems UK Ltd. (Company #02937203, SL9 0BG) _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
>> I thought some code to switch forth and back between two shadow page >> tables needs to be added at least (one to run l1 guest and one to >> run >> l2 guest). > >No need - as long as the n1 guest provides valid pagetables (which may >themselves be shadows of n2 pagetables), all n0 has to do is shadow them >(again).Yes. The reason to use shadow on shadow for now is to reduce the rebase patch size. It is already too large :( Thx, Eddie _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
> From: Christoph Egger > Sent: Wednesday, June 01, 2011 6:35 PM > > On 06/01/11 12:15, Tim Deegan wrote: > > At 11:56 +0200 on 01 Jun (1306929406), Christoph Egger wrote: > >> On 06/01/11 06:11, Dong, Eddie wrote: > >>> Keir/Tim: > >>> Here is the nested VMX support series for comments. > >>> The current solution works with host shadow page table. The virtual EPT > >>> support will come soon. > >> > >> I am surprised that shadow-on-shadow works w/o touching anything in > >> xen/arch/x86/mm/* > > > > What do you think should break? One major thing was that we didn''t > > properly report invalid PTE bits, but that''s been fixed. > > I thought some code to switch forth and back between two shadow page > tables needs to be added at least (one to run l1 guest and one to run > l2 guest). > > Christoph >as long as correctly emulating HOST_CR3 and GUEST_CR3 fields as L1 cr3 switch action, you don''t need any other special logic. Thanks Kevin _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel