ia64/xen-unstable

changeset 17531:18727843db60

x86, hvm: Guest CPUID configuration.

CPUID's replies are now pre-calculated in libxc and given to the
hypervisor via a new domctl.

There are two parts to this feature:
- We can overwrite cpuid's replies.
- We can check that a vm is compatible with a host's processor.

Signed-off-by: Jean Guyader <jean.guyader@eu.citrix.com>
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Apr 25 13:44:45 2008 +0100 (2008-04-25)
parents 1c6008fc4d9a
children 483d006cc607
files tools/examples/xmexample.hvm tools/libxc/Makefile tools/libxc/xc_cpufeature.h tools/libxc/xc_cpuid_x86.c tools/libxc/xenctrl.h tools/python/xen/lowlevel/xc/xc.c tools/python/xen/xend/XendCheckpoint.py tools/python/xen/xend/XendConfig.py tools/python/xen/xend/image.py tools/python/xen/xm/create.py xen/arch/x86/domain.c xen/arch/x86/domctl.c xen/arch/x86/hvm/hvm.c xen/arch/x86/hvm/svm/svm.c xen/arch/x86/hvm/vmx/vmx.c xen/include/asm-x86/domain.h xen/include/public/domctl.h
line diff
     1.1 --- a/tools/examples/xmexample.hvm	Fri Apr 25 13:40:39 2008 +0100
     1.2 +++ b/tools/examples/xmexample.hvm	Fri Apr 25 13:44:45 2008 +0100
     1.3 @@ -219,3 +219,28 @@ serial='pty'
     1.4  #-----------------------------------------------------------------------------
     1.5  #   Set keyboard layout, default is en-us keyboard. 
     1.6  #keymap='ja'
     1.7 +
     1.8 +#-----------------------------------------------------------------------------
     1.9 +#   Configure guest CPUID responses:
    1.10 +#cpuid=[ '1:ecx=xxxxxxxxxxxxxxxxxxxxxxxxxx1xxxxx,
    1.11 +#           eax=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' ]
    1.12 +# - Set the VMX feature flag in the guest (CPUID_1:ECX:5)
    1.13 +# - Default behaviour for all other bits in ECX And EAX registers.
    1.14 +# 
    1.15 +# Each successive character represent a lesser-significant bit:
    1.16 +#  '1' -> force the corresponding bit to 1
    1.17 +#  '0' -> force to 0
    1.18 +#  'x' -> we don't care (default behaviour)
    1.19 +#  'k' -> pass through the host bit value
    1.20 +#  's' -> as 'k' but preserve across save/restore and migration
    1.21 +#
    1.22 +#   Configure host CPUID consistency checks, which must be satisfied for this
    1.23 +#   VM to be allowed to run on this host's processor type:
    1.24 +#cpuid_check=[ '1:ecx=xxxxxxxxxxxxxxxxxxxxxxxxxx1xxxxx' ]
    1.25 +# - Host must have VMX feature flag set
    1.26 +#
    1.27 +# The format is similar to the above for 'cpuid':
    1.28 +#  '1' -> the bit must be '1'
    1.29 +#  '0' -> the bit must be '0'
    1.30 +#  'x' -> we don't care (do not check)
    1.31 +#  's' -> the bit must be the same as on the host that started this VM
     2.1 --- a/tools/libxc/Makefile	Fri Apr 25 13:40:39 2008 +0100
     2.2 +++ b/tools/libxc/Makefile	Fri Apr 25 13:44:45 2008 +0100
     2.3 @@ -53,6 +53,7 @@ GUEST_SRCS-y                 += xc_dom_b
     2.4  GUEST_SRCS-y                 += xc_dom_compat_linux.c
     2.5  
     2.6  GUEST_SRCS-$(CONFIG_X86)     += xc_dom_x86.c
     2.7 +GUEST_SRCS-$(CONFIG_X86)     += xc_cpuid_x86.c
     2.8  GUEST_SRCS-$(CONFIG_IA64)    += xc_dom_ia64.c
     2.9  GUEST_SRCS-$(CONFIG_POWERPC) += xc_dom_powerpc.c
    2.10  endif
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/tools/libxc/xc_cpufeature.h	Fri Apr 25 13:44:45 2008 +0100
     3.3 @@ -0,0 +1,115 @@
     3.4 +#ifndef __LIBXC_CPUFEATURE_H
     3.5 +#define __LIBXC_CPUFEATURE_H
     3.6 +
     3.7 +/* Intel-defined CPU features, CPUID level 0x00000001 (edx), word 0 */
     3.8 +#define X86_FEATURE_FPU		(0*32+ 0) /* Onboard FPU */
     3.9 +#define X86_FEATURE_VME		(0*32+ 1) /* Virtual Mode Extensions */
    3.10 +#define X86_FEATURE_DE		(0*32+ 2) /* Debugging Extensions */
    3.11 +#define X86_FEATURE_PSE 	(0*32+ 3) /* Page Size Extensions */
    3.12 +#define X86_FEATURE_TSC		(0*32+ 4) /* Time Stamp Counter */
    3.13 +#define X86_FEATURE_MSR		(0*32+ 5) /* Model-Specific Registers, RDMSR, WRMSR */
    3.14 +#define X86_FEATURE_PAE		(0*32+ 6) /* Physical Address Extensions */
    3.15 +#define X86_FEATURE_MCE		(0*32+ 7) /* Machine Check Architecture */
    3.16 +#define X86_FEATURE_CX8		(0*32+ 8) /* CMPXCHG8 instruction */
    3.17 +#define X86_FEATURE_APIC	(0*32+ 9) /* Onboard APIC */
    3.18 +#define X86_FEATURE_SEP		(0*32+11) /* SYSENTER/SYSEXIT */
    3.19 +#define X86_FEATURE_MTRR	(0*32+12) /* Memory Type Range Registers */
    3.20 +#define X86_FEATURE_PGE		(0*32+13) /* Page Global Enable */
    3.21 +#define X86_FEATURE_MCA		(0*32+14) /* Machine Check Architecture */
    3.22 +#define X86_FEATURE_CMOV	(0*32+15) /* CMOV instruction (FCMOVCC and FCOMI too if FPU present) */
    3.23 +#define X86_FEATURE_PAT		(0*32+16) /* Page Attribute Table */
    3.24 +#define X86_FEATURE_PSE36	(0*32+17) /* 36-bit PSEs */
    3.25 +#define X86_FEATURE_PN		(0*32+18) /* Processor serial number */
    3.26 +#define X86_FEATURE_CLFLSH	(0*32+19) /* Supports the CLFLUSH instruction */
    3.27 +#define X86_FEATURE_DS		(0*32+21) /* Debug Store */
    3.28 +#define X86_FEATURE_ACPI	(0*32+22) /* ACPI via MSR */
    3.29 +#define X86_FEATURE_MMX		(0*32+23) /* Multimedia Extensions */
    3.30 +#define X86_FEATURE_FXSR	(0*32+24) /* FXSAVE and FXRSTOR instructions (fast save and restore */
    3.31 +				          /* of FPU context), and CR4.OSFXSR available */
    3.32 +#define X86_FEATURE_XMM		(0*32+25) /* Streaming SIMD Extensions */
    3.33 +#define X86_FEATURE_XMM2	(0*32+26) /* Streaming SIMD Extensions-2 */
    3.34 +#define X86_FEATURE_SELFSNOOP	(0*32+27) /* CPU self snoop */
    3.35 +#define X86_FEATURE_HT		(0*32+28) /* Hyper-Threading */
    3.36 +#define X86_FEATURE_ACC		(0*32+29) /* Automatic clock control */
    3.37 +#define X86_FEATURE_IA64	(0*32+30) /* IA-64 processor */
    3.38 +#define X86_FEATURE_PBE		(0*32+31) /* Pending Break Enable */
    3.39 +
    3.40 +/* AMD-defined CPU features, CPUID level 0x80000001, word 1 */
    3.41 +/* Don't duplicate feature flags which are redundant with Intel! */
    3.42 +#define X86_FEATURE_SYSCALL	(1*32+11) /* SYSCALL/SYSRET */
    3.43 +#define X86_FEATURE_MP		(1*32+19) /* MP Capable. */
    3.44 +#define X86_FEATURE_NX		(1*32+20) /* Execute Disable */
    3.45 +#define X86_FEATURE_MMXEXT	(1*32+22) /* AMD MMX extensions */
    3.46 +#define X86_FEATURE_FFXSR       (1*32+25) /* FFXSR instruction optimizations */
    3.47 +#define X86_FEATURE_PAGE1GB	(1*32+26) /* 1Gb large page support */
    3.48 +#define X86_FEATURE_RDTSCP	(1*32+27) /* RDTSCP */
    3.49 +#define X86_FEATURE_LM		(1*32+29) /* Long Mode (x86-64) */
    3.50 +#define X86_FEATURE_3DNOWEXT	(1*32+30) /* AMD 3DNow! extensions */
    3.51 +#define X86_FEATURE_3DNOW	(1*32+31) /* 3DNow! */
    3.52 +
    3.53 +/* Transmeta-defined CPU features, CPUID level 0x80860001, word 2 */
    3.54 +#define X86_FEATURE_RECOVERY	(2*32+ 0) /* CPU in recovery mode */
    3.55 +#define X86_FEATURE_LONGRUN	(2*32+ 1) /* Longrun power control */
    3.56 +#define X86_FEATURE_LRTI	(2*32+ 3) /* LongRun table interface */
    3.57 +
    3.58 +/* Other features, Linux-defined mapping, word 3 */
    3.59 +/* This range is used for feature bits which conflict or are synthesized */
    3.60 +#define X86_FEATURE_CXMMX	(3*32+ 0) /* Cyrix MMX extensions */
    3.61 +#define X86_FEATURE_K6_MTRR	(3*32+ 1) /* AMD K6 nonstandard MTRRs */
    3.62 +#define X86_FEATURE_CYRIX_ARR	(3*32+ 2) /* Cyrix ARRs (= MTRRs) */
    3.63 +#define X86_FEATURE_CENTAUR_MCR	(3*32+ 3) /* Centaur MCRs (= MTRRs) */
    3.64 +/* cpu types for specific tunings: */
    3.65 +#define X86_FEATURE_K8		(3*32+ 4) /* Opteron, Athlon64 */
    3.66 +#define X86_FEATURE_K7		(3*32+ 5) /* Athlon */
    3.67 +#define X86_FEATURE_P3		(3*32+ 6) /* P3 */
    3.68 +#define X86_FEATURE_P4		(3*32+ 7) /* P4 */
    3.69 +#define X86_FEATURE_CONSTANT_TSC (3*32+ 8) /* TSC ticks at a constant rate */
    3.70 +
    3.71 +/* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
    3.72 +#define X86_FEATURE_XMM3	(4*32+ 0) /* Streaming SIMD Extensions-3 */
    3.73 +#define X86_FEATURE_DTES64	(4*32+ 2) /* 64-bit Debug Store */
    3.74 +#define X86_FEATURE_MWAIT	(4*32+ 3) /* Monitor/Mwait support */
    3.75 +#define X86_FEATURE_DSCPL	(4*32+ 4) /* CPL Qualified Debug Store */
    3.76 +#define X86_FEATURE_VMXE	(4*32+ 5) /* Virtual Machine Extensions */
    3.77 +#define X86_FEATURE_SMXE	(4*32+ 6) /* Safer Mode Extensions */
    3.78 +#define X86_FEATURE_EST		(4*32+ 7) /* Enhanced SpeedStep */
    3.79 +#define X86_FEATURE_TM2		(4*32+ 8) /* Thermal Monitor 2 */
    3.80 +#define X86_FEATURE_SSSE3	(4*32+ 9) /* Supplemental Streaming SIMD Extensions-3 */
    3.81 +#define X86_FEATURE_CID		(4*32+10) /* Context ID */
    3.82 +#define X86_FEATURE_CX16        (4*32+13) /* CMPXCHG16B */
    3.83 +#define X86_FEATURE_XTPR	(4*32+14) /* Send Task Priority Messages */
    3.84 +#define X86_FEATURE_PDCM	(4*32+15) /* Perf/Debug Capability MSR */
    3.85 +#define X86_FEATURE_DCA		(4*32+18) /* Direct Cache Access */
    3.86 +#define X86_FEATURE_SSE4_1	(4*32+19) /* Streaming SIMD Extensions 4.1 */
    3.87 +#define X86_FEATURE_SSE4_2	(4*32+20) /* Streaming SIMD Extensions 4.2 */
    3.88 +#define X86_FEATURE_POPCNT	(4*32+23) /* POPCNT instruction */
    3.89 +
    3.90 +/* VIA/Cyrix/Centaur-defined CPU features, CPUID level 0xC0000001, word 5 */
    3.91 +#define X86_FEATURE_XSTORE	(5*32+ 2) /* on-CPU RNG present (xstore insn) */
    3.92 +#define X86_FEATURE_XSTORE_EN	(5*32+ 3) /* on-CPU RNG enabled */
    3.93 +#define X86_FEATURE_XCRYPT	(5*32+ 6) /* on-CPU crypto (xcrypt insn) */
    3.94 +#define X86_FEATURE_XCRYPT_EN	(5*32+ 7) /* on-CPU crypto enabled */
    3.95 +#define X86_FEATURE_ACE2	(5*32+ 8) /* Advanced Cryptography Engine v2 */
    3.96 +#define X86_FEATURE_ACE2_EN	(5*32+ 9) /* ACE v2 enabled */
    3.97 +#define X86_FEATURE_PHE		(5*32+ 10) /* PadLock Hash Engine */
    3.98 +#define X86_FEATURE_PHE_EN	(5*32+ 11) /* PHE enabled */
    3.99 +#define X86_FEATURE_PMM		(5*32+ 12) /* PadLock Montgomery Multiplier */
   3.100 +#define X86_FEATURE_PMM_EN	(5*32+ 13) /* PMM enabled */
   3.101 +
   3.102 +/* More extended AMD flags: CPUID level 0x80000001, ecx, word 6 */
   3.103 +#define X86_FEATURE_LAHF_LM	(6*32+ 0) /* LAHF/SAHF in long mode */
   3.104 +#define X86_FEATURE_CMP_LEGACY	(6*32+ 1) /* If yes HyperThreading not valid */
   3.105 +#define X86_FEATURE_SVME        (6*32+ 2) /* Secure Virtual Machine */
   3.106 +#define X86_FEATURE_EXTAPICSPACE (6*32+ 3) /* Extended APIC space */
   3.107 +#define X86_FEATURE_ALTMOVCR	(6*32+ 4) /* LOCK MOV CR accesses CR+8 */
   3.108 +#define X86_FEATURE_ABM		(6*32+ 5) /* Advanced Bit Manipulation */
   3.109 +#define X86_FEATURE_SSE4A	(6*32+ 6) /* AMD Streaming SIMD Extensions-4a */
   3.110 +#define X86_FEATURE_MISALIGNSSE	(6*32+ 7) /* Misaligned SSE Access */
   3.111 +#define X86_FEATURE_3DNOWPF	(6*32+ 8) /* 3DNow! Prefetch */
   3.112 +#define X86_FEATURE_OSVW	(6*32+ 9) /* OS Visible Workaround */
   3.113 +#define X86_FEATURE_IBS		(6*32+ 10) /* Instruction Based Sampling */
   3.114 +#define X86_FEATURE_SSE5	(6*32+ 11) /* AMD Streaming SIMD Extensions-5 */
   3.115 +#define X86_FEATURE_SKINIT	(6*32+ 12) /* SKINIT, STGI/CLGI, DEV */
   3.116 +#define X86_FEATURE_WDT		(6*32+ 13) /* Watchdog Timer */
   3.117 +
   3.118 +#endif /* __LIBXC_CPUFEATURE_H */
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/tools/libxc/xc_cpuid_x86.c	Fri Apr 25 13:44:45 2008 +0100
     4.3 @@ -0,0 +1,430 @@
     4.4 +/******************************************************************************
     4.5 + * xc_cpuid_x86.c 
     4.6 + *
     4.7 + * Compute cpuid of a domain.
     4.8 + *
     4.9 + * Copyright (c) 2008, Citrix Systems, Inc.
    4.10 + *
    4.11 + * This program is free software; you can redistribute it and/or modify it
    4.12 + * under the terms and conditions of the GNU General Public License,
    4.13 + * version 2, as published by the Free Software Foundation.
    4.14 + *
    4.15 + * This program is distributed in the hope it will be useful, but WITHOUT
    4.16 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    4.17 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
    4.18 + * more details.
    4.19 + *
    4.20 + * You should have received a copy of the GNU General Public License along with
    4.21 + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
    4.22 + * Place - Suite 330, Boston, MA 02111-1307 USA.
    4.23 + */
    4.24 +
    4.25 +#include <stdlib.h>
    4.26 +#include "xc_private.h"
    4.27 +#include "xc_cpufeature.h"
    4.28 +#include <xen/hvm/params.h>
    4.29 +
    4.30 +#define bitmaskof(idx)      (1u << ((idx) & 31))
    4.31 +#define clear_bit(idx, dst) ((dst) &= ~(1u << (idx)))
    4.32 +#define set_bit(idx, dst)   ((dst) |= (1u << (idx)))
    4.33 +
    4.34 +#define DEF_MAX_BASE 0x00000004u
    4.35 +#define DEF_MAX_EXT  0x80000008u
    4.36 +
    4.37 +static void amd_xc_cpuid_policy(
    4.38 +    int xc, domid_t domid, const unsigned int *input, unsigned int *regs)
    4.39 +{
    4.40 +    unsigned long pae = 0;
    4.41 +
    4.42 +    xc_get_hvm_param(xc, domid, HVM_PARAM_PAE_ENABLED, &pae);
    4.43 +
    4.44 +    switch ( input[0] )
    4.45 +    {
    4.46 +    case 0x00000001:
    4.47 +        /* Mask Intel-only features. */
    4.48 +        regs[2] &= ~(bitmaskof(X86_FEATURE_SSSE3) |
    4.49 +                     bitmaskof(X86_FEATURE_SSE4_1) |
    4.50 +                     bitmaskof(X86_FEATURE_SSE4_2));
    4.51 +        break;
    4.52 +
    4.53 +    case 0x00000002:
    4.54 +    case 0x00000004:
    4.55 +        regs[0] = regs[1] = regs[2] = 0;
    4.56 +        break;
    4.57 +
    4.58 +    case 0x80000001:
    4.59 +        if ( !pae )
    4.60 +            clear_bit(X86_FEATURE_PAE & 31, regs[3]);
    4.61 +        clear_bit(X86_FEATURE_PSE36 & 31, regs[3]);
    4.62 +
    4.63 +        /* Filter all other features according to a whitelist. */
    4.64 +        regs[2] &= (bitmaskof(X86_FEATURE_LAHF_LM) |
    4.65 +                    bitmaskof(X86_FEATURE_ALTMOVCR) |
    4.66 +                    bitmaskof(X86_FEATURE_ABM) |
    4.67 +                    bitmaskof(X86_FEATURE_SSE4A) |
    4.68 +                    bitmaskof(X86_FEATURE_MISALIGNSSE) |
    4.69 +                    bitmaskof(X86_FEATURE_3DNOWPF));
    4.70 +        regs[3] &= (0x0183f3ff | /* features shared with 0x00000001:EDX */
    4.71 +                    bitmaskof(X86_FEATURE_NX) |
    4.72 +                    bitmaskof(X86_FEATURE_LM) |
    4.73 +                    bitmaskof(X86_FEATURE_SYSCALL) |
    4.74 +                    bitmaskof(X86_FEATURE_MP) |
    4.75 +                    bitmaskof(X86_FEATURE_MMXEXT) |
    4.76 +                    bitmaskof(X86_FEATURE_FFXSR) |
    4.77 +                    bitmaskof(X86_FEATURE_3DNOW) |
    4.78 +                    bitmaskof(X86_FEATURE_3DNOWEXT));
    4.79 +        break;
    4.80 +    }
    4.81 +}
    4.82 +
    4.83 +static void intel_xc_cpuid_policy(
    4.84 +    int xc, domid_t domid, const unsigned int *input, unsigned int *regs)
    4.85 +{
    4.86 +    switch ( input[0] )
    4.87 +    {
    4.88 +    case 0x00000001:
    4.89 +        /* Mask AMD-only features. */
    4.90 +        regs[2] &= ~(bitmaskof(X86_FEATURE_POPCNT));
    4.91 +        break;
    4.92 +
    4.93 +    case 0x00000004:
    4.94 +        regs[0] &= 0x3FF;
    4.95 +        regs[3] &= 0x3FF;
    4.96 +        break;
    4.97 +
    4.98 +    case 0x80000001:
    4.99 +        /* Only a few features are advertised in Intel's 0x80000001. */
   4.100 +        regs[2] &= (bitmaskof(X86_FEATURE_LAHF_LM));
   4.101 +        regs[3] &= (bitmaskof(X86_FEATURE_NX) |
   4.102 +                    bitmaskof(X86_FEATURE_LM) |
   4.103 +                    bitmaskof(X86_FEATURE_SYSCALL));
   4.104 +        break;
   4.105 +    }
   4.106 +}
   4.107 +
   4.108 +static void cpuid(const unsigned int *input, unsigned int *regs)
   4.109 +{
   4.110 +    unsigned int count = (input[1] == XEN_CPUID_INPUT_UNUSED) ? 0 : input[1];
   4.111 +    unsigned int bx_temp;
   4.112 +    asm ( "mov %%ebx,%4; cpuid; mov %%ebx,%1; mov %4,%%ebx"
   4.113 +          : "=a" (regs[0]), "=r" (regs[1]),
   4.114 +          "=c" (regs[2]), "=d" (regs[3]), "=m" (bx_temp)
   4.115 +          : "0" (input[0]), "2" (count) );
   4.116 +}
   4.117 +
   4.118 +/* Get the manufacturer brand name of the host processor. */
   4.119 +static void xc_cpuid_brand_get(char *str)
   4.120 +{
   4.121 +    unsigned int input[2] = { 0, 0 };
   4.122 +    unsigned int regs[4];
   4.123 +
   4.124 +    cpuid(input, regs);
   4.125 +
   4.126 +    *(uint32_t *)(str + 0) = regs[1];
   4.127 +    *(uint32_t *)(str + 4) = regs[3];
   4.128 +    *(uint32_t *)(str + 8) = regs[2];
   4.129 +    str[12] = '\0';
   4.130 +}
   4.131 +
   4.132 +static void xc_cpuid_policy(
   4.133 +    int xc, domid_t domid, const unsigned int *input, unsigned int *regs)
   4.134 +{
   4.135 +    char brand[13];
   4.136 +    unsigned long pae;
   4.137 +
   4.138 +    xc_get_hvm_param(xc, domid, HVM_PARAM_PAE_ENABLED, &pae);
   4.139 +
   4.140 +    switch( input[0] )
   4.141 +    {
   4.142 +    case 0x00000000:
   4.143 +        if ( regs[0] > DEF_MAX_BASE )
   4.144 +            regs[0] = DEF_MAX_BASE;
   4.145 +        break;
   4.146 +
   4.147 +    case 0x00000001:
   4.148 +        regs[2] &= (bitmaskof(X86_FEATURE_XMM3) |
   4.149 +                    bitmaskof(X86_FEATURE_SSSE3) |
   4.150 +                    bitmaskof(X86_FEATURE_CX16) |
   4.151 +                    bitmaskof(X86_FEATURE_SSE4_1) |
   4.152 +                    bitmaskof(X86_FEATURE_SSE4_2) |
   4.153 +                    bitmaskof(X86_FEATURE_POPCNT));
   4.154 +
   4.155 +        regs[3] &= (bitmaskof(X86_FEATURE_FPU) |
   4.156 +                    bitmaskof(X86_FEATURE_VME) |
   4.157 +                    bitmaskof(X86_FEATURE_DE) |
   4.158 +                    bitmaskof(X86_FEATURE_PSE) |
   4.159 +                    bitmaskof(X86_FEATURE_TSC) |
   4.160 +                    bitmaskof(X86_FEATURE_MSR) |
   4.161 +                    bitmaskof(X86_FEATURE_PAE) |
   4.162 +                    bitmaskof(X86_FEATURE_MCE) |
   4.163 +                    bitmaskof(X86_FEATURE_CX8) |
   4.164 +                    bitmaskof(X86_FEATURE_APIC) |
   4.165 +                    bitmaskof(X86_FEATURE_SEP) |
   4.166 +                    bitmaskof(X86_FEATURE_MTRR) |
   4.167 +                    bitmaskof(X86_FEATURE_PGE) |
   4.168 +                    bitmaskof(X86_FEATURE_MCA) |
   4.169 +                    bitmaskof(X86_FEATURE_CMOV) |
   4.170 +                    bitmaskof(X86_FEATURE_PAT) |
   4.171 +                    bitmaskof(X86_FEATURE_CLFLSH) |
   4.172 +                    bitmaskof(X86_FEATURE_MMX) |
   4.173 +                    bitmaskof(X86_FEATURE_FXSR) |
   4.174 +                    bitmaskof(X86_FEATURE_XMM) |
   4.175 +                    bitmaskof(X86_FEATURE_XMM2));
   4.176 +            
   4.177 +        /* We always support MTRR MSRs. */
   4.178 +        regs[3] |= bitmaskof(X86_FEATURE_MTRR);
   4.179 +
   4.180 +        if ( !pae )
   4.181 +            clear_bit(X86_FEATURE_PAE & 31, regs[3]);
   4.182 +        break;
   4.183 +
   4.184 +    case 0x80000000:
   4.185 +        if ( regs[0] > DEF_MAX_EXT )
   4.186 +            regs[0] = DEF_MAX_EXT;
   4.187 +        break;
   4.188 +
   4.189 +    case 0x80000001:
   4.190 +        if ( !pae )
   4.191 +            clear_bit(X86_FEATURE_NX & 31, regs[3]);
   4.192 +        break;
   4.193 +
   4.194 +
   4.195 +    case 0x80000008:
   4.196 +        regs[0] &= 0x0000ffffu;
   4.197 +        regs[1] = regs[2] = regs[3] = 0;
   4.198 +        break;
   4.199 +
   4.200 +    case 0x00000002:
   4.201 +    case 0x00000004:
   4.202 +    case 0x80000002:
   4.203 +    case 0x80000003:
   4.204 +    case 0x80000004:
   4.205 +    case 0x80000006:
   4.206 +        break;
   4.207 +
   4.208 +    default:
   4.209 +        regs[0] = regs[1] = regs[2] = regs[3] = 0;
   4.210 +        break;
   4.211 +    }
   4.212 +
   4.213 +    xc_cpuid_brand_get(brand);
   4.214 +    if ( strstr(brand, "AMD") )
   4.215 +        amd_xc_cpuid_policy(xc, domid, input, regs);
   4.216 +    else
   4.217 +        intel_xc_cpuid_policy(xc, domid, input, regs);
   4.218 +}
   4.219 +
   4.220 +static int xc_cpuid_do_domctl(
   4.221 +    int xc, domid_t domid,
   4.222 +    const unsigned int *input, const unsigned int *regs)
   4.223 +{
   4.224 +    DECLARE_DOMCTL;
   4.225 +
   4.226 +    memset(&domctl, 0, sizeof (domctl));
   4.227 +    domctl.domain = domid;
   4.228 +    domctl.cmd = XEN_DOMCTL_set_cpuid;
   4.229 +    domctl.u.cpuid.input[0] = input[0];
   4.230 +    domctl.u.cpuid.input[1] = input[1];
   4.231 +    domctl.u.cpuid.eax = regs[0];
   4.232 +    domctl.u.cpuid.ebx = regs[1];
   4.233 +    domctl.u.cpuid.ecx = regs[2];
   4.234 +    domctl.u.cpuid.edx = regs[3];
   4.235 +
   4.236 +    return do_domctl(xc, &domctl);
   4.237 +}
   4.238 +
   4.239 +static char *alloc_str(void)
   4.240 +{
   4.241 +    char *s = malloc(33);
   4.242 +    memset(s, 0, 33);
   4.243 +    return s;
   4.244 +}
   4.245 +
   4.246 +void xc_cpuid_to_str(const unsigned int *regs, char **strs)
   4.247 +{
   4.248 +    int i, j;
   4.249 +
   4.250 +    for ( i = 0; i < 4; i++ )
   4.251 +    {
   4.252 +        strs[i] = alloc_str();
   4.253 +        for ( j = 0; j < 32; j++ )
   4.254 +            strs[i][j] = !!((regs[i] & (1U << (31 - j)))) ? '1' : '0';
   4.255 +    }
   4.256 +}
   4.257 +
   4.258 +int xc_cpuid_apply_policy(int xc, domid_t domid)
   4.259 +{
   4.260 +    unsigned int input[2] = { 0, 0 }, regs[4];
   4.261 +    unsigned int base_max, ext_max;
   4.262 +    int rc;
   4.263 +
   4.264 +    cpuid(input, regs);
   4.265 +    base_max = (regs[0] <= DEF_MAX_BASE) ? regs[0] : DEF_MAX_BASE;
   4.266 +    input[0] = 0x80000000;
   4.267 +    cpuid(input, regs);
   4.268 +    ext_max = (regs[0] <= DEF_MAX_EXT) ? regs[0] : DEF_MAX_EXT;
   4.269 +
   4.270 +    input[0] = 0;
   4.271 +    input[1] = XEN_CPUID_INPUT_UNUSED;
   4.272 +    for ( ; ; )
   4.273 +    {
   4.274 +        cpuid(input, regs);
   4.275 +        xc_cpuid_policy(xc, domid, input, regs);
   4.276 +
   4.277 +        if ( regs[0] || regs[1] || regs[2] || regs[3] )
   4.278 +        {
   4.279 +            rc = xc_cpuid_do_domctl(xc, domid, input, regs);
   4.280 +            if ( rc )
   4.281 +                return rc;
   4.282 +
   4.283 +            /* Intel cache descriptor leaves. */
   4.284 +            if ( input[0] == 4 )
   4.285 +            {
   4.286 +                input[1]++;
   4.287 +                /* More to do? Then loop keeping %%eax==0x00000004. */
   4.288 +                if ( (regs[0] & 0x1f) != 0 )
   4.289 +                    continue;
   4.290 +            }
   4.291 +        }
   4.292 +
   4.293 +        input[0]++;
   4.294 +        input[1] = (input[0] == 4) ? 0 : XEN_CPUID_INPUT_UNUSED;
   4.295 +        if ( !(input[0] & 0x80000000u) && (input[0] > base_max ) )
   4.296 +            input[0] = 0x80000000u;
   4.297 +
   4.298 +        if ( (input[0] & 0x80000000u) && (input[0] > ext_max) )
   4.299 +            break;
   4.300 +    }
   4.301 +
   4.302 +    return 0;
   4.303 +}
   4.304 +
   4.305 +/*
   4.306 + * Check whether a VM is allowed to launch on this host's processor type.
   4.307 + *
   4.308 + * @config format is similar to that of xc_cpuid_set():
   4.309 + *  '1' -> the bit must be set to 1
   4.310 + *  '0' -> must be 0
   4.311 + *  'x' -> we don't care
   4.312 + *  's' -> (same) must be the same
   4.313 + */
   4.314 +int xc_cpuid_check(
   4.315 +    int xc, const unsigned int *input,
   4.316 +    const char **config,
   4.317 +    char **config_transformed)
   4.318 +{
   4.319 +    int i, j;
   4.320 +    unsigned int regs[4];
   4.321 +
   4.322 +    memset(config_transformed, 0, 4 * sizeof(*config_transformed));
   4.323 +
   4.324 +    cpuid(input, regs);
   4.325 +
   4.326 +    for ( i = 0; i < 4; i++ )
   4.327 +    {
   4.328 +        if ( config[i] == NULL )
   4.329 +            continue;
   4.330 +        config_transformed[i] = alloc_str();
   4.331 +        for ( j = 0; j < 32; j++ )
   4.332 +        {
   4.333 +            unsigned char val = !!((regs[i] & (1U << (31 - j))));
   4.334 +            if ( !strchr("10xs", config[i][j]) ||
   4.335 +                 ((config[i][j] == '1') && !val) ||
   4.336 +                 ((config[i][j] == '0') && val) )
   4.337 +                goto fail;
   4.338 +            config_transformed[i][j] = config[i][j];
   4.339 +            if ( config[i][j] == 's' )
   4.340 +                config_transformed[i][j] = '0' + val;
   4.341 +        }
   4.342 +    }
   4.343 +
   4.344 +    return 0;
   4.345 +
   4.346 + fail:
   4.347 +    for ( i = 0; i < 4; i++ )
   4.348 +    {
   4.349 +        free(config_transformed[i]);
   4.350 +        config_transformed[i] = NULL;
   4.351 +    }
   4.352 +    return -EPERM;
   4.353 +}
   4.354 +
   4.355 +/*
   4.356 + * Configure a single input with the informatiom from config.
   4.357 + *
   4.358 + * Config is an array of strings:
   4.359 + *   config[0] = eax
   4.360 + *   config[1] = ebx
   4.361 + *   config[2] = ecx
   4.362 + *   config[3] = edx
   4.363 + *
   4.364 + * The format of the string is the following:
   4.365 + *   '1' -> force to 1
   4.366 + *   '0' -> force to 0
   4.367 + *   'x' -> we don't care (use default)
   4.368 + *   'k' -> pass through host value
   4.369 + *   's' -> pass through the first time and then keep the same value
   4.370 + *          across save/restore and migration.
   4.371 + * 
   4.372 + * For 's' and 'x' the configuration is overwritten with the value applied.
   4.373 + */
   4.374 +int xc_cpuid_set(
   4.375 +    int xc, domid_t domid, const unsigned int *input,
   4.376 +    const char **config, char **config_transformed)
   4.377 +{
   4.378 +    int rc;
   4.379 +    unsigned int i, j, regs[4], polregs[4];
   4.380 +
   4.381 +    memset(config_transformed, 0, 4 * sizeof(*config_transformed));
   4.382 +
   4.383 +    cpuid(input, regs);
   4.384 +
   4.385 +    memcpy(polregs, regs, sizeof(regs));
   4.386 +    xc_cpuid_policy(xc, domid, input, polregs);
   4.387 +
   4.388 +    for ( i = 0; i < 4; i++ )
   4.389 +    {
   4.390 +        if ( config[i] == NULL )
   4.391 +            continue;
   4.392 +        
   4.393 +        config_transformed[i] = alloc_str();
   4.394 +
   4.395 +        for ( j = 0; j < 32; j++ )
   4.396 +        {
   4.397 +            unsigned char val = !!((regs[i] & (1U << (31 - j))));
   4.398 +            unsigned char polval = !!((polregs[i] & (1U << (31 - j))));
   4.399 +
   4.400 +            rc = -EINVAL;
   4.401 +            if ( !strchr("10xks", config[i][j]) )
   4.402 +                goto fail;
   4.403 +
   4.404 +            if ( config[i][j] == '1' )
   4.405 +                val = 1;
   4.406 +            else if ( config[i][j] == '0' )
   4.407 +                val = 0;
   4.408 +            else if ( config[i][j] == 'x' )
   4.409 +                val = polval;
   4.410 +
   4.411 +            if ( val )
   4.412 +                set_bit(31 - j, regs[i]);
   4.413 +            else
   4.414 +                clear_bit(31 - j, regs[i]);
   4.415 +
   4.416 +            config_transformed[i][j] = config[i][j];
   4.417 +            if ( config[i][j] == 's' )
   4.418 +                config_transformed[i][j] = '0' + val;
   4.419 +        }
   4.420 +    }
   4.421 +
   4.422 +    rc = xc_cpuid_do_domctl(xc, domid, input, regs);
   4.423 +    if ( rc == 0 )
   4.424 +        return 0;
   4.425 +
   4.426 + fail:
   4.427 +    for ( i = 0; i < 4; i++ )
   4.428 +    {
   4.429 +        free(config_transformed[i]);
   4.430 +        config_transformed[i] = NULL;
   4.431 +    }
   4.432 +    return rc;
   4.433 +}
     5.1 --- a/tools/libxc/xenctrl.h	Fri Apr 25 13:40:39 2008 +0100
     5.2 +++ b/tools/libxc/xenctrl.h	Fri Apr 25 13:44:45 2008 +0100
     5.3 @@ -983,4 +983,20 @@ int xc_domain_set_target(int xc_handle,
     5.4                           uint32_t domid,
     5.5                           uint32_t target);
     5.6  
     5.7 +#if defined(__i386__) || defined(__x86_64__)
     5.8 +int xc_cpuid_check(int xc,
     5.9 +                   const unsigned int *input,
    5.10 +                   const char **config,
    5.11 +                   char **config_transformed);
    5.12 +int xc_cpuid_set(int xc,
    5.13 +                 domid_t domid,
    5.14 +                 const unsigned int *input,
    5.15 +                 const char **config,
    5.16 +                 char **config_transformed);
    5.17 +int xc_cpuid_apply_policy(int xc,
    5.18 +                          domid_t domid);
    5.19 +void xc_cpuid_to_str(const unsigned int *regs,
    5.20 +                     char **strs);
    5.21 +#endif
    5.22 +
    5.23  #endif /* XENCTRL_H */
     6.1 --- a/tools/python/xen/lowlevel/xc/xc.c	Fri Apr 25 13:40:39 2008 +0100
     6.2 +++ b/tools/python/xen/lowlevel/xc/xc.c	Fri Apr 25 13:44:45 2008 +0100
     6.3 @@ -611,6 +611,110 @@ static PyObject *pyxc_set_os_type(XcObje
     6.4  }
     6.5  #endif /* __ia64__ */
     6.6  
     6.7 +
     6.8 +#if defined(__i386__) || defined(__x86_64__)
     6.9 +static void pyxc_dom_extract_cpuid(PyObject *config,
    6.10 +                                  char **regs)
    6.11 +{
    6.12 +    const char *regs_extract[4] = { "eax", "ebx", "ecx", "edx" };
    6.13 +    PyObject *obj;
    6.14 +    int i;
    6.15 +
    6.16 +    memset(regs, 0, 4*sizeof(*regs));
    6.17 +
    6.18 +    if ( !PyDict_Check(config) )
    6.19 +        return;
    6.20 +
    6.21 +    for ( i = 0; i < 4; i++ )
    6.22 +        if ( (obj = PyDict_GetItemString(config, regs_extract[i])) != NULL )
    6.23 +            regs[i] = PyString_AS_STRING(obj);
    6.24 +}
    6.25 +
    6.26 +static PyObject *pyxc_create_cpuid_dict(char **regs)
    6.27 +{
    6.28 +   const char *regs_extract[4] = { "eax", "ebx", "ecx", "edx" };
    6.29 +   PyObject *dict;
    6.30 +   int i;
    6.31 +
    6.32 +   dict = PyDict_New();
    6.33 +   for ( i = 0; i < 4; i++ )
    6.34 +   {
    6.35 +       if ( regs[i] == NULL )
    6.36 +           continue;
    6.37 +       PyDict_SetItemString(dict, regs_extract[i],
    6.38 +                            PyString_FromString(regs[i]));
    6.39 +       free(regs[i]);
    6.40 +       regs[i] = NULL;
    6.41 +   }
    6.42 +   return dict;
    6.43 +}
    6.44 +
    6.45 +static PyObject *pyxc_dom_check_cpuid(XcObject *self,
    6.46 +                                      PyObject *args)
    6.47 +{
    6.48 +    PyObject *sub_input, *config;
    6.49 +    unsigned int input[2];
    6.50 +    char *regs[4], *regs_transform[4];
    6.51 +
    6.52 +    if ( !PyArg_ParseTuple(args, "iOO", &input[0], &sub_input, &config) )
    6.53 +        return NULL;
    6.54 +
    6.55 +    pyxc_dom_extract_cpuid(config, regs);
    6.56 +
    6.57 +    input[1] = XEN_CPUID_INPUT_UNUSED;
    6.58 +    if ( PyLong_Check(sub_input) )
    6.59 +        input[1] = PyLong_AsUnsignedLong(sub_input);
    6.60 +
    6.61 +    if ( xc_cpuid_check(self->xc_handle, input,
    6.62 +                        (const char **)regs, regs_transform) )
    6.63 +        return pyxc_error_to_exception();
    6.64 +
    6.65 +    return pyxc_create_cpuid_dict(regs_transform);
    6.66 +}
    6.67 +
    6.68 +static PyObject *pyxc_dom_set_policy_cpuid(XcObject *self,
    6.69 +                                           PyObject *args)
    6.70 +{
    6.71 +    domid_t domid;
    6.72 +
    6.73 +    if ( !PyArg_ParseTuple(args, "i", &domid) )
    6.74 +        return NULL;
    6.75 +
    6.76 +    if ( xc_cpuid_apply_policy(self->xc_handle, domid) )
    6.77 +        return pyxc_error_to_exception();
    6.78 +
    6.79 +    Py_INCREF(zero);
    6.80 +    return zero;
    6.81 +}
    6.82 +
    6.83 +
    6.84 +static PyObject *pyxc_dom_set_cpuid(XcObject *self,
    6.85 +                                    PyObject *args)
    6.86 +{
    6.87 +    domid_t domid;
    6.88 +    PyObject *sub_input, *config;
    6.89 +    unsigned int input[2];
    6.90 +    char *regs[4], *regs_transform[4];
    6.91 +
    6.92 +    if ( !PyArg_ParseTuple(args, "iiOO", &domid,
    6.93 +                           &input[0], &sub_input, &config) )
    6.94 +        return NULL;
    6.95 +
    6.96 +    pyxc_dom_extract_cpuid(config, regs);
    6.97 +
    6.98 +    input[1] = XEN_CPUID_INPUT_UNUSED;
    6.99 +    if ( PyLong_Check(sub_input) )
   6.100 +        input[1] = PyLong_AsUnsignedLong(sub_input);
   6.101 +
   6.102 +    if ( xc_cpuid_set(self->xc_handle, domid, input, (const char **)regs,
   6.103 +                      regs_transform) )
   6.104 +        return pyxc_error_to_exception();
   6.105 +
   6.106 +    return pyxc_create_cpuid_dict(regs_transform);
   6.107 +}
   6.108 +
   6.109 +#endif /* __i386__ || __x86_64__ */
   6.110 +
   6.111  static PyObject *pyxc_hvm_build(XcObject *self,
   6.112                                  PyObject *args,
   6.113                                  PyObject *kwds)
   6.114 @@ -1635,6 +1739,37 @@ static PyMethodDef pyxc_methods[] = {
   6.115        " log [int]: Specifies the area's size.\n"
   6.116        "Returns: [int] 0 on success; -1 on error.\n" },
   6.117  #endif /* __powerpc */
   6.118 +  
   6.119 +#if defined(__i386__) || defined(__x86_64__)
   6.120 +    { "domain_check_cpuid", 
   6.121 +      (PyCFunction)pyxc_dom_check_cpuid, 
   6.122 +      METH_VARARGS, "\n"
   6.123 +      "Apply checks to host CPUID.\n"
   6.124 +      " input [long]: Input for cpuid instruction (eax)\n"
   6.125 +      " sub_input [long]: Second input (optional, may be None) for cpuid "
   6.126 +      "                     instruction (ecx)\n"
   6.127 +      " config [dict]: Dictionary of register\n"
   6.128 +      " config [dict]: Dictionary of register, use for checking\n\n"
   6.129 +      "Returns: [int] 0 on success; exception on error.\n" },
   6.130 +    
   6.131 +    { "domain_set_cpuid", 
   6.132 +      (PyCFunction)pyxc_dom_set_cpuid, 
   6.133 +      METH_VARARGS, "\n"
   6.134 +      "Set cpuid response for an input and a domain.\n"
   6.135 +      " dom [int]: Identifier of domain.\n"
   6.136 +      " input [long]: Input for cpuid instruction (eax)\n"
   6.137 +      " sub_input [long]: Second input (optional, may be None) for cpuid "
   6.138 +      "                     instruction (ecx)\n"
   6.139 +      " config [dict]: Dictionary of register\n\n"
   6.140 +      "Returns: [int] 0 on success; exception on error.\n" },
   6.141 +
   6.142 +    { "domain_set_policy_cpuid", 
   6.143 +      (PyCFunction)pyxc_dom_set_policy_cpuid, 
   6.144 +      METH_VARARGS, "\n"
   6.145 +      "Set the default cpuid policy for a domain.\n"
   6.146 +      " dom [int]: Identifier of domain.\n\n"
   6.147 +      "Returns: [int] 0 on success; exception on error.\n" },
   6.148 +#endif
   6.149  
   6.150      { NULL, NULL, 0, NULL }
   6.151  };
     7.1 --- a/tools/python/xen/xend/XendCheckpoint.py	Fri Apr 25 13:40:39 2008 +0100
     7.2 +++ b/tools/python/xen/xend/XendCheckpoint.py	Fri Apr 25 13:44:45 2008 +0100
     7.3 @@ -309,6 +309,7 @@ def restore(xd, fd, dominfo = None, paus
     7.4                  else:
     7.5                      break
     7.6              os.close(qemu_fd)
     7.7 +            restore_image.setCpuid()
     7.8  
     7.9  
    7.10          os.read(fd, 1)           # Wait for source to close connection
     8.1 --- a/tools/python/xen/xend/XendConfig.py	Fri Apr 25 13:40:39 2008 +0100
     8.2 +++ b/tools/python/xen/xend/XendConfig.py	Fri Apr 25 13:44:45 2008 +0100
     8.3 @@ -203,6 +203,8 @@ XENAPI_CFG_TYPES = {
     8.4      'target': int,
     8.5      'security_label': str,
     8.6      'pci': str,
     8.7 +    'cpuid' : dict,
     8.8 +    'cpuid_check' : dict,
     8.9  }
    8.10  
    8.11  # List of legacy configuration keys that have no equivalent in the
    8.12 @@ -497,6 +499,32 @@ class XendConfig(dict):
    8.13          if 'handle' in dominfo:
    8.14              self['uuid'] = uuid.toString(dominfo['handle'])
    8.15              
    8.16 +    def parse_cpuid(self, cfg, field):
    8.17 +       def int2bin(n, count=32):
    8.18 +           return "".join([str((n >> y) & 1) for y in range(count-1, -1, -1)])
    8.19 +
    8.20 +       for input, regs in cfg[field].iteritems():
    8.21 +           if not regs is dict:
    8.22 +               cfg[field][input] = dict(regs)
    8.23 +
    8.24 +       cpuid = {}
    8.25 +       for input in cfg[field]:
    8.26 +           inputs = input.split(',')
    8.27 +           if inputs[0][0:2] == '0x':
    8.28 +               inputs[0] = str(int(inputs[0], 16))
    8.29 +           if len(inputs) == 2:
    8.30 +               if inputs[1][0:2] == '0x':
    8.31 +                   inputs[1] = str(int(inputs[1], 16))
    8.32 +           new_input = ','.join(inputs)
    8.33 +           cpuid[new_input] = {} # new input
    8.34 +           for reg in cfg[field][input]:
    8.35 +               val = cfg[field][input][reg]
    8.36 +               if val[0:2] == '0x':
    8.37 +                   cpuid[new_input][reg] = int2bin(int(val, 16))
    8.38 +               else:
    8.39 +                   cpuid[new_input][reg] = val
    8.40 +       cfg[field] = cpuid
    8.41 +
    8.42      def _parse_sxp(self, sxp_cfg):
    8.43          """ Populate this XendConfig using the parsed SXP.
    8.44  
    8.45 @@ -653,6 +681,12 @@ class XendConfig(dict):
    8.46                  except ValueError, e:
    8.47                      raise XendConfigError('cpus = %s: %s' % (cfg['cpus'], e))
    8.48  
    8.49 +        # Parse cpuid
    8.50 +        if 'cpuid' in cfg:
    8.51 +            self.parse_cpuid(cfg, 'cpuid')
    8.52 +        if 'cpuid_check' in cfg:
    8.53 +            self.parse_cpuid(cfg, 'cpuid_check')
    8.54 +
    8.55          import xen.util.xsm.xsm as security
    8.56          if security.on():
    8.57              from xen.util.acmpolicy import ACM_LABEL_UNLABELED
    8.58 @@ -901,6 +935,16 @@ class XendConfig(dict):
    8.59              int(self['vcpus_params'].get('weight', 256))
    8.60          self['vcpus_params']['cap'] = int(self['vcpus_params'].get('cap', 0))
    8.61  
    8.62 +    def cpuid_to_sxp(self, sxpr, field):
    8.63 +        regs_list = []
    8.64 +        for input, regs in self[field].iteritems():
    8.65 +            reg_list = []
    8.66 +            for reg, val in regs.iteritems():
    8.67 +                reg_list.append([reg, val])
    8.68 +            regs_list.append([input, reg_list])
    8.69 +        sxpr.append([field, regs_list])
    8.70 +
    8.71 +
    8.72      def to_sxp(self, domain = None, ignore_devices = False, ignore = [],
    8.73                 legacy_only = True):
    8.74          """ Get SXP representation of this config object.
    8.75 @@ -1012,6 +1056,13 @@ class XendConfig(dict):
    8.76                  txn.abort()
    8.77                  raise
    8.78  
    8.79 +        if 'cpuid' in self:
    8.80 +            self.cpuid_to_sxp(sxpr, 'cpuid')
    8.81 +        if 'cpuid_check' in self:
    8.82 +            self.cpuid_to_sxp(sxpr, 'cpuid_check')
    8.83 +
    8.84 +        log.debug(sxpr)
    8.85 +
    8.86          return sxpr    
    8.87      
    8.88      def _blkdev_name_to_number(self, dev):
     9.1 --- a/tools/python/xen/xend/image.py	Fri Apr 25 13:40:39 2008 +0100
     9.2 +++ b/tools/python/xen/xend/image.py	Fri Apr 25 13:44:45 2008 +0100
     9.3 @@ -551,6 +551,38 @@ class HVMImageHandler(ImageHandler):
     9.4          self.acpi = int(vmConfig['platform'].get('acpi', 0))
     9.5          self.guest_os_type = vmConfig['platform'].get('guest_os_type')
     9.6  
     9.7 +        self.vmConfig = vmConfig
     9.8 +           
     9.9 +    def setCpuid(self):
    9.10 +        xc.domain_set_policy_cpuid(self.vm.getDomid())
    9.11 +
    9.12 +        if 'cpuid' in self.vmConfig:
    9.13 +            cpuid = self.vmConfig['cpuid']
    9.14 +            transformed = {}
    9.15 +            for sinput, regs in cpuid.iteritems():
    9.16 +                inputs = sinput.split(',')
    9.17 +                input = long(inputs[0])
    9.18 +                sub_input = None
    9.19 +                if len(inputs) == 2:
    9.20 +                    sub_input = long(inputs[1])
    9.21 +                t = xc.domain_set_cpuid(self.vm.getDomid(),
    9.22 +                                        input, sub_input, regs)
    9.23 +                transformed[sinput] = t
    9.24 +            self.vmConfig['cpuid'] = transformed
    9.25 +
    9.26 +        if 'cpuid_check' in self.vmConfig:
    9.27 +            cpuid_check = self.vmConfig['cpuid_check']
    9.28 +            transformed = {}
    9.29 +            for sinput, regs_check in cpuid_check.iteritems():
    9.30 +                inputs = sinput.split(',')
    9.31 +                input = long(inputs[0])
    9.32 +                sub_input = None
    9.33 +                if len(inputs) == 2:
    9.34 +                    sub_input = long(inputs[1])
    9.35 +                t = xc.domain_check_cpuid(input, sub_input, regs_check)
    9.36 +                transformed[sinput] = t
    9.37 +            self.vmConfig['cpuid_check'] = transformed
    9.38 +
    9.39      # Return a list of cmd line args to the device models based on the
    9.40      # xm config file
    9.41      def parseDeviceModelArgs(self, vmConfig):
    9.42 @@ -718,6 +750,7 @@ class X86_HVM_ImageHandler(HVMImageHandl
    9.43  
    9.44      def buildDomain(self):
    9.45          xc.hvm_set_param(self.vm.getDomid(), HVM_PARAM_PAE_ENABLED, self.pae)
    9.46 +        self.setCpuid()
    9.47          return HVMImageHandler.buildDomain(self)
    9.48  
    9.49      def getRequiredAvailableMemory(self, mem_kb):
    10.1 --- a/tools/python/xen/xm/create.py	Fri Apr 25 13:40:39 2008 +0100
    10.2 +++ b/tools/python/xen/xm/create.py	Fri Apr 25 13:44:45 2008 +0100
    10.3 @@ -549,6 +549,14 @@ gopts.var('hap', val='HAP',
    10.4            use="""Hap status (0=hap is disabled;
    10.5            1=hap is enabled.""")
    10.6  
    10.7 +gopts.var('cpuid', val="IN[,SIN]:eax=EAX,ebx=EBX,exc=ECX,edx=EDX",
    10.8 +          fn=append_value, default=[],
    10.9 +          use="""Cpuid description.""")
   10.10 +
   10.11 +gopts.var('cpuid_check', val="IN[,SIN]:eax=EAX,ebx=EBX,exc=ECX,edx=EDX",
   10.12 +          fn=append_value, default=[],
   10.13 +          use="""Cpuid check description.""")
   10.14 +
   10.15  def err(msg):
   10.16      """Print an error to stderr and exit.
   10.17      """
   10.18 @@ -755,7 +763,7 @@ def configure_hvm(config_image, vals):
   10.19               'vnc', 'vncdisplay', 'vncunused', 'vncconsole', 'vnclisten',
   10.20               'sdl', 'display', 'xauthority', 'rtc_timeoffset', 'monitor',
   10.21               'acpi', 'apic', 'usb', 'usbdevice', 'keymap', 'pci', 'hpet',
   10.22 -             'guest_os_type', 'hap', 'opengl']
   10.23 +             'guest_os_type', 'hap', 'opengl', 'cpuid', 'cpuid_check']
   10.24  
   10.25      for a in args:
   10.26          if a in vals.__dict__ and vals.__dict__[a] is not None:
   10.27 @@ -779,7 +787,8 @@ def make_config(vals):
   10.28      map(add_conf, ['name', 'memory', 'maxmem', 'shadow_memory',
   10.29                     'restart', 'on_poweroff',
   10.30                     'on_reboot', 'on_crash', 'vcpus', 'vcpu_avail', 'features',
   10.31 -                   'on_xend_start', 'on_xend_stop', 'target'])
   10.32 +                   'on_xend_start', 'on_xend_stop', 'target', 'cpuid',
   10.33 +                   'cpuid_check'])
   10.34  
   10.35      if vals.uuid is not None:
   10.36          config.append(['uuid', vals.uuid])
   10.37 @@ -843,6 +852,24 @@ def preprocess_disk(vals):
   10.38          disk.append(d)
   10.39      vals.disk = disk
   10.40  
   10.41 +def preprocess_cpuid(vals, attr_name):
   10.42 +    if not vals.cpuid: return
   10.43 +    cpuid = {} 
   10.44 +    for cpuid_input in getattr(vals, attr_name):
   10.45 +        cpuid_match = re.match(r"(?P<input>(0x)?[0-9A-Fa-f]+):(?P<regs>.*)", cpuid_input)
   10.46 +        if cpuid_match != None:
   10.47 +            res_cpuid = cpuid_match.groupdict()
   10.48 +            input = res_cpuid['input']
   10.49 +            regs = res_cpuid['regs'].split(',')
   10.50 +            cpuid[input]= {} # New input
   10.51 +            for reg in regs:
   10.52 +                reg_match = re.match(r"(?P<reg>eax|ebx|ecx|edx)=(?P<val>.*)", reg)
   10.53 +                if reg_match == None:
   10.54 +                    err("cpuid's syntax is (eax|ebx|ecx|edx)=value")
   10.55 +                res = reg_match.groupdict()
   10.56 +                cpuid[input][res['reg']] = res['val'] # new register
   10.57 +    setattr(vals, attr_name, cpuid)
   10.58 +
   10.59  def preprocess_pci(vals):
   10.60      if not vals.pci: return
   10.61      pci = []
   10.62 @@ -1047,6 +1074,8 @@ def preprocess(vals):
   10.63      preprocess_vnc(vals)
   10.64      preprocess_vtpm(vals)
   10.65      preprocess_access_control(vals)
   10.66 +    preprocess_cpuid(vals, 'cpuid')
   10.67 +    preprocess_cpuid(vals, 'cpuid_check')
   10.68  
   10.69  
   10.70  def comma_sep_kv_to_dict(c):
    11.1 --- a/xen/arch/x86/domain.c	Fri Apr 25 13:40:39 2008 +0100
    11.2 +++ b/xen/arch/x86/domain.c	Fri Apr 25 13:44:45 2008 +0100
    11.3 @@ -440,10 +440,9 @@ int arch_domain_create(struct domain *d,
    11.4  {
    11.5  #ifdef __x86_64__
    11.6      struct page_info *pg;
    11.7 -    int i;
    11.8  #endif
    11.9      l1_pgentry_t gdt_l1e;
   11.10 -    int vcpuid, pdpt_order, paging_initialised = 0;
   11.11 +    int i, vcpuid, pdpt_order, paging_initialised = 0;
   11.12      int rc = -ENOMEM;
   11.13  
   11.14      d->arch.hvm_domain.hap_enabled =
   11.15 @@ -541,6 +540,13 @@ int arch_domain_create(struct domain *d,
   11.16              (CONFIG_PAGING_LEVELS != 4);
   11.17      }
   11.18  
   11.19 +    memset(d->arch.cpuids, 0, sizeof(d->arch.cpuids));
   11.20 +    for ( i = 0; i < MAX_CPUID_INPUT; i++ )
   11.21 +    {
   11.22 +        d->arch.cpuids[i].input[0] = XEN_CPUID_INPUT_UNUSED;
   11.23 +        d->arch.cpuids[i].input[1] = XEN_CPUID_INPUT_UNUSED;
   11.24 +    }
   11.25 +
   11.26      return 0;
   11.27  
   11.28   fail:
   11.29 @@ -1910,6 +1916,37 @@ void arch_dump_vcpu_info(struct vcpu *v)
   11.30      paging_dump_vcpu_info(v);
   11.31  }
   11.32  
   11.33 +void domain_cpuid(
   11.34 +    struct domain *d,
   11.35 +    unsigned int  input,
   11.36 +    unsigned int  sub_input,
   11.37 +    unsigned int  *eax,
   11.38 +    unsigned int  *ebx,
   11.39 +    unsigned int  *ecx,
   11.40 +    unsigned int  *edx)
   11.41 +{
   11.42 +    cpuid_input_t *cpuid;
   11.43 +    int i;
   11.44 +
   11.45 +    for ( i = 0; i < MAX_CPUID_INPUT; i++ )
   11.46 +    {
   11.47 +        cpuid = &d->arch.cpuids[i];
   11.48 +
   11.49 +        if ( (cpuid->input[0] == input) &&
   11.50 +             ((cpuid->input[1] == XEN_CPUID_INPUT_UNUSED) ||
   11.51 +              (cpuid->input[1] == sub_input)) )
   11.52 +        {
   11.53 +            *eax = cpuid->eax;
   11.54 +            *ebx = cpuid->ebx;
   11.55 +            *ecx = cpuid->ecx;
   11.56 +            *edx = cpuid->edx;
   11.57 +            return;
   11.58 +        }
   11.59 +    }
   11.60 +
   11.61 +    *eax = *ebx = *ecx = *edx = 0;
   11.62 +}
   11.63 +
   11.64  /*
   11.65   * Local variables:
   11.66   * mode: C
    12.1 --- a/xen/arch/x86/domctl.c	Fri Apr 25 13:40:39 2008 +0100
    12.2 +++ b/xen/arch/x86/domctl.c	Fri Apr 25 13:44:45 2008 +0100
    12.3 @@ -842,6 +842,45 @@ long arch_do_domctl(
    12.4      }
    12.5      break;
    12.6  
    12.7 +    case XEN_DOMCTL_set_cpuid:
    12.8 +    {
    12.9 +        struct domain *d;
   12.10 +        xen_domctl_cpuid_t *ctl = &domctl->u.cpuid;
   12.11 +        cpuid_input_t *cpuid = NULL; 
   12.12 +        int i;
   12.13 +
   12.14 +        ret = -ESRCH;
   12.15 +        d = rcu_lock_domain_by_id(domctl->domain);
   12.16 +        if ( d == NULL )
   12.17 +            break;
   12.18 +
   12.19 +        for ( i = 0; i < MAX_CPUID_INPUT; i++ )
   12.20 +        {
   12.21 +            cpuid = &d->arch.cpuids[i];
   12.22 +
   12.23 +            if ( cpuid->input[0] == XEN_CPUID_INPUT_UNUSED )
   12.24 +                break;
   12.25 +
   12.26 +            if ( (cpuid->input[0] == ctl->input[0]) &&
   12.27 +                 ((cpuid->input[1] == XEN_CPUID_INPUT_UNUSED) ||
   12.28 +                  (cpuid->input[1] == ctl->input[1])) )
   12.29 +                break;
   12.30 +        }
   12.31 +        
   12.32 +        if ( i == MAX_CPUID_INPUT )
   12.33 +        {
   12.34 +            ret = -ENOENT;
   12.35 +        }
   12.36 +        else
   12.37 +        {
   12.38 +            memcpy(cpuid, ctl, sizeof(cpuid_input_t));
   12.39 +            ret = 0;
   12.40 +        }
   12.41 +
   12.42 +        rcu_unlock_domain(d);
   12.43 +    }
   12.44 +    break;
   12.45 +
   12.46      default:
   12.47          ret = -ENOSYS;
   12.48          break;
    13.1 --- a/xen/arch/x86/hvm/hvm.c	Fri Apr 25 13:40:39 2008 +0100
    13.2 +++ b/xen/arch/x86/hvm/hvm.c	Fri Apr 25 13:44:45 2008 +0100
    13.3 @@ -1594,66 +1594,15 @@ void hvm_cpuid(unsigned int input, unsig
    13.4      if ( cpuid_hypervisor_leaves(input, eax, ebx, ecx, edx) )
    13.5          return;
    13.6  
    13.7 -    cpuid(input, eax, ebx, ecx, edx);
    13.8 -
    13.9 -    switch ( input )
   13.10 -    {
   13.11 -    case 0x00000001:
   13.12 -        /* Clear #threads count and poke initial VLAPIC ID. */
   13.13 -        *ebx &= 0x0000FFFFu;
   13.14 -        *ebx |= (current->vcpu_id * 2) << 24;
   13.15 -
   13.16 -        /* We always support MTRR MSRs. */
   13.17 -        *edx |= bitmaskof(X86_FEATURE_MTRR);
   13.18 -
   13.19 -        *ecx &= (bitmaskof(X86_FEATURE_XMM3) |
   13.20 -                 bitmaskof(X86_FEATURE_SSSE3) |
   13.21 -                 bitmaskof(X86_FEATURE_CX16) |
   13.22 -                 bitmaskof(X86_FEATURE_SSE4_1) |
   13.23 -                 bitmaskof(X86_FEATURE_SSE4_2) |
   13.24 -                 bitmaskof(X86_FEATURE_POPCNT));
   13.25 +    domain_cpuid(v->domain, input, *ecx, eax, ebx, ecx, edx);
   13.26  
   13.27 -        *edx &= (bitmaskof(X86_FEATURE_FPU) |
   13.28 -                 bitmaskof(X86_FEATURE_VME) |
   13.29 -                 bitmaskof(X86_FEATURE_DE) |
   13.30 -                 bitmaskof(X86_FEATURE_PSE) |
   13.31 -                 bitmaskof(X86_FEATURE_TSC) |
   13.32 -                 bitmaskof(X86_FEATURE_MSR) |
   13.33 -                 bitmaskof(X86_FEATURE_PAE) |
   13.34 -                 bitmaskof(X86_FEATURE_MCE) |
   13.35 -                 bitmaskof(X86_FEATURE_CX8) |
   13.36 -                 bitmaskof(X86_FEATURE_APIC) |
   13.37 -                 bitmaskof(X86_FEATURE_SEP) |
   13.38 -                 bitmaskof(X86_FEATURE_MTRR) |
   13.39 -                 bitmaskof(X86_FEATURE_PGE) |
   13.40 -                 bitmaskof(X86_FEATURE_MCA) |
   13.41 -                 bitmaskof(X86_FEATURE_CMOV) |
   13.42 -                 bitmaskof(X86_FEATURE_PAT) |
   13.43 -                 bitmaskof(X86_FEATURE_CLFLSH) |
   13.44 -                 bitmaskof(X86_FEATURE_MMX) |
   13.45 -                 bitmaskof(X86_FEATURE_FXSR) |
   13.46 -                 bitmaskof(X86_FEATURE_XMM) |
   13.47 -                 bitmaskof(X86_FEATURE_XMM2));
   13.48 +    if ( input == 0x00000001 )
   13.49 +    {
   13.50 +        /* Fix up VLAPIC details. */
   13.51 +        *ebx &= 0x00FFFFFFu;
   13.52 +        *ebx |= (v->vcpu_id * 2) << 24;
   13.53          if ( vlapic_hw_disabled(vcpu_vlapic(v)) )
   13.54 -            __clear_bit(X86_FEATURE_APIC & 31, edx);
   13.55 -#if CONFIG_PAGING_LEVELS >= 3
   13.56 -        if ( !v->domain->arch.hvm_domain.params[HVM_PARAM_PAE_ENABLED] )
   13.57 -#endif
   13.58 -            __clear_bit(X86_FEATURE_PAE & 31, edx);
   13.59 -        break;
   13.60 -
   13.61 -    case 0x80000001:
   13.62 -#if CONFIG_PAGING_LEVELS >= 3
   13.63 -        if ( !v->domain->arch.hvm_domain.params[HVM_PARAM_PAE_ENABLED] )
   13.64 -#endif
   13.65 -            __clear_bit(X86_FEATURE_NX & 31, edx);
   13.66 -#ifdef __i386__
   13.67 -        /* Mask feature for Intel ia32e or AMD long mode. */
   13.68 -        __clear_bit(X86_FEATURE_LAHF_LM & 31, ecx);
   13.69 -        __clear_bit(X86_FEATURE_LM & 31, edx);
   13.70 -        __clear_bit(X86_FEATURE_SYSCALL & 31, edx);
   13.71 -#endif
   13.72 -        break;
   13.73 +            __clear_bit(X86_FEATURE_APIC & 31, ebx);
   13.74      }
   13.75  }
   13.76  
   13.77 @@ -1663,11 +1612,15 @@ int hvm_msr_read_intercept(struct cpu_us
   13.78      uint64_t msr_content = 0;
   13.79      struct vcpu *v = current;
   13.80      uint64_t *var_range_base, *fixed_range_base;
   13.81 -    int index;
   13.82 +    int index, mtrr;
   13.83 +    uint32_t cpuid[4];
   13.84  
   13.85      var_range_base = (uint64_t *)v->arch.hvm_vcpu.mtrr.var_ranges;
   13.86      fixed_range_base = (uint64_t *)v->arch.hvm_vcpu.mtrr.fixed_ranges;
   13.87  
   13.88 +    hvm_cpuid(1, &cpuid[0], &cpuid[1], &cpuid[2], &cpuid[3]);
   13.89 +    mtrr = !!(cpuid[3] & bitmaskof(X86_FEATURE_MTRR));
   13.90 +
   13.91      switch ( ecx )
   13.92      {
   13.93      case MSR_IA32_TSC:
   13.94 @@ -1695,25 +1648,37 @@ int hvm_msr_read_intercept(struct cpu_us
   13.95          break;
   13.96  
   13.97      case MSR_MTRRcap:
   13.98 +        if ( !mtrr )
   13.99 +            goto gp_fault;
  13.100          msr_content = v->arch.hvm_vcpu.mtrr.mtrr_cap;
  13.101          break;
  13.102      case MSR_MTRRdefType:
  13.103 +        if ( !mtrr )
  13.104 +            goto gp_fault;
  13.105          msr_content = v->arch.hvm_vcpu.mtrr.def_type
  13.106                          | (v->arch.hvm_vcpu.mtrr.enabled << 10);
  13.107          break;
  13.108      case MSR_MTRRfix64K_00000:
  13.109 +        if ( !mtrr )
  13.110 +            goto gp_fault;
  13.111          msr_content = fixed_range_base[0];
  13.112          break;
  13.113      case MSR_MTRRfix16K_80000:
  13.114      case MSR_MTRRfix16K_A0000:
  13.115 +        if ( !mtrr )
  13.116 +            goto gp_fault;
  13.117          index = regs->ecx - MSR_MTRRfix16K_80000;
  13.118          msr_content = fixed_range_base[index + 1];
  13.119          break;
  13.120      case MSR_MTRRfix4K_C0000...MSR_MTRRfix4K_F8000:
  13.121 +        if ( !mtrr )
  13.122 +            goto gp_fault;
  13.123          index = regs->ecx - MSR_MTRRfix4K_C0000;
  13.124          msr_content = fixed_range_base[index + 3];
  13.125          break;
  13.126      case MSR_IA32_MTRR_PHYSBASE0...MSR_IA32_MTRR_PHYSMASK7:
  13.127 +        if ( !mtrr )
  13.128 +            goto gp_fault;
  13.129          index = regs->ecx - MSR_IA32_MTRR_PHYSBASE0;
  13.130          msr_content = var_range_base[index];
  13.131          break;
  13.132 @@ -1725,6 +1690,10 @@ int hvm_msr_read_intercept(struct cpu_us
  13.133      regs->eax = (uint32_t)msr_content;
  13.134      regs->edx = (uint32_t)(msr_content >> 32);
  13.135      return X86EMUL_OKAY;
  13.136 +
  13.137 +gp_fault:
  13.138 +    hvm_inject_exception(TRAP_gp_fault, 0, 0);
  13.139 +    return X86EMUL_EXCEPTION;
  13.140  }
  13.141  
  13.142  int hvm_msr_write_intercept(struct cpu_user_regs *regs)
  13.143 @@ -1739,7 +1708,11 @@ int hvm_msr_write_intercept(struct cpu_u
  13.144      uint32_t ecx = regs->ecx;
  13.145      uint64_t msr_content = (uint32_t)regs->eax | ((uint64_t)regs->edx << 32);
  13.146      struct vcpu *v = current;
  13.147 -    int index;
  13.148 +    int index, mtrr;
  13.149 +    uint32_t cpuid[4];
  13.150 +
  13.151 +    hvm_cpuid(1, &cpuid[0], &cpuid[1], &cpuid[2], &cpuid[3]);
  13.152 +    mtrr = !!(cpuid[3] & bitmaskof(X86_FEATURE_MTRR));
  13.153  
  13.154      switch ( ecx )
  13.155      {
  13.156 @@ -1758,29 +1731,41 @@ int hvm_msr_write_intercept(struct cpu_u
  13.157          break;
  13.158  
  13.159      case MSR_MTRRcap:
  13.160 +        if ( !mtrr )
  13.161 +            goto gp_fault;
  13.162          goto gp_fault;
  13.163      case MSR_MTRRdefType:
  13.164 +        if ( !mtrr )
  13.165 +            goto gp_fault;
  13.166          if ( !mtrr_def_type_msr_set(&v->arch.hvm_vcpu.mtrr, msr_content) )
  13.167             goto gp_fault;
  13.168          break;
  13.169      case MSR_MTRRfix64K_00000:
  13.170 +        if ( !mtrr )
  13.171 +            goto gp_fault;
  13.172          if ( !mtrr_fix_range_msr_set(&v->arch.hvm_vcpu.mtrr, 0, msr_content) )
  13.173              goto gp_fault;
  13.174          break;
  13.175      case MSR_MTRRfix16K_80000:
  13.176      case MSR_MTRRfix16K_A0000:
  13.177 +        if ( !mtrr )
  13.178 +            goto gp_fault;
  13.179          index = regs->ecx - MSR_MTRRfix16K_80000 + 1;
  13.180          if ( !mtrr_fix_range_msr_set(&v->arch.hvm_vcpu.mtrr,
  13.181                                       index, msr_content) )
  13.182              goto gp_fault;
  13.183          break;
  13.184      case MSR_MTRRfix4K_C0000...MSR_MTRRfix4K_F8000:
  13.185 +        if ( !mtrr )
  13.186 +            goto gp_fault;
  13.187          index = regs->ecx - MSR_MTRRfix4K_C0000 + 3;
  13.188          if ( !mtrr_fix_range_msr_set(&v->arch.hvm_vcpu.mtrr,
  13.189                                       index, msr_content) )
  13.190              goto gp_fault;
  13.191          break;
  13.192      case MSR_IA32_MTRR_PHYSBASE0...MSR_IA32_MTRR_PHYSMASK7:
  13.193 +        if ( !mtrr )
  13.194 +            goto gp_fault;
  13.195          if ( !mtrr_var_range_msr_set(&v->arch.hvm_vcpu.mtrr,
  13.196                                       regs->ecx, msr_content) )
  13.197              goto gp_fault;
    14.1 --- a/xen/arch/x86/hvm/svm/svm.c	Fri Apr 25 13:40:39 2008 +0100
    14.2 +++ b/xen/arch/x86/hvm/svm/svm.c	Fri Apr 25 13:44:45 2008 +0100
    14.3 @@ -892,56 +892,11 @@ static void svm_cpuid_intercept(
    14.4  
    14.5      hvm_cpuid(input, eax, ebx, ecx, edx);
    14.6  
    14.7 -    switch ( input )
    14.8 +    if ( input == 0x80000001 )
    14.9      {
   14.10 -    case 0x00000001:
   14.11 -        /* Mask Intel-only features. */
   14.12 -        *ecx &= ~(bitmaskof(X86_FEATURE_SSSE3) |
   14.13 -                  bitmaskof(X86_FEATURE_SSE4_1) |
   14.14 -                  bitmaskof(X86_FEATURE_SSE4_2));
   14.15 -        break;
   14.16 -
   14.17 -    case 0x80000001:
   14.18 -        /* Filter features which are shared with 0x00000001:EDX. */
   14.19 +        /* Fix up VLAPIC details. */
   14.20          if ( vlapic_hw_disabled(vcpu_vlapic(v)) )
   14.21              __clear_bit(X86_FEATURE_APIC & 31, edx);
   14.22 -#if CONFIG_PAGING_LEVELS >= 3
   14.23 -        if ( !v->domain->arch.hvm_domain.params[HVM_PARAM_PAE_ENABLED] )
   14.24 -#endif
   14.25 -            __clear_bit(X86_FEATURE_PAE & 31, edx);
   14.26 -        __clear_bit(X86_FEATURE_PSE36 & 31, edx);
   14.27 -
   14.28 -        /* We always support MTRR MSRs. */
   14.29 -        *edx |= bitmaskof(X86_FEATURE_MTRR);
   14.30 -
   14.31 -        /* Filter all other features according to a whitelist. */
   14.32 -        *ecx &= (bitmaskof(X86_FEATURE_LAHF_LM) |
   14.33 -                 bitmaskof(X86_FEATURE_ALTMOVCR) |
   14.34 -                 bitmaskof(X86_FEATURE_ABM) |
   14.35 -                 bitmaskof(X86_FEATURE_SSE4A) |
   14.36 -                 bitmaskof(X86_FEATURE_MISALIGNSSE) |
   14.37 -                 bitmaskof(X86_FEATURE_3DNOWPF));
   14.38 -        *edx &= (0x0183f3ff | /* features shared with 0x00000001:EDX */
   14.39 -                 bitmaskof(X86_FEATURE_NX) |
   14.40 -                 bitmaskof(X86_FEATURE_LM) |
   14.41 -                 bitmaskof(X86_FEATURE_SYSCALL) |
   14.42 -                 bitmaskof(X86_FEATURE_MP) |
   14.43 -                 bitmaskof(X86_FEATURE_MMXEXT) |
   14.44 -                 bitmaskof(X86_FEATURE_FFXSR) |
   14.45 -                 bitmaskof(X86_FEATURE_3DNOW) |
   14.46 -                 bitmaskof(X86_FEATURE_3DNOWEXT));
   14.47 -        break;
   14.48 -
   14.49 -    case 0x80000007:
   14.50 -    case 0x8000000A:
   14.51 -        /* Mask out features of power management and SVM extension. */
   14.52 -        *eax = *ebx = *ecx = *edx = 0;
   14.53 -        break;
   14.54 -
   14.55 -    case 0x80000008:
   14.56 -        /* Make sure Number of CPU core is 1 when HTT=0 */
   14.57 -        *ecx &= 0xFFFFFF00;
   14.58 -        break;
   14.59      }
   14.60  
   14.61      HVMTRACE_3D(CPUID, v, input,
    15.1 --- a/xen/arch/x86/hvm/vmx/vmx.c	Fri Apr 25 13:40:39 2008 +0100
    15.2 +++ b/xen/arch/x86/hvm/vmx/vmx.c	Fri Apr 25 13:44:45 2008 +0100
    15.3 @@ -1311,34 +1311,21 @@ static void vmx_cpuid_intercept(
    15.4      unsigned int *ecx, unsigned int *edx)
    15.5  {
    15.6      unsigned int input = *eax;
    15.7 -    unsigned int count = *ecx;
    15.8 +    struct segment_register cs;
    15.9 +    struct vcpu *v = current;
   15.10  
   15.11      hvm_cpuid(input, eax, ebx, ecx, edx);
   15.12  
   15.13      switch ( input )
   15.14      {
   15.15 -    case 0x00000001:
   15.16 -        /* Mask AMD-only features. */
   15.17 -        *ecx &= ~(bitmaskof(X86_FEATURE_POPCNT));
   15.18 -        break;
   15.19 -
   15.20 -    case 0x00000004:
   15.21 -        cpuid_count(input, count, eax, ebx, ecx, edx);
   15.22 -        *eax &= 0x3FFF; /* one core */
   15.23 -        break;
   15.24 -
   15.25 -    case 0x00000006:
   15.26 -    case 0x00000009:
   15.27 -        *eax = *ebx = *ecx = *edx = 0;
   15.28 -        break;
   15.29 -
   15.30 -    case 0x80000001:
   15.31 -        /* Only a few features are advertised in Intel's 0x80000001. */
   15.32 -        *ecx &= (bitmaskof(X86_FEATURE_LAHF_LM));
   15.33 -        *edx &= (bitmaskof(X86_FEATURE_NX) |
   15.34 -                 bitmaskof(X86_FEATURE_LM) |
   15.35 -                 bitmaskof(X86_FEATURE_SYSCALL));
   15.36 -        break;
   15.37 +        case 0x80000001:
   15.38 +            /* SYSCALL is visible iff running in long mode. */
   15.39 +            hvm_get_segment_register(v, x86_seg_cs, &cs);
   15.40 +            if ( cs.attr.fields.l )
   15.41 +                *edx |= bitmaskof(X86_FEATURE_SYSCALL);
   15.42 +            else
   15.43 +                *edx &= ~(bitmaskof(X86_FEATURE_SYSCALL));
   15.44 +            break;
   15.45      }
   15.46  
   15.47      HVMTRACE_3D(CPUID, current, input,
    16.1 --- a/xen/include/asm-x86/domain.h	Fri Apr 25 13:40:39 2008 +0100
    16.2 +++ b/xen/include/asm-x86/domain.h	Fri Apr 25 13:44:45 2008 +0100
    16.3 @@ -187,6 +187,9 @@ struct paging_vcpu {
    16.4      struct shadow_vcpu shadow;
    16.5  };
    16.6  
    16.7 +#define MAX_CPUID_INPUT 40
    16.8 +typedef xen_domctl_cpuid_t cpuid_input_t;
    16.9 +
   16.10  struct p2m_domain;
   16.11  
   16.12  struct arch_domain
   16.13 @@ -243,6 +246,8 @@ struct arch_domain
   16.14          RELMEM_done,
   16.15      } relmem;
   16.16      struct list_head relmem_list;
   16.17 +
   16.18 +    cpuid_input_t cpuids[MAX_CPUID_INPUT];
   16.19  } __cacheline_aligned;
   16.20  
   16.21  #ifdef CONFIG_X86_PAE
   16.22 @@ -353,6 +358,14 @@ unsigned long pv_guest_cr4_fixup(unsigne
   16.23  #define real_cr4_to_pv_guest_cr4(c) \
   16.24      ((c) & ~(X86_CR4_PGE | X86_CR4_PSE))
   16.25  
   16.26 +void domain_cpuid(struct domain *d,
   16.27 +                  unsigned int  input,
   16.28 +                  unsigned int  sub_input,
   16.29 +                  unsigned int  *eax,
   16.30 +                  unsigned int  *ebx,
   16.31 +                  unsigned int  *ecx,
   16.32 +                  unsigned int  *edx);
   16.33 +
   16.34  #endif /* __ASM_DOMAIN_H__ */
   16.35  
   16.36  /*
    17.1 --- a/xen/include/public/domctl.h	Fri Apr 25 13:40:39 2008 +0100
    17.2 +++ b/xen/include/public/domctl.h	Fri Apr 25 13:44:45 2008 +0100
    17.3 @@ -571,6 +571,19 @@ struct xen_domctl_set_target {
    17.4  typedef struct xen_domctl_set_target xen_domctl_set_target_t;
    17.5  DEFINE_XEN_GUEST_HANDLE(xen_domctl_set_target_t);
    17.6  
    17.7 +#if defined(__i386__) || defined(__x86_64__)
    17.8 +# define XEN_CPUID_INPUT_UNUSED  0xFFFFFFFF
    17.9 +# define XEN_DOMCTL_set_cpuid 49
   17.10 +struct xen_domctl_cpuid {
   17.11 +  unsigned int  input[2];
   17.12 +  unsigned int  eax;
   17.13 +  unsigned int  ebx;
   17.14 +  unsigned int  ecx;
   17.15 +  unsigned int  edx;
   17.16 +};
   17.17 +typedef struct xen_domctl_cpuid xen_domctl_cpuid_t;
   17.18 +DEFINE_XEN_GUEST_HANDLE(xen_domctl_cpuid_t);
   17.19 +#endif
   17.20  
   17.21  struct xen_domctl {
   17.22      uint32_t cmd;
   17.23 @@ -609,6 +622,9 @@ struct xen_domctl {
   17.24          struct xen_domctl_ext_vcpucontext   ext_vcpucontext;
   17.25          struct xen_domctl_set_opt_feature   set_opt_feature;
   17.26          struct xen_domctl_set_target        set_target;
   17.27 +#if defined(__i386__) || defined(__x86_64__)
   17.28 +        struct xen_domctl_cpuid             cpuid;
   17.29 +#endif
   17.30          uint8_t                             pad[128];
   17.31      } u;
   17.32  };