qemu-kvm.git uq/master queue
The following changes since commit adc56dda0c4eed62149d28939b7d7e329ad95ae8:
migration: move some declarations to migration.h (2011-04-15 20:14:54 +0000)
are available in the git repository at:
git://git.kernel.org/pub/scm/virt/kvm/qemu-kvm.git uq/master
Glauber Costa (3):
kvm: use kernel-provided para_features instead of statically coming up with new capabilities
kvm: add kvmclock to its second bit
kvm: create kvmclock when one of the flags are present
Jan Kiszka (3):
Break up user and system cpu_interrupt implementations Redirect cpu_interrupt to callback handler
kvm: Install specialized interrupt handler
cpu-all.h | 14 ++++++++- exec.c | 18 ++++++++--- hw/kvmclock.c | 6 +++- kvm-all.c | 11 +++++++ target-i386/cpuid.c | 3 +- target-i386/kvm.c | 78 ++++++++++++++++++++++++++++++++------------------- 6 files changed, 92 insertions(+), 38 deletions(-)
PATCH 1/6 kvm: use kernel-provided para_features instead of statically coming up with new capabilities
From: Glauber Costa <[email protected]>
Use the features provided by KVM_GET_SUPPORTED_CPUID directly to mask out features from guest-visible cpuid.
The old get_para_features() mechanism is kept for older kernels that do not implement it.
--- target-i386/kvm.c | 78 +++++++++++++++++++++++++++++++++------------------- 1 files changed, 49 insertions(+), 29 deletions(-)
target-i386/kvm.c +49 -29
@@ -92,6 +92,35 @@ static struct kvm_cpuid2 *try_get_cpuid(KVMState *s, int max)return cpuid; } +#ifdef CONFIG_KVM_PARA +struct kvm_para_features { +int cap; +int feature; +} para_features[] = { + {KVM_CAP_CLOCKSOURCE ,KVM_FEATURE_CLOCKSOURCE }, + {KVM_CAP_NOP_IO_DELAY ,KVM_FEATURE_NOP_IO_DELAY }, + {KVM_CAP_PV_MMU ,KVM_FEATURE_MMU_OP }, +#ifdef KVM_CAP_ASYNC_PF + {KVM_CAP_ASYNC_PF ,KVM_FEATURE_ASYNC_PF }, +#endif + {-1 ,-1 } +}; + +static int get_para_features (CPUState *env) +{ +int i, features =0 ; + +for (i =0 ; i <ARRAY_SIZE (para_features) -1 ; i++) { +if (kvm_check_extension (env->kvm_state, para_features[i].cap)) { + features |= (1 << para_features[i].feature); + } + } + +return features; +} +#endif + +uint32_t kvm_arch_get_supported_cpuid (CPUState *env,uint32_t function,uint32_t index,int reg) {
@@ -99,6 +128,9 @@ uint32_t kvm_arch_get_supported_cpuid(CPUState *env, uint32_t function,int i, max;uint32_t ret =0 ;uint32_t cpuid_1_edx; +#ifdef CONFIG_KVM_PARA +int has_kvm_features =0 ; +#endif max =1 ;while ((cpuid =try_get_cpuid (env->kvm_state, max)) ==NULL ) {
@@ -108,6 +140,11 @@ uint32_t kvm_arch_get_supported_cpuid(CPUState *env, uint32_t function,for (i =0 ; i < cpuid->nent; ++i) {if (cpuid->entries[i].function == function && cpuid->entries[i].index == index) { +#ifdef CONFIG_KVM_PARA +if (cpuid->entries[i].function ==KVM_CPUID_FEATURES ) { + has_kvm_features =1 ; + } +#endif switch (reg) {case R_EAX : ret = cpuid->entries[i].eax;
@@ -140,38 +177,15 @@ uint32_t kvm_arch_get_supported_cpuid(CPUState *env, uint32_t function,qemu_free (cpuid); -return ret; -} -#ifdef CONFIG_KVM_PARA -struct kvm_para_features { -int cap; -int feature; -} para_features[] = { - {KVM_CAP_CLOCKSOURCE ,KVM_FEATURE_CLOCKSOURCE }, - {KVM_CAP_NOP_IO_DELAY ,KVM_FEATURE_NOP_IO_DELAY }, - {KVM_CAP_PV_MMU ,KVM_FEATURE_MMU_OP }, -#ifdef KVM_CAP_ASYNC_PF - {KVM_CAP_ASYNC_PF ,KVM_FEATURE_ASYNC_PF }, -#endif - {-1 ,-1 } -}; - -static int get_para_features (CPUState *env) -{ -int i, features =0 ; - -for (i =0 ; i <ARRAY_SIZE (para_features) -1 ; i++) { -if (kvm_check_extension (env->kvm_state, para_features[i].cap)) { - features |= (1 << para_features[i].feature); - } +/* fallback for older kernels */ +if (!has_kvm_features && (function ==KVM_CPUID_FEATURES )) { + ret =get_para_features (env); } -#ifdef KVM_CAP_ASYNC_PF - has_msr_async_pf_en = features & (1 <<KVM_FEATURE_ASYNC_PF );#endif -return features; + +return ret; } -#endif /* CONFIG_KVM_PARA */ typedef struct HWPoisonPage { ram_addr_t ram_addr;
@@ -397,7 +411,13 @@ int kvm_arch_init_vcpu(CPUState *env) c = &cpuid_data.entries[cpuid_i++];memset (c,0 ,sizeof (*c)); c->function =KVM_CPUID_FEATURES ; - c->eax = env->cpuid_kvm_features &get_para_features (env); + c->eax = env->cpuid_kvm_features &kvm_arch_get_supported_cpuid (env, +KVM_CPUID_FEATURES ,0 ,R_EAX ); + +#ifdef KVM_CAP_ASYNC_PF + has_msr_async_pf_en = c->eax & (1 <<KVM_FEATURE_ASYNC_PF ); +#endif +#endif cpu_x86_cpuid (env,0 ,0 , &limit, &unused, &unused, &unused);
Signature · 1 line
1.7.4.2
PATCH 2/6 kvm: add kvmclock to its second bit
In reply to Marcelo TosattiFrom: Glauber Costa <[email protected]>
We have two bits that can represent kvmclock in cpuid.
They signal the guest which msr set to use. When we tweak flags involving this value - specially when we use "-", we have to act on both.
Besides adding it to the kvm features list, we also have to "break" the assumption represented by the break in lookup_feature.
--- target-i386/cpuid.c | 3 +-- 1 files changed, 1 insertions(+), 2 deletions(-)
target-i386/cpuid.c +1 -2
@@ -73,7 +73,7 @@ static const char *ext3_feature_name[] = { };static const char *kvm_feature_name[] = { -"kvmclock" ,"kvm_nopiodelay" ,"kvm_mmu" ,NULL ,"kvm_asyncpf" ,NULL ,NULL ,NULL , +"kvmclock" ,"kvm_nopiodelay" ,"kvm_mmu" ,"kvmclock" ,"kvm_asyncpf" ,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 ,NULL ,NULL ,
@@ -193,7 +193,6 @@ static int lookup_feature(uint32_t *pval, const char *s, const char *e,for (mask =1 , ppc = featureset; mask; mask <<=1 , ++ppc)if (*ppc && !altcmp (s, e, *ppc)) { *pval |= mask; -break ; }return (mask ?1 :0 ); }
Signature · 1 line
1.7.4.2
Re: [PATCH 2/6] kvm: add kvmclock to its second bit
Quoted 29 lines · Marcelo Tosatti
From: Glauber Costa <[email protected]>
We have two bits that can represent kvmclock in cpuid.
They signal the guest which msr set to use. When we tweak flags involving this value - specially when we use "-", we have to act on both.Besides adding it to the kvm features list, we also have to "break" the assumption represented by the break in
lookup_feature.Signed-off-by Glauber Costa <[email protected]>Signed-off-by Avi Kivity <[email protected]>--- target-i386/cpuid.c | 3 +-- 1 files changed, 1 insertions(+), 2 deletions(-)target-i386/cpuid.c +1
-1@@ -73,7 +73,7 @@ static const char *ext3_feature_name[] = { };static const char *kvm_feature_name[] = { -"kvmclock" ,"kvm_nopiodelay" ,"kvm_mmu" ,NULL ,"kvm_asyncpf" ,NULL ,NULL ,NULL , +"kvmclock" ,"kvm_nopiodelay" ,"kvm_mmu" ,"kvmclock" ,"kvm_asyncpf" ,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 ,NULL ,NULL ,
target-i386/cpuid.c static int lookup_feature(uint32_t *pval, const char *s, const char *e, · line 198
Quoted 7 lines
target-i386/cpuid.c +0
-1@@ -193,7 +193,6 @@ static int lookup_feature(uint32_t *pval, const char *s, const char *e,for (mask =1 , ppc = featureset; mask; mask <<=1 , ++ppc)if (*ppc && !altcmp (s, e, *ppc)) { *pval |= mask; -break ; }return (mask ?1 :0 ); }
This is required on top to fix the issues Anthony was seeing:
target-i386/cpuid.c +3 -1
@@ -189,12 +189,14 @@ static int lookup_feature(uint32_t *pval, const char *s, const char *e, {uint32_t mask;const char **ppc; +int found =0 ;for (mask =1 , ppc = featureset; mask; mask <<=1 , ++ppc)if (*ppc && !altcmp (s, e, *ppc)) { *pval |= mask; + found =1 ; } -return (mask ?1 :0 ); +return found; } static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features,
PATCH v2 1/1 x86: Allow multiple cpu feature matches of lookup_feature
kvmclock is represented by two feature bits. Therefore, lookup_feature needs to continue its search even after the first match. Enhance it accordingly and switch to a bool return type at this chance.
--- target-i386/cpuid.c | 14 ++++++++------ 1 files changed, 8 insertions(+), 6 deletions(-)
Glauber, could you check/ack this? Marcelo, please respin the series afterward. I'd like to see all bits upstream and merged back into qemu-kvm to proceed with switching the latter to upstream's kvm infrastructure.
target-i386/cpuid.c +8 -6
@@ -182,20 +182,22 @@ static int altcmp(const char *s, const char *e, const char *altstr) }/* search featureset for flag *[s..e), if found set corresponding bit in -* *pval and return success, otherwise return zero +* *pval and return true, otherwise return false */ -static int lookup_feature (uint32_t *pval,const char *s,const char *e, -const char **featureset) +static bool lookup_feature (uint32_t *pval,const char *s,const char *e, +const char **featureset) {uint32_t mask;const char **ppc; +bool found = false; -for (mask =1 , ppc = featureset; mask; mask <<=1 , ++ppc) +for (mask =1 , ppc = featureset; mask; mask <<=1 , ++ppc) {if (*ppc && !altcmp (s, e, *ppc)) { *pval |= mask; -break ; + found = true; } -return (mask ?1 :0 ); + } +return found; } static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features,
Signature · 1 line
1.7.1
Re: [PATCH v2 2a/6] x86: Allow multiple cpu feature matches of lookup_feature
Quoted 5 lines · Jan Kiszka
kvmclock is represented by two feature bits. Therefore,
lookup_featureneeds to continue its search even after the first match. Enhance it accordingly and switch to a bool return type at this chance.Signed-off-by Jan Kiszka <[email protected]>
Quoted 8 lines
--- target-i386/cpuid.c | 14 ++++++++------ 1 files changed, 8 insertions(+), 6 deletions(-)Glauber, could you check/ack this? Marcelo, please respin the series afterward. I'd like to see all bits upstream and merged back into qemu-kvm to proceed with switching the latter to upstream's kvm infrastructure.
Yes, this patch is okay.
Actually, I did sent out something like this, maybe Marcelo applied only part of the series?
Anyway, Jan's version is handy, please apply it.
Quoted 33 lines
target-i386/cpuid.c +8
-6@@ -182,20 +182,22 @@ static int altcmp(const char *s, const char *e, const char *altstr) }/* search featureset for flag *[s..e), if found set corresponding bit in -* *pval and return success, otherwise return zero +* *pval and return true, otherwise return false */ -static int lookup_feature (uint32_t *pval,const char *s,const char *e, -const char **featureset) +static bool lookup_feature (uint32_t *pval,const char *s,const char *e, +const char **featureset) {uint32_t mask;const char **ppc; +bool found = false; -for (mask =1 , ppc = featureset; mask; mask <<=1 , ++ppc) +for (mask =1 , ppc = featureset; mask; mask <<=1 , ++ppc) {if (*ppc && !altcmp (s, e, *ppc)) { *pval |= mask; -break ; + found = true; } -return (mask ?1 :0 ); + } +return found; } static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features,
PATCH v2 1/1 kvm: add kvmclock to its second bit
In reply to Jan KiszkaFrom: Glauber Costa <[email protected]>
We have two bits that can represent kvmclock in cpuid. They signal the guest which msr set to use. When we tweak flags involving this value - specially when we use "-", we have to act on both.
--- target-i386/cpuid.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
target-i386/cpuid.c +1 -1
@@ -73,7 +73,7 @@ static const char *ext3_feature_name[] = { };static const char *kvm_feature_name[] = { -"kvmclock" ,"kvm_nopiodelay" ,"kvm_mmu" ,NULL ,"kvm_asyncpf" ,NULL ,NULL ,NULL , +"kvmclock" ,"kvm_nopiodelay" ,"kvm_mmu" ,"kvmclock" ,"kvm_asyncpf" ,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 ,NULL ,NULL ,
Signature · 1 line
1.7.1
PATCH 3/6 kvm: create kvmclock when one of the flags are present
In reply to Marcelo TosattiFrom: Glauber Costa <[email protected]>
kvmclock presence can be signalled by two different flags. So for device creation, we have to test for both.
--- hw/kvmclock.c | 6 +++++- 1 files changed, 5 insertions(+), 1 deletions(-)
hw/kvmclock.c +5 -1
@@ -103,7 +103,11 @@ static SysBusDeviceInfo kvmclock_info = {void kvmclock_create (void ) {if (kvm_enabled () && - first_cpu->cpuid_kvm_features & (1ULL <<KVM_FEATURE_CLOCKSOURCE )) { + first_cpu->cpuid_kvm_features & ((1ULL <<KVM_FEATURE_CLOCKSOURCE ) +#ifdef KVM_FEATURE_CLOCKSOURCE2 + || (1ULL <<KVM_FEATURE_CLOCKSOURCE2 ) +#endif + )) {sysbus_create_simple ("kvmclock" ,-1 ,NULL ); } }
Signature · 1 line
1.7.4.2
PATCH 4/6 Break up user and system cpu_interrupt implementations
In reply to Marcelo TosattiFrom: Jan Kiszka <[email protected]>
Both have only two lines in common, and we will convert the system service into a callback which is of no use for user mode operation.
--- exec.c | 14 ++++++++++---- 1 files changed, 10 insertions(+), 4 deletions(-)
exec.c +10 -4
@@ -1630,6 +1630,7 @@ static void cpu_unlink_tb(CPUState *env)spin_unlock (&interrupt_lock); } +#ifndef CONFIG_USER_ONLY /* mask must never be zero, except for A20 change call */ void cpu_interrupt (CPUState *env,int mask) {
@@ -1638,7 +1639,6 @@ void cpu_interrupt(CPUState *env, int mask) old_mask = env->interrupt_request; env->interrupt_request |= mask; -#ifndef CONFIG_USER_ONLY /* * If called from iothread context, wake the target cpu in * case its halted.
@@ -1647,21 +1647,27 @@ void cpu_interrupt(CPUState *env, int mask)qemu_cpu_kick (env); return; } -#endif if (use_icount) { env->icount_decr.u16.high =0xffff ; -#ifndef CONFIG_USER_ONLY if (!can_do_io (env) && (mask & ~old_mask) !=0 ) {cpu_abort (env,"Raised interrupt while not in I/O function" ); } -#endif }else {cpu_unlink_tb (env); } } +#else /* CONFIG_USER_ONLY */ + +void cpu_interrupt (CPUState *env,int mask) +{ + env->interrupt_request |= mask; +cpu_unlink_tb (env); +} +#endif /* CONFIG_USER_ONLY */ +void cpu_reset_interrupt (CPUState *env,int mask) { env->interrupt_request &= ~mask;
Signature · 1 line
1.7.4.2
PATCH 5/6 Redirect cpu_interrupt to callback handler
In reply to Marcelo TosattiFrom: Jan Kiszka <[email protected]>
This allows to override the interrupt handling of QEMU in system mode. KVM will make use of it to set a specialized handler.
--- cpu-all.h | 14 +++++++++++++- exec.c | 4 +++- 2 files changed, 16 insertions(+), 2 deletions(-)
cpu-all.h +13 -1
@@ -789,7 +789,19 @@ extern CPUState *cpu_single_env;#define CPU_INTERRUPT_SIPI 0x800/* SIPI pending. */ #define CPU_INTERRUPT_MCE 0x1000/* (x86 only) MCE pending. */ -void cpu_interrupt (CPUState *s,int mask); +#ifndef CONFIG_USER_ONLY +typedef void (*CPUInterruptHandler )(CPUState *,int ); + +extern CPUInterruptHandler cpu_interrupt_handler; + +static inline void cpu_interrupt (CPUState *s,int mask) +{ +cpu_interrupt_handler (s, mask); +} +#else /* USER_ONLY */ +void cpu_interrupt (CPUState *env,int mask); +#endif /* USER_ONLY */ +void cpu_reset_interrupt (CPUState *env,int mask);void cpu_exit (CPUState *s);
exec.c +3 -1
@@ -1632,7 +1632,7 @@ static void cpu_unlink_tb(CPUState *env)#ifndef CONFIG_USER_ONLY /* mask must never be zero, except for A20 change call */ -void cpu_interrupt (CPUState *env,int mask) +static void tcg_handle_interrupt (CPUState *env,int mask) {int old_mask;
@@ -1659,6 +1659,8 @@ void cpu_interrupt(CPUState *env, int mask) } } +CPUInterruptHandler cpu_interrupt_handler = tcg_handle_interrupt; +#else /* CONFIG_USER_ONLY */ void cpu_interrupt (CPUState *env,int mask)
Signature · 1 line
1.7.4.2
PATCH 6/6 kvm: Install specialized interrupt handler
In reply to Marcelo TosattiFrom: Jan Kiszka <[email protected]>
KVM only requires to set the raised IRQ in CPUState and to kick the receiving vcpu if it is remote. Installing a specialized handler allows potential future changes to the TCG code path without risking KVM side effects.
--- kvm-all.c | 11 +++++++++++ 1 files changed, 11 insertions(+), 0 deletions(-)
kvm-all.c +11 -0
@@ -651,6 +651,15 @@ static CPUPhysMemoryClient kvm_cpu_phys_memory_client = { .log_stop = kvm_log_stop, }; +static void kvm_handle_interrupt (CPUState *env,int mask) +{ + env->interrupt_request |= mask; + +if (!qemu_cpu_is_self (env)) { +qemu_cpu_kick (env); + } +} +int kvm_init (void ) { static const char upgrade_note[] =
@@ -759,6 +768,8 @@ int kvm_init(void) s->many_ioeventfds =kvm_check_many_ioeventfds (); + cpu_interrupt_handler = kvm_handle_interrupt; +return 0 ; err:
Signature · 1 line
1.7.4.2
Quoted 9 lines · Marcelo Tosatti
The following changes since commit
adc56dda0c4eed62149d28939b7d7e329ad95ae8:migration: move some declarations to migration.h (2011-04-15 20:14:54 +0000)are available in the git repository at:
git://git.kernel.org/pub/scm/virt/kvm/qemu-kvm.gituq/masterGlauber Costa (3):
kvm: use kernel-providedpara_featuresinstead of statically coming up with new capabilities
It's hard to follow this logic, but something in this series introduces a ton of chatter on stdout. For instance:
anthony@titi:~/build/qemu$ x86_64-softmmu/qemu-system-x86_64 -hda ~/images/linux.img -snapshot error: feature "sse2" not available in set error: bad option value [feature_edx = sse2 sse fxsr mmx pat cmov pge sep apic cx8 mce pae msr tsc pse de fpu mtrr clflush mca pse36] error: feature "sse2" not available in set error: bad option value [feature_edx = sse2 sse fxsr mmx pat cmov pge sep apic cx8 mce pae msr tsc pse de fpu mtrr clflush mca pse36] error: feature "sse2" not available in set error: bad option value [feature_edx = sse2 sse fxsr mmx pat cmov pge sep apic cx8 mce pae msr tsc pse de fpu mtrr clflush mca pse36] error: feature "sse2" not available in set error: bad option value [feature_edx = sse2 sse fxsr mmx pat cmov pge sep apic cx8 mce pae msr tsc pse de fpu mtrr clflush mca pse36] error: feature "sse2" not available in set error: bad option value [feature_edx = sse2 sse fxsr mmx pat cmov pge sep apic cx8 mce pae msr tsc pse de fpu mtrr clflush mca pse36] error: feature "sse2" not available in set error: bad option value [feature_edx = sse2 sse fxsr mmx pat cmov pge sep apic cx8 mce pae msr tsc pse de fpu mtrr clflush mca pse36] CPU feature hypervisor not found
This is with or without KVM enabled.
Regards,
Anthony Liguori
Quoted 15 lines
kvm: add kvmclock to its second bit
kvm: create kvmclock when one of the flags are presentJan Kiszka (3):
Break up user and systemcpu_interruptimplementations Redirectcpu_interruptto callback handler
kvm: Install specialized interrupt handlercpu-all.h | 14 ++++++++- exec.c | 18 ++++++++--- hw/kvmclock.c | 6 +++- kvm-all.c | 11 +++++++ target-i386/cpuid.c | 3 +- target-i386/kvm.c | 78 ++++++++++++++++++++++++++++++++------------------- 6 files changed, 92 insertions(+), 38 deletions(-)