WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

Re: [Xen-devel] [PATCH 10/17] vmx: nest: VMExit handler in L2

To: Qing He <qing.he@xxxxxxxxx>
Subject: Re: [Xen-devel] [PATCH 10/17] vmx: nest: VMExit handler in L2
From: Tim Deegan <Tim.Deegan@xxxxxxxxxx>
Date: Thu, 20 May 2010 12:44:14 +0100
Cc: "xen-devel@xxxxxxxxxxxxxxxxxxx" <xen-devel@xxxxxxxxxxxxxxxxxxx>
Delivery-date: Thu, 20 May 2010 04:45:11 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
In-reply-to: <1271929289-18572-11-git-send-email-qing.he@xxxxxxxxx>
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
References: <1271929289-18572-1-git-send-email-qing.he@xxxxxxxxx> <1271929289-18572-11-git-send-email-qing.he@xxxxxxxxx>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Mutt/1.5.18 (2008-05-17)
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