ia64/xen-unstable

changeset 8849:70024ebbdf55

Clarify lazy FPU management in VMX domains.

Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Tue Feb 14 20:17:26 2006 +0100 (2006-02-14)
parents 39b392a22002
children 646edff07475
files xen/arch/x86/hvm/vmx/vmx.c xen/include/asm-x86/hvm/vmx/vmx.h
line diff
     1.1 --- a/xen/arch/x86/hvm/vmx/vmx.c	Tue Feb 14 19:43:45 2006 +0100
     1.2 +++ b/xen/arch/x86/hvm/vmx/vmx.c	Tue Feb 14 20:17:26 2006 +0100
     1.3 @@ -617,12 +617,17 @@ static void vmx_do_no_device_fault(void)
     1.4  
     1.5      clts();
     1.6      setup_fpu(current);
     1.7 +
     1.8 +    /* Disable TS in guest CR0 unless the guest wants the exception too. */
     1.9      __vmread_vcpu(v, CR0_READ_SHADOW, &cr0);
    1.10 -    if (!(cr0 & X86_CR0_TS)) {
    1.11 +    if ( !(cr0 & X86_CR0_TS) )
    1.12 +    {
    1.13          __vmread_vcpu(v, GUEST_CR0, &cr0);
    1.14          cr0 &= ~X86_CR0_TS;
    1.15          __vmwrite(GUEST_CR0, cr0);
    1.16      }
    1.17 +
    1.18 +    /* Xen itself doesn't need another exception. */
    1.19      __vm_clear_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_NM);
    1.20  }
    1.21  
    1.22 @@ -1152,14 +1157,17 @@ static int vmx_set_cr0(unsigned long val
    1.23       */
    1.24      __vmread_vcpu(v, CR0_READ_SHADOW, &old_cr0);
    1.25      paging_enabled = (old_cr0 & X86_CR0_PE) && (old_cr0 & X86_CR0_PG);
    1.26 -    /* If OS don't use clts to clear TS bit...*/
    1.27 -    if((old_cr0 & X86_CR0_TS) && !(value & X86_CR0_TS))
    1.28 +
    1.29 +    /*
    1.30 +     * Disable TS? Then we do so at the same time, and initialise FPU.
    1.31 +     * This avoids needing another vmexit.
    1.32 +     */
    1.33 +    if ( (old_cr0 & ~value & X86_CR0_TS) != 0 )
    1.34      {
    1.35 -            clts();
    1.36 -            setup_fpu(v);
    1.37 +        clts();
    1.38 +        setup_fpu(v);
    1.39      }
    1.40  
    1.41 -
    1.42      __vmwrite(GUEST_CR0, value | X86_CR0_PE | X86_CR0_PG | X86_CR0_NE);
    1.43      __vmwrite(CR0_READ_SHADOW, value);
    1.44  
    1.45 @@ -1510,6 +1518,8 @@ static int vmx_cr_access(unsigned long e
    1.46          break;
    1.47      case TYPE_CLTS:
    1.48          TRACE_VMEXIT(1,TYPE_CLTS);
    1.49 +
    1.50 +        /* We initialise the FPU now, to avoid needing another vmexit. */
    1.51          clts();
    1.52          setup_fpu(current);
    1.53  
     2.1 --- a/xen/include/asm-x86/hvm/vmx/vmx.h	Tue Feb 14 19:43:45 2006 +0100
     2.2 +++ b/xen/include/asm-x86/hvm/vmx/vmx.h	Tue Feb 14 20:17:26 2006 +0100
     2.3 @@ -382,14 +382,22 @@ static inline void vmx_stts(void)
     2.4      unsigned long cr0;
     2.5      struct vcpu *v = current;
     2.6  
     2.7 -    __vmread_vcpu(v, GUEST_CR0, &cr0);
     2.8 -    if (!(cr0 & X86_CR0_TS)) {
     2.9 +    /* FPU state already dirty? Then no need to setup_fpu() lazily. */
    2.10 +    if ( test_bit(_VCPUF_fpu_dirtied, &v->vcpu_flags) )
    2.11 +        return;
    2.12 +
    2.13 +    /*
    2.14 +     * If the guest does not have TS enabled then we must cause and handle an 
    2.15 +     * exception on first use of the FPU. If the guest *does* have TS enabled 
    2.16 +     * then this is not necessary: no FPU activity can occur until the guest 
    2.17 +     * clears CR0.TS, and we will initialise the FPU when that happens.
    2.18 +     */
    2.19 +    __vmread_vcpu(v, CR0_READ_SHADOW, &cr0);
    2.20 +    if ( !(cr0 & X86_CR0_TS) )
    2.21 +    {
    2.22          __vmwrite(GUEST_CR0, cr0 | X86_CR0_TS);
    2.23 +        __vm_set_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_NM);
    2.24      }
    2.25 -
    2.26 -    __vmread_vcpu(v, CR0_READ_SHADOW, &cr0);
    2.27 -    if (!(cr0 & X86_CR0_TS))
    2.28 -       __vm_set_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_NM);
    2.29  }
    2.30  
    2.31  /* Works only for vcpu == current */