[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH 10/17] vmx: nest: VMExit handler in L2
At 10:41 +0100 on 22 Apr (1271932882), Qing He wrote: > Handles VMExits happened in L2 > > Signed-off-by: Qing He <qing.he@xxxxxxxxx> > > --- > arch/x86/hvm/vmx/nest.c | 182 > +++++++++++++++++++++++++++++++++++++++++ > arch/x86/hvm/vmx/vmx.c | 6 + > include/asm-x86/hvm/vmx/nest.h | 3 > include/asm-x86/hvm/vmx/vmx.h | 1 > 4 files changed, 192 insertions(+) > > diff -r a7de30ed250d -r 2f9ba6dbbe62 xen/arch/x86/hvm/vmx/nest.c > --- a/xen/arch/x86/hvm/vmx/nest.c Thu Apr 22 22:30:09 2010 +0800 > +++ b/xen/arch/x86/hvm/vmx/nest.c Thu Apr 22 22:30:09 2010 +0800 > @@ -976,3 +976,185 @@ > > /* TODO: NMI */ > } > + > +/* > + * L2 VMExit handling > + */ > + > +static struct control_bit_for_reason { > + int reason; > + unsigned long bit; > +} control_bit_for_reason [] = { > + {EXIT_REASON_PENDING_VIRT_INTR, CPU_BASED_VIRTUAL_INTR_PENDING}, > + {EXIT_REASON_HLT, CPU_BASED_HLT_EXITING}, > + {EXIT_REASON_INVLPG, CPU_BASED_INVLPG_EXITING}, > + {EXIT_REASON_MWAIT_INSTRUCTION, CPU_BASED_MWAIT_EXITING}, > + {EXIT_REASON_RDPMC, CPU_BASED_RDPMC_EXITING}, > + {EXIT_REASON_RDTSC, CPU_BASED_RDTSC_EXITING}, > + {EXIT_REASON_PENDING_VIRT_NMI, CPU_BASED_VIRTUAL_NMI_PENDING}, > + {EXIT_REASON_DR_ACCESS, CPU_BASED_MOV_DR_EXITING}, > + {EXIT_REASON_MONITOR_INSTRUCTION, CPU_BASED_MONITOR_EXITING}, > + {EXIT_REASON_PAUSE_INSTRUCTION, CPU_BASED_PAUSE_EXITING}, > +}; > + > +int vmx_nest_l2_vmexit_handler(struct cpu_user_regs *regs, > + unsigned int exit_reason) > +{ > + struct vcpu *v = current; > + struct vmx_nest_struct *nest = &v->arch.hvm_vmx.nest; > + u32 ctrl; > + int bypass_l0 = 0; > + > + nest->vmexit_pending = 0; > + nest->intr_info = 0; > + nest->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) ) > + nest->vmexit_pending = 1; > + } > + else if ( (intr_info & valid_mask) == valid_mask ) > + { > + exec_bitmap =__get_vvmcs(nest->vvmcs, EXCEPTION_BITMAP); > + > + if ( exec_bitmap & (1 << vector) ) > + nest->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_IO_INSTRUCTION: > + case EXIT_REASON_CPUID: > + case EXIT_REASON_MSR_READ: > + case EXIT_REASON_MSR_WRITE: Aren't these gated on a control bitmap in the L1 VMCS? > + 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 */ > + nest->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) ) > + nest->vmexit_pending = 1; > + > + break; > + } > + case EXIT_REASON_PENDING_VIRT_NMI: > + { > + ctrl = v->arch.hvm_vmx.exec_control; > + > + if ( !(ctrl & CPU_BASED_VIRTUAL_NMI_PENDING) ) > + nest->vmexit_pending = 1; > + > + break; > + } > + > + case EXIT_REASON_HLT: > + case EXIT_REASON_RDTSC: > + case EXIT_REASON_RDPMC: > + case EXIT_REASON_MWAIT_INSTRUCTION: > + case EXIT_REASON_PAUSE_INSTRUCTION: > + case EXIT_REASON_MONITOR_INSTRUCTION: > + case EXIT_REASON_DR_ACCESS: > + case EXIT_REASON_INVLPG: > + { > + int i; > + > + /* exit according to guest exec_control */ > + ctrl = __get_vvmcs(nest->vvmcs, CPU_BASED_VM_EXEC_CONTROL); > + > + for ( i = 0; i < ARRAY_SIZE(control_bit_for_reason); i++ ) > + if ( control_bit_for_reason[i].reason == exit_reason ) > + break; You've already got a switch statement - why not gate these individually rather than bundling them together and scanning an array? > + if ( i == ARRAY_SIZE(control_bit_for_reason) ) > + break; > + > + if ( control_bit_for_reason[i].bit & ctrl ) > + nest->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 = __get_vvmcs(nest->vvmcs, CPU_BASED_VM_EXEC_CONTROL); > + > + if ( cr == 3 ) > + { > + mask = write? CPU_BASED_CR3_STORE_EXITING: > + CPU_BASED_CR3_LOAD_EXITING; > + if ( ctrl & mask ) > + nest->vmexit_pending = 1; > + } > + else if ( cr == 8 ) > + { > + mask = write? CPU_BASED_CR8_STORE_EXITING: > + CPU_BASED_CR8_LOAD_EXITING; > + if ( ctrl & mask ) > + nest->vmexit_pending = 1; > + } > + else /* CR0, CR4, CLTS, LMSW */ > + nest->vmexit_pending = 1; > + > + break; > + } > + default: > + gdprintk(XENLOG_WARNING, "Unknown nested vmexit reason %x.\n", > + exit_reason); > + } > + > + if ( nest->vmexit_pending ) > + bypass_l0 = 1; This variable doesn't seem to do anything useful. > + return bypass_l0; > +} Cheers, Tim. -- Tim Deegan <Tim.Deegan@xxxxxxxxxx> Principal Software Engineer, XenServer Engineering Citrix Systems UK Ltd. (Company #02937203, SL9 0BG) _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |