From 7b46e5ce81d5107927685e7645b1bd39a1e1cd63 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Thu, 4 Oct 2012 17:48:53 -0300 Subject: [PATCH 01/28] i386: kvm: kvm_arch_get_supported_cpuid: move R_EDX hack outside of for loop The for loop will become a separate function, so clean it up so it can become independent from the bit hacking for R_EDX. No behavior change[1], just code movement. [1] Well, only if the kernel returned CPUID leafs 1 or 0x80000001 as unsupported, but there's no kernel version that does that. Signed-off-by: Eduardo Habkost Signed-off-by: Marcelo Tosatti --- target-i386/kvm.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 3aa62b20ff..b7490f92d9 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -155,24 +155,29 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, break; case R_EDX: ret = cpuid->entries[i].edx; - switch (function) { - case 1: - /* KVM before 2.6.30 misreports the following features */ - ret |= CPUID_MTRR | CPUID_PAT | CPUID_MCE | CPUID_MCA; - break; - case 0x80000001: - /* On Intel, kvm returns cpuid according to the Intel spec, - * so add missing bits according to the AMD spec: - */ - cpuid_1_edx = kvm_arch_get_supported_cpuid(s, 1, 0, R_EDX); - ret |= cpuid_1_edx & CPUID_EXT2_AMD_ALIASES; - break; - } break; } } } + /* Fixups for the data returned by KVM, below */ + + if (reg == R_EDX) { + switch (function) { + case 1: + /* KVM before 2.6.30 misreports the following features */ + ret |= CPUID_MTRR | CPUID_PAT | CPUID_MCE | CPUID_MCA; + break; + case 0x80000001: + /* On Intel, kvm returns cpuid according to the Intel spec, + * so add missing bits according to the AMD spec: + */ + cpuid_1_edx = kvm_arch_get_supported_cpuid(s, 1, 0, R_EDX); + ret |= cpuid_1_edx & CPUID_EXT2_AMD_ALIASES; + break; + } + } + g_free(cpuid); /* fallback for older kernels */ From 8c723b7958127b8f204dd4b278ad3c8f6f48ae17 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Thu, 4 Oct 2012 17:48:54 -0300 Subject: [PATCH 02/28] i386: kvm: kvm_arch_get_supported_cpuid: clean up has_kvm_features check Instead of a function-specific has_kvm_features variable, simply use a "found" variable that will be checked in case we have to use the legacy get_para_features() interface. No behavior change, just code cleanup. Signed-off-by: Eduardo Habkost Signed-off-by: Marcelo Tosatti --- target-i386/kvm.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/target-i386/kvm.c b/target-i386/kvm.c index b7490f92d9..56addf1866 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -130,7 +130,7 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, int i, max; uint32_t ret = 0; uint32_t cpuid_1_edx; - int has_kvm_features = 0; + bool found = false; max = 1; while ((cpuid = try_get_cpuid(s, max)) == NULL) { @@ -140,9 +140,7 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, for (i = 0; i < cpuid->nent; ++i) { if (cpuid->entries[i].function == function && cpuid->entries[i].index == index) { - if (cpuid->entries[i].function == KVM_CPUID_FEATURES) { - has_kvm_features = 1; - } + found = true; switch (reg) { case R_EAX: ret = cpuid->entries[i].eax; @@ -181,7 +179,7 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, g_free(cpuid); /* fallback for older kernels */ - if (!has_kvm_features && (function == KVM_CPUID_FEATURES)) { + if ((function == KVM_CPUID_FEATURES) && !found) { ret = get_para_features(s); } From 47111e2cfa1a83a99ac10ed19c7c8b02be4fe973 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Thu, 4 Oct 2012 17:48:55 -0300 Subject: [PATCH 03/28] i386: kvm: kvm_arch_get_supported_cpuid: use 'entry' variable The reg switch will be moved to a separate function, so store the entry pointer in a variable. No behavior change, just code movement. Signed-off-by: Eduardo Habkost Signed-off-by: Marcelo Tosatti --- target-i386/kvm.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 56addf1866..18782e49db 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -140,19 +140,20 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, for (i = 0; i < cpuid->nent; ++i) { if (cpuid->entries[i].function == function && cpuid->entries[i].index == index) { + struct kvm_cpuid_entry2 *entry = &cpuid->entries[i]; found = true; switch (reg) { case R_EAX: - ret = cpuid->entries[i].eax; + ret = entry->eax; break; case R_EBX: - ret = cpuid->entries[i].ebx; + ret = entry->ebx; break; case R_ECX: - ret = cpuid->entries[i].ecx; + ret = entry->ecx; break; case R_EDX: - ret = cpuid->entries[i].edx; + ret = entry->edx; break; } } From 829ae2f9fa37bf026de556f50d58ef14a7dab9b3 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Thu, 4 Oct 2012 17:48:56 -0300 Subject: [PATCH 04/28] i386: kvm: extract register switch to cpuid_entry_get_reg() function No behavior change: just code movement. Signed-off-by: Eduardo Habkost Signed-off-by: Marcelo Tosatti --- target-i386/kvm.c | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 18782e49db..695deb9f93 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -123,6 +123,28 @@ static int get_para_features(KVMState *s) } +/* Returns the value for a specific register on the cpuid entry + */ +static uint32_t cpuid_entry_get_reg(struct kvm_cpuid_entry2 *entry, int reg) +{ + uint32_t ret = 0; + switch (reg) { + case R_EAX: + ret = entry->eax; + break; + case R_EBX: + ret = entry->ebx; + break; + case R_ECX: + ret = entry->ecx; + break; + case R_EDX: + ret = entry->edx; + break; + } + return ret; +} + uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, uint32_t index, int reg) { @@ -142,20 +164,7 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, cpuid->entries[i].index == index) { struct kvm_cpuid_entry2 *entry = &cpuid->entries[i]; found = true; - switch (reg) { - case R_EAX: - ret = entry->eax; - break; - case R_EBX: - ret = entry->ebx; - break; - case R_ECX: - ret = entry->ecx; - break; - case R_EDX: - ret = entry->edx; - break; - } + ret = cpuid_entry_get_reg(entry, reg); } } From 4fb73f1d3be285caeb52a58fa5eaea49bd918650 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Thu, 4 Oct 2012 17:48:57 -0300 Subject: [PATCH 05/28] i386: kvm: extract CPUID entry lookup to cpuid_find_entry() function No behavior change, just code movement. Signed-off-by: Eduardo Habkost Signed-off-by: Marcelo Tosatti --- target-i386/kvm.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 695deb9f93..c94897f5d3 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -145,11 +145,28 @@ static uint32_t cpuid_entry_get_reg(struct kvm_cpuid_entry2 *entry, int reg) return ret; } +/* Find matching entry for function/index on kvm_cpuid2 struct + */ +static struct kvm_cpuid_entry2 *cpuid_find_entry(struct kvm_cpuid2 *cpuid, + uint32_t function, + uint32_t index) +{ + int i; + for (i = 0; i < cpuid->nent; ++i) { + if (cpuid->entries[i].function == function && + cpuid->entries[i].index == index) { + return &cpuid->entries[i]; + } + } + /* not found: */ + return NULL; +} + uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, uint32_t index, int reg) { struct kvm_cpuid2 *cpuid; - int i, max; + int max; uint32_t ret = 0; uint32_t cpuid_1_edx; bool found = false; @@ -159,13 +176,10 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, max *= 2; } - for (i = 0; i < cpuid->nent; ++i) { - if (cpuid->entries[i].function == function && - cpuid->entries[i].index == index) { - struct kvm_cpuid_entry2 *entry = &cpuid->entries[i]; - found = true; - ret = cpuid_entry_get_reg(entry, reg); - } + struct kvm_cpuid_entry2 *entry = cpuid_find_entry(cpuid, function, index); + if (entry) { + found = true; + ret = cpuid_entry_get_reg(entry, reg); } /* Fixups for the data returned by KVM, below */ From dd87f8a690330777363f9a8680fce8f2ec544414 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Thu, 4 Oct 2012 17:48:58 -0300 Subject: [PATCH 06/28] i386: kvm: extract try_get_cpuid() loop to get_supported_cpuid() function No behavior change, just code movement. Signed-off-by: Eduardo Habkost Signed-off-by: Marcelo Tosatti --- target-i386/kvm.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/target-i386/kvm.c b/target-i386/kvm.c index c94897f5d3..d74dbc152c 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -98,6 +98,19 @@ static struct kvm_cpuid2 *try_get_cpuid(KVMState *s, int max) return cpuid; } +/* Run KVM_GET_SUPPORTED_CPUID ioctl(), allocating a buffer large enough + * for all entries. + */ +static struct kvm_cpuid2 *get_supported_cpuid(KVMState *s) +{ + struct kvm_cpuid2 *cpuid; + int max = 1; + while ((cpuid = try_get_cpuid(s, max)) == NULL) { + max *= 2; + } + return cpuid; +} + struct kvm_para_features { int cap; int feature; @@ -166,15 +179,11 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, uint32_t index, int reg) { struct kvm_cpuid2 *cpuid; - int max; uint32_t ret = 0; uint32_t cpuid_1_edx; bool found = false; - max = 1; - while ((cpuid = try_get_cpuid(s, max)) == NULL) { - max *= 2; - } + cpuid = get_supported_cpuid(s); struct kvm_cpuid_entry2 *entry = cpuid_find_entry(cpuid, function, index); if (entry) { From c2acb022c83fbaf7fdd7ab9538d44ae6e0e94f94 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Thu, 4 Oct 2012 17:48:59 -0300 Subject: [PATCH 07/28] i386: kvm: kvm_arch_get_supported_cpuid: replace if+switch with single 'if' Additional fixups will be added, and making them a single 'if/else if' chain makes it clearer than two nested switch statements. Signed-off-by: Eduardo Habkost Signed-off-by: Marcelo Tosatti --- target-i386/kvm.c | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/target-i386/kvm.c b/target-i386/kvm.c index d74dbc152c..1f943c5c5a 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -193,20 +193,15 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, /* Fixups for the data returned by KVM, below */ - if (reg == R_EDX) { - switch (function) { - case 1: - /* KVM before 2.6.30 misreports the following features */ - ret |= CPUID_MTRR | CPUID_PAT | CPUID_MCE | CPUID_MCA; - break; - case 0x80000001: - /* On Intel, kvm returns cpuid according to the Intel spec, - * so add missing bits according to the AMD spec: - */ - cpuid_1_edx = kvm_arch_get_supported_cpuid(s, 1, 0, R_EDX); - ret |= cpuid_1_edx & CPUID_EXT2_AMD_ALIASES; - break; - } + if (function == 1 && reg == R_EDX) { + /* KVM before 2.6.30 misreports the following features */ + ret |= CPUID_MTRR | CPUID_PAT | CPUID_MCE | CPUID_MCA; + } else if (function == 0x80000001 && reg == R_EDX) { + /* On Intel, kvm returns cpuid according to the Intel spec, + * so add missing bits according to the AMD spec: + */ + cpuid_1_edx = kvm_arch_get_supported_cpuid(s, 1, 0, R_EDX); + ret |= cpuid_1_edx & CPUID_EXT2_AMD_ALIASES; } g_free(cpuid); From 84bd945cf298650096691509e7e9170036605e02 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Thu, 4 Oct 2012 17:49:00 -0300 Subject: [PATCH 08/28] i386: kvm: set CPUID_EXT_HYPERVISOR on kvm_arch_get_supported_cpuid() Full grep for kvm_arch_get_supported_cpuid: kvm.h:uint32_t kvm_arch_get_supported_cpuid(KVMState *env, uint32_t function, target-i386/cpu.c: x86_cpu_def->cpuid_7_0_ebx_features = kvm_arch_get_supported_cpuid(kvm_state, 0x7, 0, R_EBX); target-i386/cpu.c: *eax = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EAX); target-i386/cpu.c: *ebx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EBX); target-i386/cpu.c: *ecx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_ECX); target-i386/cpu.c: *edx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EDX); target-i386/cpu.c: *eax = kvm_arch_get_supported_cpuid(s, 0xd, count, R_EAX); target-i386/cpu.c: *ebx = kvm_arch_get_supported_cpuid(s, 0xd, count, R_EBX); target-i386/cpu.c: *ecx = kvm_arch_get_supported_cpuid(s, 0xd, count, R_ECX); target-i386/cpu.c: *edx = kvm_arch_get_supported_cpuid(s, 0xd, count, R_EDX); target-i386/kvm.c:uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, target-i386/kvm.c: cpuid_1_edx = kvm_arch_get_supported_cpuid(s, 1, 0, R_EDX); target-i386/kvm.c: env->cpuid_features &= kvm_arch_get_supported_cpuid(s, 1, 0, R_EDX); * target-i386/kvm.c: env->cpuid_ext_features &= kvm_arch_get_supported_cpuid(s, 1, 0, R_ECX); target-i386/kvm.c: env->cpuid_ext2_features &= kvm_arch_get_supported_cpuid(s, 0x80000001, target-i386/kvm.c: env->cpuid_ext3_features &= kvm_arch_get_supported_cpuid(s, 0x80000001, target-i386/kvm.c: env->cpuid_svm_features &= kvm_arch_get_supported_cpuid(s, 0x8000000A, target-i386/kvm.c: kvm_arch_get_supported_cpuid(s, KVM_CPUID_FEATURES, 0, R_EAX); target-i386/kvm.c: kvm_arch_get_supported_cpuid(s, 0xC0000001, 0, R_EDX); Note that there is only one call for CPUID[1].ECX above (*), and it is the one that gets hacked to include CPUID_EXT_HYPERVISOR, so we can simply make kvm_arch_get_supported_cpuid() set it, to let the rest of the code automatically know that the flag can be safely set by QEMU. Signed-off-by: Eduardo Habkost Signed-off-by: Marcelo Tosatti --- target-i386/kvm.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 1f943c5c5a..aabac72a66 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -196,6 +196,11 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, if (function == 1 && reg == R_EDX) { /* KVM before 2.6.30 misreports the following features */ ret |= CPUID_MTRR | CPUID_PAT | CPUID_MCE | CPUID_MCA; + } else if (function == 1 && reg == R_ECX) { + /* We can set the hypervisor flag, even if KVM does not return it on + * GET_SUPPORTED_CPUID + */ + ret |= CPUID_EXT_HYPERVISOR; } else if (function == 0x80000001 && reg == R_EDX) { /* On Intel, kvm returns cpuid according to the Intel spec, * so add missing bits according to the AMD spec: @@ -399,10 +404,8 @@ int kvm_arch_init_vcpu(CPUX86State *env) env->cpuid_features &= kvm_arch_get_supported_cpuid(s, 1, 0, R_EDX); - i = env->cpuid_ext_features & CPUID_EXT_HYPERVISOR; j = env->cpuid_ext_features & CPUID_EXT_TSC_DEADLINE_TIMER; env->cpuid_ext_features &= kvm_arch_get_supported_cpuid(s, 1, 0, R_ECX); - env->cpuid_ext_features |= i; if (j && kvm_irqchip_in_kernel() && kvm_check_extension(s, KVM_CAP_TSC_DEADLINE_TIMER)) { env->cpuid_ext_features |= CPUID_EXT_TSC_DEADLINE_TIMER; From ac67ee260ae8e353314b6995ed5dccf1bb94fa9d Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Thu, 4 Oct 2012 17:49:01 -0300 Subject: [PATCH 09/28] i386: kvm: set CPUID_EXT_TSC_DEADLINE_TIMER on kvm_arch_get_supported_cpuid() This moves the CPUID_EXT_TSC_DEADLINE_TIMER CPUID flag hacking from kvm_arch_init_vcpu() to kvm_arch_get_supported_cpuid(). Full git grep for kvm_arch_get_supported_cpuid: kvm.h:uint32_t kvm_arch_get_supported_cpuid(KVMState *env, uint32_t function, target-i386/cpu.c: x86_cpu_def->cpuid_7_0_ebx_features = kvm_arch_get_supported_cpuid(kvm_state, 0x7, 0, R_EBX); target-i386/cpu.c: *eax = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EAX); target-i386/cpu.c: *ebx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EBX); target-i386/cpu.c: *ecx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_ECX); target-i386/cpu.c: *edx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EDX); target-i386/cpu.c: *eax = kvm_arch_get_supported_cpuid(s, 0xd, count, R_EAX); target-i386/cpu.c: *ebx = kvm_arch_get_supported_cpuid(s, 0xd, count, R_EBX); target-i386/cpu.c: *ecx = kvm_arch_get_supported_cpuid(s, 0xd, count, R_ECX); target-i386/cpu.c: *edx = kvm_arch_get_supported_cpuid(s, 0xd, count, R_EDX); target-i386/kvm.c:uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, target-i386/kvm.c: cpuid_1_edx = kvm_arch_get_supported_cpuid(s, 1, 0, R_EDX); target-i386/kvm.c: env->cpuid_features &= kvm_arch_get_supported_cpuid(s, 1, 0, R_EDX); * target-i386/kvm.c: env->cpuid_ext_features &= kvm_arch_get_supported_cpuid(s, 1, 0, R_ECX); target-i386/kvm.c: env->cpuid_ext2_features &= kvm_arch_get_supported_cpuid(s, 0x80000001, target-i386/kvm.c: env->cpuid_ext3_features &= kvm_arch_get_supported_cpuid(s, 0x80000001, target-i386/kvm.c: env->cpuid_svm_features &= kvm_arch_get_supported_cpuid(s, 0x8000000A, target-i386/kvm.c: kvm_arch_get_supported_cpuid(s, KVM_CPUID_FEATURES, 0, R_EAX); target-i386/kvm.c: kvm_arch_get_supported_cpuid(s, 0xC0000001, 0, R_EDX); Note that there is only one call for CPUID[1].ECX above (*), and it is the one that gets hacked to include CPUID_EXT_TSC_DEADLINE_TIMER, so we can simply make kvm_arch_get_supported_cpuid() set it, to let the rest of the code know the flag can be safely set by QEMU. One thing I was worrying about when doing this is that now kvm_arch_get_supported_cpuid() depends on kvm_irqchip_in_kernel(). But the 'kvm_kernel_irqchip' global variable is initialized during kvm_init(), that is called very early, and kvm_init() is already a requirement to run the GET_SUPPORTED_CPUID ioctl() (as kvm_init() is the function that initializes the 'kvm_state' global variable). Signed-off-by: Eduardo Habkost Signed-off-by: Marcelo Tosatti --- target-i386/kvm.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/target-i386/kvm.c b/target-i386/kvm.c index aabac72a66..aae8af22dd 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -201,6 +201,14 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, * GET_SUPPORTED_CPUID */ ret |= CPUID_EXT_HYPERVISOR; + /* tsc-deadline flag is not returned by GET_SUPPORTED_CPUID, but it + * can be enabled if the kernel has KVM_CAP_TSC_DEADLINE_TIMER, + * and the irqchip is in the kernel. + */ + if (kvm_irqchip_in_kernel() && + kvm_check_extension(s, KVM_CAP_TSC_DEADLINE_TIMER)) { + ret |= CPUID_EXT_TSC_DEADLINE_TIMER; + } } else if (function == 0x80000001 && reg == R_EDX) { /* On Intel, kvm returns cpuid according to the Intel spec, * so add missing bits according to the AMD spec: @@ -404,12 +412,7 @@ int kvm_arch_init_vcpu(CPUX86State *env) env->cpuid_features &= kvm_arch_get_supported_cpuid(s, 1, 0, R_EDX); - j = env->cpuid_ext_features & CPUID_EXT_TSC_DEADLINE_TIMER; env->cpuid_ext_features &= kvm_arch_get_supported_cpuid(s, 1, 0, R_ECX); - if (j && kvm_irqchip_in_kernel() && - kvm_check_extension(s, KVM_CAP_TSC_DEADLINE_TIMER)) { - env->cpuid_ext_features |= CPUID_EXT_TSC_DEADLINE_TIMER; - } env->cpuid_ext2_features &= kvm_arch_get_supported_cpuid(s, 0x80000001, 0, R_EDX); From 41e5e76db07b52591d9c9b88826278b8a5112258 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Thu, 4 Oct 2012 17:49:02 -0300 Subject: [PATCH 10/28] i386: kvm: x2apic is not supported without in-kernel irqchip This is necessary so that x2apic is not improperly enabled when the in-kernel irqchip is disabled. This won't generate a warning with "-cpu ...,check" because the current check/enforce code is broken (it checks the host CPU data directly, instead of using kvm_arch_get_supported_cpuid()), but it will be eventually fixed to properly report the missing x2apic flag. Signed-off-by: Eduardo Habkost Signed-off-by: Marcelo Tosatti --- target-i386/kvm.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/target-i386/kvm.c b/target-i386/kvm.c index aae8af22dd..4e96b046da 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -209,6 +209,13 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, kvm_check_extension(s, KVM_CAP_TSC_DEADLINE_TIMER)) { ret |= CPUID_EXT_TSC_DEADLINE_TIMER; } + + /* x2apic is reported by GET_SUPPORTED_CPUID, but it can't be enabled + * without the in-kernel irqchip + */ + if (!kvm_irqchip_in_kernel()) { + ret &= ~CPUID_EXT_X2APIC; + } } else if (function == 0x80000001 && reg == R_EDX) { /* On Intel, kvm returns cpuid according to the Intel spec, * so add missing bits according to the AMD spec: From ea85c9e45655c5e3a665a5295e5338b995e4a29c Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Thu, 4 Oct 2012 17:49:03 -0300 Subject: [PATCH 11/28] i386: kvm: mask cpuid_kvm_features earlier Instead of masking the KVM feature bits very late (while building the KVM_SET_CPUID2 data), mask it out on env->cpuid_kvm_features, at the same point where the other feature words are masked out. Signed-off-by: Eduardo Habkost Signed-off-by: Marcelo Tosatti --- target-i386/kvm.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 4e96b046da..8eb61a02e7 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -428,6 +428,9 @@ int kvm_arch_init_vcpu(CPUX86State *env) env->cpuid_svm_features &= kvm_arch_get_supported_cpuid(s, 0x8000000A, 0, R_EDX); + env->cpuid_kvm_features &= + kvm_arch_get_supported_cpuid(s, KVM_CPUID_FEATURES, 0, R_EAX); + cpuid_i = 0; /* Paravirtualization CPUIDs */ @@ -448,8 +451,7 @@ int kvm_arch_init_vcpu(CPUX86State *env) c = &cpuid_data.entries[cpuid_i++]; memset(c, 0, sizeof(*c)); c->function = KVM_CPUID_FEATURES; - c->eax = env->cpuid_kvm_features & - kvm_arch_get_supported_cpuid(s, KVM_CPUID_FEATURES, 0, R_EAX); + c->eax = env->cpuid_kvm_features; if (hyperv_enabled()) { memcpy(signature, "Hv#1\0\0\0\0\0\0\0\0", 12); From c9da8382c1432fbafb8705e7faecdf783c0b1821 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Thu, 4 Oct 2012 17:49:04 -0300 Subject: [PATCH 12/28] i386: kvm: mask cpuid_ext4_features bits earlier This way all the filtering by GET_SUPPORTED_CPUID is being done at the same place in the code. Signed-off-by: Eduardo Habkost Signed-off-by: Marcelo Tosatti --- target-i386/kvm.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 8eb61a02e7..be37a1f7ba 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -431,6 +431,9 @@ int kvm_arch_init_vcpu(CPUX86State *env) env->cpuid_kvm_features &= kvm_arch_get_supported_cpuid(s, KVM_CPUID_FEATURES, 0, R_EAX); + env->cpuid_ext4_features &= kvm_arch_get_supported_cpuid(s, 0xC0000001, + 0, R_EDX); + cpuid_i = 0; /* Paravirtualization CPUIDs */ @@ -572,8 +575,6 @@ int kvm_arch_init_vcpu(CPUX86State *env) /* Call Centaur's CPUID instructions they are supported. */ if (env->cpuid_xlevel2 > 0) { - env->cpuid_ext4_features &= - kvm_arch_get_supported_cpuid(s, 0xC0000001, 0, R_EDX); cpu_x86_cpuid(env, 0xC0000000, 0, &limit, &unused, &unused, &unused); for (i = 0xC0000000; i <= limit; i++) { From bc74b7db86bc84d3e027ac7b536e8e39140d984f Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Thu, 4 Oct 2012 17:49:05 -0300 Subject: [PATCH 13/28] i386: kvm: filter CPUID feature words earlier, on cpu.c cpu.c contains the code that will check if all requested CPU features are available, so the filtering of KVM features must be there, so we can implement "check" and "enforce" properly. The only point where kvm_arch_init_vcpu() is called on i386 is: - cpu_x86_init() - x86_cpu_realize() (after cpu_x86_register() is called) - qemu_init_vcpu() - qemu_kvm_start_vcpu() - qemu_kvm_thread_fn() (on a new thread) - kvm_init_vcpu() - kvm_arch_init_vcpu() With this patch, the filtering will be done earlier, at: - cpu_x86_init() - cpu_x86_register() (before x86_cpu_realize() is called) Also, the KVM CPUID filtering will now be done at the same place where the TCG CPUID feature filtering is done. Later, the code can be changed to use the same filtering code for the "check" and "enforce" modes, as now the cpu.c code knows exactly which CPU features are going to be exposed to the guest (and much earlier). One thing I was worrying about when doing this is that kvm_arch_get_supported_cpuid() depends on kvm_irqchip_in_kernel(), and maybe the 'kvm_kernel_irqchip' global variable wasn't initialized yet at CPU creation time. But kvm_kernel_irqchip is initialized during kvm_init(), that is called very early (much earlier than the machine init function), and kvm_init() is already a requirement to run the GET_SUPPORTED_CPUID ioctl() (as kvm_init() initializes the kvm_state global variable). Side note: it would be nice to keep KVM-specific code inside kvm.c. The problem is that properly implementing -cpu check/enforce code (that's inside cpu.c) depends directly on the feature bit filtering done using kvm_arch_get_supported_cpuid(). Currently -cpu check/enforce is broken because it simply uses the host CPU feature bits instead of GET_SUPPORTED_CPUID, and we need to fix that. Signed-off-by: Eduardo Habkost Signed-off-by: Marcelo Tosatti --- kvm.h | 1 + target-i386/cpu.c | 30 ++++++++++++++++++++++++++++++ target-i386/kvm.c | 18 ------------------ 3 files changed, 31 insertions(+), 18 deletions(-) diff --git a/kvm.h b/kvm.h index 2b26dcb9bb..1e7f244561 100644 --- a/kvm.h +++ b/kvm.h @@ -20,6 +20,7 @@ #ifdef CONFIG_KVM #include +#include #endif extern int kvm_allowed; diff --git a/target-i386/cpu.c b/target-i386/cpu.c index d4f2e65cd9..78876f632b 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -1368,6 +1368,32 @@ CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp) return cpu_list; } +#ifdef CONFIG_KVM +static void filter_features_for_kvm(X86CPU *cpu) +{ + CPUX86State *env = &cpu->env; + KVMState *s = kvm_state; + + env->cpuid_features &= kvm_arch_get_supported_cpuid(s, 1, 0, R_EDX); + + env->cpuid_ext_features &= kvm_arch_get_supported_cpuid(s, 1, 0, R_ECX); + + env->cpuid_ext2_features &= kvm_arch_get_supported_cpuid(s, 0x80000001, + 0, R_EDX); + env->cpuid_ext3_features &= kvm_arch_get_supported_cpuid(s, 0x80000001, + 0, R_ECX); + env->cpuid_svm_features &= kvm_arch_get_supported_cpuid(s, 0x8000000A, + 0, R_EDX); + + env->cpuid_kvm_features &= + kvm_arch_get_supported_cpuid(s, KVM_CPUID_FEATURES, 0, R_EAX); + + env->cpuid_ext4_features &= kvm_arch_get_supported_cpuid(s, 0xC0000001, + 0, R_EDX); + +} +#endif + int cpu_x86_register(X86CPU *cpu, const char *cpu_model) { CPUX86State *env = &cpu->env; @@ -1425,6 +1451,10 @@ int cpu_x86_register(X86CPU *cpu, const char *cpu_model) ); env->cpuid_ext3_features &= TCG_EXT3_FEATURES; env->cpuid_svm_features &= TCG_SVM_FEATURES; + } else { +#ifdef CONFIG_KVM + filter_features_for_kvm(cpu); +#endif } object_property_set_str(OBJECT(cpu), def->model_id, "model-id", &error); if (error_is_set(&error)) { diff --git a/target-i386/kvm.c b/target-i386/kvm.c index be37a1f7ba..593e9d3e0f 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -410,30 +410,12 @@ int kvm_arch_init_vcpu(CPUX86State *env) struct kvm_cpuid2 cpuid; struct kvm_cpuid_entry2 entries[100]; } QEMU_PACKED cpuid_data; - KVMState *s = env->kvm_state; uint32_t limit, i, j, cpuid_i; uint32_t unused; struct kvm_cpuid_entry2 *c; uint32_t signature[3]; int r; - env->cpuid_features &= kvm_arch_get_supported_cpuid(s, 1, 0, R_EDX); - - env->cpuid_ext_features &= kvm_arch_get_supported_cpuid(s, 1, 0, R_ECX); - - env->cpuid_ext2_features &= kvm_arch_get_supported_cpuid(s, 0x80000001, - 0, R_EDX); - env->cpuid_ext3_features &= kvm_arch_get_supported_cpuid(s, 0x80000001, - 0, R_ECX); - env->cpuid_svm_features &= kvm_arch_get_supported_cpuid(s, 0x8000000A, - 0, R_EDX); - - env->cpuid_kvm_features &= - kvm_arch_get_supported_cpuid(s, KVM_CPUID_FEATURES, 0, R_EAX); - - env->cpuid_ext4_features &= kvm_arch_get_supported_cpuid(s, 0xC0000001, - 0, R_EDX); - cpuid_i = 0; /* Paravirtualization CPUIDs */ From b8091f245d36da604219db42552cc28400698446 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Thu, 4 Oct 2012 17:49:06 -0300 Subject: [PATCH 14/28] i386: kvm: reformat filter_features_for_kvm() code Cosmetic, but it will also help to make futher patches easier to review. Signed-off-by: Eduardo Habkost Signed-off-by: Marcelo Tosatti --- target-i386/cpu.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 78876f632b..be16898e37 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -1374,22 +1374,20 @@ static void filter_features_for_kvm(X86CPU *cpu) CPUX86State *env = &cpu->env; KVMState *s = kvm_state; - env->cpuid_features &= kvm_arch_get_supported_cpuid(s, 1, 0, R_EDX); - - env->cpuid_ext_features &= kvm_arch_get_supported_cpuid(s, 1, 0, R_ECX); - - env->cpuid_ext2_features &= kvm_arch_get_supported_cpuid(s, 0x80000001, - 0, R_EDX); - env->cpuid_ext3_features &= kvm_arch_get_supported_cpuid(s, 0x80000001, - 0, R_ECX); - env->cpuid_svm_features &= kvm_arch_get_supported_cpuid(s, 0x8000000A, - 0, R_EDX); - + env->cpuid_features &= + kvm_arch_get_supported_cpuid(s, 1, 0, R_EDX); + env->cpuid_ext_features &= + kvm_arch_get_supported_cpuid(s, 1, 0, R_ECX); + env->cpuid_ext2_features &= + kvm_arch_get_supported_cpuid(s, 0x80000001, 0, R_EDX); + env->cpuid_ext3_features &= + kvm_arch_get_supported_cpuid(s, 0x80000001, 0, R_ECX); + env->cpuid_svm_features &= + kvm_arch_get_supported_cpuid(s, 0x8000000A, 0, R_EDX); env->cpuid_kvm_features &= - kvm_arch_get_supported_cpuid(s, KVM_CPUID_FEATURES, 0, R_EAX); - - env->cpuid_ext4_features &= kvm_arch_get_supported_cpuid(s, 0xC0000001, - 0, R_EDX); + kvm_arch_get_supported_cpuid(s, KVM_CPUID_FEATURES, 0, R_EAX); + env->cpuid_ext4_features &= + kvm_arch_get_supported_cpuid(s, 0xC0000001, 0, R_EDX); } #endif From ffa8c11f0bbf47e1b7a3a62f97bc1da591c6734a Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Thu, 4 Oct 2012 17:49:07 -0300 Subject: [PATCH 15/28] i386: kvm: filter CPUID leaf 7 based on GET_SUPPORTED_CPUID, too Now that CPUID leaf 7 features can be enabled/disabled on the command-line, we need to filter them properly using GET_SUPPORTED_CPUID, at the same place where other features are filtered out. Signed-off-by: Eduardo Habkost Signed-off-by: Marcelo Tosatti --- target-i386/cpu.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index be16898e37..22d91ed074 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -1384,6 +1384,8 @@ static void filter_features_for_kvm(X86CPU *cpu) kvm_arch_get_supported_cpuid(s, 0x80000001, 0, R_ECX); env->cpuid_svm_features &= kvm_arch_get_supported_cpuid(s, 0x8000000A, 0, R_EDX); + env->cpuid_7_0_ebx_features &= + kvm_arch_get_supported_cpuid(s, 7, 0, R_EBX); env->cpuid_kvm_features &= kvm_arch_get_supported_cpuid(s, KVM_CPUID_FEATURES, 0, R_EAX); env->cpuid_ext4_features &= From 811a8ae09e179d0a4d8cde13ba9f72e7c782c9ff Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Tue, 9 Oct 2012 11:03:59 -0300 Subject: [PATCH 16/28] i386: cpu: add missing CPUID[EAX=7,ECX=0] flag names This makes QEMU recognize the following CPU flag names: Flags | Corresponding KVM kernel commit -----------------+---------------------------------------- FSGSBASE | 176f61da82435eae09cc96f70b530d1ba0746b8b AVX2, BMI1, BMI2 | fb215366b3c7320ac25dca766a0152df16534932 HLE, RTM | 83c529151ab0d4a813e3f6a3e293fff75d468519 INVPCID | ad756a1603c5fac207758faaac7f01c34c9d0b7b ERMS | a01c8f9b4e266df1d7166d23216f2060648f862d Reviewed-by: Don Slutz Signed-off-by: Eduardo Habkost Signed-off-by: Marcelo Tosatti --- target-i386/cpu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 22d91ed074..7c726fc0b1 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -106,8 +106,8 @@ static const char *svm_feature_name[] = { }; static const char *cpuid_7_0_ebx_feature_name[] = { - NULL, NULL, NULL, NULL, NULL, NULL, NULL, "smep", - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "fsgsbase", NULL, NULL, "bmi1", "hle", "avx2", NULL, "smep", + "bmi2", "erms", "invpcid", "rtm", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "smap", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }; From c3d3980794124508e0bd4eaa406d7fa0e832a221 Mon Sep 17 00:00:00 2001 From: Don Slutz Date: Fri, 12 Oct 2012 15:43:23 -0400 Subject: [PATCH 17/28] target-i386: Add missing kvm cpuid feature name Currently "-cpu host,-kvmclock,-kvm_nopiodelay,-kvm_mmu" does not turn off all bits in CPUID 0x40000001 EAX. The missing ones is KVM_FEATURE_STEAL_TIME. This adds the name kvm_steal_time. Signed-off-by: Don Slutz Signed-off-by: Marcelo Tosatti --- target-i386/cpu.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 7c726fc0b1..4417d6abed 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -88,10 +88,14 @@ static const char *ext3_feature_name[] = { }; static const char *kvm_feature_name[] = { - "kvmclock", "kvm_nopiodelay", "kvm_mmu", "kvmclock", "kvm_asyncpf", NULL, "kvm_pv_eoi", NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "kvmclock", "kvm_nopiodelay", "kvm_mmu", "kvmclock", + "kvm_asyncpf", "kvm_steal_time", "kvm_pv_eoi", NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, }; static const char *svm_feature_name[] = { From 19403a68fb8eaefb2e1245b6a8384d3a3ffa7ca0 Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Fri, 5 Oct 2012 14:51:39 -0300 Subject: [PATCH 18/28] cirrus_vga: allow configurable vram size Allow RAM size to be configurable for cirrus, to allow migration compatibility from qemu-kvm. Acked-by: Gerd Hoffmann Signed-off-by: Marcelo Tosatti --- hw/cirrus_vga.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c index e4af2e9ded..9bef96e6d7 100644 --- a/hw/cirrus_vga.c +++ b/hw/cirrus_vga.c @@ -42,8 +42,6 @@ //#define DEBUG_CIRRUS //#define DEBUG_BITBLT -#define VGA_RAM_SIZE (8192 * 1024) - /*************************************** * * definitions @@ -2856,7 +2854,8 @@ static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci, /* I/O handler for LFB */ memory_region_init_io(&s->cirrus_linear_io, &cirrus_linear_io_ops, s, - "cirrus-linear-io", VGA_RAM_SIZE); + "cirrus-linear-io", s->vga.vram_size_mb + * 1024 * 1024); memory_region_set_flush_coalesced(&s->cirrus_linear_io); /* I/O handler for LFB */ @@ -2899,7 +2898,6 @@ static int vga_initfn(ISADevice *dev) ISACirrusVGAState *d = DO_UPCAST(ISACirrusVGAState, dev, dev); VGACommonState *s = &d->cirrus_vga.vga; - s->vram_size_mb = VGA_RAM_SIZE >> 20; vga_common_init(s); cirrus_init_common(&d->cirrus_vga, CIRRUS_ID_CLGD5430, 0, isa_address_space(dev)); @@ -2912,6 +2910,12 @@ static int vga_initfn(ISADevice *dev) return 0; } +static Property isa_vga_cirrus_properties[] = { + DEFINE_PROP_UINT32("vgamem_mb", struct ISACirrusVGAState, + cirrus_vga.vga.vram_size_mb, 8), + DEFINE_PROP_END_OF_LIST(), +}; + static void isa_cirrus_vga_class_init(ObjectClass *klass, void *data) { ISADeviceClass *k = ISA_DEVICE_CLASS(klass); @@ -2919,6 +2923,7 @@ static void isa_cirrus_vga_class_init(ObjectClass *klass, void *data) dc->vmsd = &vmstate_cirrus_vga; k->init = vga_initfn; + dc->props = isa_vga_cirrus_properties; } static TypeInfo isa_cirrus_vga_info = { @@ -2942,7 +2947,6 @@ static int pci_cirrus_vga_initfn(PCIDevice *dev) int16_t device_id = pc->device_id; /* setup VGA */ - s->vga.vram_size_mb = VGA_RAM_SIZE >> 20; vga_common_init(&s->vga); cirrus_init_common(s, device_id, 1, pci_address_space(dev)); s->vga.ds = graphic_console_init(s->vga.update, s->vga.invalidate, @@ -2969,6 +2973,12 @@ static int pci_cirrus_vga_initfn(PCIDevice *dev) return 0; } +static Property pci_vga_cirrus_properties[] = { + DEFINE_PROP_UINT32("vgamem_mb", struct PCICirrusVGAState, + cirrus_vga.vga.vram_size_mb, 8), + DEFINE_PROP_END_OF_LIST(), +}; + static void cirrus_vga_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -2982,6 +2992,7 @@ static void cirrus_vga_class_init(ObjectClass *klass, void *data) k->class_id = PCI_CLASS_DISPLAY_VGA; dc->desc = "Cirrus CLGD 54xx VGA"; dc->vmsd = &vmstate_pci_cirrus_vga; + dc->props = pci_vga_cirrus_properties; } static TypeInfo cirrus_vga_info = { From e43d594ee55038442d59d301eb34fdf0c378d3a4 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Fri, 5 Oct 2012 14:51:40 -0300 Subject: [PATCH 19/28] Use machine options to emulate -no-kvm-irqchip Releases of qemu-kvm will be interrupted at qemu 1.3.0. Users should switch to plain qemu releases. To avoid breaking scenarios which are setup with command line options specific to qemu-kvm, port these switches from qemu-kvm to qemu.git. Port -no-kvm-irqchip option. Signed-off-by: Marcelo Tosatti --- qemu-options.hx | 3 +++ vl.c | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/qemu-options.hx b/qemu-options.hx index a67a2551e5..d813755ccb 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -2888,6 +2888,9 @@ STEXI Enable FIPS 140-2 compliance mode. ETEXI +HXCOMM Deprecated by -machine kernel_irqchip=on|off property +DEF("no-kvm-irqchip", HAS_ARG, QEMU_OPTION_no_kvm_irqchip, "", QEMU_ARCH_I386) + HXCOMM This is the last statement. Insert new options before this line! STEXI @end table diff --git a/vl.c b/vl.c index 5a3d316980..7d0708afcd 100644 --- a/vl.c +++ b/vl.c @@ -2574,6 +2574,11 @@ int main(int argc, char **argv, char **envp) case QEMU_OPTION_M: machine = machine_parse(optarg); break; + case QEMU_OPTION_no_kvm_irqchip: { + olist = qemu_find_opts("machine"); + qemu_opts_parse(olist, "kernel_irqchip=off", 0); + break; + } case QEMU_OPTION_cpu: /* hw initialization will check this */ cpu_model = optarg; From 4086bde8c08746913d7ca6dcbc5e18a49a627cdc Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Fri, 5 Oct 2012 14:51:41 -0300 Subject: [PATCH 20/28] Issue warning when deprecated -no-kvm-pit is used Releases of qemu-kvm will be interrupted at qemu 1.3.0. Users should switch to plain qemu releases. To avoid breaking scenarios which are setup with command line options specific to qemu-kvm, port these switches from qemu-kvm to qemu.git. Port -no-kvm-pit option. Signed-off-by: Marcelo Tosatti --- qemu-options.hx | 3 +++ vl.c | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/qemu-options.hx b/qemu-options.hx index d813755ccb..42e642c65b 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -2888,6 +2888,9 @@ STEXI Enable FIPS 140-2 compliance mode. ETEXI +HXCOMM Deprecated (ignored) +DEF("no-kvm-pit", HAS_ARG, QEMU_OPTION_no_kvm_pit, "", QEMU_ARCH_I386) + HXCOMM Deprecated by -machine kernel_irqchip=on|off property DEF("no-kvm-irqchip", HAS_ARG, QEMU_OPTION_no_kvm_irqchip, "", QEMU_ARCH_I386) diff --git a/vl.c b/vl.c index 7d0708afcd..37717b4559 100644 --- a/vl.c +++ b/vl.c @@ -3171,6 +3171,11 @@ int main(int argc, char **argv, char **envp) machine = machine_parse(optarg); } break; + case QEMU_OPTION_no_kvm_pit: { + fprintf(stderr, "Warning: KVM PIT can no longer be disabled " + "separately.\n"); + break; + } case QEMU_OPTION_usb: machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0); if (machine_opts) { From c21fb4f8b802108697f9353a8f807079507b586c Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Fri, 5 Oct 2012 14:51:42 -0300 Subject: [PATCH 21/28] Use global properties to emulate -no-kvm-pit-reinjection Releases of qemu-kvm will be interrupted at qemu 1.3.0. Users should switch to plain qemu releases. To avoid breaking scenarios which are setup with command line options specific to qemu-kvm, port these switches from qemu-kvm to qemu.git. Port -no-kvm-pit-reinjection. Signed-off-by: Marcelo Tosatti --- qemu-options.hx | 4 ++++ vl.c | 15 +++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/qemu-options.hx b/qemu-options.hx index 42e642c65b..4403c9c718 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -2888,6 +2888,10 @@ STEXI Enable FIPS 140-2 compliance mode. ETEXI +HXCOMM Deprecated by kvm-pit driver properties +DEF("no-kvm-pit-reinjection", HAS_ARG, QEMU_OPTION_no_kvm_pit_reinjection, + "", QEMU_ARCH_I386) + HXCOMM Deprecated (ignored) DEF("no-kvm-pit", HAS_ARG, QEMU_OPTION_no_kvm_pit, "", QEMU_ARCH_I386) diff --git a/vl.c b/vl.c index 37717b4559..3068b4bc59 100644 --- a/vl.c +++ b/vl.c @@ -3176,6 +3176,21 @@ int main(int argc, char **argv, char **envp) "separately.\n"); break; } + case QEMU_OPTION_no_kvm_pit_reinjection: { + static GlobalProperty kvm_pit_lost_tick_policy[] = { + { + .driver = "kvm-pit", + .property = "lost_tick_policy", + .value = "discard", + }, + { /* end of list */ } + }; + + fprintf(stderr, "Warning: option deprecated, use " + "lost_tick_policy property of kvm-pit instead.\n"); + qdev_prop_register_global_list(kvm_pit_lost_tick_policy); + break; + } case QEMU_OPTION_usb: machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0); if (machine_opts) { From 0d92d17a6d0d65af8cb905bdd5f9e04e210564ff Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Fri, 5 Oct 2012 14:51:43 -0300 Subject: [PATCH 22/28] Issue warning when deprecated drive parameter boot=on|off is used Releases of qemu-kvm will be interrupted at qemu 1.3.0. Users should switch to plain qemu releases. To avoid breaking scenarios which are setup with command line options specific to qemu-kvm, port these switches from qemu-kvm to qemu.git. Port drive boot option. From the qemu-kvm original commit message: We do not want to maintain this option forever. It will be removed after a grace period of a few releases. So warn the user that this option has no effect and will become invalid soon. Signed-off-by: Marcelo Tosatti --- blockdev.c | 6 ++++++ qemu-config.c | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/blockdev.c b/blockdev.c index a068a4b669..e73fd6e388 100644 --- a/blockdev.c +++ b/blockdev.c @@ -433,6 +433,12 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi) return NULL; } + if (qemu_opt_get(opts, "boot") != NULL) { + fprintf(stderr, "qemu-kvm: boot=on|off is deprecated and will be " + "ignored. Future versions will reject this parameter. Please " + "update your scripts.\n"); + } + on_write_error = BLOCKDEV_ON_ERROR_ENOSPC; if ((buf = qemu_opt_get(opts, "werror")) != NULL) { if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO && type != IF_NONE) { diff --git a/qemu-config.c b/qemu-config.c index e854fffe19..3154cac10f 100644 --- a/qemu-config.c +++ b/qemu-config.c @@ -114,6 +114,10 @@ static QemuOptsList qemu_drive_opts = { .name = "copy-on-read", .type = QEMU_OPT_BOOL, .help = "copy read data from backing file into image file", + },{ + .name = "boot", + .type = QEMU_OPT_BOOL, + .help = "(deprecated, ignored)", }, { /* end of list */ } }, From 88eed34a6b3eba46397de5aaf24ed66ea290794b Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Fri, 5 Oct 2012 14:51:44 -0300 Subject: [PATCH 23/28] Issue warning when deprecated -tdf option is used Releases of qemu-kvm will be interrupted at qemu 1.3.0. Users should switch to plain qemu releases. To avoid breaking scenarios which are setup with command line options specific to qemu-kvm, port these switches from qemu-kvm to qemu.git. Port -tdf option. Signed-off-by: Marcelo Tosatti --- qemu-options.hx | 3 +++ vl.c | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/qemu-options.hx b/qemu-options.hx index 4403c9c718..628bd44591 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -2898,6 +2898,9 @@ DEF("no-kvm-pit", HAS_ARG, QEMU_OPTION_no_kvm_pit, "", QEMU_ARCH_I386) HXCOMM Deprecated by -machine kernel_irqchip=on|off property DEF("no-kvm-irqchip", HAS_ARG, QEMU_OPTION_no_kvm_irqchip, "", QEMU_ARCH_I386) +HXCOMM Deprecated (ignored) +DEF("tdf", 0, QEMU_OPTION_tdf,"", QEMU_ARCH_ALL) + HXCOMM This is the last statement. Insert new options before this line! STEXI @end table diff --git a/vl.c b/vl.c index 3068b4bc59..cd7c0fbd52 100644 --- a/vl.c +++ b/vl.c @@ -3280,6 +3280,10 @@ int main(int argc, char **argv, char **envp) case QEMU_OPTION_semihosting: semihosting_enabled = 1; break; + case QEMU_OPTION_tdf: + fprintf(stderr, "Warning: user space PIT time drift fix " + "is no longer supported.\n"); + break; case QEMU_OPTION_name: qemu_name = g_strdup(optarg); { From a0dac021fa4b8b87160192c1f60ee26fc6c5ce2e Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Fri, 5 Oct 2012 14:51:45 -0300 Subject: [PATCH 24/28] Emulate qemu-kvms -no-kvm option Releases of qemu-kvm will be interrupted at qemu 1.3.0. Users should switch to plain qemu releases. To avoid breaking scenarios which are setup with command line options specific to qemu-kvm, port these switches from qemu-kvm to qemu.git. Port -no-kvm option. Signed-off-by: Marcelo Tosatti --- qemu-options.hx | 3 +++ vl.c | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/qemu-options.hx b/qemu-options.hx index 628bd44591..fe8f15c541 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -2888,6 +2888,9 @@ STEXI Enable FIPS 140-2 compliance mode. ETEXI +HXCOMM Deprecated by -machine accel=tcg property +DEF("no-kvm", HAS_ARG, QEMU_OPTION_no_kvm, "", QEMU_ARCH_I386) + HXCOMM Deprecated by kvm-pit driver properties DEF("no-kvm-pit-reinjection", HAS_ARG, QEMU_OPTION_no_kvm_pit_reinjection, "", QEMU_ARCH_I386) diff --git a/vl.c b/vl.c index cd7c0fbd52..b39f22ed35 100644 --- a/vl.c +++ b/vl.c @@ -3171,6 +3171,10 @@ int main(int argc, char **argv, char **envp) machine = machine_parse(optarg); } break; + case QEMU_OPTION_no_kvm: + olist = qemu_find_opts("machine"); + qemu_opts_parse(olist, "accel=tcg", 0); + break; case QEMU_OPTION_no_kvm_pit: { fprintf(stderr, "Warning: KVM PIT can no longer be disabled " "separately.\n"); From 1aefc6b8cbe66e5adb3e6b160f6790171e0a7785 Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Wed, 24 Oct 2012 19:44:05 -0200 Subject: [PATCH 25/28] target-i386: make cpu_x86_fill_host() void The return value of that function is always 0, and is always ignored. Signed-off-by: Eduardo Habkost Signed-off-by: Marcelo Tosatti --- target-i386/cpu.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 4417d6abed..6575834885 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -766,7 +766,7 @@ static int cpu_x86_fill_model_id(char *str) return 0; } -static int cpu_x86_fill_host(x86_def_t *x86_cpu_def) +static void cpu_x86_fill_host(x86_def_t *x86_cpu_def) { uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0; @@ -819,8 +819,6 @@ static int cpu_x86_fill_host(x86_def_t *x86_cpu_def) * unsupported ones later. */ x86_cpu_def->svm_features = -1; - - return 0; } static int unavailable_host_feature(struct model_features_t *f, uint32_t mask) From 6e746f30558cb1331598575918c2a8808be2a75b Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Wed, 24 Oct 2012 19:44:06 -0200 Subject: [PATCH 26/28] target-i386: cpu: make -cpu host/check/enforce code KVM-specific Rationale: * "-cpu host" is available only when using KVM * The current implementation of -cpu check/enforce (check_features_against_host()) makes sense only when using KVM. So this makes the functions check_features_against_host() and cpu_x86_fill_host() KVM-specific, document them as such, and rename them to kvm_check_features_against_host() and kvm_cpu_fill_host(). Signed-off-by: Eduardo Habkost Signed-off-by: Marcelo Tosatti --- target-i386/cpu.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 6575834885..390ed4771d 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -766,10 +766,17 @@ static int cpu_x86_fill_model_id(char *str) return 0; } -static void cpu_x86_fill_host(x86_def_t *x86_cpu_def) +/* Fill a x86_def_t struct with information about the host CPU, and + * the CPU features supported by the host hardware + host kernel + * + * This function may be called only if KVM is enabled. + */ +static void kvm_cpu_fill_host(x86_def_t *x86_cpu_def) { uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0; + assert(kvm_enabled()); + x86_cpu_def->name = "host"; host_cpuid(0x0, 0, &eax, &ebx, &ecx, &edx); x86_cpu_def->level = eax; @@ -784,7 +791,7 @@ static void cpu_x86_fill_host(x86_def_t *x86_cpu_def) x86_cpu_def->ext_features = ecx; x86_cpu_def->features = edx; - if (kvm_enabled() && x86_cpu_def->level >= 7) { + if (x86_cpu_def->level >= 7) { x86_cpu_def->cpuid_7_0_ebx_features = kvm_arch_get_supported_cpuid(kvm_state, 0x7, 0, R_EBX); } else { x86_cpu_def->cpuid_7_0_ebx_features = 0; @@ -839,8 +846,10 @@ static int unavailable_host_feature(struct model_features_t *f, uint32_t mask) /* best effort attempt to inform user requested cpu flags aren't making * their way to the guest. Note: ft[].check_feat ideally should be * specified via a guest_def field to suppress report of extraneous flags. + * + * This function may be called only if KVM is enabled. */ -static int check_features_against_host(x86_def_t *guest_def) +static int kvm_check_features_against_host(x86_def_t *guest_def) { x86_def_t host_def; uint32_t mask; @@ -855,7 +864,9 @@ static int check_features_against_host(x86_def_t *guest_def) {&guest_def->ext3_features, &host_def.ext3_features, ~CPUID_EXT3_SVM, ext3_feature_name, 0x80000001}}; - cpu_x86_fill_host(&host_def); + assert(kvm_enabled()); + + kvm_cpu_fill_host(&host_def); for (rv = 0, i = 0; i < ARRAY_SIZE(ft); ++i) for (mask = 1; mask; mask <<= 1) if (ft[i].check_feat & mask && *ft[i].guest_feat & mask && @@ -1142,7 +1153,7 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model) if (name && !strcmp(name, def->name)) break; if (kvm_enabled() && name && strcmp(name, "host") == 0) { - cpu_x86_fill_host(x86_cpu_def); + kvm_cpu_fill_host(x86_cpu_def); } else if (!def) { goto error; } else { @@ -1280,8 +1291,8 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model) x86_cpu_def->kvm_features &= ~minus_kvm_features; x86_cpu_def->svm_features &= ~minus_svm_features; x86_cpu_def->cpuid_7_0_ebx_features &= ~minus_7_0_ebx_features; - if (check_cpuid) { - if (check_features_against_host(x86_cpu_def) && enforce_cpuid) + if (check_cpuid && kvm_enabled()) { + if (kvm_check_features_against_host(x86_cpu_def) && enforce_cpuid) goto error; } if (x86_cpu_def->cpuid_7_0_ebx_features && x86_cpu_def->level < 7) { From 12869995ea4f436ab76af5059fd2e9ae83c6cf9d Mon Sep 17 00:00:00 2001 From: Eduardo Habkost Date: Wed, 24 Oct 2012 19:44:07 -0200 Subject: [PATCH 27/28] target-i386: kvm_cpu_fill_host: use GET_SUPPORTED_CPUID Change the kvm_cpu_fill_host() function to use kvm_arch_get_supported_cpuid() instead of running the CPUID instruction directly, when checking for supported CPUID features. This should solve two problems at the same time: * "-cpu host" was not enabling features that don't need support on the host CPU (e.g. x2apic); * "check" and "enforce" options were not detecting problems when the host CPU did support a feature, but the KVM kernel code didn't support it. Signed-off-by: Eduardo Habkost Signed-off-by: Marcelo Tosatti --- target-i386/cpu.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 390ed4771d..4c84e9fbc4 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -773,13 +773,13 @@ static int cpu_x86_fill_model_id(char *str) */ static void kvm_cpu_fill_host(x86_def_t *x86_cpu_def) { + KVMState *s = kvm_state; uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0; assert(kvm_enabled()); x86_cpu_def->name = "host"; host_cpuid(0x0, 0, &eax, &ebx, &ecx, &edx); - x86_cpu_def->level = eax; x86_cpu_def->vendor1 = ebx; x86_cpu_def->vendor2 = edx; x86_cpu_def->vendor3 = ecx; @@ -788,21 +788,24 @@ static void kvm_cpu_fill_host(x86_def_t *x86_cpu_def) x86_cpu_def->family = ((eax >> 8) & 0x0F) + ((eax >> 20) & 0xFF); x86_cpu_def->model = ((eax >> 4) & 0x0F) | ((eax & 0xF0000) >> 12); x86_cpu_def->stepping = eax & 0x0F; - x86_cpu_def->ext_features = ecx; - x86_cpu_def->features = edx; + + x86_cpu_def->level = kvm_arch_get_supported_cpuid(s, 0x0, 0, R_EAX); + x86_cpu_def->features = kvm_arch_get_supported_cpuid(s, 0x1, 0, R_EDX); + x86_cpu_def->ext_features = kvm_arch_get_supported_cpuid(s, 0x1, 0, R_ECX); if (x86_cpu_def->level >= 7) { - x86_cpu_def->cpuid_7_0_ebx_features = kvm_arch_get_supported_cpuid(kvm_state, 0x7, 0, R_EBX); + x86_cpu_def->cpuid_7_0_ebx_features = + kvm_arch_get_supported_cpuid(s, 0x7, 0, R_EBX); } else { x86_cpu_def->cpuid_7_0_ebx_features = 0; } - host_cpuid(0x80000000, 0, &eax, &ebx, &ecx, &edx); - x86_cpu_def->xlevel = eax; + x86_cpu_def->xlevel = kvm_arch_get_supported_cpuid(s, 0x80000000, 0, R_EAX); + x86_cpu_def->ext2_features = + kvm_arch_get_supported_cpuid(s, 0x80000001, 0, R_EDX); + x86_cpu_def->ext3_features = + kvm_arch_get_supported_cpuid(s, 0x80000001, 0, R_ECX); - host_cpuid(0x80000001, 0, &eax, &ebx, &ecx, &edx); - x86_cpu_def->ext2_features = edx; - x86_cpu_def->ext3_features = ecx; cpu_x86_fill_model_id(x86_cpu_def->model_id); x86_cpu_def->vendor_override = 0; @@ -811,11 +814,13 @@ static void kvm_cpu_fill_host(x86_def_t *x86_cpu_def) x86_cpu_def->vendor2 == CPUID_VENDOR_VIA_2 && x86_cpu_def->vendor3 == CPUID_VENDOR_VIA_3) { host_cpuid(0xC0000000, 0, &eax, &ebx, &ecx, &edx); + eax = kvm_arch_get_supported_cpuid(s, 0xC0000000, 0, R_EAX); if (eax >= 0xC0000001) { /* Support VIA max extended level */ x86_cpu_def->xlevel2 = eax; host_cpuid(0xC0000001, 0, &eax, &ebx, &ecx, &edx); - x86_cpu_def->ext4_features = edx; + x86_cpu_def->ext4_features = + kvm_arch_get_supported_cpuid(s, 0xC0000001, 0, R_EDX); } } From b55f546eefe79cb6e6b15ebb23f352a736bafc39 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Mon, 22 Oct 2012 12:54:39 +0100 Subject: [PATCH 28/28] update-linux-headers.sh: Handle new kernel uapi/ directories Recent kernels have moved to keeping the userspace headers in uapi/ subdirectories. This breaks the detection of whether an architecture has KVM support in the kernel because kvm.h has moved in the kernel source tree. Update the check to support both the old and new locations. Signed-off-by: Peter Maydell Signed-off-by: Marcelo Tosatti --- scripts/update-linux-headers.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/update-linux-headers.sh b/scripts/update-linux-headers.sh index 67be2efecd..4c7b566fdf 100755 --- a/scripts/update-linux-headers.sh +++ b/scripts/update-linux-headers.sh @@ -34,7 +34,8 @@ ARCHLIST=$(cd "$linux/arch" && echo *) for arch in $ARCHLIST; do # Discard anything which isn't a KVM-supporting architecture - if ! [ -e "$linux/arch/$arch/include/asm/kvm.h" ]; then + if ! [ -e "$linux/arch/$arch/include/asm/kvm.h" ] && + ! [ -e "$linux/arch/$arch/include/uapi/asm/kvm.h" ] ; then continue fi