aboutsummaryrefslogtreecommitdiffstats
path: root/target-i386/kvm.c
diff options
context:
space:
mode:
authorAndre Przywara <andre.przywara@amd.com>2009-06-25 00:08:02 +0200
committerAnthony Liguori <aliguori@us.ibm.com>2009-06-29 13:52:11 -0500
commit6c1f42fe83bf9bc14a7a6cc5afd8dad83ee25c74 (patch)
treeb3b04d592bf6d1e5428f58edae5a4a718479aa5c /target-i386/kvm.c
parentf441bee871fa251d73cfcd63120f1dc76314b289 (diff)
fix KVMs GET_SUPPORTED_CPUID feature usage
If we want to trim the user provided CPUID bits for KVM to be not greater than that of the host, we should not remove the bits _after_ we sent them to the kernel. This fixes the masking of features that are not present on the host by moving the trim function and it's call from helper.c to kvm.c. It helps to use -cpu host. Signed-off-by: Andre Przywara <andre.przywara@amd.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Diffstat (limited to 'target-i386/kvm.c')
-rw-r--r--target-i386/kvm.c22
1 files changed, 22 insertions, 0 deletions
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index c4fd4848c..70a9b4558 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -117,6 +117,19 @@ uint32_t kvm_arch_get_supported_cpuid(CPUState *env, uint32_t function, int reg)
#endif
+static void kvm_trim_features(uint32_t *features, uint32_t supported)
+{
+ int i;
+ uint32_t mask;
+
+ for (i = 0; i < 32; ++i) {
+ mask = 1U << i;
+ if ((*features & mask) && !(supported & mask)) {
+ *features &= ~mask;
+ }
+ }
+}
+
int kvm_arch_init_vcpu(CPUState *env)
{
struct {
@@ -128,6 +141,15 @@ int kvm_arch_init_vcpu(CPUState *env)
env->mp_state = KVM_MP_STATE_RUNNABLE;
+ kvm_trim_features(&env->cpuid_features,
+ kvm_arch_get_supported_cpuid(env, 1, R_EDX));
+ kvm_trim_features(&env->cpuid_ext_features,
+ kvm_arch_get_supported_cpuid(env, 1, R_ECX));
+ kvm_trim_features(&env->cpuid_ext2_features,
+ kvm_arch_get_supported_cpuid(env, 0x80000001, R_EDX));
+ kvm_trim_features(&env->cpuid_ext3_features,
+ kvm_arch_get_supported_cpuid(env, 0x80000001, R_ECX));
+
cpuid_i = 0;
cpu_x86_cpuid(env, 0, 0, &limit, &unused, &unused, &unused);