debuggers.hg
changeset 17562: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>
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 };