debuggers.hg

changeset 22797:58304c1cc725

x86 fpu: Code clean up. Eliminate per-cpu xsave init verbosity.

Signed-off-by: Keir Fraser <keir@xen.org>
author Keir Fraser <keir@xen.org>
date Fri Jan 14 09:11:28 2011 +0000 (2011-01-14)
parents 4b7cb21caf0e
children ff97273750b8
files xen/arch/x86/acpi/suspend.c xen/arch/x86/domain.c xen/arch/x86/i387.c xen/include/asm-x86/i387.h
line diff
     1.1 --- a/xen/arch/x86/acpi/suspend.c	Fri Jan 14 08:34:53 2011 +0000
     1.2 +++ b/xen/arch/x86/acpi/suspend.c	Fri Jan 14 09:11:28 2011 +0000
     1.3 @@ -24,8 +24,7 @@ static uint16_t saved_segs[4];
     1.4  
     1.5  void save_rest_processor_state(void)
     1.6  {
     1.7 -    if ( !is_idle_vcpu(current) )
     1.8 -        unlazy_fpu(current);
     1.9 +    save_init_fpu(current);
    1.10  
    1.11  #if defined(CONFIG_X86_64)
    1.12      asm volatile (
     2.1 --- a/xen/arch/x86/domain.c	Fri Jan 14 08:34:53 2011 +0000
     2.2 +++ b/xen/arch/x86/domain.c	Fri Jan 14 09:11:28 2011 +0000
     2.3 @@ -1384,7 +1384,7 @@ static void __context_switch(void)
     2.4          memcpy(&p->arch.guest_context.user_regs,
     2.5                 stack_regs,
     2.6                 CTXT_SWITCH_STACK_BYTES);
     2.7 -        unlazy_fpu(p);
     2.8 +        save_init_fpu(p);
     2.9          p->arch.ctxt_switch_from(p);
    2.10      }
    2.11  
     3.1 --- a/xen/arch/x86/i387.c	Fri Jan 14 08:34:53 2011 +0000
     3.2 +++ b/xen/arch/x86/i387.c	Fri Jan 14 09:11:28 2011 +0000
     3.3 @@ -16,6 +16,49 @@
     3.4  #include <asm/i387.h>
     3.5  #include <asm/asm_defns.h>
     3.6  
     3.7 +static bool_t __read_mostly cpu_has_xsaveopt;
     3.8 +
     3.9 +static void xsave(struct vcpu *v)
    3.10 +{
    3.11 +    struct xsave_struct *ptr = v->arch.xsave_area;
    3.12 +
    3.13 +    asm volatile (
    3.14 +        ".byte " REX_PREFIX "0x0f,0xae,0x27"
    3.15 +        :
    3.16 +        : "a" (-1), "d" (-1), "D"(ptr)
    3.17 +        : "memory" );
    3.18 +}
    3.19 +
    3.20 +static void xsaveopt(struct vcpu *v)
    3.21 +{
    3.22 +    struct xsave_struct *ptr = v->arch.xsave_area;
    3.23 +
    3.24 +    asm volatile (
    3.25 +        ".byte " REX_PREFIX "0x0f,0xae,0x37"
    3.26 +        :
    3.27 +        : "a" (-1), "d" (-1), "D"(ptr)
    3.28 +        : "memory" );
    3.29 +}
    3.30 +
    3.31 +static void xrstor(struct vcpu *v)
    3.32 +{
    3.33 +    struct xsave_struct *ptr = v->arch.xsave_area;
    3.34 +
    3.35 +    asm volatile (
    3.36 +        ".byte " REX_PREFIX "0x0f,0xae,0x2f"
    3.37 +        :
    3.38 +        : "m" (*ptr), "a" (-1), "d" (-1), "D"(ptr) );
    3.39 +}
    3.40 +
    3.41 +static void load_mxcsr(unsigned long val)
    3.42 +{
    3.43 +    val &= 0xffbf;
    3.44 +    asm volatile ( "ldmxcsr %0" : : "m" (val) );
    3.45 +}
    3.46 +
    3.47 +static void init_fpu(void);
    3.48 +static void restore_fpu(struct vcpu *v);
    3.49 +
    3.50  void setup_fpu(struct vcpu *v)
    3.51  {
    3.52      ASSERT(!is_idle_vcpu(v));
    3.53 @@ -23,47 +66,52 @@ void setup_fpu(struct vcpu *v)
    3.54      /* Avoid recursion. */
    3.55      clts();
    3.56  
    3.57 -    if ( !v->fpu_dirtied )
    3.58 -    {
    3.59 -        v->fpu_dirtied = 1;
    3.60 -        if ( cpu_has_xsave )
    3.61 -        {
    3.62 -            if ( !v->fpu_initialised )
    3.63 -                v->fpu_initialised = 1;
    3.64 +    if ( v->fpu_dirtied )
    3.65 +        return;
    3.66  
    3.67 -            /* XCR0 normally represents what guest OS set. In case of Xen
    3.68 -             * itself, we set all supported feature mask before doing
    3.69 -             * save/restore.
    3.70 -             */
    3.71 -            set_xcr0(v->arch.xcr0_accum);
    3.72 -            xrstor(v);
    3.73 -            set_xcr0(v->arch.xcr0);
    3.74 -        }
    3.75 -        else
    3.76 -        {
    3.77 -            if ( v->fpu_initialised )
    3.78 -                restore_fpu(v);
    3.79 -            else
    3.80 -                init_fpu();
    3.81 -        }
    3.82 +    if ( cpu_has_xsave )
    3.83 +    {
    3.84 +        /*
    3.85 +         * XCR0 normally represents what guest OS set. In case of Xen itself, 
    3.86 +         * we set all supported feature mask before doing save/restore.
    3.87 +         */
    3.88 +        set_xcr0(v->arch.xcr0_accum);
    3.89 +        xrstor(v);
    3.90 +        set_xcr0(v->arch.xcr0);
    3.91      }
    3.92 +    else if ( v->fpu_initialised )
    3.93 +    {
    3.94 +        restore_fpu(v);
    3.95 +    }
    3.96 +    else
    3.97 +    {
    3.98 +        init_fpu();
    3.99 +    }
   3.100 +
   3.101 +    v->fpu_initialised = 1;
   3.102 +    v->fpu_dirtied = 1;
   3.103  }
   3.104  
   3.105 -void init_fpu(void)
   3.106 +static void init_fpu(void)
   3.107  {
   3.108      asm volatile ( "fninit" );
   3.109      if ( cpu_has_xmm )
   3.110          load_mxcsr(0x1f80);
   3.111 -    current->fpu_initialised = 1;
   3.112  }
   3.113  
   3.114  void save_init_fpu(struct vcpu *v)
   3.115  {
   3.116 -    unsigned long cr0 = read_cr0();
   3.117 -    char *fpu_ctxt = v->arch.guest_context.fpu_ctxt.x;
   3.118 +    unsigned long cr0;
   3.119 +    char *fpu_ctxt;
   3.120 +
   3.121 +    if ( !v->fpu_dirtied )
   3.122 +        return;
   3.123  
   3.124      ASSERT(!is_idle_vcpu(v));
   3.125  
   3.126 +    cr0 = read_cr0();
   3.127 +    fpu_ctxt = v->arch.guest_context.fpu_ctxt.x;
   3.128 +
   3.129      /* This can happen, if a paravirtualised guest OS has set its CR0.TS. */
   3.130      if ( cr0 & X86_CR0_TS )
   3.131          clts();
   3.132 @@ -126,7 +174,7 @@ void save_init_fpu(struct vcpu *v)
   3.133      write_cr0(cr0|X86_CR0_TS);
   3.134  }
   3.135  
   3.136 -void restore_fpu(struct vcpu *v)
   3.137 +static void restore_fpu(struct vcpu *v)
   3.138  {
   3.139      char *fpu_ctxt = v->arch.guest_context.fpu_ctxt.x;
   3.140  
   3.141 @@ -188,29 +236,19 @@ u64 xfeature_mask;
   3.142  /* Cached xcr0 for fast read */
   3.143  DEFINE_PER_CPU(uint64_t, xcr0);
   3.144  
   3.145 -bool_t __read_mostly cpu_has_xsaveopt;
   3.146 -
   3.147  void xsave_init(void)
   3.148  {
   3.149      u32 eax, ebx, ecx, edx;
   3.150      int cpu = smp_processor_id();
   3.151      u32 min_size;
   3.152  
   3.153 -    if ( boot_cpu_data.cpuid_level < XSTATE_CPUID ) {
   3.154 -        printk(XENLOG_ERR "XSTATE_CPUID missing\n");
   3.155 +    if ( boot_cpu_data.cpuid_level < XSTATE_CPUID )
   3.156          return;
   3.157 -    }
   3.158  
   3.159      cpuid_count(XSTATE_CPUID, 0, &eax, &ebx, &ecx, &edx);
   3.160  
   3.161 -    printk("%s: cpu%d: cntxt_max_size: 0x%x and states: %08x:%08x\n",
   3.162 -        __func__, cpu, ecx, edx, eax);
   3.163 -
   3.164 -    if ( ((eax & XSTATE_FP_SSE) != XSTATE_FP_SSE) ||
   3.165 -         ((eax & XSTATE_YMM) && !(eax & XSTATE_SSE)) )
   3.166 -    {
   3.167 -        BUG();
   3.168 -    }
   3.169 +    BUG_ON((eax & XSTATE_FP_SSE) != XSTATE_FP_SSE);
   3.170 +    BUG_ON((eax & XSTATE_YMM) && !(eax & XSTATE_SSE));
   3.171  
   3.172      /* FP/SSE, XSAVE.HEADER, YMM */
   3.173      min_size =  XSAVE_AREA_MIN_SIZE;
     4.1 --- a/xen/include/asm-x86/i387.h	Fri Jan 14 08:34:53 2011 +0000
     4.2 +++ b/xen/include/asm-x86/i387.h	Fri Jan 14 09:11:28 2011 +0000
     4.3 @@ -16,7 +16,6 @@
     4.4  
     4.5  extern unsigned int xsave_cntxt_size;
     4.6  extern u64 xfeature_mask;
     4.7 -extern bool_t cpu_has_xsaveopt;
     4.8  
     4.9  void xsave_init(void);
    4.10  int xsave_alloc_save_area(struct vcpu *v);
    4.11 @@ -75,54 +74,7 @@ static inline uint64_t get_xcr0(void)
    4.12      return this_cpu(xcr0);
    4.13  }
    4.14  
    4.15 -static inline void xsave(struct vcpu *v)
    4.16 -{
    4.17 -    struct xsave_struct *ptr;
    4.18 -
    4.19 -    ptr =(struct xsave_struct *)v->arch.xsave_area;
    4.20 -
    4.21 -    asm volatile (".byte " REX_PREFIX "0x0f,0xae,0x27"
    4.22 -        :
    4.23 -        : "a" (-1), "d" (-1), "D"(ptr)
    4.24 -        : "memory");
    4.25 -}
    4.26 -
    4.27 -static inline void xsaveopt(struct vcpu *v)
    4.28 -{
    4.29 -    struct xsave_struct *ptr;
    4.30 -
    4.31 -    ptr =(struct xsave_struct *)v->arch.xsave_area;
    4.32 -
    4.33 -    asm volatile (".byte " REX_PREFIX "0x0f,0xae,0x37"
    4.34 -        :
    4.35 -        : "a" (-1), "d" (-1), "D"(ptr)
    4.36 -        : "memory");
    4.37 -}
    4.38 -
    4.39 -static inline void xrstor(struct vcpu *v)
    4.40 -{
    4.41 -    struct xsave_struct *ptr;
    4.42 -
    4.43 -    ptr =(struct xsave_struct *)v->arch.xsave_area;
    4.44 -
    4.45 -    asm volatile (".byte " REX_PREFIX "0x0f,0xae,0x2f"
    4.46 -        :
    4.47 -        : "m" (*ptr), "a" (-1), "d" (-1), "D"(ptr));
    4.48 -}
    4.49 -
    4.50  extern void setup_fpu(struct vcpu *v);
    4.51 -extern void init_fpu(void);
    4.52  extern void save_init_fpu(struct vcpu *v);
    4.53 -extern void restore_fpu(struct vcpu *v);
    4.54 -
    4.55 -#define unlazy_fpu(v) do {                      \
    4.56 -    if ( (v)->fpu_dirtied )                     \
    4.57 -        save_init_fpu(v);                       \
    4.58 -} while ( 0 )
    4.59 -
    4.60 -#define load_mxcsr(val) do {                                    \
    4.61 -    unsigned long __mxcsr = ((unsigned long)(val) & 0xffbf);    \
    4.62 -    __asm__ __volatile__ ( "ldmxcsr %0" : : "m" (__mxcsr) );    \
    4.63 -} while ( 0 )
    4.64  
    4.65  #endif /* __ASM_I386_I387_H */