* [Qemu-devel] [PATCH 0/4] Improve cpuid x86 code. @ 2009-01-29 17:19 Glauber Costa 2009-01-29 17:19 ` [Qemu-devel] [PATCH 1/4] convert cpuid registration to KVM_SET_CPUID2 Glauber Costa 2009-01-30 10:15 ` [Qemu-devel] [PATCH 0/4] Improve cpuid x86 code Amit Shah 0 siblings, 2 replies; 13+ messages in thread From: Glauber Costa @ 2009-01-29 17:19 UTC (permalink / raw) To: qemu-devel; +Cc: aliguori Hey, This is a resend of the cpuid patches, following Anthony's last suggestion. It proved to lead to a much better code IMHO. I'm also using the existing host_cpuid function to mask out features, but now relying on kvm's provided ioctl. This seem to provide the expected behavior. ^ permalink raw reply [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH 1/4] convert cpuid registration to KVM_SET_CPUID2 2009-01-29 17:19 [Qemu-devel] [PATCH 0/4] Improve cpuid x86 code Glauber Costa @ 2009-01-29 17:19 ` Glauber Costa 2009-01-29 17:19 ` [Qemu-devel] [PATCH 2/4] Factor out common code in filling cpuid code Glauber Costa 2009-01-30 10:15 ` [Qemu-devel] [PATCH 0/4] Improve cpuid x86 code Amit Shah 1 sibling, 1 reply; 13+ messages in thread From: Glauber Costa @ 2009-01-29 17:19 UTC (permalink / raw) To: qemu-devel; +Cc: aliguori Use KVM_SET_CPUID2 instead of KVM_SET_CPUID. This will allow us to do registration of cpuid leaves without multiple calls to the kernel in the future. Signed-off-by: Glauber Costa <glommer@redhat.com> --- target-i386/kvm.c | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-) diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 2412ae4..729568c 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -36,8 +36,8 @@ int kvm_arch_init_vcpu(CPUState *env) { struct { - struct kvm_cpuid cpuid; - struct kvm_cpuid_entry entries[100]; + struct kvm_cpuid2 cpuid; + struct kvm_cpuid_entry2 entries[100]; } __attribute__((packed)) cpuid_data; uint32_t limit, i, cpuid_i; uint32_t eax, ebx, ecx, edx; @@ -48,7 +48,7 @@ int kvm_arch_init_vcpu(CPUState *env) limit = eax; for (i = 0; i <= limit; i++) { - struct kvm_cpuid_entry *c = &cpuid_data.entries[cpuid_i++]; + struct kvm_cpuid_entry2 *c = &cpuid_data.entries[cpuid_i++]; cpu_x86_cpuid(env, i, &eax, &ebx, &ecx, &edx); c->function = i; @@ -62,7 +62,7 @@ int kvm_arch_init_vcpu(CPUState *env) limit = eax; for (i = 0x80000000; i <= limit; i++) { - struct kvm_cpuid_entry *c = &cpuid_data.entries[cpuid_i++]; + struct kvm_cpuid_entry2 *c = &cpuid_data.entries[cpuid_i++]; cpu_x86_cpuid(env, i, &eax, &ebx, &ecx, &edx); c->function = i; @@ -74,7 +74,7 @@ int kvm_arch_init_vcpu(CPUState *env) cpuid_data.cpuid.nent = cpuid_i; - return kvm_vcpu_ioctl(env, KVM_SET_CPUID, &cpuid_data); + return kvm_vcpu_ioctl(env, KVM_SET_CPUID2, &cpuid_data); } static int kvm_has_msr_star(CPUState *env) -- 1.5.6.5 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH 2/4] Factor out common code in filling cpuid code 2009-01-29 17:19 ` [Qemu-devel] [PATCH 1/4] convert cpuid registration to KVM_SET_CPUID2 Glauber Costa @ 2009-01-29 17:19 ` Glauber Costa 2009-01-29 17:19 ` [Qemu-devel] [PATCH 3/4] mask out forbidden cpuid features with kvm ioctl Glauber Costa 0 siblings, 1 reply; 13+ messages in thread From: Glauber Costa @ 2009-01-29 17:19 UTC (permalink / raw) To: qemu-devel; +Cc: aliguori Use kvm_fill_cpuid to query qemu for cpuid data. There are two exactly equal instances of this code, and the future introduction of kvm paravirt features will make it three. Signed-off-by: Glauber Costa <glommer@redhat.com> --- target-i386/kvm.c | 46 +++++++++++++++++++++++----------------------- 1 files changed, 23 insertions(+), 23 deletions(-) diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 729568c..64b24db 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -33,22 +33,19 @@ do { } while (0) #endif -int kvm_arch_init_vcpu(CPUState *env) -{ - struct { +typedef struct KVMCpuid { struct kvm_cpuid2 cpuid; struct kvm_cpuid_entry2 entries[100]; - } __attribute__((packed)) cpuid_data; - uint32_t limit, i, cpuid_i; - uint32_t eax, ebx, ecx, edx; +} KVMCpuid; - cpuid_i = 0; - - cpu_x86_cpuid(env, 0, &eax, &ebx, &ecx, &edx); - limit = eax; +static void kvm_fill_cpuid(CPUState *env, KVMCpuid *cpuid_data, + uint32_t start, uint32_t limit) +{ + int i; + uint32_t eax, ebx, ecx, edx; - for (i = 0; i <= limit; i++) { - struct kvm_cpuid_entry2 *c = &cpuid_data.entries[cpuid_i++]; + for (i = start; i <= limit; i++) { + struct kvm_cpuid_entry2 *c = &cpuid_data->entries[cpuid_data->cpuid.nent++]; cpu_x86_cpuid(env, i, &eax, &ebx, &ecx, &edx); c->function = i; @@ -57,22 +54,25 @@ int kvm_arch_init_vcpu(CPUState *env) c->ecx = ecx; c->edx = edx; } +} - cpu_x86_cpuid(env, 0x80000000, &eax, &ebx, &ecx, &edx); +int kvm_arch_init_vcpu(CPUState *env) +{ + KVMCpuid cpuid_data; + uint32_t limit; + uint32_t eax, ebx, ecx, edx; + + cpuid_data.cpuid.nent = 0; + + cpu_x86_cpuid(env, 0, &eax, &ebx, &ecx, &edx); limit = eax; - for (i = 0x80000000; i <= limit; i++) { - struct kvm_cpuid_entry2 *c = &cpuid_data.entries[cpuid_i++]; + kvm_fill_cpuid(env, &cpuid_data, 0, limit); - cpu_x86_cpuid(env, i, &eax, &ebx, &ecx, &edx); - c->function = i; - c->eax = eax; - c->ebx = ebx; - c->ecx = ecx; - c->edx = edx; - } + cpu_x86_cpuid(env, 0x80000000, &eax, &ebx, &ecx, &edx); + limit = eax; - cpuid_data.cpuid.nent = cpuid_i; + kvm_fill_cpuid(env, &cpuid_data, 0x80000000, limit); return kvm_vcpu_ioctl(env, KVM_SET_CPUID2, &cpuid_data); } -- 1.5.6.5 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH 3/4] mask out forbidden cpuid features with kvm ioctl 2009-01-29 17:19 ` [Qemu-devel] [PATCH 2/4] Factor out common code in filling cpuid code Glauber Costa @ 2009-01-29 17:19 ` Glauber Costa 2009-01-29 17:19 ` [Qemu-devel] [PATCH 4/4] kvm pv features PART I Glauber Costa 2009-01-29 20:50 ` [Qemu-devel] Re: [PATCH 3/4] mask out forbidden cpuid features with kvm ioctl Anthony Liguori 0 siblings, 2 replies; 13+ messages in thread From: Glauber Costa @ 2009-01-29 17:19 UTC (permalink / raw) To: qemu-devel; +Cc: aliguori KVM has a (so far unused) ioctl to inform userspace about supported cpuid bits in the current host. The lack of this kind of checking can lead to bugs in which a cpuid bit is exposed but not supported by the host kernel (an example is fedora bug https://bugzilla.redhat.com/show_bug.cgi?id=481274) The current host_cpuid code is replaced by this general check. Signed-off-by: Glauber Costa <glommer@redhat.com> --- target-i386/helper.c | 89 ++++++++++++++++++++++--------------------------- 1 files changed, 40 insertions(+), 49 deletions(-) diff --git a/target-i386/helper.c b/target-i386/helper.c index a28ab93..1410002 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -1370,37 +1370,33 @@ static void breakpoint_handler(CPUState *env) } #endif /* !CONFIG_USER_ONLY */ -static void host_cpuid(uint32_t function, uint32_t *eax, uint32_t *ebx, +static void host_cpuid(CPUState *env, uint32_t function, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) { #if defined(CONFIG_KVM) - uint32_t vec[4]; + static struct { + struct kvm_cpuid2 cpuid; + struct kvm_cpuid_entry2 entries[100]; + } __attribute__((packed)) cpuid_base; + int i; -#ifdef __x86_64__ - asm volatile("cpuid" - : "=a"(vec[0]), "=b"(vec[1]), - "=c"(vec[2]), "=d"(vec[3]) - : "0"(function) : "cc"); -#else - asm volatile("pusha \n\t" - "cpuid \n\t" - "mov %%eax, 0(%1) \n\t" - "mov %%ebx, 4(%1) \n\t" - "mov %%ecx, 8(%1) \n\t" - "mov %%edx, 12(%1) \n\t" - "popa" - : : "a"(function), "S"(vec) - : "memory", "cc"); -#endif + if (cpuid_base.cpuid.nent == 0) { + cpuid_base.cpuid.nent = 100; + kvm_ioctl(env->kvm_state, KVM_GET_SUPPORTED_CPUID, &cpuid_base); + } - if (eax) - *eax = vec[0]; - if (ebx) - *ebx = vec[1]; - if (ecx) - *ecx = vec[2]; - if (edx) - *edx = vec[3]; + for (i = 0; i < cpuid_base.cpuid.nent; i++) { + if (cpuid_base.entries[i].function == function) { + if (eax) + *eax = cpuid_base.entries[i].eax; + if (ebx) + *ebx = cpuid_base.entries[i].ebx; + if (ecx) + *ecx = cpuid_base.entries[i].ecx; + if (edx) + *edx = cpuid_base.entries[i].edx; + } + } #endif } @@ -1429,7 +1425,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, * actuall cpu, and say goodbye to migration between different vendors * is you use compatibility mode. */ if (kvm_enabled()) - host_cpuid(0, NULL, ebx, ecx, edx); + host_cpuid(env, 0, NULL, ebx, ecx, edx); break; case 1: *eax = env->cpuid_version; @@ -1437,9 +1433,18 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, *ecx = env->cpuid_ext_features; *edx = env->cpuid_features; - /* "Hypervisor present" bit required for Microsoft SVVP */ - if (kvm_enabled()) + if (kvm_enabled()) { + uint32_t h_eax; + uint32_t h_ecx = ~0U; + uint32_t h_edx = ~0U; + + host_cpuid(env, 1, &h_eax, NULL, &h_ecx, &h_edx); + + *ecx &= h_ecx; + *edx &= h_edx; + /* "Hypervisor present" bit required for Microsoft SVVP */ *ecx |= (1 << 31); + } break; case 2: /* cache info: needed for Pentium Pro compatibility */ @@ -1519,28 +1524,14 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, *edx = env->cpuid_ext2_features; if (kvm_enabled()) { - uint32_t h_eax, h_edx; - - host_cpuid(0x80000001, &h_eax, NULL, NULL, &h_edx); - - /* disable CPU features that the host does not support */ - - /* long mode */ - if ((h_edx & 0x20000000) == 0 /* || !lm_capable_kernel */) - *edx &= ~0x20000000; - /* syscall */ - if ((h_edx & 0x00000800) == 0) - *edx &= ~0x00000800; - /* nx */ - if ((h_edx & 0x00100000) == 0) - *edx &= ~0x00100000; + uint32_t h_eax; + uint32_t h_ecx = ~0U; + uint32_t h_edx = ~0U; - /* disable CPU features that KVM cannot support */ + host_cpuid(env, 0x80000001, &h_eax, NULL, &h_ecx, &h_edx); - /* svm */ - *ecx &= ~4UL; - /* 3dnow */ - *edx &= ~0xc0000000; + *ecx &= h_ecx; + *edx &= h_edx; } break; case 0x80000002: -- 1.5.6.5 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH 4/4] kvm pv features PART I 2009-01-29 17:19 ` [Qemu-devel] [PATCH 3/4] mask out forbidden cpuid features with kvm ioctl Glauber Costa @ 2009-01-29 17:19 ` Glauber Costa 2009-01-29 19:17 ` Glauber Costa 2009-01-29 20:50 ` [Qemu-devel] Re: [PATCH 3/4] mask out forbidden cpuid features with kvm ioctl Anthony Liguori 1 sibling, 1 reply; 13+ messages in thread From: Glauber Costa @ 2009-01-29 17:19 UTC (permalink / raw) To: qemu-devel; +Cc: aliguori Signed-off-by: Glauber Costa <glommer@redhat.com> --- kvm.h | 5 +++++ target-i386/helper.c | 19 ++++++++++++++++++- target-i386/kvm.c | 30 ++++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 1 deletions(-) diff --git a/kvm.h b/kvm.h index efce145..49a2653 100644 --- a/kvm.h +++ b/kvm.h @@ -17,6 +17,8 @@ #include "config.h" #ifdef CONFIG_KVM +#include <linux/kvm.h> +#include <linux/kvm_para.h> extern int kvm_allowed; #define kvm_enabled() (kvm_allowed) @@ -76,4 +78,7 @@ int kvm_arch_init(KVMState *s, int smp_cpus); int kvm_arch_init_vcpu(CPUState *env); +/* x86 specific */ +uint32_t kvm_get_para_features(CPUState *env); + #endif diff --git a/target-i386/helper.c b/target-i386/helper.c index 1410002..6bcd94d 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -1405,7 +1405,10 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t *ecx, uint32_t *edx) { /* test if maximum index reached */ - if (index & 0x80000000) { + if (index & 0x40000000) { + /* Those are KVM-specific, dodge them without messing with + * exposed cpuid_level */ + } else if (index & 0x80000000) { if (index > env->cpuid_xlevel) index = env->cpuid_level; } else { @@ -1511,6 +1514,20 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, *ecx = 0; *edx = 0; break; + case 0x40000000: + if (kvm_enabled()) { + /* KVM CPUID signature */ + *eax = 0; + *ebx = 0x4b4d564b; /* KVMKVMK */ + *ecx = 0x564b4d56; /* VMKV */ + *edx = 0x0000004d; /* M */ + } + break; + case 0x40000001: + if (kvm_enabled()) { + *eax = kvm_get_para_features(env); + } + break; case 0x80000000: *eax = env->cpuid_xlevel; *ebx = env->cpuid_vendor1; diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 64b24db..c9f0272 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -56,6 +56,36 @@ static void kvm_fill_cpuid(CPUState *env, KVMCpuid *cpuid_data, } } +static struct kvm_para_features { + int cap; + int feature; +} para_features[] = { +#ifdef KVM_CAP_CLOCKSOURCE + { KVM_CAP_CLOCKSOURCE, KVM_FEATURE_CLOCKSOURCE }, +#endif +#ifdef KVM_CAP_NOP_IO_DELAY + { KVM_CAP_NOP_IO_DELAY, KVM_FEATURE_NOP_IO_DELAY }, +#endif +#ifdef KVM_CAP_PV_MMU + { KVM_CAP_PV_MMU, KVM_FEATURE_MMU_OP }, +#endif +#ifdef KVM_CAP_CR3_CACHE + { KVM_CAP_CR3_CACHE, KVM_FEATURE_CR3_CACHE }, +#endif +}; + +uint32_t kvm_get_para_features(CPUState *env) + { + uint32_t i, features = 0; + + for (i = 0; i < ARRAY_SIZE(para_features); i++) { + if (kvm_ioctl(env->kvm_state, KVM_CHECK_EXTENSION, para_features[i].cap)) + features |= (1 << para_features[i].feature); + } + + return features; +} + int kvm_arch_init_vcpu(CPUState *env) { KVMCpuid cpuid_data; -- 1.5.6.5 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH 4/4] kvm pv features PART I 2009-01-29 17:19 ` [Qemu-devel] [PATCH 4/4] kvm pv features PART I Glauber Costa @ 2009-01-29 19:17 ` Glauber Costa 0 siblings, 0 replies; 13+ messages in thread From: Glauber Costa @ 2009-01-29 19:17 UTC (permalink / raw) To: qemu-devel; +Cc: aliguori On Thu, Jan 29, 2009 at 3:19 PM, Glauber Costa <glommer@redhat.com> wrote: > Signed-off-by: Glauber Costa <glommer@redhat.com> Shame on you, what a great changelog entry! This is where temporary becomes definitive by accident ;-) Anthony, let me know if you are okay with this patch, and if so, I'll provide a more meaningful changelog (that would be easy). > --- > kvm.h | 5 +++++ > target-i386/helper.c | 19 ++++++++++++++++++- > target-i386/kvm.c | 30 ++++++++++++++++++++++++++++++ > 3 files changed, 53 insertions(+), 1 deletions(-) > > diff --git a/kvm.h b/kvm.h > index efce145..49a2653 100644 > --- a/kvm.h > +++ b/kvm.h > @@ -17,6 +17,8 @@ > #include "config.h" > > #ifdef CONFIG_KVM > +#include <linux/kvm.h> > +#include <linux/kvm_para.h> > extern int kvm_allowed; > > #define kvm_enabled() (kvm_allowed) > @@ -76,4 +78,7 @@ int kvm_arch_init(KVMState *s, int smp_cpus); > > int kvm_arch_init_vcpu(CPUState *env); > > +/* x86 specific */ > +uint32_t kvm_get_para_features(CPUState *env); > + > #endif > diff --git a/target-i386/helper.c b/target-i386/helper.c > index 1410002..6bcd94d 100644 > --- a/target-i386/helper.c > +++ b/target-i386/helper.c > @@ -1405,7 +1405,10 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, > uint32_t *ecx, uint32_t *edx) > { > /* test if maximum index reached */ > - if (index & 0x80000000) { > + if (index & 0x40000000) { > + /* Those are KVM-specific, dodge them without messing with > + * exposed cpuid_level */ > + } else if (index & 0x80000000) { > if (index > env->cpuid_xlevel) > index = env->cpuid_level; > } else { > @@ -1511,6 +1514,20 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, > *ecx = 0; > *edx = 0; > break; > + case 0x40000000: > + if (kvm_enabled()) { > + /* KVM CPUID signature */ > + *eax = 0; > + *ebx = 0x4b4d564b; /* KVMKVMK */ > + *ecx = 0x564b4d56; /* VMKV */ > + *edx = 0x0000004d; /* M */ > + } > + break; > + case 0x40000001: > + if (kvm_enabled()) { > + *eax = kvm_get_para_features(env); > + } > + break; > case 0x80000000: > *eax = env->cpuid_xlevel; > *ebx = env->cpuid_vendor1; > diff --git a/target-i386/kvm.c b/target-i386/kvm.c > index 64b24db..c9f0272 100644 > --- a/target-i386/kvm.c > +++ b/target-i386/kvm.c > @@ -56,6 +56,36 @@ static void kvm_fill_cpuid(CPUState *env, KVMCpuid *cpuid_data, > } > } > > +static struct kvm_para_features { > + int cap; > + int feature; > +} para_features[] = { > +#ifdef KVM_CAP_CLOCKSOURCE > + { KVM_CAP_CLOCKSOURCE, KVM_FEATURE_CLOCKSOURCE }, > +#endif > +#ifdef KVM_CAP_NOP_IO_DELAY > + { KVM_CAP_NOP_IO_DELAY, KVM_FEATURE_NOP_IO_DELAY }, > +#endif > +#ifdef KVM_CAP_PV_MMU > + { KVM_CAP_PV_MMU, KVM_FEATURE_MMU_OP }, > +#endif > +#ifdef KVM_CAP_CR3_CACHE > + { KVM_CAP_CR3_CACHE, KVM_FEATURE_CR3_CACHE }, > +#endif > +}; > + > +uint32_t kvm_get_para_features(CPUState *env) > + { > + uint32_t i, features = 0; > + > + for (i = 0; i < ARRAY_SIZE(para_features); i++) { > + if (kvm_ioctl(env->kvm_state, KVM_CHECK_EXTENSION, para_features[i].cap)) > + features |= (1 << para_features[i].feature); > + } > + > + return features; > +} > + > int kvm_arch_init_vcpu(CPUState *env) > { > KVMCpuid cpuid_data; > -- > 1.5.6.5 > > > > -- Glauber Costa. "Free as in Freedom" http://glommer.net "The less confident you are, the more serious you have to act." ^ permalink raw reply [flat|nested] 13+ messages in thread
* [Qemu-devel] Re: [PATCH 3/4] mask out forbidden cpuid features with kvm ioctl 2009-01-29 17:19 ` [Qemu-devel] [PATCH 3/4] mask out forbidden cpuid features with kvm ioctl Glauber Costa 2009-01-29 17:19 ` [Qemu-devel] [PATCH 4/4] kvm pv features PART I Glauber Costa @ 2009-01-29 20:50 ` Anthony Liguori 2009-01-30 12:37 ` Glauber Costa ` (2 more replies) 1 sibling, 3 replies; 13+ messages in thread From: Anthony Liguori @ 2009-01-29 20:50 UTC (permalink / raw) To: Glauber Costa; +Cc: qemu-devel Glauber Costa wrote: > KVM has a (so far unused) ioctl to inform userspace > about supported cpuid bits in the current host. > > The lack of this kind of checking can lead to bugs in which > a cpuid bit is exposed but not supported by the host kernel > (an example is fedora bug https://bugzilla.redhat.com/show_bug.cgi?id=481274) > > The current host_cpuid code is replaced by this general check. > > Signed-off-by: Glauber Costa <glommer@redhat.com> > So what do we do about live migration? Does KVM mask a set of bits unconditionally? Before, we were masking unconditionally which should insulate migration reasonable well. Regards, Anthony Liguori > --- > target-i386/helper.c | 89 ++++++++++++++++++++++--------------------------- > 1 files changed, 40 insertions(+), 49 deletions(-) > > diff --git a/target-i386/helper.c b/target-i386/helper.c > index a28ab93..1410002 100644 > --- a/target-i386/helper.c > +++ b/target-i386/helper.c > @@ -1370,37 +1370,33 @@ static void breakpoint_handler(CPUState *env) > } > #endif /* !CONFIG_USER_ONLY */ > > -static void host_cpuid(uint32_t function, uint32_t *eax, uint32_t *ebx, > +static void host_cpuid(CPUState *env, uint32_t function, uint32_t *eax, uint32_t *ebx, > uint32_t *ecx, uint32_t *edx) > { > #if defined(CONFIG_KVM) > - uint32_t vec[4]; > + static struct { > + struct kvm_cpuid2 cpuid; > + struct kvm_cpuid_entry2 entries[100]; > + } __attribute__((packed)) cpuid_base; > + int i; > > -#ifdef __x86_64__ > - asm volatile("cpuid" > - : "=a"(vec[0]), "=b"(vec[1]), > - "=c"(vec[2]), "=d"(vec[3]) > - : "0"(function) : "cc"); > -#else > - asm volatile("pusha \n\t" > - "cpuid \n\t" > - "mov %%eax, 0(%1) \n\t" > - "mov %%ebx, 4(%1) \n\t" > - "mov %%ecx, 8(%1) \n\t" > - "mov %%edx, 12(%1) \n\t" > - "popa" > - : : "a"(function), "S"(vec) > - : "memory", "cc"); > -#endif > + if (cpuid_base.cpuid.nent == 0) { > + cpuid_base.cpuid.nent = 100; > + kvm_ioctl(env->kvm_state, KVM_GET_SUPPORTED_CPUID, &cpuid_base); > + } > > - if (eax) > - *eax = vec[0]; > - if (ebx) > - *ebx = vec[1]; > - if (ecx) > - *ecx = vec[2]; > - if (edx) > - *edx = vec[3]; > + for (i = 0; i < cpuid_base.cpuid.nent; i++) { > + if (cpuid_base.entries[i].function == function) { > + if (eax) > + *eax = cpuid_base.entries[i].eax; > + if (ebx) > + *ebx = cpuid_base.entries[i].ebx; > + if (ecx) > + *ecx = cpuid_base.entries[i].ecx; > + if (edx) > + *edx = cpuid_base.entries[i].edx; > + } > + } > #endif > } > > @@ -1429,7 +1425,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, > * actuall cpu, and say goodbye to migration between different vendors > * is you use compatibility mode. */ > if (kvm_enabled()) > - host_cpuid(0, NULL, ebx, ecx, edx); > + host_cpuid(env, 0, NULL, ebx, ecx, edx); > break; > case 1: > *eax = env->cpuid_version; > @@ -1437,9 +1433,18 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, > *ecx = env->cpuid_ext_features; > *edx = env->cpuid_features; > > - /* "Hypervisor present" bit required for Microsoft SVVP */ > - if (kvm_enabled()) > + if (kvm_enabled()) { > + uint32_t h_eax; > + uint32_t h_ecx = ~0U; > + uint32_t h_edx = ~0U; > + > + host_cpuid(env, 1, &h_eax, NULL, &h_ecx, &h_edx); > + > + *ecx &= h_ecx; > + *edx &= h_edx; > + /* "Hypervisor present" bit required for Microsoft SVVP */ > *ecx |= (1 << 31); > + } > break; > case 2: > /* cache info: needed for Pentium Pro compatibility */ > @@ -1519,28 +1524,14 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, > *edx = env->cpuid_ext2_features; > > if (kvm_enabled()) { > - uint32_t h_eax, h_edx; > - > - host_cpuid(0x80000001, &h_eax, NULL, NULL, &h_edx); > - > - /* disable CPU features that the host does not support */ > - > - /* long mode */ > - if ((h_edx & 0x20000000) == 0 /* || !lm_capable_kernel */) > - *edx &= ~0x20000000; > - /* syscall */ > - if ((h_edx & 0x00000800) == 0) > - *edx &= ~0x00000800; > - /* nx */ > - if ((h_edx & 0x00100000) == 0) > - *edx &= ~0x00100000; > + uint32_t h_eax; > + uint32_t h_ecx = ~0U; > + uint32_t h_edx = ~0U; > > - /* disable CPU features that KVM cannot support */ > + host_cpuid(env, 0x80000001, &h_eax, NULL, &h_ecx, &h_edx); > > - /* svm */ > - *ecx &= ~4UL; > - /* 3dnow */ > - *edx &= ~0xc0000000; > + *ecx &= h_ecx; > + *edx &= h_edx; > } > break; > case 0x80000002: > ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] Re: [PATCH 3/4] mask out forbidden cpuid features with kvm ioctl 2009-01-29 20:50 ` [Qemu-devel] Re: [PATCH 3/4] mask out forbidden cpuid features with kvm ioctl Anthony Liguori @ 2009-01-30 12:37 ` Glauber Costa 2009-02-03 21:25 ` Avi Kivity 2009-02-03 21:27 ` Avi Kivity 2 siblings, 0 replies; 13+ messages in thread From: Glauber Costa @ 2009-01-30 12:37 UTC (permalink / raw) To: qemu-devel; +Cc: Glauber Costa, Anthony Liguori On Thu, Jan 29, 2009 at 6:50 PM, Anthony Liguori <aliguori@us.ibm.com> wrote: > Glauber Costa wrote: >> >> KVM has a (so far unused) ioctl to inform userspace >> about supported cpuid bits in the current host. >> >> The lack of this kind of checking can lead to bugs in which >> a cpuid bit is exposed but not supported by the host kernel >> (an example is fedora bug >> https://bugzilla.redhat.com/show_bug.cgi?id=481274) >> >> The current host_cpuid code is replaced by this general check. >> >> Signed-off-by: Glauber Costa <glommer@redhat.com> >> > > So what do we do about live migration? Does KVM mask a set of bits > unconditionally? Before, we were masking unconditionally which should > insulate migration reasonable well. > Just to be clear: Are you raising the flag against the lack of unconditional mask only, or about it + querying kvm.ko for supported bits? I think we need to query it anyway, because calling cpuid will only give you information about your cpu, and querying the kernel will give you this, plus information about what the kernel supports (think of the 32 bit kernel on 64 bit hardware case), plus whatever else kvm wants to mask for whatever reason. About migration, I was under the impression that the solution we were going towards was based on defining a kvm machine type that would contain a common set of features among the hosts involved. If this is the case, I believe we don't need to unconditionally mask out anything, since the features we expose in the machine type won't even have the problematic features. If this is not the case, I'm fine with redoing this patch with querying kvm.ko + unconditional mask of potentially problematic features. -- Glauber Costa. "Free as in Freedom" http://glommer.net "The less confident you are, the more serious you have to act." ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] Re: [PATCH 3/4] mask out forbidden cpuid features with kvm ioctl 2009-01-29 20:50 ` [Qemu-devel] Re: [PATCH 3/4] mask out forbidden cpuid features with kvm ioctl Anthony Liguori 2009-01-30 12:37 ` Glauber Costa @ 2009-02-03 21:25 ` Avi Kivity 2009-02-04 6:26 ` Amit Shah 2009-02-03 21:27 ` Avi Kivity 2 siblings, 1 reply; 13+ messages in thread From: Avi Kivity @ 2009-02-03 21:25 UTC (permalink / raw) To: qemu-devel; +Cc: Glauber Costa Anthony Liguori wrote: > Glauber Costa wrote: >> KVM has a (so far unused) ioctl to inform userspace >> about supported cpuid bits in the current host. >> >> The lack of this kind of checking can lead to bugs in which >> a cpuid bit is exposed but not supported by the host kernel >> (an example is fedora bug >> https://bugzilla.redhat.com/show_bug.cgi?id=481274) >> >> The current host_cpuid code is replaced by this general check. >> >> Signed-off-by: Glauber Costa <glommer@redhat.com> >> > > So what do we do about live migration? We need a way to completely specify cpuid from the command line. The management utility would figure out what is supported (driven by both cpu capabilities and installed kvm capabilities) and fgure out a greatest common denominator, or something. > Does KVM mask a set of bits unconditionally? The kernel doesn't touch cpuid (except nx due to an historical mistake). > Before, we were masking unconditionally which should insulate > migration reasonable well. That suits migration, but not other uses of qemu. -- I have a truly marvellous patch that fixes the bug which this signature is too narrow to contain. ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] Re: [PATCH 3/4] mask out forbidden cpuid features with kvm ioctl 2009-02-03 21:25 ` Avi Kivity @ 2009-02-04 6:26 ` Amit Shah 0 siblings, 0 replies; 13+ messages in thread From: Amit Shah @ 2009-02-04 6:26 UTC (permalink / raw) To: qemu-devel; +Cc: Glauber Costa, avi On (Tue) Feb 03 2009 [23:25:47], Avi Kivity wrote: > Anthony Liguori wrote: >> Glauber Costa wrote: >>> KVM has a (so far unused) ioctl to inform userspace >>> about supported cpuid bits in the current host. >>> >>> The lack of this kind of checking can lead to bugs in which >>> a cpuid bit is exposed but not supported by the host kernel >>> (an example is fedora bug >>> https://bugzilla.redhat.com/show_bug.cgi?id=481274) >>> >>> The current host_cpuid code is replaced by this general check. >>> >>> Signed-off-by: Glauber Costa <glommer@redhat.com> >>> >> >> So what do we do about live migration? > > We need a way to completely specify cpuid from the command line. The > management utility would figure out what is supported (driven by both > cpu capabilities and installed kvm capabilities) and fgure out a > greatest common denominator, or something. I had proposed this a few days ago, pasted below: http://thread.gmane.org/gmane.comp.emulators.qemu/37134/focus=37306 --- What I'm thinking of is moving all the CPU definitions out from helper.c into $(PREFIX)/usr/share/qemu/cpu-defs/... with one file holding one definition, like $ cat core2duo.def model= 15 family = 16 stepping = 11 level = 10 . . . Adding a new def then just becomes a matter of submitting a text file for inclusion and doesn't need any recompilation. Also, there are many details not captured in a CPU def, like the cache sizes and types. They're hard-coded for all the CPUs in the cpuid helper function. So we could have those values too incorporated in the CPU def file an fall back to the defaults when not available. When we do get some kind of a machine FDT, we can specify the cpu type by either pointing to one of these files or by constructing a new CPU type by specifying individual values. --- I have a patch that adds some of this functionality to the command line. It needs cleaning up, but shows the general idea that I'm progressing in. It takes as input a file from which to read the cpuid definitions. The cpuid defs could be straight from a host or from a management application that has computed the "greatest common denominator": diff --git a/qemu/target-i386/cpu.h b/qemu/target-i386/cpu.h index 944e386..98dc4d0 100644 --- a/qemu/target-i386/cpu.h +++ b/qemu/target-i386/cpu.h @@ -643,6 +643,12 @@ typedef struct CPUX86State { int mp_state; } CPUX86State; +struct KMScpuid { + uint32_t function, eax, ebx, ecx, edx; +}; +extern struct KMScpuid *kms_cpuids; +extern uint32_t kms_leaves; + CPUX86State *cpu_x86_init(const char *cpu_model); int cpu_x86_exec(CPUX86State *s); void cpu_x86_close(CPUX86State *s); diff --git a/qemu/target-i386/helper.c b/qemu/target-i386/helper.c index cda0390..33aed77 100644 --- a/qemu/target-i386/helper.c +++ b/qemu/target-i386/helper.c @@ -264,8 +264,15 @@ static x86_def_t x86_defs[] = { .xlevel = 0x8000000A, .model_id = "Intel(R) Atom(TM) CPU N270 @ 1.60GHz", }, + { + .name = "migrate-safe", + }, }; +u_int32_t kms_leaves; +struct KMScpuid *kms_cpuids; +static char kms_file_path[100]; + static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model) { unsigned int i; @@ -338,6 +345,8 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model) } else if (!strcmp(featurestr, "model_id")) { pstrcpy(x86_cpu_def->model_id, sizeof(x86_cpu_def->model_id), val); + } else if (!strncmp(featurestr, "cpuids", 6)) { + pstrcpy(kms_file_path, sizeof(kms_file_path), val); } else { fprintf(stderr, "unrecognized feature %s\n", featurestr); goto error; @@ -356,6 +365,7 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model) x86_cpu_def->ext_features &= ~minus_ext_features; x86_cpu_def->ext2_features &= ~minus_ext2_features; x86_cpu_def->ext3_features &= ~minus_ext3_features; + free(s); return 0; @@ -372,12 +382,74 @@ void x86_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...)) (*cpu_fprintf)(f, "x86 %16s\n", x86_defs[i].name); } +static int get_cpuids(x86_def_t *def) +{ + int leaves, i, r; + struct KMScpuid cpuid_line; + FILE *kms_fp; + + kms_fp = fopen(kms_file_path, "r"); + if (!kms_fp) { + fprintf(stderr, "Can't find cpuid file\n"); + return -1; + } + fscanf(kms_fp, "%08x %08x %08x %08x %08x\n", + &cpuid_line.function, &cpuid_line.eax, &cpuid_line.ebx, + &cpuid_line.ecx, &cpuid_line.edx); + + def->level = cpuid_line.eax; + leaves = cpuid_line.eax + 1; + r = fseek(kms_fp, 45 * (leaves - 1), SEEK_CUR); + if (r < 0) { + fprintf(stderr, "Error reading cpuid input, %s\n", strerror(errno)); + return -1; + } + fscanf(kms_fp, "%08x %08x %08x %08x %08x\n", + &cpuid_line.function, &cpuid_line.eax, &cpuid_line.ebx, + &cpuid_line.ecx, &cpuid_line.edx); + + if (cpuid_line.function == 0x80000000) { + leaves += cpuid_line.eax - 0x80000000 + 1; + def->xlevel = cpuid_line.eax; + } + kms_cpuids = malloc(sizeof(struct KMScpuid)*leaves); + if (!kms_cpuids) { + fprintf(stderr, "Not enough memory allocating leaves\n"); + return -1; + } + rewind(kms_fp); + kms_leaves = leaves; + for (i = 0; i < leaves; i++) { + r = fscanf(kms_fp, "%08x %08x %08x %08x %08x\n", + &kms_cpuids[i].function, + &kms_cpuids[i].eax, &kms_cpuids[i].ebx, + &kms_cpuids[i].ecx, &kms_cpuids[i].edx); + if (r == EOF) + break; + } + fclose(kms_fp); + return 0; +} + static int cpu_x86_register (CPUX86State *env, const char *cpu_model) { x86_def_t def1, *def = &def1; if (cpu_x86_find_by_name(def, cpu_model) < 0) return -1; + if (!strncmp(cpu_model, "migrate-safe", 12)) { + if (get_cpuids(def) < 0) + return -1; + + def->vendor1 = kms_cpuids[0].ebx; + def->vendor2 = kms_cpuids[0].edx; + def->vendor3 = kms_cpuids[0].ecx; + + def->features = kms_cpuids[1].edx; + def->ext_features = kms_cpuids[1].ecx; + def->ext2_features = kms_cpuids[def->level + 2].edx; + def->ext3_features = kms_cpuids[def->level + 2].ecx; + } if (def->vendor1) { env->cpuid_vendor1 = def->vendor1; env->cpuid_vendor2 = def->vendor2; @@ -388,19 +460,25 @@ static int cpu_x86_register (CPUX86State *env, const char *cpu_model) env->cpuid_vendor3 = CPUID_VENDOR_INTEL_3; } env->cpuid_level = def->level; - if (def->family > 0x0f) - env->cpuid_version = 0xf00 | ((def->family - 0x0f) << 20); - else - env->cpuid_version = def->family << 8; - env->cpuid_version |= ((def->model & 0xf) << 4) | ((def->model >> 4) << 16); - env->cpuid_version |= def->stepping; + if (!kms_leaves) { + if (def->family > 0x0f) + env->cpuid_version = 0xf00 | ((def->family - 0x0f) << 20); + else + env->cpuid_version = def->family << 8; + env->cpuid_version |= + ((def->model & 0xf) << 4) | ((def->model >> 4) << 16); + env->cpuid_version |= def->stepping; + } else + env->cpuid_version = kms_cpuids[1].eax; + env->cpuid_features = def->features; env->pat = 0x0007040600070406ULL; env->cpuid_ext_features = def->ext_features; env->cpuid_ext2_features = def->ext2_features; env->cpuid_xlevel = def->xlevel; env->cpuid_ext3_features = def->ext3_features; - { + + if (!kms_leaves) { const char *model_id = def->model_id; int c, len, i; @@ -416,6 +494,16 @@ static int cpu_x86_register (CPUX86State *env, const char *cpu_model) c = (uint8_t)model_id[i]; env->cpuid_model[i >> 2] |= c << (8 * (i & 3)); } + } else { + uint32_t i; + + /* Leaves 0x80000002 - 0x80000004 store the model information */ + for (i = 0; i < 3; i++) { + env->cpuid_model[i * 4 + 0] = kms_cpuids[def->level + 3 + i].eax; + env->cpuid_model[i * 4 + 1] = kms_cpuids[def->level + 3 + i].ebx; + env->cpuid_model[i * 4 + 2] = kms_cpuids[def->level + 3 + i].ecx; + env->cpuid_model[i * 4 + 3] = kms_cpuids[def->level + 3 + i].edx; + } } return 0; } @@ -1383,6 +1471,21 @@ static void host_cpuid(uint32_t function, uint32_t *eax, uint32_t *ebx, #if defined(CONFIG_KVM) || defined(USE_KVM) uint32_t vec[4]; + if (kms_leaves) { + /* We're using a migrate-safe CPU type */ + int i; + + for (i = 0; i <= function && i < kms_leaves; i++) { + if (kms_cpuids[i].function == function) { + vec[0] = kms_cpuids[i].eax; + vec[1] = kms_cpuids[i].ebx; + vec[2] = kms_cpuids[i].ecx; + vec[3] = kms_cpuids[i].edx; + break; + } + } + } else { + #ifdef __x86_64__ asm volatile("cpuid" : "=a"(vec[0]), "=b"(vec[1]), @@ -1399,6 +1502,7 @@ static void host_cpuid(uint32_t function, uint32_t *eax, uint32_t *ebx, : : "a"(function), "S"(vec) : "memory", "cc"); #endif + } if (eax) *eax = vec[0]; @@ -1435,7 +1539,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, * isn't supported in compatibility mode on Intel. so advertise the * actuall cpu, and say goodbye to migration between different vendors * is you use compatibility mode. */ - if (kvm_enabled()) + if (!kms_leaves && kvm_enabled()) host_cpuid(0, NULL, ebx, ecx, edx); break; case 1: @@ -1528,19 +1632,21 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, if (kvm_enabled()) { uint32_t h_eax, h_edx; - host_cpuid(0x80000001, &h_eax, NULL, NULL, &h_edx); + if (!kms_leaves) { + host_cpuid(0x80000001, &h_eax, NULL, NULL, &h_edx); - /* disable CPU features that the host does not support */ + /* disable CPU features that the host does not support */ - /* long mode */ - if ((h_edx & 0x20000000) == 0 /* || !lm_capable_kernel */) - *edx &= ~0x20000000; - /* syscall */ - if ((h_edx & 0x00000800) == 0) - *edx &= ~0x00000800; - /* nx */ - if ((h_edx & 0x00100000) == 0) - *edx &= ~0x00100000; + /* long mode */ + if ((h_edx & 0x20000000) == 0 /* || !lm_capable_kernel */) + *edx &= ~0x20000000; + /* syscall */ + if ((h_edx & 0x00000800) == 0) + *edx &= ~0x00000800; + /* nx */ + if ((h_edx & 0x00100000) == 0) + *edx &= ~0x00100000; + } /* disable CPU features that KVM cannot support */ ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] Re: [PATCH 3/4] mask out forbidden cpuid features with kvm ioctl 2009-01-29 20:50 ` [Qemu-devel] Re: [PATCH 3/4] mask out forbidden cpuid features with kvm ioctl Anthony Liguori 2009-01-30 12:37 ` Glauber Costa 2009-02-03 21:25 ` Avi Kivity @ 2009-02-03 21:27 ` Avi Kivity 2009-02-03 21:36 ` Anthony Liguori 2 siblings, 1 reply; 13+ messages in thread From: Avi Kivity @ 2009-02-03 21:27 UTC (permalink / raw) To: qemu-devel; +Cc: Glauber Costa Anthony Liguori wrote: > Glauber Costa wrote: >> KVM has a (so far unused) ioctl to inform userspace >> about supported cpuid bits in the current host. >> >> The lack of this kind of checking can lead to bugs in which >> a cpuid bit is exposed but not supported by the host kernel >> (an example is fedora bug >> https://bugzilla.redhat.com/show_bug.cgi?id=481274) >> >> The current host_cpuid code is replaced by this general check. >> >> Signed-off-by: Glauber Costa <glommer@redhat.com> >> > > So what do we do about live migration? We need a way to completely specify cpuid from the command line. The management utility would figure out what is supported (driven by both cpu capabilities and installed kvm capabilities) and fgure out a greatest common denominator, or something. > Does KVM mask a set of bits unconditionally? The kernel doesn't touch cpuid (except nx due to an historical mistake). > Before, we were masking unconditionally which should insulate > migration reasonable well. That suits migration, but not other uses of qemu. -- I have a truly marvellous patch that fixes the bug which this signature is too narrow to contain. ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] Re: [PATCH 3/4] mask out forbidden cpuid features with kvm ioctl 2009-02-03 21:27 ` Avi Kivity @ 2009-02-03 21:36 ` Anthony Liguori 0 siblings, 0 replies; 13+ messages in thread From: Anthony Liguori @ 2009-02-03 21:36 UTC (permalink / raw) To: qemu-devel; +Cc: Glauber Costa Avi Kivity wrote: > Anthony Liguori wrote: >> Glauber Costa wrote: >>> KVM has a (so far unused) ioctl to inform userspace >>> about supported cpuid bits in the current host. >>> >>> The lack of this kind of checking can lead to bugs in which >>> a cpuid bit is exposed but not supported by the host kernel >>> (an example is fedora bug >>> https://bugzilla.redhat.com/show_bug.cgi?id=481274) >>> >>> The current host_cpuid code is replaced by this general check. >>> >>> Signed-off-by: Glauber Costa <glommer@redhat.com> >>> >> >> So what do we do about live migration? > > We need a way to completely specify cpuid from the command line. The > management utility would figure out what is supported (driven by both > cpu capabilities and installed kvm capabilities) and fgure out a > greatest common denominator, or something. What is the default case? Pass everything through or pick a reasonable small, constant subset? That is, is -cpuid a union or an intersection. Regards, Anthony Liguori >> Does KVM mask a set of bits unconditionally? > > The kernel doesn't touch cpuid (except nx due to an historical mistake). > >> Before, we were masking unconditionally which should insulate >> migration reasonable well. > > That suits migration, but not other uses of qemu. > ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH 0/4] Improve cpuid x86 code. 2009-01-29 17:19 [Qemu-devel] [PATCH 0/4] Improve cpuid x86 code Glauber Costa 2009-01-29 17:19 ` [Qemu-devel] [PATCH 1/4] convert cpuid registration to KVM_SET_CPUID2 Glauber Costa @ 2009-01-30 10:15 ` Amit Shah 1 sibling, 0 replies; 13+ messages in thread From: Amit Shah @ 2009-01-30 10:15 UTC (permalink / raw) To: qemu-devel; +Cc: aliguori On (Thu) Jan 29 2009 [12:19:25], Glauber Costa wrote: > Hey, > > This is a resend of the cpuid patches, following Anthony's last > suggestion. It proved to lead to a much better code IMHO. > > I'm also using the existing host_cpuid function to mask out features, > but now relying on kvm's provided ioctl. This seem to provide the expected > behavior. I had submitted patches previously to convert to get_cpuid2. If Anthony has them in his queue, we're going to have clashes. My patches add full support for cupid functions 4, 0xb and 0xd that's missing currently. I also have a patch ready for function 2; guess I'll send them after this stuff is in. ^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2009-02-04 6:25 UTC | newest] Thread overview: 13+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2009-01-29 17:19 [Qemu-devel] [PATCH 0/4] Improve cpuid x86 code Glauber Costa 2009-01-29 17:19 ` [Qemu-devel] [PATCH 1/4] convert cpuid registration to KVM_SET_CPUID2 Glauber Costa 2009-01-29 17:19 ` [Qemu-devel] [PATCH 2/4] Factor out common code in filling cpuid code Glauber Costa 2009-01-29 17:19 ` [Qemu-devel] [PATCH 3/4] mask out forbidden cpuid features with kvm ioctl Glauber Costa 2009-01-29 17:19 ` [Qemu-devel] [PATCH 4/4] kvm pv features PART I Glauber Costa 2009-01-29 19:17 ` Glauber Costa 2009-01-29 20:50 ` [Qemu-devel] Re: [PATCH 3/4] mask out forbidden cpuid features with kvm ioctl Anthony Liguori 2009-01-30 12:37 ` Glauber Costa 2009-02-03 21:25 ` Avi Kivity 2009-02-04 6:26 ` Amit Shah 2009-02-03 21:27 ` Avi Kivity 2009-02-03 21:36 ` Anthony Liguori 2009-01-30 10:15 ` [Qemu-devel] [PATCH 0/4] Improve cpuid x86 code Amit Shah
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).