aboutsummaryrefslogtreecommitdiffstats
path: root/tools/libxc/xc_cpuid_x86.c
diff options
context:
space:
mode:
authorKeir Fraser <keir@xen.org>2010-12-17 09:54:22 +0000
committerKeir Fraser <keir@xen.org>2010-12-17 09:54:22 +0000
commit00b8b6c5db3a87d07ed8dd7eb7cf390ce8734a00 (patch)
treeb1aade1f258822424a4053c3de9c97fc4ec3dbe7 /tools/libxc/xc_cpuid_x86.c
parentee8ac49677904c14b69b7fe65d79b57af964edc5 (diff)
downloadxen-00b8b6c5db3a87d07ed8dd7eb7cf390ce8734a00.tar.gz
xen-00b8b6c5db3a87d07ed8dd7eb7cf390ce8734a00.tar.bz2
xen-00b8b6c5db3a87d07ed8dd7eb7cf390ce8734a00.zip
x86 hvm: Move CPUID.0xd (XSAVE) configuration into libxc.
Signed-off-by: Keir Fraser <keir@xen.org>
Diffstat (limited to 'tools/libxc/xc_cpuid_x86.c')
-rw-r--r--tools/libxc/xc_cpuid_x86.c57
1 files changed, 53 insertions, 4 deletions
diff --git a/tools/libxc/xc_cpuid_x86.c b/tools/libxc/xc_cpuid_x86.c
index c5b452488a..6b5a915b0a 100644
--- a/tools/libxc/xc_cpuid_x86.c
+++ b/tools/libxc/xc_cpuid_x86.c
@@ -171,7 +171,8 @@ static void xc_cpuid_hvm_policy(
DECLARE_DOMCTL;
char brand[13];
unsigned long pae;
- int is_pae, xsave_supported;
+ int is_pae;
+ uint64_t xfeature_mask;
xc_get_hvm_param(xch, domid, HVM_PARAM_PAE_ENABLED, &pae);
is_pae = !!pae;
@@ -181,7 +182,7 @@ static void xc_cpuid_hvm_policy(
domctl.cmd = XEN_DOMCTL_getvcpuextstate;
domctl.domain = domid;
do_domctl(xch, &domctl);
- xsave_supported = (domctl.u.vcpuextstate.xfeature_mask != 0);
+ xfeature_mask = domctl.u.vcpuextstate.xfeature_mask;
switch ( input[0] )
{
@@ -204,7 +205,7 @@ static void xc_cpuid_hvm_policy(
bitmaskof(X86_FEATURE_SSE4_2) |
bitmaskof(X86_FEATURE_POPCNT) |
bitmaskof(X86_FEATURE_AES) |
- (xsave_supported ?
+ ((xfeature_mask != 0) ?
(bitmaskof(X86_FEATURE_AVX) |
bitmaskof(X86_FEATURE_XSAVE)) : 0));
@@ -242,6 +243,46 @@ static void xc_cpuid_hvm_policy(
clear_bit(X86_FEATURE_PAE, regs[3]);
break;
+ case 0x0000000d:
+#define XSTATE_FP (1 << 0)
+#define XSTATE_SSE (1 << 1)
+#define XSTATE_YMM (1 << 2)
+#define XSAVEOPT (1 << 0)
+#define XSTATE_YMM_SIZE 256
+ if ( xfeature_mask == 0 )
+ {
+ regs[0] = regs[1] = regs[2] = regs[3] = 0;
+ break;
+ }
+ switch ( input[1] )
+ {
+ case 0:
+ /* We only enable the features we know. */
+ regs[0] = xfeature_mask;
+ /* FP/SSE + XSAVE.HEADER + YMM. */
+ regs[2] = 512 + 64;
+ if ( regs[0] & XSTATE_YMM )
+ regs[2] += XSTATE_YMM_SIZE;
+ regs[1] = regs[2];
+ regs[3] = 0;
+ break;
+ case 1:
+ regs[0] &= XSAVEOPT;
+ regs[1] = regs[2] = regs[3] = 0;
+ break;
+ case 2:
+ if ( !(xfeature_mask & XSTATE_YMM) )
+ break;
+ regs[0] = XSTATE_YMM_SIZE;
+ regs[1] = 512 + 64; /* FP/SSE + XSAVE.HEADER */
+ regs[2] = regs[3] = 0;
+ break;
+ default:
+ regs[0] = regs[1] = regs[2] = regs[3] = 0;
+ break;
+ }
+ break;
+
case 0x80000000:
if ( regs[0] > DEF_MAX_EXT )
regs[0] = DEF_MAX_EXT;
@@ -373,6 +414,7 @@ static void xc_cpuid_pv_policy(
break;
case 5: /* MONITOR/MWAIT */
case 0xa: /* Architectural Performance Monitor Features */
+ case 0xd: /* XSAVE */
case 0x8000000a: /* SVM revision and features */
case 0x8000001b: /* Instruction Based Sampling */
regs[0] = regs[1] = regs[2] = regs[3] = 0;
@@ -468,13 +510,20 @@ int xc_cpuid_apply_policy(xc_interface *xch, domid_t domid)
if ( (regs[0] & 0x1f) != 0 )
continue;
}
+
+ /* XSAVE information, subleaves 0-2. */
+ if ( (input[0] == 0xd) && (input[1]++ < 2) )
+ continue;
}
input[0]++;
- input[1] = (input[0] == 4) ? 0 : XEN_CPUID_INPUT_UNUSED;
if ( !(input[0] & 0x80000000u) && (input[0] > base_max ) )
input[0] = 0x80000000u;
+ input[1] = XEN_CPUID_INPUT_UNUSED;
+ if ( (input[0] == 4) || (input[0] == 0xd) )
+ input[1] = 0;
+
if ( (input[0] & 0x80000000u) && (input[0] > ext_max) )
break;
}