debuggers.hg

changeset 22671:920826e80bee

x86 xsave: supports xsave (CPUID:0xD) enumeration for all sub-leaves.

In specific, it fixes the following issues:

1. The sub-leaves of CPUID:0x0000000D aren't contiguous. Hypervisor
shouldn't use register values to stop the enumeration. This patch
moves checking on XSAVE sub-leaves out of if-else statement. It also
bumps up sub-leaves to 63.
2. It creates a common function for xsave.
3. The main leaf 0 of CPUID:0x0000000D in current Xen is broken,
especially ECX and EBX registers. This patch cleans it up.
4. It adds support to detects EBX value of CPUID:0x0000000D main leaf
0 on-the-fly.

Signed-off-by: Wei Huang2 <wei.huang2@amd.com>
author Keir Fraser <keir@xen.org>
date Fri Dec 24 08:39:42 2010 +0000 (2010-12-24)
parents 26e7e6c6ff7f
children ceb508436e6e
files tools/libxc/xc_cpuid_x86.c xen/arch/x86/hvm/hvm.c
line diff
     1.1 --- a/tools/libxc/xc_cpuid_x86.c	Fri Dec 24 08:38:22 2010 +0000
     1.2 +++ b/tools/libxc/xc_cpuid_x86.c	Fri Dec 24 08:39:42 2010 +0000
     1.3 @@ -164,6 +164,58 @@ static void intel_xc_cpuid_policy(
     1.4      }
     1.5  }
     1.6  
     1.7 +#define XSAVEOPT        (1 << 0)
     1.8 +/* Configure extended state enumeration leaves (0x0000000D for xsave) */
     1.9 +static void xc_cpuid_config_xsave(
    1.10 +    xc_interface *xch, domid_t domid, uint64_t xfeature_mask,
    1.11 +    const unsigned int *input, unsigned int *regs)
    1.12 +{
    1.13 +    if ( xfeature_mask == 0 )
    1.14 +    {
    1.15 +        regs[0] = regs[1] = regs[2] = regs[3] = 0;
    1.16 +        return;
    1.17 +    }
    1.18 +
    1.19 +    switch ( input[1] )
    1.20 +    {
    1.21 +    case 0: 
    1.22 +        /* EAX: low 32bits of xfeature_enabled_mask */
    1.23 +        regs[0] = xfeature_mask & 0xFFFFFFFF;
    1.24 +        /* EDX: high 32bits of xfeature_enabled_mask */
    1.25 +        regs[3] = (xfeature_mask >> 32) & 0xFFFFFFFF;
    1.26 +        /* ECX: max size required by all HW features */
    1.27 +        {
    1.28 +            unsigned int _input[2] = {0xd, 0x0}, _regs[4];
    1.29 +            regs[2] = 0;
    1.30 +            for ( _input[1] = 2; _input[1] < 64; _input[1]++ )
    1.31 +            {
    1.32 +                cpuid(_input, _regs);
    1.33 +                if ( (_regs[0] + _regs[1]) > regs[2] )
    1.34 +                    regs[2] = _regs[0] + _regs[1];
    1.35 +            }
    1.36 +        }
    1.37 +        /* EBX: max size required by enabled features. 
    1.38 +         * This register contains a dynamic value, which varies when a guest 
    1.39 +         * enables or disables XSTATE features (via xsetbv). The default size 
    1.40 +         * after reset is 576. */ 
    1.41 +        regs[1] = 512 + 64; /* FP/SSE + XSAVE.HEADER */
    1.42 +        break;
    1.43 +    case 1: /* leaf 1 */
    1.44 +        regs[0] &= XSAVEOPT;
    1.45 +        regs[1] = regs[2] = regs[3] = 0;
    1.46 +        break;
    1.47 +    case 2 ... 63: /* sub-leaves */
    1.48 +        if ( !(xfeature_mask & (1ULL << input[1])) )
    1.49 +        {
    1.50 +            regs[0] = regs[1] = regs[2] = regs[3] = 0;
    1.51 +            break;
    1.52 +        }
    1.53 +        /* Don't touch EAX, EBX. Also cleanup ECX and EDX */
    1.54 +        regs[2] = regs[3] = 0;
    1.55 +        break;
    1.56 +    }
    1.57 +}
    1.58 +
    1.59  static void xc_cpuid_hvm_policy(
    1.60      xc_interface *xch, domid_t domid,
    1.61      const unsigned int *input, unsigned int *regs)
    1.62 @@ -244,43 +296,7 @@ static void xc_cpuid_hvm_policy(
    1.63          break;
    1.64  
    1.65      case 0x0000000d:
    1.66 -#define XSTATE_FP       (1 << 0)
    1.67 -#define XSTATE_SSE      (1 << 1)
    1.68 -#define XSTATE_YMM      (1 << 2)
    1.69 -#define XSAVEOPT        (1 << 0)
    1.70 -#define XSTATE_YMM_SIZE 256
    1.71 -        if ( xfeature_mask == 0 )
    1.72 -        {
    1.73 -            regs[0] = regs[1] = regs[2] = regs[3] = 0;
    1.74 -            break;
    1.75 -        }
    1.76 -        switch ( input[1] )
    1.77 -        {
    1.78 -        case 0:
    1.79 -            /* We only enable the features we know. */
    1.80 -            regs[0] = xfeature_mask;
    1.81 -            /* FP/SSE + XSAVE.HEADER + YMM. */
    1.82 -            regs[2] = 512 + 64;
    1.83 -            if ( regs[0] & XSTATE_YMM )
    1.84 -                regs[2] += XSTATE_YMM_SIZE;
    1.85 -            regs[1] = regs[2];
    1.86 -            regs[3] = 0;
    1.87 -            break;
    1.88 -        case 1:
    1.89 -            regs[0] &= XSAVEOPT;
    1.90 -            regs[1] = regs[2] = regs[3] = 0;
    1.91 -            break;
    1.92 -        case 2:
    1.93 -            if ( !(xfeature_mask & XSTATE_YMM) )
    1.94 -                break;
    1.95 -            regs[0] = XSTATE_YMM_SIZE;
    1.96 -            regs[1] = 512 + 64; /* FP/SSE + XSAVE.HEADER */
    1.97 -            regs[2] = regs[3] = 0;
    1.98 -            break;
    1.99 -        default:
   1.100 -            regs[0] = regs[1] = regs[2] = regs[3] = 0;
   1.101 -            break;
   1.102 -        }
   1.103 +        xc_cpuid_config_xsave(xch, domid, xfeature_mask, input, regs);
   1.104          break;
   1.105  
   1.106      case 0x80000000:
   1.107 @@ -501,21 +517,21 @@ int xc_cpuid_apply_policy(xc_interface *
   1.108              rc = xc_cpuid_do_domctl(xch, domid, input, regs);
   1.109              if ( rc )
   1.110                  return rc;
   1.111 +        }
   1.112  
   1.113 -            /* Intel cache descriptor leaves. */
   1.114 -            if ( input[0] == 4 )
   1.115 -            {
   1.116 -                input[1]++;
   1.117 -                /* More to do? Then loop keeping %%eax==0x00000004. */
   1.118 -                if ( (regs[0] & 0x1f) != 0 )
   1.119 -                    continue;
   1.120 -            }
   1.121 -
   1.122 -            /* XSAVE information, subleaves 0-2. */
   1.123 -            if ( (input[0] == 0xd) && (input[1]++ < 2) )
   1.124 +        /* Intel cache descriptor leaves. */
   1.125 +        if ( input[0] == 4 )
   1.126 +        {
   1.127 +            input[1]++;
   1.128 +            /* More to do? Then loop keeping %%eax==0x00000004. */
   1.129 +            if ( (regs[0] & 0x1f) != 0 )
   1.130                  continue;
   1.131          }
   1.132  
   1.133 +        /* XSAVE information, subleaves 0-63. */
   1.134 +        if ( (input[0] == 0xd) && (input[1]++ < 63) )
   1.135 +            continue;
   1.136 +
   1.137          input[0]++;
   1.138          if ( !(input[0] & 0x80000000u) && (input[0] > base_max ) )
   1.139              input[0] = 0x80000000u;
     2.1 --- a/xen/arch/x86/hvm/hvm.c	Fri Dec 24 08:38:22 2010 +0000
     2.2 +++ b/xen/arch/x86/hvm/hvm.c	Fri Dec 24 08:39:42 2010 +0000
     2.3 @@ -2144,6 +2144,24 @@ void hvm_cpuid(unsigned int input, unsig
     2.4          /* Fix the x2APIC identifier. */
     2.5          *edx = v->vcpu_id * 2;
     2.6          break;
     2.7 +    case 0xd:
     2.8 +    {
     2.9 +        unsigned int sub_leaf, _eax, _ebx, _ecx, _edx;
    2.10 +        /* EBX value of main leaf 0 depends on enabled xsave features */
    2.11 +        if ( count == 0 && v->arch.xcr0 ) 
    2.12 +        {
    2.13 +            for ( sub_leaf = 2; 
    2.14 +                  (sub_leaf < 64) && (v->arch.xcr0 & (1ULL << sub_leaf));
    2.15 +                  sub_leaf++ ) 
    2.16 +            {
    2.17 +                domain_cpuid(v->domain, input, sub_leaf, &_eax, &_ebx, &_ecx, 
    2.18 +                             &_edx);
    2.19 +                if ( (_eax + _ebx) > *ebx )
    2.20 +                    *ebx = _eax + _ebx;
    2.21 +            }
    2.22 +        }
    2.23 +        break;
    2.24 +    }
    2.25      case 0x80000001:
    2.26          /* We expose RDTSCP feature to guest only when
    2.27             tsc_mode == TSC_MODE_DEFAULT and host_tsc_is_safe() returns 1 */